WIP: filament/material filtering per selected printers

This commit is contained in:
Vojtech Kral 2019-08-30 17:40:25 +02:00
parent 9a465514ff
commit c5a67ff931
3 changed files with 206 additions and 126 deletions

View file

@ -475,7 +475,7 @@ PagePrinters::PagePrinters(ConfigWizard *parent,
picker->Bind(EVT_PRINTER_PICK, [this, appconfig](const PrinterPickerEvent &evt) {
appconfig->set_variant(evt.vendor_id, evt.model_id, evt.variant_name, evt.enable);
wizard_p()->on_printer_pick(this);
wizard_p()->on_printer_pick(this, evt);
});
append(new wxStaticLine(this));
@ -527,6 +527,7 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
, list_l3(new PresetList(this))
, sel1_prev(wxNOT_FOUND)
, sel2_prev(wxNOT_FOUND)
, presets_loaded(false)
{
append_spacer(VERTICAL_SPACING);
@ -559,12 +560,6 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
append(grid);
list_l1->append(_(L("(All)")), &EMPTY);
for (const std::string &type : materials->types) {
list_l1->append(type, &type);
}
list_l1->Bind(wxEVT_LISTBOX, [this](wxCommandEvent &) {
update_lists(list_l1->GetSelection(), list_l2->GetSelection());
});
@ -577,10 +572,27 @@ PageMaterials::PageMaterials(ConfigWizard *parent, Materials *materials, wxStrin
sel_all->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { select_all(true); });
sel_none->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { select_all(false); });
reload_presets();
}
void PageMaterials::reload_presets()
{
list_l1->Clear();
list_l1->append(_(L("(All)")), &EMPTY);
for (const std::string &type : materials->types) {
list_l1->append(type, &type);
}
if (list_l1->GetCount() > 0) {
list_l1->SetSelection(0);
sel1_prev = wxNOT_FOUND;
sel2_prev = wxNOT_FOUND;
update_lists(0, 0);
}
presets_loaded = true;
}
void PageMaterials::update_lists(int sel1, int sel2)
@ -592,14 +604,14 @@ void PageMaterials::update_lists(int sel1, int sel2)
// Refresh the second list
// XXX: The vendor list is created with quadratic complexity here,
// but the number of vendors is realistically so small this shouldn't be a problem.
// but the number of vendors is going to be very small this shouldn't be a problem.
list_l2->Clear();
list_l2->append(_(L("(All)")), &EMPTY);
if (sel1 != wxNOT_FOUND) {
const std::string &type = list_l1->get_data(sel1);
materials->filter_presets(type, EMPTY, [this](Preset &p) {
materials->filter_presets(type, EMPTY, [this](const Preset *p) {
const std::string &vendor = this->materials->get_vendor(p);
if (list_l2->find(vendor) == wxNOT_FOUND) {
@ -623,9 +635,9 @@ void PageMaterials::update_lists(int sel1, int sel2)
const std::string &type = list_l1->get_data(sel1);
const std::string &vendor = list_l2->get_data(sel2);
materials->filter_presets(type, vendor, [this](Preset &p) {
const int i = list_l3->append(p.name, &p);
const bool checked = wizard_p()->appconfig_new.has(materials->appconfig_section(), p.name);
materials->filter_presets(type, vendor, [this](const Preset *p) {
const int i = list_l3->append(p->name, p);
const bool checked = wizard_p()->appconfig_new.has(materials->appconfig_section(), p->name);
list_l3->Check(i, checked);
});
}
@ -660,6 +672,24 @@ void PageMaterials::select_all(bool select)
}
}
void PageMaterials::clear()
{
list_l1->Clear();
list_l2->Clear();
list_l3->Clear();
sel1_prev = wxNOT_FOUND;
sel2_prev = wxNOT_FOUND;
presets_loaded = false;
}
void PageMaterials::on_activate()
{
if (! presets_loaded) {
wizard_p()->update_materials();
reload_presets();
}
}
const char *PageCustom::default_profile_name = "My Settings";
@ -952,8 +982,8 @@ ConfigWizardIndex::ConfigWizardIndex(wxWindow *parent)
, bullet_black(ScalableBitmap(parent, "bullet_black.png"))
, bullet_blue(ScalableBitmap(parent, "bullet_blue.png"))
, bullet_white(ScalableBitmap(parent, "bullet_white.png"))
, item_active(0)
, item_hover(-1)
, item_active(NO_ITEM)
, item_hover(NO_ITEM)
, last_page((size_t)-1)
{
SetMinSize(bg.bmp().GetSize());
@ -1015,6 +1045,8 @@ 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);
@ -1027,6 +1059,8 @@ 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);
@ -1035,19 +1069,27 @@ void ConfigWizardIndex::go_next()
}
}
// This one actually performs the go-to op
void ConfigWizardIndex::go_to(size_t i)
{
if (i < items.size() && items[i].page != nullptr) {
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(); }
if (former_active != nullptr) {
former_active->Hide();
}
item_active = i;
items[i].page->Show();
new_active->Show();
wxCommandEvent evt(EVT_INDEX_PAGE, GetId());
AddPendingEvent(evt);
Refresh();
new_active->on_activate();
}
}
@ -1069,7 +1111,7 @@ void ConfigWizardIndex::clear()
if (former_active != nullptr) { former_active->Hide(); }
items.clear();
item_active = 0;
item_active = NO_ITEM;
}
void ConfigWizardIndex::on_paint(wxPaintEvent & evt)
@ -1150,24 +1192,38 @@ void ConfigWizardIndex::msw_rescale()
const std::string Materials::UNKNOWN = "(Unknown)";
void Materials::push(const Preset *preset)
{
presets.insert(preset);
types.insert(technology & T_FFF
? Materials::get_filament_type(preset)
: Materials::get_material_type(preset));
}
void Materials::clear()
{
presets.clear();
types.clear();
}
const std::string& Materials::appconfig_section() const
{
return (technology & T_FFF) ? AppConfig::SECTION_FILAMENTS : AppConfig::SECTION_MATERIALS;
}
const std::string& Materials::get_type(Preset &preset) const
const std::string& Materials::get_type(const Preset *preset) const
{
return (technology & T_FFF) ? get_filament_type(preset) : get_material_type(preset);
}
const std::string& Materials::get_vendor(Preset &preset) const
const std::string& Materials::get_vendor(const Preset *preset) const
{
return (technology & T_FFF) ? get_filament_vendor(preset) : get_material_vendor(preset);
}
const std::string& Materials::get_filament_type(const Preset &preset)
const std::string& Materials::get_filament_type(const Preset *preset)
{
const auto *opt = preset.config.opt<ConfigOptionStrings>("filament_type");
const auto *opt = preset->config.opt<ConfigOptionStrings>("filament_type");
if (opt != nullptr && opt->values.size() > 0) {
return opt->values[0];
} else {
@ -1175,15 +1231,15 @@ const std::string& Materials::get_filament_type(const Preset &preset)
}
}
const std::string& Materials::get_filament_vendor(const Preset &preset)
const std::string& Materials::get_filament_vendor(const Preset *preset)
{
const auto *opt = preset.config.opt<ConfigOptionString>("filament_vendor");
const auto *opt = preset->config.opt<ConfigOptionString>("filament_vendor");
return opt != nullptr ? opt->value : UNKNOWN;
}
const std::string& Materials::get_material_type(Preset &preset)
const std::string& Materials::get_material_type(const Preset *preset)
{
const auto *opt = preset.config.opt<ConfigOptionString>("material_type");
const auto *opt = preset->config.opt<ConfigOptionString>("material_type");
if (opt != nullptr) {
return opt->value;
} else {
@ -1191,9 +1247,9 @@ const std::string& Materials::get_material_type(Preset &preset)
}
}
const std::string& Materials::get_material_vendor(const Preset &preset)
const std::string& Materials::get_material_vendor(const Preset *preset)
{
const auto *opt = preset.config.opt<ConfigOptionString>("material_vendor");
const auto *opt = preset->config.opt<ConfigOptionString>("material_vendor");
return opt != nullptr ? opt->value : UNKNOWN;
}
@ -1275,73 +1331,8 @@ void ConfigWizard::priv::init_dialog_size()
void ConfigWizard::priv::load_vendors()
{
// const auto vendor_dir = fs::path(Slic3r::data_dir()) / "vendor";
// const auto rsrc_vendor_dir = fs::path(resources_dir()) / "profiles";
// PresetBundle bundle;
// bundle.load_available_system_presets();
bundles = BundleMap::load();
// // Load vendors from the "vendors" directory in datadir
// // XXX: The VendorProfile is loaded twice here, ditto below
// for (auto &dir_entry : boost::filesystem::directory_iterator(vendor_dir)) {
// if (Slic3r::is_ini_file(dir_entry)) {
// try {
// bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
// auto vp = VendorProfile::from_ini(dir_entry.path());
// vendors[vp.id] = std::move(vp);
// }
// catch (const std::exception& e) {
// BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
// }
// }
// }
// // Additionally load up vendors from the application resources directory, but only those not seen in the datadir
// for (auto &dir_entry : boost::filesystem::directory_iterator(rsrc_vendor_dir)) {
// if (Slic3r::is_ini_file(dir_entry)) {
// const auto id = dir_entry.path().stem().string();
// if (vendors.find(id) == vendors.end()) {
// try {
// bundle.load_configbundle(dir_entry.path().string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
// auto vp = VendorProfile::from_ini(dir_entry.path());
// vendors_rsrc[vp.id] = dir_entry.path().filename().string();
// vendors[vp.id] = std::move(vp);
// }
// catch (const std::exception& e) {
// BOOST_LOG_TRIVIAL(error) << boost::format("Error loading vendor bundle %1%: %2%") % dir_entry.path() % e.what();
// }
// }
// }
// }
// // Move materials to our Materials container:
// for (auto &&f : bundle.filaments) {
// f.vendor = nullptr;
// filaments.presets.push_back(std::move(f));
// filaments.types.insert(Materials::get_filament_type(f));
// }
// for (auto &&m : bundle.sla_materials) {
// m.vendor = nullptr;
// sla_materials.presets.push_back(std::move(m));
// sla_materials.types.insert(Materials::get_material_type(m));
// }
for (auto &pair : bundles) {
for (auto &&f : pair.second.preset_bundle->filaments) {
f.vendor = nullptr;
filaments.presets.push_back(std::move(f));
filaments.types.insert(Materials::get_filament_type(f));
}
for (auto &&m : pair.second.preset_bundle->sla_materials) {
m.vendor = nullptr;
sla_materials.presets.push_back(std::move(m));
sla_materials.types.insert(Materials::get_material_type(m));
}
}
// Load up the set of vendors / models / variants the user has had enabled up till now
AppConfig *app_config = wxGetApp().app_config;
if (! app_config->legacy_datadir()) {
@ -1360,15 +1351,13 @@ void ConfigWizard::priv::load_vendors()
}
}
// TODO: This'll be done differently, cf. the design document
// Load up the materials enabled till now,
// apply defaults from vendor profiles if there are no selections yet.
// bundle.init_materials_selection(*app_config);
// Initialize the is_visible flag in printer Presets
for (auto &pair : bundles) {
pair.second.preset_bundle->load_installed_printers(appconfig_new);
}
update_materials();
// TODO: load up sane defaults if no previous data in AppConfig
// as per the design doc:
// - all f/m for installed printers if prev Slicer version
// - default f/m set from bundle + default for each printer from bundle if fresh install
if (app_config->has_section(AppConfig::SECTION_FILAMENTS)) {
appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, app_config->get_section(AppConfig::SECTION_FILAMENTS));
}
@ -1420,12 +1409,66 @@ void ConfigWizard::priv::set_run_reason(RunReason run_reason)
}
}
void ConfigWizard::priv::update_materials()
{
filaments.clear();
sla_materials.clear();
if (any_fff_selected) {
// Iterate filaments in all bundles
for (const auto &pair : bundles) {
for (const auto &filament : pair.second.preset_bundle->filaments) {
// Check if filament is already added
if (filaments.containts(&filament)) { continue; }
// Iterate printers in all bundles
for (const auto &pair : bundles) {
for (const auto &printer : pair.second.preset_bundle->printers) {
// Filter out inapplicable printers
if (!printer.is_visible || printer.printer_technology() != ptFFF) {
continue;
}
if (filament.is_compatible_with_printer(printer)) {
filaments.push(&filament);
}
}
}
}
}
}
if (any_sla_selected) {
// Iterate SLA materials in all bundles
for (const auto &pair : bundles) {
for (const auto &material : pair.second.preset_bundle->sla_materials) {
// Check if material is already added
if (sla_materials.containts(&material)) { continue; }
// Iterate printers in all bundles
for (const auto &pair : bundles) {
for (const auto &printer : pair.second.preset_bundle->printers) {
// Filter out inapplicable printers
if (!printer.is_visible || printer.printer_technology() != ptSLA) {
continue;
}
if (material.is_compatible_with_printer(printer)) {
sla_materials.push(&material);
}
}
}
}
}
}
}
void ConfigWizard::priv::on_custom_setup()
{
load_pages();
}
void ConfigWizard::priv::on_printer_pick(PagePrinters *page)
void ConfigWizard::priv::on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt)
{
if (page_msla->any_selected() != any_sla_selected ||
page_fff->any_selected() != any_fff_selected) {
@ -1434,6 +1477,24 @@ void ConfigWizard::priv::on_printer_pick(PagePrinters *page)
load_pages();
}
// Update the is_visible flag on relevant printer profiles
for (auto &pair : bundles) {
if (pair.first != evt.vendor_id) { continue; }
for (auto &preset : pair.second.preset_bundle->printers) {
if (preset.config.opt_string("printer_model") == evt.model_id
&& preset.config.opt_string("printer_variant") == evt.variant_name) {
preset.is_visible = evt.enable;
}
}
}
if (page == page_fff) {
page_filaments->clear();
} else if (page == page_msla) {
page_sla_materials->clear();
}
}
void ConfigWizard::priv::on_3rdparty_install(const VendorProfile *vendor, bool install)
@ -1636,7 +1697,9 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
p->any_sla_selected = p->page_msla->any_selected();
p->any_fff_selected = p->page_fff->any_selected();
p->load_pages();
p->index->go_to(size_t{0});
vsizer->Add(topsizer, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
vsizer->Add(hline, 0, wxEXPAND);

View file

@ -21,7 +21,6 @@
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/Utils/PresetUpdater.hpp"
#include "AppConfig.hpp"
// #include "Preset.hpp"
#include "PresetBundle.hpp"
#include "BedShapeDialog.hpp"
@ -58,17 +57,23 @@ enum Technology {
struct Materials
{
Technology technology;
std::vector<Preset> presets;
std::set<const Preset*> presets;
std::set<std::string> types;
Materials(Technology technology) : technology(technology) {}
void push(const Preset *preset);
void clear();
bool containts(const Preset *preset) {
return presets.find(preset) != presets.end();
}
const std::string& appconfig_section() const;
const std::string& get_type(Preset &preset) const;
const std::string& get_vendor(Preset &preset) const;
const std::string& get_type(const Preset *preset) const;
const std::string& get_vendor(const Preset *preset) const;
template<class F> void filter_presets(const std::string &type, const std::string &vendor, F cb) {
for (Preset &preset : presets) {
for (const Preset *preset : presets) {
if ((type.empty() || get_type(preset) == type) && (vendor.empty() || get_vendor(preset) == vendor)) {
cb(preset);
}
@ -76,10 +81,10 @@ struct Materials
}
static const std::string UNKNOWN;
static const std::string& get_filament_type(const Preset &preset);
static const std::string& get_filament_vendor(const Preset &preset);
static const std::string& get_material_type(Preset &preset);
static const std::string& get_material_vendor(const Preset &preset);
static const std::string& get_filament_type(const Preset *preset);
static const std::string& get_filament_vendor(const Preset *preset);
static const std::string& get_material_type(const Preset *preset);
static const std::string& get_material_vendor(const Preset *preset);
};
struct Bundle
@ -104,6 +109,7 @@ struct BundleMap: std::unordered_map<std::string /* = vendor ID */, Bundle>
const Bundle& prusa_bundle() const;
};
struct PrinterPickerEvent;
// GUI elements
@ -170,6 +176,7 @@ struct ConfigWizardPage: wxPanel
virtual void apply_custom_config(DynamicPrintConfig &config) {}
virtual void set_run_reason(ConfigWizard::RunReason run_reason) {}
virtual void on_activate() {}
};
struct PageWelcome: ConfigWizardPage
@ -209,6 +216,9 @@ template<class T, class D> struct DataList : public T
{
DataList(wxWindow *parent) : T(parent, wxID_ANY) {}
// Note: We're _not_ using wxLB_SORT here because it doesn't do the right thing,
// eg. "ABS" is sorted before "(All)"
int append(const std::string &label, const D *data) {
void *ptr = reinterpret_cast<void*>(const_cast<D*>(data));
return this->Append(from_u8(label), ptr);
@ -241,14 +251,19 @@ struct PageMaterials: ConfigWizardPage
StringList *list_l1, *list_l2;
PresetList *list_l3;
int sel1_prev, sel2_prev;
bool presets_loaded;
static const std::string EMPTY;
PageMaterials(ConfigWizard *parent, Materials *materials, wxString title, wxString shortname, wxString list1name);
void reload_presets();
void update_lists(int sel1, int sel2);
void select_material(int i);
void select_all(bool select);
void clear();
static const std::string EMPTY;
virtual void on_activate() override;
};
struct PageCustom: ConfigWizardPage
@ -339,6 +354,8 @@ public:
void msw_rescale();
int em() const { return em_w; }
static const size_t NO_ITEM = size_t(-1);
private:
struct Item
{
@ -379,14 +396,12 @@ struct ConfigWizard::priv
ConfigWizard *q;
ConfigWizard::RunReason run_reason = RR_USER;
AppConfig appconfig_new; // Backing for vendor/model/variant and material selections in the GUI
// std::unordered_map<std::string, VendorProfile> vendors;
// PresetBundle bundle; // XXX: comment
BundleMap bundles; // XXX: comment
BundleMap bundles; // Holds all loaded config bundles, the key is the vendor names.
// Materials refers to Presets in those bundles by pointers.
// Also we update the is_visible flag in printer Presets according to the
// PrinterPickers state.
Materials filaments; // Holds available filament presets and their types & vendors
Materials sla_materials; // Ditto for SLA materials
// std::set<const VendorProfile*> install_3rdparty;
// XXX: rm: (?)
// std::unordered_map<std::string, std::string> vendors_rsrc; // List of bundles to install from resources
std::unique_ptr<DynamicPrintConfig> custom_config; // Backing for custom printer definition
bool any_fff_selected; // Used to decide whether to display Filaments page
bool any_sla_selected; // Used to decide whether to display SLA Materials page
@ -437,10 +452,11 @@ struct ConfigWizard::priv
void set_start_page(ConfigWizard::StartPage start_page);
void create_3rdparty_pages();
void set_run_reason(RunReason run_reason);
void update_materials();
void on_custom_setup();
void on_printer_pick(PagePrinters *page);
void on_3rdparty_install(const VendorProfile *vendor, bool install); // XXX: ?
void on_printer_pick(PagePrinters *page, const PrinterPickerEvent &evt);
void on_3rdparty_install(const VendorProfile *vendor, bool install);
void apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater);

View file

@ -134,20 +134,21 @@ public:
void load_default_preset_bitmaps(wxWindow *window);
// FIXME: rm
void load_available_system_presets(); // XXX: name XXX: retval (VendorMap stored internally)
// Set the is_visible flag for printer vendors, printer models and printer variants
// based on the user configuration.
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
void load_installed_printers(const AppConfig &config);
static const char *PRUSA_BUNDLE;
private:
std::string load_system_presets();
// Merge one vendor's presets with the other vendor's presets, report duplicates.
std::vector<std::string> merge_presets(PresetBundle &&other);
// Set the "enabled" flag for printer vendors, printer models and printer variants
// based on the user configuration.
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
void load_installed_printers(const AppConfig &config);
// Set the enabled flag for filaments and sla materials,
// Set the is_visible flag for filaments and sla materials,
// apply defaults based on enabled printers when no filaments/materials are installed.
void load_installed_filaments(AppConfig &config);
void load_installed_sla_materials(AppConfig &config);