From aecead1f8c926a80c84160bcb8469e6a148e5d67 Mon Sep 17 00:00:00 2001 From: sentientstardust Date: Sun, 10 May 2026 17:44:28 +0100 Subject: [PATCH] Auto-assign a texture mapping zone to objects when 3mf color region data is cleared in the manage color data dialog --- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 67 +++++++++++++++++-- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index dc8867b438f..85a9f11df06 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -4446,6 +4446,23 @@ static bool object_has_rgba_data(const ModelObject &object) return false; } +static bool model_volume_has_non_region_color_data(const ModelVolume *volume) +{ + return volume != nullptr && + volume->is_model_part() && + (!volume->imported_vertex_colors_rgba.empty() || + model_volume_has_imported_image_texture_data(volume) || + !volume->texture_mapping_color_facets.empty()); +} + +static bool object_has_non_region_color_data(const ModelObject &object) +{ + for (const ModelVolume *volume : object.volumes) + if (model_volume_has_non_region_color_data(volume)) + return true; + return false; +} + static bool object_has_managed_color_data(const ModelObject &object, ManagedColorDataType type) { switch (type) { @@ -4695,12 +4712,48 @@ static void assign_texture_mapping_zone_preserving_painted_regions(ModelObject & } } -static bool image_texture_zone_is_usable_for_projection(const TextureMappingManager &texture_mgr, unsigned int zone_id) +static bool image_texture_zone_is_usable(const TextureMappingManager &texture_mgr, unsigned int zone_id) { const TextureMappingZone *zone = texture_mgr.zone_from_id(zone_id); return zone != nullptr && zone->enabled && !zone->deleted && zone->is_image_texture(); } +static bool non_region_color_data_is_assigned_to_image_texture_zone(const ModelObject &object) +{ + if (wxGetApp().preset_bundle == nullptr) + return false; + + const TextureMappingManager &texture_mgr = wxGetApp().preset_bundle->texture_mapping_zones; + bool has_color_data = false; + for (const ModelVolume *volume : object.volumes) { + if (!model_volume_has_non_region_color_data(volume)) + continue; + + has_color_data = true; + const int extruder_id = volume->extruder_id(); + if (extruder_id <= 0 || !image_texture_zone_is_usable(texture_mgr, unsigned(extruder_id))) + return false; + } + return has_color_data; +} + +static bool assign_non_region_color_data_to_image_texture_zone(ModelObject &object) +{ + if (!object_has_non_region_color_data(object) || + non_region_color_data_is_assigned_to_image_texture_zone(object)) + return false; + + const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); + if (texture_mapping_filament_id == 0) + return false; + + object.config.set("extruder", int(texture_mapping_filament_id)); + for (ModelVolume *volume : object.volumes) + if (model_volume_has_non_region_color_data(volume)) + volume->config.set("extruder", int(texture_mapping_filament_id)); + return true; +} + static unsigned int painted_image_texture_zone_id_for_projection(const ModelObject &object) { if (wxGetApp().preset_bundle == nullptr) @@ -4714,13 +4767,13 @@ static unsigned int painted_image_texture_zone_id_for_projection(const ModelObje const auto &used_states = volume->mmu_segmentation_facets.get_data().used_states; for (size_t state_idx = static_cast(EnforcerBlockerType::Extruder1); state_idx < used_states.size(); ++state_idx) { - if (used_states[state_idx] && image_texture_zone_is_usable_for_projection(texture_mgr, unsigned(state_idx))) + if (used_states[state_idx] && image_texture_zone_is_usable(texture_mgr, unsigned(state_idx))) painted_ids.emplace_back(unsigned(state_idx)); } } for (const TextureMappingZone &zone : texture_mgr.zones()) - if (image_texture_zone_is_usable_for_projection(texture_mgr, zone.zone_id) && + if (image_texture_zone_is_usable(texture_mgr, zone.zone_id) && std::find(painted_ids.begin(), painted_ids.end(), zone.zone_id) != painted_ids.end()) return zone.zone_id; return 0; @@ -4735,7 +4788,7 @@ static unsigned int base_image_texture_zone_id_for_projection(const ModelObject std::vector base_ids; if (const ConfigOption *opt = object.config.option("extruder"); opt != nullptr) { const int extruder_id = opt->getInt(); - if (extruder_id > 0 && image_texture_zone_is_usable_for_projection(texture_mgr, unsigned(extruder_id))) + if (extruder_id > 0 && image_texture_zone_is_usable(texture_mgr, unsigned(extruder_id))) base_ids.emplace_back(unsigned(extruder_id)); } @@ -4743,12 +4796,12 @@ static unsigned int base_image_texture_zone_id_for_projection(const ModelObject if (volume == nullptr || !volume->is_model_part()) continue; const int extruder_id = volume->extruder_id(); - if (extruder_id > 0 && image_texture_zone_is_usable_for_projection(texture_mgr, unsigned(extruder_id))) + if (extruder_id > 0 && image_texture_zone_is_usable(texture_mgr, unsigned(extruder_id))) base_ids.emplace_back(unsigned(extruder_id)); } for (const TextureMappingZone &zone : texture_mgr.zones()) - if (image_texture_zone_is_usable_for_projection(texture_mgr, zone.zone_id) && + if (image_texture_zone_is_usable(texture_mgr, zone.zone_id) && std::find(base_ids.begin(), base_ids.end(), zone.zone_id) != base_ids.end()) return zone.zone_id; return 0; @@ -6172,6 +6225,8 @@ private: Plater::TakeSnapshot snapshot(wxGetApp().plater(), clear_snapshot_name(type), UndoRedo::SnapshotType::GizmoAction); if (!clear_object_managed_color_data(*m_object, type)) return; + if (type == ManagedColorDataType::ColorRegions) + assign_non_region_color_data_to_image_texture_zone(*m_object); refresh_object_after_change(); refresh_rows();