From 95f6cb25743353cdbb7f2b4127cd2ced2a10f2b5 Mon Sep 17 00:00:00 2001 From: Rad Date: Wed, 11 Mar 2026 17:49:17 +0100 Subject: [PATCH] obj color match "keep color" append missing color simplification --- localization/i18n/Snapmaker_Orca.pot | 12 +- localization/i18n/en/Snapmaker_Orca_en.po | 12 +- src/slic3r/GUI/ObjColorDialog.cpp | 205 ++++++++++++++++------ src/slic3r/GUI/ObjColorDialog.hpp | 18 +- 4 files changed, 185 insertions(+), 62 deletions(-) diff --git a/localization/i18n/Snapmaker_Orca.pot b/localization/i18n/Snapmaker_Orca.pot index c11cab95be..5d686c982e 100644 --- a/localization/i18n/Snapmaker_Orca.pot +++ b/localization/i18n/Snapmaker_Orca.pot @@ -8121,10 +8121,16 @@ msgstr "" msgid "Approximate color matching." msgstr "" -msgid "Append" +msgid "Append all" msgstr "" -msgid "Add consumable extruder after existing extruders." +msgid "Add all clustered colors after the existing filaments." +msgstr "" + +msgid "Keep color" +msgstr "" + +msgid "Add this cluster color as a new filament." msgstr "" msgid "Reset mapped extruders." @@ -16248,4 +16254,4 @@ msgid "Snapmaker Orca is licensed under the GNU Affero Generall Public License, msgstr "" msgid "OrcaSlicer is forked from Bambu Studio by Bambu Lab." -msgstr "" \ No newline at end of file +msgstr "" diff --git a/localization/i18n/en/Snapmaker_Orca_en.po b/localization/i18n/en/Snapmaker_Orca_en.po index 56131f568b..43eb7c5db3 100644 --- a/localization/i18n/en/Snapmaker_Orca_en.po +++ b/localization/i18n/en/Snapmaker_Orca_en.po @@ -8242,10 +8242,16 @@ msgstr "" msgid "Approximate color matching." msgstr "" -msgid "Append" +msgid "Append all" msgstr "" -msgid "Add consumable extruder after existing extruders." +msgid "Add all clustered colors after the existing filaments." +msgstr "" + +msgid "Keep color" +msgstr "" + +msgid "Add this cluster color as a new filament." msgstr "" msgid "Reset mapped extruders." @@ -17185,4 +17191,4 @@ msgstr "" #~ msgstr "" #~ "It is not recommend for bed temperature of other layers to be lower than " #~ "the first layer by more than this threshold. Too low bed temperature of " -#~ "other layer may cause the model to break free from the build plate." \ No newline at end of file +#~ "other layer may cause the model to break free from the build plate." diff --git a/src/slic3r/GUI/ObjColorDialog.cpp b/src/slic3r/GUI/ObjColorDialog.cpp index 3fe4375925..89bfccdf04 100644 --- a/src/slic3r/GUI/ObjColorDialog.cpp +++ b/src/slic3r/GUI/ObjColorDialog.cpp @@ -26,12 +26,12 @@ int OBJCOLOR_ITEM_WIDTH() { return objcolor_scale(30); } static const wxColour g_text_color = wxColour(107, 107, 107, 255); const int HEADER_BORDER = 5; const int CONTENT_BORDER = 3; -const int PANEL_WIDTH = 370; -const int COLOR_LABEL_WIDTH = 180; +const int PANEL_WIDTH = 430; +const int COLOR_LABEL_WIDTH = 165; #undef ICON_SIZE #define ICON_SIZE wxSize(FromDIP(16), FromDIP(16)) -#define MIN_OBJCOLOR_DIALOG_WIDTH FromDIP(400) +#define MIN_OBJCOLOR_DIALOG_WIDTH FromDIP(460) #define FIX_SCROLL_HEIGTH FromDIP(400) #define BTN_SIZE wxSize(FromDIP(58), FromDIP(24)) #define BTN_GAP FromDIP(20) @@ -399,7 +399,7 @@ void ObjColorPanel::update_filament_ids() const int existing_filament_count = static_cast(m_colours.size()); std::map appended_filament_id_map; - if (m_is_add_filament) { + if (!m_new_add_colors.empty()) { std::vector selected_appended_indices; selected_appended_indices.reserve(m_cluster_map_filaments.size()); for (int mapped_filament_id : m_cluster_map_filaments) { @@ -471,8 +471,8 @@ wxBoxSizer *ObjColorPanel::create_add_btn_sizer(wxWindow *parent) StateColor calc_btn_bd(std::pair(wxColour(0, 150, 136), StateColor::Normal)); StateColor calc_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); // create btn - m_quick_add_btn = new Button(parent, _L("Append")); - m_quick_add_btn->SetToolTip(_L("Add consumable extruder after existing extruders.")); + m_quick_add_btn = new Button(parent, _L("Append all")); + m_quick_add_btn->SetToolTip(_L("Add all clustered colors after the existing filaments.")); auto cur_btn = m_quick_add_btn; cur_btn->SetFont(Label::Body_13); cur_btn->SetMinSize(wxSize(FromDIP(60), FromDIP(20))); @@ -497,7 +497,7 @@ wxBoxSizer *ObjColorPanel::create_reset_btn_sizer(wxWindow *parent) StateColor calc_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); // create btn m_quick_reset_btn = new Button(parent, _L("Reset")); - m_quick_add_btn->SetToolTip(_L("Reset mapped extruders.")); + m_quick_reset_btn->SetToolTip(_L("Reset mapped extruders.")); auto cur_btn = m_quick_reset_btn; cur_btn->SetFont(Label::Body_13); cur_btn->SetMinSize(wxSize(FromDIP(60), FromDIP(20))); @@ -574,7 +574,7 @@ ComboBox *ObjColorPanel::CreateEditorCtrl(wxWindow *parent, int id) // wxRect la void ObjColorPanel::deal_approximate_match_btn() { - if (m_is_add_filament) { + if (!m_new_add_colors.empty()) { deal_reset_btn(); } @@ -606,6 +606,93 @@ void ObjColorPanel::deal_approximate_match_btn() m_result_icon_list[i]->bitmap_combox->SetSelection(new_index); m_cluster_map_filaments[i] = new_index; } + update_keep_color_buttons(); +} + +bool ObjColorPanel::colors_are_equal(const wxColour &lhs, const wxColour &rhs) +{ + return lhs.Red() == rhs.Red() && lhs.Green() == rhs.Green() && lhs.Blue() == rhs.Blue() && lhs.Alpha() == rhs.Alpha(); +} + +int ObjColorPanel::find_filament_selection_by_color(const wxColour &color) const +{ + for (size_t i = 0; i < m_colours.size(); ++i) { + if (colors_are_equal(m_colours[i], color)) { + return static_cast(i + 1); + } + } + + for (size_t i = 0; i < m_new_add_colors.size(); ++i) { + if (colors_are_equal(m_new_add_colors[i], color)) { + return static_cast(m_colours.size() + i + 1); + } + } + + return 0; +} + +int ObjColorPanel::append_new_filament_option(const wxColour &color) +{ + if (m_colours.size() + m_new_add_colors.size() >= g_max_color) { + return 0; + } + + m_new_add_colors.emplace_back(color); + const int selection = static_cast(m_colours.size() + m_new_add_colors.size()); + auto * bitmap = get_extruder_color_icon(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), std::to_string(selection), m_combox_icon_width, m_combox_icon_height); + + for (auto *item : m_result_icon_list) { + if (item->bitmap_combox == nullptr) { + continue; + } + + item->bitmap_combox->Append(wxString::Format("%d", item->bitmap_combox->GetCount()), *bitmap); + item->bitmap_combox->SetItemTooltip(item->bitmap_combox->GetCount() - 1, color.GetAsString(wxC2S_HTML_SYNTAX)); + } + + return selection; +} + +void ObjColorPanel::update_keep_color_buttons() +{ + for (size_t i = 0; i < m_result_icon_list.size(); ++i) { + auto *item = m_result_icon_list[i]; + if (item->keep_color_btn == nullptr) { + continue; + } + + const bool has_cluster_color = i < m_cluster_colours.size(); + const bool show_keep_color = has_cluster_color && find_filament_selection_by_color(m_cluster_colours[i]) == 0; + item->keep_color_btn->Show(show_keep_color); + item->keep_color_btn->Enable(show_keep_color); + } + + if (m_scrolledWindow != nullptr) { + m_scrolledWindow->Layout(); + } + Layout(); +} + +void ObjColorPanel::deal_keep_color_btn(int id) +{ + if (id < 0 || id >= static_cast(m_cluster_colours.size())) { + return; + } + + int selection = find_filament_selection_by_color(m_cluster_colours[id]); + if (selection == 0) { + selection = append_new_filament_option(m_cluster_colours[id]); + } + + if (selection == 0) { + m_warning_text->SetLabelText(_L("Warning: The count of newly added and \ncurrent extruders exceeds 16.")); + return; + } + + m_result_icon_list[id]->bitmap_combox->SetSelection(selection); + m_cluster_map_filaments[id] = selection; + m_warning_text->SetLabelText(_L("Note: The color has been selected, you can choose OK \nto continue or manually adjust it.")); + update_keep_color_buttons(); } void ObjColorPanel::show_sizer(wxSizer *sizer, bool show) @@ -639,17 +726,16 @@ void ObjColorPanel::redraw_part_table() { int id = i; wxPanel *row_panel = new wxPanel(m_scrolledWindow); row_panel->SetBackgroundColour((i+1) % 2 == 0 ? *wxWHITE : wxColour(238, 238, 238)); - auto row_sizer = new wxGridSizer(1, 2, 1, 3); + auto row_sizer = new wxBoxSizer(wxHORIZONTAL); row_panel->SetSizer(row_sizer); row_panel->SetMinSize(wxSize(FromDIP(PANEL_WIDTH), -1)); row_panel->SetMaxSize(wxSize(FromDIP(PANEL_WIDTH), -1)); auto cluster_color_icon_sizer = create_color_icon_and_rgba_sizer(row_panel, id, m_cluster_colours[id]); - row_sizer->Add(cluster_color_icon_sizer, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, FromDIP(CONTENT_BORDER)); - // result_combox - create_result_button_sizer(row_panel, id); - row_sizer->Add(m_result_icon_list[id]->bitmap_combox, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, 0); + row_sizer->Add(cluster_color_icon_sizer, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); + row_sizer->AddStretchSpacer(); + row_sizer->Add(create_result_button_sizer(row_panel, id), 0, wxALIGN_CENTER_VERTICAL, 0); m_row_sizer_list.emplace_back(row_sizer); m_gridsizer->Add(row_panel, 0, wxALIGN_LEFT | wxALL, FromDIP(HEADER_BORDER)); @@ -660,6 +746,7 @@ void ObjColorPanel::redraw_part_table() { // m_color_cluster_icon_list//m_color_cluster_text_list update_color_icon_and_rgba_sizer(i, m_cluster_colours[i]); } + update_keep_color_buttons(); m_scrolledWindow->Refresh(); } @@ -674,7 +761,7 @@ void ObjColorPanel::draw_table() for (size_t ii = 0; ii < row; ii++) { wxPanel *row_panel = new wxPanel(m_scrolledWindow); row_panel->SetBackgroundColour(ii % 2 == 0 ? *wxWHITE : wxColour(238, 238, 238)); - auto row_sizer = new wxGridSizer(1, 2, 1, 5); + auto row_sizer = new wxBoxSizer(wxHORIZONTAL); row_panel->SetSizer(row_sizer); row_panel->SetMinSize(wxSize(FromDIP(PANEL_WIDTH), -1)); @@ -682,19 +769,19 @@ void ObjColorPanel::draw_table() if (ii == 0) { wxStaticText *colors_left_title = new wxStaticText(row_panel, wxID_ANY, _L("Cluster colors")); colors_left_title->SetFont(Label::Head_14); - row_sizer->Add(colors_left_title, 0, wxALIGN_CENTER | wxALL, FromDIP(HEADER_BORDER)); + row_sizer->Add(colors_left_title, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(40)); + row_sizer->AddStretchSpacer(); wxStaticText *colors_middle_title = new wxStaticText(row_panel, wxID_ANY, _L("Map Filament")); colors_middle_title->SetFont(Label::Head_14); - row_sizer->Add(colors_middle_title, 0, wxALIGN_CENTER | wxALL, FromDIP(HEADER_BORDER)); + row_sizer->Add(colors_middle_title, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(HEADER_BORDER)); } else { int id = ii - 1; if (id < m_cluster_colours.size()) { auto cluster_color_icon_sizer = create_color_icon_and_rgba_sizer(row_panel, id, m_cluster_colours[id]); - row_sizer->Add(cluster_color_icon_sizer, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, FromDIP(CONTENT_BORDER)); - // result_combox - create_result_button_sizer(row_panel, id); - row_sizer->Add(m_result_icon_list[id]->bitmap_combox, 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL, FromDIP(CONTENT_BORDER)); + row_sizer->Add(cluster_color_icon_sizer, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); + row_sizer->AddStretchSpacer(); + row_sizer->Add(create_result_button_sizer(row_panel, id), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(CONTENT_BORDER)); } } row_height = row_panel->GetSize().GetHeight(); @@ -717,6 +804,7 @@ void ObjColorPanel::draw_table() m_scrolledWindow->EnableScrolling(false, true); m_scrolledWindow->ShowScrollbars(wxSHOW_SB_NEVER, wxSHOW_SB_DEFAULT);//wxSHOW_SB_ALWAYS m_scrolledWindow->SetScrollRate(20, 20); + update_keep_color_buttons(); } void ObjColorPanel::deal_algo(char cluster_number, bool redraw_ui) @@ -761,64 +849,83 @@ void ObjColorPanel::deal_default_strategy() void ObjColorPanel::deal_add_btn() { - if (m_colours.size() > g_max_color) { return; } + if (m_colours.size() >= g_max_color) { return; } deal_reset_btn(); - std::vector new_icons; - auto new_color_size = m_cluster_colors_from_algo.size(); - new_icons.reserve(new_color_size); - m_new_add_colors.clear(); - m_new_add_colors.reserve(new_color_size); - int new_index = m_colours.size() + 1; bool is_exceed = false; - for (size_t i = 0; i < new_color_size; i++) { - if (m_colours.size() + new_icons.size() >= g_max_color) { + std::vector appended_selections; + appended_selections.reserve(m_cluster_colors_from_algo.size()); + for (size_t i = 0; i < m_cluster_colors_from_algo.size(); i++) { + const wxColour cur_color = convert_to_wxColour(m_cluster_colors_from_algo[i]); + const int selection = append_new_filament_option(cur_color); + if (selection == 0) { is_exceed = true; break; } - wxColour cur_color = convert_to_wxColour(m_cluster_colors_from_algo[i]); - m_new_add_colors.emplace_back(cur_color); - new_icons.emplace_back(get_extruder_color_icon(cur_color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString(), - std::to_string(new_index), m_combox_icon_width, m_combox_icon_height)); - new_index++; - } - new_index = m_colours.size() + 1; - for (size_t i = 0; i < m_result_icon_list.size(); i++) { - auto item = m_result_icon_list[i]; - for (size_t k = 0; k < new_icons.size(); k++) { - item->bitmap_combox->Append(wxString::Format("%d", item->bitmap_combox->GetCount()), *new_icons[k]); - item->bitmap_combox->SetItemTooltip(item->bitmap_combox->GetCount() -1,m_new_add_colors[k].GetAsString(wxC2S_HTML_SYNTAX)); - } - item->bitmap_combox->SetSelection(new_index); - m_cluster_map_filaments[i] = new_index; - new_index++; + appended_selections.emplace_back(selection); } if (is_exceed) { deal_approximate_match_btn(); m_warning_text->SetLabelText(_L("Warning: The count of newly added and \ncurrent extruders exceeds 16.")); + return; } - m_is_add_filament = true; + + for (size_t i = 0; i < m_cluster_colours.size() && i < appended_selections.size(); i++) { + m_result_icon_list[i]->bitmap_combox->SetSelection(appended_selections[i]); + m_cluster_map_filaments[i] = appended_selections[i]; + } + + update_keep_color_buttons(); } void ObjColorPanel::deal_reset_btn() { - for (auto item : m_result_icon_list) { + for (size_t i = 0; i < m_result_icon_list.size(); ++i) { + auto *item = m_result_icon_list[i]; // delete redundant bitmap while (item->bitmap_combox->GetCount() > m_colours.size()+ 1) { item->bitmap_combox->DeleteOneItem(item->bitmap_combox->GetCount() - 1); } item->bitmap_combox->SetSelection(0); + if (i < m_cluster_map_filaments.size()) { + m_cluster_map_filaments[i] = 0; + } } - m_is_add_filament = false; m_new_add_colors.clear(); m_warning_text->SetLabelText(""); + update_keep_color_buttons(); } -void ObjColorPanel::create_result_button_sizer(wxWindow *parent, int id) +wxBoxSizer *ObjColorPanel::create_result_button_sizer(wxWindow *parent, int id) { for (size_t i = m_result_icon_list.size(); i < id + 1; i++) { m_result_icon_list.emplace_back(new ButtonState()); } + m_result_icon_list[id]->bitmap_combox = CreateEditorCtrl(parent,id); + auto *result_sizer = new wxBoxSizer(wxHORIZONTAL); + result_sizer->Add(m_result_icon_list[id]->bitmap_combox, 0, wxALIGN_CENTER_VERTICAL, 0); + + StateColor calc_btn_bg(std::pair(wxColour(0, 137, 123), StateColor::Pressed), std::pair(wxColour(38, 166, 154), StateColor::Hovered), + std::pair(wxColour(0, 150, 136), StateColor::Normal)); + StateColor calc_btn_bd(std::pair(wxColour(0, 150, 136), StateColor::Normal)); + StateColor calc_btn_text(std::pair(wxColour(255, 255, 254), StateColor::Normal)); + + auto *keep_color_btn = new Button(parent, _L("Keep color")); + keep_color_btn->SetToolTip(_L("Add this cluster color as a new filament.")); + keep_color_btn->SetFont(Label::Body_13); + keep_color_btn->SetMinSize(wxSize(FromDIP(88), FromDIP(24))); + keep_color_btn->SetCornerRadius(FromDIP(12)); + keep_color_btn->SetBackgroundColor(calc_btn_bg); + keep_color_btn->SetBorderColor(calc_btn_bd); + keep_color_btn->SetTextColor(calc_btn_text); + keep_color_btn->Bind(wxEVT_BUTTON, [this, id](wxCommandEvent &) { + deal_keep_color_btn(id); + }); + m_result_icon_list[id]->keep_color_btn = keep_color_btn; + + result_sizer->AddSpacer(FromDIP(8)); + result_sizer->Add(keep_color_btn, 0, wxALIGN_CENTER_VERTICAL, 0); + return result_sizer; } wxBoxSizer *ObjColorPanel::create_color_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour& color) diff --git a/src/slic3r/GUI/ObjColorDialog.hpp b/src/slic3r/GUI/ObjColorDialog.hpp index 6019035973..f6c74dee2b 100644 --- a/src/slic3r/GUI/ObjColorDialog.hpp +++ b/src/slic3r/GUI/ObjColorDialog.hpp @@ -31,8 +31,9 @@ public: void update_filament_ids(); struct ButtonState { - ComboBox* bitmap_combox{nullptr}; - bool is_map{false};//int id{0}; + ComboBox *bitmap_combox{nullptr}; + Button * keep_color_btn{nullptr}; + bool is_map{false}; // int id{0}; }; private: wxBoxSizer *create_approximate_match_btn_sizer(wxWindow *parent); @@ -40,7 +41,7 @@ private: wxBoxSizer *create_reset_btn_sizer(wxWindow *parent); wxBoxSizer *create_extruder_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour& color); std::string get_color_str(const wxColour &color); - void create_result_button_sizer(wxWindow *parent, int id); + wxBoxSizer *create_result_button_sizer(wxWindow *parent, int id); wxBoxSizer *create_color_icon_and_rgba_sizer(wxWindow *parent, int id, const wxColour& color); void update_color_icon_and_rgba_sizer(int id, const wxColour &color); ComboBox* CreateEditorCtrl(wxWindow *parent,int id); @@ -48,10 +49,15 @@ private: void show_sizer(wxSizer *sizer, bool show); void redraw_part_table(); void deal_approximate_match_btn(); + void deal_keep_color_btn(int id); void deal_add_btn(); void deal_reset_btn(); void deal_algo(char cluster_number,bool redraw_ui =false); void deal_default_strategy(); + int find_filament_selection_by_color(const wxColour &color) const; + int append_new_filament_option(const wxColour &color); + void update_keep_color_buttons(); + static bool colors_are_equal(const wxColour &lhs, const wxColour &rhs); private: //view ui wxScrolledWindow * m_scrolledWindow = nullptr; @@ -66,7 +72,7 @@ private: std::vector m_extruder_icon_list; std::vector m_color_cluster_icon_list;//need modeify std::vector m_color_cluster_text_list;//need modeify - std::vector m_row_sizer_list; // control show or not + std::vector m_row_sizer_list; // control show or not std::vector m_result_icon_list; int m_last_cluster_num{-1}; const int m_combox_width{50}; @@ -83,13 +89,11 @@ private: std::vector m_colours;//from project and show right std::vector m_cluster_map_filaments;//show middle std::vector m_cluster_colours;//from_algo and show left - bool m_can_add_filament{true}; std::vector m_new_add_colors; //algo result std::vector m_cluster_colors_from_algo; std::vector m_cluster_labels_from_algo; //result - bool m_is_add_filament{false}; unsigned char& m_first_extruder_id; std::vector &m_filament_ids; }; @@ -111,4 +115,4 @@ private: unsigned char & m_first_extruder_id; }; -#endif // _WIPE_TOWER_DIALOG_H_ \ No newline at end of file +#endif // _WIPE_TOWER_DIALOG_H_