ENH: support default filament for modifier

1. set modifier's initial filament index to "default" (0)
2. allow to change modifier's filament index to "default"

Change-Id: I66e546e20fa5492532dd8733df5b0d38a92fd4d7
Signed-off-by: yifan.wu <yifan.wu@bambulab.com>
This commit is contained in:
yifan.wu 2022-11-19 22:08:27 +08:00 committed by Lane.Wei
parent 6d46ac98ba
commit 05a00edb79
7 changed files with 94 additions and 17 deletions

View File

@ -313,13 +313,18 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
labelRect.GetTopLeft(), wxSize(labelRect.GetWidth(), -1), labelRect.GetTopLeft(), wxSize(labelRect.GetWidth(), -1),
0, nullptr, wxCB_READONLY | CB_NO_DROP_ICON | CB_NO_TEXT); 0, nullptr, wxCB_READONLY | CB_NO_DROP_ICON | CB_NO_TEXT);
c_editor->GetDropDown().SetUseContentWidth(true); c_editor->GetDropDown().SetUseContentWidth(true);
// BBS
if (has_default_extruder && has_default_extruder())
c_editor->Append(_L("default"), *get_default_extruder_color_icon());
for (size_t i = 0; i < icons.size(); i++) 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]);
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); c_editor->SetSelection(atoi(data.GetText().c_str()) - 1);
#ifdef __linux__ #ifdef __linux__
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) { c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
// to avoid event propagation to other sidebar items // to avoid event propagation to other sidebar items

View File

@ -153,11 +153,13 @@ public:
void set_can_create_editor_ctrl_function(std::function<bool()> can_create_fn) { can_create_editor_ctrl = can_create_fn; } void set_can_create_editor_ctrl_function(std::function<bool()> can_create_fn) { can_create_editor_ctrl = can_create_fn; }
void set_default_extruder_idx(std::function<int()> default_extruder_idx_fn) { get_default_extruder_idx = default_extruder_idx_fn; } void set_default_extruder_idx(std::function<int()> default_extruder_idx_fn) { get_default_extruder_idx = default_extruder_idx_fn; }
void set_has_default_extruder(std::function<bool()> has_default_extruder_fn) { has_default_extruder = has_default_extruder_fn; }
private: private:
DataViewBitmapText m_value; DataViewBitmapText m_value;
std::function<bool()> can_create_editor_ctrl { nullptr }; std::function<bool()> can_create_editor_ctrl { nullptr };
std::function<int()> get_default_extruder_idx{ nullptr }; std::function<int()> get_default_extruder_idx{ nullptr };
std::function<bool()> has_default_extruder{ nullptr };
}; };

View File

@ -1436,22 +1436,34 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
int initial_extruder = -1; // negative value for multiple object/part selection int initial_extruder = -1; // negative value for multiple object/part selection
if (sels.Count() == 1) { if (sels.Count() == 1) {
const ModelConfig& config = obj_list()->get_item_config(sels[0]); const ModelConfig& config = obj_list()->get_item_config(sels[0]);
// BBS: set default extruder to 1 // BBS
const auto sel_vol = obj_list()->get_selected_model_volume();
if (sel_vol && sel_vol->type() == ModelVolumeType::PARAMETER_MODIFIER)
initial_extruder = config.has("extruder") ? config.extruder() : 0;
else
initial_extruder = config.has("extruder") ? config.extruder() : 1; initial_extruder = config.has("extruder") ? config.extruder() : 1;
} }
for (int i = 1; i <= filaments_cnt; i++) // BBS
bool has_modifier = false;
for (auto sel : sels) {
if (obj_list()->GetModel()->GetVolumeType(sel) == ModelVolumeType::PARAMETER_MODIFIER) {
has_modifier = true;
break;
}
}
for (int i = has_modifier ? 0 : 1; i <= filaments_cnt; i++)
{ {
// BBS // BBS
//bool is_active_extruder = i == initial_extruder; //bool is_active_extruder = i == initial_extruder;
bool is_active_extruder = false; bool is_active_extruder = false;
int icon_idx = i == 0 ? 0 : i - 1;
const wxString& item_name = wxString::Format(_L("Filament %d"), i) + const wxString& item_name = (i == 0 ? _L("Default") : wxString::Format(_L("Filament %d"), i)) +
(is_active_extruder ? " (" + _L("current") + ")" : ""); (is_active_extruder ? " (" + _L("current") + ")" : "");
append_menu_item(extruder_selection_menu, wxID_ANY, item_name, "", append_menu_item(extruder_selection_menu, wxID_ANY, item_name, "",
[i](wxCommandEvent&) { obj_list()->set_extruder_for_selected_items(i); }, *icons[icon_idx], menu, [i](wxCommandEvent&) { obj_list()->set_extruder_for_selected_items(i); }, i == 0 ? wxNullBitmap : *icons[i - 1], menu,
[is_active_extruder]() { return !is_active_extruder; }, m_parent); [is_active_extruder]() { return !is_active_extruder; }, m_parent);
} }
menu->Append(wxID_ANY, name, extruder_selection_menu, _L("Change Filament")); menu->Append(wxID_ANY, name, extruder_selection_menu, _L("Change Filament"));

View File

@ -354,6 +354,9 @@ void ObjectList::create_objects_ctrl()
bmp_choice_renderer->set_default_extruder_idx([this]() { bmp_choice_renderer->set_default_extruder_idx([this]() {
return m_objects_model->GetDefaultExtruderIdx(GetSelection()); return m_objects_model->GetDefaultExtruderIdx(GetSelection());
}); });
bmp_choice_renderer->set_has_default_extruder([this]() {
return m_objects_model->GetVolumeType(GetSelection()) == ModelVolumeType::PARAMETER_MODIFIER;
});
AppendColumn(new wxDataViewColumn(_L("Fila."), bmp_choice_renderer, AppendColumn(new wxDataViewColumn(_L("Fila."), bmp_choice_renderer,
colFilament, m_columns_width[colFilament] * em, wxALIGN_CENTER_HORIZONTAL, 0)); colFilament, m_columns_width[colFilament] * em, wxALIGN_CENTER_HORIZONTAL, 0));
@ -1367,7 +1370,7 @@ void ObjectList::key_event(wxKeyEvent& event)
//else if (event.GetUnicodeKey() == 'p') //else if (event.GetUnicodeKey() == 'p')
// toggle_printable_state(); // toggle_printable_state();
else if (filaments_count() > 1) { else if (filaments_count() > 1) {
std::vector<wxChar> numbers = { '1', '2', '3', '4', '5', '6', '7', '8', '9' }; std::vector<wxChar> numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
wxChar key_char = event.GetUnicodeKey(); wxChar key_char = event.GetUnicodeKey();
if (std::find(numbers.begin(), numbers.end(), key_char) != numbers.end()) { if (std::find(numbers.begin(), numbers.end(), key_char) != numbers.end()) {
long extruder_number; long extruder_number;
@ -1846,7 +1849,7 @@ void ObjectList::load_modifier(const wxArrayString& input_files, ModelObject& mo
// set a default extruder value, since user can't add it manually // set a default extruder value, since user can't add it manually
// BBS // BBS
int extruder_id = 0; int extruder_id = 0;
if (model_object.config.has("extruder")) if (new_volume->type() == ModelVolumeType::MODEL_PART && model_object.config.has("extruder"))
extruder_id = model_object.config.opt_int("extruder"); extruder_id = model_object.config.opt_int("extruder");
new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id)); new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id));
// update source data // update source data
@ -1949,10 +1952,11 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
const wxString name = _L("Generic") + "-" + _(type_name); const wxString name = _L("Generic") + "-" + _(type_name);
new_volume->name = into_u8(name); new_volume->name = into_u8(name);
// set a default extruder value, since user can't add it manually // set a default extruder value, since user can't add it manually
// BBS // BBS
int extruder_id = 0; int extruder_id = 0;
if (model_object.config.has("extruder")) if (new_volume->type() == ModelVolumeType::MODEL_PART && model_object.config.has("extruder"))
extruder_id = model_object.config.opt_int("extruder"); extruder_id = model_object.config.opt_int("extruder");
new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id)); new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id));
new_volume->source.is_from_builtin_objects = true; new_volume->source.is_from_builtin_objects = true;
@ -4844,11 +4848,11 @@ void ObjectList::set_extruder_for_selected_items(const int extruder)
else else
config.set_key_value("extruder", new ConfigOptionInt(extruder)); config.set_key_value("extruder", new ConfigOptionInt(extruder));
// for object, clear all its volume's extruder config // for object, clear all its part volume's extruder config
if (type & itObject) { if (type & itObject) {
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
for (ModelVolume* mv : node->m_model_object->volumes) { for (ModelVolume* mv : node->m_model_object->volumes) {
if (mv->config.has("extruder")) if (mv->type() == ModelVolumeType::MODEL_PART && mv->config.has("extruder"))
mv->config.erase("extruder"); mv->config.erase("extruder");
} }
} }

View File

@ -349,6 +349,11 @@ void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= "
else if (m_type & itVolume && m_volume_type == ModelVolumeType::MODEL_PART) { else if (m_type & itVolume && m_volume_type == ModelVolumeType::MODEL_PART) {
extruder_idx = atoi(m_parent->GetExtruder().c_str()); extruder_idx = atoi(m_parent->GetExtruder().c_str());
} }
// BBS
else if (m_type & itVolume && m_volume_type == ModelVolumeType::PARAMETER_MODIFIER) {
m_extruder_bmp = *get_default_extruder_color_icon();
return;
}
else { else {
m_extruder_bmp = wxNullBitmap; m_extruder_bmp = wxNullBitmap;
return; return;
@ -546,10 +551,20 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent
if (insert_position >= 0) insert_position++; if (insert_position >= 0) insert_position++;
} }
wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder); // BBS
wxString extruder_str;
if (extruder == 0) {
if (volume_type == ModelVolumeType::PARAMETER_MODIFIER)
extruder_str = _L("default");
else
extruder_str = root->m_extruder;
}
else {
extruder_str = wxString::Format("%d", extruder);
}
const auto node = new ObjectDataViewModelNode(root, name, volume_type, GetVolumeIcon(volume_type, warning_icon_name), const auto node = new ObjectDataViewModelNode(root, name, volume_type, GetVolumeIcon(volume_type, warning_icon_name),
extruder == 0 ? root->m_extruder : extruder_str, root->m_volumes_cnt, warning_icon_name); extruder_str, root->m_volumes_cnt, warning_icon_name);
insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position); insert_position < 0 ? root->Append(node) : root->Insert(node, insert_position);
// if part with errors is added, but object wasn't marked, then mark it // if part with errors is added, but object wasn't marked, then mark it
@ -1378,7 +1393,7 @@ void ObjectDataViewModel::UpdateVolumesExtruderBitmap(wxDataViewItem obj_item, b
return; return;
ObjectDataViewModelNode* obj_node = static_cast<ObjectDataViewModelNode*>(obj_item.GetID()); ObjectDataViewModelNode* obj_node = static_cast<ObjectDataViewModelNode*>(obj_item.GetID());
for (auto child : obj_node->GetChildren()) for (auto child : obj_node->GetChildren())
if (child->GetVolumeType() == ModelVolumeType::MODEL_PART || child->GetVolumeType() == ModelVolumeType::PARAMETER_MODIFIER) if (child->GetVolumeType() == ModelVolumeType::MODEL_PART)
child->UpdateExtruderAndColorIcon(use_obj_extruder ? obj_node->GetExtruder() : ""); child->UpdateExtruderAndColorIcon(use_obj_extruder ? obj_node->GetExtruder() : "");
} }

View File

@ -462,6 +462,44 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
return *bmp; return *bmp;
} }
wxBitmap* get_default_extruder_color_icon(bool thin_icon/* = false*/)
{
static Slic3r::GUI::BitmapCache bmp_cache;
const double em = Slic3r::GUI::wxGetApp().em_unit();
const int icon_width = lround((thin_icon ? 2 : 4.5) * em);
const int icon_height = lround(2 * em);
bool dark_mode = Slic3r::GUI::wxGetApp().dark_mode();
wxClientDC cdc((wxWindow*)Slic3r::GUI::wxGetApp().mainframe);
wxMemoryDC dc(&cdc);
dc.SetFont(::Label::Body_12);
wxString label = _L("default");
std::string bitmap_key = std::string("default_color") + "-h" + std::to_string(icon_height) + "-w" + std::to_string(icon_width)
+ "-i" + label.ToStdString();
wxBitmap* bitmap = bmp_cache.find(bitmap_key);
if (bitmap == nullptr) {
// Paint the color icon.
//Slic3r::GUI::BitmapCache::parse_color(color, rgb);
// there is no neede to scale created solid bitmap
wxColor clr(255, 255, 255, 0);
bitmap = bmp_cache.insert(bitmap_key, wxBitmap(icon_width, icon_height));
dc.SelectObject(*bitmap);
dc.SetBackground(wxBrush(clr));
dc.Clear();
dc.SetBrush(wxBrush(clr));
dc.SetPen(*wxGREY_PEN);
auto size = dc.GetTextExtent(wxString(label));
dc.SetTextForeground(clr.GetLuminance() < 0.51 ? *wxWHITE : *wxBLACK);
dc.DrawText(label, (icon_width - size.x) / 2, (icon_height - size.y) / 2);
dc.SelectObject(wxNullBitmap);
}
return bitmap;
}
std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon/* = false*/) std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon/* = false*/)
{ {
static Slic3r::GUI::BitmapCache bmp_cache; static Slic3r::GUI::BitmapCache bmp_cache;

View File

@ -64,6 +64,7 @@ wxBitmap create_scaled_bitmap(const std::string& bmp_name, wxWindow *win = nullp
const int px_cnt = 16, const bool grayscale = false, const bool resize = false); const int px_cnt = 16, const bool grayscale = false, const bool resize = false);
#endif #endif
wxBitmap* get_default_extruder_color_icon(bool thin_icon = false);
std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon = false); std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon = false);
namespace Slic3r { namespace Slic3r {