mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-25 11:52:05 +00:00
feat(gui): per-filament nozzle volume selection and persistence
- FilamentMapDialog's manual page understands volume types: a mixed (Hybrid) extruder shows separate Standard / High Flow drop zones with live sub-nozzle counts, a validation timer with an inline error + "set nozzle count" suggestion, and composes a per-filament volume map on OK (persisted to the plate or globally) - switching an extruder's Flow type rewrites the affected plate map entries; plate maps stay sized across filament add/delete/count changes (values keep their filament, no index shift) - CLI: manual mapping on multi-nozzle printers synthesizes the volume map from extruder flow types when absent; nozzle-manual mode requires explicit maps; computed maps land on the plate so exported projects carry filament_volume_maps - filament_nozzle_map joins the project options (selection seeding + filament-count resizing) - pot entries for the new dialog strings All 19 reference fixtures byte-identical; slicing an exported Hybrid project reproduces its g-code byte-for-byte with the volume map round-tripped through model_settings.config.
This commit is contained in:
@@ -1213,9 +1213,16 @@ ExtruderGroup::ExtruderGroup(wxWindow * parent, int index, wxString const &title
|
||||
combo_flow->GetDropDown().SetUseContentWidth(true);
|
||||
combo_flow->Bind(wxEVT_COMBOBOX, [this, index, combo_flow](wxCommandEvent &evt) {
|
||||
auto printer_tab = dynamic_cast<TabPrinter *>(wxGetApp().get_tab(Preset::TYPE_PRINTER));
|
||||
printer_tab->set_extruder_volume_type(index, NozzleVolumeType(intptr_t(combo_flow->GetClientData(evt.GetInt()))));
|
||||
if (GUI::wxGetApp().plater())
|
||||
GUI::wxGetApp().plater()->update_machine_sync_status();
|
||||
NozzleVolumeType volume_type = NozzleVolumeType(intptr_t(combo_flow->GetClientData(evt.GetInt())));
|
||||
printer_tab->set_extruder_volume_type(index, volume_type);
|
||||
auto plater = GUI::wxGetApp().plater();
|
||||
if (plater) {
|
||||
// A new Flow type invalidates the per-filament volume choices stored on the
|
||||
// plates for this extruder; rewrite them so the next apply/grouping sees the
|
||||
// selected volume instead of a stale one.
|
||||
plater->update_filament_volume_map(index, static_cast<int>(volume_type));
|
||||
plater->update_machine_sync_status();
|
||||
}
|
||||
});
|
||||
this->combo_flow = combo_flow;
|
||||
|
||||
@@ -7328,6 +7335,16 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
filament_map->values.resize(filament_count, 1);
|
||||
}
|
||||
|
||||
ConfigOptionInts* filament_nozzle_map = proj_cfg.opt<ConfigOptionInts>("filament_nozzle_map", true);
|
||||
if (filament_nozzle_map->size() != filament_count) {
|
||||
filament_nozzle_map->values.resize(filament_count, 0);
|
||||
}
|
||||
|
||||
ConfigOptionInts* filament_volume_map = proj_cfg.opt<ConfigOptionInts>("filament_volume_map", true);
|
||||
if (filament_volume_map->size() != filament_count) {
|
||||
filament_volume_map->values.resize(filament_count, static_cast<int>(NozzleVolumeType::nvtStandard));
|
||||
}
|
||||
|
||||
// Sync filament multi colour
|
||||
ConfigOptionStrings* filament_multi_color = proj_cfg.opt<ConfigOptionStrings>("filament_multi_colour", true);
|
||||
if (filament_multi_color->size() != filament_count) {
|
||||
@@ -17799,12 +17816,24 @@ void Plater::set_global_filament_map(const std::vector<int>& filament_map)
|
||||
project_config.option<ConfigOptionInts>("filament_map")->values = filament_map;
|
||||
}
|
||||
|
||||
void Plater::set_global_filament_volume_map(const std::vector<int>& filament_volume_map)
|
||||
{
|
||||
auto& project_config = wxGetApp().preset_bundle->project_config;
|
||||
project_config.option<ConfigOptionInts>("filament_volume_map")->values = filament_volume_map;
|
||||
}
|
||||
|
||||
std::vector<int> Plater::get_global_filament_map() const
|
||||
{
|
||||
auto& project_config = wxGetApp().preset_bundle->project_config;
|
||||
return project_config.option<ConfigOptionInts>("filament_map")->values;
|
||||
}
|
||||
|
||||
std::vector<int> Plater::get_global_filament_volume_map() const
|
||||
{
|
||||
auto& project_config = wxGetApp().preset_bundle->project_config;
|
||||
return project_config.option<ConfigOptionInts>("filament_volume_map")->values;
|
||||
}
|
||||
|
||||
|
||||
FilamentMapMode Plater::get_global_filament_map_mode() const
|
||||
{
|
||||
@@ -18721,13 +18750,17 @@ void Plater::open_filament_map_setting_dialog(wxCommandEvent &evt)
|
||||
|
||||
auto plate_filament_maps = curr_plate->get_real_filament_maps(project_config);
|
||||
auto plate_filament_map_mode = curr_plate->get_filament_map_mode();
|
||||
auto plate_filament_volume_maps = curr_plate->get_real_filament_volume_maps(project_config);
|
||||
if (plate_filament_maps.size() != filament_colors.size()) // refine it later, save filament map to app config
|
||||
plate_filament_maps.resize(filament_colors.size(), 1);
|
||||
if (plate_filament_volume_maps.size() != filament_colors.size())
|
||||
plate_filament_volume_maps.resize(filament_colors.size(), 0);
|
||||
|
||||
FilamentMapDialog filament_dlg(this,
|
||||
filament_colors,
|
||||
filament_types,
|
||||
plate_filament_maps,
|
||||
plate_filament_volume_maps,
|
||||
curr_plate->get_extruders(true),
|
||||
plate_filament_map_mode,
|
||||
this->get_machine_sync_status(),
|
||||
@@ -18741,16 +18774,21 @@ void Plater::open_filament_map_setting_dialog(wxCommandEvent &evt)
|
||||
FilamentMapMode old_map_mode = curr_plate->get_filament_map_mode();
|
||||
FilamentMapMode new_map_mode = filament_dlg.get_mode();
|
||||
|
||||
std::vector<int> new_filament_volume_maps = filament_dlg.get_filament_volume_maps();
|
||||
std::vector<int> old_filament_volume_maps = curr_plate->get_real_filament_volume_maps(project_config);
|
||||
|
||||
if (new_map_mode != old_map_mode) {
|
||||
curr_plate->set_filament_map_mode(new_map_mode);
|
||||
}
|
||||
|
||||
if (new_map_mode == fmmManual){
|
||||
curr_plate->set_filament_maps(new_filament_maps);
|
||||
curr_plate->set_filament_volume_maps(new_filament_volume_maps);
|
||||
}
|
||||
|
||||
bool need_invalidate = (old_map_mode != new_map_mode ||
|
||||
old_filament_maps != new_filament_maps);
|
||||
old_filament_maps != new_filament_maps ||
|
||||
old_filament_volume_maps != new_filament_volume_maps);
|
||||
|
||||
if (need_invalidate) {
|
||||
if (need_slice) {
|
||||
@@ -19216,6 +19254,30 @@ bool Plater::get_machine_sync_status()
|
||||
return p->get_machine_sync_status();
|
||||
}
|
||||
|
||||
void Plater::update_filament_volume_map(int extruder_id, int volume_type)
|
||||
{
|
||||
// Hybrid is a per-extruder mix, not a per-filament volume; reset the affected filaments
|
||||
// to Standard so the manual grouping dialog starts from a concrete assignment.
|
||||
int selected_volume_type = volume_type == static_cast<int>(NozzleVolumeType::nvtHybrid) ? static_cast<int>(NozzleVolumeType::nvtStandard) : volume_type;
|
||||
auto& partplate_list = get_partplate_list();
|
||||
for (int idx = 0; idx < partplate_list.get_plate_count(); ++idx) {
|
||||
auto plate = partplate_list.get_plate(idx);
|
||||
if (!plate) continue;
|
||||
auto filament_map = plate->get_filament_maps();
|
||||
auto filament_volume_map = plate->get_filament_volume_maps();
|
||||
if (filament_map.empty() || filament_volume_map.empty()) continue;
|
||||
if (filament_volume_map.size() < filament_map.size()) {
|
||||
filament_volume_map.resize(filament_map.size(), static_cast<int>(NozzleVolumeType::nvtStandard));
|
||||
}
|
||||
for (size_t i = 0; i < filament_map.size(); ++i) {
|
||||
if (filament_map[i] == extruder_id + 1) {
|
||||
filament_volume_map[i] = selected_volume_type;
|
||||
}
|
||||
}
|
||||
plate->set_filament_volume_maps(filament_volume_map);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_ENVIRONMENT_MAP
|
||||
void Plater::init_environment_texture()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user