Merge branch 'master' into lm_sla_supports_auto2

This commit is contained in:
Lukas Matena 2019-02-19 10:15:16 +01:00
commit 023b788777
44 changed files with 3347 additions and 2635 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Before After
Before After

View file

@ -1,8 +1,14 @@
min_slic3r_version = 1.42.0-alpha6
0.8.0-alpha6
min_slic3r_version = 1.42.0-alpha min_slic3r_version = 1.42.0-alpha
0.8.0-alpha
0.4.0-alpha4 Updated SLA profiles 0.4.0-alpha4 Updated SLA profiles
0.4.0-alpha3 Update of SLA profiles 0.4.0-alpha3 Update of SLA profiles
0.4.0-alpha2 First SLA profiles 0.4.0-alpha2 First SLA profiles
min_slic3r_version = 1.41.3-alpha
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
min_slic3r_version = 1.41.1 min_slic3r_version = 1.41.1
0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
0.3.3 Prusament PETG released 0.3.3 Prusament PETG released
0.3.2 New MK2.5 and MK3 FW versions 0.3.2 New MK2.5 and MK3 FW versions
0.3.1 New MK2.5 and MK3 FW versions 0.3.1 New MK2.5 and MK3 FW versions
@ -34,6 +40,7 @@ min_slic3r_version = 1.41.0-alpha
0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0 0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0
0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters 0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
min_slic3r_version = 1.40.0 min_slic3r_version = 1.40.0
0.1.12 New MK2.5 and MK3 FW versions
0.1.11 fw version changed to 3.3.1 0.1.11 fw version changed to 3.3.1
0.1.10 MK3 jerk and acceleration update 0.1.10 MK3 jerk and acceleration update
0.1.9 edited support extrusion width for 0.25 and 0.6 nozzles 0.1.9 edited support extrusion width for 0.25 and 0.6 nozzles

File diff suppressed because it is too large Load diff

View file

@ -1333,6 +1333,8 @@ void Transformation::set_rotation(const Vec3d& rotation)
void Transformation::set_rotation(Axis axis, double rotation) void Transformation::set_rotation(Axis axis, double rotation)
{ {
rotation = angle_to_0_2PI(rotation); rotation = angle_to_0_2PI(rotation);
if (is_approx(std::abs(rotation), 2.0 * (double)PI))
rotation = 0.0;
if (m_rotation(axis) != rotation) if (m_rotation(axis) != rotation)
{ {

View file

@ -1445,7 +1445,7 @@ int ModelVolume::extruder_id() const
int extruder_id = -1; int extruder_id = -1;
if (this->is_model_part()) { if (this->is_model_part()) {
const ConfigOption *opt = this->config.option("extruder"); const ConfigOption *opt = this->config.option("extruder");
if (opt == nullptr) if ((opt == nullptr) || (opt->getInt() == 0))
opt = this->object->config.option("extruder"); opt = this->object->config.option("extruder");
extruder_id = (opt == nullptr) ? 0 : opt->getInt(); extruder_id = (opt == nullptr) ? 0 : opt->getInt();
} }

View file

@ -1137,6 +1137,9 @@ std::string Print::validate() const
// Apply the same transformations we apply to the actual meshes when slicing them. // Apply the same transformations we apply to the actual meshes when slicing them.
object->model_object()->instances.front()->transform_polygon(&convex_hull); object->model_object()->instances.front()->transform_polygon(&convex_hull);
// Grow convex hull with the clearance margin. // Grow convex hull with the clearance margin.
// FIXME: Arrangement has different parameters for offsetting (jtMiter, limit 2)
// which causes that the warning will be showed after arrangement with the
// appropriate object distance. Even if I set this to jtMiter the warning still shows up.
convex_hull = offset(convex_hull, scale_(m_config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front(); convex_hull = offset(convex_hull, scale_(m_config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
// Now we check that no instance of convex_hull intersects any of the previously checked object instances. // Now we check that no instance of convex_hull intersects any of the previously checked object instances.
for (const Point &copy : object->m_copies) { for (const Point &copy : object->m_copies) {

View file

@ -42,22 +42,27 @@ namespace Slic3r {
static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error; static boost::log::trivial::severity_level logSeverity = boost::log::trivial::error;
void set_logging_level(unsigned int level) static boost::log::trivial::severity_level level_to_boost(unsigned level)
{ {
switch (level) { switch (level) {
// Report fatal errors only. // Report fatal errors only.
case 0: logSeverity = boost::log::trivial::fatal; break; case 0: return boost::log::trivial::fatal;
// Report fatal errors and errors. // Report fatal errors and errors.
case 1: logSeverity = boost::log::trivial::error; break; case 1: return boost::log::trivial::error;
// Report fatal errors, errors and warnings. // Report fatal errors, errors and warnings.
case 2: logSeverity = boost::log::trivial::warning; break; case 2: return boost::log::trivial::warning;
// Report all errors, warnings and infos. // Report all errors, warnings and infos.
case 3: logSeverity = boost::log::trivial::info; break; case 3: return boost::log::trivial::info;
// Report all errors, warnings, infos and debugging. // Report all errors, warnings, infos and debugging.
case 4: logSeverity = boost::log::trivial::debug; break; case 4: return boost::log::trivial::debug;
// Report everyting including fine level tracing information. // Report everyting including fine level tracing information.
default: logSeverity = boost::log::trivial::trace; break; default: return boost::log::trivial::trace;
} }
}
void set_logging_level(unsigned int level)
{
logSeverity = level_to_boost(level);
boost::log::core::get()->set_filter boost::log::core::get()->set_filter
( (
@ -73,6 +78,7 @@ unsigned get_logging_level()
case boost::log::trivial::warning : return 2; case boost::log::trivial::warning : return 2;
case boost::log::trivial::info : return 3; case boost::log::trivial::info : return 3;
case boost::log::trivial::debug : return 4; case boost::log::trivial::debug : return 4;
case boost::log::trivial::trace : return 5;
default: return 1; default: return 1;
} }
} }
@ -88,21 +94,7 @@ static struct RunOnInit {
void trace(unsigned int level, const char *message) void trace(unsigned int level, const char *message)
{ {
boost::log::trivial::severity_level severity = boost::log::trivial::trace; boost::log::trivial::severity_level severity = level_to_boost(level);
switch (level) {
// Report fatal errors only.
case 0: severity = boost::log::trivial::fatal; break;
// Report fatal errors and errors.
case 1: severity = boost::log::trivial::error; break;
// Report fatal errors, errors and warnings.
case 2: severity = boost::log::trivial::warning; break;
// Report all errors, warnings and infos.
case 3: severity = boost::log::trivial::info; break;
// Report all errors, warnings, infos and debugging.
case 4: severity = boost::log::trivial::debug; break;
// Report everyting including fine level tracing information.
default: severity = boost::log::trivial::trace; break;
}
BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\ BOOST_LOG_STREAM_WITH_PARAMS(::boost::log::trivial::logger::get(),\
(::boost::log::keywords::severity = severity)) << message; (::boost::log::keywords::severity = severity)) << message;

File diff suppressed because it is too large Load diff

View file

@ -16,30 +16,30 @@ namespace GUI {
class ConfigWizard: public wxDialog class ConfigWizard: public wxDialog
{ {
public: public:
// Why is the Wizard run // Why is the Wizard run
enum RunReason { enum RunReason {
RR_DATA_EMPTY, // No or empty datadir RR_DATA_EMPTY, // No or empty datadir
RR_DATA_LEGACY, // Pre-updating datadir RR_DATA_LEGACY, // Pre-updating datadir
RR_DATA_INCOMPAT, // Incompatible datadir - Slic3r downgrade situation RR_DATA_INCOMPAT, // Incompatible datadir - Slic3r downgrade situation
RR_USER, // User requested the Wizard from the menus RR_USER, // User requested the Wizard from the menus
}; };
ConfigWizard(wxWindow *parent, RunReason run_reason); ConfigWizard(wxWindow *parent, RunReason run_reason);
ConfigWizard(ConfigWizard &&) = delete; ConfigWizard(ConfigWizard &&) = delete;
ConfigWizard(const ConfigWizard &) = delete; ConfigWizard(const ConfigWizard &) = delete;
ConfigWizard &operator=(ConfigWizard &&) = delete; ConfigWizard &operator=(ConfigWizard &&) = delete;
ConfigWizard &operator=(const ConfigWizard &) = delete; ConfigWizard &operator=(const ConfigWizard &) = delete;
~ConfigWizard(); ~ConfigWizard();
// Run the Wizard. Return whether it was completed. // Run the Wizard. Return whether it was completed.
bool run(PresetBundle *preset_bundle, const PresetUpdater *updater); bool run(PresetBundle *preset_bundle, const PresetUpdater *updater);
static const wxString& name(const bool from_menu = false); static const wxString& name(const bool from_menu = false);
private: private:
struct priv; struct priv;
std::unique_ptr<priv> p; std::unique_ptr<priv> p;
friend struct ConfigWizardPage; friend struct ConfigWizardPage;
}; };

View file

@ -6,6 +6,7 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <functional>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <wx/sizer.h> #include <wx/sizer.h>
@ -13,6 +14,7 @@
#include <wx/button.h> #include <wx/button.h>
#include <wx/choice.h> #include <wx/choice.h>
#include <wx/spinctrl.h> #include <wx/spinctrl.h>
#include <wx/textctrl.h>
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
#include "slic3r/Utils/PresetUpdater.hpp" #include "slic3r/Utils/PresetUpdater.hpp"
@ -26,211 +28,264 @@ namespace Slic3r {
namespace GUI { namespace GUI {
enum { enum {
WRAP_WIDTH = 500, WRAP_WIDTH = 500,
MODEL_MIN_WRAP = 150, MODEL_MIN_WRAP = 150,
DIALOG_MARGIN = 15, DIALOG_MARGIN = 15,
INDEX_MARGIN = 40, INDEX_MARGIN = 40,
BTN_SPACING = 10, BTN_SPACING = 10,
INDENT_SPACING = 30, INDENT_SPACING = 30,
VERTICAL_SPACING = 10, VERTICAL_SPACING = 10,
MAX_COLS = 4,
ROW_SPACING = 75,
}; };
typedef std::function<bool(const VendorProfile::PrinterModel&)> ModelFilter;
struct PrinterPicker: wxPanel struct PrinterPicker: wxPanel
{ {
struct Checkbox : wxCheckBox struct Checkbox : wxCheckBox
{ {
Checkbox(wxWindow *parent, const wxString &label, const std::string &model, const std::string &variant) : Checkbox(wxWindow *parent, const wxString &label, const std::string &model, const std::string &variant) :
wxCheckBox(parent, wxID_ANY, label), wxCheckBox(parent, wxID_ANY, label),
model(model), model(model),
variant(variant) variant(variant)
{} {}
std::string model; std::string model;
std::string variant; std::string variant;
}; };
const std::string vendor_id; const std::string vendor_id;
std::vector<Checkbox*> cboxes; std::vector<Checkbox*> cboxes;
unsigned variants_checked; std::vector<Checkbox*> cboxes_alt;
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, const AppConfig &appconfig_vendors); PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors, const ModelFilter &filter);
PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxString title, size_t max_cols, const AppConfig &appconfig_vendors);
void select_all(bool select); void select_all(bool select, bool alternates = false);
void select_one(size_t i, bool select); void select_one(size_t i, bool select);
void on_checkbox(const Checkbox *cbox, bool checked); void on_checkbox(const Checkbox *cbox, bool checked);
int get_width() const { return width; }
private:
int width;
}; };
struct ConfigWizardPage: wxPanel struct ConfigWizardPage: wxPanel
{ {
ConfigWizard *parent; ConfigWizard *parent;
const wxString shortname; const wxString shortname;
wxBoxSizer *content; wxBoxSizer *content;
const unsigned indent;
ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname); ConfigWizardPage(ConfigWizard *parent, wxString title, wxString shortname, unsigned indent = 0);
virtual ~ConfigWizardPage();
virtual ~ConfigWizardPage(); template<class T>
void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
{
content->Add(thing, proportion, flag, border);
}
ConfigWizardPage* page_prev() const { return p_prev; } void append_text(wxString text);
ConfigWizardPage* page_next() const { return p_next; } void append_spacer(int space);
ConfigWizardPage* chain(ConfigWizardPage *page);
template<class T> ConfigWizard::priv *wizard_p() const { return parent->p.get(); }
void append(T *thing, int proportion = 0, int flag = wxEXPAND|wxTOP|wxBOTTOM, int border = 10)
{
content->Add(thing, proportion, flag, border);
}
void append_text(wxString text); virtual void apply_custom_config(DynamicPrintConfig &config) {}
void append_spacer(int space);
ConfigWizard::priv *wizard_p() const { return parent->p.get(); }
virtual bool Show(bool show = true);
virtual bool Hide() { return Show(false); }
virtual wxPanel* extra_buttons() { return nullptr; }
virtual void on_page_set() {}
virtual void apply_custom_config(DynamicPrintConfig &config) {}
void enable_next(bool enable);
private:
ConfigWizardPage *p_prev;
ConfigWizardPage *p_next;
}; };
struct PageWelcome: ConfigWizardPage struct PageWelcome: ConfigWizardPage
{ {
PrinterPicker *printer_picker; wxCheckBox *cbox_reset;
wxPanel *others_buttons;
wxCheckBox *cbox_reset;
PageWelcome(ConfigWizard *parent, bool check_first_variant); PageWelcome(ConfigWizard *parent);
virtual wxPanel* extra_buttons() { return others_buttons; } bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; }
virtual void on_page_set(); };
struct PagePrinters: ConfigWizardPage
{
enum Technology {
// Bitflag equivalent of PrinterTechnology
T_FFF = 0x1,
T_SLA = 0x2,
T_Any = ~0,
};
std::vector<PrinterPicker *> printer_pickers;
PagePrinters(ConfigWizard *parent, wxString title, wxString shortname, const VendorProfile &vendor, unsigned indent, Technology technology);
void select_all(bool select, bool alternates = false);
int get_width() const;
};
struct PageCustom: ConfigWizardPage
{
PageCustom(ConfigWizard *parent);
bool custom_wanted() const { return cb_custom->GetValue(); }
std::string profile_name() const { return into_u8(tc_profile_name->GetValue()); }
private:
static const char* default_profile_name;
wxCheckBox *cb_custom;
wxTextCtrl *tc_profile_name;
wxString profile_name_prev;
bool reset_user_profile() const { return cbox_reset != nullptr ? cbox_reset->GetValue() : false; }
void on_variant_checked();
}; };
struct PageUpdate: ConfigWizardPage struct PageUpdate: ConfigWizardPage
{ {
bool version_check; bool version_check;
bool preset_update; bool preset_update;
PageUpdate(ConfigWizard *parent); PageUpdate(ConfigWizard *parent);
}; };
struct PageVendors: ConfigWizardPage struct PageVendors: ConfigWizardPage
{ {
std::vector<PrinterPicker*> pickers; std::vector<PrinterPicker*> pickers;
PageVendors(ConfigWizard *parent); PageVendors(ConfigWizard *parent);
virtual void on_page_set(); void on_vendor_pick(size_t i);
void on_vendor_pick(size_t i);
void on_variant_checked();
}; };
struct PageFirmware: ConfigWizardPage struct PageFirmware: ConfigWizardPage
{ {
const ConfigOptionDef &gcode_opt; const ConfigOptionDef &gcode_opt;
wxChoice *gcode_picker; wxChoice *gcode_picker;
PageFirmware(ConfigWizard *parent); PageFirmware(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config); virtual void apply_custom_config(DynamicPrintConfig &config);
}; };
struct PageBedShape: ConfigWizardPage struct PageBedShape: ConfigWizardPage
{ {
BedShapePanel *shape_panel; BedShapePanel *shape_panel;
PageBedShape(ConfigWizard *parent); PageBedShape(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config); virtual void apply_custom_config(DynamicPrintConfig &config);
}; };
struct PageDiameters: ConfigWizardPage struct PageDiameters: ConfigWizardPage
{ {
wxSpinCtrlDouble *spin_nozzle; wxSpinCtrlDouble *spin_nozzle;
wxSpinCtrlDouble *spin_filam; wxSpinCtrlDouble *spin_filam;
PageDiameters(ConfigWizard *parent); PageDiameters(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config); virtual void apply_custom_config(DynamicPrintConfig &config);
}; };
struct PageTemperatures: ConfigWizardPage struct PageTemperatures: ConfigWizardPage
{ {
wxSpinCtrlDouble *spin_extr; wxSpinCtrlDouble *spin_extr;
wxSpinCtrlDouble *spin_bed; wxSpinCtrlDouble *spin_bed;
PageTemperatures(ConfigWizard *parent); PageTemperatures(ConfigWizard *parent);
virtual void apply_custom_config(DynamicPrintConfig &config); virtual void apply_custom_config(DynamicPrintConfig &config);
}; };
class ConfigWizardIndex: public wxPanel class ConfigWizardIndex: public wxPanel
{ {
public: public:
ConfigWizardIndex(wxWindow *parent); ConfigWizardIndex(wxWindow *parent);
void add_page(ConfigWizardPage *page);
void add_label(wxString label, unsigned indent = 0);
size_t active_item() const { return item_active; }
ConfigWizardPage* active_page() const;
bool active_is_last() const { return item_active < items.size() && item_active == last_page; }
void go_prev();
void go_next();
void go_to(size_t i);
void go_to(ConfigWizardPage *page);
void clear();
void load_items(ConfigWizardPage *firstpage);
void set_active(ConfigWizardPage *page);
private: private:
const wxBitmap bg; struct Item
const wxBitmap bullet_black; {
const wxBitmap bullet_blue; wxString label;
const wxBitmap bullet_white; unsigned indent;
int text_height; ConfigWizardPage *page; // nullptr page => label-only item
std::vector<wxString> items; bool operator==(ConfigWizardPage *page) const { return this->page == page; }
std::vector<wxString>::const_iterator item_active; };
void on_paint(wxPaintEvent &evt); int em;
int em_h;
const wxBitmap bg;
const wxBitmap bullet_black;
const wxBitmap bullet_blue;
const wxBitmap bullet_white;
std::vector<Item> items;
size_t item_active;
ssize_t item_hover;
size_t last_page;
int item_height() const { return std::max(bullet_black.GetSize().GetHeight(), em) + em; }
void on_paint(wxPaintEvent &evt);
void on_mouse_move(wxMouseEvent &evt);
}; };
wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent);
struct ConfigWizard::priv struct ConfigWizard::priv
{ {
ConfigWizard *q; ConfigWizard *q;
ConfigWizard::RunReason run_reason; ConfigWizard::RunReason run_reason;
AppConfig appconfig_vendors; AppConfig appconfig_vendors;
std::unordered_map<std::string, VendorProfile> vendors; std::unordered_map<std::string, VendorProfile> vendors;
std::unordered_map<std::string, std::string> vendors_rsrc; std::unordered_map<std::string, std::string> vendors_rsrc;
std::unique_ptr<DynamicPrintConfig> custom_config; std::unique_ptr<DynamicPrintConfig> custom_config;
wxScrolledWindow *hscroll = nullptr; wxScrolledWindow *hscroll = nullptr;
wxBoxSizer *hscroll_sizer = nullptr; wxBoxSizer *hscroll_sizer = nullptr;
wxBoxSizer *btnsizer = nullptr; wxBoxSizer *btnsizer = nullptr;
ConfigWizardPage *page_current = nullptr; ConfigWizardPage *page_current = nullptr;
ConfigWizardIndex *index = nullptr; ConfigWizardIndex *index = nullptr;
wxButton *btn_prev = nullptr; wxButton *btn_prev = nullptr;
wxButton *btn_next = nullptr; wxButton *btn_next = nullptr;
wxButton *btn_finish = nullptr; wxButton *btn_finish = nullptr;
wxButton *btn_cancel = nullptr; wxButton *btn_cancel = nullptr;
PageWelcome *page_welcome = nullptr; PageWelcome *page_welcome = nullptr;
PageUpdate *page_update = nullptr; PagePrinters *page_fff = nullptr;
PageVendors *page_vendors = nullptr; PagePrinters *page_msla = nullptr;
PageFirmware *page_firmware = nullptr; PageCustom *page_custom = nullptr;
PageBedShape *page_bed = nullptr; PageUpdate *page_update = nullptr;
PageDiameters *page_diams = nullptr; PageVendors *page_vendors = nullptr; // XXX: ?
PageTemperatures *page_temps = nullptr;
priv(ConfigWizard *q) : q(q) {} // Custom setup pages
PageFirmware *page_firmware = nullptr;
PageBedShape *page_bed = nullptr;
PageDiameters *page_diams = nullptr;
PageTemperatures *page_temps = nullptr;
void load_vendors(); priv(ConfigWizard *q) : q(q) {}
void add_page(ConfigWizardPage *page);
void index_refresh();
void set_page(ConfigWizardPage *page);
void layout_fit();
void go_prev() { if (page_current != nullptr) { set_page(page_current->page_prev()); } }
void go_next() { if (page_current != nullptr) { set_page(page_current->page_next()); } }
void enable_next(bool enable);
void on_other_vendors(); void load_pages(bool custom_setup);
void on_custom_setup();
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater); bool check_first_variant() const;
void load_vendors();
void add_page(ConfigWizardPage *page);
void enable_next(bool enable);
void on_custom_setup(bool custom_wanted);
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);
}; };

View file

@ -145,19 +145,24 @@ void Field::get_value_by_opt_type(wxString& str)
double val; double val;
// Replace the first occurence of comma in decimal number. // Replace the first occurence of comma in decimal number.
str.Replace(",", ".", false); str.Replace(",", ".", false);
if(!str.ToCDouble(&val)) if (str == ".")
{ val = 0.0;
show_error(m_parent, _(L("Invalid numeric input."))); else
set_value(double_to_string(val), true); {
} if (!str.ToCDouble(&val))
if (m_opt.min > val || val > m_opt.max) {
{ show_error(m_parent, _(L("Invalid numeric input.")));
show_error(m_parent, _(L("Input value is out of range"))); set_value(double_to_string(val), true);
if (m_opt.min > val) val = m_opt.min; }
if (val > m_opt.max) val = m_opt.max; if (m_opt.min > val || val > m_opt.max)
set_value(double_to_string(val), true); {
} show_error(m_parent, _(L("Input value is out of range")));
m_value = val; if (m_opt.min > val) val = m_opt.min;
if (val > m_opt.max) val = m_opt.max;
set_value(double_to_string(val), true);
}
}
m_value = val;
break; } break; }
case coString: case coString:
case coStrings: case coStrings:
@ -459,7 +464,7 @@ void SpinCtrl::BUILD() {
// # As a workaround, we get the new value from $event->GetString and store // # As a workaround, we get the new value from $event->GetString and store
// # here temporarily so that we can return it from $self->get_value // # here temporarily so that we can return it from $self->get_value
std::string value = e.GetString().utf8_str().data(); std::string value = e.GetString().utf8_str().data();
if (is_matched(value, "^\\d+$")) if (is_matched(value, "^\\-?\\d+$"))
tmp_value = std::stoi(value); tmp_value = std::stoi(value);
else tmp_value = -9999; else tmp_value = -9999;
#ifdef __WXOSX__ #ifdef __WXOSX__
@ -475,7 +480,7 @@ void SpinCtrl::BUILD() {
void SpinCtrl::propagate_value() void SpinCtrl::propagate_value()
{ {
if (tmp_value < 0) if (tmp_value == -9999)
on_kill_focus(); on_kill_focus();
else if (boost::any_cast<int>(m_value) != tmp_value) else if (boost::any_cast<int>(m_value) != tmp_value)
on_change_field(); on_change_field();
@ -867,8 +872,8 @@ void StaticText::BUILD()
if (m_opt.height >= 0) size.SetHeight(m_opt.height); if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width); if (m_opt.width >= 0) size.SetWidth(m_opt.width);
wxString legend(static_cast<const ConfigOptionString*>(m_opt.default_value)->value); const wxString legend(static_cast<const ConfigOptionString*>(m_opt.default_value)->value);
auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size); auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size, wxST_ELLIPSIZE_MIDDLE);
temp->SetFont(wxGetApp().bold_font()); temp->SetFont(wxGetApp().bold_font());
// // recast as a wxWindow to fit the calling convention // // recast as a wxWindow to fit the calling convention

View file

@ -141,8 +141,8 @@ bool GeometryBuffer::set_from_triangles(const Polygons& triangles, float z, bool
float inv_size_y = -1.0f / size_y; float inv_size_y = -1.0f / size_y;
for (unsigned int i = 0; i < m_tex_coords.size(); i += 2) for (unsigned int i = 0; i < m_tex_coords.size(); i += 2)
{ {
m_tex_coords[i] *= inv_size_x; m_tex_coords[i] = (m_tex_coords[i] - min_x) * inv_size_x;
m_tex_coords[i + 1] *= inv_size_y; m_tex_coords[i + 1] = (m_tex_coords[i + 1] - min_y) * inv_size_y;
} }
} }
} }
@ -595,11 +595,25 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
#endif // ENABLE_PRINT_BED_MODELS #endif // ENABLE_PRINT_BED_MODELS
{ {
std::string tex_path = resources_dir() + "/icons/bed/" + key; std::string tex_path = resources_dir() + "/icons/bed/" + key;
// use higher resolution images if graphic card allows
GLint max_tex_size;
::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size);
// temporary set to lowest resolution
max_tex_size = 2048;
if (max_tex_size >= 8192)
tex_path += "_8192";
else if (max_tex_size >= 4096)
tex_path += "_4096";
#if ENABLE_PRINT_BED_MODELS #if ENABLE_PRINT_BED_MODELS
std::string model_path = resources_dir() + "/models/" + key; std::string model_path = resources_dir() + "/models/" + key;
#endif // ENABLE_PRINT_BED_MODELS #endif // ENABLE_PRINT_BED_MODELS
#if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES #if ENABLE_ANISOTROPIC_FILTER_ON_BED_TEXTURES
// use anisotropic filter if graphic card allows
GLfloat max_anisotropy = 0.0f; GLfloat max_anisotropy = 0.0f;
if (glewIsSupported("GL_EXT_texture_filter_anisotropic")) if (glewIsSupported("GL_EXT_texture_filter_anisotropic"))
::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy); ::glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
@ -646,11 +660,17 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
{ {
filename = model_path + "_bed.stl"; filename = model_path + "_bed.stl";
if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs)) { if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs)) {
Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.1 + 0.5 * m_model.get_bounding_box().size()(2)); Vec3d offset = m_bounding_box.center() - Vec3d(0.0, 0.0, 0.5 * m_model.get_bounding_box().size()(2));
if (key == "mk2") if (key == "mk2")
offset.y() += 15. / 2.; // hardcoded value to match the stl model
offset += Vec3d(0.0, 7.5, -0.03);
else if (key == "mk3") else if (key == "mk3")
offset += Vec3d(0., (19. - 8.) / 2., 2.); // hardcoded value to match the stl model
offset += Vec3d(0.0, 5.5, 2.43);
else if (key == "sl1")
// hardcoded value to match the stl model
offset += Vec3d(0.0, 0.0, -0.03);
m_model.center_around(offset); m_model.center_around(offset);
} }
@ -5343,14 +5363,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// Set focus in order to remove it from sidebar fields // Set focus in order to remove it from sidebar fields
if (m_canvas != nullptr) { if (m_canvas != nullptr) {
// Only set focus, if the top level window of this canvas is active. // Only set focus, if the top level window of this canvas is active.
auto p = dynamic_cast<wxWindow*>(evt.GetEventObject()); auto p = dynamic_cast<wxWindow*>(evt.GetEventObject());
while (p->GetParent()) while (p->GetParent())
p = p->GetParent(); p = p->GetParent();
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p); auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
if (top_level_wnd && top_level_wnd->IsActive()) if (top_level_wnd && top_level_wnd->IsActive())
{
m_canvas->SetFocus(); m_canvas->SetFocus();
}
// forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while
// the context menu is shown, ensuring it to disappear if the mouse is outside any volume and to
// change the volume hover state if any is under the mouse
m_mouse.position = pos.cast<double>();
render();
}
}
m_mouse.set_start_position_2D_as_invalid(); m_mouse.set_start_position_2D_as_invalid();
//#endif //#endif
} }
@ -5479,7 +5506,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
// propagate event through callback // propagate event through callback
if (m_hover_volume_id != -1) if (m_hover_volume_id != -1)
{ {
if (evt.LeftDown() && m_moving_enabled && (m_mouse.drag.move_volume_idx == -1)) if (evt.LeftDown() && m_moving_enabled && (m_mouse.drag.move_volume_idx == -1))
@ -5498,9 +5524,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
else if (evt.RightDown()) else if (evt.RightDown())
{ {
m_mouse.position = pos.cast<double>();
// forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while // forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while
// the context menu is already shown, ensuring it to disappear if the mouse is outside any volume // the context menu is already shown
m_mouse.position = Vec2d((double)pos(0), (double)pos(1));
render(); render();
if (m_hover_volume_id != -1) if (m_hover_volume_id != -1)
{ {
@ -5514,14 +5540,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
_update_gizmos_data(); _update_gizmos_data();
wxGetApp().obj_manipul()->update_settings_value(m_selection); wxGetApp().obj_manipul()->update_settings_value(m_selection);
// forces a frame render to update the view before the context menu is shown // // forces a frame render to update the view before the context menu is shown
render(); // render();
Vec2d logical_pos = pos.cast<double>(); Vec2d logical_pos = pos.cast<double>();
#if ENABLE_RETINA_GL #if ENABLE_RETINA_GL
const float factor = m_retina_helper->get_scale_factor(); const float factor = m_retina_helper->get_scale_factor();
logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor)); logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor));
#endif #endif // ENABLE_RETINA_GL
post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos)); post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos));
} }
} }
@ -5817,7 +5843,7 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const
else else
t->SetTip(tooltip); t->SetTip(tooltip);
} }
else else if (!tooltip.empty()) // Avoid "empty" tooltips => unset of the empty tooltip leads to application crash under OSX
m_canvas->SetToolTip(tooltip); m_canvas->SetToolTip(tooltip);
} }
} }
@ -6150,7 +6176,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "add"; item.name = "add";
item.tooltip = GUI::L_str("Add...") + " [" + GUI::shortkey_ctrl_prefix() + "I]"; item.tooltip = GUI::L_str("Add...") + " [" + GUI::shortkey_ctrl_prefix() + "I]";
item.sprite_id = 0; item.sprite_id = 0;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_ADD; item.action_event = EVT_GLTOOLBAR_ADD;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6158,7 +6183,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "delete"; item.name = "delete";
item.tooltip = GUI::L_str("Delete") + " [Del]"; item.tooltip = GUI::L_str("Delete") + " [Del]";
item.sprite_id = 1; item.sprite_id = 1;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_DELETE; item.action_event = EVT_GLTOOLBAR_DELETE;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6166,7 +6190,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "deleteall"; item.name = "deleteall";
item.tooltip = GUI::L_str("Delete all") + " [" + GUI::shortkey_ctrl_prefix() + "Del]"; item.tooltip = GUI::L_str("Delete all") + " [" + GUI::shortkey_ctrl_prefix() + "Del]";
item.sprite_id = 2; item.sprite_id = 2;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_DELETE_ALL; item.action_event = EVT_GLTOOLBAR_DELETE_ALL;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6174,7 +6197,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "arrange"; item.name = "arrange";
item.tooltip = GUI::L_str("Arrange [A]"); item.tooltip = GUI::L_str("Arrange [A]");
item.sprite_id = 3; item.sprite_id = 3;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_ARRANGE; item.action_event = EVT_GLTOOLBAR_ARRANGE;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6185,7 +6207,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "more"; item.name = "more";
item.tooltip = GUI::L_str("Add instance [+]"); item.tooltip = GUI::L_str("Add instance [+]");
item.sprite_id = 4; item.sprite_id = 4;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_MORE; item.action_event = EVT_GLTOOLBAR_MORE;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6193,7 +6214,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "fewer"; item.name = "fewer";
item.tooltip = GUI::L_str("Remove instance [-]"); item.tooltip = GUI::L_str("Remove instance [-]");
item.sprite_id = 5; item.sprite_id = 5;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_FEWER; item.action_event = EVT_GLTOOLBAR_FEWER;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6204,7 +6224,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "splitobjects"; item.name = "splitobjects";
item.tooltip = GUI::L_str("Split to objects"); item.tooltip = GUI::L_str("Split to objects");
item.sprite_id = 6; item.sprite_id = 6;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS; item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -6212,7 +6231,6 @@ bool GLCanvas3D::_init_toolbar()
item.name = "splitvolumes"; item.name = "splitvolumes";
item.tooltip = GUI::L_str("Split to parts"); item.tooltip = GUI::L_str("Split to parts");
item.sprite_id = 8; item.sprite_id = 8;
item.is_toggable = false;
item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES;
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;

View file

@ -355,21 +355,6 @@ boost::filesystem::path into_path(const wxString &str)
return boost::filesystem::path(str.wx_str()); return boost::filesystem::path(str.wx_str());
} }
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height)
{
const auto idx = wxDisplay::GetFromWindow(window);
if (idx == wxNOT_FOUND) {
return false;
}
wxDisplay display(idx);
const auto disp_size = display.GetClientArea();
width = disp_size.GetWidth();
height = disp_size.GetHeight();
return true;
}
void about() void about()
{ {
AboutDialog dlg; AboutDialog dlg;

View file

@ -71,9 +71,6 @@ wxString from_path(const boost::filesystem::path &path);
// boost path from wxString // boost path from wxString
boost::filesystem::path into_path(const wxString &str); boost::filesystem::path into_path(const wxString &str);
// Returns the dimensions of the screen on which the main frame is displayed
bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height);
// Display an About dialog // Display an About dialog
extern void about(); extern void about();
// Ask the destop to open the datadir using the default file explorer. // Ask the destop to open the datadir using the default file explorer.

View file

@ -3,8 +3,10 @@
#include "GUI_ObjectManipulation.hpp" #include "GUI_ObjectManipulation.hpp"
#include "I18N.hpp" #include "I18N.hpp"
#include <exception>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/log/trivial.hpp>
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
#include <wx/imagpng.h> #include <wx/imagpng.h>
@ -125,6 +127,10 @@ bool GUI_App::OnInit()
app_config->save(); app_config->save();
preset_updater = new PresetUpdater(); preset_updater = new PresetUpdater();
Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent &evt) {
app_config->set("version_online", into_u8(evt.GetString()));
app_config->save();
});
load_language(); load_language();
@ -181,7 +187,6 @@ bool GUI_App::OnInit()
mainframe->Close(); mainframe->Close();
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
show_error(nullptr, ex.what()); show_error(nullptr, ex.what());
mainframe->Close();
} }
}); });
@ -351,21 +356,10 @@ void GUI_App::persist_window_geometry(wxTopLevelWindow *window)
}); });
window_pos_restore(window, name); window_pos_restore(window, name);
#ifdef _WIN32
// On windows, the wxEVT_SHOW is not received if the window is created maximized on_window_geometry(window, [=]() {
// cf. https://groups.google.com/forum/#!topic/wx-users/c7ntMt6piRI window_pos_sanitize(window);
// so we sanitize the position right away
window_pos_sanitize(window);
#else
// On other platforms on the other hand it's needed to wait before the window is actually on screen
// and some initial round of events is complete otherwise position / display index is not reported correctly.
window->Bind(wxEVT_SHOW, [=](wxShowEvent &event) {
CallAfter([=]() {
window_pos_sanitize(window);
});
event.Skip();
}); });
#endif
} }
void GUI_App::load_project(wxWindow *parent, wxString& input_file) void GUI_App::load_project(wxWindow *parent, wxString& input_file)
@ -573,7 +567,10 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("Simple")), _(L("Simple View Mode"))); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("Simple")), _(L("Simple View Mode")));
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeAdvanced, _(L("Advanced")), _(L("Advanced View Mode"))); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeAdvanced, _(L("Advanced")), _(L("Advanced View Mode")));
mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("Expert")), _(L("Expert View Mode"))); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("Expert")), _(L("Expert View Mode")));
mode_menu->Check(config_id_base + ConfigMenuModeSimple + get_mode(), true); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comSimple); }, config_id_base + ConfigMenuModeSimple);
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comAdvanced); }, config_id_base + ConfigMenuModeAdvanced);
Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Check(get_mode() == comExpert); }, config_id_base + ConfigMenuModeExpert);
local_menu->AppendSubMenu(mode_menu, _(L("Mode")), _(L("Slic3r View Mode"))); local_menu->AppendSubMenu(mode_menu, _(L("Mode")), _(L("Slic3r View Mode")));
local_menu->AppendSeparator(); local_menu->AppendSeparator();
local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application &Language"))); local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application &Language")));
@ -692,6 +689,23 @@ void GUI_App::load_current_presets()
} }
} }
bool GUI_App::OnExceptionInMainLoop()
{
try {
throw;
} catch (const std::exception &ex) {
const std::string error = (boost::format("Uncaught exception: %1%") % ex.what()).str();
BOOST_LOG_TRIVIAL(error) << error;
show_error(nullptr, from_u8(error));
} catch (...) {
const char *error = "Uncaught exception: Unknown error";
BOOST_LOG_TRIVIAL(error) << error;
show_error(nullptr, from_u8(error));
}
return false;
}
#ifdef __APPLE__ #ifdef __APPLE__
// wxWidgets override to get an event on open files. // wxWidgets override to get an event on open files.
void GUI_App::MacOpenFiles(const wxArrayString &fileNames) void GUI_App::MacOpenFiles(const wxArrayString &fileNames)

View file

@ -137,6 +137,8 @@ public:
bool checked_tab(Tab* tab); bool checked_tab(Tab* tab);
void load_current_presets(); void load_current_presets();
virtual bool OnExceptionInMainLoop();
#ifdef __APPLE__ #ifdef __APPLE__
// wxWidgets override to get an event on open files. // wxWidgets override to get an event on open files.
void MacOpenFiles(const wxArrayString &fileNames) override; void MacOpenFiles(const wxArrayString &fileNames) override;

View file

@ -42,10 +42,9 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
// Objects(sub-objects) name // Objects(sub-objects) name
def.label = L("Name"); def.label = L("Name");
// def.type = coString;
def.gui_type = "legend"; def.gui_type = "legend";
def.tooltip = L("Object name"); def.tooltip = L("Object name");
def.full_width = true; def.width = 200;
def.default_value = new ConfigOptionString{ " " }; def.default_value = new ConfigOptionString{ " " };
m_og->append_single_option_line(Option(def, "object_name")); m_og->append_single_option_line(Option(def, "object_name"));
@ -73,14 +72,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
def.default_value = new ConfigOptionFloat(0.0); def.default_value = new ConfigOptionFloat(0.0);
def.width = 50; def.width = 50;
if (option_name == "Rotation")
{
def.min = -360;
def.max = 360;
}
// Add "uniform scaling" button in front of "Scale" option // Add "uniform scaling" button in front of "Scale" option
else if (option_name == "Scale") { if (option_name == "Scale") {
line.near_label_widget = [this](wxWindow* parent) { line.near_label_widget = [this](wxWindow* parent) {
auto btn = new PrusaLockButton(parent, wxID_ANY); auto btn = new PrusaLockButton(parent, wxID_ANY);
btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){ btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){
@ -293,13 +286,13 @@ void ObjectManipulation::update_if_dirty()
deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i)); deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i));
} }
if (m_cache.rotation(0) != m_new_rotation(0)) if ((m_cache.rotation(0) != m_new_rotation(0)) || (m_new_rotation(0) == 0.0))
m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2)); m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2));
if (m_cache.rotation(1) != m_new_rotation(1)) if ((m_cache.rotation(1) != m_new_rotation(1)) || (m_new_rotation(1) == 0.0))
m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2)); m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2));
if (m_cache.rotation(2) != m_new_rotation(2)) if ((m_cache.rotation(2) != m_new_rotation(2)) || (m_new_rotation(2) == 0.0))
m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2)); m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2));
m_cache.rotation = deg_rotation; m_cache.rotation = deg_rotation;

View file

@ -26,6 +26,28 @@ wxTopLevelWindow* find_toplevel_parent(wxWindow *window)
return nullptr; return nullptr;
} }
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback)
{
#ifdef _WIN32
// On windows, the wxEVT_SHOW is not received if the window is created maximized
// cf. https://groups.google.com/forum/#!topic/wx-users/c7ntMt6piRI
// OTOH the geometry is available very soon, so we can call the callback right away
callback();
#elif defined __linux__
tlw->Bind(wxEVT_SHOW, [=](wxShowEvent &evt) {
// On Linux, the geometry is only available after wxEVT_SHOW + CallAfter
// cf. https://groups.google.com/forum/?pli=1#!topic/wx-users/fERSXdpVwAI
tlw->CallAfter([=]() { callback(); });
evt.Skip();
});
#elif defined __APPLE__
tlw->Bind(wxEVT_SHOW, [=](wxShowEvent &evt) {
callback();
evt.Skip();
});
#endif
}
CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent)
: wxPanel(parent, wxID_ANY) : wxPanel(parent, wxID_ANY)

View file

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <ostream> #include <ostream>
#include <functional>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -24,6 +25,8 @@ namespace GUI {
wxTopLevelWindow* find_toplevel_parent(wxWindow *window); wxTopLevelWindow* find_toplevel_parent(wxWindow *window);
void on_window_geometry(wxTopLevelWindow *tlw, std::function<void()> callback);
class EventGuard class EventGuard
{ {

View file

@ -12,7 +12,6 @@
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/notebook.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/bmpcbox.h> #include <wx/bmpcbox.h>
#include <wx/statbox.h> #include <wx/statbox.h>
@ -1092,7 +1091,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
: q(q) : q(q)
, main_frame(main_frame) , main_frame(main_frame)
, config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
"bed_shape", "complete_objects", "extruder_clearance_radius", "skirts", "skirt_distance", "bed_shape", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance",
"brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host",
"printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material", "printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle",
@ -1774,8 +1773,11 @@ void Plater::priv::arrange()
// FIXME: I don't know how to obtain the minimum distance, it depends // FIXME: I don't know how to obtain the minimum distance, it depends
// on printer technology. I guess the following should work but it crashes. // on printer technology. I guess the following should work but it crashes.
double dist = 6; //PrintConfig::min_object_distance(config); double dist = 6; //PrintConfig::min_object_distance(config);
if(printer_technology == ptFFF) {
dist = PrintConfig::min_object_distance(config);
}
auto min_obj_distance = static_cast<coord_t>(dist/SCALING_FACTOR); auto min_obj_distance = coord_t(dist/SCALING_FACTOR);
const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape"); const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape");

View file

@ -11,8 +11,10 @@
#include <Windows.h> #include <Windows.h>
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#include <algorithm>
#include <fstream> #include <fstream>
#include <stdexcept> #include <stdexcept>
#include <unordered_map>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
@ -83,6 +85,16 @@ VendorProfile VendorProfile::from_ini(const boost::filesystem::path &path, bool
return VendorProfile::from_ini(tree, path, load_all); return VendorProfile::from_ini(tree, path, load_all);
} }
static const std::unordered_map<std::string, std::string> pre_family_model_map {{
{ "MK3", "MK3" },
{ "MK3MMU2", "MK3" },
{ "MK2.5", "MK2.5" },
{ "MK2.5MMU2", "MK2.5" },
{ "MK2S", "MK2" },
{ "MK2SMM", "MK2" },
{ "SL1", "SL1" },
}};
VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem::path &path, bool load_all) VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem::path &path, bool load_all)
{ {
static const std::string printer_model_key = "printer_model:"; static const std::string printer_model_key = "printer_model:";
@ -128,11 +140,21 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
VendorProfile::PrinterModel model; VendorProfile::PrinterModel model;
model.id = section.first.substr(printer_model_key.size()); model.id = section.first.substr(printer_model_key.size());
model.name = section.second.get<std::string>("name", model.id); model.name = section.second.get<std::string>("name", model.id);
auto technology_field = section.second.get<std::string>("technology", "FFF");
const char *technology_fallback = boost::algorithm::starts_with(model.id, "SL") ? "SLA" : "FFF";
auto technology_field = section.second.get<std::string>("technology", technology_fallback);
if (! ConfigOptionEnum<PrinterTechnology>::from_string(technology_field, model.technology)) { if (! ConfigOptionEnum<PrinterTechnology>::from_string(technology_field, model.technology)) {
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Invalid printer technology field: `%2%`") % id % technology_field; BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Invalid printer technology field: `%2%`") % id % technology_field;
model.technology = ptFFF; model.technology = ptFFF;
} }
model.family = section.second.get<std::string>("family", std::string());
if (model.family.empty() && res.name == "Prusa Research") {
// If no family is specified, it can be inferred for known printers
const auto from_pre_map = pre_family_model_map.find(model.id);
if (from_pre_map != pre_family_model_map.end()) { model.family = from_pre_map->second; }
}
#if 0 #if 0
// Remove SLA printers from the initial alpha. // Remove SLA printers from the initial alpha.
if (model.technology == ptSLA) if (model.technology == ptSLA)
@ -157,6 +179,20 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
return res; return res;
} }
std::vector<std::string> VendorProfile::families() const
{
std::vector<std::string> res;
unsigned num_familiies = 0;
for (auto &model : models) {
if (std::find(res.begin(), res.end(), model.family) == res.end()) {
res.push_back(model.family);
num_familiies++;
}
}
return res;
}
// Suffix to be added to a modified preset name in the combo box. // Suffix to be added to a modified preset name in the combo box.
static std::string g_suffix_modified = " (modified)"; static std::string g_suffix_modified = " (modified)";

View file

@ -54,13 +54,16 @@ public:
std::string id; std::string id;
std::string name; std::string name;
PrinterTechnology technology; PrinterTechnology technology;
std::string family;
std::vector<PrinterVariant> variants; std::vector<PrinterVariant> variants;
PrinterVariant* variant(const std::string &name) { PrinterVariant* variant(const std::string &name) {
for (auto &v : this->variants) for (auto &v : this->variants)
if (v.name == name) if (v.name == name)
return &v; return &v;
return nullptr; return nullptr;
} }
const PrinterVariant* variant(const std::string &name) const { return const_cast<PrinterModel*>(this)->variant(name); } const PrinterVariant* variant(const std::string &name) const { return const_cast<PrinterModel*>(this)->variant(name); }
}; };
std::vector<PrinterModel> models; std::vector<PrinterModel> models;
@ -72,6 +75,7 @@ public:
static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true); static VendorProfile from_ini(const boost::property_tree::ptree &tree, const boost::filesystem::path &path, bool load_all=true);
size_t num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; } size_t num_variants() const { size_t n = 0; for (auto &model : models) n += model.variants.size(); return n; }
std::vector<std::string> families() const;
bool operator< (const VendorProfile &rhs) const { return this->id < rhs.id; } bool operator< (const VendorProfile &rhs) const { return this->id < rhs.id; }
bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; } bool operator==(const VendorProfile &rhs) const { return this->id == rhs.id; }

View file

@ -244,7 +244,7 @@ void Http::priv::http_perform()
::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this)); ::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this));
#endif #endif
::curl_easy_setopt(curl, CURLOPT_VERBOSE, get_logging_level() >= 4); ::curl_easy_setopt(curl, CURLOPT_VERBOSE, get_logging_level() >= 5);
if (headerlist != nullptr) { if (headerlist != nullptr) {
::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);

View file

@ -13,7 +13,6 @@
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <wx/app.h> #include <wx/app.h>
#include <wx/event.h>
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include "libslic3r/libslic3r.h" #include "libslic3r/libslic3r.h"
@ -90,9 +89,25 @@ struct Updates
std::vector<Update> updates; std::vector<Update> updates;
}; };
static Semver get_slic3r_version()
{
auto res = Semver::parse(SLIC3R_VERSION);
if (! res) {
const char *error = "Could not parse Slic3r version string: " SLIC3R_VERSION;
BOOST_LOG_TRIVIAL(error) << error;
throw std::runtime_error(error);
}
return *res;
}
wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
struct PresetUpdater::priv struct PresetUpdater::priv
{ {
const Semver ver_slic3r;
std::vector<Index> index_db; std::vector<Index> index_db;
bool enabled_version_check; bool enabled_version_check;
@ -122,12 +137,13 @@ struct PresetUpdater::priv
static void copy_file(const fs::path &from, const fs::path &to); static void copy_file(const fs::path &from, const fs::path &to);
}; };
PresetUpdater::priv::priv() : PresetUpdater::priv::priv()
had_config_update(false), : ver_slic3r(get_slic3r_version())
cache_path(fs::path(Slic3r::data_dir()) / "cache"), , had_config_update(false)
rsrc_path(fs::path(resources_dir()) / "profiles"), , cache_path(fs::path(Slic3r::data_dir()) / "cache")
vendor_path(fs::path(Slic3r::data_dir()) / "vendor"), , rsrc_path(fs::path(resources_dir()) / "profiles")
cancel(false) , vendor_path(fs::path(Slic3r::data_dir()) / "vendor")
, cancel(false)
{ {
set_download_prefs(GUI::wxGetApp().app_config); set_download_prefs(GUI::wxGetApp().app_config);
check_install_indices(); check_install_indices();
@ -209,11 +225,10 @@ void PresetUpdater::priv::sync_version() const
.on_complete([&](std::string body, unsigned /* http_status */) { .on_complete([&](std::string body, unsigned /* http_status */) {
boost::trim(body); boost::trim(body);
BOOST_LOG_TRIVIAL(info) << boost::format("Got Slic3rPE online version: `%1%`. Sending to GUI thread...") % body; BOOST_LOG_TRIVIAL(info) << boost::format("Got Slic3rPE online version: `%1%`. Sending to GUI thread...") % body;
// wxCommandEvent* evt = new wxCommandEvent(version_online_event);
// evt->SetString(body); wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
// GUI::get_app()->QueueEvent(evt); evt->SetString(GUI::from_u8(body));
GUI::wxGetApp().app_config->set("version_online", body); GUI::wxGetApp().QueueEvent(evt);
GUI::wxGetApp().app_config->save();
}) })
.perform_sync(); .perform_sync();
} }
@ -260,7 +275,7 @@ void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors)
continue; continue;
} }
if (new_index.version() < index.version()) { if (new_index.version() < index.version()) {
BOOST_LOG_TRIVIAL(error) << boost::format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.") % idx_path_temp % vendor.name; BOOST_LOG_TRIVIAL(warning) << boost::format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.") % idx_path_temp % vendor.name;
continue; continue;
} }
Slic3r::rename_file(idx_path_temp, idx_path); Slic3r::rename_file(idx_path_temp, idx_path);
@ -275,6 +290,7 @@ void PresetUpdater::priv::sync_config(const std::set<VendorProfile> vendors)
BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % vendor.name; BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % vendor.name;
continue; continue;
} }
const auto recommended = recommended_it->config_version; const auto recommended = recommended_it->config_version;
BOOST_LOG_TRIVIAL(debug) << boost::format("Got index for vendor: %1%: current version: %2%, recommended version: %3%") BOOST_LOG_TRIVIAL(debug) << boost::format("Got index for vendor: %1%: current version: %2%, recommended version: %3%")
@ -341,7 +357,8 @@ Updates PresetUpdater::priv::get_config_updates() const
if (ver_current == idx.end()) { if (ver_current == idx.end()) {
auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str(); auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str();
BOOST_LOG_TRIVIAL(error) << message; BOOST_LOG_TRIVIAL(error) << message;
throw std::runtime_error(message); GUI::show_error(nullptr, GUI::from_u8(message));
continue;
} }
// Getting a recommended version from the latest index, wich may have been downloaded // Getting a recommended version from the latest index, wich may have been downloaded
@ -528,18 +545,14 @@ void PresetUpdater::slic3r_update_notify()
} }
auto* app_config = GUI::wxGetApp().app_config; auto* app_config = GUI::wxGetApp().app_config;
const auto ver_slic3r = Semver::parse(SLIC3R_VERSION);
const auto ver_online_str = app_config->get("version_online"); const auto ver_online_str = app_config->get("version_online");
const auto ver_online = Semver::parse(ver_online_str); const auto ver_online = Semver::parse(ver_online_str);
const auto ver_online_seen = Semver::parse(app_config->get("version_online_seen")); const auto ver_online_seen = Semver::parse(app_config->get("version_online_seen"));
if (! ver_slic3r) {
throw std::runtime_error("Could not parse Slic3r version string: " SLIC3R_VERSION);
}
if (ver_online) { if (ver_online) {
// Only display the notification if the version available online is newer AND if we haven't seen it before // Only display the notification if the version available online is newer AND if we haven't seen it before
if (*ver_online > *ver_slic3r && (! ver_online_seen || *ver_online_seen < *ver_online)) { if (*ver_online > p->ver_slic3r && (! ver_online_seen || *ver_online_seen < *ver_online)) {
GUI::MsgUpdateSlic3r notification(*ver_slic3r, *ver_online); GUI::MsgUpdateSlic3r notification(p->ver_slic3r, *ver_online);
notification.ShowModal(); notification.ShowModal();
if (notification.disable_version_check()) { if (notification.disable_version_check()) {
app_config->set("version_check", "0"); app_config->set("version_check", "0");

View file

@ -4,6 +4,8 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <wx/event.h>
namespace Slic3r { namespace Slic3r {
@ -37,6 +39,8 @@ private:
std::unique_ptr<priv> p; std::unique_ptr<priv> p;
}; };
wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent);
} }
#endif #endif