diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index 1aacb5d9c54..c862459874c 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -18,6 +18,7 @@ //BBS: add partplate related logic #include "PartPlate.hpp" #include "Gizmos/GLGizmoEmboss.hpp" +#include "Gizmos/GLGizmoMmuSegmentation.hpp" #include "Gizmos/GLGizmoSVG.hpp" #include @@ -98,6 +99,31 @@ static std::vector ui_ordered_filament_ids(int fallback_count) return ids; } +static int menu_item_position(wxMenu *menu, const wxString &name) +{ + int position = 0; + for (auto node = menu->GetMenuItems().GetFirst(); node; node = node->GetNext(), ++position) { + wxMenuItem *item = node->GetData(); + if (item != nullptr && item->GetItemLabelText() == name) + return position; + } + return wxNOT_FOUND; +} + +static ModelObject *selected_managed_color_data_object() +{ + Plater *app_plater = wxGetApp().plater(); + if (app_plater == nullptr) + return nullptr; + + const int object_idx = app_plater->get_selection().get_object_idx(); + ModelObjectPtrs &objects = wxGetApp().model().objects; + if (object_idx < 0 || size_t(object_idx) >= objects.size()) + return nullptr; + + return objects[size_t(object_idx)]; +} + static bool is_improper_category(const std::string& category, const int filaments_cnt, const bool is_object_settings = true) { return category.empty() || @@ -1174,6 +1200,45 @@ void MenuFactory::append_menu_items_flush_options(wxMenu* menu) menu->Insert(i, wxID_ANY, _L("Flush Options"), flush_options_menu); } +void MenuFactory::append_menu_item_manage_color_data(wxMenu *menu) +{ + const wxString name = _L("Manage Color Data"); + const int item_id = menu->FindItem(name); + if (item_id != wxNOT_FOUND) + menu->Destroy(item_id); + + if (selected_managed_color_data_object() == nullptr) + return; + + int insert_pos = menu_item_position(menu, _L("Flush Options")); + if (insert_pos != wxNOT_FOUND) + ++insert_pos; + else { + insert_pos = menu_item_position(menu, _L("Edit in Parameter Table")); + if (insert_pos != wxNOT_FOUND) + ++insert_pos; + } + + auto can_manage_color_data = []() { + Plater *app_plater = wxGetApp().plater(); + return app_plater != nullptr && app_plater->get_view3D_canvas3D() != nullptr && selected_managed_color_data_object() != nullptr; + }; + + append_menu_item(menu, wxID_ANY, name, _L("Manage Color Data for this object"), + [this](wxCommandEvent &) { + Plater *app_plater = wxGetApp().plater(); + if (app_plater == nullptr) + return; + + GLCanvas3D *canvas = app_plater->get_view3D_canvas3D(); + ModelObject *object = selected_managed_color_data_object(); + if (canvas == nullptr || object == nullptr) + return; + + Slic3r::GUI::open_color_data_management_dialog(m_parent, *canvas, object); + }, "", menu, can_manage_color_data, m_parent, insert_pos); +} + void MenuFactory::append_menu_items_convert_unit(wxMenu* menu) { std::vector obj_idxs, vol_idxs; @@ -1825,6 +1890,7 @@ wxMenu* MenuFactory::object_menu() { append_menu_items_convert_unit(&m_object_menu); append_menu_items_flush_options(&m_object_menu); + append_menu_item_manage_color_data(&m_object_menu); append_menu_item_invalidate_cut_info(&m_object_menu); append_menu_item_edit_text(&m_object_menu); append_menu_item_edit_svg(&m_object_menu); diff --git a/src/slic3r/GUI/GUI_Factories.hpp b/src/slic3r/GUI/GUI_Factories.hpp index f80ef85d53e..f54b05f6dbe 100644 --- a/src/slic3r/GUI/GUI_Factories.hpp +++ b/src/slic3r/GUI/GUI_Factories.hpp @@ -152,6 +152,7 @@ private: void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu); void append_menu_items_convert_unit(wxMenu* menu); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk" void append_menu_items_flush_options(wxMenu* menu); + void append_menu_item_manage_color_data(wxMenu *menu); void append_menu_item_merge_to_multipart_object(wxMenu *menu); void append_menu_item_merge_to_single_object(wxMenu* menu); void append_menu_item_merge_parts_to_single_part(wxMenu *menu); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 9e484f2e2e3..1b4d8f2c26c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -4319,6 +4319,30 @@ static bool assign_object_to_texture_mapping_zone(ModelObject &object) return true; } +static void assign_texture_mapping_zone_preserving_painted_regions(ModelObject &object, unsigned int texture_mapping_filament_id) +{ + if (texture_mapping_filament_id == 0) + return; + + bool has_painted_regions = false; + for (const ModelVolume *volume : object.volumes) { + if (volume != nullptr && volume->is_model_part() && !volume->mmu_segmentation_facets.empty()) { + has_painted_regions = true; + break; + } + } + + if (!has_painted_regions) + object.config.set("extruder", int(texture_mapping_filament_id)); + + for (ModelVolume *volume : object.volumes) { + if (volume == nullptr || !volume->is_model_part()) + continue; + if (!has_painted_regions || volume->mmu_segmentation_facets.empty()) + volume->config.set("extruder", int(texture_mapping_filament_id)); + } +} + struct ManagedRegionColorSource { std::vector> triangles_per_type; @@ -5472,6 +5496,15 @@ private: wxStaticText *m_raw_image_texture_mode = nullptr; }; +void open_color_data_management_dialog(wxWindow *parent, GLCanvas3D &canvas, ModelObject *object, std::function on_object_changed) +{ + if (object == nullptr) + return; + + ColorDataManagementDialog dialog(parent, canvas, object, std::move(on_object_changed)); + dialog.ShowModal(); +} + void GLGizmoMmuSegmentation::init_extruders_data(const std::vector &extruder_colors) { const unsigned int old_selected_filament_id = @@ -6674,12 +6707,7 @@ void GLGizmoMmuSegmentation::convert_selected_object_vertex_colors_to_texture_ma return; const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); - if (texture_mapping_filament_id != 0) { - object->config.set("extruder", int(texture_mapping_filament_id)); - for (ModelVolume *volume : object->volumes) - if (volume != nullptr && volume->is_model_part()) - volume->config.set("extruder", int(texture_mapping_filament_id)); - } + assign_texture_mapping_zone_preserving_painted_regions(*object, texture_mapping_filament_id); for (auto &selector : m_triangle_selectors) if (selector != nullptr) @@ -6750,12 +6778,7 @@ void GLGizmoMmuSegmentation::convert_selected_object_image_texture_to_texture_ma return; const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); - if (texture_mapping_filament_id != 0) { - object->config.set("extruder", int(texture_mapping_filament_id)); - for (ModelVolume *volume : object->volumes) - if (volume != nullptr && volume->is_model_part()) - volume->config.set("extruder", int(texture_mapping_filament_id)); - } + assign_texture_mapping_zone_preserving_painted_regions(*object, texture_mapping_filament_id); for (auto &selector : m_triangle_selectors) if (selector != nullptr) @@ -7239,13 +7262,15 @@ void GLGizmoTrueColorPainting::init_model_triangle_selectors() preview_rgb_data = preview.get(); m_preview_rgb_data_by_volume.back() = std::move(preview); } + } else { + preview_rgb_data = &volume->texture_mapping_color_facets; } m_triangle_selectors.emplace_back(std::make_unique(volume->mesh(), volume, colors, 0.2f)); if (TriangleSelectorPatch *patch = dynamic_cast(m_triangle_selectors.back().get())) { patch->set_none_state_rendered(false); patch->set_texture_mapping_color_preview(preview_rgb_data); - patch->set_texture_preview_needed(!volume->texture_mapping_color_facets.empty() || preview_rgb_data != nullptr); + patch->set_texture_preview_needed(preview_rgb_data != nullptr); patch->set_texture_preview_opaque(true); } m_triangle_selectors.back()->set_wireframe_needed(true); @@ -7385,12 +7410,7 @@ void GLGizmoTrueColorPainting::update_model_object() return; const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); - if (texture_mapping_filament_id != 0) { - object->config.set("extruder", int(texture_mapping_filament_id)); - for (ModelVolume *volume : object->volumes) - if (volume != nullptr && volume->is_model_part()) - volume->config.set("extruder", int(texture_mapping_filament_id)); - } + assign_texture_mapping_zone_preserving_painted_regions(*object, texture_mapping_filament_id); refresh_selected_object_after_rgb_change(object); } @@ -7409,13 +7429,12 @@ void GLGizmoTrueColorPainting::open_color_data_management_dialog() if (object == nullptr) return; - ColorDataManagementDialog dialog(wxGetApp().mainframe, m_parent, object, [this]() { + Slic3r::GUI::open_color_data_management_dialog(wxGetApp().mainframe, m_parent, object, [this]() { update_selected_object_color_state(); init_model_triangle_selectors(); m_parent.set_as_dirty(); m_parent.request_extra_frame(); }); - dialog.ShowModal(); update_selected_object_color_state(); init_model_triangle_selectors(); m_parent.set_as_dirty(); @@ -7475,12 +7494,7 @@ void GLGizmoTrueColorPainting::initialize_selected_object_rgb_data() return; const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); - if (texture_mapping_filament_id != 0) { - object->config.set("extruder", int(texture_mapping_filament_id)); - for (ModelVolume *volume : object->volumes) - if (volume != nullptr && volume->is_model_part()) - volume->config.set("extruder", int(texture_mapping_filament_id)); - } + assign_texture_mapping_zone_preserving_painted_regions(*object, texture_mapping_filament_id); refresh_selected_object_after_rgb_change(object); } @@ -7540,12 +7554,7 @@ void GLGizmoTrueColorPainting::convert_selected_object_vertex_colors_to_rgb_data return; const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); - if (texture_mapping_filament_id != 0) { - object->config.set("extruder", int(texture_mapping_filament_id)); - for (ModelVolume *volume : object->volumes) - if (volume != nullptr && volume->is_model_part()) - volume->config.set("extruder", int(texture_mapping_filament_id)); - } + assign_texture_mapping_zone_preserving_painted_regions(*object, texture_mapping_filament_id); refresh_selected_object_after_rgb_change(object); } @@ -7601,12 +7610,7 @@ void GLGizmoTrueColorPainting::convert_selected_object_image_texture_to_rgb_data return; const unsigned int texture_mapping_filament_id = ensure_texture_mapping_zone(); - if (texture_mapping_filament_id != 0) { - object->config.set("extruder", int(texture_mapping_filament_id)); - for (ModelVolume *volume : object->volumes) - if (volume != nullptr && volume->is_model_part()) - volume->config.set("extruder", int(texture_mapping_filament_id)); - } + assign_texture_mapping_zone_preserving_painted_regions(*object, texture_mapping_filament_id); refresh_selected_object_after_rgb_change(object); } @@ -8490,13 +8494,12 @@ void GLGizmoImageProjection::open_color_data_management_dialog() if (object == nullptr) return; - ColorDataManagementDialog dialog(wxGetApp().mainframe, m_parent, object, [this]() { + Slic3r::GUI::open_color_data_management_dialog(wxGetApp().mainframe, m_parent, object, [this]() { m_projection_mode_initialized = false; update_default_projection_mode(); m_parent.set_as_dirty(); m_parent.request_extra_frame(); }); - dialog.ShowModal(); m_projection_mode_initialized = false; update_default_projection_mode(); m_parent.set_as_dirty(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 76abaa279c9..ee8b5eae5bc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -7,13 +7,24 @@ #include #include +#include #include #include #include #include +class wxWindow; + +namespace Slic3r { +class ModelObject; +} + namespace Slic3r::GUI { +class GLCanvas3D; + +void open_color_data_management_dialog(wxWindow *parent, GLCanvas3D &canvas, ModelObject *object, std::function on_object_changed = {}); + class GLMmSegmentationGizmo3DScene { public: diff --git a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp index 4272fd5497d..5af73567ea2 100644 --- a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp +++ b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp @@ -3663,8 +3663,13 @@ void render_model_vertex_color_preview_models( print_volume_z); for (size_t idx = 0; idx < models.size(); ++idx) { - const float mix = texture_preview_mix_for_filament(filament_ids[idx], num_physical, texture_mgr); - const bool invalid = texture_preview_settings_invalid_for_filament(filament_ids[idx], num_physical, texture_mgr); + const bool raw_vertex_color_preview = filament_ids[idx] == 0; + const float mix = raw_vertex_color_preview ? + 1.f : + texture_preview_mix_for_filament(filament_ids[idx], num_physical, texture_mgr); + const bool invalid = raw_vertex_color_preview ? + false : + texture_preview_settings_invalid_for_filament(filament_ids[idx], num_physical, texture_mgr); if (mix <= 0.f && !invalid) continue; shader->set_uniform("texture_preview_mix", mix);