Add options to texture mapping zone menu: "Assign to selected objects" and "Delete all texture mapping zones"

- Use perimeter path modulation by default for gradient zones
This commit is contained in:
sentientstardust
2026-05-23 21:17:18 +01:00
parent a32bcfda35
commit 24ab0b81a2
6 changed files with 235 additions and 17 deletions

View File

@@ -1008,6 +1008,7 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const
seam_hiding == rhs.seam_hiding &&
nonlinear_offset_adjustment == rhs.nonlinear_offset_adjustment &&
modulation_mode == rhs.modulation_mode &&
modulation_mode_manually_changed == rhs.modulation_mode_manually_changed &&
recolor_small_perimeter_loops == rhs.recolor_small_perimeter_loops &&
recolor_top_visible_perimeter_sections == rhs.recolor_top_visible_perimeter_sections &&
top_visible_perimeter_recolor_aggressiveness == rhs.top_visible_perimeter_recolor_aggressiveness &&
@@ -1081,6 +1082,7 @@ void TextureMappingManager::refresh(const std::vector<std::string> &filament_col
zone.component_b = zone.linear_gradient_stops.back().filament_id;
}
}
zone.apply_default_modulation_mode();
}
}
@@ -1168,6 +1170,7 @@ TextureMappingZone *TextureMappingManager::add_zone(size_t num_physical,
surface_pattern == int(TextureMappingZone::Gradient2D) || surface_pattern == int(TextureMappingZone::LinearGradient) ?
surface_pattern :
int(TextureMappingZone::ImageTexture);
zone.apply_default_modulation_mode();
std::vector<unsigned int> ids;
for (size_t i = 1; i <= std::min<size_t>(num_physical, 9); ++i)
@@ -1267,6 +1270,7 @@ std::string TextureMappingManager::serialize_entries()
zone.stable_id = normalize_stable_id(zone.stable_id);
if (zone.display_color.empty() || zone.display_color[0] != '#')
zone.display_color = random_display_color(zone.stable_id);
zone.apply_default_modulation_mode();
std::vector<unsigned int> component_ids = decode_component_ids(zone.component_ids, 9);
if (zone.is_linear_gradient()) {
@@ -1335,6 +1339,7 @@ std::string TextureMappingManager::serialize_entries()
texture["hide_seams"] = zone.seam_hiding;
texture["nonlinear_offset_adjustment"] = zone.nonlinear_offset_adjustment;
texture["modulation_mode"] = modulation_mode_name(zone.modulation_mode);
texture["modulation_mode_manually_changed"] = zone.modulation_mode_manually_changed;
texture["recolor_small_perimeter_loops"] = zone.recolor_small_perimeter_loops || zone.recolor_top_visible_perimeter_sections;
texture["recolor_top_visible_perimeter_sections"] = zone.recolor_top_visible_perimeter_sections;
texture["top_visible_perimeter_recolor_aggressiveness"] =
@@ -1506,9 +1511,16 @@ void TextureMappingManager::load_entries(const std::string &serialized,
zone.reduce_outer_surface_texture = false;
zone.seam_hiding = texture.value("hide_seams", false);
zone.nonlinear_offset_adjustment = texture.value("nonlinear_offset_adjustment", false);
zone.modulation_mode =
modulation_mode_from_name(texture.value("modulation_mode",
modulation_mode_name(TextureMappingZone::DefaultModulationMode)));
const auto modulation_mode_it = texture.find("modulation_mode");
const bool has_modulation_mode =
modulation_mode_it != texture.end() && modulation_mode_it->is_string();
zone.modulation_mode = has_modulation_mode ?
modulation_mode_from_name(modulation_mode_it->get<std::string>()) :
TextureMappingZone::default_modulation_mode_for_surface_pattern(zone.surface_pattern);
zone.modulation_mode_manually_changed =
texture.value("modulation_mode_manually_changed",
has_modulation_mode && zone.modulation_mode != TextureMappingZone::ModulationLineWidth);
zone.apply_default_modulation_mode();
zone.recolor_small_perimeter_loops =
texture.value("recolor_small_perimeter_loops", TextureMappingZone::DefaultRecolorSmallPerimeterLoops);
zone.recolor_top_visible_perimeter_sections =

View File

@@ -125,7 +125,11 @@ struct TextureMappingZone
static constexpr bool DefaultReduceOuterSurfaceTexture = false;
static constexpr bool DefaultSeamHiding = false;
static constexpr bool DefaultNonlinearOffsetAdjustment = false;
static constexpr int DefaultModulationMode = int(ModulationLineWidth);
static constexpr int DefaultImageTextureModulationMode = int(ModulationLineWidth);
static constexpr int Default2DGradientModulationMode = int(ModulationPerimeterPath);
static constexpr int DefaultLinearGradientModulationMode = int(ModulationPerimeterPath);
static constexpr int DefaultModulationMode = DefaultImageTextureModulationMode;
static constexpr bool DefaultModulationModeManuallyChanged = false;
static constexpr bool DefaultRecolorSmallPerimeterLoops = false;
static constexpr bool DefaultRecolorTopVisiblePerimeterSections = false;
static constexpr int DefaultTopVisiblePerimeterRecolorAggressiveness = int(TopVisibleRecolorAggressive);
@@ -153,6 +157,15 @@ struct TextureMappingZone
static constexpr bool DefaultPreviewLimitResolution = true;
static constexpr bool DefaultAutoAdjustFilamentSelection = true;
static constexpr int default_modulation_mode_for_surface_pattern(int surface_pattern)
{
switch (surface_pattern) {
case int(Gradient2D): return Default2DGradientModulationMode;
case int(LinearGradient): return DefaultLinearGradientModulationMode;
default: return DefaultImageTextureModulationMode;
}
}
struct LinearGradientAnchor {
bool valid = false;
size_t object_id = 0;
@@ -201,6 +214,7 @@ struct TextureMappingZone
bool seam_hiding = DefaultSeamHiding;
bool nonlinear_offset_adjustment = DefaultNonlinearOffsetAdjustment;
int modulation_mode = DefaultModulationMode;
bool modulation_mode_manually_changed = DefaultModulationModeManuallyChanged;
bool recolor_small_perimeter_loops = DefaultRecolorSmallPerimeterLoops;
bool recolor_top_visible_perimeter_sections = DefaultRecolorTopVisiblePerimeterSections;
int top_visible_perimeter_recolor_aggressiveness = DefaultTopVisiblePerimeterRecolorAggressiveness;
@@ -243,6 +257,12 @@ struct TextureMappingZone
bool is_surface_gradient() const { return is_2d_gradient() || is_linear_gradient(); }
bool uses_perimeter_path_modulation() const { return modulation_mode == int(ModulationPerimeterPath); }
void apply_default_modulation_mode()
{
if (!modulation_mode_manually_changed)
modulation_mode = default_modulation_mode_for_surface_pattern(surface_pattern);
}
void reset_offset_settings()
{
offset_distances.clear();
@@ -265,7 +285,8 @@ struct TextureMappingZone
reduce_outer_surface_texture = DefaultReduceOuterSurfaceTexture;
seam_hiding = DefaultSeamHiding;
nonlinear_offset_adjustment = DefaultNonlinearOffsetAdjustment;
modulation_mode = DefaultModulationMode;
modulation_mode = default_modulation_mode_for_surface_pattern(surface_pattern);
modulation_mode_manually_changed = DefaultModulationModeManuallyChanged;
recolor_small_perimeter_loops = DefaultRecolorSmallPerimeterLoops;
recolor_top_visible_perimeter_sections = DefaultRecolorTopVisiblePerimeterSections;
top_visible_perimeter_recolor_aggressiveness = DefaultTopVisiblePerimeterRecolorAggressiveness;

View File

@@ -194,6 +194,18 @@ const ModelObject *linear_gradient_anchor_model_object(const Model &model,
return nullptr;
}
bool linear_gradient_anchor_has_object_reference(const TextureMappingZone::LinearGradientAnchor &anchor)
{
return anchor.object_backup_id >= 0 || anchor.object_id != 0 || anchor.object_index_valid;
}
bool linear_gradient_anchor_object_resolves(const TextureMappingZone::LinearGradientAnchor &anchor)
{
if (!anchor.valid || !linear_gradient_anchor_has_object_reference(anchor))
return true;
return linear_gradient_anchor_model_object(GUI::wxGetApp().model(), anchor) != nullptr;
}
bool linear_gradient_anchor_matches_model_object(const Model &model,
const ModelObject *object,
const TextureMappingZone::LinearGradientAnchor &anchor)
@@ -3208,11 +3220,17 @@ void GLVolumeCollection::render_linear_gradient_direction_arrows(const Transform
component_colors.emplace_back(linear_gradient_filament_color(component_id, filament_colors));
const LinearGradientArrowUsage usage = linear_gradient_arrow_usage(volumes, zone.zone_id);
const std::optional<Vec3f> start_anchor = linear_gradient_anchor_global_point(volumes, zone.linear_gradient_start);
const bool stale_unused_start_anchor =
!usage.any && zone.linear_gradient_start.valid && !linear_gradient_anchor_object_resolves(zone.linear_gradient_start);
const bool stale_unused_end_anchor =
!usage.any && zone.linear_gradient_end.valid && !linear_gradient_anchor_object_resolves(zone.linear_gradient_end);
const std::optional<Vec3f> start_anchor = stale_unused_start_anchor ?
std::nullopt :
linear_gradient_anchor_global_point(volumes, zone.linear_gradient_start);
const bool radial_mode = zone.linear_gradient_mode == int(TextureMappingZone::LinearGradientRadial);
const std::optional<Vec3f> end_anchor = radial_mode ?
std::nullopt :
linear_gradient_anchor_global_point(volumes, zone.linear_gradient_end);
(stale_unused_end_anchor ? std::nullopt : linear_gradient_anchor_global_point(volumes, zone.linear_gradient_end));
if (!usage.any && !start_anchor && !end_anchor)
continue;

View File

@@ -6880,6 +6880,72 @@ void ObjectList::set_extruder_for_selected_items(const int extruder)
Refresh();
}
bool ObjectList::assign_extruder_to_objects_and_clear_filament_region_painting(const std::vector<size_t>& object_idxs, const int extruder)
{
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
if (extruder <= 0 || extruder > int(colors.size()))
return false;
std::vector<size_t> valid_object_idxs;
for (size_t obj_idx : object_idxs) {
if (m_objects == nullptr || obj_idx >= m_objects->size() || (*m_objects)[obj_idx] == nullptr)
continue;
if (std::find(valid_object_idxs.begin(), valid_object_idxs.end(), obj_idx) == valid_object_idxs.end())
valid_object_idxs.emplace_back(obj_idx);
}
if (valid_object_idxs.empty())
return false;
bool changed = false;
for (size_t obj_idx : valid_object_idxs) {
ModelObject *model_object = (*m_objects)[obj_idx];
const int current_extruder = model_object->config.has("extruder") ? model_object->config.opt_int("extruder") : 1;
changed |= current_extruder != extruder;
for (ModelVolume *mv : model_object->volumes) {
if (mv->type() == ModelVolumeType::MODEL_PART && mv->config.has("extruder"))
changed = true;
if (!mv->mmu_segmentation_facets.empty())
changed = true;
}
}
if (!changed)
return false;
take_snapshot("Assign Texture Mapping Zone");
if (Plater *plater = wxGetApp().plater(); plater != nullptr)
if (GLCanvas3D *canvas = plater->canvas3D(); canvas != nullptr)
canvas->get_gizmos_manager().reset_all_states();
for (size_t obj_idx : valid_object_idxs) {
ModelObject *model_object = (*m_objects)[obj_idx];
if (model_object->config.has("extruder"))
model_object->config.set("extruder", extruder);
else
model_object->config.set_key_value("extruder", new ConfigOptionInt(extruder));
for (ModelVolume *mv : model_object->volumes) {
if (mv->type() == ModelVolumeType::MODEL_PART && mv->config.has("extruder"))
mv->config.erase("extruder");
if (!mv->mmu_segmentation_facets.empty())
mv->mmu_segmentation_facets.reset();
}
wxDataViewItem item = m_objects_model->GetItemById(int(obj_idx));
if (item.IsOk()) {
m_objects_model->SetExtruder(wxString::Format("%d", extruder), item);
update_info_items(obj_idx);
}
}
wxGetApp().plater()->update();
wxGetApp().plater()->object_list_changed();
Refresh();
return true;
}
void ObjectList::on_plate_added(PartPlate* part_plate)
{
wxDataViewItem plate_item = m_objects_model->AddPlate(part_plate);

View File

@@ -456,6 +456,7 @@ public:
//BBS: remove const qualifier
void set_extruder_for_selected_items(const int extruder);
bool assign_extruder_to_objects_and_clear_filament_region_painting(const std::vector<size_t>& object_idxs, const int extruder);
wxDataViewItemArray reorder_volumes_and_get_selection(int obj_idx, std::function<bool(const ModelVolume*)> add_to_selection = nullptr);
void apply_volumes_order();

View File

@@ -1793,6 +1793,7 @@ private:
if (!apply_to(preview))
return;
preview.surface_pattern = int(TextureMappingZone::Gradient2D);
preview.apply_default_modulation_mode();
m_live_preview(preview);
}
@@ -1848,6 +1849,7 @@ public:
bool seam_hiding,
bool nonlinear_offset_adjustment,
int modulation_mode,
bool modulation_mode_manually_changed,
bool recolor_small_perimeter_loops,
bool recolor_top_visible_perimeter_sections,
int top_visible_perimeter_recolor_aggressiveness,
@@ -1875,6 +1877,7 @@ public:
{
(void) generic_solver_mix_model;
(void) reduce_outer_surface_texture;
m_modulation_mode_manually_changed = modulation_mode_manually_changed;
m_strength_offsets_expanded = initial_strength_offsets_expanded;
const int gap = FromDIP(8);
auto *root = new wxBoxSizer(wxVERTICAL);
@@ -2128,7 +2131,10 @@ public:
int(TextureMappingZone::ModulationPerimeterPath)));
modulation_mode_row->Add(m_modulation_mode_choice, 1, wxALIGN_CENTER_VERTICAL);
print_settings_root->Add(modulation_mode_row, 0, wxEXPAND | wxALL, gap);
m_modulation_mode_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent &) { update_modulation_mode_options_visibility(false); });
m_modulation_mode_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent &) {
m_modulation_mode_manually_changed = true;
update_modulation_mode_options_visibility(false);
});
auto *print_settings_box = new wxStaticBoxSizer(wxVERTICAL,
print_settings_page,
@@ -2458,6 +2464,7 @@ public:
int(TextureMappingZone::ModulationPerimeterPath)) :
TextureMappingZone::DefaultModulationMode;
}
bool modulation_mode_manually_changed() const { return m_modulation_mode_manually_changed; }
bool compact_offset_mode() const { return dithering_enabled() || (m_compact_offset_mode_checkbox && m_compact_offset_mode_checkbox->GetValue()); }
bool recolor_small_perimeter_loops() const
{
@@ -2880,6 +2887,7 @@ private:
wxCheckBox *m_seam_hiding_checkbox {nullptr};
wxCheckBox *m_nonlinear_offset_adjustment_checkbox {nullptr};
wxChoice *m_modulation_mode_choice {nullptr};
bool m_modulation_mode_manually_changed {false};
wxCheckBox *m_recolor_small_perimeter_loops_checkbox {nullptr};
wxCheckBox *m_recolor_top_visible_perimeter_sections_checkbox {nullptr};
wxStaticText *m_top_visible_perimeter_recolor_aggressiveness_label {nullptr};
@@ -6806,6 +6814,27 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
canvas->reload_scene(true, true);
};
auto selected_texture_mapping_object_idxs = [this]() {
std::vector<size_t> object_idxs;
auto append_selection = [this, &object_idxs](const Selection &selection) {
if (selection.is_empty() || selection.is_wipe_tower())
return;
for (const auto &item : selection.get_content()) {
if (item.first < 0 || p->plater == nullptr || size_t(item.first) >= p->plater->model().objects.size())
continue;
const size_t obj_idx = size_t(item.first);
if (std::find(object_idxs.begin(), object_idxs.end(), obj_idx) == object_idxs.end())
object_idxs.emplace_back(obj_idx);
}
};
if (p->plater != nullptr) {
if (GLCanvas3D *canvas = p->plater->get_current_canvas3D())
append_selection(canvas->get_selection());
append_selection(p->plater->get_selection());
}
return object_idxs;
};
auto texture_mapping_zone_affects_scene = [print_cfg](unsigned int zone_id) {
const Plater *plater = wxGetApp().plater();
return plater != nullptr && model_uses_texture_mapping_zone_id(plater->model(), print_cfg, zone_id);
@@ -6907,17 +6936,21 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
rows[zone_index] = std::move(updated);
mgr_ptr->normalize_zone_ids(num_physical);
const unsigned int after_zone_id = rows[zone_index].zone_id;
const bool linear_gradient_preview_change = before.is_linear_gradient() || rows[zone_index].is_linear_gradient();
const bool affects_scene = texture_mapping_zone_affects_scene(before_zone_id) ||
texture_mapping_zone_affects_scene(after_zone_id);
refresh_summary_preview(rows[zone_index]);
set_config_string("texture_mapping_definitions", serialize_texture_mapping_manager(mgr_ptr));
if (preview_only_change) {
notify_change(false);
if (affects_scene)
if (affects_scene || linear_gradient_preview_change)
refresh_texture_mapping_preview();
}
else
else {
notify_change(affects_scene);
if (linear_gradient_preview_change)
refresh_texture_mapping_preview();
}
return affects_scene;
};
@@ -7055,12 +7088,14 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
set_start_btn_ref,
set_end_btn_ref,
clear_points_btn_ref,
surface_choice,
linear_gradient_mode_choice,
editor_ref,
row_ref,
update_texture_mapping_area_height](GLGizmoTextureGradientPointPicker::Target active_target) {
const TextureMappingZone *zone = mgr_ptr != nullptr && zone_index < mgr_ptr->zones().size() ? &mgr_ptr->zones()[zone_index] : nullptr;
const bool radial_gradient = linear_gradient_mode_choice != nullptr && linear_gradient_mode_choice->GetSelection() == 1;
const bool linear_gradient = surface_choice != nullptr && surface_choice->GetSelection() == 1;
const bool radial_gradient = linear_gradient && linear_gradient_mode_choice != nullptr && linear_gradient_mode_choice->GetSelection() == 1;
const bool has_start = zone != nullptr && zone->linear_gradient_start.valid;
const bool has_end = zone != nullptr && zone->linear_gradient_end.valid;
if (wxButton *button = set_start_btn_ref.get()) {
@@ -7068,18 +7103,22 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
(has_start ? _L("Set Center") : _L("Add Center")) :
(has_start ? _L("Set Start") : _L("Add Start"));
button->SetLabel(active_target == GLGizmoTextureGradientPointPicker::Target::Start ? _L("Cancel selection") : inactive_label);
button->Show(linear_gradient);
button->Enable(linear_gradient);
button->InvalidateBestSize();
button->Fit();
}
if (wxButton *button = set_end_btn_ref.get()) {
button->SetLabel(active_target == GLGizmoTextureGradientPointPicker::Target::End ? _L("Cancel selection") : (has_end ? _L("Set End") : _L("Add End")));
button->Show(!radial_gradient);
button->Enable(!radial_gradient);
button->Show(linear_gradient && !radial_gradient);
button->Enable(linear_gradient && !radial_gradient);
button->InvalidateBestSize();
button->Fit();
}
if (wxButton *button = clear_points_btn_ref.get())
button->Enable(has_start || has_end);
if (wxButton *button = clear_points_btn_ref.get()) {
button->Show(linear_gradient);
button->Enable(linear_gradient && (has_start || has_end));
}
if (wxWindow *window = editor_ref.get())
window->Layout();
if (wxWindow *window = row_ref.get())
@@ -7189,6 +7228,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
}
updated.enabled = true;
updated.surface_pattern = surface_pattern;
updated.apply_default_modulation_mode();
updated.component_ids = encode_texture_mapping_component_ids(ids);
if (updated.is_linear_gradient() && !updated.linear_gradient_stops.empty()) {
updated.component_a = updated.linear_gradient_stops.front().filament_id;
@@ -7365,6 +7405,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
updated.enabled = true;
updated.surface_pattern = surface_pattern;
updated.apply_default_modulation_mode();
updated.component_ids = encode_texture_mapping_component_ids(ids);
if (updated.is_linear_gradient() && !updated.linear_gradient_stops.empty()) {
updated.component_a = updated.linear_gradient_stops.front().filament_id;
@@ -7451,6 +7492,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
});
if (linear_gradient_radius_spin != nullptr) {
linear_gradient_radius_spin->Bind(wxEVT_SPINCTRLDOUBLE, [apply_controls](wxSpinDoubleEvent &) { apply_controls(); });
linear_gradient_radius_spin->Bind(wxEVT_TEXT, [apply_controls](wxCommandEvent &) { apply_controls(); });
linear_gradient_radius_spin->Bind(wxEVT_TEXT_ENTER, [apply_controls](wxCommandEvent &) { apply_controls(); });
linear_gradient_radius_spin->Bind(wxEVT_KILL_FOCUS, [apply_controls](wxFocusEvent &evt) {
apply_controls();
@@ -7515,6 +7557,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
else
updated.linear_gradient_end = anchor;
updated.surface_pattern = int(TextureMappingZone::LinearGradient);
updated.apply_default_modulation_mode();
if (updated == mgr_ptr->zones()[zone_index])
return;
sync_current_model_texture_mapping_definitions(serialize_texture_mapping_manager(mgr_ptr));
@@ -7567,6 +7610,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
const std::string original_serialized = serialize_texture_mapping_manager(mgr_ptr);
TextureMappingZone active_preview = original;
active_preview.surface_pattern = int(TextureMappingZone::LinearGradient);
active_preview.apply_default_modulation_mode();
active_preview.show_linear_gradient_direction_arrow = true;
auto live_preview_applied = std::make_shared<bool>(false);
auto redraw_live_preview = [this]() {
@@ -7634,6 +7678,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
else
preview.linear_gradient_end = anchor;
preview.surface_pattern = int(TextureMappingZone::LinearGradient);
preview.apply_default_modulation_mode();
apply_live_preview(std::move(preview));
}, cancel_live_selection);
if (gizmos.get_current_type() != GLGizmosManager::TextureGradientPointPicker)
@@ -7661,6 +7706,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
TextureMappingZone updated = mgr_ptr->zones()[zone_index];
updated.clear_linear_gradient_points();
updated.surface_pattern = int(TextureMappingZone::LinearGradient);
updated.apply_default_modulation_mode();
if (updated == mgr_ptr->zones()[zone_index])
return;
sync_current_model_texture_mapping_definitions(serialize_texture_mapping_manager(mgr_ptr));
@@ -7725,6 +7771,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
return;
}
updated.surface_pattern = int(TextureMappingZone::Gradient2D);
updated.apply_default_modulation_mode();
apply_zone(std::move(updated));
CallAfter([this]() { update_texture_mapping_panel(false); });
});
@@ -7777,6 +7824,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
updated.seam_hiding,
updated.nonlinear_offset_adjustment,
updated.modulation_mode,
updated.modulation_mode_manually_changed,
updated.recolor_small_perimeter_loops,
updated.recolor_top_visible_perimeter_sections,
updated.top_visible_perimeter_recolor_aggressiveness,
@@ -7818,6 +7866,8 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
updated.seam_hiding = dlg.seam_hiding();
updated.nonlinear_offset_adjustment = dlg.nonlinear_offset_adjustment();
updated.modulation_mode = dlg.modulation_mode();
updated.modulation_mode_manually_changed = dlg.modulation_mode_manually_changed();
updated.apply_default_modulation_mode();
updated.recolor_small_perimeter_loops = dlg.recolor_small_perimeter_loops();
updated.recolor_top_visible_perimeter_sections = dlg.recolor_top_visible_perimeter_sections();
updated.top_visible_perimeter_recolor_aggressiveness = dlg.top_visible_perimeter_recolor_aggressiveness();
@@ -7916,20 +7966,43 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
evt.StopPropagation();
evt.Skip();
});
menu_btn->Bind(wxEVT_BUTTON, [this, zone_index, num_physical, physical_colors, mgr_ptr, persist_rows, menu_btn, bundle, set_config_string, texture_mapping_zone_affects_scene](wxCommandEvent &) {
menu_btn->Bind(wxEVT_BUTTON, [this, zone_index, num_physical, physical_colors, mgr_ptr, persist_rows, menu_btn, bundle, set_config_string,
texture_mapping_zone_affects_scene, selected_texture_mapping_object_idxs, refresh_texture_mapping_preview](wxCommandEvent &) {
if (menu_btn == nullptr)
return;
wxMenu menu;
const int assign_selected_objects_id = wxWindow::NewControlId();
const int duplicate_id = wxWindow::NewControlId();
const int delete_id = wxWindow::NewControlId();
const int delete_all_id = wxWindow::NewControlId();
wxMenuItem *assign_selected_objects_item = menu.Append(assign_selected_objects_id, _L("Assign to selected objects"));
if (assign_selected_objects_item != nullptr)
assign_selected_objects_item->Enable(!selected_texture_mapping_object_idxs().empty());
menu.Append(duplicate_id, _L("Duplicate"));
menu.Append(delete_id, _L("Delete"));
menu.Bind(wxEVT_COMMAND_MENU_SELECTED, [this, zone_index, num_physical, physical_colors, mgr_ptr, persist_rows, duplicate_id, delete_id, bundle, set_config_string, texture_mapping_zone_affects_scene](wxCommandEvent &evt) {
menu.Append(delete_all_id, _L("Delete All Texture Mapping Zones"));
menu.Bind(wxEVT_COMMAND_MENU_SELECTED, [this, zone_index, num_physical, physical_colors, mgr_ptr, persist_rows, assign_selected_objects_id,
duplicate_id, delete_id, delete_all_id, bundle, set_config_string,
texture_mapping_zone_affects_scene, selected_texture_mapping_object_idxs,
refresh_texture_mapping_preview, menu_btn](wxCommandEvent &evt) {
if (mgr_ptr == nullptr)
return;
auto &rows = mgr_ptr->zones();
if (zone_index >= rows.size())
return;
if (evt.GetId() == assign_selected_objects_id) {
std::vector<size_t> object_idxs = selected_texture_mapping_object_idxs();
if (object_idxs.empty()) {
MessageDialog(menu_btn, _L("No objects are currently selected."), _L("Assign to selected objects"), wxOK | wxICON_INFORMATION).ShowModal();
return;
}
const unsigned int zone_id = rows[zone_index].zone_id;
if (zone_id == 0 || obj_list() == nullptr)
return;
if (obj_list()->assign_extruder_to_objects_and_clear_filament_region_painting(object_idxs, int(zone_id)))
refresh_texture_mapping_preview();
return;
}
if (evt.GetId() == duplicate_id) {
mgr_ptr->duplicate_zone(zone_index, num_physical, physical_colors);
persist_rows(false);
@@ -7950,6 +8023,33 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
p->m_expanded_texture_mapping_rows.clear();
persist_rows(affects_scene);
CallAfter([this]() { update_texture_mapping_panel(false); });
return;
}
if (evt.GetId() == delete_all_id) {
if (MessageDialog(menu_btn,
_L("Delete all texture mapping zones?"),
wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Delete All Texture Mapping Zones"),
wxYES_NO | wxNO_DEFAULT | wxICON_WARNING).ShowModal() != wxID_YES)
return;
bool affects_scene = false;
const uint64_t settings_zone_uid = bundle->texture_mapping_global_settings.prime_tower_settings_zone_uid;
bool clear_settings_zone_uid = false;
for (const TextureMappingZone &zone : rows) {
if (!zone.enabled || zone.deleted)
continue;
affects_scene |= texture_mapping_zone_affects_scene(zone.zone_id);
clear_settings_zone_uid |= settings_zone_uid != 0 && zone.stable_id == settings_zone_uid;
}
rows.clear();
if (clear_settings_zone_uid) {
TextureMappingGlobalSettings settings = bundle->texture_mapping_global_settings;
settings.prime_tower_settings_zone_uid = 0;
bundle->texture_mapping_global_settings = settings;
set_config_string("texture_mapping_global_settings", bundle->texture_mapping_global_settings.serialize());
}
p->m_expanded_texture_mapping_rows.clear();
persist_rows(affects_scene);
CallAfter([this]() { update_texture_mapping_panel(false); });
}
});
menu_btn->PopupMenu(&menu, wxPoint(0, menu_btn->GetSize().GetHeight()));