Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'xs/src/slic3r/GUI/GUI_ObjectParts.cpp')
-rw-r--r--xs/src/slic3r/GUI/GUI_ObjectParts.cpp669
1 files changed, 495 insertions, 174 deletions
diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
index 0c7b7a5d8..ae34359ce 100644
--- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
+++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp
@@ -13,6 +13,9 @@
#include "Geometry.hpp"
#include "slic3r/Utils/FixModelByWin10.hpp"
+#include <wx/glcanvas.h>
+#include "3DScene.hpp"
+
namespace Slic3r
{
namespace GUI
@@ -23,10 +26,12 @@ wxSizer *m_sizer_object_movers = nullptr;
wxDataViewCtrl *m_objects_ctrl = nullptr;
PrusaObjectDataViewModel *m_objects_model = nullptr;
wxCollapsiblePane *m_collpane_settings = nullptr;
+PrusaDoubleSlider *m_slider = nullptr;
+wxGLCanvas *m_preview_canvas = nullptr;
-wxIcon m_icon_modifiermesh;
-wxIcon m_icon_solidmesh;
-wxIcon m_icon_manifold_warning;
+wxBitmap m_icon_modifiermesh;
+wxBitmap m_icon_solidmesh;
+wxBitmap m_icon_manifold_warning;
wxBitmap m_bmp_cog;
wxBitmap m_bmp_split;
@@ -64,8 +69,6 @@ bool m_part_settings_changed = false;
wxString g_selected_extruder = "";
#endif //__WXOSX__
-// typedef std::map<std::string, std::string> t_category_icon;
-typedef std::map<std::string, wxBitmap> t_category_icon;
inline t_category_icon& get_category_icon() {
static t_category_icon CATEGORY_ICON;
if (CATEGORY_ICON.empty()){
@@ -138,11 +141,11 @@ void set_objects_from_model(Model &model) {
}
void init_mesh_icons(){
- m_icon_modifiermesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
- m_icon_solidmesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
+ m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
+ m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
// init icon for manifold warning
- m_icon_manifold_warning = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
+ m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
// init bitmap for "Split to sub-objects" context menu
m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG);
@@ -233,7 +236,7 @@ wxDataViewColumn* object_ctrl_create_extruder_column(int extruders_count)
void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz)
{
m_objects_ctrl = new wxDataViewCtrl(win, wxID_ANY, wxDefaultPosition, wxDefaultSize);
- m_objects_ctrl->SetInitialSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects
+ m_objects_ctrl->SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects
objects_sz = new wxBoxSizer(wxVERTICAL);
objects_sz->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20);
@@ -245,9 +248,10 @@ void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz)
m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT);
#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
- // column 0(Icon+Text) of the view control:
- m_objects_ctrl->AppendIconTextColumn(_(L("Name")), 0, wxDATAVIEW_CELL_INERT, 200,
- wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE);
+ // column 0(Icon+Text) of the view control:
+ // And Icon can be consisting of several bitmaps
+ m_objects_ctrl->AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(),
+ 0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE));
// column 1 of the view control:
m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45,
@@ -278,7 +282,7 @@ wxBoxSizer* create_objects_list(wxWindow *win)
m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) {
object_ctrl_context_menu();
- event.Skip();
+// event.Skip();
});
m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX
@@ -316,15 +320,15 @@ wxBoxSizer* create_edit_object_buttons(wxWindow* win)
//*** button's functions
btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&) {
- on_btn_load(win);
+// on_btn_load(win);
});
btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) {
- on_btn_load(win, true);
+// on_btn_load(win, true);
});
btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) {
- on_btn_load(win, true, true);
+// on_btn_load(win, true, true);
});
btn_delete ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_del(); });
@@ -660,7 +664,7 @@ void add_object_to_list(const std::string &name, ModelObject* model_object)
int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
stats.facets_added + stats.facets_reversed + stats.backwards_edges;
if (errors > 0) {
- const wxDataViewIconText data(item_name, m_icon_manifold_warning);
+ const PrusaDataViewBitmapText data(item_name, m_icon_manifold_warning);
wxVariant variant;
variant << data;
m_objects_model->SetValue(variant, item, 0);
@@ -724,15 +728,26 @@ void select_current_object(int idx)
{
g_prevent_list_events = true;
m_objects_ctrl->UnselectAll();
- if (idx < 0) {
- g_prevent_list_events = false;
- return;
- }
- m_objects_ctrl->Select(m_objects_model->GetItemById(idx));
+ if (idx>=0)
+ m_objects_ctrl->Select(m_objects_model->GetItemById(idx));
part_selection_changed();
g_prevent_list_events = false;
}
+void select_current_volume(int idx, int vol_idx)
+{
+ if (vol_idx < 0) {
+ select_current_object(idx);
+ return;
+ }
+ g_prevent_list_events = true;
+ m_objects_ctrl->UnselectAll();
+ if (idx >= 0)
+ m_objects_ctrl->Select(m_objects_model->GetItemByVolumeId(idx, vol_idx));
+ part_selection_changed();
+ g_prevent_list_events = false;
+}
+
void remove()
{
auto item = m_objects_ctrl->GetSelection();
@@ -758,8 +773,17 @@ void object_ctrl_selection_changed()
if (m_event_object_selection_changed > 0) {
wxCommandEvent event(m_event_object_selection_changed);
- event.SetInt(int(m_objects_model->GetParent(m_objects_ctrl->GetSelection()) != wxDataViewItem(0)));
- event.SetId(m_selected_object_id);
+ event.SetId(m_selected_object_id); // set $obj_idx
+ const wxDataViewItem item = m_objects_ctrl->GetSelection();
+ if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0))
+ event.SetInt(-1); // set $vol_idx
+ else {
+ const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
+ if (vol_idx == -2) // is settings item
+ event.SetInt(m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item))); // set $vol_idx
+ else
+ event.SetInt(vol_idx);
+ }
get_main_frame()->ProcessWindowEvent(event);
}
@@ -772,9 +796,9 @@ void object_ctrl_context_menu()
{
wxDataViewItem item;
wxDataViewColumn* col;
- printf("object_ctrl_context_menu\n");
+// printf("object_ctrl_context_menu\n");
const wxPoint pt = get_mouse_position_in_control();
- printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y);
+// printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y);
m_objects_ctrl->HitTest(pt, item, col);
if (!item)
#ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX
@@ -788,9 +812,9 @@ void object_ctrl_context_menu()
#else
return;
#endif // __WXOSX__
- printf("item exists\n");
+// printf("item exists\n");
const wxString title = col->GetTitle();
- printf("title = *%s*\n", title.data().AsChar());
+// printf("title = *%s*\n", title.data().AsChar());
if (title == " ")
show_context_menu();
@@ -836,6 +860,15 @@ void object_ctrl_item_value_change(wxDataViewEvent& event)
}
}
+void show_manipulation_og(const bool show)
+{
+ wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer();
+ if (show == grid_sizer->IsShown(2))
+ return;
+ for (size_t id = 2; id < 12; id++)
+ grid_sizer->Show(id, show);
+}
+
//update_optgroup
void update_settings_list()
{
@@ -856,14 +889,19 @@ void update_settings_list()
m_option_sizer->Clear(true);
- if (m_config)
+ bool show_manipulations = true;
+ const auto item = m_objects_ctrl->GetSelection();
+ if (m_config && m_objects_model->IsSettingsItem(item))
{
auto extra_column = [](wxWindow* parent, const Line& line)
{
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
- auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("erase.png")), wxBITMAP_TYPE_PNG),
+ auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG),
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
+#ifdef __WXMSW__
+ btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+#endif // __WXMSW__
btn->Bind(wxEVT_BUTTON, [opt_key](wxEvent &event){
(*m_config)->erase(opt_key);
wxTheApp->CallAfter([]() { update_settings_list(); });
@@ -873,60 +911,75 @@ void update_settings_list()
std::map<std::string, std::vector<std::string>> cat_options;
auto opt_keys = (*m_config)->keys();
- if (opt_keys.size() == 1 && opt_keys[0] == "extruder")
- return;
-
- auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
- get_preset_bundle()->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
-
- for (auto& opt_key : opt_keys) {
- auto category = (*m_config)->def()->get(opt_key)->category;
- if (category.empty() ||
- (category == "Extruders" && extruders_cnt==1)) continue;
-
- std::vector< std::string > new_category;
-
- auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category);
- cat_opt.push_back(opt_key);
- if (cat_opt.size() == 1)
- cat_options[category] = cat_opt;
- }
-
-
- m_og_settings.resize(0);
- for (auto& cat : cat_options) {
- if (cat.second.size() == 1 && cat.second[0] == "extruder")
- continue;
-
- auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, *m_config, false, ogDEFAULT, extra_column);
- optgroup->label_width = 100;
- optgroup->sidetext_width = 70;
+ m_og_settings.resize(0);
+ std::vector<std::string> categories;
+ if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder"))// return;
+ {
+ auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 :
+ get_preset_bundle()->printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
+
+ for (auto& opt_key : opt_keys) {
+ auto category = (*m_config)->def()->get(opt_key)->category;
+ if (category.empty() ||
+ (category == "Extruders" && extruders_cnt == 1)) continue;
+
+ std::vector< std::string > new_category;
+
+ auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category);
+ cat_opt.push_back(opt_key);
+ if (cat_opt.size() == 1)
+ cat_options[category] = cat_opt;
+ }
+
+ for (auto& cat : cat_options) {
+ if (cat.second.size() == 1 && cat.second[0] == "extruder")
+ continue;
+
+ auto optgroup = std::make_shared<ConfigOptionsGroup>(parent, cat.first, *m_config, false, ogDEFAULT, extra_column);
+ optgroup->label_width = 150;
+ optgroup->sidetext_width = 70;
+
+ for (auto& opt : cat.second)
+ {
+ if (opt == "extruder")
+ continue;
+ Option option = optgroup->get_option(opt);
+ option.opt.width = 70;
+ optgroup->append_single_option_line(option);
+ }
+ optgroup->reload_config();
+ m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0);
+ m_og_settings.push_back(optgroup);
+
+ categories.push_back(cat.first);
+ }
+ }
- for (auto& opt : cat.second)
- {
- if (opt == "extruder")
- continue;
- Option option = optgroup->get_option(opt);
- option.opt.width = 70;
- optgroup->append_single_option_line(option);
- }
- optgroup->reload_config();
- m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0);
- m_og_settings.push_back(optgroup);
- }
+ if (m_og_settings.empty()) {
+ m_objects_ctrl->Select(m_objects_model->Delete(item));
+ part_selection_changed();
+ }
+ else {
+ if (!categories.empty())
+ m_objects_model->UpdateSettingsDigest(item, categories);
+ show_manipulations = false;
+ }
}
+ show_manipulation_og(show_manipulations);
+ show_info_sizer(show_manipulations && item && m_objects_model->GetParent(item) == wxDataViewItem(0));
+
#ifdef __linux__
no_updates.reset(nullptr);
#endif
- /*get_right_panel()*/parent->Layout();
- get_right_panel()->GetParent()->GetParent()->Layout();
+ parent->Layout();
+ get_right_panel()->GetParent()->Layout();
}
void get_settings_choice(wxMenu *menu, int id, bool is_part)
{
- auto category_name = menu->GetLabel(id);
+ const auto category_name = menu->GetLabel(id);
wxArrayString names;
wxArrayInt selections;
@@ -974,15 +1027,35 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part)
(*m_config)->set_key_value(opt_key, m_default_config.get()->option(opt_key)->clone());
}
+
+ // Add settings item for object
+ const auto item = m_objects_ctrl->GetSelection();
+ if (item) {
+ const auto settings_item = m_objects_model->HasSettings(item);
+ m_objects_ctrl->Select(settings_item ? settings_item :
+ m_objects_model->AddSettingsChild(item));
+#ifndef __WXOSX__
+ part_selection_changed();
+#endif //no __WXOSX__
+ }
+ else
update_settings_list();
}
-bool cur_item_hase_children()
-{
- wxDataViewItemArray children;
- if (m_objects_model->GetChildren(m_objects_ctrl->GetSelection(), children) > 0)
- return true;
- return false;
+void menu_item_add_generic(wxMenuItem* &menu, int id) {
+ auto sub_menu = new wxMenu;
+
+ std::vector<std::string> menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") };
+ for (auto& item : menu_items)
+ sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item)));
+
+#ifndef __WXMSW__
+ sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) {
+ load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString());
+ });
+#endif //no __WXMSW__
+
+ menu->SetSubMenu(sub_menu);
}
wxMenuItem* menu_item_split(wxMenu* menu, int id) {
@@ -991,11 +1064,11 @@ wxMenuItem* menu_item_split(wxMenu* menu, int id) {
return menu_item;
}
-wxMenuItem* menu_item_settings(wxMenu* menu, int id) {
+wxMenuItem* menu_item_settings(wxMenu* menu, int id, const bool is_part) {
auto menu_item = new wxMenuItem(menu, id, _(L("Add settings")));
menu_item->SetBitmap(m_bmp_cog);
- auto sub_menu = create_add_settings_popupmenu(false);
+ auto sub_menu = create_add_settings_popupmenu(is_part);
menu_item->SetSubMenu(sub_menu);
return menu_item;
}
@@ -1005,44 +1078,54 @@ wxMenu *create_add_part_popupmenu()
wxMenu *menu = new wxMenu;
std::vector<std::string> menu_items = { L("Add part"), L("Add modifier"), L("Add generic") };
- wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+2);
+ wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+4+2);
int i = 0;
for (auto& item : menu_items) {
auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item));
menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh);
- menu->Append(menu_item);
+ if (item == "Add generic")
+ menu_item_add_generic(menu_item, config_id_base + i);
+ menu->Append(menu_item);
i++;
}
menu->AppendSeparator();
- auto menu_item = menu_item_split(menu, config_id_base + i);
+ auto menu_item = menu_item_split(menu, config_id_base + i + 4);
menu->Append(menu_item);
- menu_item->Enable(!cur_item_hase_children());
+ menu_item->Enable(is_splittable_object(false));
menu->AppendSeparator();
// Append settings popupmenu
- menu->Append(menu_item_settings(menu, config_id_base + i + 1));
-
- wxWindow* win = get_tab_panel()->GetPage(0);
+ menu->Append(menu_item_settings(menu, config_id_base + i + 5, false));
- menu->Bind(wxEVT_MENU, [config_id_base, win, menu](wxEvent &event){
+ menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){
switch (event.GetId() - config_id_base) {
case 0:
- on_btn_load(win);
+ on_btn_load();
break;
case 1:
- on_btn_load(win, true);
+ on_btn_load(true);
break;
case 2:
- on_btn_load(win, true, true);
+// on_btn_load(true, true);
break;
- case 3:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+#ifdef __WXMSW__
+ load_lambda(menu->GetLabel(event.GetId()).ToStdString());
+#endif // __WXMSW__
+ break;
+ case 7: //3:
on_btn_split(false);
break;
- default:{
+ default:
+#ifdef __WXMSW__
get_settings_choice(menu, event.GetId(), false);
- break;}
+#endif // __WXMSW__
+ break;
}
});
@@ -1054,11 +1137,13 @@ wxMenu *create_part_settings_popupmenu()
wxMenu *menu = new wxMenu;
wxWindowID config_id_base = wxWindow::NewControlId(2);
- menu->Append(menu_item_split(menu, config_id_base));
+ auto menu_item = menu_item_split(menu, config_id_base);
+ menu->Append(menu_item);
+ menu_item->Enable(is_splittable_object(true));
menu->AppendSeparator();
// Append settings popupmenu
- menu->Append(menu_item_settings(menu, config_id_base + 1));
+ menu->Append(menu_item_settings(menu, config_id_base + 1, true));
menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){
switch (event.GetId() - config_id_base) {
@@ -1090,35 +1175,35 @@ wxMenu *create_add_settings_popupmenu(bool is_part)
wxNullBitmap : categories.at(cat.first));
menu->Append(menu_item);
}
-
- menu->Bind(wxEVT_MENU, [menu](wxEvent &event) {
- get_settings_choice(menu, event.GetId(), true);
+#ifndef __WXMSW__
+ menu->Bind(wxEVT_MENU, [menu,is_part](wxEvent &event) {
+ get_settings_choice(menu, event.GetId(), is_part);
});
-
+#endif //no __WXMSW__
return menu;
}
void show_context_menu()
{
- auto item = m_objects_ctrl->GetSelection();
+ const auto item = m_objects_ctrl->GetSelection();
if (item)
{
- if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
- auto menu = create_add_part_popupmenu();
- get_tab_panel()->GetPage(0)->PopupMenu(menu);
- }
- else {
- auto menu = create_part_settings_popupmenu();
- get_tab_panel()->GetPage(0)->PopupMenu(menu);
- }
+ if (m_objects_model->IsSettingsItem(item))
+ return;
+ const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ?
+ create_add_part_popupmenu() :
+ create_part_settings_popupmenu();
+ get_tab_panel()->GetPage(0)->PopupMenu(menu);
}
}
// ******
-void load_part( wxWindow* parent, ModelObject* model_object,
+void load_part( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier)
{
+ wxWindow* parent = get_tab_panel()->GetPage(0);
+
wxArrayString input_files;
open_model(parent, input_files);
for (int i = 0; i < input_files.size(); ++i) {
@@ -1137,7 +1222,7 @@ void load_part( wxWindow* parent, ModelObject* model_object,
for ( auto object : model.objects) {
for (auto volume : object->volumes) {
auto new_volume = model_object->add_volume(*volume);
- new_volume->modifier = is_modifier;
+ new_volume->set_type(is_modifier ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART);
boost::filesystem::path(input_file).filename().string();
new_volume->name = boost::filesystem::path(input_file).filename().string();
@@ -1156,10 +1241,10 @@ void load_part( wxWindow* parent, ModelObject* model_object,
}
}
-void load_lambda( wxWindow* parent, ModelObject* model_object,
+void load_lambda( ModelObject* model_object,
wxArrayString& part_names, const bool is_modifier)
{
- auto dlg = new LambdaObjectDialog(parent);
+ auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow());
if (dlg->ShowModal() == wxID_CANCEL) {
return;
}
@@ -1195,7 +1280,8 @@ void load_lambda( wxWindow* parent, ModelObject* model_object,
mesh.repair();
auto new_volume = model_object->add_volume(mesh);
- new_volume->modifier = is_modifier;
+ new_volume->set_type(is_modifier ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART);
+
new_volume->name = name;
// set a default extruder value, since user can't add it manually
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
@@ -1205,7 +1291,50 @@ void load_lambda( wxWindow* parent, ModelObject* model_object,
m_parts_changed = true;
}
-void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/* = false*/)
+void load_lambda(const std::string& type_name)
+{
+ if (m_selected_object_id < 0) return;
+
+ auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name);
+ if (dlg->ShowModal() == wxID_CANCEL)
+ return;
+
+ const std::string name = "lambda-"+type_name;
+ TriangleMesh mesh;
+
+ const auto params = dlg->ObjectParameters();
+ if (type_name == _("Box"))
+ mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]);
+ else if (type_name == _("Cylinder"))
+ mesh = make_cylinder(params.cyl_r, params.cyl_h);
+ else if (type_name == _("Sphere"))
+ mesh = make_sphere(params.sph_rho);
+ else if (type_name == _("Slab")){
+ const auto& size = (*m_objects)[m_selected_object_id]->bounding_box().size();
+ mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h);
+ // box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z
+ mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z);
+ }
+ mesh.repair();
+
+ auto new_volume = (*m_objects)[m_selected_object_id]->add_volume(mesh);
+ new_volume->set_type(ModelVolume::PARAMETER_MODIFIER);
+
+ new_volume->name = name;
+ // set a default extruder value, since user can't add it manually
+ new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
+
+ m_parts_changed = true;
+ parts_changed(m_selected_object_id);
+
+ m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(),
+ name, m_icon_modifiermesh));
+#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
+ object_ctrl_selection_changed();
+#endif //no __WXOSX__ //__WXMSW__
+}
+
+void on_btn_load(bool is_modifier /*= false*/, bool is_lambda/* = false*/)
{
auto item = m_objects_ctrl->GetSelection();
if (!item)
@@ -1219,19 +1348,54 @@ void on_btn_load(wxWindow* parent, bool is_modifier /*= false*/, bool is_lambda/
if (obj_idx < 0) return;
wxArrayString part_names;
if (is_lambda)
- load_lambda(parent, (*m_objects)[obj_idx], part_names, is_modifier);
+ load_lambda((*m_objects)[obj_idx], part_names, is_modifier);
else
- load_part(parent, (*m_objects)[obj_idx], part_names, is_modifier);
+ load_part((*m_objects)[obj_idx], part_names, is_modifier);
parts_changed(obj_idx);
for (int i = 0; i < part_names.size(); ++i)
m_objects_ctrl->Select( m_objects_model->AddChild(item, part_names.Item(i),
is_modifier ? m_icon_modifiermesh : m_icon_solidmesh));
-// part_selection_changed();
-#ifdef __WXMSW__
+#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
object_ctrl_selection_changed();
-#endif //__WXMSW__
+#endif //no __WXOSX__//__WXMSW__
+}
+
+void remove_settings_from_config()
+{
+ auto opt_keys = (*m_config)->keys();
+ if (opt_keys.size() == 1 && opt_keys[0] == "extruder")
+ return;
+ int extruder = -1;
+ if ((*m_config)->has("extruder"))
+ extruder = (*m_config)->option<ConfigOptionInt>("extruder")->value;
+
+ (*m_config)->clear();
+
+ if (extruder >=0 )
+ (*m_config)->set_key_value("extruder", new ConfigOptionInt(extruder));
+}
+
+bool remove_subobject_from_object(const int volume_id)
+{
+ const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
+
+ // if user is deleting the last solid part, throw error
+ int solid_cnt = 0;
+ for (auto vol : (*m_objects)[m_selected_object_id]->volumes)
+ if (vol->is_model_part())
+ ++solid_cnt;
+ if (volume->is_model_part() && solid_cnt == 1) {
+ Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
+ return false;
+ }
+
+ (*m_objects)[m_selected_object_id]->delete_volume(volume_id);
+ m_parts_changed = true;
+
+ parts_changed(m_selected_object_id);
+ return true;
}
void on_btn_del()
@@ -1239,50 +1403,67 @@ void on_btn_del()
auto item = m_objects_ctrl->GetSelection();
if (!item) return;
- auto volume_id = m_objects_model->GetVolumeIdByItem(item);
- if (volume_id < 0)
+ const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
+ if (volume_id ==-1)
return;
- auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
-
- // if user is deleting the last solid part, throw error
- int solid_cnt = 0;
- for (auto vol : (*m_objects)[m_selected_object_id]->volumes)
- if (!vol->modifier)
- ++solid_cnt;
- if (!volume->modifier && solid_cnt == 1) {
- Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object.")));
- return;
- }
-
- (*m_objects)[m_selected_object_id]->delete_volume(volume_id);
- m_parts_changed = true;
-
- parts_changed(m_selected_object_id);
+
+ if (volume_id ==-2)
+ remove_settings_from_config();
+ else if (!remove_subobject_from_object(volume_id))
+ return;
m_objects_ctrl->Select(m_objects_model->Delete(item));
part_selection_changed();
-// #ifdef __WXMSW__
-// object_ctrl_selection_changed();
-// #endif //__WXMSW__
+}
+
+bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume)
+{
+ if (!item || m_selected_object_id < 0)
+ return false;
+ const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
+ if (volume_id < 0) {
+ if (split_part) return false;
+ volume = (*m_objects)[m_selected_object_id]->volumes[0];
+ }
+ else
+ volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
+ if (volume)
+ return true;
+ return false;
+}
+
+bool is_splittable_object(const bool split_part)
+{
+ const wxDataViewItem item = m_objects_ctrl->GetSelection();
+ if (!item) return false;
+
+ wxDataViewItemArray children;
+ if (!split_part && m_objects_model->GetChildren(item, children) > 0)
+ return false;
+
+ ModelVolume* volume;
+ if (!get_volume_by_item(split_part, item, volume) || !volume)
+ return false;
+
+ TriangleMeshPtrs meshptrs = volume->mesh.split();
+ if (meshptrs.size() <= 1) {
+ delete meshptrs.front();
+ return false;
+ }
+
+ return true;
}
void on_btn_split(const bool split_part)
{
- auto item = m_objects_ctrl->GetSelection();
+ const auto item = m_objects_ctrl->GetSelection();
if (!item || m_selected_object_id<0)
return;
- auto volume_id = m_objects_model->GetVolumeIdByItem(item);
ModelVolume* volume;
- if (volume_id < 0) {
- if (split_part) return;
- else
- volume = (*m_objects)[m_selected_object_id]->volumes[0]; }
- else
- volume = (*m_objects)[m_selected_object_id]->volumes[volume_id];
- DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config;
- auto nozzle_dmrs_cnt = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
- auto split_rez = volume->split(nozzle_dmrs_cnt);
- if (split_rez == 1) {
+ if (!get_volume_by_item(split_part, item, volume)) return;
+ DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config;
+ const auto nozzle_dmrs_cnt = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
+ if (volume->split(nozzle_dmrs_cnt) == 1) {
wxMessageBox(_(L("The selected object couldn't be split because it contains only one part.")));
return;
}
@@ -1295,8 +1476,9 @@ void on_btn_split(const bool split_part)
for (auto id = 0; id < model_object->volumes.size(); id++)
m_objects_model->AddChild(parent, model_object->volumes[id]->name,
- model_object->volumes[id]->modifier ? m_icon_modifiermesh : m_icon_solidmesh,
- model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
+ model_object->volumes[id]->is_modifier() ? m_icon_modifiermesh : m_icon_solidmesh,
+ model_object->volumes[id]->config.has("extruder") ?
+ model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
false);
m_objects_ctrl->Expand(parent);
@@ -1305,10 +1487,14 @@ void on_btn_split(const bool split_part)
for (auto id = 0; id < model_object->volumes.size(); id++)
m_objects_model->AddChild(item, model_object->volumes[id]->name,
m_icon_solidmesh,
- model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
+ model_object->volumes[id]->config.has("extruder") ?
+ model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value : 0,
false);
m_objects_ctrl->Expand(item);
}
+
+ m_parts_changed = true;
+ parts_changed(m_selected_object_id);
}
void on_btn_move_up(){
@@ -1389,33 +1575,49 @@ void part_selection_changed()
auto item = m_objects_ctrl->GetSelection();
int obj_idx = -1;
auto og = get_optgroup(ogFrequentlyObjectSettings);
+ m_config = nullptr;
+ wxString object_name = wxEmptyString;
if (item)
{
+ const bool is_settings_item = m_objects_model->IsSettingsItem(item);
bool is_part = false;
- if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
+ wxString og_name = wxEmptyString;
+ if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
obj_idx = m_objects_model->GetIdByItem(item);
- og->set_name(" " + _(L("Object Settings")) + " ");
+ og_name = _(L("Object manipulation"));
m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config);
}
else {
auto parent = m_objects_model->GetParent(item);
- // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
+ // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
obj_idx = m_objects_model->GetIdByItem(parent);
- og->set_name(" " + _(L("Part Settings")) + " ");
- is_part = true;
- auto volume_id = m_objects_model->GetVolumeIdByItem(item);
- m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
+ if (is_settings_item) {
+ if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) {
+ og_name = _(L("Object Settings to modify"));
+ m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->config);
+ }
+ else {
+ og_name = _(L("Part Settings to modify"));
+ is_part = true;
+ auto main_parent = m_objects_model->GetParent(parent);
+ obj_idx = m_objects_model->GetIdByItem(main_parent);
+ const auto volume_id = m_objects_model->GetVolumeIdByItem(parent);
+ m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
+ }
+ }
+ else {
+ og_name = _(L("Part manipulation"));
+ is_part = true;
+ const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
+ m_config = std::make_shared<DynamicPrintConfig*>(&(*m_objects)[obj_idx]->volumes[volume_id]->config);
+ }
}
- auto config = m_config;
- og->set_value("object_name", m_objects_model->GetName(item));
+ og->set_name(" " + og_name + " ");
+ object_name = m_objects_model->GetName(item);
m_default_config = std::make_shared<DynamicPrintConfig>(*DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)));
}
- else {
- wxString empty_str = wxEmptyString;
- og->set_value("object_name", empty_str);
- m_config = nullptr;
- }
+ og->set_value("object_name", object_name);
update_settings_list();
@@ -1561,9 +1763,15 @@ void update_position_values()
auto og = get_optgroup(ogFrequentlyObjectSettings);
auto instance = (*m_objects)[m_selected_object_id]->instances.front();
+#if ENABLE_MODELINSTANCE_3D_OFFSET
+ og->set_value("position_x", int(instance->get_offset(X)));
+ og->set_value("position_y", int(instance->get_offset(Y)));
+ og->set_value("position_z", int(instance->get_offset(Z)));
+#else
og->set_value("position_x", int(instance->offset(0)));
og->set_value("position_y", int(instance->offset(1)));
og->set_value("position_z", 0);
+#endif // ENABLE_MODELINSTANCE_3D_OFFSET
}
void update_position_values(const Vec3d& position)
@@ -1638,7 +1846,7 @@ void on_begin_drag(wxDataViewEvent &event)
wxDataViewItem item(event.GetItem());
// only allow drags for item, not containers
- if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
+ if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) {
event.Veto();
return;
}
@@ -1662,7 +1870,7 @@ void on_drop_possible(wxDataViewEvent &event)
// only allow drags for item or background, not containers
if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
- event.GetDataFormat() != wxDF_UNICODETEXT)
+ event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item))
event.Veto();
}
@@ -1672,7 +1880,7 @@ void on_drop(wxDataViewEvent &event)
// only allow drops for item, not containers
if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) ||
- event.GetDataFormat() != wxDF_UNICODETEXT) {
+ event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) {
event.Veto();
return;
}
@@ -1700,6 +1908,9 @@ void on_drop(wxDataViewEvent &event)
for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id+=delta, cnt++)
std::swap(volumes[id], volumes[id +delta]);
+ m_parts_changed = true;
+ parts_changed(m_selected_object_id);
+
g_prevent_list_events = false;
}
@@ -1716,5 +1927,115 @@ void update_objects_list_extruder_column(int extruders_count)
set_extruder_column_hidden(extruders_count <= 1);
}
+void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas)
+{
+ m_slider = new PrusaDoubleSlider(parent, wxID_ANY, 0, 0, 0, 100);
+ sizer->Add(m_slider, 0, wxEXPAND, 0);
+
+ m_preview_canvas = canvas;
+ m_preview_canvas->Bind(wxEVT_KEY_DOWN, update_double_slider_from_canvas);
+
+ m_slider->Bind(wxEVT_SCROLL_CHANGED, [parent](wxEvent& event) {
+ _3DScene::set_toolpaths_range(m_preview_canvas, m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6);
+ if (parent->IsShown())
+ m_preview_canvas->Refresh();
+ });
+}
+
+void fill_slider_values(std::vector<std::pair<int, double>> &values,
+ const std::vector<double> &layers_z)
+{
+ std::vector<double> layers_all_z = _3DScene::get_current_print_zs(m_preview_canvas, false);
+ if (layers_all_z.size() == layers_z.size())
+ for (int i = 0; i < layers_z.size(); i++)
+ values.push_back(std::pair<int, double>(i+1, layers_z[i]));
+ else if (layers_all_z.size() > layers_z.size()) {
+ int cur_id = 0;
+ for (int i = 0; i < layers_z.size(); i++)
+ for (int j = cur_id; j < layers_all_z.size(); j++)
+ if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) {
+ values.push_back(std::pair<int, double>(j+1, layers_z[i]));
+ cur_id = j;
+ break;
+ }
+ }
+}
+
+void set_double_slider_thumbs( const bool force_sliders_full_range,
+ const std::vector<double> &layers_z,
+ const double z_low, const double z_high)
+{
+ // Force slider full range only when slider is created.
+ // Support selected diapason on the all next steps
+ if (/*force_sliders_full_range*/z_high == 0.0) {
+ m_slider->SetLowerValue(0);
+ m_slider->SetHigherValue(layers_z.size() - 1);
+ return;
+ }
+
+ for (int i = layers_z.size() - 1; i >= 0; i--)
+ if (z_low >= layers_z[i]) {
+ m_slider->SetLowerValue(i);
+ break;
+ }
+ for (int i = layers_z.size() - 1; i >= 0 ; i--)
+ if (z_high >= layers_z[i]) {
+ m_slider->SetHigherValue(i);
+ break;
+ }
+}
+
+void update_double_slider(bool force_sliders_full_range)
+{
+ std::vector<std::pair<int, double>> values;
+ std::vector<double> layers_z = _3DScene::get_current_print_zs(m_preview_canvas, true);
+ fill_slider_values(values, layers_z);
+
+ const double z_low = m_slider->GetLowerValueD();
+ const double z_high = m_slider->GetHigherValueD();
+ m_slider->SetMaxValue(layers_z.size() - 1);
+ m_slider->SetSliderValues(values);
+
+ set_double_slider_thumbs(force_sliders_full_range, layers_z, z_low, z_high);
+}
+
+void reset_double_slider()
+{
+ m_slider->SetHigherValue(0);
+ m_slider->SetLowerValue(0);
+}
+
+void update_double_slider_from_canvas(wxKeyEvent& event)
+{
+ if (event.HasModifiers()) {
+ event.Skip();
+ return;
+ }
+
+ const auto key = event.GetKeyCode();
+
+ if (key == 'U' || key == 'D') {
+ const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1;
+ m_slider->SetHigherValue(new_pos);
+ if (event.ShiftDown()) m_slider->SetLowerValue(m_slider->GetHigherValue());
+ }
+ else if (key == 'S')
+ m_slider->ChangeOneLayerLock();
+ else
+ event.Skip();
+}
+
+void show_manipulation_sizer(const bool is_simple_mode)
+{
+ auto item = m_objects_ctrl->GetSelection();
+ if (!item || !is_simple_mode)
+ return;
+
+ if (m_objects_model->IsSettingsItem(item)) {
+ m_objects_ctrl->Select(m_objects_model->GetParent(item));
+ part_selection_changed();
+ }
+}
+
} //namespace GUI
} //namespace Slic3r \ No newline at end of file