mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-24 09:23:27 +00:00
Improve virtual color namings and added for parts
This commit is contained in:
@@ -1479,6 +1479,60 @@ std::string compute_mixed_filament_display_color(const MixedFilament &entry, con
|
||||
mix_b);
|
||||
}
|
||||
|
||||
std::string mixed_filament_standardized_name(const MixedFilament &entry, size_t num_physical)
|
||||
{
|
||||
const std::string normalized_pattern = MixedFilamentManager::normalize_manual_pattern(entry.manual_pattern);
|
||||
if (!normalized_pattern.empty()) {
|
||||
const std::string flattened = flatten_manual_pattern_groups(normalized_pattern);
|
||||
return std::string("Pattern ") + (flattened.empty() ? normalized_pattern : flattened);
|
||||
}
|
||||
|
||||
std::vector<std::pair<unsigned int, int>> parts;
|
||||
parts.reserve(4);
|
||||
auto append_part = [&parts](unsigned int component_id, int percent) {
|
||||
if (component_id == 0 || percent <= 0)
|
||||
return;
|
||||
for (auto &part : parts) {
|
||||
if (part.first == component_id) {
|
||||
part.second += percent;
|
||||
return;
|
||||
}
|
||||
}
|
||||
parts.emplace_back(component_id, percent);
|
||||
};
|
||||
|
||||
const std::vector<unsigned int> gradient_ids = decode_gradient_component_ids(entry.gradient_component_ids, num_physical);
|
||||
if (gradient_ids.size() >= 3) {
|
||||
std::vector<int> weights = decode_gradient_component_weights(entry.gradient_component_weights, gradient_ids.size());
|
||||
if (weights.empty())
|
||||
weights.assign(gradient_ids.size(), 1);
|
||||
const std::vector<int> percentages = normalize_weight_vector_to_percent(weights);
|
||||
for (size_t idx = 0; idx < gradient_ids.size() && idx < percentages.size(); ++idx)
|
||||
append_part(gradient_ids[idx], percentages[idx]);
|
||||
} else {
|
||||
const unsigned int component_a = (entry.component_a >= 1 && entry.component_a <= num_physical)
|
||||
? entry.component_a
|
||||
: 1;
|
||||
const unsigned int component_b = (entry.component_b >= 1 && entry.component_b <= num_physical)
|
||||
? entry.component_b
|
||||
: component_a;
|
||||
const int pct_b = clamp_int(entry.mix_b_percent, 0, 100);
|
||||
append_part(component_a, 100 - pct_b);
|
||||
append_part(component_b, pct_b);
|
||||
}
|
||||
|
||||
if (parts.empty())
|
||||
return "1:100%";
|
||||
|
||||
std::ostringstream out;
|
||||
for (size_t idx = 0; idx < parts.size(); ++idx) {
|
||||
if (idx > 0)
|
||||
out << " + ";
|
||||
out << parts[idx].first << ':' << parts[idx].second << '%';
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// MixedFilamentManager
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -144,6 +144,11 @@ std::pair<int, int> mixed_filament_apparent_pair_percentages(const MixedFilament
|
||||
bool bias_mode_enabled);
|
||||
std::string compute_mixed_filament_display_color(const MixedFilament &entry, const MixedFilamentDisplayContext &context);
|
||||
|
||||
// Build a standardized user-facing mixed filament name.
|
||||
// - Pattern rows: "Pattern <flattened pattern>" (for example "Pattern 1212354").
|
||||
// - Mix rows: "<id>:<pct>% + <id>:<pct>% ..." (for example "1:30% + 2:20% + 3:50%").
|
||||
std::string mixed_filament_standardized_name(const MixedFilament &entry, size_t num_physical);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// MixedFilamentManager
|
||||
//
|
||||
|
||||
@@ -263,6 +263,33 @@ bool BitmapChoiceRenderer::GetValue(wxVariant& value) const
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::vector<wxBitmap*> mixed_aware_extruder_icons(bool thin_icon = false)
|
||||
{
|
||||
std::vector<wxBitmap*> icons = get_extruder_color_icons(thin_icon);
|
||||
|
||||
if (Slic3r::GUI::wxGetApp().plater() == nullptr)
|
||||
return icons;
|
||||
|
||||
const std::vector<std::string> all_colors =
|
||||
Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(nullptr, true);
|
||||
if (all_colors.size() <= icons.size())
|
||||
return icons;
|
||||
|
||||
const double em = Slic3r::GUI::wxGetApp().em_unit();
|
||||
const int icon_width = int((thin_icon ? 2.0 : 4.4) * em + 0.5);
|
||||
const int icon_height = int(2.0 * em + 0.5);
|
||||
for (size_t idx = icons.size(); idx < all_colors.size(); ++idx) {
|
||||
if (all_colors[idx].empty()) {
|
||||
icons.push_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
icons.push_back(get_extruder_color_icon(all_colors[idx], std::to_string(idx + 1), icon_width, icon_height));
|
||||
}
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
||||
bool BitmapChoiceRenderer::Render(wxRect rect, wxDC* dc, int state)
|
||||
{
|
||||
const wxBitmap& icon = m_value.GetBitmap();
|
||||
@@ -301,7 +328,7 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
|
||||
if (can_create_editor_ctrl && !can_create_editor_ctrl())
|
||||
return nullptr;
|
||||
|
||||
std::vector<wxBitmap*> icons = get_extruder_color_icons();
|
||||
std::vector<wxBitmap*> icons = mixed_aware_extruder_icons(false);
|
||||
if (icons.empty())
|
||||
return nullptr;
|
||||
|
||||
@@ -317,12 +344,14 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
|
||||
c_editor->Append(_L("default"), *get_default_extruder_color_icon());
|
||||
|
||||
for (size_t i = 0; i < icons.size(); i++)
|
||||
c_editor->Append(wxString::Format("%d", i+1), *icons[i]);
|
||||
c_editor->Append(wxString::Format("%d", i + 1), icons[i] ? *icons[i] : wxNullBitmap);
|
||||
|
||||
if (has_default_extruder && has_default_extruder())
|
||||
c_editor->SetSelection(atoi(data.GetText().c_str()));
|
||||
else
|
||||
c_editor->SetSelection(atoi(data.GetText().c_str()) - 1);
|
||||
int selection = (has_default_extruder && has_default_extruder())
|
||||
? atoi(data.GetText().c_str())
|
||||
: atoi(data.GetText().c_str()) - 1;
|
||||
if (selection < 0 || selection >= int(c_editor->GetCount()))
|
||||
selection = 0;
|
||||
c_editor->SetSelection(selection);
|
||||
|
||||
c_editor->Bind(wxEVT_SET_FOCUS, [c_editor](wxFocusEvent& evt) {
|
||||
#ifdef __WXGTK__
|
||||
|
||||
@@ -56,7 +56,7 @@ static std::vector<unsigned int> ui_ordered_filament_ids()
|
||||
return wxGetApp().plater()->sidebar().get_ui_ordered_filament_ids();
|
||||
}
|
||||
|
||||
static wxString filament_menu_item_name(const int filament_id_1based, const int display_filament_id_1based)
|
||||
static wxString filament_menu_item_name(const int filament_id_1based)
|
||||
{
|
||||
if (filament_id_1based <= 0)
|
||||
return _L("Default");
|
||||
@@ -76,7 +76,12 @@ static wxString filament_menu_item_name(const int filament_id_1based, const int
|
||||
return wxString::Format(_L("Filament %d"), filament_id_1based);
|
||||
}
|
||||
|
||||
return wxString::Format(_L("Mixed Filament %d"), display_filament_id_1based);
|
||||
const auto &mgr = wxGetApp().preset_bundle->mixed_filaments;
|
||||
const MixedFilament *mixed = mgr.mixed_filament_from_id(unsigned(filament_id_1based), size_t(physical));
|
||||
if (mixed == nullptr)
|
||||
return _L("Mixed Filament");
|
||||
|
||||
return from_u8(mixed_filament_standardized_name(*mixed, size_t(physical)));
|
||||
}
|
||||
|
||||
static bool is_improper_category(const std::string& category, const int filaments_cnt, const bool is_object_settings = true)
|
||||
@@ -1108,7 +1113,7 @@ void MenuFactory::append_menu_item_change_extruder(wxMenu* menu)
|
||||
const bool is_active_extruder = actual_filament_id == initial_extruder;
|
||||
const int icon_idx = actual_filament_id == 0 ? 0 : actual_filament_id - 1;
|
||||
|
||||
wxString item_name = filament_menu_item_name(actual_filament_id, int(display_idx));
|
||||
wxString item_name = filament_menu_item_name(actual_filament_id);
|
||||
|
||||
if (is_active_extruder) {
|
||||
item_name << " (" + _L("current") + ")";
|
||||
@@ -2286,7 +2291,7 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
|
||||
const int actual_filament_id = display_idx == 0 ? 0 : int(ordered_filament_ids[display_idx - 1]);
|
||||
bool is_active_extruder = false;
|
||||
|
||||
wxString item_name = filament_menu_item_name(actual_filament_id, int(display_idx));
|
||||
wxString item_name = filament_menu_item_name(actual_filament_id);
|
||||
|
||||
if (is_active_extruder) {
|
||||
item_name << " (" + _L("current") + ")";
|
||||
|
||||
@@ -6551,9 +6551,9 @@ void ObjectList::OnEditingDone(wxDataViewEvent &event)
|
||||
// BBS: remove "const" qualifier
|
||||
void ObjectList::set_extruder_for_selected_items(const int extruder)
|
||||
{
|
||||
// BBS: check extruder id
|
||||
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
if (extruder > colors.size())
|
||||
// Accept any configured filament id, including mixed virtual filaments.
|
||||
const int max_filaments = filaments_count();
|
||||
if (extruder < 0 || extruder > max_filaments)
|
||||
return;
|
||||
|
||||
wxDataViewItemArray sels;
|
||||
|
||||
@@ -2804,13 +2804,28 @@ int ObjectTablePanel::init_bitmap()
|
||||
m_undo_bitmap = create_scaled_bitmap("lock_normal", nullptr, 18);
|
||||
m_color_bitmaps = get_extruder_color_icons();
|
||||
|
||||
const std::vector<std::string> all_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(nullptr, true);
|
||||
if (all_colors.size() > m_color_bitmaps.size()) {
|
||||
const double em = wxGetApp().em_unit();
|
||||
const int icon_width = int(4.4 * em + 0.5);
|
||||
const int icon_height = int(2.0 * em + 0.5);
|
||||
for (size_t idx = m_color_bitmaps.size(); idx < all_colors.size(); ++idx) {
|
||||
if (all_colors[idx].empty()) {
|
||||
m_color_bitmaps.push_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
m_color_bitmaps.push_back(get_extruder_color_icon(all_colors[idx], std::to_string(idx + 1), icon_width, icon_height));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ObjectTablePanel::init_filaments_and_colors()
|
||||
{
|
||||
const std::vector<std::string> filament_presets = wxGetApp().preset_bundle->filament_presets;
|
||||
const std::vector<std::string> filament_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
|
||||
const std::vector<std::string> filament_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(nullptr, true);
|
||||
m_filaments_count = filament_colors.size();
|
||||
if (m_filaments_count <= 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", can not get filaments, count: %1%, set to default") % m_filaments_count;
|
||||
@@ -2844,9 +2859,9 @@ int ObjectTablePanel::init_filaments_and_colors()
|
||||
continue;
|
||||
}
|
||||
|
||||
m_filaments_name[i] = wxString::Format("%d: Mixed Filament %d (F%u + F%u)",
|
||||
i + 1, i + 1,
|
||||
unsigned(mf.component_a), unsigned(mf.component_b));
|
||||
m_filaments_name[i] = wxString::Format("%d: %s",
|
||||
i + 1,
|
||||
from_u8(mixed_filament_standardized_name(mf, physical_count)));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -423,15 +423,31 @@ void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= "
|
||||
}
|
||||
}
|
||||
|
||||
const size_t extruder_id_1based = extruder_idx;
|
||||
if (extruder_idx > 0) --extruder_idx;
|
||||
|
||||
// Create the bitmap with color bars.
|
||||
std::vector<wxBitmap*> bmps = get_extruder_color_icons(false);// use wide icons
|
||||
if (bmps.empty()) {
|
||||
m_extruder_bmp = wxNullBitmap;
|
||||
if (!bmps.empty() && extruder_idx < bmps.size()) {
|
||||
m_extruder_bmp = *bmps[extruder_idx];
|
||||
return;
|
||||
}
|
||||
|
||||
m_extruder_bmp = *bmps[extruder_idx >= bmps.size() ? 0 : extruder_idx];
|
||||
// Fallback for mixed virtual filaments when the shared icon vector only covers physical filaments.
|
||||
if (wxGetApp().plater() != nullptr) {
|
||||
const std::vector<std::string> all_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(nullptr, true);
|
||||
if (extruder_id_1based >= 1 && extruder_id_1based <= all_colors.size() && !all_colors[extruder_id_1based - 1].empty()) {
|
||||
const double em = wxGetApp().em_unit();
|
||||
const int icon_width = int(4.4 * em + 0.5);
|
||||
const int icon_height = int(2.0 * em + 0.5);
|
||||
if (wxBitmap *bmp = get_extruder_color_icon(all_colors[extruder_id_1based - 1], std::to_string(extruder_id_1based), icon_width, icon_height)) {
|
||||
m_extruder_bmp = *bmp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_extruder_bmp = bmps.empty() ? wxNullBitmap : *bmps.front();
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
+25
-17
@@ -963,9 +963,17 @@ struct DynamicFilamentList : DynamicList
|
||||
return wxString::Format(_L("Filament %d"), int(filament_id_1based));
|
||||
}
|
||||
|
||||
static wxString mixed_filament_label()
|
||||
static wxString mixed_filament_label(unsigned int filament_id_1based, size_t num_physical)
|
||||
{
|
||||
return _L("Mixed Filament");
|
||||
if (wxGetApp().preset_bundle == nullptr)
|
||||
return _L("Mixed Filament");
|
||||
|
||||
const auto &mgr = wxGetApp().preset_bundle->mixed_filaments;
|
||||
const MixedFilament *mixed = mgr.mixed_filament_from_id(filament_id_1based, num_physical);
|
||||
if (mixed == nullptr)
|
||||
return _L("Mixed Filament");
|
||||
|
||||
return from_u8(mixed_filament_standardized_name(*mixed, num_physical));
|
||||
}
|
||||
|
||||
static wxBitmap *fallback_icon_from_color(unsigned int filament_id_1based,
|
||||
@@ -994,7 +1002,7 @@ struct DynamicFilamentList : DynamicList
|
||||
|
||||
wxString label = filament_id_1based <= num_physical
|
||||
? physical_filament_label(filament_id_1based)
|
||||
: mixed_filament_label();
|
||||
: mixed_filament_label(filament_id_1based, num_physical);
|
||||
|
||||
items.push_back({label, icon});
|
||||
filament_ids.push_back(int(filament_id_1based));
|
||||
@@ -4430,14 +4438,14 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
for (const std::string &hex : physical_colors)
|
||||
palette.emplace_back(parse_mixed_color(hex));
|
||||
|
||||
auto mixed_summary_text = [&mixed](size_t mixed_id) -> wxString {
|
||||
auto mixed_display_name = [&mixed, num_physical](size_t mixed_id) -> wxString {
|
||||
if (mixed_id >= mixed.size()) return wxString();
|
||||
const MixedFilament &entry = mixed[mixed_id];
|
||||
if (!entry.custom)
|
||||
return wxString::Format("(Filament %u + Filament %u)", unsigned(entry.component_a), unsigned(entry.component_b));
|
||||
const std::string normalized = MixedFilamentManager::normalize_manual_pattern(entry.manual_pattern);
|
||||
if (!normalized.empty()) return _L("(Pattern)");
|
||||
return wxString::Format("(F%u + F%u)", unsigned(entry.component_a), unsigned(entry.component_b));
|
||||
return from_u8(mixed_filament_standardized_name(entry, num_physical));
|
||||
};
|
||||
|
||||
auto mixed_summary_text = [](size_t) -> wxString {
|
||||
return wxString();
|
||||
};
|
||||
|
||||
auto apply_mixed_entry_changes = [this, preset_bundle, print_cfg, num_physical]
|
||||
@@ -4545,9 +4553,7 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
swatch->SetMinSize(wxSize(FromDIP(12), FromDIP(12)));
|
||||
header_sizer->Add(swatch, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, compact_gap_x);
|
||||
|
||||
const int virtual_filament_id = int(num_physical + display_idx + 1);
|
||||
auto *name_label = new wxStaticText(header_panel, wxID_ANY,
|
||||
wxString::Format("Mixed Filament %d", virtual_filament_id));
|
||||
auto *name_label = new wxStaticText(header_panel, wxID_ANY, mixed_display_name(mixed_id));
|
||||
name_label->SetForegroundColour(mixed_text_fg);
|
||||
header_sizer->Add(name_label, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, compact_gap_x);
|
||||
|
||||
@@ -4642,9 +4648,9 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
};
|
||||
|
||||
auto ensure_editor = [this, mixed_id, num_physical, physical_colors, nozzle_diameters, palette,
|
||||
preview_settings, component_bias_enabled, preset_bundle,
|
||||
editor_host, editor_sizer, swatch, summary_label, header_panel, row,
|
||||
rows_scroller, mixed_summary_text, apply_mixed_entry_changes, &mixed]() {
|
||||
preview_settings, component_bias_enabled, preset_bundle,
|
||||
editor_host, editor_sizer, swatch, name_label, summary_label, header_panel, row,
|
||||
rows_scroller, mixed_display_name, mixed_summary_text, apply_mixed_entry_changes, &mixed]() {
|
||||
if (!preset_bundle || !editor_sizer || editor_sizer->GetItemCount() > 0) return;
|
||||
auto &mgr2 = preset_bundle->mixed_filaments;
|
||||
auto &mfs2 = mgr2.mixed_filaments();
|
||||
@@ -4653,14 +4659,16 @@ void Sidebar::update_mixed_filament_panel(bool sync_manager)
|
||||
editor_host, mixed_id, mfs2[mixed_id], num_physical,
|
||||
physical_colors, nozzle_diameters, palette, preview_settings,
|
||||
component_bias_enabled,
|
||||
[this, mixed_id, swatch, summary_label, header_panel, row, rows_scroller,
|
||||
mixed_summary_text, apply_mixed_entry_changes]
|
||||
[this, mixed_id, swatch, name_label, summary_label, header_panel, row, rows_scroller,
|
||||
mixed_display_name, mixed_summary_text, apply_mixed_entry_changes]
|
||||
(const MixedFilament &updated_mf) {
|
||||
apply_mixed_entry_changes(mixed_id, updated_mf, true);
|
||||
if (swatch) {
|
||||
swatch->SetBackgroundColour(parse_mixed_color(updated_mf.display_color));
|
||||
swatch->Refresh();
|
||||
}
|
||||
if (name_label)
|
||||
name_label->SetLabel(mixed_display_name(mixed_id));
|
||||
if (summary_label)
|
||||
summary_label->SetLabel(mixed_summary_text(mixed_id));
|
||||
if (header_panel) header_panel->Layout();
|
||||
|
||||
@@ -783,6 +783,24 @@ void apply_extruder_selector(Slic3r::GUI::BitmapComboBox** ctrl,
|
||||
bool use_thin_icon/* = false*/)
|
||||
{
|
||||
std::vector<wxBitmap*> icons = get_extruder_color_icons(use_thin_icon);
|
||||
if (dynamic_cast<Slic3r::GUI::ObjectList*>(parent) != nullptr && Slic3r::GUI::wxGetApp().plater() != nullptr) {
|
||||
const std::vector<std::string> all_colors =
|
||||
Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(nullptr, true);
|
||||
|
||||
if (all_colors.size() > icons.size()) {
|
||||
const double em = Slic3r::GUI::wxGetApp().em_unit();
|
||||
const int icon_width = int((use_thin_icon ? 2.0 : 4.4) * em + 0.5);
|
||||
const int icon_height = int(2.0 * em + 0.5);
|
||||
for (size_t idx = icons.size(); idx < all_colors.size(); ++idx) {
|
||||
if (all_colors[idx].empty()) {
|
||||
icons.push_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
icons.push_back(get_extruder_color_icon(all_colors[idx], std::to_string(idx + 1), icon_width, icon_height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!*ctrl) {
|
||||
*ctrl = new Slic3r::GUI::BitmapComboBox(parent, wxID_ANY, wxEmptyString, pos, size, 0, nullptr, wxCB_READONLY);
|
||||
@@ -811,13 +829,13 @@ void apply_extruder_selector(Slic3r::GUI::BitmapComboBox** ctrl,
|
||||
for (wxBitmap* bmp : icons) {
|
||||
if (i == 0) {
|
||||
if (!first_item.empty())
|
||||
(*ctrl)->Append(_(first_item), *bmp);
|
||||
(*ctrl)->Append(_(first_item), bmp ? *bmp : wxNullBitmap);
|
||||
++i;
|
||||
}
|
||||
|
||||
(*ctrl)->Append(use_full_item_name
|
||||
? Slic3r::GUI::from_u8((boost::format("%1% %2%") % str % i).str())
|
||||
: wxString::Format("%d", i), *bmp);
|
||||
: wxString::Format("%d", i), bmp ? *bmp : wxNullBitmap);
|
||||
++i;
|
||||
}
|
||||
(*ctrl)->SetSelection(0);
|
||||
|
||||
Reference in New Issue
Block a user