Merge remote-tracking branch 'origin/master' into tm_pad_speedup
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_4096_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 144 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_4096_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 364 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_8192_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 398 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk2_8192_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 794 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_4096_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 143 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_4096_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 361 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_8192_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 396 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/mk3_8192_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 790 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_4096_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 105 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_4096_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 277 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_8192_bottom.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 324 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/bed/sl1_8192_top.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 674 KiB | 
| Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 70 KiB | 
| Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 58 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK2.5S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK2.5SMMU2S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 58 KiB | 
| Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 65 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK3S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 65 KiB | 
							
								
								
									
										
											BIN
										
									
								
								resources/icons/printers/PrusaResearch_MK3SMMU2S.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 70 KiB | 
| Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 55 KiB | 
|  | @ -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) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -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 © : object->m_copies) { |                 for (const Point © : object->m_copies) { | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -5790,7 +5810,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); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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.
 | ||||||
|  |  | ||||||
|  | @ -351,21 +351,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) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -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"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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)"; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|  |  | ||||||
 tamasmeszaros
						tamasmeszaros