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),
0, nullptr, wxCB_READONLY | CB_NO_DROP_ICON | CB_NO_TEXT);
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++)
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);
#ifdef __linux__
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
// 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_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:
DataViewBitmapText m_value;
std::function<bool()> can_create_editor_ctrl { 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
if (sels.Count() == 1) {
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;
}
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
//bool is_active_extruder = i == initial_extruder;
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") + ")" : "");
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);
}
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]() {
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,
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')
// toggle_printable_state();
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();
if (std::find(numbers.begin(), numbers.end(), key_char) != numbers.end()) {
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
// BBS
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");
new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id));
// 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);
new_volume->name = into_u8(name);
// set a default extruder value, since user can't add it manually
// BBS
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");
new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id));
new_volume->source.is_from_builtin_objects = true;
@ -4844,11 +4848,11 @@ void ObjectList::set_extruder_for_selected_items(const int extruder)
else
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) {
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
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");
}
}

View File

@ -349,6 +349,11 @@ void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= "
else if (m_type & itVolume && m_volume_type == ModelVolumeType::MODEL_PART) {
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 {
m_extruder_bmp = wxNullBitmap;
return;
@ -546,10 +551,20 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent
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),
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);
// 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;
ObjectDataViewModelNode* obj_node = static_cast<ObjectDataViewModelNode*>(obj_item.GetID());
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() : "");
}

View File

@ -462,6 +462,44 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
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*/)
{
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);
#endif
wxBitmap* get_default_extruder_color_icon(bool thin_icon = false);
std::vector<wxBitmap*> get_extruder_color_icons(bool thin_icon = false);
namespace Slic3r {