diff --git a/resources/images/bullet_black.png b/resources/images/bullet_black.png new file mode 100644 index 000000000..0ad73727e Binary files /dev/null and b/resources/images/bullet_black.png differ diff --git a/resources/images/bullet_blue.png b/resources/images/bullet_blue.png new file mode 100644 index 000000000..a7651ec8a Binary files /dev/null and b/resources/images/bullet_blue.png differ diff --git a/resources/images/bullet_white.png b/resources/images/bullet_white.png new file mode 100644 index 000000000..2ff85a6fc Binary files /dev/null and b/resources/images/bullet_white.png differ diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 3800aefb8..57437884d 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -757,6 +757,9 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex if (boost::iequals(it.key(),BBL_JSON_KEY_VERSION)) { key_values.emplace(BBL_JSON_KEY_VERSION, it.value()); } + if (boost::iequals(it.key(), BBL_JSON_KEY_IS_CUSTOM)) { + key_values.emplace(BBL_JSON_KEY_IS_CUSTOM, it.value()); + } else if (boost::iequals(it.key(), BBL_JSON_KEY_NAME)) { key_values.emplace(BBL_JSON_KEY_NAME, it.value()); } @@ -1209,14 +1212,15 @@ ConfigSubstitutions ConfigBase::load_from_gcode_file(const std::string &file, Fo } //BBS: add json support -void ConfigBase::save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version) const +void ConfigBase::save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version, const std::string is_custom) const { json j; - //record the headers j[BBL_JSON_KEY_VERSION] = version; j[BBL_JSON_KEY_NAME] = name; j[BBL_JSON_KEY_FROM] = from; + if (!is_custom.empty()) + j[BBL_JSON_KEY_IS_CUSTOM] = is_custom; //record all the key-values for (const std::string &opt_key : this->keys()) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 793654630..42fa9df62 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -2139,7 +2139,7 @@ public: void save(const std::string &file) const; //BBS: add json support - void save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version) const; + void save_to_json(const std::string &file, const std::string &name, const std::string &from, const std::string &version, const std::string is_custom = "") const; // Set all the nullable values to nils. void null_nullables(); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 9daf935e2..1d6ceed4f 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -520,10 +520,10 @@ void Preset::save(DynamicPrintConfig* parent_config) ConfigOption *opt_dst = temp_config.option(option, true); opt_dst->set(opt_src); } - temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string()); + temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined); } else - this->config.save_to_json(this->file, this->name, from_str, this->version.to_string()); + this->config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined); fs::path idx_file(this->file); idx_file.replace_extension(".info"); @@ -682,6 +682,13 @@ bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle) return is_bbl_vendor_preset; } +bool Preset::is_custom_defined() +{ + if (custom_defined == "1") + return true; + return false; +} + static std::vector s_Preset_print_options { "layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness", @@ -757,7 +764,7 @@ static std::vector s_Preset_machine_limits_options { static std::vector s_Preset_printer_options { "printer_technology", - "printable_area", "bed_exclude_area", "gcode_flavor", + "printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor", "single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode", "printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "default_print_profile", "inherits", @@ -841,7 +848,7 @@ static std::vector s_Preset_sla_material_options { static std::vector s_Preset_sla_printer_options { "printer_technology", - "printable_area", "printable_height", + "printable_area","bed_custom_texture", "bed_custom_model", "printable_height", "display_width", "display_height", "display_pixels_x", "display_pixels_y", "display_mirror_x", "display_mirror_y", "display_orientation", @@ -1017,14 +1024,20 @@ void PresetCollection::load_presets( } preset.version = *version; + if (key_values.find(BBL_JSON_KEY_IS_CUSTOM) != key_values.end()) + preset.custom_defined = key_values[BBL_JSON_KEY_IS_CUSTOM]; + //BBS: use inherit config as the base Preset* inherit_preset = nullptr; ConfigOption* inherits_config = config.option(BBL_JSON_KEY_INHERITS); + + // check inherits_config if (inherits_config) { ConfigOptionString * option_str = dynamic_cast (inherits_config); std::string inherits_value = option_str->value; - inherit_preset = this->find_preset(inherits_value, false, true); + } else { + ; } const Preset& default_preset = this->default_preset_for(config); if (inherit_preset) { @@ -1032,19 +1045,22 @@ void PresetCollection::load_presets( preset.filament_id = inherit_preset->filament_id; } else { + if (!preset.is_custom_defined()) { + BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file; + continue; + } //should not happen - BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file; + //BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file; // Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field. - //preset.config = default_preset.config; - continue; + preset.config = default_preset.config; } preset.config.apply(std::move(config)); Preset::normalize(preset.config); // Report configuration fields, which are misplaced into a wrong group. std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config); - if (! incorrect_keys.empty()) + if (!incorrect_keys.empty()) BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << - preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; + preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; preset.loaded = true; //BBS: add some workaround for previous incorrect settings if ((!preset.setting_id.empty())&&(preset.setting_id == preset.base_id)) @@ -1352,25 +1368,29 @@ void PresetCollection::save_user_presets(const std::string& dir_path, const std: if (!preset->is_user()) continue; preset->file = path_from_name(preset->name); - //BBS: only save difference for user preset - std::string inherits = Preset::inherits(preset->config); - if (inherits.empty()) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find inherits for %1% , should not happen")%preset->name; - // BBS add sync info - preset->sync_info = "delete"; - need_to_delete_list.push_back(preset->setting_id); - delete_name_list.push_back(preset->name); - continue; - } - Preset* parent_preset = this->find_preset(inherits, false, true); - if (!parent_preset) { - BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find parent preset for %1% , inherits %2%")%preset->name %inherits; - continue; - } + if (preset->is_custom_defined()) { + preset->save(nullptr); + } else { + //BBS: only save difference for user preset + std::string inherits = Preset::inherits(preset->config); + if (inherits.empty()) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find inherits for %1% , should not happen")%preset->name; + // BBS add sync info + preset->sync_info = "delete"; + need_to_delete_list.push_back(preset->setting_id); + delete_name_list.push_back(preset->name); + continue; + } + Preset* parent_preset = this->find_preset(inherits, false, true); + if (!parent_preset) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find parent preset for %1% , inherits %2%")%preset->name %inherits; + continue; + } - if (preset->base_id.empty()) - preset->base_id = parent_preset->setting_id; - preset->save(&(parent_preset->config)); + if (preset->base_id.empty()) + preset->base_id = parent_preset->setting_id; + preset->save(&(parent_preset->config)); + } } for (auto delete_name: delete_name_list) @@ -1596,11 +1616,11 @@ bool PresetCollection::validate_printers(const std::string &name, DynamicPrintCo // Load a preset from an already parsed config file, insert it into the sorted sequence of presets // and select it, losing previous modifications. -Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select) +Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select, Semver file_version, bool is_custom_defined) { DynamicPrintConfig cfg(this->default_preset().config); cfg.apply_only(config, cfg.keys(), true); - return this->load_preset(path, name, std::move(cfg), select); + return this->load_preset(path, name, std::move(cfg), select, file_version, is_custom_defined); } static bool profile_print_params_same(const DynamicPrintConfig &cfg_old, const DynamicPrintConfig &cfg_new) @@ -1867,7 +1887,7 @@ std::pair PresetCollection::load_external_preset( return std::make_pair(&preset, false); } -Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select) +Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select, Semver file_version, bool is_custom_defined) { lock(); auto it = this->find_preset_internal(name); @@ -1882,6 +1902,10 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string preset.config = std::move(config); preset.loaded = true; preset.is_dirty = false; + preset.custom_defined = is_custom_defined ? "1": "0"; + //BBS + if (file_version.valid()) + preset.version = file_version; if (select) this->select_preset_by_name(name, true); unlock(); diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 7578bb239..4f8cb22ba 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -29,6 +29,7 @@ //BBS: add json support #define BBL_JSON_KEY_VERSION "version" +#define BBL_JSON_KEY_IS_CUSTOM "is_custom_defined" #define BBL_JSON_KEY_URL "url" #define BBL_JSON_KEY_NAME "name" #define BBL_JSON_KEY_DESCRIPTION "description" @@ -229,6 +230,7 @@ public: std::string user_id; // preset user_id std::string base_id; // base id of preset std::string sync_info; // enum: "delete", "create", "update", "" + std::string custom_defined; // enum: "1", "0", "" long long updated_time{0}; //last updated time std::map key_values; @@ -300,6 +302,8 @@ public: bool is_bbl_vendor_preset(PresetBundle *preset_bundle); + bool is_custom_defined(); + static const std::vector& print_options(); static const std::vector& filament_options(); // Printer options contain the nozzle options. @@ -434,8 +438,8 @@ public: // Load a preset from an already parsed config file, insert it into the sorted sequence of presets // and select it, losing previous modifications. - Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true); - Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true); + Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false); + Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false); // Returns a loaded preset, returns true if an existing preset was selected AND modified from config. // In that case the successive filament loaded for a multi material printer should not be modified, but diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index cbaa0f260..389a9f6b7 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1756,7 +1756,7 @@ ConfigSubstitutions PresetBundle::load_config_file(const std::string &path, Forw // Load a config file from a boost property_tree. This is a private method called from load_config_file. // is_external == false on if called from ConfigWizard -void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version) +void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version, bool selected, bool is_custom_defined) { PrinterTechnology printer_technology = Preset::printer_technology(config); @@ -1826,7 +1826,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool [&config, &inherits, &inherits_values, &compatible_printers_condition, &compatible_printers_condition_values, &compatible_prints_condition, &compatible_prints_condition_values, - is_external, &name, &name_or_path, file_version] + is_external, &name, &name_or_path, file_version, selected, is_custom_defined] (PresetCollection &presets, size_t idx, const std::string &key, const std::set &different_keys, std::string filament_id) { // Split the "compatible_printers_condition" and "inherits" values one by one from a single vector to the print & printer profiles. inherits = inherits_values[idx]; @@ -1838,7 +1838,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool if (is_external) presets.load_external_preset(name_or_path, name, config.opt_string(key, true), config, different_keys, PresetCollection::LoadAndSelect::Always, file_version, filament_id); else - presets.load_preset(presets.path_from_name(name), name, config).save(nullptr); + presets.load_preset(presets.path_from_name(name), name, config, selected, file_version, is_custom_defined).save(nullptr); }; switch (Preset::printer_technology(config)) { @@ -1899,7 +1899,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool loaded = this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config, filament_different_keys_set, PresetCollection::LoadAndSelect::Always, file_version, filament_id).first; else { // called from Config Wizard. - loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config); + loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config, true, file_version, is_custom_defined); loaded->save(nullptr); } this->filament_presets.clear(); diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp index 5b5c41d50..7e554283e 100644 --- a/src/libslic3r/PresetBundle.hpp +++ b/src/libslic3r/PresetBundle.hpp @@ -126,8 +126,8 @@ public: // Load user configuration and store it into the user profiles. // This method is called by the configuration wizard. - void load_config_from_wizard(const std::string &name, DynamicPrintConfig config) - { this->load_config_file_config(name, false, std::move(config)); } + void load_config_from_wizard(const std::string &name, DynamicPrintConfig config, Semver file_version, bool is_custom_defined = false) + { this->load_config_file_config(name, false, std::move(config), file_version, true, is_custom_defined); } // Load configuration that comes from a model file containing configuration, such as 3MF et al. // This method is called by the Plater. @@ -225,7 +225,7 @@ private: // Load print, filament & printer presets from a config. If it is an external config, then the name is extracted from the external path. // and the external config is just referenced, not stored into user profile directory. // If it is not an external config, then the config will be stored into the user profile directory. - void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version = Semver()); + void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config, Semver file_version = Semver(), bool selected = false, bool is_custom_defined = false); /*ConfigSubstitutions load_config_file_config_bundle( const std::string &path, const boost::property_tree::ptree &tree, ForwardCompatibilitySubstitutionRule compatibility_rule);*/ diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 55cd810d7..0240ea0c5 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -329,6 +329,16 @@ void PrintConfigDef::init_common_params() def->gui_type = ConfigOptionDef::GUIType::one_string; def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0) }); + def = this->add("bed_custom_texture", coString); + def->label = L("Bed custom texture"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionString("")); + + def = this->add("bed_custom_model", coString); + def->label = L("Bed custom model"); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionString("")); + def = this->add("elefant_foot_compensation", coFloat); def->label = L("Elephant foot compensation"); def->category = L("Quality"); @@ -1408,29 +1418,29 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("What kind of gcode the printer is compatible with"); def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("marlin"); - //def->enum_values.push_back("reprap"); - //def->enum_values.push_back("reprapfirmware"); - //def->enum_values.push_back("repetier"); - //def->enum_values.push_back("teacup"); - //def->enum_values.push_back("makerware"); - //def->enum_values.push_back("marlin2"); - //def->enum_values.push_back("sailfish"); - //def->enum_values.push_back("mach3"); - //def->enum_values.push_back("machinekit"); - //def->enum_values.push_back("smoothie"); - //def->enum_values.push_back("no-extrusion"); + /*def->enum_values.push_back("reprap"); + def->enum_values.push_back("reprapfirmware"); + def->enum_values.push_back("repetier"); + def->enum_values.push_back("teacup"); + def->enum_values.push_back("makerware"); + def->enum_values.push_back("marlin2"); + def->enum_values.push_back("sailfish"); + def->enum_values.push_back("mach3"); + def->enum_values.push_back("machinekit"); + def->enum_values.push_back("smoothie"); + def->enum_values.push_back("no-extrusion");*/ def->enum_labels.push_back("Marlin(legacy)"); - //def->enum_labels.push_back("RepRap/Sprinter"); - //def->enum_labels.push_back("RepRapFirmware"); - //def->enum_labels.push_back("Repetier"); - //def->enum_labels.push_back("Teacup"); - //def->enum_labels.push_back("MakerWare (MakerBot)"); - //def->enum_labels.push_back("Marlin 2"); - //def->enum_labels.push_back("Sailfish (MakerBot)"); - //def->enum_labels.push_back("Mach3/LinuxCNC"); - //def->enum_labels.push_back("Machinekit"); - //def->enum_labels.push_back("Smoothie"); - //def->enum_labels.push_back(L("No extrusion")); + /*def->enum_labels.push_back("RepRap/Sprinter"); + def->enum_labels.push_back("RepRapFirmware"); + def->enum_labels.push_back("Repetier"); + def->enum_labels.push_back("Teacup"); + def->enum_labels.push_back("MakerWare (MakerBot)"); + def->enum_labels.push_back("Marlin 2"); + def->enum_labels.push_back("Sailfish (MakerBot)"); + def->enum_labels.push_back("Mach3/LinuxCNC"); + def->enum_labels.push_back("Machinekit"); + def->enum_labels.push_back("Smoothie"); + def->enum_labels.push_back(L("No extrusion"));*/ def->mode = comAdvanced; def->readonly = false; def->set_default_value(new ConfigOptionEnum(gcfMarlinLegacy)); @@ -3894,6 +3904,16 @@ std::string DynamicPrintConfig::get_filament_type(std::string &displayed_filamen return "PLA"; } +bool DynamicPrintConfig::is_custom_defined() +{ + auto* is_custom_defined = dynamic_cast(this->option("is_custom_defined")); + if (!is_custom_defined || is_custom_defined->empty()) + return false; + if (is_custom_defined->get_at(0) == "1") + return true; + return false; +} + //FIXME localize this function. std::string validate(const FullPrintConfig &cfg) { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 4734d84bb..ae6852807 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -357,6 +357,8 @@ public: //BBS special case Support G/ Support W std::string get_filament_type(std::string &displayed_filament_type, int id = 0); + + bool is_custom_defined(); }; void handle_legacy_sla(DynamicPrintConfig &config); diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 56cff773c..0acb645d5 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -169,6 +169,8 @@ set(SLIC3R_GUI_SOURCES GUI/MainFrame.hpp GUI/BBLTopbar.cpp GUI/BBLTopbar.hpp + GUI/BedShapeDialog.cpp + GUI/BedShapeDialog.hpp GUI/Plater.cpp GUI/Plater.hpp GUI/PartPlate.cpp diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 165778584..3d96cbbee 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -47,6 +47,7 @@ #include "format.hpp" #include "MsgDialog.hpp" #include "UnsavedChangesDialog.hpp" +#include "MainFrame.hpp" #if defined(__linux__) && defined(__WXGTK3__) #define wxLinux_gtk3 true @@ -1220,70 +1221,67 @@ PageCustom::PageCustom(ConfigWizard *parent) append(tc_profile_name); } -#ifdef _WIN32 -PageFilesAssociation::PageFilesAssociation(ConfigWizard* parent) - : ConfigWizardPage(parent, _L("Files association"), _L("Files association")) +PageFirmware::PageFirmware(ConfigWizard *parent) + : ConfigWizardPage(parent, _L("Firmware Type"), _L("Firmware"), 1) + , gcode_opt(*print_config_def.get("gcode_flavor")) + , gcode_picker(nullptr) { - cb_3mf = new wxCheckBox(this, wxID_ANY, _L("Associate with 3mf files")); - cb_stl = new wxCheckBox(this, wxID_ANY, _L("Associate with stl files")); - //cb_gcode = new wxCheckBox(this, wxID_ANY, _L("Associate with gcode files")); + append_text(_L("Choose the type of firmware used by your printer.")); + append_text(_(gcode_opt.tooltip)); - append(cb_3mf); - append(cb_stl); - //append(cb_gcode); + wxArrayString choices; + choices.Alloc(gcode_opt.enum_labels.size()); + for (const auto &label : gcode_opt.enum_labels) { + choices.Add(label); + } + + gcode_picker = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); + wxGetApp().UpdateDarkUI(gcode_picker); + const auto &enum_values = gcode_opt.enum_values; + auto needle = enum_values.cend(); + if (gcode_opt.default_value) { + needle = std::find(enum_values.cbegin(), enum_values.cend(), gcode_opt.default_value->serialize()); + } + if (needle != enum_values.cend()) { + gcode_picker->SetSelection(needle - enum_values.cbegin()); + } else { + gcode_picker->SetSelection(0); + } + + append(gcode_picker); } -#endif // _WIN32 -PageVendors::PageVendors(ConfigWizard *parent) - : ConfigWizardPage(parent, _L("Other Vendors"), _L("Other Vendors")) +void PageFirmware::apply_custom_config(DynamicPrintConfig &config) { - const AppConfig &appconfig = this->wizard_p()->appconfig_new; - - append_text(_L("Pick another vendor:")); - - auto boldfont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - boldfont.SetWeight(wxFONTWEIGHT_BOLD); - - for (const auto &pair : wizard_p()->bundles) { - const VendorProfile *vendor = pair.second.vendor_profile; - //BBS: add BBL as default - if (vendor->id == PresetBundle::BBL_BUNDLE) { continue; } - - auto *cbox = new wxCheckBox(this, wxID_ANY, vendor->name); - cbox->Bind(wxEVT_CHECKBOX, [=](wxCommandEvent &event) { - wizard_p()->on_3rdparty_install(vendor, cbox->IsChecked()); - }); - - const auto &vendors = appconfig.vendors(); - const bool enabled = vendors.find(pair.first) != vendors.end(); - if (enabled) { - cbox->SetValue(true); - - auto pages = wizard_p()->pages_3rdparty.find(vendor->id); - wxCHECK_RET(pages != wizard_p()->pages_3rdparty.end(), _L("Internal error: third party vendor printers not created")); - - for (PagePrinters* page : { pages->second.first, pages->second.second }) - if (page) page->install = true; - } - - append(cbox); + auto sel = gcode_picker->GetSelection(); + if (sel >= 0 && (size_t)sel < gcode_opt.enum_labels.size()) { + auto *opt = new ConfigOptionEnum(static_cast(sel)); + config.set_key_value("gcode_flavor", opt); } } -/*PageBedShape::PageBedShape(ConfigWizard *parent) +PageBedShape::PageBedShape(ConfigWizard* parent) : ConfigWizardPage(parent, _L("Bed Shape and Size"), _L("Bed Shape"), 1) , shape_panel(new BedShapePanel(this)) { append_text(_L("Set the shape of your printer's bed.")); - shape_panel->build_panel(*wizard_p()->custom_config->option("printable_area"), {}, {}); + + shape_panel->build_panel(*wizard_p()->custom_config->option("printable_area"), + *wizard_p()->custom_config->option("bed_custom_texture"), + *wizard_p()->custom_config->option("bed_custom_model")); + append(shape_panel); } -void PageBedShape::apply_custom_config(DynamicPrintConfig &config) +void PageBedShape::apply_custom_config(DynamicPrintConfig& config) { const std::vector& points = shape_panel->get_shape(); + const std::string& custom_texture = shape_panel->get_custom_texture(); + const std::string& custom_model = shape_panel->get_custom_model(); config.set_key_value("printable_area", new ConfigOptionPoints(points)); -}*/ + config.set_key_value("bed_custom_texture", new ConfigOptionString(custom_texture)); + config.set_key_value("bed_custom_model", new ConfigOptionString(custom_model)); +} static void focus_event(wxFocusEvent& e, wxTextCtrl* ctrl, double def_value) { @@ -1460,19 +1458,231 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent) append(sizer_bed); } -void PageTemperatures::apply_custom_config(DynamicPrintConfig &config) +void PageTemperatures::apply_custom_config(DynamicPrintConfig& config) { // BBS -#if 0 - auto *opt_extr = new ConfigOptionInts(1, spin_extr->GetValue()); + /* + auto* opt_extr = new ConfigOptionInts(1, spin_extr->GetValue()); config.set_key_value("nozzle_temperature", opt_extr); - auto *opt_extr1st = new ConfigOptionInts(1, spin_extr->GetValue()); + auto* opt_extr1st = new ConfigOptionInts(1, spin_extr->GetValue()); config.set_key_value("nozzle_temperature_initial_layer", opt_extr1st); - auto *opt_bed = new ConfigOptionInts(1, spin_bed->GetValue()); + auto* opt_bed = new ConfigOptionInts(1, spin_bed->GetValue()); config.set_key_value("bed_temperature", opt_bed); - auto *opt_bed1st = new ConfigOptionInts(1, spin_bed->GetValue()); + auto* opt_bed1st = new ConfigOptionInts(1, spin_bed->GetValue()); config.set_key_value("bed_temperature_initial_layer", opt_bed1st); -#endif + */ +} + +ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent) + : wxPanel(parent) + , bg(ScalableBitmap(parent, "BambuStudio_192px_transparent.png", 192)) + , bullet_black(ScalableBitmap(parent, "bullet_black.png")) + , bullet_blue(ScalableBitmap(parent, "bullet_blue.png")) + , bullet_white(ScalableBitmap(parent, "bullet_white.png")) + , item_active(NO_ITEM) + , item_hover(NO_ITEM) + , last_page((size_t)-1) +{ +#ifndef __WXOSX__ + SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX +#endif //__WXOSX__ + SetMinSize(bg.bmp().GetSize()); + + const wxSize size = GetTextExtent("m"); + em_w = size.x; + em_h = size.y; + + Bind(wxEVT_PAINT, &ConfigWizardIndex::on_paint, this); + Bind(wxEVT_SIZE, [this](wxEvent& e) { e.Skip(); Refresh(); }); + Bind(wxEVT_MOTION, &ConfigWizardIndex::on_mouse_move, this); + + Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent &evt) { + if (item_hover != -1) { + item_hover = -1; + Refresh(); + } + evt.Skip(); + }); + + Bind(wxEVT_LEFT_UP, [this](wxMouseEvent &evt) { + if (item_hover >= 0) { go_to(item_hover); } + }); +} + +wxDECLARE_EVENT(EVT_INDEX_PAGE, wxCommandEvent); + +void ConfigWizardIndex::add_page(ConfigWizardPage *page) +{ + if (!page) + return; + last_page = items.size(); + items.emplace_back(Item { page->shortname, page->indent, page }); + Refresh(); +} + +void ConfigWizardIndex::add_label(wxString label, unsigned indent) +{ + items.emplace_back(Item { std::move(label), indent, nullptr }); + Refresh(); +} + +ConfigWizardPage* ConfigWizardIndex::active_page() const +{ + if (item_active >= items.size()) { return nullptr; } + + return items[item_active].page; +} + +void ConfigWizardIndex::go_prev() +{ + // Search for a preceiding item that is a page (not a label, ie. page != nullptr) + + if (item_active == NO_ITEM) { return; } + + for (size_t i = item_active; i > 0; i--) { + if (items[i - 1].page != nullptr) { + go_to(i - 1); + return; + } + } +} + +void ConfigWizardIndex::go_next() +{ + // Search for a next item that is a page (not a label, ie. page != nullptr) + + if (item_active == NO_ITEM) { return; } + + for (size_t i = item_active + 1; i < items.size(); i++) { + if (items[i].page != nullptr) { + go_to(i); + return; + } + } +} + +// This one actually performs the go-to op +void ConfigWizardIndex::go_to(size_t i) +{ + if (i != item_active + && i < items.size() + && items[i].page != nullptr) { + auto *new_active = items[i].page; + auto *former_active = active_page(); + if (former_active != nullptr) { + former_active->Hide(); + } + + item_active = i; + new_active->Show(); + + wxCommandEvent evt(EVT_INDEX_PAGE, GetId()); + AddPendingEvent(evt); + + Refresh(); + + new_active->on_activate(); + } +} + +void ConfigWizardIndex::go_to(const ConfigWizardPage *page) +{ + if (page == nullptr) { return; } + + for (size_t i = 0; i < items.size(); i++) { + if (items[i].page == page) { + go_to(i); + return; + } + } +} + +void ConfigWizardIndex::clear() +{ + auto *former_active = active_page(); + if (former_active != nullptr) { former_active->Hide(); } + + items.clear(); + item_active = NO_ITEM; +} + +void ConfigWizardIndex::on_paint(wxPaintEvent & evt) +{ + const auto size = GetClientSize(); + if (size.GetHeight() == 0 || size.GetWidth() == 0) { return; } + + wxPaintDC dc(this); + + const auto bullet_w = bullet_black.bmp().GetSize().GetWidth(); + const auto bullet_h = bullet_black.bmp().GetSize().GetHeight(); + const int yoff_icon = bullet_h < em_h ? (em_h - bullet_h) / 2 : 0; + const int yoff_text = bullet_h > em_h ? (bullet_h - em_h) / 2 : 0; + const int yinc = item_height(); + + int index_width = 0; + + unsigned y = 0; + for (size_t i = 0; i < items.size(); i++) { + const Item& item = items[i]; + unsigned x = em_w/2 + item.indent * em_w; + + if (i == item_active || (item_hover >= 0 && i == (size_t)item_hover)) { + dc.DrawBitmap(bullet_blue.bmp(), x, y + yoff_icon, false); + } + else if (i < item_active) { dc.DrawBitmap(bullet_black.bmp(), x, y + yoff_icon, false); } + else if (i > item_active) { dc.DrawBitmap(bullet_white.bmp(), x, y + yoff_icon, false); } + + x += + bullet_w + em_w/2; + const auto text_size = dc.GetTextExtent(item.label); + dc.SetTextForeground(wxGetApp().get_label_clr_default()); + dc.DrawText(item.label, x, y + yoff_text); + + y += yinc; + index_width = std::max(index_width, (int)x + text_size.x); + } + + //draw logo + if (int y = size.y - bg.GetBmpHeight(); y>=0) { + dc.DrawBitmap(bg.bmp(), 0, y, false); + index_width = std::max(index_width, bg.GetBmpWidth() + em_w / 2); + } + + if (GetMinSize().x < index_width) { + CallAfter([this, index_width]() { + SetMinSize(wxSize(index_width, GetMinSize().y)); + Refresh(); + }); + } +} + +void ConfigWizardIndex::on_mouse_move(wxMouseEvent &evt) +{ + const wxClientDC dc(this); + const wxPoint pos = evt.GetLogicalPosition(dc); + + const ssize_t item_hover_new = pos.y / item_height(); + + if (item_hover_new < ssize_t(items.size()) && item_hover_new != item_hover) { + item_hover = item_hover_new; + Refresh(); + } + + evt.Skip(); +} + +void ConfigWizardIndex::msw_rescale() +{ + const wxSize size = GetTextExtent("m"); + em_w = size.x; + em_h = size.y; + + bg.msw_rescale(); + SetMinSize(bg.bmp().GetSize()); + + bullet_black.msw_rescale(); + bullet_blue.msw_rescale(); + bullet_white.msw_rescale(); + Refresh(); } // Materials @@ -1562,8 +1772,29 @@ void ConfigWizard::priv::load_pages() wxWindowUpdateLocker freeze_guard(q); (void)freeze_guard; + const ConfigWizardPage *former_active = index->active_page(); + + index->clear(); + + // Printers + if (!only_sla_mode) { + index->add_page(page_custom); + if (page_custom->custom_wanted()) { + index->add_page(page_firmware); + index->add_page(page_bed); + index->add_page(page_diams); + //index->add_page(page_temps); + } + + // Filaments & Materials + if (any_fff_selected) { index->add_page(page_filaments); } + } + if (any_sla_selected) { index->add_page(page_sla_materials); } + // there should to be selected at least one printer - btn_finish->Enable(); + btn_finish->Enable(any_fff_selected || any_sla_selected || custom_printer_selected); + + index->go_to(former_active); // Will restore the active item/page if possible q->Layout(); // This Refresh() is needed to avoid ugly artifacts after printer selection, when no one vendor was selected from the very beginnig @@ -1584,6 +1815,12 @@ void ConfigWizard::priv::init_dialog_size() 9*disp_rect.width / 10, 9*disp_rect.height / 10); + const int width_hint = index->GetSize().GetWidth() + 90 * em()/*std::max(90 * em(), (only_sla_mode ? page_msla->get_width() : page_fff->get_width()) + 30 * em())*/; // XXX: magic constant, I found no better solution + if (width_hint < window_rect.width) { + window_rect.x += (window_rect.width - width_hint) / 2; + window_rect.width = width_hint; + } + q->SetSize(window_rect); } @@ -1668,16 +1905,20 @@ void ConfigWizard::priv::enable_next(bool enable) void ConfigWizard::priv::set_start_page(ConfigWizard::StartPage start_page) { switch (start_page) { - case ConfigWizard::SP_PRINTERS: + case ConfigWizard::SP_CUSTOM: + index->go_to(page_custom); btn_next->SetFocus(); break; case ConfigWizard::SP_FILAMENTS: + index->go_to(page_filaments); btn_finish->SetFocus(); break; case ConfigWizard::SP_MATERIALS: + index->go_to(page_sla_materials); btn_finish->SetFocus(); break; default: + index->go_to(page_custom); btn_next->SetFocus(); break; } @@ -1714,7 +1955,7 @@ void ConfigWizard::priv::create_3rdparty_pages() add_page(pageSLA); } - pages_3rdparty.insert({vendor->id, {pageFFF, pageSLA}}); + //pages_3rdparty.insert({vendor->id, {pageFFF, pageSLA}}); } } @@ -1932,19 +2173,19 @@ void ConfigWizard::priv::select_default_materials_for_printer_models(Technology void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool install) { - auto it = pages_3rdparty.find(vendor->id); - wxCHECK_RET(it != pages_3rdparty.end(), "Internal error: GUI page not found for 3rd party vendor profile"); + //auto it = pages_3rdparty.find(vendor->id); + //wxCHECK_RET(it != pages_3rdparty.end(), "Internal error: GUI page not found for 3rd party vendor profile"); - for (PagePrinters* page : { it->second.first, it->second.second }) - if (page) { - if (page->install && !install) - page->select_all(false); - page->install = install; - // if some 3rd vendor is selected, select first printer for them - if (install) - page->printer_pickers[0]->select_one(0, true); - page->Layout(); - } + //for (PagePrinters* page : { it->second.first, it->second.second }) + // if (page) { + // if (page->install && !install) + // page->select_all(false); + // page->install = install; + // // if some 3rd vendor is selected, select first printer for them + // if (install) + // page->printer_pickers[0]->select_one(0, true); + // page->Layout(); + // } load_pages(); } @@ -1960,6 +2201,7 @@ bool ConfigWizard::priv::on_bnt_finish() * than last changes wouldn't be updated for filaments/materials. * SO, do that before close of Wizard */ + update_materials(T_ANY); if (any_fff_selected) page_filaments->reload_presets(); @@ -2323,30 +2565,42 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese app_config->set_vendors(appconfig_new); -#ifdef _WIN32 - app_config->set_bool("associate_3mf", page_files_association->associate_3mf()); - app_config->set_bool("associate_stl", page_files_association->associate_stl()); - - if (wxGetApp().is_editor()) { - if (page_files_association->associate_3mf()) - wxGetApp().associate_files(L"3mf"); - if (page_files_association->associate_stl()) - wxGetApp().associate_files(L"stl"); - } -// else { -// if (page_files_association->associate_gcode()) -// wxGetApp().associate_gcode_files(); -// } - -#endif // _WIN32 - if (check_unsaved_preset_changes) preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem, {preferred_model, preferred_variant, first_added_filament, first_added_sla_material}); + if (!only_sla_mode && page_custom->custom_wanted()) { + // if unsaved changes was not cheched till this moment + if (!check_unsaved_preset_changes && + !wxGetApp().check_and_keep_current_preset_changes(caption, _L("Custom printer was installed and it will be activated."), act_btns, &apply_keeped_changes)) + return false; + + page_firmware->apply_custom_config(*custom_config); + page_bed->apply_custom_config(*custom_config); + page_diams->apply_custom_config(*custom_config); + //page_temps->apply_custom_config(*custom_config); + +#if ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE + copy_bed_model_and_texture_if_needed(*custom_config); +#endif // ENABLE_COPY_CUSTOM_BED_MODEL_AND_TEXTURE + + custom_config->set_key_value("filament_colour", wxGetApp().preset_bundle->project_config.option("filament_colour")); + const std::string profile_name = page_custom->profile_name(); + Semver semver(SLIC3R_VERSION); + preset_bundle->load_config_from_wizard(profile_name, *custom_config, semver, true); + + wxGetApp().plater()->sidebar().update_presets(Slic3r::Preset::Type::TYPE_PRINTER); + wxGetApp().plater()->sidebar().update_presets(Slic3r::Preset::Type::TYPE_FILAMENT); + wxGetApp().plater()->sidebar().update_presets(Slic3r::Preset::Type::TYPE_PRINT); + } + // Update the selections from the compatibilty. preset_bundle->export_selections(*app_config); + // Update Preset Combobox + //auto evt = new SimpleEvent(EVT_UPDATE_PRESET_CB); + //wxQueueEvent(wxGetApp().mainframe, evt); + return true; } void ConfigWizard::priv::update_presets_in_config(const std::string& section, const std::string& alias_key, bool add) @@ -2370,11 +2624,7 @@ void ConfigWizard::priv::update_presets_in_config(const std::string& section, co bool ConfigWizard::priv::check_fff_selected() { - bool ret = page_fff->any_selected(); - for (const auto& printer: pages_3rdparty) - if (printer.second.first) // FFF page - ret |= printer.second.first->any_selected(); - return ret; + return false; } bool ConfigWizard::priv::check_sla_selected() @@ -2386,7 +2636,7 @@ bool ConfigWizard::priv::check_sla_selected() // Public ConfigWizard::ConfigWizard(wxWindow *parent) - : DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(name()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + : DPIDialog(parent, wxID_ANY, wxString(SLIC3R_APP_NAME) + " - " + _(name()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE /*| wxRESIZE_BORDER*/) , p(new priv(this)) { this->SetFont(wxGetApp().normal_font()); @@ -2394,9 +2644,12 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->load_vendors(); //BBS: add bed exclude areas p->custom_config.reset(DynamicPrintConfig::new_from_defaults_keys({ - "gcode_flavor", "printable_area", "bed_exclude_area", "nozzle_diameter", "filament_diameter", "nozzle_temperature", /*"bed_temperature",*/ + "gcode_flavor", "printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "nozzle_diameter", "filament_diameter" + //, "nozzle_temperature", "bed_temperature" })); + p->index = new ConfigWizardIndex(this); + auto *vsizer = new wxBoxSizer(wxVERTICAL); auto *topsizer = new wxBoxSizer(wxHORIZONTAL); auto* hline = new StaticLine(this); @@ -2408,12 +2661,10 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->hscroll_sizer = new wxBoxSizer(wxHORIZONTAL); p->hscroll->SetSizer(p->hscroll_sizer); + topsizer->Add(p->index, 0, wxEXPAND); topsizer->AddSpacer(INDEX_MARGIN); topsizer->Add(p->hscroll, 1, wxEXPAND); - p->btn_sel_all = new wxButton(this, wxID_ANY, _L("Select all standard printers")); - p->btnsizer->Add(p->btn_sel_all); - p->btn_prev = new wxButton(this, wxID_ANY, _L("< &Back")); p->btn_next = new wxButton(this, wxID_ANY, _L("&Next >")); p->btn_finish = new wxButton(this, wxID_APPLY, _L("&Finish")); @@ -2424,7 +2675,6 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->btnsizer->Add(p->btn_finish, 0, wxLEFT, BTN_SPACING); p->btnsizer->Add(p->btn_cancel, 0, wxLEFT, BTN_SPACING); - wxGetApp().UpdateDarkUI(p->btn_sel_all); wxGetApp().UpdateDarkUI(p->btn_prev); wxGetApp().UpdateDarkUI(p->btn_next); wxGetApp().UpdateDarkUI(p->btn_finish); @@ -2435,36 +2685,22 @@ ConfigWizard::ConfigWizard(wxWindow *parent) wxCHECK_RET(bbl_it != p->bundles.cend(), "Vendor BambooLab not found"); const VendorProfile * vendor_bbl = bbl_it->second.vendor_profile; - p->page_fff = new PagePrinters(this, _L("BBL FFF Technology Printers"), "BBL FFF", *vendor_bbl, 0, T_FFF); p->only_sla_mode = false; - if (!p->only_sla_mode) { - p->add_page(p->page_fff); - p->page_fff->is_primary_printer_page = true; - } - - if (!p->only_sla_mode) { - // Pages for 3rd party vendors - p->create_3rdparty_pages(); // Needs to be done _before_ creating PageVendors - p->add_page(p->page_vendors = new PageVendors(this)); - //p->add_page(p->page_custom = new PageCustom(this)); - //p->custom_printer_selected = p->page_custom->custom_wanted(); - } - p->any_sla_selected = p->check_sla_selected(); if (p->only_sla_mode) p->any_fff_selected = p->check_fff_selected(); - p->update_materials(T_ANY); - if (!p->only_sla_mode) - p->add_page(p->page_filaments = new PageMaterials(this, &p->filaments, - _L("Filament Profiles Selection"), _L("Filaments"), _L("Type:") )); + p->add_page(p->page_custom = new PageCustom(this)); + p->custom_printer_selected = p->page_custom->custom_wanted(); -#ifdef _WIN32 - p->add_page(p->page_files_association = new PageFilesAssociation(this)); -#endif // _WIN32 - //p->add_page(p->page_bed = new PageBedShape(this)); + p->add_page(p->page_firmware = new PageFirmware(this)); + p->add_page(p->page_bed = new PageBedShape(this)); p->add_page(p->page_diams = new PageDiameters(this)); - p->add_page(p->page_temps = new PageTemperatures(this)); + //p->add_page(p->page_temps = new PageTemperatures(this)); + + p->update_materials(T_ANY); + p->add_page(p->page_filaments = new PageMaterials(this, &p->filaments, + _L("Filament Profiles Selection"), _L("Filaments"), _L("Type:"))); p->load_pages(); @@ -2484,7 +2720,12 @@ ConfigWizard::ConfigWizard(wxWindow *parent) p->btn_next->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { - ; + ConfigWizardPage* active_page = this->p->index->active_page(); + if ((active_page == p->page_filaments || active_page == p->page_sla_materials) && + !p->check_and_install_missing_materials(dynamic_cast(active_page)->materials->technology)) + // In that case don't leave the page and the function above queried the user whether to install default materials. + return; + this->p->index->go_next(); }); p->btn_finish->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) @@ -2493,10 +2734,13 @@ ConfigWizard::ConfigWizard(wxWindow *parent) this->EndModal(wxID_OK); }); - p->btn_sel_all->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) { - p->any_sla_selected = true; - p->load_pages(); - p->page_fff->select_all(true, false); + p->index->Bind(EVT_INDEX_PAGE, [this](const wxCommandEvent &) { + const bool is_last = p->index->active_is_last(); + p->btn_next->Show(! is_last); + if (is_last) + p->btn_finish->SetFocus(); + + Layout(); }); if (wxLinux_gtk3) @@ -2558,13 +2802,9 @@ void ConfigWizard::on_dpi_changed(const wxRect &suggested_rect) msw_buttons_rescale(this, em, { wxID_APPLY, wxID_CANCEL, - p->btn_sel_all->GetId(), p->btn_next->GetId(), p->btn_prev->GetId() }); - for (auto printer_picker: p->page_fff->printer_pickers) - msw_buttons_rescale(this, em, printer_picker->get_button_indexes()); - p->init_dialog_size(); Refresh(); diff --git a/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp index 88d2e2d7c..f929a3aaa 100644 --- a/src/slic3r/GUI/ConfigWizard.hpp +++ b/src/slic3r/GUI/ConfigWizard.hpp @@ -32,6 +32,7 @@ public: SP_PRINTERS, SP_FILAMENTS, SP_MATERIALS, + SP_CUSTOM, }; ConfigWizard(wxWindow *parent); diff --git a/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp index 157bf07c1..1e0bf40ed 100644 --- a/src/slic3r/GUI/ConfigWizard_private.hpp +++ b/src/slic3r/GUI/ConfigWizard_private.hpp @@ -24,7 +24,7 @@ #include "libslic3r/PrintConfig.hpp" #include "libslic3r/PresetBundle.hpp" #include "slic3r/Utils/PresetUpdater.hpp" -//#include "BedShapeDialog.hpp" +#include "BedShapeDialog.hpp" #include "GUI.hpp" #include "wxExtensions.hpp" @@ -162,7 +162,7 @@ struct PrinterPickerEvent; typedef std::function ModelFilter; -struct PrinterPicker: wxPanel +struct PrinterPicker: wxPanel //TO check { struct Checkbox : wxCheckBox { @@ -240,7 +240,7 @@ struct PageWelcome: ConfigWizardPage virtual void set_run_reason(ConfigWizard::RunReason run_reason) override; }; -struct PagePrinters: ConfigWizardPage +struct PagePrinters: ConfigWizardPage //TO check { std::vector printer_pickers; Technology technology; @@ -386,50 +386,59 @@ private: }; -struct PageUpdate: ConfigWizardPage +//struct PageUpdate: ConfigWizardPage +//{ +// bool version_check; +// bool preset_update; +// +// PageUpdate(ConfigWizard *parent); +//}; + +//struct PageReloadFromDisk : ConfigWizardPage +//{ +// bool full_pathnames; +// +// PageReloadFromDisk(ConfigWizard* parent); +//}; + +//#ifdef _WIN32 +//struct PageFilesAssociation : ConfigWizardPage +//{ +//private: +// wxCheckBox* cb_3mf{ nullptr }; +// wxCheckBox* cb_stl{ nullptr }; +//// wxCheckBox* cb_gcode; +// +//public: +// PageFilesAssociation(ConfigWizard* parent); +// +// bool associate_3mf() const { return cb_3mf->IsChecked(); } +// bool associate_stl() const { return cb_stl->IsChecked(); } +//// bool associate_gcode() const { return cb_gcode->IsChecked(); } +//}; +//#endif // _WIN32 + +//struct PageVendors: ConfigWizardPage +//{ +// PageVendors(ConfigWizard *parent); +//}; + +struct PageFirmware: ConfigWizardPage { - bool version_check; - bool preset_update; + const ConfigOptionDef &gcode_opt; + wxChoice *gcode_picker; - PageUpdate(ConfigWizard *parent); -}; - -struct PageReloadFromDisk : ConfigWizardPage -{ - bool full_pathnames; - - PageReloadFromDisk(ConfigWizard* parent); -}; - -#ifdef _WIN32 -struct PageFilesAssociation : ConfigWizardPage -{ -private: - wxCheckBox* cb_3mf{ nullptr }; - wxCheckBox* cb_stl{ nullptr }; -// wxCheckBox* cb_gcode; - -public: - PageFilesAssociation(ConfigWizard* parent); - - bool associate_3mf() const { return cb_3mf->IsChecked(); } - bool associate_stl() const { return cb_stl->IsChecked(); } -// bool associate_gcode() const { return cb_gcode->IsChecked(); } -}; -#endif // _WIN32 - -struct PageVendors: ConfigWizardPage -{ - PageVendors(ConfigWizard *parent); -}; - -/*struct PageBedShape: ConfigWizardPage -{ - BedShapePanel *shape_panel; - - PageBedShape(ConfigWizard *parent); + PageFirmware(ConfigWizard *parent); virtual void apply_custom_config(DynamicPrintConfig &config); -};*/ +}; + +struct PageBedShape : ConfigWizardPage +{ + BedShapePanel* shape_panel; + + PageBedShape(ConfigWizard* parent); + virtual void apply_custom_config(DynamicPrintConfig& config); +}; struct PageDiameters: ConfigWizardPage { @@ -454,6 +463,62 @@ typedef std::map> Pages3rdparty; + +class ConfigWizardIndex: public wxPanel +{ +public: + 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(const ConfigWizardPage *page); + + void clear(); + void msw_rescale(); + + int em() const { return em_w; } + + static const size_t NO_ITEM = size_t(-1); +private: + struct Item + { + wxString label; + unsigned indent; + ConfigWizardPage *page; // nullptr page => label-only item + + bool operator==(ConfigWizardPage *page) const { return this->page == page; } + }; + + int em_w; + int em_h; + ScalableBitmap bg; + ScalableBitmap bullet_black; + ScalableBitmap bullet_blue; + ScalableBitmap bullet_white; + + std::vector items; + size_t item_active; + ssize_t item_hover; + size_t last_page; + + int item_height() const { return std::max(bullet_black.bmp().GetSize().GetHeight(), em_w) + em_w; } + + void on_paint(wxPaintEvent &evt); + void on_mouse_move(wxMouseEvent &evt); +}; + +wxDEFINE_EVENT(EVT_INDEX_PAGE, wxCommandEvent); + + + // ConfigWizard private data typedef std::map> PresetAliases; @@ -482,26 +547,28 @@ struct ConfigWizard::priv wxBoxSizer *hscroll_sizer = nullptr; wxBoxSizer *btnsizer = nullptr; ConfigWizardPage *page_current = nullptr; - wxButton *btn_sel_all = nullptr; + ConfigWizardIndex *index = nullptr; + //wxButton *btn_sel_all = nullptr; wxButton *btn_prev = nullptr; wxButton *btn_next = nullptr; wxButton *btn_finish = nullptr; wxButton *btn_cancel = nullptr; - PagePrinters *page_fff = nullptr; - PagePrinters *page_msla = nullptr; + //PagePrinters *page_fff = nullptr; + //PagePrinters *page_msla = nullptr; PageMaterials *page_filaments = nullptr; PageMaterials *page_sla_materials = nullptr; PageCustom *page_custom = nullptr; - PageReloadFromDisk *page_reload_from_disk = nullptr; -#ifdef _WIN32 - PageFilesAssociation* page_files_association = nullptr; -#endif // _WIN32 - PageVendors *page_vendors = nullptr; - Pages3rdparty pages_3rdparty; + //PageReloadFromDisk *page_reload_from_disk = nullptr; +//#ifdef _WIN32 +// PageFilesAssociation* page_files_association = nullptr; +//#endif // _WIN32 + //PageVendors *page_vendors = nullptr; + //Pages3rdparty pages_3rdparty; // Custom setup pages - //PageBedShape *page_bed = nullptr; + PageFirmware *page_firmware = nullptr; + PageBedShape *page_bed = nullptr; PageDiameters *page_diams = nullptr; PageTemperatures *page_temps = nullptr; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ab07b42f2..16a18ddcc 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3653,6 +3653,7 @@ void GUI_App::sync_preset(Preset* preset) std::string updated_info; // only sync user's preset if (!preset->is_user()) return; + if (preset->is_custom_defined()) return; if (preset->setting_id.empty() && preset->sync_info.empty() && !preset->base_id.empty()) { std::map values_map; @@ -4944,14 +4945,14 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage { wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null"); - if (reason == ConfigWizard::RR_USER) { - //TODO: turn off it currently, maybe need to turn on in the future - //if (preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED) - // return false; - } + //if (reason == ConfigWizard::RR_USER) { + // //TODO: turn off it currently, maybe need to turn on in the future + // if (preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED) + // return false; + //} - //auto wizard = new ConfigWizard(mainframe); - //const bool res = wizard->run(reason, start_page); + //auto wizard_t = new ConfigWizard(mainframe); + //const bool res = wizard_t->run(reason, start_page); std::string strFinish = wxGetApp().app_config->get("firstguide", "finish"); long pStyle = wxCAPTION | wxCLOSE_BOX | wxSYSTEM_MENU; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index c126ad771..57d1474f0 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -56,6 +56,7 @@ #include "NotificationManager.hpp" #include "MarkdownTip.hpp" #include "NetworkTestDialog.hpp" +#include "ConfigWizard.hpp" #ifdef _WIN32 #include @@ -69,6 +70,7 @@ namespace GUI { wxDEFINE_EVENT(EVT_SELECT_TAB, wxCommandEvent); wxDEFINE_EVENT(EVT_HTTP_ERROR, wxCommandEvent); wxDEFINE_EVENT(EVT_USER_LOGIN, wxCommandEvent); +wxDEFINE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent); // BBS: backup wxDEFINE_EVENT(EVT_BACKUP_POST, wxCommandEvent); @@ -321,6 +323,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_ TabPosition pos = (TabPosition)evt.GetInt(); m_tabpanel->SetSelection(pos); }); + Bind(EVT_SYNC_CLOUD_PRESET, &MainFrame::on_select_default_preset, this); // Bind(wxEVT_MENU, @@ -1153,10 +1156,23 @@ bool MainFrame::can_export_gcode() const return true; } +bool MainFrame::can_print_3mf() const +{ + if (m_plater && !m_plater->model().objects.empty()) { + if (wxGetApp().preset_bundle->printers.get_edited_preset().is_custom_defined()) + return false; + } + return true; +} + bool MainFrame::can_send_gcode() const { if (m_plater && !m_plater->model().objects.empty()) { + // BBL printer presets + if (!wxGetApp().preset_bundle->printers.get_edited_preset().is_custom_defined()) + return false; + auto cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config; if (const auto *print_host_opt = cfg.option("print_host"); print_host_opt) return !print_host_opt->value.empty(); @@ -1261,44 +1277,44 @@ wxBoxSizer* MainFrame::create_side_tools() sizer->Layout(); m_slice_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) - { - //this->m_plater->select_view_3D("Preview"); - m_plater->update(); - if (m_slice_select == eSliceAll) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL)); - else - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE)); + { + //this->m_plater->select_view_3D("Preview"); + m_plater->update(); + if (m_slice_select == eSliceAll) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL)); + else + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE)); this->m_tabpanel->SetSelection(tpPreview); }); m_print_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) - { - //this->m_plater->select_view_3D("Preview"); - if (m_print_select == ePrintAll || m_print_select == ePrintPlate) { - m_plater->apply_background_progress(); - // check valid of print - m_print_enable = get_enable_print_status(); - m_print_btn->Enable(m_print_enable); - if (m_print_enable) { - if (m_print_select == ePrintAll) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_ALL)); - if (m_print_select == ePrintPlate) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE)); + //this->m_plater->select_view_3D("Preview"); + if (m_print_select == ePrintAll || m_print_select == ePrintPlate) + { + m_plater->apply_background_progress(); + // check valid of print + m_print_enable = get_enable_print_status(); + m_print_btn->Enable(m_print_enable); + if (m_print_enable) { + if (m_print_select == ePrintAll) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_ALL)); + if (m_print_select == ePrintPlate) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE)); + } } - } - else if (m_print_select == eExportGcode) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_GCODE)); - else if (m_print_select == eSendGcode) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_GCODE)); - else if (m_print_select == eUploadGcode) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_UPLOAD_GCODE)); - else if (m_print_select == eExportSlicedFile) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); - else if (m_print_select == eSendToPrinter) - wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER)); - }); + else if (m_print_select == eExportGcode) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_GCODE)); + else if (m_print_select == eSendGcode) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_GCODE)); + else if (m_print_select == eUploadGcode) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_UPLOAD_GCODE)); + else if (m_print_select == eExportSlicedFile) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); + else if (m_print_select == eSendToPrinter) + wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_TO_PRINTER)); + }); // only support single plate currently #if 0 @@ -1311,21 +1327,21 @@ wxBoxSizer* MainFrame::create_side_tools() slice_plate_btn->SetCornerRadius(0); slice_all_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) { - m_slice_btn->SetLabel(_L("Slice all")); - m_slice_select = eSliceAll; - m_slice_enable = get_enable_slice_status(); - m_slice_btn->Enable(m_slice_enable); - this->Layout(); - p->Dismiss(); + m_slice_btn->SetLabel(_L("Slice all")); + m_slice_select = eSliceAll; + m_slice_enable = get_enable_slice_status(); + m_slice_btn->Enable(m_slice_enable); + this->Layout(); + p->Dismiss(); }); slice_plate_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) { - m_slice_btn->SetLabel(_L("Slice plate")); - m_slice_select = eSlicePlate; - m_slice_enable = get_enable_slice_status(); - m_slice_btn->Enable(m_slice_enable); - this->Layout(); - p->Dismiss(); + m_slice_btn->SetLabel(_L("Slice plate")); + m_slice_select = eSlicePlate; + m_slice_enable = get_enable_slice_status(); + m_slice_btn->Enable(m_slice_enable); + this->Layout(); + p->Dismiss(); }); p->append_button(slice_all_btn); p->append_button(slice_plate_btn); @@ -1340,14 +1356,14 @@ wxBoxSizer* MainFrame::create_side_tools() #if ENABEL_PRINT_ALL SideButton* print_all_btn = new SideButton(p, _L("Print all"), ""); print_all_btn->SetCornerRadius(0); - print_all_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent &) { + print_all_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) { m_print_btn->SetLabel(_L("Print all")); m_print_select = ePrintAll; if (m_print_enable) m_print_enable = get_enable_print_status(); m_print_btn->Enable(m_print_enable); this->Layout(); p->Dismiss(); - }); + }); #endif #if ENABEL_PRINT_ALL p->append_button(print_all_btn); @@ -1393,7 +1409,8 @@ wxBoxSizer* MainFrame::create_side_tools() p->append_button(send_gcode_btn); //p->append_button(upload_gcode_btn); p->append_button(export_gcode_btn); - } else { + } + else { //Bambu Studio Buttons SideButton* print_plate_btn = new SideButton(p, _L("Print"), ""); print_plate_btn->SetCornerRadius(0); @@ -1754,6 +1771,7 @@ static wxMenu* generate_help_menu() }, "", nullptr, []() { return true; }); + // About #ifndef __APPLE__ wxString about_title = wxString::Format(_L("&About %s"), SLIC3R_APP_FULL_NAME); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 416552743..d7ac7cf63 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -112,6 +112,7 @@ class MainFrame : public DPIFrame bool can_export_toolpaths() const; bool can_export_supports() const; bool can_export_gcode() const; + bool can_print_3mf() const; bool can_send_gcode() const; //bool can_export_gcode_sd() const; //bool can_eject() const; @@ -359,6 +360,7 @@ public: wxDECLARE_EVENT(EVT_HTTP_ERROR, wxCommandEvent); wxDECLARE_EVENT(EVT_USER_LOGIN, wxCommandEvent); +wxDECLARE_EVENT(EVT_UPDATE_PRESET_CB, SimpleEvent); } // GUI } //Slic3r diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index af49197fd..ff2e8b49a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -457,6 +457,12 @@ Sidebar::Sidebar(Plater *parent) p->m_printer_icon = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "printer"); p->m_text_printer_settings = new Label(p->m_panel_printer_title, _L("Printer")); + p->m_printer_icon->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) { + auto wizard_t = new ConfigWizard(wxGetApp().mainframe); + wizard_t->run(ConfigWizard::RR_USER, ConfigWizard::SP_CUSTOM); + }); + + p->m_printer_setting = new ScalableButton(p->m_panel_printer_title, wxID_ANY, "settings"); p->m_printer_setting->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { // p->editing_filament = -1; @@ -972,9 +978,15 @@ void Sidebar::update_presets(Preset::Type preset_type) } case Preset::TYPE_PRINT: + //wxGetApp().mainframe->m_param_panel; //p->combo_print->update(); + { + Tab* print_tab = wxGetApp().get_tab(Preset::TYPE_PRINT); + if (print_tab) { + print_tab->get_combo_box()->update(); + } break; - + } case Preset::TYPE_SLA_PRINT: ;// p->combo_sla_print->update(); break; @@ -987,6 +999,12 @@ void Sidebar::update_presets(Preset::Type preset_type) { update_all_preset_comboboxes(); p->show_preset_comboboxes(); + + /* update bed shape */ + Tab* printer_tab = wxGetApp().get_tab(Preset::TYPE_PRINTER); + if (printer_tab) { + printer_tab->update(); + } break; } @@ -2000,7 +2018,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , main_frame(main_frame) //BBS: add bed_exclude_area , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ - "printable_area", "bed_exclude_area", "print_sequence", + "printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "print_sequence", "extruder_clearance_radius", "extruder_clearance_max_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_distance", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", @@ -9328,6 +9346,10 @@ void Plater::on_config_change(const DynamicPrintConfig &config) bed_shape_changed = true; update_scheduled = true; } + else if (opt_key == "bed_shape" || opt_key == "bed_custom_texture" || opt_key == "bed_custom_model") { + bed_shape_changed = true; + update_scheduled = true; + } else if (boost::starts_with(opt_key, "enable_prime_tower") || boost::starts_with(opt_key, "prime_tower") || boost::starts_with(opt_key, "wipe_tower") || @@ -9406,7 +9428,8 @@ void Plater::set_bed_shape() const //BBS: add bed exclude areas p->config->option("bed_exclude_area")->values, p->config->option("printable_height")->value, - texture_filename, {}); + p->config->option("bed_custom_texture")->value.empty() ? texture_filename : p->config->option("bed_custom_texture")->value, + p->config->option("bed_custom_model")->value); } //BBS: add bed exclude area