NEW: Official filament color selection approved

- Add a filament picker dialog for official color selection
- Enable displaying multiple filament colors in the picker dialog and preview sidebar
- Introduce two new config options:
  - `filament_multi_colors`
  - `filament_color_types`
  to both the application config and the 3MF config

jira: STUDIO-12346

Change-Id: I66f8c1ec9147df4f5948c8a329c1737551280e63
(cherry picked from commit 522dc0bbca49033a1ba9725ca7f6c3ea729691a6)
This commit is contained in:
fei2.fang
2025-06-12 21:12:23 +08:00
committed by Noisyfox
parent 5a1dc90e8c
commit 9ee76e4775
17 changed files with 1369 additions and 82 deletions

View File

@@ -3,6 +3,7 @@
#include <cstddef>
#include <vector>
#include <string>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <wx/sizer.h>
@@ -41,6 +42,8 @@
#include "SavePresetDialog.hpp"
#include "MsgDialog.hpp"
#include "ParamsDialog.hpp"
#include "FilamentPickerDialog.hpp"
#include "wxExtensions.hpp"
// A workaround for a set of issues related to text fitting into gtk widgets:
#if defined(__WXGTK20__) || defined(__WXGTK3__)
@@ -219,6 +222,8 @@ int PresetComboBox::update_ams_color()
if (m_filament_idx < 0) return -1;
int idx = selected_ams_filament();
std::string color;
std::string ctype;
std::vector<std::string> colors;
if (idx < 0) {
auto name = Preset::remove_suffix_modified(GetValue().ToUTF8().data());
auto *preset = m_collection->find_preset(name);
@@ -233,12 +238,30 @@ int PresetComboBox::update_ams_color()
return -1;
}
color = iter->second.opt_string("filament_colour", 0u);
ctype = iter->second.opt_string("filament_colour_type", 0u);
colors = iter->second.opt<ConfigOptionStrings>("filament_multi_colour")->values;
}
DynamicPrintConfig *cfg = &wxGetApp().preset_bundle->project_config;
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone());
colors->values[m_filament_idx] = color;
auto color_head = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone()); // single color (the first color if multi-color filament)
auto color_pack = static_cast<ConfigOptionStrings *>(cfg->option("filament_multi_colour")->clone()); // multi color (all colors in all kinds of filament)
auto color_type = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour_type")->clone()); // color type
color_head->values[m_filament_idx] = color;
color_type->values[m_filament_idx] = ctype;
std::string color_str = ""; // Translate multi color info to config storage format
for (auto &c : colors) {
if (c.empty()) continue;
color_str += c + " ";
}
if (color_str.empty()) color_str = color;
else color_str.erase(color_str.size() - 1);
color_pack->values[m_filament_idx] = color_str;
// Update color informations in config
DynamicPrintConfig new_cfg;
new_cfg.set_key_value("filament_colour", colors);
new_cfg.set_key_value("filament_colour", color_head);
new_cfg.set_key_value("filament_colour_type", color_type);
new_cfg.set_key_value("filament_multi_colour", color_pack);
cfg->apply(new_cfg);
wxGetApp().plater()->on_config_change(new_cfg);
//trigger the filament color changed
@@ -507,6 +530,7 @@ bool PresetComboBox::add_ams_filaments(std::string selected, bool alias_name)
}
const_cast<Preset&>(*iter).is_visible = true;
auto color = tray.opt_string("filament_colour", 0u);
auto multi_color = tray.opt<ConfigOptionStrings>("filament_multi_colour")->values;
wxBitmap bmp(*get_extruder_color_icon(color, name, icon_width, 16));
auto text = get_preset_name(*iter);
int item_id = Append(text, bmp.ConvertToImage(), &m_first_ams_filament + entry.first);
@@ -809,39 +833,48 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset
for (int i = 0; i < colors.size(); i++) {
m_clrData.SetCustomColour(i, string_to_wxColor(colors[i]));
}
wxColourDialog dialog(this, &m_clrData);
dialog.SetTitle(_L("Please choose the filament color"));
if ( dialog.ShowModal() == wxID_OK )
{
m_clrData = dialog.GetColourData();
if (colors.size() != CUSTOM_COLOR_COUNT) {
colors.resize(CUSTOM_COLOR_COUNT);
// Check if it's an official filament
auto fila_type = Preset::remove_suffix_modified(GetValue().ToUTF8().data());
bool is_official = boost::algorithm::starts_with(fila_type, "Bambu");
if (is_official) {
// Get filament_id from filament_presets
const std::string& preset_name = m_preset_bundle->filament_presets[m_filament_idx];
const Preset* selected_preset = m_collection->find_preset(preset_name);
wxString fila_id = selected_preset ? wxString::FromUTF8(selected_preset->filament_id) : "GFA00";
FilamentColor fila_color = get_cur_color_info();
// Show filament picker dialog
FilamentPickerDialog dialog(this, fila_id, fila_color, fila_type);
if (!dialog.IsDataLoaded()) {
// If FilamentPicker fails, fallback to default color picker
show_default_color_picker();
} else if (dialog.ShowModal() == wxID_OK) {
// Get selected filament color data
FilamentColor fila_color = dialog.GetSelectedFilamentColor();
// Check if we have valid color data
if (!fila_color.m_colors.empty()) {
// Convert to storage format
std::vector<std::string> colors;
for (const wxColour& color : fila_color.m_colors) {
colors.push_back(color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString());
}
bool is_gradient = (fila_color.m_color_type == FilamentColor::ColorType::GRADIENT_CLR);
this->sync_colour_config(colors, is_gradient);
} else {
// Fallback to basic color if no FilamentColor data
wxColour selected_color = dialog.GetSelectedColour();
if (selected_color.IsOk()) {
std::vector<std::string> color = {selected_color.GetAsString(wxC2S_HTML_SYNTAX).ToStdString()};
this->sync_colour_config(color, false);
}
}
}
for (int i = 0; i < CUSTOM_COLOR_COUNT; i++) {
colors[i] = color_to_string(m_clrData.GetCustomColour(i));
}
wxGetApp().app_config->save_custom_color_to_config(colors);
// get current color
DynamicPrintConfig* cfg = &wxGetApp().preset_bundle->project_config;
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone());
wxColour clr(colors->values[m_filament_idx]);
if (!clr.IsOk())
clr = wxColour(0, 0, 0); // Don't set alfa to transparence
colors->values[m_filament_idx] = m_clrData.GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
DynamicPrintConfig cfg_new = *cfg;
cfg_new.set_key_value("filament_colour", colors);
//wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
cfg->apply(cfg_new);
wxGetApp().plater()->update_project_dirty_from_presets();
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
update();
wxGetApp().plater()->on_config_change(cfg_new);
wxCommandEvent *evt = new wxCommandEvent(EVT_FILAMENT_COLOR_CHANGED);
evt->SetInt(m_filament_idx);
wxQueueEvent(wxGetApp().plater(), evt);
} else {
show_default_color_picker();
}
});
}
@@ -1066,13 +1099,8 @@ void PlaterPresetComboBox::update()
invalidate_selection();
const Preset* selected_filament_preset = nullptr;
std::string filament_color;
if (m_type == Preset::TYPE_FILAMENT)
{
//unsigned char rgb[3];
filament_color = m_preset_bundle->project_config.opt_string("filament_colour", (unsigned int) m_filament_idx);
wxColor clr(filament_color);
clr_picker->SetBackgroundColour(clr);
std::vector<wxBitmap *> bitmaps = get_extruder_color_icons(true);
if (m_filament_idx < bitmaps.size()) {
clr_picker->SetBitmap(*bitmaps[m_filament_idx]);
@@ -1160,7 +1188,6 @@ void PlaterPresetComboBox::update()
preset_filament_types[name] = preset.config.option<ConfigOptionStrings>("filament_type")->values.at(0);
}
}
wxBitmap* bmp = get_bmp(preset);
assert(bmp);
@@ -1332,7 +1359,7 @@ void PlaterPresetComboBox::update()
update_selection();
if (m_type == Preset::TYPE_FILAMENT) {
if (wxGetApp().plater()->is_same_printer_for_connected_and_selected(false)) {
if (wxGetApp().plater()->is_same_printer_for_connected_and_selected(false)) {
update_badge_according_flag();
}
}
@@ -1370,6 +1397,80 @@ void PlaterPresetComboBox::msw_rescale()
}
FilamentColor PlaterPresetComboBox::get_cur_color_info()
{
std::vector<std::string> filaments_multi_color = Slic3r::GUI::wxGetApp().plater()->get_filament_colors_render_info();
std::vector<std::string> filament_color_type = Slic3r::GUI::wxGetApp().plater()->get_filament_color_render_type();
std::string filament_color_info = filaments_multi_color[m_filament_idx];
std::vector<std::string> colors;
boost::split(colors, filament_color_info, boost::is_any_of(" "));
FilamentColor fila_color;
for (const std::string& color_str : colors) {
if (!color_str.empty()) {
wxColour color(color_str);
if (color.IsOk()) {
fila_color.m_colors.insert(color);
}
}
}
fila_color.EndSet(filament_color_type[m_filament_idx] == "0" ? 0 : 1);
return fila_color;
}
void PlaterPresetComboBox::show_default_color_picker()
{
wxColourDialog dialog(this, &m_clrData);
dialog.SetTitle(_L("Please choose the filament colour"));
if (dialog.ShowModal() == wxID_OK)
{
m_clrData = dialog.GetColourData();
std::vector<std::string> color = {m_clrData.GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString()};
this->sync_colour_config(color, false);
}
}
void PlaterPresetComboBox::sync_colour_config(const std::vector<std::string> &clrs, bool is_gradient)
{
DynamicPrintConfig *cfg = &wxGetApp().preset_bundle->project_config;
// Clone the string vector and patch the value at current extruder index.
auto multi_colour_opt = static_cast<ConfigOptionStrings *>(cfg->option("filament_multi_colour")->clone());
auto colour_type_opt = static_cast<ConfigOptionStrings *>(cfg->option("filament_colour_type")->clone());
auto colour_opt = static_cast<ConfigOptionStrings *>(cfg->option("filament_colour")->clone());
if (m_filament_idx >= multi_colour_opt->values.size()) multi_colour_opt->values.resize(m_filament_idx + 1);
if (m_filament_idx >= colour_type_opt->values.size()) colour_type_opt->values.resize(m_filament_idx + 1);
if (m_filament_idx >= colour_opt->values.size()) colour_opt->values.resize(m_filament_idx + 1);
std::string clr_str = "";
for(auto &clr : clrs) {
clr_str += clr + " ";
}
clr_str.pop_back();
multi_colour_opt->values[m_filament_idx] = clr_str;
colour_opt->values[m_filament_idx] = clrs[0];
colour_type_opt->values[m_filament_idx] = is_gradient ? "0" : "1";
DynamicPrintConfig cfg_new = *cfg;
cfg_new.set_key_value("filament_multi_colour", multi_colour_opt);
cfg_new.set_key_value("filament_colour", colour_opt);
cfg_new.set_key_value("filament_colour_type", colour_type_opt);
cfg->apply(cfg_new);
wxGetApp().plater()->update_project_dirty_from_presets();
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
update(); // refresh the preset combobox with new config
wxGetApp().plater()->on_config_change(cfg_new);
wxCommandEvent *evt = new wxCommandEvent(EVT_CALI_TRAY_CHANGED);
evt->SetInt(m_filament_idx);
wxQueueEvent(wxGetApp().plater(), evt);
}
// ---------------------------------
// *** TabPresetComboBox ***
// ---------------------------------