From dd70dd6e101dcadec70e0bd2e6ae7069ec5f3ad5 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 27 May 2019 13:07:37 +0200 Subject: [PATCH 01/83] Implemented LayerItem for ObjectList --- resources/icons/row.png | Bin 0 -> 1923 bytes resources/icons/table.png | Bin 0 -> 465 bytes src/slic3r/GUI/GUI_ObjectList.cpp | 28 +++++- src/slic3r/GUI/GUI_ObjectList.hpp | 4 +- src/slic3r/GUI/Plater.cpp | 4 + src/slic3r/GUI/wxExtensions.cpp | 142 ++++++++++++++++++++++++------ src/slic3r/GUI/wxExtensions.hpp | 18 ++-- 7 files changed, 156 insertions(+), 40 deletions(-) create mode 100644 resources/icons/row.png create mode 100644 resources/icons/table.png diff --git a/resources/icons/row.png b/resources/icons/row.png new file mode 100644 index 0000000000000000000000000000000000000000..18a6034fd597baffa886ed65145183a5627310d5 GIT binary patch literal 1923 zcmV-}2YmR6P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+SONCmh2`B{bv2UMA8^>9>^_xpz(Zwiv zHGSLq3H|aI5Zvz1_kI(~wxin+U54kwW9Cucdb$m`J;B*OTejJ4{I%@@ zf>8zb*c#iI_`uhXSr{I0`E;)}#d9y*CP-YE^8KLAk%;OFC3F=|K z5w8Mb0b>(YG>U3={5Vr{c}XN_K%`<^x0tPRH8)C&*R&>g~Qf<`)#!5J8{j=*>r z3}8Xq!P%kYoE^*!&W>oYDa3*`l0i~Wj#K!Y^M|GRS;c!vrK}pckmGR4kTeUIs5#m$l@Jfwcz(V#zdB%*-p;@{ z&0L$;Nq;}I3(mEZ$j$}FlujvxM;AT$`>r%UQuwY!nm(5in*!(hIsNi&ud3RXZ)pp$ zSG2QV!WNGn>(dHd>xiq}wqoX{+DVpvQ7++aLD#g6OX>b-w4wFj`cYopZmnHz27ov& z5EDbYVJOR^3q<=2g57eW1;#aGgHH#V8;toH4K8`Jl}d&3@=}pfYw|Zxy9G?+ zsK^?gJuWRdZ^M>r;TGyMwx;$WbzHnR+oX2uy5DFDarF!UONb2Jf_vlM#f{w;Bs8QE z+5XuPwKw%8geQmw^0j~X#Wyz1pz{?)dT67m@{lr6*c*tjg=V1mlmY3}l6LO{%-17B z-RS~5Z{`bWI1M~?$8|MV7PDs-OD04cvU^A~ZUHMPBAWzlulxR?oMS80WF^jEN+huL zrk<8h(j|rBsl?qxB1`(FEp_E1tdZCxcFuPg?hb=b7$G7r2DyY7ZOt=`a3**ihxJbI z9tZqVy5MX8VWE+}=pQ=-$N7Y_OZi@ z=tF5w2o#apMis&FL3ii|c!_OOF@z@JT9LNYQDc2QFIw3yVCUxp#&_7Q3pMKNafE2* zJDmIk=j||hL$Obh31bl6A21yL`M$%Dhfx36arDtpD7D^Vd@h<53F|1d^8f$=eMv+?R5;6}lfP>eaS+8nyPOg{@Cs48h+uV9gzJ*R ze?TEk3T?&Uk3t2p5eq?xjgf;uuCc!qDe^a@NFkU)61#ALG>U?O&gG~L@2O~EF6Js96?B2zL=jM9-h43{auge5rD+;k#$uJ=f*m}I4TM;NkL?DUCb0n2FpujP_3yERzEr4X!YfPEZ{sG~-EP|Z%oVWl0002ov JPDHLkV1lKIrrrPm literal 0 HcmV?d00001 diff --git a/resources/icons/table.png b/resources/icons/table.png new file mode 100644 index 0000000000000000000000000000000000000000..3bc0bd32fceb21d70368f7842a00a53d6369ba48 GIT binary patch literal 465 zcmV;?0WSWDP)zJNu3H-P zO&@UpeyZQXi7jKe-Hk?r-sue;aDce_XqkvXP+W#F_*ot`jB?BS93Uw71|U^ZjLH`yP%FO7U<6!nLCG} z$SDlW(menu_); @@ -1301,7 +1307,11 @@ void ObjectList::create_object_popupmenu(wxMenu *menu) append_menu_item_scale_selection_to_fit_print_volume(menu); // Split object to parts - m_menu_item_split = append_menu_item_split(menu); + append_menu_item_split(menu); + menu->AppendSeparator(); + + // Layers Editing for object + append_menu_item_layers_editing(menu); menu->AppendSeparator(); // rest of a object_menu will be added later in: @@ -1330,7 +1340,7 @@ void ObjectList::create_part_popupmenu(wxMenu *menu) append_menu_item_fix_through_netfabb(menu); append_menu_item_export_stl(menu); - m_menu_item_split_part = append_menu_item_split(menu); + append_menu_item_split(menu); // Append change part type menu->AppendSeparator(); @@ -1774,6 +1784,20 @@ void ObjectList::split() changed_object(obj_idx); } +void ObjectList::layers_editing() +{ + const auto item = GetSelection(); + const int obj_idx = get_selected_obj_idx(); + if (!item || obj_idx < 0) + return; + + wxDataViewItem layers_item = m_objects_model->GetItemByType(item, itLayerRoot); + if (!layers_item.IsOk()) + layers_item = m_objects_model->AddLayersRoot(item); + + select_item(layers_item); +} + bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume) { auto obj_idx = get_selected_obj_idx(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 166606e2e..076ab5f13 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -119,8 +119,6 @@ class ObjectList : public wxDataViewCtrl MenuWithSeparators m_menu_part; MenuWithSeparators m_menu_sla_object; MenuWithSeparators m_menu_instance; - wxMenuItem* m_menu_item_split { nullptr }; - wxMenuItem* m_menu_item_split_part { nullptr }; wxMenuItem* m_menu_item_settings { nullptr }; wxMenuItem* m_menu_item_split_instances { nullptr }; @@ -199,6 +197,7 @@ public: wxMenu* append_submenu_add_generic(wxMenu* menu, const ModelVolumeType type); void append_menu_items_add_volume(wxMenu* menu); wxMenuItem* append_menu_item_split(wxMenu* menu); + wxMenuItem* append_menu_item_layers_editing(wxMenu* menu); wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent); @@ -226,6 +225,7 @@ public: void del_instances_from_object(const int obj_idx); bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(); + void layers_editing(); bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume); bool is_splittable(); bool selected_instances_of_same_object(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 64c698a9b..c0f267204 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3066,6 +3066,10 @@ bool Plater::priv::complit_init_object_menu() [this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q); object_menu.AppendSeparator(); + // Layers Editing for object + sidebar->obj_list()->append_menu_item_layers_editing(&object_menu); + object_menu.AppendSeparator(); + // "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume() return true; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 76ba853dc..988d4a8ea 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -437,27 +437,44 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent m_type(type), m_extruder(wxEmptyString) { - if (type == itSettings) { + if (type == itSettings) m_name = "Settings to modified"; - } - else if (type == itInstanceRoot) { + else if (type == itInstanceRoot) m_name = _(L("Instances")); -#ifdef __WXGTK__ - m_container = true; -#endif //__WXGTK__ - } - else if (type == itInstance) { + else if (type == itInstance) + { m_idx = parent->GetChildCount(); m_name = wxString::Format(_(L("Instance %d")), m_idx + 1); set_action_icon(); } + else if (type == itLayerRoot) + { + m_bmp = create_scaled_bitmap(nullptr, "table.png"); // FIXME: pass window ptr + m_name = _(L("Layers")); + } + else if (type == itLayer) + { + m_idx = parent->GetChildCount(); + m_name = wxString::Format(_(L("Layer %d")), m_idx + 1); + m_bmp = create_scaled_bitmap(nullptr, "row.png"); // FIXME: pass window ptr + + set_action_icon(); + } + +#ifdef __WXGTK__ + // it's necessary on GTK because of control have to know if this item will be container + // in another case you couldn't to add subitem for this item + // it will be produce "segmentation fault" + if (type & (itInstanceRoot | itLayerRoot | itLayer)) + m_container = true; +#endif //__WXGTK__ } void ObjectDataViewModelNode::set_action_icon() { - m_action_icon_name = m_type == itObject ? "advanced_plus" : - m_type == itVolume ? "cog" : "set_separate_obj"; + m_action_icon_name = m_type & itObject ? "advanced_plus" : + m_type & (itVolume | itLayer) ? "cog" : /*m_type & itInstance*/ "set_separate_obj"; m_action_icon = create_scaled_bitmap(nullptr, m_action_icon_name); // FIXME: pass window ptr } @@ -619,36 +636,62 @@ wxDataViewItem ObjectDataViewModel::AddSettingsChild(const wxDataViewItem &paren return child; } -int get_istances_root_idx(ObjectDataViewModelNode *parent_node) +static int get_root_idx(ObjectDataViewModelNode *parent_node, const ItemType root_type) { - // because of istance_root is a last item of the object - const int inst_root_idx = parent_node->GetChildCount()-1; + // because of istance_root and layers_root are at the end of the list, so + // start locking from the end + for (int root_idx = parent_node->GetChildCount() - 1; root_idx >= 0; root_idx--) + { + // if there is SettingsItem or VolumeItem, then RootItems don't exist in current ObjectItem + if (parent_node->GetNthChild(root_idx)->GetType() & (itSettings | itVolume)) + break; + if (parent_node->GetNthChild(root_idx)->GetType() & root_type) + return root_idx; + } - if (inst_root_idx < 0 || parent_node->GetNthChild(inst_root_idx)->GetType() == itInstanceRoot) - return inst_root_idx; - return -1; } +/* return values: + * true => root_node is created and added to the parent_root + * false => root node alredy exists +*/ +static bool append_root_node(ObjectDataViewModelNode *parent_node, + ObjectDataViewModelNode **root_node, + const ItemType root_type) +{ + const int inst_root_id = get_root_idx(parent_node, root_type); + + *root_node = inst_root_id < 0 ? + new ObjectDataViewModelNode(parent_node, root_type) : + parent_node->GetNthChild(inst_root_id); + + if (inst_root_id < 0) { + if ((root_type&itInstanceRoot) || + (root_type&itLayerRoot) && get_root_idx(parent_node, itInstanceRoot)<0) + parent_node->Append(*root_node); + else if (root_type&itLayerRoot) + parent_node->Insert(*root_node, unsigned int(get_root_idx(parent_node, itInstanceRoot))); + return true; + } + + return false; +} + wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) { ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return wxDataViewItem(0); - // Check and create/get instances root node - const int inst_root_id = get_istances_root_idx(parent_node); + // get InstanceRoot node + ObjectDataViewModelNode *inst_root_node { nullptr }; - ObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ? - new ObjectDataViewModelNode(parent_node, itInstanceRoot) : - parent_node->GetNthChild(inst_root_id); + const bool appended = append_root_node(parent_node, &inst_root_node, itInstanceRoot); const wxDataViewItem inst_root_item((void*)inst_root_node); + if (!inst_root_node) return wxDataViewItem(0); - if (inst_root_id < 0) { - parent_node->Append(inst_root_node); - // notify control - ItemAdded(parent_item, inst_root_item); -// if (num == 1) num++; - } + if (appended) + ItemAdded(parent_item, inst_root_item);// notify control // Add instance nodes ObjectDataViewModelNode *instance_node = nullptr; @@ -665,6 +708,47 @@ wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &paren return wxDataViewItem((void*)instance_node); } +wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_item) +{ + ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); + if (!parent_node) return wxDataViewItem(0); + + // get LayerRoot node + ObjectDataViewModelNode *layer_root_node{ nullptr }; + const bool appended = append_root_node(parent_node, &layer_root_node, itLayerRoot); + if (!layer_root_node) return wxDataViewItem(0); + + const wxDataViewItem layer_root_item((void*)layer_root_node); + + if (appended) + ItemAdded(parent_item, layer_root_item);// notify control + + return wxDataViewItem((void*)layer_root_item); +} + +wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item) +{ + ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); + if (!parent_node) return wxDataViewItem(0); + + // get LayerRoot node + const int root_idx = get_root_idx(parent_node, itLayerRoot); + if (root_idx < 0) return wxDataViewItem(0); + ObjectDataViewModelNode *layer_root_node = parent_node->GetNthChild(root_idx); + + const wxDataViewItem layer_root_item((void*)layer_root_node); + + // Add layer node + ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, itLayer); + layer_root_node->Append(layer_node); + + // notify control + const wxDataViewItem instance_item((void*)layer_node); + ItemAdded(layer_root_item, instance_item); + + return wxDataViewItem((void*)layer_node); +} + wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) { auto ret_item = wxDataViewItem(0); @@ -817,7 +901,7 @@ wxDataViewItem ObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &par ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return ret_item; - const int inst_root_id = get_istances_root_idx(parent_node); + const int inst_root_id = get_root_idx(parent_node, itInstanceRoot); if (inst_root_id < 0) return ret_item; wxDataViewItemArray items; @@ -2573,7 +2657,7 @@ ModeSizer::ModeSizer(wxWindow *parent, int hgap/* = 10*/) : m_mode_btns.push_back(new ModeButton(parent, wxID_ANY, button.second, button.first));; #endif // __WXOSX__ - m_mode_btns.back()->Bind(wxEVT_BUTTON, std::bind(modebtnfn, std::placeholders::_1, m_mode_btns.size() - 1)); + m_mode_btns.back()->Bind(wxEVT_BUTTON, std::bind(modebtnfn, std::placeholders::_1, int(m_mode_btns.size() - 1))); Add(m_mode_btns.back()); } } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 78fb7be55..424f7832a 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -159,12 +159,14 @@ DECLARE_VARIANT_OBJECT(DataViewBitmapText) // ---------------------------------------------------------------------------- enum ItemType { - itUndef = 0, - itObject = 1, - itVolume = 2, - itInstanceRoot = 4, - itInstance = 8, - itSettings = 16 + itUndef = 0, + itObject = 1, + itVolume = 2, + itInstanceRoot = 4, + itInstance = 8, + itSettings = 16, + itLayerRoot = 32, + itLayer = 64, }; class ObjectDataViewModelNode; @@ -348,7 +350,7 @@ public: } // Set action icons for node - void set_action_icon(); + void set_action_icon(); void update_settings_digest_bitmaps(); bool update_settings_digest(const std::vector& categories); @@ -388,6 +390,8 @@ public: const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); + wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); + wxDataViewItem AddLayersChild(const wxDataViewItem &parent_item); wxDataViewItem Delete(const wxDataViewItem &item); wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); void DeleteAll(); From 9d19e3d2a72742fd3398174b01be7e1ad583407b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 27 May 2019 16:13:24 +0200 Subject: [PATCH 02/83] Improved Delete() Add() ans Select() functions for Layer(s)Item --- src/slic3r/GUI/GUI_ObjectList.cpp | 19 ++++--- src/slic3r/GUI/wxExtensions.cpp | 84 ++++++++++++++++++++----------- 2 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 5e14459e2..e180f1dfc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1648,6 +1648,8 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) del_settings_from_config(); else if (type == itInstanceRoot && obj_idx != -1) del_instances_from_object(obj_idx); + else if ((type & itLayerRoot) && obj_idx != -1) + /*del_layers_from_object(obj_idx)*/; else if (idx == -1) return; else if (!del_subobject_from_object(obj_idx, idx, type)) @@ -1728,6 +1730,8 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con } object->delete_instance(idx); } + else if (type == itLayer) { + } else return false; @@ -1791,9 +1795,11 @@ void ObjectList::layers_editing() if (!item || obj_idx < 0) return; - wxDataViewItem layers_item = m_objects_model->GetItemByType(item, itLayerRoot); + wxDataViewItem obj_item = m_objects_model->GetTopParent(item); + + wxDataViewItem layers_item = m_objects_model->GetItemByType(obj_item, itLayerRoot); if (!layers_item.IsOk()) - layers_item = m_objects_model->AddLayersRoot(item); + layers_item = m_objects_model->AddLayersRoot(obj_item); select_item(layers_item); } @@ -2171,7 +2177,8 @@ void ObjectList::update_selections() m_selection_mode = smInstance; // We doesn't update selection if SettingsItem for the current object/part is selected - if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) == itSettings ) +// if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) == itSettings ) + if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) & (itSettings | itLayerRoot | itLayer)) { const auto item = GetSelection(); if (selection.is_single_full_object() && @@ -2294,8 +2301,8 @@ void ObjectList::update_selections_on_canvas() auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, int instance_idx, bool as_single_selection) { const ItemType& type = m_objects_model->GetItemType(item); - if ( type == itInstanceRoot || m_objects_model->GetParent(item) == wxDataViewItem(0) ) { - wxDataViewItem obj_item = type == itInstanceRoot ? m_objects_model->GetParent(item) : item; + if ( type == itLayerRoot || m_objects_model->GetParent(item) == wxDataViewItem(0) ) { + wxDataViewItem obj_item = type == itLayerRoot ? m_objects_model->GetParent(item) : item; selection.add_object(m_objects_model->GetIdByItem(obj_item), as_single_selection); return; } @@ -2317,7 +2324,7 @@ void ObjectList::update_selections_on_canvas() if (sel_cnt == 1) { wxDataViewItem item = GetSelection(); - if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot)) + if (m_objects_model->GetItemType(item) & (itSettings | itInstanceRoot | itLayerRoot | itLayer)) add_to_selection(m_objects_model->GetParent(item), selection, instance_idx, true); else add_to_selection(item, selection, instance_idx, true); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 988d4a8ea..7849f66dd 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -540,6 +540,22 @@ void ObjectDataViewModelNode::SetIdx(const int& idx) // ObjectDataViewModel // ---------------------------------------------------------------------------- +static int get_root_idx(ObjectDataViewModelNode *parent_node, const ItemType root_type) +{ + // because of istance_root and layers_root are at the end of the list, so + // start locking from the end + for (int root_idx = parent_node->GetChildCount() - 1; root_idx >= 0; root_idx--) + { + // if there is SettingsItem or VolumeItem, then RootItems don't exist in current ObjectItem + if (parent_node->GetNthChild(root_idx)->GetType() & (itSettings | itVolume)) + break; + if (parent_node->GetNthChild(root_idx)->GetType() & root_type) + return root_idx; + } + + return -1; +} + ObjectDataViewModel::ObjectDataViewModel() { m_bitmap_cache = new Slic3r::GUI::BitmapCache; @@ -584,10 +600,10 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder); - // because of istance_root is a last item of the object - int insert_position = root->GetChildCount() - 1; - if (insert_position < 0 || root->GetNthChild(insert_position)->m_type != itInstanceRoot) - insert_position = -1; + // get insertion position according to the existed Layers and/or Instances Items + int insert_position = get_root_idx(root, itLayerRoot); + if (insert_position < 0) + insert_position = get_root_idx(root, itInstanceRoot); const bool obj_errors = root->m_bmp.IsOk(); @@ -603,7 +619,7 @@ wxDataViewItem ObjectDataViewModel::AddVolumeChild( const wxDataViewItem &parent ItemAdded(parent_item, child); root->m_volumes_cnt++; - if (insert_position > 0) insert_position++; + if (insert_position >= 0) insert_position++; } const auto node = new ObjectDataViewModelNode(root, name, GetVolumeIcon(volume_type, has_errors), extruder_str, root->m_volumes_cnt); @@ -636,22 +652,6 @@ wxDataViewItem ObjectDataViewModel::AddSettingsChild(const wxDataViewItem &paren return child; } -static int get_root_idx(ObjectDataViewModelNode *parent_node, const ItemType root_type) -{ - // because of istance_root and layers_root are at the end of the list, so - // start locking from the end - for (int root_idx = parent_node->GetChildCount() - 1; root_idx >= 0; root_idx--) - { - // if there is SettingsItem or VolumeItem, then RootItems don't exist in current ObjectItem - if (parent_node->GetNthChild(root_idx)->GetType() & (itSettings | itVolume)) - break; - if (parent_node->GetNthChild(root_idx)->GetType() & root_type) - return root_idx; - } - - return -1; -} - /* return values: * true => root_node is created and added to the parent_root * false => root node alredy exists @@ -723,6 +723,8 @@ wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_i if (appended) ItemAdded(parent_item, layer_root_item);// notify control + AddLayersChild(layer_root_item); + return wxDataViewItem((void*)layer_root_item); } @@ -732,9 +734,15 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_ if (!parent_node) return wxDataViewItem(0); // get LayerRoot node - const int root_idx = get_root_idx(parent_node, itLayerRoot); - if (root_idx < 0) return wxDataViewItem(0); - ObjectDataViewModelNode *layer_root_node = parent_node->GetNthChild(root_idx); + ObjectDataViewModelNode *layer_root_node; + + if (parent_node->GetType() & itLayerRoot) + layer_root_node = parent_node; + else { + const int root_idx = get_root_idx(parent_node, itLayerRoot); + if (root_idx < 0) return wxDataViewItem(0); + layer_root_node = parent_node->GetNthChild(root_idx); + } const wxDataViewItem layer_root_item((void*)layer_root_node); @@ -763,9 +771,9 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) // NOTE: MyObjectTreeModelNodePtrArray is only an array of _pointers_ // thus removing the node from it doesn't result in freeing it if (node_parent) { - if (node->m_type == itInstanceRoot) + if (node->m_type & (itInstanceRoot|itLayerRoot)) { - for (int i = node->GetChildCount() - 1; i > 0; i--) + for (int i = node->GetChildCount() - 1; i >= (node->m_type & itInstanceRoot ? 1 : 0); i--) Delete(wxDataViewItem(node->GetNthChild(i))); return parent; } @@ -774,7 +782,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) auto idx = node->GetIdx(); - if (node->m_type == itVolume) { + if (node->m_type & (itVolume|itLayer)) { node_parent->m_volumes_cnt--; DeleteSettings(item); } @@ -810,6 +818,22 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) delete node_parent; ret_item = wxDataViewItem(obj_node); +#ifndef __WXGTK__ + if (obj_node->GetChildCount() == 0) + obj_node->m_container = false; +#endif //__WXGTK__ + ItemDeleted(ret_item, wxDataViewItem(node_parent)); + return ret_item; + } + + // if there was last layer item, delete this one and layers root item + if (node_parent->GetChildCount() == 0 && node_parent->m_type == itLayerRoot) + { + ObjectDataViewModelNode *obj_node = node_parent->GetParent(); + obj_node->GetChildren().Remove(node_parent); + delete node_parent; + ret_item = wxDataViewItem(obj_node); + #ifndef __WXGTK__ if (obj_node->GetChildCount() == 0) obj_node->m_container = false; @@ -819,7 +843,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) } // if there is last volume item after deleting, delete this last volume too - if (node_parent->GetChildCount() <= 3) + if (node_parent->GetChildCount() <= 3) // 3??? #ys_FIXME { int vol_cnt = 0; int vol_idx = 0; @@ -1120,7 +1144,7 @@ void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type type = itUndef; ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); - if (!node || node->GetIdx() <-1 || node->GetIdx() ==-1 && !(node->GetType() & (itObject | itSettings | itInstanceRoot))) + if (!node || node->GetIdx() <-1 || node->GetIdx() == -1 && !(node->GetType() & (itObject | itSettings | itInstanceRoot | itLayerRoot/* | itLayer*/))) return; idx = node->GetIdx(); @@ -1128,7 +1152,7 @@ void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type ObjectDataViewModelNode *parent_node = node->GetParent(); if (!parent_node) return; - if (type == itInstance) + if (type & (itInstance | itLayer)) parent_node = node->GetParent()->GetParent(); if (!parent_node || parent_node->m_type != itObject) { type = itUndef; return; } From 765d4264ae9380a549bd84bd8d79d776858d8816 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 28 May 2019 16:38:04 +0200 Subject: [PATCH 03/83] Implemented ObjectLayers class + some code refactoring --- src/slic3r/GUI/GUI_App.cpp | 5 + src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/GUI_ObjectLayers.cpp | 150 ++++++++++++++++++++++++++ src/slic3r/GUI/GUI_ObjectLayers.hpp | 36 +++++++ src/slic3r/GUI/GUI_ObjectList.cpp | 29 ++++- src/slic3r/GUI/GUI_ObjectList.hpp | 12 ++- src/slic3r/GUI/GUI_ObjectSettings.cpp | 4 +- src/slic3r/GUI/Plater.cpp | 13 +++ src/slic3r/GUI/Plater.hpp | 2 + 9 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 src/slic3r/GUI/GUI_ObjectLayers.cpp create mode 100644 src/slic3r/GUI/GUI_ObjectLayers.hpp diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index b75b946e6..405de3ae9 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -924,6 +924,11 @@ ObjectList* GUI_App::obj_list() return sidebar().obj_list(); } +ObjectLayers* GUI_App::obj_layers() +{ + return sidebar().obj_layers(); +} + Plater* GUI_App::plater() { return plater_; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index b70f0dc16..675121824 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -155,6 +155,7 @@ public: ObjectManipulation* obj_manipul(); ObjectSettings* obj_settings(); ObjectList* obj_list(); + ObjectLayers* obj_layers(); Plater* plater(); std::vector *model_objects(); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp new file mode 100644 index 000000000..31a17bbf6 --- /dev/null +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -0,0 +1,150 @@ +#include "GUI_ObjectLayers.hpp" +#include "GUI_ObjectList.hpp" + +#include "OptionsGroup.hpp" +#include "PresetBundle.hpp" +#include "libslic3r/Model.hpp" + +#include + +#include "I18N.hpp" + +#include + +namespace Slic3r +{ +namespace GUI +{ + +ObjectLayers::ObjectLayers(wxWindow* parent) : + OG_Settings(parent, true) +{ + m_og->label_width = 0; + m_og->set_grid_vgap(5); + + // Legend for object layers + Line line = Line{ "", "" }; + + ConfigOptionDef def; + def.label = ""; + def.gui_type = "legend"; + def.type = coString; + def.width = field_width; + + for (const std::string axis : { "Min Z", "Max Z", "Layer height" }) { + def.set_default_value(new ConfigOptionString{ axis }); + std::string label = boost::algorithm::replace_all_copy(axis, " ", "_"); + boost::algorithm::to_lower(label); + line.append_option(Option(def, label + "_legend")); + } + + m_og->append_line(line); + + m_bmp_delete = ScalableBitmap(parent, "cross"); + m_bmp_add = ScalableBitmap(parent, "add_copies"); +} + +void ObjectLayers::update_layers_list() +{ + ObjectList* objects_ctrl = wxGetApp().obj_list(); + if (objects_ctrl->multiple_selection()) return; + + const auto item = objects_ctrl->GetSelection(); + if (!item) return; + + const int obj_idx = objects_ctrl->get_selected_obj_idx(); + if (obj_idx < 0) return; + + const ItemType type = objects_ctrl->GetModel()->GetItemType(item); + if (!(type & (itLayerRoot | itLayer))) return; + + ModelObject* object = objects_ctrl->object(obj_idx); + if (!object || object->layer_height_ranges.empty()) return; + + auto grid_sizer = m_og->get_grid_sizer(); + + const int cols = grid_sizer->GetCols(); + const int rows = grid_sizer->GetRows(); + for (int idx = cols*rows-1; idx >= cols; idx--) { + grid_sizer->Remove(idx); + } + + ConfigOptionDef def; + def.label = ""; + def.gui_type = ""; + def.type = coFloat; + def.width = field_width; + + if (type & itLayerRoot) + { + auto create_btns = [this](wxWindow* parent) { + auto sizer = new wxBoxSizer(wxHORIZONTAL); + auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); + del_btn->SetToolTip(_(L("Remove layer"))); + + sizer->Add(del_btn, 0, wxRIGHT, em_unit(parent)); + + del_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { + del_layer(); +// wxTheApp->CallAfter([this]() { +// wxWindowUpdateLocker noUpdates(m_parent); +// update_layers_list(); +// m_parent->Layout(); +// }); + }); + + auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); + add_btn->SetToolTip(_(L("Add layer"))); + + sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); + + add_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { + add_layer(); +// wxTheApp->CallAfter([this]() { +// wxWindowUpdateLocker noUpdates(m_parent); +// update_layers_list(); +// m_parent->Layout(); +// }); + }); + + return sizer; + }; + + Line line{"",""}; + for (const auto layer : object->layer_height_ranges) + { + std::string label = (boost::format("min_z_%.2f") % layer.first.first).str(); + def.set_default_value(new ConfigOptionFloat(layer.first.first)); + line.append_option(Option(def, label)); + + label = (boost::format("max_z_%.2f") % layer.first.second).str(); + def.set_default_value(new ConfigOptionFloat(layer.first.second)); + line.append_option(Option(def, label)); + + label = (boost::format("layer_height_%.2f_%.2f") % layer.first.first % layer.first.second).str(); + def.set_default_value(new ConfigOptionFloat(layer.second)); + line.append_option(Option(def, label)); + + line.append_widget(create_btns); + } + + m_og->append_line(line); + } +} + +void ObjectLayers::UpdateAndShow(const bool show) +{ + if (show) + update_layers_list(); + + OG_Settings::UpdateAndShow(show); +} + +void ObjectLayers::msw_rescale() +{ + m_bmp_delete.msw_rescale(); + m_bmp_add.msw_rescale(); +} + +} //namespace GUI +} //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp new file mode 100644 index 000000000..8f8b55998 --- /dev/null +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -0,0 +1,36 @@ +#ifndef slic3r_GUI_ObjectLayers_hpp_ +#define slic3r_GUI_ObjectLayers_hpp_ + +#include "GUI_ObjectSettings.hpp" +#include "wxExtensions.hpp" + +class wxBoxSizer; + +namespace Slic3r { +class ModelObject; + +namespace GUI { +class ConfigOptionsGroup; + +class ObjectLayers : public OG_Settings +{ + ScalableBitmap m_bmp_delete; + ScalableBitmap m_bmp_add; + + int field_width {8}; + +public: + ObjectLayers(wxWindow* parent); + ~ObjectLayers() {} + + void update_layers_list(); + void add_layer() {}; + void del_layer() {}; + + void UpdateAndShow(const bool show) override; + void msw_rescale(); +}; + +}} + +#endif // slic3r_GUI_ObjectLayers_hpp_ diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index e180f1dfc..080ebbe21 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1,6 +1,7 @@ #include "libslic3r/libslic3r.h" #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" +#include "GUI_ObjectLayers.hpp" #include "GUI_App.hpp" #include "I18N.hpp" @@ -1799,7 +1800,11 @@ void ObjectList::layers_editing() wxDataViewItem layers_item = m_objects_model->GetItemByType(obj_item, itLayerRoot); if (!layers_item.IsOk()) + { + const t_layer_height_range first_range = { 0.0f, 0.2f }; + object(obj_idx)->layer_height_ranges[first_range] = 0.1f; layers_item = m_objects_model->AddLayersRoot(obj_item); + } select_item(layers_item); } @@ -1873,6 +1878,7 @@ void ObjectList::part_selection_changed() bool update_and_show_manipulations = false; bool update_and_show_settings = false; + bool update_and_show_layers = false; const auto item = GetSelection(); @@ -1898,7 +1904,8 @@ void ObjectList::part_selection_changed() 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 obj_idx = m_objects_model->GetIdByItem(parent); - if (m_objects_model->GetItemType(item) == itSettings) { + const ItemType type = m_objects_model->GetItemType(item); + if (type & itSettings) { if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { og_name = _(L("Object Settings to modify")); m_config = &(*m_objects)[obj_idx]->config; @@ -1912,13 +1919,13 @@ void ObjectList::part_selection_changed() } update_and_show_settings = true; } - else if (m_objects_model->GetItemType(item) == itVolume) { + else if (type & itVolume) { og_name = _(L("Part manipulation")); volume_id = m_objects_model->GetVolumeIdByItem(item); m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; update_and_show_manipulations = true; } - else if (m_objects_model->GetItemType(item) == itInstance) { + else if (type & itInstance) { og_name = _(L("Instance manipulation")); update_and_show_manipulations = true; @@ -1926,6 +1933,10 @@ void ObjectList::part_selection_changed() const int obj_idx_ = m_objects_model->GetObjectIdByItem(item); m_config = &(*m_objects)[obj_idx_]->config; } + else if (type & (itLayerRoot|itLayer)) { + og_name = type & itLayerRoot ? _(L("Layers Editing")) : _(L("Layer Editing")); + update_and_show_layers = true; + } } } } @@ -1944,11 +1955,15 @@ void ObjectList::part_selection_changed() if (update_and_show_settings) wxGetApp().obj_settings()->get_og()->set_name(" " + og_name + " "); + if (update_and_show_layers) + wxGetApp().obj_layers()->get_og()->set_name(" " + og_name + " "); + Sidebar& panel = wxGetApp().sidebar(); panel.Freeze(); wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations); wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings); + wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers); wxGetApp().sidebar().show_info_sizer(); panel.Layout(); @@ -2946,5 +2961,13 @@ void ObjectList::set_extruder_for_selected_items(const int extruder) const wxGetApp().plater()->update(); } +ModelObject* ObjectList::object(const int obj_idx) const +{ + if (obj_idx < 0) + return nullptr; + + return (*m_objects)[obj_idx]; +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 076ab5f13..764aac1e8 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -122,6 +122,10 @@ class ObjectList : public wxDataViewCtrl wxMenuItem* m_menu_item_settings { nullptr }; wxMenuItem* m_menu_item_split_instances { nullptr }; + ObjectDataViewModel *m_objects_model{ nullptr }; + DynamicPrintConfig *m_config {nullptr}; + std::vector *m_objects{ nullptr }; + std::vector m_bmp_vector; int m_selected_object_id = -1; @@ -151,11 +155,11 @@ public: std::map CATEGORY_ICON; - ObjectDataViewModel *m_objects_model{ nullptr }; - DynamicPrintConfig *m_config {nullptr}; - - std::vector *m_objects{ nullptr }; + ObjectDataViewModel* GetModel() const { return m_objects_model; } + DynamicPrintConfig* config() const { return m_config; } + std::vector* objects() const { return m_objects; } + ModelObject* object(const int obj_idx) const ; void create_objects_ctrl(); void create_popup_menus(); diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index 4107e872a..a4aa7dec2 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -68,8 +68,8 @@ void ObjectSettings::update_settings_list() m_settings_list_sizer->Clear(true); auto objects_ctrl = wxGetApp().obj_list(); - auto objects_model = wxGetApp().obj_list()->m_objects_model; - auto config = wxGetApp().obj_list()->m_config; + auto objects_model = wxGetApp().obj_list()->GetModel(); + auto config = wxGetApp().obj_list()->config(); const auto item = objects_ctrl->GetSelection(); if (item && !objects_ctrl->multiple_selection() && diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c0f267204..88abe9b83 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -43,6 +43,7 @@ #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" +#include "GUI_ObjectLayers.hpp" #include "GUI_Utils.hpp" #include "wxExtensions.hpp" #include "MainFrame.hpp" @@ -611,6 +612,7 @@ struct Sidebar::priv ObjectList *object_list; ObjectManipulation *object_manipulation; ObjectSettings *object_settings; + ObjectLayers *object_layers; ObjectInfo *object_info; SlicedInfo *sliced_info; @@ -729,6 +731,11 @@ Sidebar::Sidebar(Plater *parent) p->object_settings = new ObjectSettings(p->scrolled); p->object_settings->Hide(); p->sizer_params->Add(p->object_settings->get_sizer(), 0, wxEXPAND | wxTOP, margin_5); + + // Object Layers + p->object_layers = new ObjectLayers(p->scrolled); + p->object_layers->Hide(); + p->sizer_params->Add(p->object_layers->get_sizer(), 0, wxEXPAND | wxTOP, margin_5); // Info boxes p->object_info = new ObjectInfo(p->scrolled); @@ -922,6 +929,7 @@ void Sidebar::msw_rescale() p->object_list->msw_rescale(); p->object_manipulation->msw_rescale(); p->object_settings->msw_rescale(); + p->object_layers->msw_rescale(); p->object_info->msw_rescale(); @@ -943,6 +951,11 @@ ObjectSettings* Sidebar::obj_settings() return p->object_settings; } +ObjectLayers* Sidebar::obj_layers() +{ + return p->object_layers; +} + wxScrolledWindow* Sidebar::scrolled_panel() { return p->scrolled; diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 16c9cbe64..3e50797a6 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -33,6 +33,7 @@ class MainFrame; class ConfigOptionsGroup; class ObjectManipulation; class ObjectSettings; +class ObjectLayers; class ObjectList; class GLCanvas3D; @@ -93,6 +94,7 @@ public: ObjectManipulation* obj_manipul(); ObjectList* obj_list(); ObjectSettings* obj_settings(); + ObjectLayers* obj_layers(); wxScrolledWindow* scrolled_panel(); wxPanel* presets_panel(); From bf56d79354cd74d645ea3e030c476c41d9c649eb Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 30 May 2019 12:41:16 +0200 Subject: [PATCH 04/83] Layers sizer updating --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 173 +++++++++++++++++----------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 9 +- src/slic3r/GUI/GUI_ObjectList.cpp | 4 + src/slic3r/GUI/OptionsGroup.cpp | 11 ++ src/slic3r/GUI/OptionsGroup.hpp | 2 + 5 files changed, 128 insertions(+), 71 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 31a17bbf6..80aa6bcca 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -14,13 +14,17 @@ namespace Slic3r { namespace GUI -{ +{ + +typedef std::map t_layer_height_ranges; + +#define field_width 8 ObjectLayers::ObjectLayers(wxWindow* parent) : OG_Settings(parent, true) { - m_og->label_width = 0; - m_og->set_grid_vgap(5); + m_og->label_width = 1; +// m_og->set_grid_vgap(5); // Legend for object layers Line line = Line{ "", "" }; @@ -36,6 +40,8 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : std::string label = boost::algorithm::replace_all_copy(axis, " ", "_"); boost::algorithm::to_lower(label); line.append_option(Option(def, label + "_legend")); + + m_legends.push_back(label + "_legend"); } m_og->append_line(line); @@ -44,6 +50,83 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : m_bmp_add = ScalableBitmap(parent, "add_copies"); } +static Line create_new_layer(const t_layer_height_ranges::value_type& layer) +{ + Line line = Line{ "", "" }; + ConfigOptionDef def; + def.label = ""; + def.gui_type = ""; + def.type = coFloat; + def.width = field_width; + + std::string label = (boost::format("min_z_%.2f") % layer.first.first).str(); + def.set_default_value(new ConfigOptionFloat(layer.first.first)); + line.append_option(Option(def, label)); + + label = (boost::format("max_z_%.2f") % layer.first.second).str(); + def.set_default_value(new ConfigOptionFloat(layer.first.second)); + line.append_option(Option(def, label)); + + label = (boost::format("layer_height_%.2f_%.2f") % layer.first.first % layer.first.second).str(); + def.set_default_value(new ConfigOptionFloat(layer.second)); + line.append_option(Option(def, label)); + + return line; +} + +void ObjectLayers::create_layers_list() +{ + auto create_btns = [this](wxWindow* parent) { + auto sizer = new wxBoxSizer(wxHORIZONTAL); + + auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); + del_btn->SetToolTip(_(L("Remove layer"))); + + sizer->Add(del_btn, 0, wxRIGHT, em_unit(parent)); + + del_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { + del_layer(); +// wxTheApp->CallAfter([this]() { +// wxWindowUpdateLocker noUpdates(m_parent); +// update_layers_list(); +// m_parent->Layout(); +// }); + }); + + auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); + add_btn->SetToolTip(_(L("Add layer"))); + + sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); + + add_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { + add_layer(); +// wxTheApp->CallAfter([this]() { +// wxWindowUpdateLocker noUpdates(m_parent); +// update_layers_list(); +// m_parent->Layout(); +// }); + }); + + return sizer; + }; + + for (const auto layer : m_object->layer_height_ranges) + { + Line line = create_new_layer(layer); + line.append_widget(create_btns); + m_og->append_line(line); + } +} + +void ObjectLayers::create_layer() +{ + for (const auto layer : m_object->layer_height_ranges) + { + m_og->append_line(create_new_layer(layer)); + break; + } +} + void ObjectLayers::update_layers_list() { ObjectList* objects_ctrl = wxGetApp().obj_list(); @@ -58,78 +141,32 @@ void ObjectLayers::update_layers_list() const ItemType type = objects_ctrl->GetModel()->GetItemType(item); if (!(type & (itLayerRoot | itLayer))) return; - ModelObject* object = objects_ctrl->object(obj_idx); - if (!object || object->layer_height_ranges.empty()) return; + m_object = objects_ctrl->object(obj_idx); + if (!m_object || m_object->layer_height_ranges.empty()) return; + + // Delete all controls from options group except of the legends auto grid_sizer = m_og->get_grid_sizer(); - - const int cols = grid_sizer->GetCols(); - const int rows = grid_sizer->GetRows(); + const int cols = grid_sizer->GetEffectiveColsCount(); + const int rows = grid_sizer->GetEffectiveRowsCount(); for (int idx = cols*rows-1; idx >= cols; idx--) { - grid_sizer->Remove(idx); + wxSizerItem* t = grid_sizer->GetItem(idx); + if (t->IsSizer()) + t->GetSizer()->Clear(true); + grid_sizer->Remove(idx); } - ConfigOptionDef def; - def.label = ""; - def.gui_type = ""; - def.type = coFloat; - def.width = field_width; + m_og->clear_fields_except_of(m_legends); + + + // Add new control according to the selected item if (type & itLayerRoot) - { - auto create_btns = [this](wxWindow* parent) { - auto sizer = new wxBoxSizer(wxHORIZONTAL); - auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); - del_btn->SetToolTip(_(L("Remove layer"))); - - sizer->Add(del_btn, 0, wxRIGHT, em_unit(parent)); - - del_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { - del_layer(); -// wxTheApp->CallAfter([this]() { -// wxWindowUpdateLocker noUpdates(m_parent); -// update_layers_list(); -// m_parent->Layout(); -// }); - }); - - auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); - add_btn->SetToolTip(_(L("Add layer"))); - - sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); - - add_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { - add_layer(); -// wxTheApp->CallAfter([this]() { -// wxWindowUpdateLocker noUpdates(m_parent); -// update_layers_list(); -// m_parent->Layout(); -// }); - }); - - return sizer; - }; - - Line line{"",""}; - for (const auto layer : object->layer_height_ranges) - { - std::string label = (boost::format("min_z_%.2f") % layer.first.first).str(); - def.set_default_value(new ConfigOptionFloat(layer.first.first)); - line.append_option(Option(def, label)); - - label = (boost::format("max_z_%.2f") % layer.first.second).str(); - def.set_default_value(new ConfigOptionFloat(layer.first.second)); - line.append_option(Option(def, label)); - - label = (boost::format("layer_height_%.2f_%.2f") % layer.first.first % layer.first.second).str(); - def.set_default_value(new ConfigOptionFloat(layer.second)); - line.append_option(Option(def, label)); - - line.append_widget(create_btns); - } - - m_og->append_line(line); - } + create_layers_list(); + else + create_layer(); + + m_parent->Layout(); } void ObjectLayers::UpdateAndShow(const bool show) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 8f8b55998..13a3da911 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -14,15 +14,18 @@ class ConfigOptionsGroup; class ObjectLayers : public OG_Settings { - ScalableBitmap m_bmp_delete; - ScalableBitmap m_bmp_add; + ScalableBitmap m_bmp_delete; + ScalableBitmap m_bmp_add; + ModelObject* m_object {nullptr}; - int field_width {8}; + std::vector m_legends; public: ObjectLayers(wxWindow* parent); ~ObjectLayers() {} + void create_layers_list(); + void create_layer(); void update_layers_list(); void add_layer() {}; void del_layer() {}; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 080ebbe21..00eb3e7de 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1803,6 +1803,10 @@ void ObjectList::layers_editing() { const t_layer_height_range first_range = { 0.0f, 0.2f }; object(obj_idx)->layer_height_ranges[first_range] = 0.1f; + + const t_layer_height_range second_range = { 0.2f, 0.4f }; + object(obj_idx)->layer_height_ranges[second_range] = 0.05f; + layers_item = m_objects_model->AddLayersRoot(obj_item); } diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 2ac6b00af..67feefa3f 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -320,6 +320,17 @@ Line OptionsGroup::create_single_option_line(const Option& option) const { return retval; } +void OptionsGroup::clear_fields_except_of(const std::vector left_fields) +{ + auto it = m_fields.begin(); + while (it != m_fields.end()) { + if (std::find(left_fields.begin(), left_fields.end(), it->first) == left_fields.end()) + it = m_fields.erase(it); + else + it++; + } +} + void OptionsGroup::on_set_focus(const std::string& opt_key) { if (m_set_focus != nullptr) diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 73b2c5110..422a5c2a2 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -160,6 +160,8 @@ public: m_show_modified_btns = show; } + void clear_fields_except_of(const std::vector left_fields); + OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false, column_t extra_clmn = nullptr) : m_parent(_parent), title(title), From 080274c638de48ed771873d1936a8e375dd5196c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 30 May 2019 13:08:05 +0200 Subject: [PATCH 05/83] Added missed files to the CMakeLists.txt --- src/slic3r/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 570e23baa..13f563fd0 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -81,6 +81,8 @@ set(SLIC3R_GUI_SOURCES GUI/GUI_ObjectManipulation.hpp GUI/GUI_ObjectSettings.cpp GUI/GUI_ObjectSettings.hpp + GUI/GUI_ObjectLayers.cpp + GUI/GUI_ObjectLayers.hpp GUI/LambdaObjectDialog.cpp GUI/LambdaObjectDialog.hpp GUI/Tab.cpp From a516f76f94447e82eed066f022deedf769f07b42 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 30 May 2019 14:41:16 +0200 Subject: [PATCH 06/83] Improved layer sizer + fixed build under OSX and Linux --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 17 ++++---- src/slic3r/GUI/GUI_ObjectLayers.hpp | 2 +- src/slic3r/GUI/GUI_ObjectList.cpp | 16 +++++--- src/slic3r/GUI/wxExtensions.cpp | 62 +++++++++++++++++++---------- src/slic3r/GUI/wxExtensions.hpp | 8 +++- 5 files changed, 70 insertions(+), 35 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 80aa6bcca..f47260530 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -24,7 +24,7 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : OG_Settings(parent, true) { m_og->label_width = 1; -// m_og->set_grid_vgap(5); + m_og->set_grid_vgap(5); // Legend for object layers Line line = Line{ "", "" }; @@ -118,13 +118,16 @@ void ObjectLayers::create_layers_list() } } -void ObjectLayers::create_layer() +void ObjectLayers::create_layer(int id) { - for (const auto layer : m_object->layer_height_ranges) - { - m_og->append_line(create_new_layer(layer)); - break; + t_layer_height_ranges::iterator layer_range = m_object->layer_height_ranges.begin(); + + while (id > 0 && layer_range != m_object->layer_height_ranges.end()) { + layer_range++; + id--; } + + m_og->append_line(create_new_layer(*layer_range)); } void ObjectLayers::update_layers_list() @@ -164,7 +167,7 @@ void ObjectLayers::update_layers_list() if (type & itLayerRoot) create_layers_list(); else - create_layer(); + create_layer(objects_ctrl->GetModel()->GetLayerIdByItem(item)); m_parent->Layout(); } diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 13a3da911..b9e9efb14 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -25,7 +25,7 @@ public: ~ObjectLayers() {} void create_layers_list(); - void create_layer(); + void create_layer(int id); void update_layers_list(); void add_layer() {}; void del_layer() {}; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 00eb3e7de..934ad34fb 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1801,15 +1801,21 @@ void ObjectList::layers_editing() wxDataViewItem layers_item = m_objects_model->GetItemByType(obj_item, itLayerRoot); if (!layers_item.IsOk()) { - const t_layer_height_range first_range = { 0.0f, 0.2f }; - object(obj_idx)->layer_height_ranges[first_range] = 0.1f; - - const t_layer_height_range second_range = { 0.2f, 0.4f }; - object(obj_idx)->layer_height_ranges[second_range] = 0.05f; + // --->>>--- Just for testing + object(obj_idx)->layer_height_ranges[{ 0.0f, 0.2f }] = 0.1f; + object(obj_idx)->layer_height_ranges[{ 0.2f, 0.4f }] = 0.05f; + object(obj_idx)->layer_height_ranges[{ 0.4f, 0.6f }] = 0.2f; + // ---<<<--- Just for testing layers_item = m_objects_model->AddLayersRoot(obj_item); } + for (const auto range : object(obj_idx)->layer_height_ranges) + { + const std::string label = (boost::format("(%.2f-%.2f)") % range.first.first % range.first.second).str(); + m_objects_model->AddLayersChild(layers_item, label); + } + select_item(layers_item); } diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 7849f66dd..989a97676 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -453,24 +453,39 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent m_bmp = create_scaled_bitmap(nullptr, "table.png"); // FIXME: pass window ptr m_name = _(L("Layers")); } - else if (type == itLayer) - { - m_idx = parent->GetChildCount(); - m_name = wxString::Format(_(L("Layer %d")), m_idx + 1); - m_bmp = create_scaled_bitmap(nullptr, "row.png"); // FIXME: pass window ptr - - set_action_icon(); - } #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container // in another case you couldn't to add subitem for this item // it will be produce "segmentation fault" - if (type & (itInstanceRoot | itLayerRoot | itLayer)) + if (type & (itInstanceRoot | itLayerRoot)) m_container = true; #endif //__WXGTK__ } +ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const wxString& label_range, + const wxString& extruder, + const int idx /*= -1 */) : + m_parent(parent), + m_type(itLayer), + m_idx(idx), + m_extruder(extruder) +{ + m_idx = parent->GetChildCount(); + m_name = wxString::Format(_(L("Layer %s")), label_range); + m_bmp = create_scaled_bitmap(nullptr, "row.png"); // FIXME: pass window ptr + +#ifdef __WXGTK__ + // it's necessary on GTK because of control have to know if this item will be container + // in another case you couldn't to add subitem for this item + // it will be produce "segmentation fault" + m_container = true; +#endif //__WXGTK__ + + set_action_icon(); +} + void ObjectDataViewModelNode::set_action_icon() { m_action_icon_name = m_type & itObject ? "advanced_plus" : @@ -671,7 +686,7 @@ static bool append_root_node(ObjectDataViewModelNode *parent_node, (root_type&itLayerRoot) && get_root_idx(parent_node, itInstanceRoot)<0) parent_node->Append(*root_node); else if (root_type&itLayerRoot) - parent_node->Insert(*root_node, unsigned int(get_root_idx(parent_node, itInstanceRoot))); + parent_node->Insert(*root_node, static_cast(get_root_idx(parent_node, itInstanceRoot))); return true; } @@ -723,38 +738,38 @@ wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_i if (appended) ItemAdded(parent_item, layer_root_item);// notify control - AddLayersChild(layer_root_item); - - return wxDataViewItem((void*)layer_root_item); + return layer_root_item; } -wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item) +wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item, const std::string& label_range) { ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return wxDataViewItem(0); // get LayerRoot node ObjectDataViewModelNode *layer_root_node; + wxDataViewItem layer_root_item; - if (parent_node->GetType() & itLayerRoot) + if (parent_node->GetType() & itLayerRoot) { layer_root_node = parent_node; + layer_root_item = parent_item; + } else { const int root_idx = get_root_idx(parent_node, itLayerRoot); if (root_idx < 0) return wxDataViewItem(0); layer_root_node = parent_node->GetNthChild(root_idx); + layer_root_item = wxDataViewItem((void*)layer_root_node); } - const wxDataViewItem layer_root_item((void*)layer_root_node); - // Add layer node - ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, itLayer); + ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, label_range); layer_root_node->Append(layer_node); // notify control - const wxDataViewItem instance_item((void*)layer_node); - ItemAdded(layer_root_item, instance_item); + const wxDataViewItem layer_item((void*)layer_node); + ItemAdded(layer_root_item, layer_item); - return wxDataViewItem((void*)layer_node); + return layer_item; } wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) @@ -1138,6 +1153,11 @@ int ObjectDataViewModel::GetInstanceIdByItem(const wxDataViewItem& item) const return GetIdByItemAndType(item, itInstance); } +int ObjectDataViewModel::GetLayerIdByItem(const wxDataViewItem& item) const +{ + return GetIdByItemAndType(item, itLayer); +} + void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) { wxASSERT(item.IsOk()); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 424f7832a..b3d8ebc18 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -231,6 +231,11 @@ public: set_action_icon(); } + ObjectDataViewModelNode(ObjectDataViewModelNode* parent, + const wxString& label_range, + const wxString& extruder = wxEmptyString, + const int idx = -1 ); + ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type); ~ObjectDataViewModelNode() @@ -391,7 +396,7 @@ public: wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); - wxDataViewItem AddLayersChild(const wxDataViewItem &parent_item); + wxDataViewItem AddLayersChild(const wxDataViewItem &parent_item, const std::string& label_range); wxDataViewItem Delete(const wxDataViewItem &item); wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); void DeleteAll(); @@ -406,6 +411,7 @@ public: int GetObjectIdByItem(const wxDataViewItem& item) const; int GetVolumeIdByItem(const wxDataViewItem& item) const; int GetInstanceIdByItem(const wxDataViewItem& item) const; + int GetLayerIdByItem(const wxDataViewItem& item) const; void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); int GetRowByItem(const wxDataViewItem& item) const; bool IsEmpty() { return m_objects.empty(); } From e531d224e8b4649ec1a16e58e2d060cc1be271d9 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 30 May 2019 16:53:17 +0200 Subject: [PATCH 07/83] Implemented delete_layers_from_object() --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 2 +- src/slic3r/GUI/GUI_ObjectList.cpp | 45 +++++++++++++++++++++++------ src/slic3r/GUI/GUI_ObjectList.hpp | 1 + src/slic3r/GUI/wxExtensions.cpp | 7 +++-- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index f47260530..191a65386 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -46,7 +46,7 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : m_og->append_line(line); - m_bmp_delete = ScalableBitmap(parent, "cross"); + m_bmp_delete = ScalableBitmap(parent, "remove_copies"/*"cross"*/); m_bmp_add = ScalableBitmap(parent, "add_copies"); } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 934ad34fb..8043ee565 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1141,7 +1141,7 @@ wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu) wxMenuItem* ObjectList::append_menu_item_layers_editing(wxMenu* menu) { return append_menu_item(menu, wxID_ANY, _(L("Edit Layers")), "", - [this](wxCommandEvent&) { layers_editing(); }, "table.png", menu); + [this](wxCommandEvent&) { layers_editing(); }, "layers", menu); } wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_) @@ -1650,7 +1650,7 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) else if (type == itInstanceRoot && obj_idx != -1) del_instances_from_object(obj_idx); else if ((type & itLayerRoot) && obj_idx != -1) - /*del_layers_from_object(obj_idx)*/; + del_layers_from_object(obj_idx); else if (idx == -1) return; else if (!del_subobject_from_object(obj_idx, idx, type)) @@ -1692,6 +1692,13 @@ void ObjectList::del_instances_from_object(const int obj_idx) changed_object(obj_idx); } +void ObjectList::del_layers_from_object(const int obj_idx) +{ + object(obj_idx)->layer_height_ranges.clear(); // ? #ys_FIXME + + changed_object(obj_idx); +} + bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type) { if (obj_idx == 1000) @@ -1732,6 +1739,13 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con object->delete_instance(idx); } else if (type == itLayer) { + t_layer_height_ranges::iterator layer_range = object->layer_height_ranges.begin(); + int id = idx; + while (id > 0 && layer_range != object->layer_height_ranges.end()) { + layer_range++; + id--; + } + object->layer_height_ranges.erase(layer_range); } else return false; @@ -1808,12 +1822,12 @@ void ObjectList::layers_editing() // ---<<<--- Just for testing layers_item = m_objects_model->AddLayersRoot(obj_item); - } - for (const auto range : object(obj_idx)->layer_height_ranges) - { - const std::string label = (boost::format("(%.2f-%.2f)") % range.first.first % range.first.second).str(); - m_objects_model->AddLayersChild(layers_item, label); + for (const auto range : object(obj_idx)->layer_height_ranges) + { + const std::string label = (boost::format(" %.2f-%.2f ") % range.first.first % range.first.second).str(); + m_objects_model->AddLayersChild(layers_item, label); + } } select_item(layers_item); @@ -2168,9 +2182,22 @@ void ObjectList::remove() if (m_objects_model->GetParent(item) == wxDataViewItem(0)) delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1); else { - if (sels.size() == 1) - select_item(m_objects_model->GetParent(item)); +// if (sels.size() == 1) +// select_item(m_objects_model->GetParent(item)); + wxDataViewItem parent = m_objects_model->GetParent(item); + if (sels.size() == 1) { + if (!(m_objects_model->GetItemType(item) & itLayer)) { + select_item(parent); + parent = wxDataViewItem(0); + } + else if (m_objects_model->GetChildren(parent, wxDataViewItemArray()) == 1) + parent = m_objects_model->GetTopParent(item); + } + del_subobject_item(item); + + if (sels.size() == 1 && parent) + select_item(parent); } } } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 764aac1e8..6963805e9 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -227,6 +227,7 @@ public: void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(); void del_instances_from_object(const int obj_idx); + void del_layers_from_object(const int obj_idx); bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(); void layers_editing(); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 989a97676..4511ab8ac 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -450,7 +450,7 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent } else if (type == itLayerRoot) { - m_bmp = create_scaled_bitmap(nullptr, "table.png"); // FIXME: pass window ptr + m_bmp = create_scaled_bitmap(nullptr, "layers"); // FIXME: pass window ptr m_name = _(L("Layers")); } @@ -473,8 +473,9 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent m_extruder(extruder) { m_idx = parent->GetChildCount(); - m_name = wxString::Format(_(L("Layer %s")), label_range); - m_bmp = create_scaled_bitmap(nullptr, "row.png"); // FIXME: pass window ptr +// m_name = wxString::Format(_(L("Layer %s (mm)")), label_range); + m_name = _(L("Range")) + label_range + "(" + _(L("mm")) + ")"; + m_bmp = create_scaled_bitmap(nullptr, "layers_white"); // FIXME: pass window ptr #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container From 38641ef5784f8607f6be77e3242970684fed3810 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 31 May 2019 10:54:52 +0200 Subject: [PATCH 08/83] ObjectLayers::del_layer_range() -> delete a layers range using "Del" button from ObjectLayers sizer --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 61 ++++++++++++----------------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 2 - src/slic3r/GUI/GUI_ObjectList.cpp | 35 ++++++++++++++++- src/slic3r/GUI/GUI_ObjectList.hpp | 2 + src/slic3r/GUI/wxExtensions.cpp | 25 +++++++++--- src/slic3r/GUI/wxExtensions.hpp | 3 ++ 6 files changed, 84 insertions(+), 44 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 191a65386..5ff650e86 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -16,8 +16,6 @@ namespace Slic3r namespace GUI { -typedef std::map t_layer_height_ranges; - #define field_width 8 ObjectLayers::ObjectLayers(wxWindow* parent) : @@ -76,42 +74,32 @@ static Line create_new_layer(const t_layer_height_ranges::value_type& layer) void ObjectLayers::create_layers_list() { - auto create_btns = [this](wxWindow* parent) { - auto sizer = new wxBoxSizer(wxHORIZONTAL); - - auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); - del_btn->SetToolTip(_(L("Remove layer"))); - - sizer->Add(del_btn, 0, wxRIGHT, em_unit(parent)); - - del_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { - del_layer(); -// wxTheApp->CallAfter([this]() { -// wxWindowUpdateLocker noUpdates(m_parent); -// update_layers_list(); -// m_parent->Layout(); -// }); - }); - - auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); - add_btn->SetToolTip(_(L("Add layer"))); - - sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); - - add_btn->Bind(wxEVT_BUTTON, [this](wxEvent &event) { - add_layer(); -// wxTheApp->CallAfter([this]() { -// wxWindowUpdateLocker noUpdates(m_parent); -// update_layers_list(); -// m_parent->Layout(); -// }); - }); - - return sizer; - }; - for (const auto layer : m_object->layer_height_ranges) { + auto create_btns = [this, layer](wxWindow* parent) { + auto sizer = new wxBoxSizer(wxHORIZONTAL); + + auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); + del_btn->SetToolTip(_(L("Remove layer"))); + + sizer->Add(del_btn, 0, wxRIGHT, em_unit(parent)); + + del_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { + wxGetApp().obj_list()->del_layer_range(layer.first); + }); + + auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); + add_btn->SetToolTip(_(L("Add layer"))); + + sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); + + add_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { + wxGetApp().obj_list()->add_layer_range(layer.first); + }); + + return sizer; + }; + Line line = create_new_layer(layer); line.append_widget(create_btns); m_og->append_line(line); @@ -122,6 +110,7 @@ void ObjectLayers::create_layer(int id) { t_layer_height_ranges::iterator layer_range = m_object->layer_height_ranges.begin(); + // May be not a best solution #ys_FIXME while (id > 0 && layer_range != m_object->layer_height_ranges.end()) { layer_range++; id--; diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index b9e9efb14..0b209d523 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -27,8 +27,6 @@ public: void create_layers_list(); void create_layer(int id); void update_layers_list(); - void add_layer() {}; - void del_layer() {}; void UpdateAndShow(const bool show) override; void msw_rescale(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 8043ee565..cb815fc72 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1812,7 +1812,7 @@ void ObjectList::layers_editing() wxDataViewItem obj_item = m_objects_model->GetTopParent(item); - wxDataViewItem layers_item = m_objects_model->GetItemByType(obj_item, itLayerRoot); + wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(obj_item); if (!layers_item.IsOk()) { // --->>>--- Just for testing @@ -2202,6 +2202,39 @@ void ObjectList::remove() } } +void ObjectList::del_layer_range(const std::pair& range) +{ + const int obj_idx = get_selected_obj_idx(); + if (obj_idx < 0) return; + + t_layer_height_ranges& ranges = object(obj_idx)->layer_height_ranges; + + wxDataViewItem selectable_item = GetSelection(); + int layer_idx = 0; + + if (ranges.size() == 1) + selectable_item = m_objects_model->GetParent(selectable_item); + else { + // May be not a best solution #ys_FIXME + t_layer_height_ranges::iterator layer_selected = ranges.find(range); + t_layer_height_ranges::iterator it = ranges.begin(); + while (it != layer_selected) { + it++; + layer_idx++; + } + } + + wxDataViewItem layer_item = m_objects_model->GetItemByLayerId(obj_idx, layer_idx); + del_subobject_item(layer_item); + + select_item(selectable_item); +} + +void ObjectList::add_layer_range(const std::pair& range) +{ + +} + void ObjectList::init_objects() { m_objects = wxGetApp().model_objects(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 6963805e9..388369137 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -270,6 +270,8 @@ public: // Remove objects/sub-object from the list void remove(); + void del_layer_range(const std::pair& range); + void add_layer_range(const std::pair& range); void init_objects(); bool multiple_selection() const ; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 4511ab8ac..dbe19dff5 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1098,25 +1098,35 @@ wxDataViewItem ObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_id return wxDataViewItem(0); } -wxDataViewItem ObjectDataViewModel::GetItemByInstanceId(int obj_idx, int inst_idx) +wxDataViewItem ObjectDataViewModel::GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type) { if (obj_idx >= m_objects.size() || obj_idx < 0) { printf("Error! Out of objects range.\n"); return wxDataViewItem(0); } - auto instances_item = GetInstanceRootItem(wxDataViewItem(m_objects[obj_idx])); - if (!instances_item) + auto item = GetItemByType(wxDataViewItem(m_objects[obj_idx]), parent_type); + if (!item) return wxDataViewItem(0); - auto parent = (ObjectDataViewModelNode*)instances_item.GetID();; + auto parent = (ObjectDataViewModelNode*)item.GetID();; for (size_t i = 0; i < parent->GetChildCount(); i++) - if (parent->GetNthChild(i)->m_idx == inst_idx) + if (parent->GetNthChild(i)->m_idx == sub_obj_idx) return wxDataViewItem(parent->GetNthChild(i)); return wxDataViewItem(0); } +wxDataViewItem ObjectDataViewModel::GetItemByInstanceId(int obj_idx, int inst_idx) +{ + return GetItemById(obj_idx, inst_idx, itInstanceRoot); +} + +wxDataViewItem ObjectDataViewModel::GetItemByLayerId(int obj_idx, int layer_idx) +{ + return GetItemById(obj_idx, layer_idx, itLayerRoot); +} + int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const { wxASSERT(item.IsOk()); @@ -1447,6 +1457,11 @@ wxDataViewItem ObjectDataViewModel::GetInstanceRootItem(const wxDataViewItem &it return GetItemByType(item, itInstanceRoot); } +wxDataViewItem ObjectDataViewModel::GetLayerRootItem(const wxDataViewItem &item) const +{ + return GetItemByType(item, itLayerRoot); +} + bool ObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const { if (!item.IsOk()) diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index b3d8ebc18..23150a915 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -404,8 +404,10 @@ public: void DeleteVolumeChildren(wxDataViewItem& parent); void DeleteSettings(const wxDataViewItem& parent); wxDataViewItem GetItemById(int obj_idx); + wxDataViewItem GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type); wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx); + wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx); int GetIdByItem(const wxDataViewItem& item) const; int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; int GetObjectIdByItem(const wxDataViewItem& item) const; @@ -460,6 +462,7 @@ public: ItemType type) const; wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const; wxDataViewItem GetInstanceRootItem(const wxDataViewItem &item) const; + wxDataViewItem GetLayerRootItem(const wxDataViewItem &item) const; bool IsSettingsItem(const wxDataViewItem &item) const; void UpdateSettingsDigest( const wxDataViewItem &item, const std::vector& categories); From 5f4b7a5292dce6c5e531de06d850006b81f3214c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 31 May 2019 15:29:09 +0200 Subject: [PATCH 09/83] ObjectLayers::add_layer_range() -> add a layers range using "Add" button from ObjectLayers sizer --- src/slic3r/GUI/GUI_ObjectList.cpp | 101 ++++++++++++++++++++++++++---- src/slic3r/GUI/GUI_ObjectList.hpp | 4 ++ src/slic3r/GUI/wxExtensions.cpp | 25 ++++++-- src/slic3r/GUI/wxExtensions.hpp | 8 ++- 4 files changed, 116 insertions(+), 22 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index cb815fc72..88d7df6cc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1810,27 +1810,26 @@ void ObjectList::layers_editing() if (!item || obj_idx < 0) return; - wxDataViewItem obj_item = m_objects_model->GetTopParent(item); - + const wxDataViewItem obj_item = m_objects_model->GetTopParent(item); wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(obj_item); + + // if it doesn't exist now if (!layers_item.IsOk()) { - // --->>>--- Just for testing - object(obj_idx)->layer_height_ranges[{ 0.0f, 0.2f }] = 0.1f; - object(obj_idx)->layer_height_ranges[{ 0.2f, 0.4f }] = 0.05f; - object(obj_idx)->layer_height_ranges[{ 0.4f, 0.6f }] = 0.2f; - // ---<<<--- Just for testing - + // create LayerRoor item layers_item = m_objects_model->AddLayersRoot(obj_item); + + if (object(obj_idx)->layer_height_ranges.empty()) + object(obj_idx)->layer_height_ranges[{ 0.0f, 0.2f }] = 0.1f;// some default value + // and create Layer item(s) according to the layer_height_ranges for (const auto range : object(obj_idx)->layer_height_ranges) - { - const std::string label = (boost::format(" %.2f-%.2f ") % range.first.first % range.first.second).str(); - m_objects_model->AddLayersChild(layers_item, label); - } + add_layer_item(range.first, layers_item); } + // select LayerRoor item and expand select_item(layers_item); + Expand(layers_item); } bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume) @@ -2230,7 +2229,83 @@ void ObjectList::del_layer_range(const std::pair& range) select_item(selectable_item); } -void ObjectList::add_layer_range(const std::pair& range) +void ObjectList::add_layer_range(const t_layer_height_range& range) +{ + const int obj_idx = get_selected_obj_idx(); + if (obj_idx < 0) return; + + wxDataViewItem layers_item = GetSelection(); + + t_layer_height_ranges& ranges = object(obj_idx)->layer_height_ranges; + + const t_layer_height_ranges::iterator selected_range = ranges.find(range); + const t_layer_height_ranges::iterator last_range = --ranges.end(); + + if (selected_range->first == last_range->first) + { + const t_layer_height_range new_range = { last_range->first.second, last_range->first.second + 0.2f }; + ranges[new_range] = last_range->second; + add_layer_item(new_range, layers_item); + } + else + { + int layer_idx = 0; + t_layer_height_ranges::iterator next_range = ++ranges.find(range); + + // May be not a best solution #ys_FIXME + t_layer_height_ranges::iterator it = ranges.begin(); + while (it != next_range && it != ranges.end()) { + layer_idx++; + it++; + } + + if (selected_range->first.second == next_range->first.first) + { + const coordf_t delta = (next_range->first.second - next_range->first.first); + if (delta < 0.05f) // next range devision has no mean + return; + + const coordf_t midl_layer = next_range->first.first + 0.5f * delta; + const coordf_t old_height = next_range->second; + t_layer_height_range new_range = { midl_layer, next_range->first.second }; + + // delete old layer + + wxDataViewItem layer_item = m_objects_model->GetItemByLayerId(obj_idx, layer_idx); + del_subobject_item(layer_item); + + // create new 2 layers instead of deleted one + + ranges[new_range] = old_height; + add_layer_item(new_range, layers_item, layer_idx); + + new_range = { selected_range->first.second, midl_layer }; + ranges[new_range] = selected_range->second; + add_layer_item(new_range, layers_item, layer_idx); + } + else + { + const t_layer_height_range new_range = { selected_range->first.second, next_range->first.first }; + ranges[new_range] = selected_range->second; + add_layer_item(new_range, layers_item, layer_idx); + } + } + + changed_object(obj_idx); + + // select item to update layers sizer + select_item(layers_item); +} + +void ObjectList::add_layer_item(const t_layer_height_range& range, + const wxDataViewItem layers_item, + const int layer_idx /* = -1*/) +{ + const std::string label = (boost::format(" %.2f-%.2f ") % range.first % range.second).str(); + m_objects_model->AddLayersChild(layers_item, label, layer_idx); +} + +void ObjectList::edit_layer_range(const std::pair& range) { } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 388369137..15cddd318 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -272,6 +272,10 @@ public: void remove(); void del_layer_range(const std::pair& range); void add_layer_range(const std::pair& range); + void add_layer_item (const std::pair& range, + const wxDataViewItem layers_item, + const int layer_idx = -1); + void edit_layer_range(const std::pair& range); void init_objects(); bool multiple_selection() const ; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index dbe19dff5..adc2e6d07 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -465,14 +465,22 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const wxString& label_range, - const wxString& extruder, - const int idx /*= -1 */) : + const int idx /*= -1 */, + const wxString& extruder) : m_parent(parent), m_type(itLayer), m_idx(idx), m_extruder(extruder) { - m_idx = parent->GetChildCount(); + const int children_cnt = parent->GetChildCount(); + if (idx < 0) + m_idx = children_cnt; + else + { + // update indexes for another Laeyr Nodes + for (int i = m_idx; i < children_cnt; i++) + parent->GetNthChild(i)->SetIdx(i + 1); + } // m_name = wxString::Format(_(L("Layer %s (mm)")), label_range); m_name = _(L("Range")) + label_range + "(" + _(L("mm")) + ")"; m_bmp = create_scaled_bitmap(nullptr, "layers_white"); // FIXME: pass window ptr @@ -742,7 +750,9 @@ wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_i return layer_root_item; } -wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item, const std::string& label_range) +wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item, + const std::string& label_range, + const int index /* = -1*/) { ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return wxDataViewItem(0); @@ -763,8 +773,11 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_ } // Add layer node - ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, label_range); - layer_root_node->Append(layer_node); + ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, label_range, index); + if (index < 0) + layer_root_node->Append(layer_node); + else + layer_root_node->Insert(layer_node, index); // notify control const wxDataViewItem layer_item((void*)layer_node); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 23150a915..775d89a3b 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -233,8 +233,8 @@ public: ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const wxString& label_range, - const wxString& extruder = wxEmptyString, - const int idx = -1 ); + const int idx = -1, + const wxString& extruder = wxEmptyString ); ObjectDataViewModelNode(ObjectDataViewModelNode* parent, const ItemType type); @@ -396,7 +396,9 @@ public: wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); - wxDataViewItem AddLayersChild(const wxDataViewItem &parent_item, const std::string& label_range); + wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item, + const std::string& label_range, + const int index = -1); wxDataViewItem Delete(const wxDataViewItem &item); wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); void DeleteAll(); From e09207e27e28d37e1873fe4f1c63bbbad3faf6d5 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 31 May 2019 15:36:38 +0200 Subject: [PATCH 10/83] Fixed OSX and Linux build --- src/slic3r/GUI/GUI_ObjectList.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 88d7df6cc..d9e1e8e82 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2189,8 +2189,11 @@ void ObjectList::remove() select_item(parent); parent = wxDataViewItem(0); } - else if (m_objects_model->GetChildren(parent, wxDataViewItemArray()) == 1) - parent = m_objects_model->GetTopParent(item); + else { + wxDataViewItemArray children; + if (m_objects_model->GetChildren(parent, children) == 1) + parent = m_objects_model->GetTopParent(item); + } } del_subobject_item(item); From 51b18fddeb1b22310171e27b8e606cc0d621f17d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 3 Jun 2019 15:35:21 +0200 Subject: [PATCH 11/83] Changed data types --- src/libslic3r/Model.hpp | 2 ++ src/libslic3r/Slicing.hpp | 3 ++ src/slic3r/GUI/GUI_ObjectLayers.cpp | 37 ++++++++++++++---------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 45 ++++++++++++++++------------- src/slic3r/GUI/GUI_ObjectList.hpp | 1 + 6 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 41bf5bd4b..d3066f33f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -179,6 +179,8 @@ public: DynamicPrintConfig config; // Variation of a layer thickness for spans of Z coordinates. t_layer_height_ranges layer_height_ranges; + // Variation of a layer thickness for spans of Z coordinates. + t_layer_config_ranges layer_config_ranges; // Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers. // The pairs of are packed into a 1D array. std::vector layer_height_profile; diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index fa5a12f9c..c3278dc0d 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -11,6 +11,8 @@ #include "libslic3r.h" #include "Utils.hpp" +#include "PrintConfig.hpp" + namespace Slic3r { @@ -129,6 +131,7 @@ inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters typedef std::pair t_layer_height_range; typedef std::map t_layer_height_ranges; +typedef std::map t_layer_config_ranges; extern std::vector layer_height_profile_from_ranges( const SlicingParameters &slicing_params, diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 5ff650e86..8dae64f3c 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -23,6 +23,8 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : { m_og->label_width = 1; m_og->set_grid_vgap(5); + + m_og->m_on_change = std::bind(&ObjectLayers::on_change, this, std::placeholders::_1, std::placeholders::_2); // Legend for object layers Line line = Line{ "", "" }; @@ -33,9 +35,9 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : def.type = coString; def.width = field_width; - for (const std::string axis : { "Min Z", "Max Z", "Layer height" }) { - def.set_default_value(new ConfigOptionString{ axis }); - std::string label = boost::algorithm::replace_all_copy(axis, " ", "_"); + for (const std::string col : { "Min Z", "Max Z", "Layer height" }) { + def.set_default_value(new ConfigOptionString{ col }); + std::string label = boost::algorithm::replace_all_copy(col, " ", "_"); boost::algorithm::to_lower(label); line.append_option(Option(def, label + "_legend")); @@ -48,7 +50,7 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : m_bmp_add = ScalableBitmap(parent, "add_copies"); } -static Line create_new_layer(const t_layer_height_ranges::value_type& layer) +static Line create_new_layer(const t_layer_config_ranges::value_type& layer, const int idx) { Line line = Line{ "", "" }; ConfigOptionDef def; @@ -57,16 +59,16 @@ static Line create_new_layer(const t_layer_height_ranges::value_type& layer) def.type = coFloat; def.width = field_width; - std::string label = (boost::format("min_z_%.2f") % layer.first.first).str(); + std::string label = (boost::format("min_z_%d") % idx).str(); def.set_default_value(new ConfigOptionFloat(layer.first.first)); line.append_option(Option(def, label)); - label = (boost::format("max_z_%.2f") % layer.first.second).str(); + label = (boost::format("max_z_%d") % idx).str(); def.set_default_value(new ConfigOptionFloat(layer.first.second)); line.append_option(Option(def, label)); - label = (boost::format("layer_height_%.2f_%.2f") % layer.first.first % layer.first.second).str(); - def.set_default_value(new ConfigOptionFloat(layer.second)); + label = (boost::format("layer_height_%d") % idx).str(); + def.set_default_value(new ConfigOptionFloat(layer.second.option("layer_height")->getFloat())); line.append_option(Option(def, label)); return line; @@ -74,7 +76,7 @@ static Line create_new_layer(const t_layer_height_ranges::value_type& layer) void ObjectLayers::create_layers_list() { - for (const auto layer : m_object->layer_height_ranges) + for (const auto layer : m_object->layer_config_ranges) { auto create_btns = [this, layer](wxWindow* parent) { auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -100,7 +102,7 @@ void ObjectLayers::create_layers_list() return sizer; }; - Line line = create_new_layer(layer); + Line line = create_new_layer(layer, m_og->get_grid_sizer()->GetEffectiveRowsCount()-1); line.append_widget(create_btns); m_og->append_line(line); } @@ -108,15 +110,15 @@ void ObjectLayers::create_layers_list() void ObjectLayers::create_layer(int id) { - t_layer_height_ranges::iterator layer_range = m_object->layer_height_ranges.begin(); + t_layer_config_ranges::iterator layer_range = m_object->layer_config_ranges.begin(); // May be not a best solution #ys_FIXME - while (id > 0 && layer_range != m_object->layer_height_ranges.end()) { - layer_range++; + while (id > 0 && layer_range != m_object->layer_config_ranges.end()) { + ++layer_range; id--; } - m_og->append_line(create_new_layer(*layer_range)); + m_og->append_line(create_new_layer(*layer_range, m_og->get_grid_sizer()->GetEffectiveRowsCount()-1)); } void ObjectLayers::update_layers_list() @@ -134,7 +136,7 @@ void ObjectLayers::update_layers_list() if (!(type & (itLayerRoot | itLayer))) return; m_object = objects_ctrl->object(obj_idx); - if (!m_object || m_object->layer_height_ranges.empty()) return; + if (!m_object || m_object->layer_config_ranges.empty()) return; // Delete all controls from options group except of the legends @@ -175,5 +177,10 @@ void ObjectLayers::msw_rescale() m_bmp_add.msw_rescale(); } +void ObjectLayers::on_change(t_config_option_key opt_key, const boost::any& value) +{ + +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 0b209d523..6280a7554 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -30,6 +30,7 @@ public: void UpdateAndShow(const bool show) override; void msw_rescale(); + void on_change(t_config_option_key opt_key, const boost::any& value); }; }} diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index d9e1e8e82..9b826f5d8 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -700,10 +700,11 @@ void ObjectList::show_context_menu() if (item) { const ItemType type = m_objects_model->GetItemType(item); - if (!(type & (itObject | itVolume | itInstance))) + if (!(type & (itObject | itVolume | itLayer | itInstance))) return; wxMenu* menu = type & itInstance ? &m_menu_instance : + type & itLayer ? &m_menu_layer : m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part : printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object; @@ -1694,7 +1695,7 @@ void ObjectList::del_instances_from_object(const int obj_idx) void ObjectList::del_layers_from_object(const int obj_idx) { - object(obj_idx)->layer_height_ranges.clear(); // ? #ys_FIXME + object(obj_idx)->layer_config_ranges.clear(); changed_object(obj_idx); } @@ -1739,13 +1740,13 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con object->delete_instance(idx); } else if (type == itLayer) { - t_layer_height_ranges::iterator layer_range = object->layer_height_ranges.begin(); + t_layer_config_ranges::iterator layer_range = object->layer_config_ranges.begin(); int id = idx; - while (id > 0 && layer_range != object->layer_height_ranges.end()) { + while (id > 0 && layer_range != object->layer_config_ranges.end()) { layer_range++; id--; } - object->layer_height_ranges.erase(layer_range); + object->layer_config_ranges.erase(layer_range); } else return false; @@ -1816,14 +1817,16 @@ void ObjectList::layers_editing() // if it doesn't exist now if (!layers_item.IsOk()) { - // create LayerRoor item + // create LayerRoot item layers_item = m_objects_model->AddLayersRoot(obj_item); - - if (object(obj_idx)->layer_height_ranges.empty()) - object(obj_idx)->layer_height_ranges[{ 0.0f, 0.2f }] = 0.1f;// some default value - // and create Layer item(s) according to the layer_height_ranges - for (const auto range : object(obj_idx)->layer_height_ranges) + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; + + if (ranges.empty()) + ranges[{ 0.0f, 0.2f }] = *DynamicPrintConfig::new_from_defaults_keys({"layer_height"});// some default value + + // and create Layer item(s) according to the layer_config_ranges + for (const auto range : ranges) add_layer_item(range.first, layers_item); } @@ -2239,10 +2242,10 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) wxDataViewItem layers_item = GetSelection(); - t_layer_height_ranges& ranges = object(obj_idx)->layer_height_ranges; + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; - const t_layer_height_ranges::iterator selected_range = ranges.find(range); - const t_layer_height_ranges::iterator last_range = --ranges.end(); + const t_layer_config_ranges::iterator selected_range = ranges.find(range); + const t_layer_config_ranges::iterator last_range = --ranges.end(); if (selected_range->first == last_range->first) { @@ -2253,13 +2256,13 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) else { int layer_idx = 0; - t_layer_height_ranges::iterator next_range = ++ranges.find(range); + t_layer_config_ranges::iterator next_range = ++ranges.find(range); // May be not a best solution #ys_FIXME - t_layer_height_ranges::iterator it = ranges.begin(); + t_layer_config_ranges::iterator it = ranges.begin(); while (it != next_range && it != ranges.end()) { layer_idx++; - it++; + ++it; } if (selected_range->first.second == next_range->first.first) @@ -2269,7 +2272,8 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) return; const coordf_t midl_layer = next_range->first.first + 0.5f * delta; - const coordf_t old_height = next_range->second; + // #ys_FIXME May be it should be copied just a "layer_height" option + const /*coordf_t*/auto old_config = next_range->second; t_layer_height_range new_range = { midl_layer, next_range->first.second }; // delete old layer @@ -2279,7 +2283,7 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) // create new 2 layers instead of deleted one - ranges[new_range] = old_height; + ranges[new_range] = old_config; add_layer_item(new_range, layers_item, layer_idx); new_range = { selected_range->first.second, midl_layer }; @@ -2996,7 +3000,8 @@ void ObjectList::msw_rescale() for (MenuWithSeparators* menu : { &m_menu_object, &m_menu_part, &m_menu_sla_object, - &m_menu_instance }) + &m_menu_instance, + &m_menu_layer }) msw_rescale_menu(menu); Layout(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 15cddd318..5b4fd4c49 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -119,6 +119,7 @@ class ObjectList : public wxDataViewCtrl MenuWithSeparators m_menu_part; MenuWithSeparators m_menu_sla_object; MenuWithSeparators m_menu_instance; + MenuWithSeparators m_menu_layer; wxMenuItem* m_menu_item_settings { nullptr }; wxMenuItem* m_menu_item_split_instances { nullptr }; From 79a89c4c8fd5b09374ba981fea7c3a3da6711236 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 4 Jun 2019 11:51:25 +0200 Subject: [PATCH 12/83] Some code review for avoid use of OptionsGroup --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 145 ++++++++++++++-------------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 6 +- 2 files changed, 77 insertions(+), 74 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 8dae64f3c..1bd57e0d8 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -21,90 +21,100 @@ namespace GUI ObjectLayers::ObjectLayers(wxWindow* parent) : OG_Settings(parent, true) { - m_og->label_width = 1; - m_og->set_grid_vgap(5); + m_grid_sizer = new wxFlexGridSizer(3, 5, 5); // "Min Z", "Max Z", "Layer height" & buttons sizer + m_grid_sizer->SetFlexibleDirection(wxHORIZONTAL); - m_og->m_on_change = std::bind(&ObjectLayers::on_change, this, std::placeholders::_1, std::placeholders::_2); - // Legend for object layers - Line line = Line{ "", "" }; - - ConfigOptionDef def; - def.label = ""; - def.gui_type = "legend"; - def.type = coString; - def.width = field_width; - for (const std::string col : { "Min Z", "Max Z", "Layer height" }) { - def.set_default_value(new ConfigOptionString{ col }); - std::string label = boost::algorithm::replace_all_copy(col, " ", "_"); - boost::algorithm::to_lower(label); - line.append_option(Option(def, label + "_legend")); + auto temp = new wxStaticText(m_parent, wxID_ANY, _(L(col)), wxDefaultPosition, /*size*/wxDefaultSize, wxST_ELLIPSIZE_MIDDLE); + temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + temp->SetBackgroundStyle(wxBG_STYLE_PAINT); + temp->SetFont(wxGetApp().bold_font()); - m_legends.push_back(label + "_legend"); + m_grid_sizer->Add(temp); } - m_og->append_line(line); + m_og->sizer->Clear(true); + m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX ? 0 : 5); m_bmp_delete = ScalableBitmap(parent, "remove_copies"/*"cross"*/); m_bmp_add = ScalableBitmap(parent, "add_copies"); } -static Line create_new_layer(const t_layer_config_ranges::value_type& layer, const int idx) +wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges::value_type& layer) { - Line line = Line{ "", "" }; - ConfigOptionDef def; - def.label = ""; - def.gui_type = ""; - def.type = coFloat; - def.width = field_width; + auto size = wxSize(field_width * em_unit(m_parent), wxDefaultCoord); - std::string label = (boost::format("min_z_%d") % idx).str(); - def.set_default_value(new ConfigOptionFloat(layer.first.first)); - line.append_option(Option(def, label)); + // Add control for the "Min Z" + wxString text_value = double_to_string(layer.first.first); + auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_PROCESS_ENTER); + temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - label = (boost::format("max_z_%d") % idx).str(); - def.set_default_value(new ConfigOptionFloat(layer.first.second)); - line.append_option(Option(def, label)); + temp->Bind(wxEVT_TEXT_ENTER, ([this, temp](wxEvent& e) + { - label = (boost::format("layer_height_%d") % idx).str(); - def.set_default_value(new ConfigOptionFloat(layer.second.option("layer_height")->getFloat())); - line.append_option(Option(def, label)); + }), temp->GetId()); - return line; + temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e) + { + + }), temp->GetId()); + + + temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event) + { + // select all text using Ctrl+A + if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) + temp->SetSelection(-1, -1); //select all + event.Skip(); + })); + + m_grid_sizer->Add(temp); + + // Add control for the "Max Z" + text_value = double_to_string(layer.first.second); + temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_PROCESS_ENTER); + temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + + m_grid_sizer->Add(temp); + + // Add control for the "Layer height" + auto sizer = new wxBoxSizer(wxHORIZONTAL); + + text_value = double_to_string(layer.second.option("layer_height")->getFloat()); + temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_PROCESS_ENTER); + temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + sizer->Add(temp); + + m_grid_sizer->Add(sizer); + + return sizer; } void ObjectLayers::create_layers_list() { for (const auto layer : m_object->layer_config_ranges) { - auto create_btns = [this, layer](wxWindow* parent) { - auto sizer = new wxBoxSizer(wxHORIZONTAL); + auto sizer = create_layer_without_buttons(layer); - auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); - del_btn->SetToolTip(_(L("Remove layer"))); + wxWindow* parent = m_parent; + auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); + del_btn->SetToolTip(_(L("Remove layer"))); - sizer->Add(del_btn, 0, wxRIGHT, em_unit(parent)); + sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, em_unit(parent)); - del_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { - wxGetApp().obj_list()->del_layer_range(layer.first); - }); + del_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { + wxGetApp().obj_list()->del_layer_range(layer.first); + }); - auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); - add_btn->SetToolTip(_(L("Add layer"))); + auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); + add_btn->SetToolTip(_(L("Add layer"))); - sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); + sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); - add_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { - wxGetApp().obj_list()->add_layer_range(layer.first); - }); - - return sizer; - }; - - Line line = create_new_layer(layer, m_og->get_grid_sizer()->GetEffectiveRowsCount()-1); - line.append_widget(create_btns); - m_og->append_line(line); + add_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { + wxGetApp().obj_list()->add_layer_range(layer.first); + }); } } @@ -117,8 +127,8 @@ void ObjectLayers::create_layer(int id) ++layer_range; id--; } - - m_og->append_line(create_new_layer(*layer_range, m_og->get_grid_sizer()->GetEffectiveRowsCount()-1)); + + create_layer_without_buttons(*layer_range); } void ObjectLayers::update_layers_list() @@ -140,19 +150,17 @@ void ObjectLayers::update_layers_list() // Delete all controls from options group except of the legends - auto grid_sizer = m_og->get_grid_sizer(); - const int cols = grid_sizer->GetEffectiveColsCount(); - const int rows = grid_sizer->GetEffectiveRowsCount(); + const int cols = m_grid_sizer->GetEffectiveColsCount(); + const int rows = m_grid_sizer->GetEffectiveRowsCount(); for (int idx = cols*rows-1; idx >= cols; idx--) { - wxSizerItem* t = grid_sizer->GetItem(idx); + wxSizerItem* t = m_grid_sizer->GetItem(idx); if (t->IsSizer()) t->GetSizer()->Clear(true); - grid_sizer->Remove(idx); + else + t->DeleteWindows(); + m_grid_sizer->Remove(idx); } - m_og->clear_fields_except_of(m_legends); - - // Add new control according to the selected item if (type & itLayerRoot) @@ -177,10 +185,5 @@ void ObjectLayers::msw_rescale() m_bmp_add.msw_rescale(); } -void ObjectLayers::on_change(t_config_option_key opt_key, const boost::any& value) -{ - -} - } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 6280a7554..329452950 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -18,19 +18,19 @@ class ObjectLayers : public OG_Settings ScalableBitmap m_bmp_add; ModelObject* m_object {nullptr}; - std::vector m_legends; + wxFlexGridSizer* m_grid_sizer; public: ObjectLayers(wxWindow* parent); ~ObjectLayers() {} - void create_layers_list(); + wxSizer* create_layer_without_buttons(const std::map, DynamicPrintConfig>::value_type& layer); void create_layer(int id); + void create_layers_list(); void update_layers_list(); void UpdateAndShow(const bool show) override; void msw_rescale(); - void on_change(t_config_option_key opt_key, const boost::any& value); }; }} From 475696167884ac80cf554b9dd6bad772facd3e8c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 4 Jun 2019 15:22:29 +0200 Subject: [PATCH 13/83] Added LayerRangeEditor class for universally editing of the layer_range's parameters + Implemented layer_height editing --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 91 +++++++++++++++++++---------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 16 +++++ src/slic3r/GUI/GUI_ObjectList.cpp | 8 ++- src/slic3r/GUI/GUI_ObjectList.hpp | 2 +- 4 files changed, 85 insertions(+), 32 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 1bd57e0d8..bba39f76a 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -46,44 +46,21 @@ wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges: auto size = wxSize(field_width * em_unit(m_parent), wxDefaultCoord); // Add control for the "Min Z" - wxString text_value = double_to_string(layer.first.first); - auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_PROCESS_ENTER); - temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - - temp->Bind(wxEVT_TEXT_ENTER, ([this, temp](wxEvent& e) - { - - }), temp->GetId()); - - temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e) - { - - }), temp->GetId()); - - - temp->Bind(wxEVT_CHAR, ([temp](wxKeyEvent& event) - { - // select all text using Ctrl+A - if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) - temp->SetSelection(-1, -1); //select all - event.Skip(); - })); - + auto temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.first), size); m_grid_sizer->Add(temp); // Add control for the "Max Z" - text_value = double_to_string(layer.first.second); - temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_PROCESS_ENTER); - temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); - + temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.second), size); m_grid_sizer->Add(temp); // Add control for the "Layer height" auto sizer = new wxBoxSizer(wxHORIZONTAL); - text_value = double_to_string(layer.second.option("layer_height")->getFloat()); - temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, wxTE_PROCESS_ENTER); - temp->SetFont(Slic3r::GUI::wxGetApp().normal_font()); + const wxString text_value = double_to_string(layer.second.option("layer_height")->getFloat()); + + temp = new LayerRangeEditor(m_parent, text_value, size, [temp, layer](coordf_t layer_height) { + wxGetApp().obj_list()->edit_layer_range(layer.first, layer_height); + } ); sizer->Add(temp); m_grid_sizer->Add(sizer); @@ -185,5 +162,59 @@ void ObjectLayers::msw_rescale() m_bmp_add.msw_rescale(); } +LayerRangeEditor::LayerRangeEditor( wxWindow* parent, + const wxString& value, + const wxSize& size, + std::function edit_fn + ) : + wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, size, wxTE_PROCESS_ENTER) +{ + this->SetFont(wxGetApp().normal_font()); + + this->Bind(wxEVT_TEXT_ENTER, ([this, edit_fn](wxEvent& e) + { + edit_fn(get_value()); + m_enter_pressed = true; + }), this->GetId()); + + this->Bind(wxEVT_KILL_FOCUS, ([this, edit_fn](wxEvent& e) + { + e.Skip(); + if (!m_enter_pressed) + edit_fn(get_value()); + m_enter_pressed = false; + }), this->GetId()); + + + this->Bind(wxEVT_CHAR, ([this](wxKeyEvent& event) + { + // select all text using Ctrl+A + if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) + this->SetSelection(-1, -1); //select all + event.Skip(); + })); +} + +coordf_t LayerRangeEditor::get_value() +{ + wxString str = GetValue(); + + coordf_t layer_height; + // Replace the first occurence of comma in decimal number. + str.Replace(",", ".", false); + if (str == ".") + layer_height = 0.0; + else + { + if (!str.ToCDouble(&layer_height) || layer_height < 0.0f) + { + show_error(m_parent, _(L("Invalid numeric input."))); + SetValue(double_to_string(layer_height)); + } + } + + return layer_height; +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 329452950..3aa3cb967 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -12,6 +12,22 @@ class ModelObject; namespace GUI { class ConfigOptionsGroup; +class LayerRangeEditor : public wxTextCtrl +{ + bool m_enter_pressed { false }; +public: + LayerRangeEditor( wxWindow* parent, + const wxString& value = wxEmptyString, + const wxSize& size = wxDefaultSize, + std::function edit_fn = [](coordf_t) {; } + ); + ~LayerRangeEditor() {} + + +private: + coordf_t get_value(); +}; + class ObjectLayers : public OG_Settings { ScalableBitmap m_bmp_delete; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 9b826f5d8..25df5c4fb 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2312,9 +2312,15 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, m_objects_model->AddLayersChild(layers_item, label, layer_idx); } -void ObjectList::edit_layer_range(const std::pair& range) +void ObjectList::edit_layer_range(const t_layer_height_range& range, coordf_t layer_height) { + const int obj_idx = get_selected_obj_idx(); + if (obj_idx < 0) return; + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; + + DynamicPrintConfig* config = &ranges[range]; + config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); } void ObjectList::init_objects() diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 5b4fd4c49..5e24b9659 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -276,7 +276,7 @@ public: void add_layer_item (const std::pair& range, const wxDataViewItem layers_item, const int layer_idx = -1); - void edit_layer_range(const std::pair& range); + void edit_layer_range(const std::pair& range, coordf_t layer_height); void init_objects(); bool multiple_selection() const ; From 213635f5596193008a96e1f910b8e2da507e9f9d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 4 Jun 2019 17:30:44 +0200 Subject: [PATCH 14/83] Implemented range's min/max Z editing --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 46 +++++++++++++++++------------ src/slic3r/GUI/GUI_ObjectLayers.hpp | 4 +-- src/slic3r/GUI/GUI_ObjectList.cpp | 28 ++++++++++++++++++ src/slic3r/GUI/GUI_ObjectList.hpp | 2 ++ 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index bba39f76a..de1c95fc9 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -43,26 +43,31 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges::value_type& layer) { - auto size = wxSize(field_width * em_unit(m_parent), wxDefaultCoord); - // Add control for the "Min Z" - auto temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.first), size); + auto temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.first), + [layer](coordf_t min_z) { + wxGetApp().obj_list()->edit_layer_range(layer.first, { min_z, layer.first.second }); + }); + m_grid_sizer->Add(temp); // Add control for the "Max Z" - temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.second), size); + temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.second), + [layer](coordf_t max_z) { + wxGetApp().obj_list()->edit_layer_range(layer.first, { layer.first.first, max_z }); + }); + m_grid_sizer->Add(temp); // Add control for the "Layer height" - auto sizer = new wxBoxSizer(wxHORIZONTAL); - - const wxString text_value = double_to_string(layer.second.option("layer_height")->getFloat()); - - temp = new LayerRangeEditor(m_parent, text_value, size, [temp, layer](coordf_t layer_height) { + temp = new LayerRangeEditor(m_parent, + double_to_string(layer.second.option("layer_height")->getFloat()), + [layer](coordf_t layer_height) { wxGetApp().obj_list()->edit_layer_range(layer.first, layer_height); - } ); - sizer->Add(temp); + }, false ); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(temp); m_grid_sizer->Add(sizer); return sizer; @@ -164,25 +169,28 @@ void ObjectLayers::msw_rescale() LayerRangeEditor::LayerRangeEditor( wxWindow* parent, const wxString& value, - const wxSize& size, - std::function edit_fn + std::function edit_fn, + const bool deletable_after_change ) : - wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, size, wxTE_PROCESS_ENTER) + wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, + wxSize(field_width * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) { this->SetFont(wxGetApp().normal_font()); this->Bind(wxEVT_TEXT_ENTER, ([this, edit_fn](wxEvent& e) { - edit_fn(get_value()); m_enter_pressed = true; + edit_fn(get_value()); }), this->GetId()); - this->Bind(wxEVT_KILL_FOCUS, ([this, edit_fn](wxEvent& e) + this->Bind(wxEVT_KILL_FOCUS, ([this, edit_fn, deletable_after_change](wxEvent& e) { - e.Skip(); - if (!m_enter_pressed) + if (!deletable_after_change) + e.Skip(); + if (!m_enter_pressed) { + m_enter_pressed = false; edit_fn(get_value()); - m_enter_pressed = false; + } }), this->GetId()); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 3aa3cb967..f34dd1314 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -18,8 +18,8 @@ class LayerRangeEditor : public wxTextCtrl public: LayerRangeEditor( wxWindow* parent, const wxString& value = wxEmptyString, - const wxSize& size = wxDefaultSize, - std::function edit_fn = [](coordf_t) {; } + std::function edit_fn = [](coordf_t) {}, + const bool deletable_after_change = true ); ~LayerRangeEditor() {} diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 25df5c4fb..96d071d54 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2265,6 +2265,9 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) ++it; } + if (selected_range->first.second > next_range->first.first) + return; // range devision has no mean + if (selected_range->first.second == next_range->first.first) { const coordf_t delta = (next_range->first.second - next_range->first.first); @@ -2323,6 +2326,31 @@ void ObjectList::edit_layer_range(const t_layer_height_range& range, coordf_t la config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); } +void ObjectList::edit_layer_range(const t_layer_height_range& range, const t_layer_height_range& new_range) +{ + const int obj_idx = get_selected_obj_idx(); + if (obj_idx < 0) return; + + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; + + const DynamicPrintConfig config = ranges[range]; + + ranges.erase(range); + ranges[new_range] = config; + + wxDataViewItem root_item = m_objects_model->GetLayerRootItem(m_objects_model->GetItemById(obj_idx)); + m_objects_model->DeleteChildren(root_item); + + if (root_item.IsOk()) + // create Layer item(s) according to the layer_config_ranges + for (const auto r : ranges) + add_layer_item(r.first, root_item); + + // To update(recreate) layers sizer call select_item for LayerRoot item expand + select_item(root_item); + Expand(root_item); +} + void ObjectList::init_objects() { m_objects = wxGetApp().model_objects(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 5e24b9659..c970a23a0 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -277,6 +277,8 @@ public: const wxDataViewItem layers_item, const int layer_idx = -1); void edit_layer_range(const std::pair& range, coordf_t layer_height); + void edit_layer_range(const std::pair& range, + const std::pair& new_range); void init_objects(); bool multiple_selection() const ; From 567f382938b7939c4266b2ffcc3e14d91f9a80a1 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 5 Jun 2019 11:03:46 +0200 Subject: [PATCH 15/83] Implemented focusing of the last edited range --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 73 +++++++++++++++++++++++------ src/slic3r/GUI/GUI_ObjectLayers.hpp | 19 ++++++-- src/slic3r/GUI/GUI_ObjectList.cpp | 8 ++-- 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index de1c95fc9..1f0511acb 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -43,28 +43,67 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges::value_type& layer) { + const bool is_last_edited_range = layer.first == m_last_edited_range; + // Add control for the "Min Z" + auto temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.first), - [layer](coordf_t min_z) { - wxGetApp().obj_list()->edit_layer_range(layer.first, { min_z, layer.first.second }); - }); + [layer, this](coordf_t min_z) + { + if (fabs(min_z - layer.first.first) < EPSILON) { + m_selection_type = sitUndef; + return false; // LayersList would not be updated/recreated + } + + // data for next focusing + m_last_edited_range = { min_z, layer.first.second }; + m_selection_type = sitMinZ; + + wxGetApp().obj_list()->edit_layer_range(layer.first, m_last_edited_range); + return true; // LayersList will be updated/recreated + } ); + + if (is_last_edited_range && m_selection_type == sitMinZ) { + temp->SetFocus(); + temp->SetInsertionPointEnd(); + } m_grid_sizer->Add(temp); // Add control for the "Max Z" + temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.second), - [layer](coordf_t max_z) { - wxGetApp().obj_list()->edit_layer_range(layer.first, { layer.first.first, max_z }); + [layer, this](coordf_t max_z) + { + if (fabs(max_z - layer.first.second) < EPSILON) { + m_selection_type = sitUndef; + return false; // LayersList would not be updated/recreated + } + + // data for next focusing + m_last_edited_range = { layer.first.first, max_z }; + m_selection_type = sitMaxZ; + + wxGetApp().obj_list()->edit_layer_range(layer.first, m_last_edited_range); + return true; // LayersList will not be updated/recreated }); + + if (is_last_edited_range && m_selection_type == sitMaxZ) { + temp->SetFocus(); + temp->SetInsertionPointEnd(); + } m_grid_sizer->Add(temp); // Add control for the "Layer height" + temp = new LayerRangeEditor(m_parent, double_to_string(layer.second.option("layer_height")->getFloat()), - [layer](coordf_t layer_height) { + [layer, this](coordf_t layer_height) + { wxGetApp().obj_list()->edit_layer_range(layer.first, layer_height); - }, false ); + return false; // LayersList would not be updated/recreated + }); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(temp); @@ -169,8 +208,7 @@ void ObjectLayers::msw_rescale() LayerRangeEditor::LayerRangeEditor( wxWindow* parent, const wxString& value, - std::function edit_fn, - const bool deletable_after_change + std::function edit_fn ) : wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, wxSize(field_width * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) @@ -179,18 +217,23 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, this->Bind(wxEVT_TEXT_ENTER, ([this, edit_fn](wxEvent& e) { - m_enter_pressed = true; - edit_fn(get_value()); + m_enter_pressed = true; + // If LayersList wasn't updated/recreated, we can call wxEVT_KILL_FOCUS.Skip() + if ( !edit_fn(get_value()) ) + m_call_kill_focus = true; }), this->GetId()); - this->Bind(wxEVT_KILL_FOCUS, ([this, edit_fn, deletable_after_change](wxEvent& e) + this->Bind(wxEVT_KILL_FOCUS, ([this, edit_fn](wxEvent& e) { - if (!deletable_after_change) - e.Skip(); if (!m_enter_pressed) { m_enter_pressed = false; - edit_fn(get_value()); + + // If LayersList wasn't updated/recreated, we should call e.Skip() + if ( !edit_fn(get_value()) ) + e.Skip(); } + else if (m_call_kill_focus) + e.Skip(); }), this->GetId()); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index f34dd1314..e69a6173a 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -14,16 +14,16 @@ class ConfigOptionsGroup; class LayerRangeEditor : public wxTextCtrl { - bool m_enter_pressed { false }; + bool m_enter_pressed { false }; + bool m_call_kill_focus { false }; + public: LayerRangeEditor( wxWindow* parent, const wxString& value = wxEmptyString, - std::function edit_fn = [](coordf_t) {}, - const bool deletable_after_change = true + std::function edit_fn = [](coordf_t) {return false; } ); ~LayerRangeEditor() {} - private: coordf_t get_value(); }; @@ -34,7 +34,16 @@ class ObjectLayers : public OG_Settings ScalableBitmap m_bmp_add; ModelObject* m_object {nullptr}; - wxFlexGridSizer* m_grid_sizer; + wxFlexGridSizer* m_grid_sizer; + std::pair m_last_edited_range; + + enum SelectedItemType + { + sitUndef, + sitMinZ, + sitMaxZ, + sitLayerHeight, + } m_selection_type {sitUndef}; public: ObjectLayers(wxWindow* parent); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 96d071d54..04423e359 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2212,7 +2212,7 @@ void ObjectList::del_layer_range(const std::pair& range) const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return; - t_layer_height_ranges& ranges = object(obj_idx)->layer_height_ranges; + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; wxDataViewItem selectable_item = GetSelection(); int layer_idx = 0; @@ -2221,10 +2221,10 @@ void ObjectList::del_layer_range(const std::pair& range) selectable_item = m_objects_model->GetParent(selectable_item); else { // May be not a best solution #ys_FIXME - t_layer_height_ranges::iterator layer_selected = ranges.find(range); - t_layer_height_ranges::iterator it = ranges.begin(); + t_layer_config_ranges::iterator layer_selected = ranges.find(range); + t_layer_config_ranges::iterator it = ranges.begin(); while (it != layer_selected) { - it++; + ++it; layer_idx++; } } From 1090105b6879b0f0212abd4259bd54e86471e60f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 5 Jun 2019 11:50:59 +0200 Subject: [PATCH 16/83] Experiments with updating layer_config_ranges from UI + Fixed OSX build --- src/libslic3r/Model.cpp | 2 ++ src/libslic3r/Print.cpp | 6 ++++-- src/libslic3r/PrintObject.cpp | 5 +++-- src/libslic3r/Slicing.cpp | 13 +++++++++---- src/libslic3r/Slicing.hpp | 3 ++- src/slic3r/GUI/GUI_ObjectLayers.hpp | 10 +++++++--- src/slic3r/GUI/GUI_ObjectList.hpp | 15 +++++++++------ src/slic3r/GUI/Selection.cpp | 3 ++- 8 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 3b1bd5df2..f31ae27db 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -600,6 +600,7 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->sla_support_points = rhs.sla_support_points; this->sla_points_status = rhs.sla_points_status; this->layer_height_ranges = rhs.layer_height_ranges; + this->layer_config_ranges = rhs.layer_config_ranges; // #ys_FIXME_experiment this->layer_height_profile = rhs.layer_height_profile; this->origin_translation = rhs.origin_translation; m_bounding_box = rhs.m_bounding_box; @@ -636,6 +637,7 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) this->sla_support_points = std::move(rhs.sla_support_points); this->sla_points_status = std::move(rhs.sla_points_status); this->layer_height_ranges = std::move(rhs.layer_height_ranges); + this->layer_config_ranges = std::move(rhs.layer_config_ranges); // #ys_FIXME_experiment this->layer_height_profile = std::move(rhs.layer_height_profile); this->origin_translation = std::move(rhs.origin_translation); m_bounding_box = std::move(rhs.m_bounding_box); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index f9129f15a..ed4af3995 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -874,7 +874,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER); if (model_parts_differ || modifiers_differ || model_object.origin_translation != model_object_new.origin_translation || - model_object.layer_height_ranges != model_object_new.layer_height_ranges || +// model_object.layer_height_ranges != model_object_new.layer_height_ranges || + model_object.layer_config_ranges != model_object_new.layer_config_ranges || // #ys_FIXME_experiment model_object.layer_height_profile != model_object_new.layer_height_profile) { // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects. auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); @@ -1227,7 +1228,8 @@ std::string Print::validate() const bool has_custom_layering = false; std::vector> layer_height_profiles; for (const PrintObject *object : m_objects) { - has_custom_layering = ! object->model_object()->layer_height_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); +// has_custom_layering = ! object->model_object()->layer_height_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); + has_custom_layering = ! object->model_object()->layer_config_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); // #ys_FIXME_experiment if (has_custom_layering) { layer_height_profiles.assign(m_objects.size(), std::vector()); break; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 660a2d939..c12861d21 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1434,8 +1434,9 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c // if (this->layer_height_profile.empty()) layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_height_ranges, model_object.volumes); else - layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_height_ranges); - updated = true; +// layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_height_ranges); + layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); // #ys_FIXME_experiment + updated = true; } return updated; } diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index 3a05e9d8a..b4c78ad09 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -157,20 +157,25 @@ SlicingParameters SlicingParameters::create_from_config( // in the height profile and the printed object may be lifted by the raft thickness at the time of the G-code generation. std::vector layer_height_profile_from_ranges( const SlicingParameters &slicing_params, - const t_layer_height_ranges &layer_height_ranges) +// const t_layer_height_ranges &layer_height_ranges) + const t_layer_config_ranges &layer_config_ranges) // #ys_FIXME_experiment { // 1) If there are any height ranges, trim one by the other to make them non-overlapping. Insert the 1st layer if fixed. std::vector> ranges_non_overlapping; - ranges_non_overlapping.reserve(layer_height_ranges.size() * 4); +// ranges_non_overlapping.reserve(layer_height_ranges.size() * 4); + ranges_non_overlapping.reserve(layer_config_ranges.size() * 4); // #ys_FIXME_experiment if (slicing_params.first_object_layer_height_fixed()) ranges_non_overlapping.push_back(std::pair( t_layer_height_range(0., slicing_params.first_object_layer_height), slicing_params.first_object_layer_height)); // The height ranges are sorted lexicographically by low / high layer boundaries. - for (t_layer_height_ranges::const_iterator it_range = layer_height_ranges.begin(); it_range != layer_height_ranges.end(); ++ it_range) { +// for (t_layer_height_ranges::const_iterator it_range = layer_height_ranges.begin(); it_range != layer_height_ranges.end(); ++ it_range) { + for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); + it_range != layer_config_ranges.end(); ++ it_range) { // #ys_FIXME_experiment coordf_t lo = it_range->first.first; coordf_t hi = std::min(it_range->first.second, slicing_params.object_print_z_height()); - coordf_t height = it_range->second; +// coordf_t height = it_range->second; + coordf_t height = it_range->second.option("layer_height")->getFloat(); // #ys_FIXME_experiment if (! ranges_non_overlapping.empty()) // Trim current low with the last high. lo = std::max(lo, ranges_non_overlapping.back().first.second); diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index c3278dc0d..ea5413e9c 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -135,7 +135,8 @@ typedef std::map t_layer_config_ranges extern std::vector layer_height_profile_from_ranges( const SlicingParameters &slicing_params, - const t_layer_height_ranges &layer_height_ranges); +// const t_layer_height_ranges &layer_height_ranges); + const t_layer_config_ranges &layer_config_ranges); extern std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index e69a6173a..aa09e64a6 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -12,6 +12,10 @@ class ModelObject; namespace GUI { class ConfigOptionsGroup; +typedef double coordf_t; +typedef std::pair t_layer_height_range; +typedef std::map t_layer_config_ranges; + class LayerRangeEditor : public wxTextCtrl { bool m_enter_pressed { false }; @@ -34,8 +38,8 @@ class ObjectLayers : public OG_Settings ScalableBitmap m_bmp_add; ModelObject* m_object {nullptr}; - wxFlexGridSizer* m_grid_sizer; - std::pair m_last_edited_range; + wxFlexGridSizer* m_grid_sizer; + t_layer_height_range m_last_edited_range; enum SelectedItemType { @@ -49,7 +53,7 @@ public: ObjectLayers(wxWindow* parent); ~ObjectLayers() {} - wxSizer* create_layer_without_buttons(const std::map, DynamicPrintConfig>::value_type& layer); + wxSizer* create_layer_without_buttons(const t_layer_config_ranges::value_type& layer); void create_layer(int id); void create_layers_list(); void update_layers_list(); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index c970a23a0..24c9f65b2 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -33,6 +33,9 @@ typedef std::map< std::string, std::vector< std::pair typedef std::vector ModelVolumePtrs; +typedef double coordf_t; +typedef std::pair t_layer_height_range; + namespace GUI { wxDECLARE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent); @@ -271,14 +274,14 @@ public: // Remove objects/sub-object from the list void remove(); - void del_layer_range(const std::pair& range); - void add_layer_range(const std::pair& range); - void add_layer_item (const std::pair& range, + void del_layer_range(const t_layer_height_range& range); + void add_layer_range(const t_layer_height_range& range); + void add_layer_item (const t_layer_height_range& range, const wxDataViewItem layers_item, const int layer_idx = -1); - void edit_layer_range(const std::pair& range, coordf_t layer_height); - void edit_layer_range(const std::pair& range, - const std::pair& new_range); + void edit_layer_range(const t_layer_height_range& range, coordf_t layer_height); + void edit_layer_range(const t_layer_height_range& range, + const t_layer_height_range& new_range); void init_objects(); bool multiple_selection() const ; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index ff994c32d..0f364f8a1 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1126,7 +1126,8 @@ void Selection::copy_to_clipboard() dst_object->config = src_object->config; dst_object->sla_support_points = src_object->sla_support_points; dst_object->sla_points_status = src_object->sla_points_status; - dst_object->layer_height_ranges = src_object->layer_height_ranges; +// dst_object->layer_height_ranges = src_object->layer_height_ranges; + dst_object->layer_config_ranges = src_object->layer_config_ranges; // #ys_FIXME_experiment dst_object->layer_height_profile = src_object->layer_height_profile; dst_object->origin_translation = src_object->origin_translation; From 401999b68b3e8e625356a9fc017427aa0903432f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 5 Jun 2019 12:32:59 +0200 Subject: [PATCH 17/83] Next try to fix OSX build --- src/slic3r/GUI/GUI_ObjectLayers.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index aa09e64a6..0b404be4f 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -9,13 +9,13 @@ class wxBoxSizer; namespace Slic3r { class ModelObject; -namespace GUI { -class ConfigOptionsGroup; - typedef double coordf_t; typedef std::pair t_layer_height_range; typedef std::map t_layer_config_ranges; +namespace GUI { +class ConfigOptionsGroup; + class LayerRangeEditor : public wxTextCtrl { bool m_enter_pressed { false }; From 67ed89c2405a242370066993c16e26fa26fdb6c4 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 5 Jun 2019 13:52:53 +0200 Subject: [PATCH 18/83] Fixed OSX build and a bug when for part is able to add "layer_height" option --- src/slic3r/GUI/GUI_ObjectLayers.hpp | 10 +++++++--- src/slic3r/GUI/GUI_ObjectList.cpp | 12 +++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 0b404be4f..bec2a1f49 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -4,18 +4,22 @@ #include "GUI_ObjectSettings.hpp" #include "wxExtensions.hpp" +#ifdef __WXOSX__ +#include "..\libslic3r\PrintConfig.hpp" +#endif + class wxBoxSizer; namespace Slic3r { class ModelObject; +namespace GUI { +class ConfigOptionsGroup; + typedef double coordf_t; typedef std::pair t_layer_height_range; typedef std::map t_layer_config_ranges; -namespace GUI { -class ConfigOptionsGroup; - class LayerRangeEditor : public wxTextCtrl { bool m_enter_pressed { false }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 04423e359..b7a582062 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1035,7 +1035,17 @@ void ObjectList::get_settings_choice(const wxString& category_name) void ObjectList::get_freq_settings_choice(const wxString& bundle_name) { - const std::vector& options = get_options_for_bundle(bundle_name); + std::vector options = get_options_for_bundle(bundle_name); + + /* Because of we couldn't edited layer_height for ItVolume and itLayer from settings list, + * correct options according to the selected item type : + * remove "layer_height" option + */ + if (m_objects_model->GetItemType(GetSelection()) & (itVolume | itLayer) && bundle_name == _("Layers and Perimeters")) { + const auto layer_height_it = std::find(options.begin(), options.end(), "layer_height"); + if (layer_height_it != options.end()) + options.erase(layer_height_it); + } assert(m_config); auto opt_keys = m_config->keys(); From 44c05fa2099b3c0a7daa96181d07a8d61e8f6397 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 5 Jun 2019 16:47:09 +0200 Subject: [PATCH 19/83] Implemented additional settings for layers range (except of "extruder") --- src/slic3r/GUI/GUI_ObjectLayers.hpp | 2 +- src/slic3r/GUI/GUI_ObjectList.cpp | 80 +++++++++++++++++++++------ src/slic3r/GUI/GUI_ObjectList.hpp | 2 + src/slic3r/GUI/GUI_ObjectSettings.cpp | 11 ++-- 4 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index bec2a1f49..55002ff35 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -5,7 +5,7 @@ #include "wxExtensions.hpp" #ifdef __WXOSX__ -#include "..\libslic3r\PrintConfig.hpp" +#include "../libslic3r/PrintConfig.hpp" #endif class wxBoxSizer; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index b7a582062..f68130ddd 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -360,6 +360,21 @@ DynamicPrintConfig& ObjectList::get_item_config(const wxDataViewItem& item) cons (*m_objects)[obj_idx]->config; } +const t_layer_height_range& ObjectList::get_layer_range_from_item(const wxDataViewItem layer_item, const int obj_idx) const +{ + ModelObject* object = (*m_objects)[obj_idx]; + t_layer_config_ranges::iterator layer_range = object->layer_config_ranges.begin(); + int id = m_objects_model->GetLayerIdByItem(layer_item); + + // May be not a best solution #ys_FIXME + while (id > 0 && layer_range != object->layer_config_ranges.end()) { + ++layer_range; + id--; + } + + return layer_range->first; +} + wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count) { wxArrayString choices; @@ -1037,11 +1052,11 @@ void ObjectList::get_freq_settings_choice(const wxString& bundle_name) { std::vector options = get_options_for_bundle(bundle_name); - /* Because of we couldn't edited layer_height for ItVolume and itLayer from settings list, + /* Because of we couldn't edited layer_height for ItVolume from settings list, * correct options according to the selected item type : * remove "layer_height" option */ - if (m_objects_model->GetItemType(GetSelection()) & (itVolume | itLayer) && bundle_name == _("Layers and Perimeters")) { + if ((m_objects_model->GetItemType(GetSelection()) & itVolume) && bundle_name == _("Layers and Perimeters")) { const auto layer_height_it = std::find(options.begin(), options.end(), "layer_height"); if (layer_height_it != options.end()) options.erase(layer_height_it); @@ -1833,7 +1848,7 @@ void ObjectList::layers_editing() t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; if (ranges.empty()) - ranges[{ 0.0f, 0.2f }] = *DynamicPrintConfig::new_from_defaults_keys({"layer_height"});// some default value + ranges[{ 0.0f, 0.6f }] = get_default_layer_config(obj_idx); // and create Layer item(s) according to the layer_config_ranges for (const auto range : ranges) @@ -1845,6 +1860,18 @@ void ObjectList::layers_editing() Expand(layers_item); } +DynamicPrintConfig ObjectList::get_default_layer_config(const int obj_idx) +{ + DynamicPrintConfig config; + coordf_t layer_height = object(obj_idx)->config.has("layer_height") ? + object(obj_idx)->config.opt_float("layer_height") : + wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("layer_height"); + config.set_key_value("layer_height",new ConfigOptionFloat(layer_height)); + config.set_key_value("extruder", new ConfigOptionInt(0)); + + return config; +} + bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume) { auto obj_idx = get_selected_obj_idx(); @@ -1937,22 +1964,28 @@ void ObjectList::part_selection_changed() update_and_show_manipulations = true; } 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 - obj_idx = m_objects_model->GetIdByItem(parent); + obj_idx = m_objects_model->GetObjectIdByItem(item); + const ItemType type = m_objects_model->GetItemType(item); if (type & itSettings) { - if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { + const auto parent = m_objects_model->GetParent(item); + const ItemType parent_type = m_objects_model->GetItemType(parent); + + if (parent_type & itObject) { og_name = _(L("Object Settings to modify")); m_config = &(*m_objects)[obj_idx]->config; } - else { + else if (parent_type & itVolume) { og_name = _(L("Part Settings to modify")); - 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); + volume_id = m_objects_model->GetVolumeIdByItem(parent); m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; } + else if (parent_type & itLayer) { + og_name = _(L("Layer range Settings to modify")); + + const t_layer_height_range& layer_height_range = get_layer_range_from_item(parent, obj_idx); + m_config = &(*m_objects)[obj_idx]->layer_config_ranges[layer_height_range]; + } update_and_show_settings = true; } else if (type & itVolume) { @@ -1966,12 +1999,14 @@ void ObjectList::part_selection_changed() update_and_show_manipulations = true; // fill m_config by object's values - const int obj_idx_ = m_objects_model->GetObjectIdByItem(item); - m_config = &(*m_objects)[obj_idx_]->config; + m_config = &(*m_objects)[obj_idx]->config; } else if (type & (itLayerRoot|itLayer)) { og_name = type & itLayerRoot ? _(L("Layers Editing")) : _(L("Layer Editing")); update_and_show_layers = true; + + const t_layer_height_range& layer_height_range = get_layer_range_from_item(item, obj_idx); + m_config = &(*m_objects)[obj_idx]->layer_config_ranges[layer_height_range]; } } } @@ -2259,8 +2294,8 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) if (selected_range->first == last_range->first) { - const t_layer_height_range new_range = { last_range->first.second, last_range->first.second + 0.2f }; - ranges[new_range] = last_range->second; + const t_layer_height_range new_range = { last_range->first.second, last_range->first.second + 0.5f }; + ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item); } else @@ -2300,13 +2335,13 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) add_layer_item(new_range, layers_item, layer_idx); new_range = { selected_range->first.second, midl_layer }; - ranges[new_range] = selected_range->second; + ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item, layer_idx); } else { const t_layer_height_range new_range = { selected_range->first.second, next_range->first.first }; - ranges[new_range] = selected_range->second; + ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item, layer_idx); } } @@ -2322,7 +2357,16 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, const int layer_idx /* = -1*/) { const std::string label = (boost::format(" %.2f-%.2f ") % range.first % range.second).str(); - m_objects_model->AddLayersChild(layers_item, label, layer_idx); + const wxDataViewItem layer_item = m_objects_model->AddLayersChild(layers_item, label, layer_idx); + + const int obj_idx = get_selected_obj_idx(); + if (obj_idx < 0) return; + +// auto opt_keys = object(obj_idx)->layer_config_ranges[range].keys(); + const DynamicPrintConfig& config = object(obj_idx)->layer_config_ranges[range]; +// if (!opt_keys.empty() && !(opt_keys.size() == 2 && opt_keys[0] == "layer_height" && opt_keys[1] == "extruder")) + if (config.keys().size() > 2) + select_item(m_objects_model->AddSettingsChild(layer_item)); } void ObjectList::edit_layer_range(const t_layer_height_range& range, coordf_t layer_height) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 24c9f65b2..ad7587a01 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -235,6 +235,7 @@ public: bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(); void layers_editing(); + DynamicPrintConfig get_default_layer_config(const int obj_idx); bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume); bool is_splittable(); bool selected_instances_of_same_object(); @@ -244,6 +245,7 @@ public: wxBoxSizer* get_sizer() {return m_sizer;} int get_selected_obj_idx() const; DynamicPrintConfig& get_item_config(const wxDataViewItem& item) const; + const t_layer_height_range& get_layer_range_from_item(const wxDataViewItem layer_item, const int obj_idx) const; void changed_object(const int obj_idx = -1) const; void part_selection_changed(); diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp index a4aa7dec2..ab2614895 100644 --- a/src/slic3r/GUI/GUI_ObjectSettings.cpp +++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp @@ -72,6 +72,8 @@ void ObjectSettings::update_settings_list() auto config = wxGetApp().obj_list()->config(); const auto item = objects_ctrl->GetSelection(); + const bool is_layers_range_settings = objects_model->GetItemType(objects_model->GetParent(item)) == itLayer; + if (item && !objects_ctrl->multiple_selection() && config && objects_model->IsSettingsItem(item)) { @@ -119,7 +121,8 @@ void ObjectSettings::update_settings_list() } for (auto& cat : cat_options) { - if (cat.second.size() == 1 && cat.second[0] == "extruder") + if (cat.second.size() == 1 && + (cat.second[0] == "extruder" || is_layers_range_settings && cat.second[0] == "layer_height")) continue; auto optgroup = std::make_shared(m_og->ctrl_parent(), _(cat.first), config, false, extra_column); @@ -129,14 +132,14 @@ void ObjectSettings::update_settings_list() optgroup->m_on_change = [](const t_config_option_key& opt_id, const boost::any& value) { wxGetApp().obj_list()->changed_object(); }; - const bool is_extriders_cat = cat.first == "Extruders"; + const bool is_extruders_cat = cat.first == "Extruders"; for (auto& opt : cat.second) { - if (opt == "extruder") + if (opt == "extruder" || is_layers_range_settings && opt == "layer_height") continue; Option option = optgroup->get_option(opt); option.opt.width = 12; - if (is_extriders_cat) + if (is_extruders_cat) option.opt.max = wxGetApp().extruders_cnt(); optgroup->append_single_option_line(option); } From 71cc0fdb535bdf1cb4c35429655ed75debf0afce Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 6 Jun 2019 14:14:29 +0200 Subject: [PATCH 20/83] Some code refactoring and improvements --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 79 ++++++-------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 8 +- src/slic3r/GUI/GUI_ObjectList.cpp | 157 +++++++++++++--------------- src/slic3r/GUI/GUI_ObjectList.hpp | 6 +- src/slic3r/GUI/Tab.cpp | 7 +- src/slic3r/GUI/wxExtensions.cpp | 61 ++++++++--- src/slic3r/GUI/wxExtensions.hpp | 11 +- 7 files changed, 171 insertions(+), 158 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 1f0511acb..ba0012a2b 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -16,8 +16,6 @@ namespace Slic3r namespace GUI { -#define field_width 8 - ObjectLayers::ObjectLayers(wxWindow* parent) : OG_Settings(parent, true) { @@ -41,27 +39,27 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : m_bmp_add = ScalableBitmap(parent, "add_copies"); } -wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges::value_type& layer) +wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) { - const bool is_last_edited_range = layer.first == m_last_edited_range; + const bool is_last_edited_range = range == m_last_edited_range; // Add control for the "Min Z" - auto temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.first), - [layer, this](coordf_t min_z) + auto temp = new LayerRangeEditor(m_parent, double_to_string(range.first), + [range, this](coordf_t min_z) { - if (fabs(min_z - layer.first.first) < EPSILON) { - m_selection_type = sitUndef; + if (fabs(min_z - range.first) < EPSILON) { + m_selection_type = sitUndef; return false; // LayersList would not be updated/recreated } // data for next focusing - m_last_edited_range = { min_z, layer.first.second }; + m_last_edited_range = { min_z, range.second }; m_selection_type = sitMinZ; - wxGetApp().obj_list()->edit_layer_range(layer.first, m_last_edited_range); + wxGetApp().obj_list()->edit_layer_range(range, m_last_edited_range); return true; // LayersList will be updated/recreated - } ); + }); if (is_last_edited_range && m_selection_type == sitMinZ) { temp->SetFocus(); @@ -72,19 +70,19 @@ wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges: // Add control for the "Max Z" - temp = new LayerRangeEditor(m_parent, double_to_string(layer.first.second), - [layer, this](coordf_t max_z) + temp = new LayerRangeEditor(m_parent, double_to_string(range.second), + [range, this](coordf_t max_z) { - if (fabs(max_z - layer.first.second) < EPSILON) { + if (fabs(max_z - range.second) < EPSILON) { m_selection_type = sitUndef; return false; // LayersList would not be updated/recreated } // data for next focusing - m_last_edited_range = { layer.first.first, max_z }; + m_last_edited_range = { range.first, max_z }; m_selection_type = sitMaxZ; - wxGetApp().obj_list()->edit_layer_range(layer.first, m_last_edited_range); + wxGetApp().obj_list()->edit_layer_range(range, m_last_edited_range); return true; // LayersList will not be updated/recreated }); @@ -92,20 +90,20 @@ wxSizer* ObjectLayers::create_layer_without_buttons(const t_layer_config_ranges: temp->SetFocus(); temp->SetInsertionPointEnd(); } - + m_grid_sizer->Add(temp); // Add control for the "Layer height" - temp = new LayerRangeEditor(m_parent, - double_to_string(layer.second.option("layer_height")->getFloat()), - [layer, this](coordf_t layer_height) + temp = new LayerRangeEditor(m_parent, + double_to_string(m_object->layer_config_ranges[range].option("layer_height")->getFloat()), + [range, this](coordf_t layer_height) { - wxGetApp().obj_list()->edit_layer_range(layer.first, layer_height); + wxGetApp().obj_list()->edit_layer_range(range, layer_height); return false; // LayersList would not be updated/recreated }); - auto sizer = new wxBoxSizer(wxHORIZONTAL); + auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(temp); m_grid_sizer->Add(sizer); @@ -116,42 +114,29 @@ void ObjectLayers::create_layers_list() { for (const auto layer : m_object->layer_config_ranges) { - auto sizer = create_layer_without_buttons(layer); + const t_layer_height_range& range = layer.first; + auto sizer = create_layer(range); - wxWindow* parent = m_parent; - auto del_btn = new ScalableButton(parent, wxID_ANY, m_bmp_delete); + auto del_btn = new ScalableButton(m_parent, wxID_ANY, m_bmp_delete); del_btn->SetToolTip(_(L("Remove layer"))); - sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, em_unit(parent)); + sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, em_unit(m_parent)); - del_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { - wxGetApp().obj_list()->del_layer_range(layer.first); + del_btn->Bind(wxEVT_BUTTON, [this, range](wxEvent &event) { + wxGetApp().obj_list()->del_layer_range(range); }); - auto add_btn = new ScalableButton(parent, wxID_ANY, m_bmp_add); + auto add_btn = new ScalableButton(m_parent, wxID_ANY, m_bmp_add); add_btn->SetToolTip(_(L("Add layer"))); - sizer->Add(add_btn, 0, wxRIGHT, em_unit(parent)); + sizer->Add(add_btn, 0, wxRIGHT, em_unit(m_parent)); - add_btn->Bind(wxEVT_BUTTON, [this, layer](wxEvent &event) { - wxGetApp().obj_list()->add_layer_range(layer.first); + add_btn->Bind(wxEVT_BUTTON, [this, range](wxEvent &event) { + wxGetApp().obj_list()->add_layer_range_after_current(range); }); } } -void ObjectLayers::create_layer(int id) -{ - t_layer_config_ranges::iterator layer_range = m_object->layer_config_ranges.begin(); - - // May be not a best solution #ys_FIXME - while (id > 0 && layer_range != m_object->layer_config_ranges.end()) { - ++layer_range; - id--; - } - - create_layer_without_buttons(*layer_range); -} - void ObjectLayers::update_layers_list() { ObjectList* objects_ctrl = wxGetApp().obj_list(); @@ -187,7 +172,7 @@ void ObjectLayers::update_layers_list() if (type & itLayerRoot) create_layers_list(); else - create_layer(objects_ctrl->GetModel()->GetLayerIdByItem(item)); + create_layer(objects_ctrl->GetModel()->GetLayerRangeByItem(item)); m_parent->Layout(); } @@ -211,7 +196,7 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, std::function edit_fn ) : wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, - wxSize(field_width * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) + wxSize(8 * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) { this->SetFont(wxGetApp().normal_font()); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 55002ff35..562e04972 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -16,9 +16,8 @@ class ModelObject; namespace GUI { class ConfigOptionsGroup; -typedef double coordf_t; -typedef std::pair t_layer_height_range; -typedef std::map t_layer_config_ranges; +typedef double coordf_t; +typedef std::pair t_layer_height_range; class LayerRangeEditor : public wxTextCtrl { @@ -57,8 +56,7 @@ public: ObjectLayers(wxWindow* parent); ~ObjectLayers() {} - wxSizer* create_layer_without_buttons(const t_layer_config_ranges::value_type& layer); - void create_layer(int id); + wxSizer* create_layer(const t_layer_height_range& range); // without_buttons void create_layers_list(); void update_layers_list(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f68130ddd..3060a166d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -351,30 +351,16 @@ DynamicPrintConfig& ObjectList::get_item_config(const wxDataViewItem& item) cons const ItemType type = m_objects_model->GetItemType(item); const int obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) : - m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); + m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); const int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1; assert(obj_idx >= 0 || ((type & itVolume) && vol_idx >=0)); return type & itVolume ?(*m_objects)[obj_idx]->volumes[vol_idx]->config : + type & itLayer ?(*m_objects)[obj_idx]->layer_config_ranges[m_objects_model->GetLayerRangeByItem(item)] : (*m_objects)[obj_idx]->config; } -const t_layer_height_range& ObjectList::get_layer_range_from_item(const wxDataViewItem layer_item, const int obj_idx) const -{ - ModelObject* object = (*m_objects)[obj_idx]; - t_layer_config_ranges::iterator layer_range = object->layer_config_ranges.begin(); - int id = m_objects_model->GetLayerIdByItem(layer_item); - - // May be not a best solution #ys_FIXME - while (id > 0 && layer_range != object->layer_config_ranges.end()) { - ++layer_range; - id--; - } - - return layer_range->first; -} - wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count) { wxArrayString choices; @@ -457,16 +443,23 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item) { if (m_prevent_update_extruder_in_config) return; - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { + + const ItemType item_type = m_objects_model->GetItemType(item); + if (item_type & itObject) { const int obj_idx = m_objects_model->GetIdByItem(item); m_config = &(*m_objects)[obj_idx]->config; } else { - const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item)); + const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); + if (item_type & itVolume) + { const int volume_id = m_objects_model->GetVolumeIdByItem(item); if (obj_idx < 0 || volume_id < 0) return; m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; + } + else if (item_type & itLayer) + m_config = &get_item_config(item); } wxVariant variant; @@ -669,7 +662,7 @@ void ObjectList::OnContextMenu(wxDataViewEvent&) const wxPoint pt = get_mouse_position_in_control(); HitTest(pt, item, col); if (!item) -#ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX +#ifdef __WXOSX__ // temporary workaround for OSX // after Yosemite OS X version, HitTest return undefined item item = GetSelection(); if (item) @@ -1668,40 +1661,52 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) ItemType type; m_objects_model->GetItemInfo(item, type, obj_idx, idx); - if (type == itUndef) + if (type & itUndef) return; - if (type == itSettings) - del_settings_from_config(); - else if (type == itInstanceRoot && obj_idx != -1) + if (type & itSettings) + del_settings_from_config(m_objects_model->GetParent(item)); + else if (type & itInstanceRoot && obj_idx != -1) del_instances_from_object(obj_idx); - else if ((type & itLayerRoot) && obj_idx != -1) + else if (type & itLayerRoot && obj_idx != -1) del_layers_from_object(obj_idx); + else if (type & itLayer && obj_idx != -1) + del_layer_from_object(obj_idx, m_objects_model->GetLayerRangeByItem(item)); else if (idx == -1) return; else if (!del_subobject_from_object(obj_idx, idx, type)) return; // If last volume item with warning was deleted, unmark object item - if (type == itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0) + if (type & itVolume && (*m_objects)[obj_idx]->get_mesh_errors_count() == 0) m_objects_model->DeleteWarningIcon(m_objects_model->GetParent(item)); m_objects_model->Delete(item); } -void ObjectList::del_settings_from_config() +void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item) { - auto opt_keys = m_config->keys(); - if (opt_keys.size() == 1 && opt_keys[0] == "extruder") + const bool is_layer_settings = m_objects_model->GetItemType(parent_item) == itLayer; + + const int opt_cnt = m_config->keys().size(); + if (opt_cnt == 1 && m_config->has("extruder") || + is_layer_settings && opt_cnt == 2 && m_config->has("extruder") && m_config->has("layer_height")) return; + int extruder = -1; if (m_config->has("extruder")) extruder = m_config->option("extruder")->value; + coordf_t layer_height = 0.0; + if (is_layer_settings) + layer_height = m_config->opt_float("layer_height"); + m_config->clear(); if (extruder >= 0) m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); + if (is_layer_settings) + m_config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); } void ObjectList::del_instances_from_object(const int obj_idx) @@ -1718,6 +1723,17 @@ void ObjectList::del_instances_from_object(const int obj_idx) changed_object(obj_idx); } +void ObjectList::del_layer_from_object(const int obj_idx, const t_layer_height_range& layer_range) +{ + const auto del_range = object(obj_idx)->layer_config_ranges.find(layer_range); + if (del_range == object(obj_idx)->layer_config_ranges.end()) + return; + + object(obj_idx)->layer_config_ranges.erase(del_range); + + changed_object(obj_idx); +} + void ObjectList::del_layers_from_object(const int obj_idx) { object(obj_idx)->layer_config_ranges.clear(); @@ -1764,15 +1780,6 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con } object->delete_instance(idx); } - else if (type == itLayer) { - t_layer_config_ranges::iterator layer_range = object->layer_config_ranges.begin(); - int id = idx; - while (id > 0 && layer_range != object->layer_config_ranges.end()) { - layer_range++; - id--; - } - object->layer_config_ranges.erase(layer_range); - } else return false; @@ -1982,9 +1989,7 @@ void ObjectList::part_selection_changed() } else if (parent_type & itLayer) { og_name = _(L("Layer range Settings to modify")); - - const t_layer_height_range& layer_height_range = get_layer_range_from_item(parent, obj_idx); - m_config = &(*m_objects)[obj_idx]->layer_config_ranges[layer_height_range]; + m_config = &get_item_config(parent); } update_and_show_settings = true; } @@ -2005,8 +2010,8 @@ void ObjectList::part_selection_changed() og_name = type & itLayerRoot ? _(L("Layers Editing")) : _(L("Layer Editing")); update_and_show_layers = true; - const t_layer_height_range& layer_height_range = get_layer_range_from_item(item, obj_idx); - m_config = &(*m_objects)[obj_idx]->layer_config_ranges[layer_height_range]; + if (type & itLayer) + m_config = &get_item_config(item); } } } @@ -2252,7 +2257,7 @@ void ObjectList::remove() } } -void ObjectList::del_layer_range(const std::pair& range) +void ObjectList::del_layer_range(const t_layer_height_range& range) { const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return; @@ -2260,73 +2265,58 @@ void ObjectList::del_layer_range(const std::pair& range) t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; wxDataViewItem selectable_item = GetSelection(); - int layer_idx = 0; if (ranges.size() == 1) selectable_item = m_objects_model->GetParent(selectable_item); - else { - // May be not a best solution #ys_FIXME - t_layer_config_ranges::iterator layer_selected = ranges.find(range); - t_layer_config_ranges::iterator it = ranges.begin(); - while (it != layer_selected) { - ++it; - layer_idx++; - } - } - wxDataViewItem layer_item = m_objects_model->GetItemByLayerId(obj_idx, layer_idx); + wxDataViewItem layer_item = m_objects_model->GetItemByLayerRange(obj_idx, range); del_subobject_item(layer_item); select_item(selectable_item); } -void ObjectList::add_layer_range(const t_layer_height_range& range) +void ObjectList::add_layer_range_after_current(const t_layer_height_range& current_range) { const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return; - wxDataViewItem layers_item = GetSelection(); + const wxDataViewItem layers_item = GetSelection(); t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; - const t_layer_config_ranges::iterator selected_range = ranges.find(range); - const t_layer_config_ranges::iterator last_range = --ranges.end(); + const t_layer_height_range& last_range = (--ranges.end())->first; - if (selected_range->first == last_range->first) + if (current_range == last_range) { - const t_layer_height_range new_range = { last_range->first.second, last_range->first.second + 0.5f }; + const t_layer_height_range& new_range = { last_range.second, last_range.second + 0.5f }; ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item); } else { - int layer_idx = 0; - t_layer_config_ranges::iterator next_range = ++ranges.find(range); + const t_layer_height_range& next_range = (++ranges.find(current_range))->first; - // May be not a best solution #ys_FIXME - t_layer_config_ranges::iterator it = ranges.begin(); - while (it != next_range && it != ranges.end()) { - layer_idx++; - ++it; - } - - if (selected_range->first.second > next_range->first.first) - return; // range devision has no mean + if (current_range.second > next_range.first) + return; // range division has no sense - if (selected_range->first.second == next_range->first.first) + const int layer_idx = m_objects_model->GetItemIdByLayerRange(obj_idx, next_range); + if (layer_idx < 0) + return; + + if (current_range.second == next_range.first) { - const coordf_t delta = (next_range->first.second - next_range->first.first); - if (delta < 0.05f) // next range devision has no mean + const coordf_t delta = (next_range.second - next_range.first); + if (delta < 0.05f) // next range division has no sense return; - const coordf_t midl_layer = next_range->first.first + 0.5f * delta; - // #ys_FIXME May be it should be copied just a "layer_height" option - const /*coordf_t*/auto old_config = next_range->second; - t_layer_height_range new_range = { midl_layer, next_range->first.second }; + const coordf_t midl_layer = next_range.first + 0.5f * delta; + + const auto old_config = ranges.at(next_range); + t_layer_height_range new_range = { midl_layer, next_range.second }; // delete old layer - wxDataViewItem layer_item = m_objects_model->GetItemByLayerId(obj_idx, layer_idx); + wxDataViewItem layer_item = m_objects_model->GetItemByLayerRange(obj_idx, next_range); del_subobject_item(layer_item); // create new 2 layers instead of deleted one @@ -2334,13 +2324,13 @@ void ObjectList::add_layer_range(const t_layer_height_range& range) ranges[new_range] = old_config; add_layer_item(new_range, layers_item, layer_idx); - new_range = { selected_range->first.second, midl_layer }; + new_range = { current_range.second, midl_layer }; ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item, layer_idx); } else { - const t_layer_height_range new_range = { selected_range->first.second, next_range->first.first }; + const t_layer_height_range new_range = { current_range.second, next_range.first }; ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item, layer_idx); } @@ -2356,15 +2346,12 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, const wxDataViewItem layers_item, const int layer_idx /* = -1*/) { - const std::string label = (boost::format(" %.2f-%.2f ") % range.first % range.second).str(); - const wxDataViewItem layer_item = m_objects_model->AddLayersChild(layers_item, label, layer_idx); + const wxDataViewItem layer_item = m_objects_model->AddLayersChild(layers_item, range, layer_idx); const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return; -// auto opt_keys = object(obj_idx)->layer_config_ranges[range].keys(); const DynamicPrintConfig& config = object(obj_idx)->layer_config_ranges[range]; -// if (!opt_keys.empty() && !(opt_keys.size() == 2 && opt_keys[0] == "layer_height" && opt_keys[1] == "extruder")) if (config.keys().size() > 2) select_item(m_objects_model->AddSettingsChild(layer_item)); } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index ad7587a01..455f9f7a1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -229,8 +229,9 @@ public: void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); void del_object(const int obj_idx); void del_subobject_item(wxDataViewItem& item); - void del_settings_from_config(); + void del_settings_from_config(const wxDataViewItem& parent_item); void del_instances_from_object(const int obj_idx); + void del_layer_from_object(const int obj_idx, const t_layer_height_range& layer_range); void del_layers_from_object(const int obj_idx); bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(); @@ -245,7 +246,6 @@ public: wxBoxSizer* get_sizer() {return m_sizer;} int get_selected_obj_idx() const; DynamicPrintConfig& get_item_config(const wxDataViewItem& item) const; - const t_layer_height_range& get_layer_range_from_item(const wxDataViewItem layer_item, const int obj_idx) const; void changed_object(const int obj_idx = -1) const; void part_selection_changed(); @@ -277,7 +277,7 @@ public: // Remove objects/sub-object from the list void remove(); void del_layer_range(const t_layer_height_range& range); - void add_layer_range(const t_layer_height_range& range); + void add_layer_range_after_current(const t_layer_height_range& current_range); void add_layer_item (const t_layer_height_range& range, const wxDataViewItem layers_item, const int layer_idx = -1); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6cd270e5b..045feb75a 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3442,9 +3442,9 @@ void TabSLAMaterial::reload_config() void TabSLAMaterial::update() { if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) - return; // #ys_FIXME + return; -// #ys_FIXME +// #ys_FIXME. Just a template for this function // m_update_cnt++; // ! something to update // m_update_cnt--; @@ -3542,9 +3542,8 @@ void TabSLAPrint::reload_config() void TabSLAPrint::update() { if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) - return; // #ys_FIXME + return; -// #ys_FIXME m_update_cnt++; double head_penetration = m_config->opt_float("support_head_penetration"); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index adc2e6d07..ed49c8513 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -464,12 +464,13 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent } ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent, - const wxString& label_range, + const t_layer_height_range& layer_range, const int idx /*= -1 */, const wxString& extruder) : m_parent(parent), m_type(itLayer), m_idx(idx), + m_layer_range(layer_range), m_extruder(extruder) { const int children_cnt = parent->GetChildCount(); @@ -481,7 +482,7 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent for (int i = m_idx; i < children_cnt; i++) parent->GetNthChild(i)->SetIdx(i + 1); } -// m_name = wxString::Format(_(L("Layer %s (mm)")), label_range); + const std::string label_range = (boost::format(" %.2f-%.2f ") % layer_range.first % layer_range.second).str(); m_name = _(L("Range")) + label_range + "(" + _(L("mm")) + ")"; m_bmp = create_scaled_bitmap(nullptr, "layers_white"); // FIXME: pass window ptr @@ -751,7 +752,7 @@ wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_i } wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item, - const std::string& label_range, + const t_layer_height_range& layer_range, const int index /* = -1*/) { ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); @@ -773,7 +774,7 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_ } // Add layer node - ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, label_range, index); + ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, layer_range, index); if (index < 0) layer_root_node->Append(layer_node); else @@ -1122,7 +1123,7 @@ wxDataViewItem ObjectDataViewModel::GetItemById(const int obj_idx, const int sub if (!item) return wxDataViewItem(0); - auto parent = (ObjectDataViewModelNode*)item.GetID();; + auto parent = (ObjectDataViewModelNode*)item.GetID(); for (size_t i = 0; i < parent->GetChildCount(); i++) if (parent->GetNthChild(i)->m_idx == sub_obj_idx) return wxDataViewItem(parent->GetNthChild(i)); @@ -1140,6 +1141,34 @@ wxDataViewItem ObjectDataViewModel::GetItemByLayerId(int obj_idx, int layer_idx) return GetItemById(obj_idx, layer_idx, itLayerRoot); } +wxDataViewItem ObjectDataViewModel::GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range) +{ + if (obj_idx >= m_objects.size() || obj_idx < 0) { + printf("Error! Out of objects range.\n"); + return wxDataViewItem(0); + } + + auto item = GetItemByType(wxDataViewItem(m_objects[obj_idx]), itLayerRoot); + if (!item) + return wxDataViewItem(0); + + auto parent = (ObjectDataViewModelNode*)item.GetID(); + for (size_t i = 0; i < parent->GetChildCount(); i++) + if (parent->GetNthChild(i)->m_layer_range == layer_range) + return wxDataViewItem(parent->GetNthChild(i)); + + return wxDataViewItem(0); +} + +int ObjectDataViewModel::GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range) +{ + wxDataViewItem item = GetItemByLayerRange(obj_idx, layer_range); + if (!item) + return -1; + + return GetLayerIdByItem(item); +} + int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const { wxASSERT(item.IsOk()); @@ -1182,6 +1211,16 @@ int ObjectDataViewModel::GetLayerIdByItem(const wxDataViewItem& item) const return GetIdByItemAndType(item, itLayer); } +t_layer_height_range ObjectDataViewModel::GetLayerRangeByItem(const wxDataViewItem& item) const +{ + wxASSERT(item.IsOk()); + + ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); + if (!node || node->m_type != itLayer) + return { 0.0f, 0.0f }; + return node->GetLayerRange(); +} + void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) { wxASSERT(item.IsOk()); @@ -1196,9 +1235,10 @@ void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type ObjectDataViewModelNode *parent_node = node->GetParent(); if (!parent_node) return; - if (type & (itInstance | itLayer)) - parent_node = node->GetParent()->GetParent(); - if (!parent_node || parent_node->m_type != itObject) { type = itUndef; return; } + + // get top parent (Object) node + while (parent_node->m_type != itObject) + parent_node = parent_node->GetParent(); auto it = find(m_objects.begin(), m_objects.end(), parent_node); if (it != m_objects.end()) @@ -1366,10 +1406,7 @@ wxDataViewItem ObjectDataViewModel::GetTopParent(const wxDataViewItem &item) con ObjectDataViewModelNode *parent_node = node->GetParent(); while (parent_node->m_type != itObject) - { - node = parent_node; - parent_node = node->GetParent(); - } + parent_node = parent_node->GetParent(); return wxDataViewItem((void*)parent_node); } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 775d89a3b..3f43b0882 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -20,6 +20,8 @@ namespace Slic3r { enum class ModelVolumeType : int; }; +typedef std::pair t_layer_height_range; + #ifdef __WXMSW__ void msw_rescale_menu(wxMenu* menu); #else /* __WXMSW__ */ @@ -179,6 +181,7 @@ class ObjectDataViewModelNode wxBitmap m_empty_bmp; size_t m_volumes_cnt = 0; std::vector< std::string > m_opt_categories; + t_layer_height_range m_layer_range = { 0.0f, 0.0f }; wxString m_name; wxBitmap& m_bmp = m_empty_bmp; @@ -232,7 +235,7 @@ public: } ObjectDataViewModelNode(ObjectDataViewModelNode* parent, - const wxString& label_range, + const t_layer_height_range& layer_range, const int idx = -1, const wxString& extruder = wxEmptyString ); @@ -325,6 +328,7 @@ public: ItemType GetType() const { return m_type; } void SetIdx(const int& idx); int GetIdx() const { return m_idx; } + t_layer_height_range GetLayerRange() const { return m_layer_range; } // use this function only for childrens void AssignAllVal(ObjectDataViewModelNode& from_node) @@ -397,7 +401,7 @@ public: wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item, - const std::string& label_range, + const t_layer_height_range& layer_range, const int index = -1); wxDataViewItem Delete(const wxDataViewItem &item); wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); @@ -410,6 +414,8 @@ public: wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); wxDataViewItem GetItemByInstanceId(int obj_idx, int inst_idx); wxDataViewItem GetItemByLayerId(int obj_idx, int layer_idx); + wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range); + int GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range); int GetIdByItem(const wxDataViewItem& item) const; int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; int GetObjectIdByItem(const wxDataViewItem& item) const; @@ -480,6 +486,7 @@ public: wxBitmap GetVolumeIcon(const Slic3r::ModelVolumeType vol_type, const bool is_marked = false); void DeleteWarningIcon(const wxDataViewItem& item, const bool unmark_object = false); + t_layer_height_range GetLayerRangeByItem(const wxDataViewItem& item) const; }; // ---------------------------------------------------------------------------- From 446e37b1512e507d3f99526e0572c7aacb1c406c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 7 Jun 2019 11:32:46 +0200 Subject: [PATCH 21/83] Implemented extruder selection for Layers --- src/slic3r/GUI/GUI_ObjectList.cpp | 10 ++++++++-- src/slic3r/GUI/wxExtensions.cpp | 7 +++++-- src/slic3r/GUI/wxExtensions.hpp | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 3060a166d..85195f87d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2346,12 +2346,18 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, const wxDataViewItem layers_item, const int layer_idx /* = -1*/) { - const wxDataViewItem layer_item = m_objects_model->AddLayersChild(layers_item, range, layer_idx); - const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return; const DynamicPrintConfig& config = object(obj_idx)->layer_config_ranges[range]; + if (!config.has("extruder")) + return; + + const auto layer_item = m_objects_model->AddLayersChild(layers_item, + range, + config.opt_int("extruder"), + layer_idx); + if (config.keys().size() > 2) select_item(m_objects_model->AddSettingsChild(layer_item)); } diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index ed49c8513..05cc265c3 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -752,12 +752,15 @@ wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_i } wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item, - const t_layer_height_range& layer_range, + const t_layer_height_range& layer_range, + const int extruder/* = 0*/, const int index /* = -1*/) { ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID(); if (!parent_node) return wxDataViewItem(0); + wxString extruder_str = extruder == 0 ? _(L("default")) : wxString::Format("%d", extruder); + // get LayerRoot node ObjectDataViewModelNode *layer_root_node; wxDataViewItem layer_root_item; @@ -774,7 +777,7 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_ } // Add layer node - ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, layer_range, index); + ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, layer_range, index, extruder_str); if (index < 0) layer_root_node->Append(layer_node); else diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 3f43b0882..8ade7af07 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -401,7 +401,8 @@ public: wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item); wxDataViewItem AddLayersChild( const wxDataViewItem &parent_item, - const t_layer_height_range& layer_range, + const t_layer_height_range& layer_range, + const int extruder = 0, const int index = -1); wxDataViewItem Delete(const wxDataViewItem &item); wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); From 6e891c08862510f2209d1f92333480b52d0f47a9 Mon Sep 17 00:00:00 2001 From: "Stuart P. Bentley" Date: Sat, 8 Jun 2019 13:52:03 -0700 Subject: [PATCH 22/83] Update usage string to match new executable name --- src/PrusaSlicer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index fef1f6e7f..0aebec420 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -576,7 +576,7 @@ void CLI::print_help(bool include_print_options, PrinterTechnology printer_techn #endif /* SLIC3R_GUI */ << std::endl << "https://github.com/prusa3d/PrusaSlicer" << std::endl << std::endl - << "Usage: slic3r [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl + << "Usage: prusa-slicer [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl << std::endl << "Actions:" << std::endl; cli_actions_config_def.print_cli_help(boost::nowide::cout, false); From 2fa87044be0796625691702485344059b1832d9f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 10 Jun 2019 10:48:43 +0200 Subject: [PATCH 23/83] Implemented update_object_list_by_printer_technology() --- src/slic3r/GUI/GUI_ObjectList.cpp | 118 +++++++++++++++++++++++++++--- src/slic3r/GUI/GUI_ObjectList.hpp | 5 ++ src/slic3r/GUI/Plater.cpp | 8 +- 3 files changed, 121 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 85195f87d..dfdaa7171 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1849,24 +1849,41 @@ void ObjectList::layers_editing() // if it doesn't exist now if (!layers_item.IsOk()) { - // create LayerRoot item - layers_item = m_objects_model->AddLayersRoot(obj_item); - t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; - + + // set some default value if (ranges.empty()) ranges[{ 0.0f, 0.6f }] = get_default_layer_config(obj_idx); - // and create Layer item(s) according to the layer_config_ranges - for (const auto range : ranges) - add_layer_item(range.first, layers_item); + // create layer root item + layers_item = add_layer_root_item(obj_item); } + if (!layers_item.IsOk()) + return; // select LayerRoor item and expand select_item(layers_item); Expand(layers_item); } +wxDataViewItem ObjectList::add_layer_root_item(const wxDataViewItem obj_item) +{ + const int obj_idx = m_objects_model->GetIdByItem(obj_item); + if (obj_idx < 0 || + object(obj_idx)->layer_config_ranges.empty() || + printer_technology() == ptSLA) + return wxDataViewItem(0); + + // create LayerRoot item + wxDataViewItem layers_item = m_objects_model->AddLayersRoot(obj_item); + + // and create Layer item(s) according to the layer_config_ranges + for (const auto range : object(obj_idx)->layer_config_ranges) + add_layer_item(range.first, layers_item); + + return layers_item; +} + DynamicPrintConfig ObjectList::get_default_layer_config(const int obj_idx) { DynamicPrintConfig config; @@ -2031,7 +2048,9 @@ void ObjectList::part_selection_changed() if (update_and_show_settings) wxGetApp().obj_settings()->get_og()->set_name(" " + og_name + " "); - if (update_and_show_layers) + if (printer_technology() == ptSLA) + update_and_show_layers = false; + else if (update_and_show_layers) wxGetApp().obj_layers()->get_og()->set_name(" " + og_name + " "); Sidebar& panel = wxGetApp().sidebar(); @@ -2346,7 +2365,7 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, const wxDataViewItem layers_item, const int layer_idx /* = -1*/) { - const int obj_idx = get_selected_obj_idx(); + const int obj_idx = m_objects_model->GetObjectIdByItem(layers_item); if (obj_idx < 0) return; const DynamicPrintConfig& config = object(obj_idx)->layer_config_ranges[range]; @@ -2908,6 +2927,87 @@ void ObjectList::update_settings_items() m_prevent_canvas_selection_update = false; } +// Update settings item for item had it +void ObjectList::update_settings_item_for_item(wxDataViewItem item, wxDataViewItemArray& selections) +{ + const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item); + select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); + + // If settings item was deleted from the list, + // it's need to be deleted from selection array, if it was there + if (settings_item != m_objects_model->GetSettingsItem(item) && + selections.Index(settings_item) != wxNOT_FOUND) { + selections.Remove(settings_item); + + // Select item, if settings_item doesn't exist for item anymore, but was selected + if (selections.Index(item) == wxNOT_FOUND) + selections.Add(item); + } +} + +void ObjectList::update_object_list_by_printer_technology() +{ + m_prevent_canvas_selection_update = true; + wxDataViewItemArray sel; + GetSelections(sel); // stash selection + + wxDataViewItemArray object_items; + m_objects_model->GetChildren(wxDataViewItem(0), object_items); + + for (auto& object_item : object_items) { + // Update Settings Item for object + update_settings_item_for_item(object_item, sel); + + // Update settings for Volumes + wxDataViewItemArray all_object_subitems; + m_objects_model->GetChildren(object_item, all_object_subitems); + for (auto item : all_object_subitems) + if (m_objects_model->GetItemType(item) & itVolume) + // update settings for volume + update_settings_item_for_item(item, sel); + + // Update Layers Items + wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item); + if (!layers_item) + layers_item = add_layer_root_item(object_item); + else if (printer_technology() == ptSLA) { + // If layers root item will be deleted from the list, so + // it's need to be deleted from selection array, if it was there + wxDataViewItemArray del_items; + bool some_layers_was_selected = false; + m_objects_model->GetAllChildren(layers_item, del_items); + for (auto& del_item:del_items) + if (sel.Index(del_item) != wxNOT_FOUND) { + some_layers_was_selected = true; + sel.Remove(del_item); + } + if (sel.Index(layers_item) != wxNOT_FOUND) { + some_layers_was_selected = true; + sel.Remove(layers_item); + } + + // delete all "layers" items + m_objects_model->Delete(layers_item); + + // Select object_item, if layers_item doesn't exist for item anymore, but was some of layer items was/were selected + if (some_layers_was_selected) + sel.Add(object_item); + } + else { + wxDataViewItemArray all_obj_layers; + m_objects_model->GetChildren(layers_item, all_obj_layers); + + for (auto item : all_obj_layers) + // update settings for layer + update_settings_item_for_item(item, sel); + } + } + + // restore selection: + SetSelections(sel); + m_prevent_canvas_selection_update = false; +} + void ObjectList::update_object_menu() { append_menu_items_add_volume(&m_menu_object); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 455f9f7a1..29a8096d4 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -236,6 +236,9 @@ public: bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(); void layers_editing(); + + wxDataViewItem add_layer_root_item(const wxDataViewItem obj_item); + DynamicPrintConfig get_default_layer_config(const int obj_idx); bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume); bool is_splittable(); @@ -305,6 +308,8 @@ public: void last_volume_is_deleted(const int obj_idx); bool has_multi_part_objects(); void update_settings_items(); + void update_settings_item_for_item(wxDataViewItem item, wxDataViewItemArray& selections); + void update_object_list_by_printer_technology(); void update_object_menu(); void instances_to_separated_object(const int obj_idx, const std::set& inst_idx); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cba15d7a9..8e2764bb3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2733,8 +2733,14 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // update plater with new config wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config()); + /* Settings list can be changed after printer preset changing, so + * update all settings items for all item had it. + * Furthermore, Layers editing is implemented only for FFF printers + * and for SLA presets they should be deleted + */ if (preset_type == Preset::TYPE_PRINTER) - wxGetApp().obj_list()->update_settings_items(); +// wxGetApp().obj_list()->update_settings_items(); + wxGetApp().obj_list()->update_object_list_by_printer_technology(); } void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) From 2b6e5a0a7077b2d759ced0a551ba482f6e0469dd Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 10 Jun 2019 15:22:09 +0200 Subject: [PATCH 24/83] Implemented Copy/Paste for Layers. + improved selection (in respect to the Layers) --- src/slic3r/GUI/GUI_ObjectList.cpp | 144 ++++++++++++++++++++++-------- src/slic3r/GUI/GUI_ObjectList.hpp | 20 +++-- src/slic3r/GUI/wxExtensions.cpp | 3 +- 3 files changed, 120 insertions(+), 47 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index dfdaa7171..f6dd6c591 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -581,6 +581,56 @@ void ObjectList::selection_changed() part_selection_changed(); } +void ObjectList::fill_layer_config_ranges_cache() +{ + wxDataViewItemArray sel_layers; + GetSelections(sel_layers); + + const int obj_idx = m_objects_model->GetObjectIdByItem(sel_layers[0]); + if (obj_idx < 0 || (int)m_objects->size() <= obj_idx) + return; + + const t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; + m_layer_config_ranges_cache.clear(); + + for (const auto layer_item : sel_layers) + if (m_objects_model->GetItemType(layer_item) & itLayer) { + auto range = m_objects_model->GetLayerRangeByItem(layer_item); + auto it = ranges.find(range); + if (it != ranges.end()) + m_layer_config_ranges_cache[it->first] = it->second; + } +} + +void ObjectList::paste_layers_into_list() +{ + const int obj_idx = m_objects_model->GetObjectIdByItem(GetSelection()); + + if (obj_idx < 0 || (int)m_objects->size() <= obj_idx || + m_layer_config_ranges_cache.empty() || printer_technology() == ptSLA) + return; + + const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx); + wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item); + if (layers_item) + m_objects_model->Delete(layers_item); + + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; + + // and create Layer item(s) according to the layer_config_ranges + for (const auto range : m_layer_config_ranges_cache) + ranges.emplace(range); + + layers_item = add_layer_root_item(object_item); + + changed_object(obj_idx); + + select_item(layers_item); +#ifndef __WXOSX__ + selection_changed(); +#endif //no __WXOSX__ +} + void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes) { if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx)) @@ -737,10 +787,18 @@ void ObjectList::key_event(wxKeyEvent& event) } else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/)) select_item_all_children(); - else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) - wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); - else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL)) - wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); + else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) { + if (m_selection_mode & smLayer) + fill_layer_config_ranges_cache(); + else + wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); + } + else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL)) { + if (!m_layer_config_ranges_cache.empty()) + paste_layers_into_list(); + else + wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); + } else event.Skip(); } @@ -2104,6 +2162,9 @@ void ObjectList::add_object_to_list(size_t obj_idx) Expand(item); } + // Add layers if it has + add_layer_root_item(item); + #ifndef __WXOSX__ selection_changed(); #endif //__WXMSW__ @@ -2568,22 +2629,18 @@ void ObjectList::update_selections_on_canvas() auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, int instance_idx, bool as_single_selection) { const ItemType& type = m_objects_model->GetItemType(item); - if ( type == itLayerRoot || m_objects_model->GetParent(item) == wxDataViewItem(0) ) { - wxDataViewItem obj_item = type == itLayerRoot ? m_objects_model->GetParent(item) : item; - selection.add_object(m_objects_model->GetIdByItem(obj_item), as_single_selection); - return; - } + const int obj_idx = m_objects_model->GetObjectIdByItem(item); if (type == itVolume) { - const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item)); const int vol_idx = m_objects_model->GetVolumeIdByItem(item); selection.add_volume(obj_idx, vol_idx, std::max(instance_idx, 0), as_single_selection); } else if (type == itInstance) { - const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); const int inst_idx = m_objects_model->GetInstanceIdByItem(item); selection.add_instance(obj_idx, inst_idx, as_single_selection); } + else + selection.add_object(obj_idx, as_single_selection); }; // stores current instance idx before to clear the selection @@ -2654,11 +2711,13 @@ void ObjectList::select_item_all_children() } else { const auto item = GetSelection(); - // Some volume(instance) is selected => select all volumes(instances) inside the current object - if (m_objects_model->GetItemType(item) & (itVolume | itInstance)) + const ItemType item_type = m_objects_model->GetItemType(item); + // Some volume/layer/instance is selected => select all volumes/layers/instances inside the current object + if (item_type & (itVolume | itInstance | itLayer)) m_objects_model->GetChildren(m_objects_model->GetParent(item), sels); - m_selection_mode = m_objects_model->GetItemType(item)&itVolume ? smVolume : smInstance; + m_selection_mode = item_type&itVolume ? smVolume : + item_type&itLayer ? smLayer : smInstance; } SetSelections(sels); @@ -2677,8 +2736,9 @@ void ObjectList::update_selection_mode() } const ItemType type = m_objects_model->GetItemType(GetSelection()); - m_selection_mode = type&itSettings ? smUndef : - type&itVolume ? smVolume : smInstance; + m_selection_mode = type & itSettings ? smUndef : + type & itLayer ? smLayer : + type & itVolume ? smVolume : smInstance; } // check last selected item. If is it possible to select it @@ -2689,33 +2749,37 @@ bool ObjectList::check_last_selection(wxString& msg_str) const bool is_shift_pressed = wxGetKeyState(WXK_SHIFT); - /* We can't mix Parts and Objects/Instances. + /* We can't mix Volumes, Layers and Objects/Instances. * So, show information about it */ const ItemType type = m_objects_model->GetItemType(m_last_selected_item); - // check a case of a selection of the Parts from different Objects - bool impossible_multipart_selection = false; - if (type & itVolume && m_selection_mode == smVolume) - { + // check a case of a selection of the same type items from different Objects + auto impossible_multi_selection = [type, this](const ItemType item_type, const SELECTION_MODE selection_mode) { + if (!(type & item_type && m_selection_mode & selection_mode)) + return false; + wxDataViewItemArray sels; GetSelections(sels); - for (const auto& sel: sels) - if (sel != m_last_selected_item && - m_objects_model->GetParent(sel) != m_objects_model->GetParent(m_last_selected_item)) - { - impossible_multipart_selection = true; - break; - } - } + for (const auto& sel : sels) + if (sel != m_last_selected_item && + m_objects_model->GetTopParent(sel) != m_objects_model->GetTopParent(m_last_selected_item)) + return true; - if (impossible_multipart_selection || + return false; + }; + + if (impossible_multi_selection(itVolume, smVolume) || + impossible_multi_selection(itLayer, smLayer ) || type & itSettings || - type & itVolume && m_selection_mode == smInstance || - !(type & itVolume) && m_selection_mode == smVolume) + type & itVolume && !(m_selection_mode & smVolume ) || + type & itLayer && !(m_selection_mode & smLayer ) || + type & itInstance && !(m_selection_mode & smInstance) + ) { // Inform user why selection isn't complited - const wxString item_type = m_selection_mode == smInstance ? _(L("Object or Instance")) : _(L("Part")); + const wxString item_type = m_selection_mode & smInstance ? _(L("Object or Instance")) : + m_selection_mode & smVolume ? _(L("Part")) : _(L("Layer")); msg_str = wxString::Format( _(L("Unsupported selection")) + "\n\n" + _(L("You started your selection with %s Item.")) + "\n" + @@ -2752,7 +2816,7 @@ void ObjectList::fix_multiselection_conflicts() wxDataViewItemArray sels; GetSelections(sels); - if (m_selection_mode == smVolume) + if (m_selection_mode & (smVolume|smLayer)) { // identify correct parent of the initial selected item const wxDataViewItem& parent = m_objects_model->GetParent(m_last_selected_item == sels.front() ? sels.back() : sels.front()); @@ -2761,8 +2825,10 @@ void ObjectList::fix_multiselection_conflicts() wxDataViewItemArray children; // selected volumes from current parent m_objects_model->GetChildren(parent, children); + const ItemType item_type = m_selection_mode & smVolume ? itVolume : itLayer; + for (const auto child : children) - if (IsSelected(child) && m_objects_model->GetItemType(child)&itVolume) + if (IsSelected(child) && m_objects_model->GetItemType(child) & item_type) sels.Add(child); // If some part is selected, unselect all items except of selected parts of the current object @@ -2928,7 +2994,7 @@ void ObjectList::update_settings_items() } // Update settings item for item had it -void ObjectList::update_settings_item_for_item(wxDataViewItem item, wxDataViewItemArray& selections) +void ObjectList::update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray& selections) { const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item); select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); @@ -2956,7 +3022,7 @@ void ObjectList::update_object_list_by_printer_technology() for (auto& object_item : object_items) { // Update Settings Item for object - update_settings_item_for_item(object_item, sel); + update_settings_item_and_selection(object_item, sel); // Update settings for Volumes wxDataViewItemArray all_object_subitems; @@ -2964,7 +3030,7 @@ void ObjectList::update_object_list_by_printer_technology() for (auto item : all_object_subitems) if (m_objects_model->GetItemType(item) & itVolume) // update settings for volume - update_settings_item_for_item(item, sel); + update_settings_item_and_selection(item, sel); // Update Layers Items wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item); @@ -2999,7 +3065,7 @@ void ObjectList::update_object_list_by_printer_technology() for (auto item : all_obj_layers) // update settings for layer - update_settings_item_for_item(item, sel); + update_settings_item_and_selection(item, sel); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 29a8096d4..7c7046626 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -33,8 +33,9 @@ typedef std::map< std::string, std::vector< std::pair typedef std::vector ModelVolumePtrs; -typedef double coordf_t; -typedef std::pair t_layer_height_range; +typedef double coordf_t; +typedef std::pair t_layer_height_range; +typedef std::map t_layer_config_ranges; namespace GUI { @@ -67,9 +68,10 @@ class ObjectList : public wxDataViewCtrl { enum SELECTION_MODE { - smUndef, - smVolume, - smInstance + smUndef = 0, + smVolume = 1, + smInstance = 2, + smLayer = 4 } m_selection_mode {smUndef}; struct dragged_item_data @@ -130,7 +132,9 @@ class ObjectList : public wxDataViewCtrl DynamicPrintConfig *m_config {nullptr}; std::vector *m_objects{ nullptr }; - std::vector m_bmp_vector; + std::vector m_bmp_vector; + + t_layer_config_ranges m_layer_config_ranges_cache; int m_selected_object_id = -1; bool m_prevent_list_events = false; // We use this flag to avoid circular event handling Select() @@ -308,7 +312,7 @@ public: void last_volume_is_deleted(const int obj_idx); bool has_multi_part_objects(); void update_settings_items(); - void update_settings_item_for_item(wxDataViewItem item, wxDataViewItemArray& selections); + void update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray& selections); void update_object_list_by_printer_technology(); void update_object_menu(); @@ -319,6 +323,8 @@ public: void fix_through_netfabb(); void update_item_error_icon(const int obj_idx, int vol_idx) const ; + void fill_layer_config_ranges_cache(); + void paste_layers_into_list(); void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes); void paste_objects_into_list(const std::vector& object_idxs); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 05cc265c3..c23caa6c8 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1174,7 +1174,8 @@ int ObjectDataViewModel::GetItemIdByLayerRange(const int obj_idx, const t_layer int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const { - wxASSERT(item.IsOk()); + if(!item.IsOk()) + return -1; ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); auto it = find(m_objects.begin(), m_objects.end(), node); From 72046598a966e04caf734867b99e8b360fb05aeb Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 10 Jun 2019 15:49:41 +0200 Subject: [PATCH 25/83] Fixed OSX build --- src/slic3r/GUI/wxExtensions.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 8ade7af07..1ed5770bb 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -20,7 +20,8 @@ namespace Slic3r { enum class ModelVolumeType : int; }; -typedef std::pair t_layer_height_range; +typedef double coordf_t; +typedef std::pair t_layer_height_range; #ifdef __WXMSW__ void msw_rescale_menu(wxMenu* menu); From 16c5a87997e6ce1cea09cda8e2ca4aaf06676092 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 11 Jun 2019 09:50:58 +0200 Subject: [PATCH 26/83] Import/export of the Layers information to/from AMF --- src/libslic3r/Format/AMF.cpp | 57 ++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index d26b5f3ed..ed9c8f445 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -106,6 +106,9 @@ struct AMFParserContext // amf/material/metadata NODE_TYPE_OBJECT, // amf/object // amf/object/metadata + NODE_TYPE_LAYER_CONFIG, // amf/object/layer_config_ranges + NODE_TYPE_RANGE, // amf/object/layer_config_ranges/range + // amf/object/layer_config_ranges/range/metadata NODE_TYPE_MESH, // amf/object/mesh NODE_TYPE_VERTICES, // amf/object/mesh/vertices NODE_TYPE_VERTEX, // amf/object/mesh/vertices/vertex @@ -260,7 +263,9 @@ void AMFParserContext::startElement(const char *name, const char **atts) m_value[0] = get_attribute(atts, "type"); node_type_new = NODE_TYPE_METADATA; } - } else if (strcmp(name, "mesh") == 0) { + } else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT) + node_type_new = NODE_TYPE_LAYER_CONFIG; + else if (strcmp(name, "mesh") == 0) { if (m_path[1] == NODE_TYPE_OBJECT) node_type_new = NODE_TYPE_MESH; } else if (strcmp(name, "instance") == 0) { @@ -317,6 +322,10 @@ void AMFParserContext::startElement(const char *name, const char **atts) else if (strcmp(name, "mirrorz") == 0) node_type_new = NODE_TYPE_MIRRORZ; } + else if (m_path[2] == NODE_TYPE_LAYER_CONFIG && strcmp(name, "range") == 0) { + assert(m_object); + node_type_new = NODE_TYPE_RANGE; + } break; case 4: if (m_path[3] == NODE_TYPE_VERTICES) { @@ -334,6 +343,10 @@ void AMFParserContext::startElement(const char *name, const char **atts) } else if (strcmp(name, "triangle") == 0) node_type_new = NODE_TYPE_TRIANGLE; } + else if (m_path[3] == NODE_TYPE_RANGE && strcmp(name, "metadata") == 0) { + m_value[0] = get_attribute(atts, "type"); + node_type_new = NODE_TYPE_METADATA; + } break; case 5: if (strcmp(name, "coordinates") == 0) { @@ -569,8 +582,13 @@ void AMFParserContext::endElement(const char * /* name */) config = &m_material->config; else if (m_path[1] == NODE_TYPE_OBJECT && m_object) config = &m_object->config; - } else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) + } + else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) config = &m_volume->config; + else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_RANGE && m_object && !m_object->layer_config_ranges.empty()) { + auto it = --m_object->layer_config_ranges.end(); + config = &it->second; + } if (config) config->set_deserialize(opt_key, m_value[1]); } else if (m_path.size() == 3 && m_path[1] == NODE_TYPE_OBJECT && m_object && strcmp(opt_key, "layer_height_profile") == 0) { @@ -607,6 +625,16 @@ void AMFParserContext::endElement(const char * /* name */) } m_object->sla_points_status = sla::PointsStatus::UserModified; } + else if (m_path.size() == 5 && m_path[1] == NODE_TYPE_OBJECT && m_path[3] == NODE_TYPE_RANGE && + m_object && strcmp(opt_key, "layer_height_ranges") == 0) { + // Parse object's layer_height_ranges, a semicolon separated doubles. + char* p = const_cast(m_value[1].c_str()); + char* end = strchr(p, ';'); + *end = 0; + + const t_layer_height_range range = {double(atof(p)), double(atof(end + 1))}; + m_object->layer_config_ranges[range]; + } else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) { if (strcmp(opt_key, "modifier") == 0) { // Is this volume a modifier volume? @@ -905,6 +933,31 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) } //FIXME Store the layer height ranges (ModelObject::layer_height_ranges) + + // #ys_FIXME_experiment : Try to export layer config range + const t_layer_config_ranges& config_ranges = object->layer_config_ranges; + if (!config_ranges.empty()) + { + // Store the layer config range as a single semicolon separated list. + stream << " \n"; + size_t layer_counter = 0; + for (auto range : config_ranges) { + stream << " \n"; + + stream << " "; + stream << range.first.first << ";" << range.first.second << "\n"; + + for (const std::string& key : range.second.keys()) + stream << " " << range.second.serialize(key) << "\n"; + + stream << " \n"; + layer_counter++; + } + + stream << " \n"; + } + + const std::vector& sla_support_points = object->sla_support_points; if (!sla_support_points.empty()) { // Store the SLA supports as a single semicolon separated list. From f0f608f247832b9f5ca3b1cd0a3bb03d148a7fad Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 11 Jun 2019 10:11:42 +0200 Subject: [PATCH 27/83] Copy/paste Layers for OSX --- src/slic3r/GUI/GUI_ObjectList.cpp | 40 ++++++++++++++++++------------- src/slic3r/GUI/GUI_ObjectList.hpp | 3 +++ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f6dd6c591..23eb67c50 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -148,10 +148,10 @@ ObjectList::ObjectList(wxWindow* parent) : wxAcceleratorTable accel(6, entries); SetAcceleratorTable(accel); - this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); }, wxID_COPY); - this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); }, wxID_PASTE); - this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->select_item_all_children(); }, wxID_SELECTALL); - this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->remove(); }, wxID_DELETE); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->copy(); }, wxID_COPY); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->paste(); }, wxID_PASTE); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->select_item_all_children(); }, wxID_SELECTALL); + this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->remove(); }, wxID_DELETE); } #else __WXOSX__ Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX @@ -773,6 +773,22 @@ void ObjectList::show_context_menu() } } +void ObjectList::copy() +{ + if (m_selection_mode & smLayer) + fill_layer_config_ranges_cache(); + else + wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); +} + +void ObjectList::paste() +{ + if (!m_layer_config_ranges_cache.empty()) + paste_layers_into_list(); + else + wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); +} + #ifndef __WXOSX__ void ObjectList::key_event(wxKeyEvent& event) { @@ -787,18 +803,10 @@ void ObjectList::key_event(wxKeyEvent& event) } else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/)) select_item_all_children(); - else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) { - if (m_selection_mode & smLayer) - fill_layer_config_ranges_cache(); - else - wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); - } - else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL)) { - if (!m_layer_config_ranges_cache.empty()) - paste_layers_into_list(); - else - wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); - } + else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) + copy(); + else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL)) + paste(); else event.Skip(); } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 7c7046626..ed055a3a6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -202,6 +202,9 @@ public: void key_event(wxKeyEvent& event); #endif /* __WXOSX__ */ + void copy(); + void paste(); + void get_settings_choice(const wxString& category_name); void get_freq_settings_choice(const wxString& bundle_name); void update_settings_item(); From 4e0eb12ef6518e0a9e964612da626c86890d5e02 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 11 Jun 2019 14:39:41 +0200 Subject: [PATCH 28/83] Import/export of the Layers information to/from 3MF --- src/libslic3r/Format/3mf.cpp | 181 ++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 38b34c462..11202e7b3 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -33,6 +33,7 @@ const std::string RELATIONSHIPS_FILE = "_rels/.rels"; const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config"; const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config"; const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt"; +const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Slic3r_PE_layer_config_ranges.txt"; const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt"; const char* MODEL_TAG = "model"; @@ -331,6 +332,7 @@ namespace Slic3r { typedef std::map IdToMetadataMap; typedef std::map IdToGeometryMap; typedef std::map> IdToLayerHeightsProfileMap; + typedef std::map IdToLayerConfigRangesMap; typedef std::map> IdToSlaSupportPointsMap; // Version of the 3mf file @@ -347,6 +349,7 @@ namespace Slic3r { CurrentConfig m_curr_config; IdToMetadataMap m_objects_metadata; IdToLayerHeightsProfileMap m_layer_heights_profiles; + IdToLayerConfigRangesMap m_layer_config_ranges; IdToSlaSupportPointsMap m_sla_support_points; std::string m_curr_metadata_name; std::string m_curr_characters; @@ -365,6 +368,7 @@ namespace Slic3r { bool _load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config); bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); + void _extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename); @@ -476,6 +480,7 @@ namespace Slic3r { m_curr_config.volume_id = -1; m_objects_metadata.clear(); m_layer_heights_profiles.clear(); + m_layer_config_ranges.clear(); m_sla_support_points.clear(); m_curr_metadata_name.clear(); m_curr_characters.clear(); @@ -546,9 +551,14 @@ namespace Slic3r { if (boost::algorithm::iequals(name, LAYER_HEIGHTS_PROFILE_FILE)) { - // extract slic3r lazer heights profile file + // extract slic3r layer heights profile file _extract_layer_heights_profile_config_from_archive(archive, stat); } + if (boost::algorithm::iequals(name, LAYER_CONFIG_RANGES_FILE)) + { + // extract slic3r layer config ranges file + _extract_layer_config_ranges_from_archive(archive, stat); + } else if (boost::algorithm::iequals(name, SLA_SUPPORT_POINTS_FILE)) { // extract sla support points file @@ -592,6 +602,11 @@ namespace Slic3r { if (obj_layer_heights_profile != m_layer_heights_profiles.end()) model_object->layer_height_profile = obj_layer_heights_profile->second; + // m_layer_config_ranges are indexed by a 1 based model object index. + IdToLayerConfigRangesMap::iterator obj_layer_config_ranges = m_layer_config_ranges.find(object.second + 1); + if (obj_layer_config_ranges != m_layer_config_ranges.end()) + model_object->layer_config_ranges = obj_layer_config_ranges->second; + // m_sla_support_points are indexed by a 1 based model object index. IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.second + 1); if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty()) { @@ -769,6 +784,115 @@ namespace Slic3r { } } + void _3MF_Importer::_extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat) + { + if (stat.m_uncomp_size > 0) + { + std::string buffer((size_t)stat.m_uncomp_size, 0); + mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0); + if (res == 0) { + add_error("Error while reading layer config ranges data to buffer"); + return; + } + + if (buffer.back() == '|') + buffer.pop_back(); + + std::vector objects; + boost::split(objects, buffer, boost::is_any_of("|"), boost::token_compress_off); + + for (std::string& object : objects) + { + // delete all spaces + boost::replace_all(object, " ", ""); + + std::vector object_data; + boost::split(object_data, object, boost::is_any_of("*"), boost::token_compress_off); + /* there should be at least one layer config range in the object + * object_data[0] => object information + * object_data[i>=1] => range information + */ + if (object_data.size() < 2) { + add_error("Error while reading object data"); + continue; + } + + std::vector object_data_id; + boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off); + if (object_data_id.size() != 2) { + add_error("Error while reading object id"); + continue; + } + + // get object information + int object_id = std::atoi(object_data_id[1].c_str()); + if (object_id == 0) { + add_error("Found invalid object id"); + continue; + } + + IdToLayerConfigRangesMap::iterator object_item = m_layer_config_ranges.find(object_id); + if (object_item != m_layer_config_ranges.end()) { + add_error("Found duplicated layer config range"); + continue; + } + + t_layer_config_ranges config_ranges; + + // get ranges information + for (size_t i = 1; i < object_data.size(); ++i) + { + if (object_data[i].back() == '\n') + object_data[i].pop_back(); + + std::vector range_data; + boost::split(range_data, object_data[i], boost::is_any_of("\n"), boost::token_compress_off); + /* There should be at least two options for layer config range + * range_data[0] => Z range information + * range_data[i>=1] => configuration for the range + */ + if (range_data.size() < 3) { + add_error("Found invalid layer config range"); + continue; + } + + std::vector z_range_str; + boost::split(z_range_str, range_data[0], boost::is_any_of("="), boost::token_compress_off); + if (z_range_str.size() != 2) { + add_error("Error while reading layer config range"); + continue; + } + + std::vector z_values; + boost::split(z_values, z_range_str[1], boost::is_any_of(";"), boost::token_compress_off); + if (z_values.size() != 2) { + add_error("Found invalid layer config range"); + continue; + } + + // get Z range information + t_layer_height_range z_range = { (coordf_t)std::atof(z_values[0].c_str()) , (coordf_t)std::atof(z_values[1].c_str()) }; + DynamicPrintConfig& config = config_ranges[z_range]; + + // get configuration options for the range + for (size_t j = 1; j < range_data.size(); ++j) + { + std::vector key_val; + boost::split(key_val, range_data[j], boost::is_any_of("="), boost::token_compress_off); + if (key_val.size() != 2) { + add_error("Error while reading config value"); + continue; + } + config.set_deserialize(key_val[0], key_val[1]); + } + } + + if (!config_ranges.empty()) + m_layer_config_ranges.insert(IdToLayerConfigRangesMap::value_type(object_id, config_ranges)); + } + } + } + void _3MF_Importer::_extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat) { if (stat.m_uncomp_size > 0) @@ -1622,6 +1746,7 @@ namespace Slic3r { bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets); bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items); bool _add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model); + bool _add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model); bool _add_print_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config); bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, const IdToObjectDataMap &objects_data); @@ -1682,6 +1807,16 @@ namespace Slic3r { return false; } + // Adds layer config ranges file ("Metadata/Slic3r_PE_layer_config_ranges.txt"). + // All layer height profiles of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model. + // The index differes from the index of an object ID of an object instance of a 3MF file! + if (!_add_layer_config_ranges_file_to_archive(archive, model)) + { + close_zip_writer(&archive); + boost::filesystem::remove(filename); + return false; + } + // Adds sla support points file ("Metadata/Slic3r_PE_sla_support_points.txt"). // All sla support points of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model. // The index differes from the index of an object ID of an object instance of a 3MF file! @@ -2012,6 +2147,50 @@ namespace Slic3r { return true; } + bool _3MF_Exporter::_add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model) + { + std::string out = ""; + char buffer[1024]; + + unsigned int object_cnt = 0; + for (const ModelObject* object : model.objects) + { + object_cnt++; + const t_layer_config_ranges& ranges = object->layer_config_ranges; + if (!ranges.empty()) + { + sprintf(buffer, "object_id=%d\n", object_cnt); + out += buffer; + + // Store the layer config ranges. + for (const auto& range : ranges) + { + // store minX and maxZ + sprintf(buffer, "*z_range = %f;%f\n", range.first.first, range.first.second); + out += buffer; + + // store range configuration + const DynamicPrintConfig& config = range.second; + for (const std::string& key : config.keys()) + out += " " + key + " = " + config.serialize(key) + "\n"; + } + + out += "|"; + } + } + + if (!out.empty()) + { + if (!mz_zip_writer_add_mem(&archive, LAYER_CONFIG_RANGES_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) + { + add_error("Unable to add layer heights profile file to archive"); + return false; + } + } + + return true; + } + bool _3MF_Exporter::_add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model) { std::string out = ""; From 26fb68ba459d11b9bc0df5047ccda8fbd0b9419e Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 11 Jun 2019 14:54:31 +0200 Subject: [PATCH 29/83] Added missed include for the OSX build --- src/libslic3r/Format/3mf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 11202e7b3..9103232a8 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include From 1694204687ca93e7bd831cf5a5598bc1acfce658 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 12 Jun 2019 16:28:25 +0200 Subject: [PATCH 30/83] Added some logic to layers editor selection --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 126 ++++++++++++++++++---------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 26 ++++-- src/slic3r/GUI/GUI_ObjectList.cpp | 44 ++++++++-- src/slic3r/GUI/GUI_ObjectList.hpp | 4 +- 4 files changed, 136 insertions(+), 64 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index ba0012a2b..5f0ec259d 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -39,72 +39,83 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : m_bmp_add = ScalableBitmap(parent, "add_copies"); } +void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_edited_range) +{ + if (is_last_edited_range && m_selection_type == editor->type()) { + editor->SetFocus(); + editor->SetInsertionPointEnd(); + } +} + wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) { const bool is_last_edited_range = range == m_last_edited_range; + auto set_focus_fn = [range, this](const EditorType type) + { + m_last_edited_range = range; + m_selection_type = type; + }; + // Add control for the "Min Z" - auto temp = new LayerRangeEditor(m_parent, double_to_string(range.first), - [range, this](coordf_t min_z) + auto editor = new LayerRangeEditor(m_parent, double_to_string(range.first), etMinZ, + set_focus_fn, [range, this](coordf_t min_z, bool enter_pressed) { - if (fabs(min_z - range.first) < EPSILON) { - m_selection_type = sitUndef; - return false; // LayersList would not be updated/recreated + if (fabs(min_z - range.first) < EPSILON || min_z > range.second) { + m_selection_type = etUndef; + return false; } // data for next focusing - m_last_edited_range = { min_z, range.second }; - m_selection_type = sitMinZ; + const t_layer_height_range& new_range = { min_z, range.second }; + if (enter_pressed) { + m_last_edited_range = new_range; + m_selection_type = etMinZ; + } - wxGetApp().obj_list()->edit_layer_range(range, m_last_edited_range); - return true; // LayersList will be updated/recreated + return wxGetApp().obj_list()->edit_layer_range(range, new_range); }); - if (is_last_edited_range && m_selection_type == sitMinZ) { - temp->SetFocus(); - temp->SetInsertionPointEnd(); - } - - m_grid_sizer->Add(temp); + select_editor(editor, is_last_edited_range); + m_grid_sizer->Add(editor); // Add control for the "Max Z" - temp = new LayerRangeEditor(m_parent, double_to_string(range.second), - [range, this](coordf_t max_z) + editor = new LayerRangeEditor(m_parent, double_to_string(range.second), etMaxZ, + set_focus_fn, [range, this](coordf_t max_z, bool enter_pressed) { - if (fabs(max_z - range.second) < EPSILON) { - m_selection_type = sitUndef; + if (fabs(max_z - range.second) < EPSILON || range.first > max_z) { + m_selection_type = etUndef; return false; // LayersList would not be updated/recreated } // data for next focusing - m_last_edited_range = { range.first, max_z }; - m_selection_type = sitMaxZ; + const t_layer_height_range& new_range = { range.first, max_z }; + if (enter_pressed) { + m_last_edited_range = new_range; + m_selection_type = etMaxZ; + } - wxGetApp().obj_list()->edit_layer_range(range, m_last_edited_range); - return true; // LayersList will not be updated/recreated + return wxGetApp().obj_list()->edit_layer_range(range, new_range); }); - if (is_last_edited_range && m_selection_type == sitMaxZ) { - temp->SetFocus(); - temp->SetInsertionPointEnd(); - } - - m_grid_sizer->Add(temp); + select_editor(editor, is_last_edited_range); + m_grid_sizer->Add(editor); // Add control for the "Layer height" - temp = new LayerRangeEditor(m_parent, + editor = new LayerRangeEditor(m_parent, double_to_string(m_object->layer_config_ranges[range].option("layer_height")->getFloat()), - [range, this](coordf_t layer_height) + etLayerHeight, set_focus_fn, [range, this](coordf_t layer_height, bool) { - wxGetApp().obj_list()->edit_layer_range(range, layer_height); - return false; // LayersList would not be updated/recreated + return wxGetApp().obj_list()->edit_layer_range(range, layer_height); }); + select_editor(editor, is_last_edited_range); + auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(temp); + sizer->Add(editor); m_grid_sizer->Add(sizer); return sizer; @@ -193,34 +204,61 @@ void ObjectLayers::msw_rescale() LayerRangeEditor::LayerRangeEditor( wxWindow* parent, const wxString& value, - std::function edit_fn + EditorType type, + std::function set_focus_fn, + std::function edit_fn ) : + m_valid_value(value), + m_type(type), wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, wxSize(8 * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) { this->SetFont(wxGetApp().normal_font()); - this->Bind(wxEVT_TEXT_ENTER, ([this, edit_fn](wxEvent& e) + this->Bind(wxEVT_TEXT_ENTER, [this, edit_fn](wxEvent&) { m_enter_pressed = true; // If LayersList wasn't updated/recreated, we can call wxEVT_KILL_FOCUS.Skip() - if ( !edit_fn(get_value()) ) + if (m_type&etLayerHeight) { + if (!edit_fn(get_value(), true)) + SetValue(m_valid_value); + else + m_valid_value = double_to_string(get_value()); m_call_kill_focus = true; - }), this->GetId()); + } + else if (!edit_fn(get_value(), true)) { + SetValue(m_valid_value); + m_call_kill_focus = true; + } + }, this->GetId()); - this->Bind(wxEVT_KILL_FOCUS, ([this, edit_fn](wxEvent& e) + this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e) { if (!m_enter_pressed) { - m_enter_pressed = false; - // If LayersList wasn't updated/recreated, we should call e.Skip() - if ( !edit_fn(get_value()) ) + if (m_type & etLayerHeight) { + if (!edit_fn(get_value(), false)) + SetValue(m_valid_value); + else + m_valid_value = double_to_string(get_value()); e.Skip(); + } + else if (!edit_fn(get_value(), false)) { + SetValue(m_valid_value); + e.Skip(); + } } - else if (m_call_kill_focus) + else if (m_call_kill_focus) { + m_call_kill_focus = false; e.Skip(); - }), this->GetId()); + } + }, this->GetId()); + this->Bind(wxEVT_LEFT_DOWN, ([this, set_focus_fn](wxEvent& e) + { + set_focus_fn(m_type); + e.Skip(); + })); this->Bind(wxEVT_CHAR, ([this](wxKeyEvent& event) { diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 562e04972..9c2af20e5 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -19,18 +19,32 @@ class ConfigOptionsGroup; typedef double coordf_t; typedef std::pair t_layer_height_range; +enum EditorType +{ + etUndef = 0, + etMinZ = 1, + etMaxZ = 2, + etLayerHeight = 4, +}; + class LayerRangeEditor : public wxTextCtrl { bool m_enter_pressed { false }; bool m_call_kill_focus { false }; + wxString m_valid_value; + EditorType m_type; public: LayerRangeEditor( wxWindow* parent, const wxString& value = wxEmptyString, - std::function edit_fn = [](coordf_t) {return false; } + EditorType type = etUndef, + std::function set_focus_fn = [](EditorType) {;}, + std::function edit_fn = [](coordf_t, bool) {return false; } ); ~LayerRangeEditor() {} + EditorType type() const {return m_type;} + private: coordf_t get_value(); }; @@ -43,19 +57,13 @@ class ObjectLayers : public OG_Settings wxFlexGridSizer* m_grid_sizer; t_layer_height_range m_last_edited_range; - - enum SelectedItemType - { - sitUndef, - sitMinZ, - sitMaxZ, - sitLayerHeight, - } m_selection_type {sitUndef}; + EditorType m_selection_type {etUndef}; public: ObjectLayers(wxWindow* parent); ~ObjectLayers() {} + void select_editor(LayerRangeEditor* editor, const bool is_last_edited_range); wxSizer* create_layer(const t_layer_height_range& range); // without_buttons void create_layers_list(); void update_layers_list(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 23eb67c50..b1b57fcd6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2363,6 +2363,18 @@ void ObjectList::del_layer_range(const t_layer_height_range& range) select_item(selectable_item); } +double get_min_layer_height(const int extruder_idx) +{ + const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; + return config.opt_float("min_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1); +} + +double get_max_layer_height(const int extruder_idx) +{ + const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; + return config.opt_float("max_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1); +} + void ObjectList::add_layer_range_after_current(const t_layer_height_range& current_range) { const int obj_idx = get_selected_obj_idx(); @@ -2393,13 +2405,14 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre if (current_range.second == next_range.first) { + const auto old_config = ranges.at(next_range); + const coordf_t delta = (next_range.second - next_range.first); - if (delta < 0.05f) // next range division has no sense + if (delta < get_min_layer_height(old_config.opt_int("extruder"))/*0.05f*/) // next range division has no sense return; const coordf_t midl_layer = next_range.first + 0.5f * delta; - const auto old_config = ranges.at(next_range); t_layer_height_range new_range = { midl_layer, next_range.second }; // delete old layer @@ -2450,21 +2463,32 @@ void ObjectList::add_layer_item(const t_layer_height_range& range, select_item(m_objects_model->AddSettingsChild(layer_item)); } -void ObjectList::edit_layer_range(const t_layer_height_range& range, coordf_t layer_height) +bool ObjectList::edit_layer_range(const t_layer_height_range& range, coordf_t layer_height) { const int obj_idx = get_selected_obj_idx(); - if (obj_idx < 0) return; + if (obj_idx < 0) + return false; - t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; + DynamicPrintConfig* config = &object(obj_idx)->layer_config_ranges[range]; + if (fabs(layer_height - config->opt_float("layer_height")) < EPSILON) + return false; - DynamicPrintConfig* config = &ranges[range]; - config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); + const int extruder_idx = config->opt_int("extruder"); + + if (layer_height >= get_min_layer_height(extruder_idx) && + layer_height <= get_max_layer_height(extruder_idx)) + { + config->set_key_value("layer_height", new ConfigOptionFloat(layer_height)); + return true; + } + + return false; } -void ObjectList::edit_layer_range(const t_layer_height_range& range, const t_layer_height_range& new_range) +bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_layer_height_range& new_range) { const int obj_idx = get_selected_obj_idx(); - if (obj_idx < 0) return; + if (obj_idx < 0) return false; t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; @@ -2484,6 +2508,8 @@ void ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay // To update(recreate) layers sizer call select_item for LayerRoot item expand select_item(root_item); Expand(root_item); + + return true; } void ObjectList::init_objects() diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index ed055a3a6..ed19edd62 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -291,8 +291,8 @@ public: void add_layer_item (const t_layer_height_range& range, const wxDataViewItem layers_item, const int layer_idx = -1); - void edit_layer_range(const t_layer_height_range& range, coordf_t layer_height); - void edit_layer_range(const t_layer_height_range& range, + bool edit_layer_range(const t_layer_height_range& range, coordf_t layer_height); + bool edit_layer_range(const t_layer_height_range& range, const t_layer_height_range& new_range); void init_objects(); From c9dd5f878699e79d64ccb4059f37b8967e872270 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 13 Jun 2019 11:37:03 +0200 Subject: [PATCH 31/83] Fixed updating of data for LayerEditors selection --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 39 ++++++++++++++++------------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 5 +++- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 5f0ec259d..df0c4faeb 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -49,18 +49,27 @@ void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_ed wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) { - const bool is_last_edited_range = range == m_last_edited_range; + const bool is_last_edited_range = range == m_selectable_range; auto set_focus_fn = [range, this](const EditorType type) { - m_last_edited_range = range; + m_selectable_range = range; m_selection_type = type; }; + auto set_focus = [range, this](const t_layer_height_range& new_range, EditorType type, bool enter_pressed) + { + // change selectable range for new one, if enter was pressed or if same range was selected + if (enter_pressed || m_selectable_range == range) + m_selectable_range = new_range; + if (enter_pressed) + m_selection_type = type; + }; + // Add control for the "Min Z" auto editor = new LayerRangeEditor(m_parent, double_to_string(range.first), etMinZ, - set_focus_fn, [range, this](coordf_t min_z, bool enter_pressed) + set_focus_fn, [range, set_focus, this](coordf_t min_z, bool enter_pressed) { if (fabs(min_z - range.first) < EPSILON || min_z > range.second) { m_selection_type = etUndef; @@ -69,10 +78,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // data for next focusing const t_layer_height_range& new_range = { min_z, range.second }; - if (enter_pressed) { - m_last_edited_range = new_range; - m_selection_type = etMinZ; - } + set_focus(new_range, etMinZ, enter_pressed); return wxGetApp().obj_list()->edit_layer_range(range, new_range); }); @@ -83,7 +89,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // Add control for the "Max Z" editor = new LayerRangeEditor(m_parent, double_to_string(range.second), etMaxZ, - set_focus_fn, [range, this](coordf_t max_z, bool enter_pressed) + set_focus_fn, [range, set_focus, this](coordf_t max_z, bool enter_pressed) { if (fabs(max_z - range.second) < EPSILON || range.first > max_z) { m_selection_type = etUndef; @@ -92,10 +98,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // data for next focusing const t_layer_height_range& new_range = { range.first, max_z }; - if (enter_pressed) { - m_last_edited_range = new_range; - m_selection_type = etMaxZ; - } + set_focus(new_range, etMaxZ, enter_pressed); return wxGetApp().obj_list()->edit_layer_range(range, new_range); }); @@ -210,6 +213,7 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, ) : m_valid_value(value), m_type(type), + m_set_focus(set_focus_fn), wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, wxSize(8 * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) { @@ -235,6 +239,11 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e) { if (!m_enter_pressed) { + // update data for next editor selection + LayerRangeEditor* new_editor = dynamic_cast(e.GetWindow()); + if (new_editor) + new_editor->set_focus(); + // If LayersList wasn't updated/recreated, we should call e.Skip() if (m_type & etLayerHeight) { if (!edit_fn(get_value(), false)) @@ -254,12 +263,6 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, } }, this->GetId()); - this->Bind(wxEVT_LEFT_DOWN, ([this, set_focus_fn](wxEvent& e) - { - set_focus_fn(m_type); - e.Skip(); - })); - this->Bind(wxEVT_CHAR, ([this](wxKeyEvent& event) { // select all text using Ctrl+A diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 9c2af20e5..e3366e03e 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -34,6 +34,8 @@ class LayerRangeEditor : public wxTextCtrl wxString m_valid_value; EditorType m_type; + std::function m_set_focus; + public: LayerRangeEditor( wxWindow* parent, const wxString& value = wxEmptyString, @@ -44,6 +46,7 @@ public: ~LayerRangeEditor() {} EditorType type() const {return m_type;} + void set_focus() const { m_set_focus(m_type);} private: coordf_t get_value(); @@ -56,7 +59,7 @@ class ObjectLayers : public OG_Settings ModelObject* m_object {nullptr}; wxFlexGridSizer* m_grid_sizer; - t_layer_height_range m_last_edited_range; + t_layer_height_range m_selectable_range; EditorType m_selection_type {etUndef}; public: From e00774d2e21319ddfacbad417f7dd7309e8f2f56 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 13 Jun 2019 13:00:46 +0200 Subject: [PATCH 32/83] Workarounds for selection under OSX and GTK --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index df0c4faeb..12c1022ce 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -42,8 +42,19 @@ ObjectLayers::ObjectLayers(wxWindow* parent) : void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_edited_range) { if (is_last_edited_range && m_selection_type == editor->type()) { + /* Workaround! Under OSX we should use CallAfter() for SetFocus() after LayerEditors "reorganizations", + * because of selected control's strange behavior: + * cursor is set to the control, but blue border - doesn't. + * And as a result we couldn't edit this control. + * */ +#ifdef __WXOSX__ + wxTheApp->CallAfter([editor]() { +#endif editor->SetFocus(); editor->SetInsertionPointEnd(); +#ifdef __WXOSX__ + }); +#endif } } @@ -239,11 +250,15 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e) { if (!m_enter_pressed) { - // update data for next editor selection +#ifndef __WXGTK__ + /* Update data for next editor selection. + * But under GTK it lucks like there is no information about selected control at e.GetWindow(), + * so we'll take it from wxEVT_LEFT_DOWN event + * */ LayerRangeEditor* new_editor = dynamic_cast(e.GetWindow()); if (new_editor) new_editor->set_focus(); - +#endif // not __WXGTK__ // If LayersList wasn't updated/recreated, we should call e.Skip() if (m_type & etLayerHeight) { if (!edit_fn(get_value(), false)) @@ -263,6 +278,14 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, } }, this->GetId()); +#ifdef __WXGTK__ // Workaround! To take information about selectable range + this->Bind(wxEVT_LEFT_DOWN, [this](wxEvent& e) + { + set_focus(); + e.Skip(); + }, this->GetId()); +#endif //__WXGTK__ + this->Bind(wxEVT_CHAR, ([this](wxKeyEvent& event) { // select all text using Ctrl+A From 86e7a07dd8130462771d91540cc3daa6e0a8bc9c Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 13 Jun 2019 16:17:54 +0200 Subject: [PATCH 33/83] Fixed selection --- src/slic3r/GUI/GUI_ObjectList.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index b1b57fcd6..31396b630 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2543,9 +2543,11 @@ void ObjectList::update_selections() if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) & (itSettings | itLayerRoot | itLayer)) { const auto item = GetSelection(); - if (selection.is_single_full_object() && - m_objects_model->GetIdByItem(m_objects_model->GetParent(item)) == selection.get_object_idx()) - return; + if (selection.is_single_full_object()) { + if (m_objects_model->GetObjectIdByItem(item) == selection.get_object_idx()) + return; + sels.Add(m_objects_model->GetItemById(selection.get_object_idx())); + } if (selection.is_single_volume() || selection.is_any_modifier()) { const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin()); if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx()) From f394f84d51b8654b9008a11e773bdd04d75b979d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 17 Jun 2019 13:09:11 +0200 Subject: [PATCH 34/83] Fixed selection after layers deleting --- src/slic3r/GUI/GUI_ObjectList.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 31396b630..1d7d95b56 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2317,32 +2317,28 @@ void ObjectList::remove() wxDataViewItemArray sels; GetSelections(sels); + wxDataViewItem parent = wxDataViewItem(0); + for (auto& item : sels) { if (m_objects_model->GetParent(item) == wxDataViewItem(0)) delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1); else { -// if (sels.size() == 1) -// select_item(m_objects_model->GetParent(item)); - wxDataViewItem parent = m_objects_model->GetParent(item); - if (sels.size() == 1) { - if (!(m_objects_model->GetItemType(item) & itLayer)) { - select_item(parent); - parent = wxDataViewItem(0); - } - else { - wxDataViewItemArray children; - if (m_objects_model->GetChildren(parent, children) == 1) - parent = m_objects_model->GetTopParent(item); - } + if (m_objects_model->GetItemType(item) & itLayer) { + parent = m_objects_model->GetParent(item); + wxDataViewItemArray children; + if (m_objects_model->GetChildren(parent, children) == 1) + parent = m_objects_model->GetTopParent(item); } + else if (sels.size() == 1) + select_item(m_objects_model->GetParent(item)); del_subobject_item(item); - - if (sels.size() == 1 && parent) - select_item(parent); } } + + if (parent) + select_item(parent); } void ObjectList::del_layer_range(const t_layer_height_range& range) From 5fd3cc267686c74e422a013e62bbae6aea588678 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 17 Jun 2019 13:46:56 +0200 Subject: [PATCH 35/83] Select edited layer after changing instead of "Layers" selection, if editing was in "Layer" mode --- src/slic3r/GUI/GUI_ObjectList.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 1d7d95b56..5539ee29a 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2486,6 +2486,8 @@ bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) return false; + const ItemType sel_type = m_objects_model->GetItemType(GetSelection()); + t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges; const DynamicPrintConfig config = ranges[range]; @@ -2501,8 +2503,7 @@ bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay for (const auto r : ranges) add_layer_item(r.first, root_item); - // To update(recreate) layers sizer call select_item for LayerRoot item expand - select_item(root_item); + select_item(sel_type&itLayer ? m_objects_model->GetItemByLayerRange(obj_idx, new_range) : root_item); Expand(root_item); return true; From 35b3fd317623b98153a0b91d3f51c784d2cc0a20 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Jun 2019 16:15:09 +0200 Subject: [PATCH 36/83] Integrated the new layer height spans with configs into the backend. Fixed some compiler warnings. --- src/libslic3r/Fill/Fill.cpp | 12 +- src/libslic3r/Format/3mf.cpp | 4 +- src/libslic3r/Format/AMF.cpp | 12 +- src/libslic3r/Model.cpp | 4 +- src/libslic3r/Model.hpp | 6 +- src/libslic3r/Print.cpp | 310 ++++++++++++++++----------- src/libslic3r/Print.hpp | 26 +-- src/libslic3r/PrintObject.cpp | 337 ++++++++++++++++++++++-------- src/libslic3r/Slicing.cpp | 22 +- src/libslic3r/Slicing.hpp | 6 +- src/libslic3r/SupportMaterial.cpp | 6 +- src/slic3r/GUI/3DBed.cpp | 4 +- src/slic3r/GUI/Plater.cpp | 3 - src/slic3r/GUI/Selection.cpp | 1 - t/print.t | 8 +- xs/xsp/Print.xsp | 2 - 16 files changed, 491 insertions(+), 272 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 75952e4c2..fbdef29b9 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -126,7 +126,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) Polygons surfaces_polygons = to_polygons(surfaces); Polygons collapsed = diff( surfaces_polygons, - offset2(surfaces_polygons, -distance_between_surfaces/2, +distance_between_surfaces/2), + offset2(surfaces_polygons, (float)-distance_between_surfaces/2, (float)+distance_between_surfaces/2), true); Polygons to_subtract; to_subtract.reserve(collapsed.size() + number_polygons(surfaces)); @@ -137,7 +137,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) surfaces_append( surfaces, intersection_ex( - offset(collapsed, distance_between_surfaces), + offset(collapsed, (float)distance_between_surfaces), to_subtract, true), stInternalSolid); @@ -219,14 +219,14 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) f->z = layerm.layer()->print_z; f->angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value)); // Maximum length of the perimeter segment linking two infill lines. - f->link_max_length = scale_(link_max_length); + f->link_max_length = (coord_t)scale_(link_max_length); // Used by the concentric infill pattern to clip the loops to create extrusion paths. - f->loop_clipping = scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER; + f->loop_clipping = coord_t(scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER); // f->layer_height = h; // apply half spacing using this flow's own spacing and generate infill FillParams params; - params.density = 0.01 * density; + params.density = float(0.01 * density); // params.dont_adjust = true; params.dont_adjust = false; Polylines polylines = f->fill_surface(&surface, params); @@ -240,7 +240,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) // so we can safely ignore the slight variation that might have // been applied to $f->flow_spacing } else { - flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, h, is_bridge || f->use_bridge_flow()); + flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, (float)h, is_bridge || f->use_bridge_flow()); } // Save into layer. diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 002e125c7..45b8fe52f 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -2031,7 +2031,7 @@ namespace Slic3r { return false; } - vertices_count += its.vertices.size(); + vertices_count += (int)its.vertices.size(); const Transform3d& matrix = volume->get_matrix(); @@ -2061,7 +2061,7 @@ namespace Slic3r { // updates triangle offsets volume_it->second.first_triangle_id = triangles_count; - triangles_count += its.indices.size(); + triangles_count += (int)its.indices.size(); volume_it->second.last_triangle_id = triangles_count - 1; for (size_t i = 0; i < its.indices.size(); ++ i) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 4f0a402ea..90a538731 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -192,7 +192,7 @@ struct AMFParserContext }; // Version of the amf file - unsigned int m_version; + unsigned int m_version; // Current Expat XML parser instance. XML_Parser m_parser; // Model to receive objects extracted from an AMF file. @@ -616,7 +616,7 @@ void AMFParserContext::endElement(const char * /* name */) if (end != nullptr) *end = 0; - point(coord_idx) = atof(p); + point(coord_idx) = float(atof(p)); if (++coord_idx == 5) { m_object->sla_support_points.push_back(sla::SupportPoint(point)); coord_idx = 0; @@ -628,8 +628,8 @@ void AMFParserContext::endElement(const char * /* name */) m_object->sla_points_status = sla::PointsStatus::UserModified; } else if (m_path.size() == 5 && m_path[1] == NODE_TYPE_OBJECT && m_path[3] == NODE_TYPE_RANGE && - m_object && strcmp(opt_key, "layer_height_ranges") == 0) { - // Parse object's layer_height_ranges, a semicolon separated doubles. + m_object && strcmp(opt_key, "layer_height_range") == 0) { + // Parse object's layer_height_range, a semicolon separated doubles. char* p = const_cast(m_value[1].c_str()); char* end = strchr(p, ';'); *end = 0; @@ -946,7 +946,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) for (auto range : config_ranges) { stream << " \n"; - stream << " "; + stream << " "; stream << range.first.first << ";" << range.first.second << "\n"; for (const std::string& key : range.second.keys()) @@ -994,7 +994,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config) stream << " \n"; stream << " \n"; } - num_vertices += its.vertices.size(); + num_vertices += (int)its.vertices.size(); } stream << " \n"; for (size_t i_volume = 0; i_volume < object->volumes.size(); ++i_volume) { diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 1f9efbc56..90725f31e 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -593,7 +593,6 @@ ModelObject& ModelObject::assign_copy(const ModelObject &rhs) this->config = rhs.config; this->sla_support_points = rhs.sla_support_points; this->sla_points_status = rhs.sla_points_status; - this->layer_height_ranges = rhs.layer_height_ranges; this->layer_config_ranges = rhs.layer_config_ranges; // #ys_FIXME_experiment this->layer_height_profile = rhs.layer_height_profile; this->origin_translation = rhs.origin_translation; @@ -630,7 +629,6 @@ ModelObject& ModelObject::assign_copy(ModelObject &&rhs) this->config = std::move(rhs.config); this->sla_support_points = std::move(rhs.sla_support_points); this->sla_points_status = std::move(rhs.sla_points_status); - this->layer_height_ranges = std::move(rhs.layer_height_ranges); this->layer_config_ranges = std::move(rhs.layer_config_ranges); // #ys_FIXME_experiment this->layer_height_profile = std::move(rhs.layer_height_profile); this->origin_translation = std::move(rhs.origin_translation); @@ -1809,7 +1807,7 @@ bool model_volume_list_changed(const ModelObject &model_object_old, const ModelO if (!mv_old.get_matrix().isApprox(mv_new.get_matrix())) return true; - ++i_old; + ++ i_old; ++ i_new; } for (; i_old < model_object_old.volumes.size(); ++ i_old) { diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 22d43dbc7..c1850df98 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -179,10 +179,8 @@ public: ModelVolumePtrs volumes; // Configuration parameters specific to a single ModelObject, overriding the global Slic3r settings. DynamicPrintConfig config; - // Variation of a layer thickness for spans of Z coordinates. - t_layer_height_ranges layer_height_ranges; - // Variation of a layer thickness for spans of Z coordinates. - t_layer_config_ranges layer_config_ranges; + // Variation of a layer thickness for spans of Z coordinates + optional parameter overrides. + t_layer_config_ranges layer_config_ranges; // Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers. // The pairs of are packed into a 1D array. std::vector layer_height_profile; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index ed4af3995..5e4f25334 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -41,36 +41,6 @@ void Print::clear() m_model.clear_objects(); } -// Only used by the Perl test cases. -void Print::reload_object(size_t /* idx */) -{ - ModelObjectPtrs model_objects; - { - tbb::mutex::scoped_lock lock(this->state_mutex()); - // The following call should stop background processing if it is running. - this->invalidate_all_steps(); - /* TODO: this method should check whether the per-object config and per-material configs - have changed in such a way that regions need to be rearranged or we can just apply - the diff and invalidate something. Same logic as apply() - For now we just re-add all objects since we haven't implemented this incremental logic yet. - This should also check whether object volumes (parts) have changed. */ - // collect all current model objects - model_objects.reserve(m_objects.size()); - for (PrintObject *object : m_objects) - model_objects.push_back(object->model_object()); - // remove our print objects - for (PrintObject *object : m_objects) - delete object; - m_objects.clear(); - for (PrintRegion *region : m_regions) - delete region; - m_regions.clear(); - } - // re-add model objects - for (ModelObject *mo : model_objects) - this->add_model_object(mo); -} - PrintRegion* Print::add_region() { m_regions.emplace_back(new PrintRegion(this)); @@ -335,7 +305,7 @@ unsigned int Print::num_object_instances() const { unsigned int instances = 0; for (const PrintObject *print_object : m_objects) - instances += print_object->copies().size(); + instances += (unsigned int)print_object->copies().size(); return instances; } @@ -360,7 +330,7 @@ double Print::max_allowed_layer_height() const // Caller is responsible for supplying models whose objects don't collide // and have explicit instance positions. -void Print::add_model_object(ModelObject* model_object, int idx) +void Print::add_model_object_perl_tests_only(ModelObject* model_object, int idx) { tbb::mutex::scoped_lock lock(this->state_mutex()); // Add a copy of this ModelObject to this Print. @@ -389,26 +359,26 @@ void Print::add_model_object(ModelObject* model_object, int idx) object->set_trafo(trafo); } - size_t volume_id = 0; + int volume_id = 0; for (const ModelVolume *volume : model_object->volumes) { if (! volume->is_model_part() && ! volume->is_modifier()) continue; // Get the config applied to this volume. - PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, *volume, 99999); + PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, *volume, 99999); // Find an existing print region with the same config. - size_t region_id = size_t(-1); - for (size_t i = 0; i < m_regions.size(); ++ i) + int region_id = -1; + for (int i = 0; i < (int)m_regions.size(); ++ i) if (config.equals(m_regions[i]->config())) { region_id = i; break; } // If no region exists with the same config, create a new one. - if (region_id == size_t(-1)) { - region_id = m_regions.size(); + if (region_id == -1) { + region_id = (int)m_regions.size(); this->add_region(config); } // Assign volume to a region. - object->add_region_volume(region_id, volume_id); + object->add_region_volume((unsigned int)region_id, volume_id, t_layer_height_range(0, DBL_MAX)); ++ volume_id; } @@ -489,18 +459,18 @@ bool Print::apply_config_perl_tests_only(DynamicPrintConfig config) bool this_region_config_set = false; for (PrintObject *object : m_objects) { if (region_id < object->region_volumes.size()) { - for (int volume_id : object->region_volumes[region_id]) { - const ModelVolume &volume = *object->model_object()->volumes[volume_id]; + for (const std::pair &volume_and_range : object->region_volumes[region_id]) { + const ModelVolume &volume = *object->model_object()->volumes[volume_and_range.second]; if (this_region_config_set) { // If the new config for this volume differs from the other // volume configs currently associated to this region, it means // the region subdivision does not make sense anymore. - if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, volume, 99999))) { + if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, volume, 99999))) { rearrange_regions = true; goto exit_for_rearrange_regions; } } else { - this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, volume, 99999); + this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, volume, 99999); this_region_config_set = true; } for (const PrintRegionConfig &cfg : other_region_configs) { @@ -540,7 +510,7 @@ exit_for_rearrange_regions: model_objects.push_back(object->model_object()); this->clear(); for (ModelObject *mo : model_objects) - this->add_model_object(mo); + this->add_model_object_perl_tests_only(mo); invalidated = true; } @@ -620,6 +590,20 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst, } } +static inline void layer_height_ranges_copy_configs(t_layer_config_ranges &lr_dst, const t_layer_config_ranges &lr_src) +{ + assert(lr_dst.size() == lr_src.size()); + auto it_src = lr_src.cbegin(); + for (auto &kvp_dst : lr_dst) { + const auto &kvp_src = *it_src ++; + assert(std::abs(kvp_dst.first.first - kvp_src.first.first ) <= EPSILON); + assert(std::abs(kvp_dst.first.second - kvp_src.first.second) <= EPSILON); + // Layer heights are allowed do differ in case the layer height table is being overriden by the smooth profile. + // assert(std::abs(kvp_dst.second.option("layer_height")->getFloat() - kvp_src.second.option("layer_height")->getFloat()) <= EPSILON); + kvp_dst.second = kvp_src.second; + } +} + static inline bool transform3d_lower(const Transform3d &lhs, const Transform3d &rhs) { typedef Transform3d::Scalar T; @@ -674,6 +658,23 @@ static std::vector print_objects_from_model_object(const ModelOb return std::vector(trafos.begin(), trafos.end()); } +// Compare just the layer ranges and their layer heights, not the associated configs. +// Ignore the layer heights if check_layer_heights is false. +bool layer_height_ranges_equal(const t_layer_config_ranges &lr1, const t_layer_config_ranges &lr2, bool check_layer_height) +{ + if (lr1.size() != lr2.size()) + return false; + auto it2 = lr2.begin(); + for (const auto &kvp1 : lr1) { + const auto &kvp2 = *it2 ++; + if (std::abs(kvp1.first.first - kvp2.first.first ) > EPSILON || + std::abs(kvp1.first.second - kvp2.first.second) > EPSILON || + (check_layer_height && std::abs(kvp1.second.option("layer_height")->getFloat() - kvp2.second.option("layer_height")->getFloat()) > EPSILON)) + return false; + } + return true; +} + Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &config_in) { #ifdef _DEBUG @@ -724,6 +725,50 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co // Handle changes to regions config defaults m_default_region_config.apply_only(config, region_diff, true); + class LayerRanges + { + public: + LayerRanges() {} + // Convert input config ranges into continuous non-overlapping sorted vector of intervals and their configs. + void assign(const t_layer_config_ranges &in) { + m_ranges.clear(); + m_ranges.reserve(in.size()); + // Input ranges are sorted lexicographically. First range trims the other ranges. + coordf_t last_z = 0; + for (const std::pair &range : in) { +// for (auto &range : in) { + if (range.first.second > last_z) { + coordf_t min_z = std::max(range.first.first, 0.); + if (min_z > last_z + EPSILON) { + m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr); + last_z = min_z; + } + if (range.first.second > last_z + EPSILON) { + const DynamicPrintConfig* cfg = &range.second; + m_ranges.emplace_back(t_layer_height_range(last_z, range.first.second), cfg); + last_z = range.first.second; + } + } + } + if (m_ranges.empty()) + m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr); + else if (m_ranges.back().second == nullptr) + m_ranges.back().first.second = DBL_MAX; + else + m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr); + } + const DynamicPrintConfig* config(const t_layer_height_range &range) const { + auto it = std::lower_bound(m_ranges.begin(), m_ranges.end(), std::make_pair< t_layer_height_range, const DynamicPrintConfig*>(t_layer_height_range(range.first - EPSILON, range.second - EPSILON), nullptr)); + assert(it != m_ranges.end()); + assert(it == m_ranges.end() || std::abs(it->first.first - range.first ) < EPSILON); + assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON); + return (it == m_ranges.end()) ? nullptr : it->second; + } + auto begin() const { return m_ranges.cbegin(); } + auto end() const { return m_ranges.cend(); } + private: + std::vector> m_ranges; + }; struct ModelObjectStatus { enum Status { Unknown, @@ -733,8 +778,9 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co Deleted, }; ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {} - ModelID id; - Status status; + ModelID id; + Status status; + LayerRanges layer_ranges; // Search by id. bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; } }; @@ -861,22 +907,23 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co auto it_status = model_object_status.find(ModelObjectStatus(model_object.id())); assert(it_status != model_object_status.end()); assert(it_status->status != ModelObjectStatus::Deleted); + const ModelObject& model_object_new = *model.objects[idx_model_object]; + const_cast(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges); if (it_status->status == ModelObjectStatus::New) // PrintObject instances will be added in the next loop. continue; // Update the ModelObject instance, possibly invalidate the linked PrintObjects. assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved); - const ModelObject &model_object_new = *model.objects[idx_model_object]; // Check whether a model part volume was added or removed, their transformations or order changed. + // Only volume IDs, volume types and their order are checked, configuration and other parameters are NOT checked. bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART); bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::PARAMETER_MODIFIER); bool support_blockers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER); bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER); if (model_parts_differ || modifiers_differ || model_object.origin_translation != model_object_new.origin_translation || -// model_object.layer_height_ranges != model_object_new.layer_height_ranges || - model_object.layer_config_ranges != model_object_new.layer_config_ranges || // #ys_FIXME_experiment - model_object.layer_height_profile != model_object_new.layer_height_profile) { + model_object.layer_height_profile != model_object_new.layer_height_profile || + ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty())) { // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects. auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); for (auto it = range.first; it != range.second; ++ it) { @@ -916,7 +963,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co //FIXME What to do with m_material_id? model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART); model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER); - // Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step. + layer_height_ranges_copy_configs(model_object.layer_config_ranges /* dst */, model_object_new.layer_config_ranges /* src */); + // Copy the ModelObject name, input_file and instances. The instances will be compared against PrintObject instances in the next step. model_object.name = model_object_new.name; model_object.input_file = model_object_new.input_file; model_object.clear_instances(); @@ -1028,19 +1076,27 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co PrintRegionConfig this_region_config; bool this_region_config_set = false; for (PrintObject *print_object : m_objects) { + const LayerRanges *layer_ranges; + { + auto it_status = model_object_status.find(ModelObjectStatus(print_object->model_object()->id())); + assert(it_status != model_object_status.end()); + assert(it_status->status != ModelObjectStatus::Deleted); + layer_ranges = &it_status->layer_ranges; + } if (region_id < print_object->region_volumes.size()) { - for (int volume_id : print_object->region_volumes[region_id]) { - const ModelVolume &volume = *print_object->model_object()->volumes[volume_id]; + for (const std::pair &volume_and_range : print_object->region_volumes[region_id]) { + const ModelVolume &volume = *print_object->model_object()->volumes[volume_and_range.second]; + const DynamicPrintConfig *layer_range_config = layer_ranges->config(volume_and_range.first); if (this_region_config_set) { // If the new config for this volume differs from the other // volume configs currently associated to this region, it means // the region subdivision does not make sense anymore. - if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, volume, num_extruders))) + if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, layer_range_config, volume, num_extruders))) // Regions were split. Reset this print_object. goto print_object_end; } else { - this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, volume, num_extruders); - for (size_t i = 0; i < region_id; ++i) { + this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, layer_range_config, volume, num_extruders); + for (size_t i = 0; i < region_id; ++ i) { const PrintRegion ®ion_other = *m_regions[i]; if (region_other.m_refcnt != 0 && region_other.config().equals(this_region_config)) // Regions were merged. Reset this print_object. @@ -1055,7 +1111,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co update_apply_status(print_object->invalidate_all_steps()); // Decrease the references to regions from this volume. int ireg = 0; - for (const std::vector &volumes : print_object->region_volumes) { + for (const std::vector> &volumes : print_object->region_volumes) { if (! volumes.empty()) -- m_regions[ireg]->m_refcnt; ++ ireg; @@ -1077,52 +1133,65 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co for (size_t idx_print_object = 0; idx_print_object < m_objects.size(); ++ idx_print_object) { PrintObject &print_object0 = *m_objects[idx_print_object]; const ModelObject &model_object = *print_object0.model_object(); - std::vector map_volume_to_region(model_object.volumes.size(), -1); + const LayerRanges *layer_ranges; + { + auto it_status = model_object_status.find(ModelObjectStatus(model_object.id())); + assert(it_status != model_object_status.end()); + assert(it_status->status != ModelObjectStatus::Deleted); + layer_ranges = &it_status->layer_ranges; + } + std::vector regions_in_object; + regions_in_object.reserve(64); for (size_t i = idx_print_object; i < m_objects.size() && m_objects[i]->model_object() == &model_object; ++ i) { PrintObject &print_object = *m_objects[i]; bool fresh = print_object.region_volumes.empty(); unsigned int volume_id = 0; + unsigned int idx_region_in_object = 0; for (const ModelVolume *volume : model_object.volumes) { if (! volume->is_model_part() && ! volume->is_modifier()) { ++ volume_id; continue; } - int region_id = -1; - if (&print_object == &print_object0) { - // Get the config applied to this volume. - PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, *volume, num_extruders); - // Find an existing print region with the same config. - int idx_empty_slot = -1; - for (int i = 0; i < (int)m_regions.size(); ++ i) { - if (m_regions[i]->m_refcnt == 0) { - if (idx_empty_slot == -1) - idx_empty_slot = i; - } else if (config.equals(m_regions[i]->config())) { - region_id = i; - break; + // Filter the layer ranges, so they do not overlap and they contain at least a single layer. + // Now insert a volume with a layer range to its own region. + for (auto it_range = layer_ranges->begin(); it_range != layer_ranges->end(); ++ it_range) { + int region_id = -1; + if (&print_object == &print_object0) { + // Get the config applied to this volume. + PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, it_range->second, *volume, num_extruders); + // Find an existing print region with the same config. + int idx_empty_slot = -1; + for (int i = 0; i < (int)m_regions.size(); ++ i) { + if (m_regions[i]->m_refcnt == 0) { + if (idx_empty_slot == -1) + idx_empty_slot = i; + } else if (config.equals(m_regions[i]->config())) { + region_id = i; + break; + } + } + // If no region exists with the same config, create a new one. + if (region_id == -1) { + if (idx_empty_slot == -1) { + region_id = (int)m_regions.size(); + this->add_region(config); + } else { + region_id = idx_empty_slot; + m_regions[region_id]->set_config(std::move(config)); + } } - } - // If no region exists with the same config, create a new one. - if (region_id == -1) { - if (idx_empty_slot == -1) { - region_id = (int)m_regions.size(); - this->add_region(config); - } else { - region_id = idx_empty_slot; - m_regions[region_id]->set_config(std::move(config)); - } - } - map_volume_to_region[volume_id] = region_id; - } else - region_id = map_volume_to_region[volume_id]; - // Assign volume to a region. - if (fresh) { - if (region_id >= print_object.region_volumes.size() || print_object.region_volumes[region_id].empty()) - ++ m_regions[region_id]->m_refcnt; - print_object.add_region_volume(region_id, volume_id); - } - ++ volume_id; - } + regions_in_object.emplace_back(region_id); + } else + region_id = regions_in_object[idx_region_in_object ++]; + // Assign volume to a region. + if (fresh) { + if (region_id >= print_object.region_volumes.size() || print_object.region_volumes[region_id].empty()) + ++ m_regions[region_id]->m_refcnt; + print_object.add_region_volume(region_id, volume_id, it_range->first); + } + } + ++ volume_id; + } } } @@ -1176,7 +1245,7 @@ std::string Print::validate() const Polygon convex_hull0 = offset( print_object->model_object()->convex_hull_2d( Geometry::assemble_transform(Vec3d::Zero(), rotation, model_instance0->get_scaling_factor(), model_instance0->get_mirror())), - scale_(m_config.extruder_clearance_radius.value) / 2., jtRound, scale_(0.1)).front(); + float(scale_(0.5 * m_config.extruder_clearance_radius.value)), jtRound, float(scale_(0.1))).front(); // Now we check that no instance of convex_hull intersects any of the previously checked object instances. for (const Point © : print_object->m_copies) { Polygon convex_hull = convex_hull0; @@ -1228,7 +1297,6 @@ std::string Print::validate() const bool has_custom_layering = false; std::vector> layer_height_profiles; for (const PrintObject *object : m_objects) { -// has_custom_layering = ! object->model_object()->layer_height_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); has_custom_layering = ! object->model_object()->layer_config_ranges.empty() || ! object->model_object()->layer_height_profile.empty(); // #ys_FIXME_experiment if (has_custom_layering) { layer_height_profiles.assign(m_objects.size(), std::vector()); @@ -1437,9 +1505,9 @@ Flow Print::brim_flow() const generation as well. */ return Flow::new_from_config_width( frPerimeter, - width, - m_config.nozzle_diameter.get_at(m_regions.front()->config().perimeter_extruder-1), - this->skirt_first_layer_height(), + width, + (float)m_config.nozzle_diameter.get_at(m_regions.front()->config().perimeter_extruder-1), + (float)this->skirt_first_layer_height(), 0 ); } @@ -1459,9 +1527,9 @@ Flow Print::skirt_flow() const generation as well. */ return Flow::new_from_config_width( frPerimeter, - width, - m_config.nozzle_diameter.get_at(m_objects.front()->config().support_material_extruder-1), - this->skirt_first_layer_height(), + width, + (float)m_config.nozzle_diameter.get_at(m_objects.front()->config().support_material_extruder-1), + (float)this->skirt_first_layer_height(), 0 ); } @@ -1636,20 +1704,20 @@ void Print::_make_skirt() // Initial offset of the brim inner edge from the object (possible with a support & raft). // The skirt will touch the brim if the brim is extruded. - Flow brim_flow = this->brim_flow(); + Flow brim_flow = this->brim_flow(); double actual_brim_width = brim_flow.spacing() * floor(m_config.brim_width.value / brim_flow.spacing()); - coord_t distance = scale_(std::max(m_config.skirt_distance.value, actual_brim_width) - spacing/2.); + auto distance = float(scale_(std::max(m_config.skirt_distance.value, actual_brim_width) - spacing/2.)); // Draw outlines from outside to inside. // Loop while we have less skirts than required or any extruder hasn't reached the min length if any. std::vector extruded_length(extruders.size(), 0.); for (int i = n_skirts, extruder_idx = 0; i > 0; -- i) { this->throw_if_canceled(); // Offset the skirt outside. - distance += coord_t(scale_(spacing)); + distance += float(scale_(spacing)); // Generate the skirt centerline. Polygon loop; { - Polygons loops = offset(convex_hull, distance, ClipperLib::jtRound, scale_(0.1)); + Polygons loops = offset(convex_hull, distance, ClipperLib::jtRound, float(scale_(0.1))); Geometry::simplify_polygons(loops, scale_(0.05), &loops); if (loops.empty()) break; @@ -1660,9 +1728,9 @@ void Print::_make_skirt() eloop.paths.emplace_back(ExtrusionPath( ExtrusionPath( erSkirt, - mm3_per_mm, // this will be overridden at G-code export time + (float)mm3_per_mm, // this will be overridden at G-code export time flow.width, - first_layer_height // this will be overridden at G-code export time + (float)first_layer_height // this will be overridden at G-code export time ))); eloop.paths.back().polyline = loop.split_at_first_point(); m_skirt.append(eloop); @@ -1788,7 +1856,7 @@ void Print::_make_wipe_tower() // Insert the new support layer. double height = lt.print_z - m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z; //FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway. - it_layer = m_objects.front()->insert_support_layer(it_layer, size_t(-1), height, lt.print_z, lt.print_z - 0.5 * height); + it_layer = m_objects.front()->insert_support_layer(it_layer, -1, height, lt.print_z, lt.print_z - 0.5 * height); ++ it_layer; } } @@ -1815,19 +1883,19 @@ void Print::_make_wipe_tower() WipeTowerPrusaMM::parse_material(m_config.filament_type.get_at(i).c_str()), m_config.temperature.get_at(i), m_config.first_layer_temperature.get_at(i), - m_config.filament_loading_speed.get_at(i), - m_config.filament_loading_speed_start.get_at(i), - m_config.filament_unloading_speed.get_at(i), - m_config.filament_unloading_speed_start.get_at(i), - m_config.filament_toolchange_delay.get_at(i), + (float)m_config.filament_loading_speed.get_at(i), + (float)m_config.filament_loading_speed_start.get_at(i), + (float)m_config.filament_unloading_speed.get_at(i), + (float)m_config.filament_unloading_speed_start.get_at(i), + (float)m_config.filament_toolchange_delay.get_at(i), m_config.filament_cooling_moves.get_at(i), - m_config.filament_cooling_initial_speed.get_at(i), - m_config.filament_cooling_final_speed.get_at(i), + (float)m_config.filament_cooling_initial_speed.get_at(i), + (float)m_config.filament_cooling_final_speed.get_at(i), m_config.filament_ramming_parameters.get_at(i), - m_config.nozzle_diameter.get_at(i)); + (float)m_config.nozzle_diameter.get_at(i)); m_wipe_tower_data.priming = Slic3r::make_unique( - wipe_tower.prime(this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false)); + wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false)); // Lets go through the wipe tower layers and determine pairs of extruder changes for each // to pass to wipe_tower (so that it can use it for planning the layout of the tower) @@ -1836,21 +1904,21 @@ void Print::_make_wipe_tower() for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers if (!layer_tools.has_wipe_tower) continue; bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front(); - wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id,false); + wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id, false); for (const auto extruder_id : layer_tools.extruders) { if ((first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) { float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange // Not all of that can be used for infill purging: - volume_to_wipe -= m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id); + volume_to_wipe -= (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id); // try to assign some infills/objects for the wiping: volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id, volume_to_wipe); // add back the minimal amount toforce on the wipe tower: - volume_to_wipe += m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id); + volume_to_wipe += (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id); // request a toolchange at the wipe tower with at least volume_to_wipe purging amount - wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, + wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back(), volume_to_wipe); current_extruder_id = extruder_id; } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 53d6d692d..c024a3ad2 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -80,8 +80,8 @@ private: // Prevents erroneous use by other classes. typedef PrintObjectBaseWithState Inherited; public: - // vector of (vectors of volume ids), indexed by region_id - std::vector> region_volumes; + // vector of (layer height ranges and vectors of volume ids), indexed by region_id + std::vector>> region_volumes; // this is set to true when LayerRegion->slices is split in top/internal/bottom // so that next call to make_perimeters() performs a union() before computing loops @@ -99,10 +99,10 @@ public: BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); } // adds region_id, too, if necessary - void add_region_volume(unsigned int region_id, int volume_id) { + void add_region_volume(unsigned int region_id, int volume_id, const t_layer_height_range &layer_range) { if (region_id >= region_volumes.size()) region_volumes.resize(region_id + 1); - region_volumes[region_id].emplace_back(volume_id); + region_volumes[region_id].emplace_back(layer_range, volume_id); } // This is the *total* layer count (including support layers) // this value is not supposed to be compared with Layer::id @@ -141,8 +141,9 @@ public: void slice(); // Helpers to slice support enforcer / blocker meshes by the support generator. - std::vector slice_support_enforcers() const; - std::vector slice_support_blockers() const; + std::vector slice_support_volumes(const ModelVolumeType &model_volume_type) const; + std::vector slice_support_blockers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_BLOCKER); } + std::vector slice_support_enforcers() const { return this->slice_support_volumes(ModelVolumeType::SUPPORT_ENFORCER); } protected: // to be called from Print only. @@ -165,7 +166,7 @@ protected: void update_slicing_parameters(); static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders); - static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume, size_t num_extruders); + static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders); private: void make_perimeters(); @@ -201,9 +202,11 @@ private: LayerPtrs m_layers; SupportLayerPtrs m_support_layers; - std::vector _slice_region(size_t region_id, const std::vector &z, bool modifier); - std::vector _slice_volumes(const std::vector &z, const std::vector &volumes) const; - std::vector _slice_volume(const std::vector &z, const ModelVolume &volume) const; + std::vector slice_region(size_t region_id, const std::vector &z) const; + std::vector slice_modifiers(size_t region_id, const std::vector &z) const; + std::vector slice_volumes(const std::vector &z, const std::vector &volumes) const; + std::vector slice_volume(const std::vector &z, const ModelVolume &volume) const; + std::vector slice_volume(const std::vector &z, const std::vector &ranges, const ModelVolume &volume) const; }; struct WipeTowerData @@ -292,8 +295,7 @@ public: ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override; // The following three methods are used by the Perl tests only. Get rid of them! - void reload_object(size_t idx); - void add_model_object(ModelObject* model_object, int idx = -1); + void add_model_object_perl_tests_only(ModelObject* model_object, int idx = -1); bool apply_config_perl_tests_only(DynamicPrintConfig config); void process() override; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 3add19021..f7d6f891d 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -49,7 +49,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, bool add_insta { // Translate meshes so that our toolpath generation algorithms work with smaller // XY coordinates; this translation is an optimization and not strictly required. - // A cloned mesh will be aligned to 0 before slicing in _slice_region() since we + // A cloned mesh will be aligned to 0 before slicing in slice_region() since we // don't assume it's already aligned and we don't alter the original position in model. // We store the XY translation so that we can place copies correctly in the output G-code // (copies are expressed in G-code coordinates and this translation is not publicly exposed). @@ -590,7 +590,12 @@ bool PrintObject::invalidate_step(PrintObjectStep step) bool PrintObject::invalidate_all_steps() { - return Inherited::invalidate_all_steps() | m_print->invalidate_all_steps(); + // First call the "invalidate" functions, which may cancel background processing. + bool result = Inherited::invalidate_all_steps() | m_print->invalidate_all_steps(); + // Then reset some of the depending values. + this->m_slicing_params.valid = false; + this->region_volumes.clear(); + return result; } bool PrintObject::has_support_material() const @@ -1354,10 +1359,12 @@ PrintObjectConfig PrintObject::object_config_from_model_object(const PrintObject return config; } -PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume, size_t num_extruders) +PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegionConfig &default_region_config, const DynamicPrintConfig *layer_range_config, const ModelVolume &volume, size_t num_extruders) { PrintRegionConfig config = default_region_config; normalize_and_apply_config(config, volume.get_object()->config); + if (layer_range_config != nullptr) + normalize_and_apply_config(config, *layer_range_config); normalize_and_apply_config(config, volume.config); if (! volume.material_id().empty()) normalize_and_apply_config(config, volume.material()->config); @@ -1375,28 +1382,37 @@ void PrintObject::update_slicing_parameters() this->print()->config(), m_config, unscale(this->size(2)), this->object_extruders()); } -SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object, float object_max_z) +SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig& full_config, const ModelObject& model_object, float object_max_z) { - PrintConfig print_config; - PrintObjectConfig object_config; - PrintRegionConfig default_region_config; - print_config .apply(full_config, true); - object_config.apply(full_config, true); - default_region_config.apply(full_config, true); - size_t num_extruders = print_config.nozzle_diameter.size(); - object_config = object_config_from_model_object(object_config, model_object, num_extruders); + PrintConfig print_config; + PrintObjectConfig object_config; + PrintRegionConfig default_region_config; + print_config.apply(full_config, true); + object_config.apply(full_config, true); + default_region_config.apply(full_config, true); + size_t num_extruders = print_config.nozzle_diameter.size(); + object_config = object_config_from_model_object(object_config, model_object, num_extruders); - std::vector object_extruders; - for (const ModelVolume *model_volume : model_object.volumes) - if (model_volume->is_model_part()) - PrintRegion::collect_object_printing_extruders( - print_config, - region_config_from_model_volume(default_region_config, *model_volume, num_extruders), - object_extruders); + std::vector object_extruders; + for (const ModelVolume* model_volume : model_object.volumes) + if (model_volume->is_model_part()) { + PrintRegion::collect_object_printing_extruders( + print_config, + region_config_from_model_volume(default_region_config, nullptr, *model_volume, num_extruders), + object_extruders); + for (const std::pair &range_and_config : model_object.layer_config_ranges) + if (range_and_config.second.has("perimeter_extruder") || + range_and_config.second.has("infill_extruder") || + range_and_config.second.has("solid_infill_extruder")) + PrintRegion::collect_object_printing_extruders( + print_config, + region_config_from_model_volume(default_region_config, &range_and_config.second, *model_volume, num_extruders), + object_extruders); + } sort_remove_duplicates(object_extruders); if (object_max_z <= 0.f) - object_max_z = model_object.raw_bounding_box().size().z(); + object_max_z = (float)model_object.raw_bounding_box().size().z(); return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders); } @@ -1430,13 +1446,12 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c layer_height_profile.clear(); if (layer_height_profile.empty()) { - if (0) + if (0) // if (this->layer_height_profile.empty()) - layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_height_ranges, model_object.volumes); + layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes); else -// layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_height_ranges); - layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); // #ys_FIXME_experiment - updated = true; + layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); // #ys_FIXME_experiment + updated = true; } return updated; } @@ -1490,22 +1505,28 @@ void PrintObject::_slice(const std::vector &layer_height_profile) } // Count model parts and modifier meshes, check whether the model parts are of the same region. - int single_volume_region = -2; // not set yet + int all_volumes_single_region = -2; // not set yet + bool has_z_ranges = false; size_t num_volumes = 0; size_t num_modifiers = 0; - std::vector map_volume_to_region(this->model_object()->volumes.size()); for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) { - for (int volume_id : this->region_volumes[region_id]) { + int last_volume_id = -1; + for (const std::pair &volume_and_range : this->region_volumes[region_id]) { + const int volume_id = volume_and_range.second; const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; if (model_volume->is_model_part()) { - map_volume_to_region[volume_id] = region_id; - if (single_volume_region == -2) - // first model volume met - single_volume_region = region_id; - else if (single_volume_region != region_id) - // multiple volumes met and they are not equal - single_volume_region = -1; - ++ num_volumes; + if (last_volume_id == volume_id) { + has_z_ranges = true; + } else { + last_volume_id = volume_id; + if (all_volumes_single_region == -2) + // first model volume met + all_volumes_single_region = region_id; + else if (all_volumes_single_region != region_id) + // multiple volumes met and they are not equal + all_volumes_single_region = -1; + ++ num_volumes; + } } else if (model_volume->is_modifier()) ++ num_modifiers; } @@ -1515,13 +1536,13 @@ void PrintObject::_slice(const std::vector &layer_height_profile) // Slice all non-modifier volumes. bool clipped = false; bool upscaled = false; - if (! m_config.clip_multipart_objects.value || single_volume_region >= 0) { + if (! has_z_ranges && (! m_config.clip_multipart_objects.value || all_volumes_single_region >= 0)) { // Cheap path: Slice regions without mutual clipping. // The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region. for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id; // slicing in parallel - std::vector expolygons_by_layer = this->_slice_region(region_id, slice_zs, false); + std::vector expolygons_by_layer = this->slice_region(region_id, slice_zs); m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start"; for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) @@ -1542,15 +1563,29 @@ void PrintObject::_slice(const std::vector &layer_height_profile) }; std::vector sliced_volumes; sliced_volumes.reserve(num_volumes); - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) - for (int volume_id : this->region_volumes[region_id]) { + for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + const std::vector> &volumes_and_ranges = this->region_volumes[region_id]; + for (size_t i = 0; i < volumes_and_ranges.size(); ) { + int volume_id = volumes_and_ranges[i].second; const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; if (model_volume->is_model_part()) { BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id; + // Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume. + std::vector ranges; + ranges.emplace_back(volumes_and_ranges[i].first); + size_t j = i + 1; + for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) + if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON) + ranges.back().second = volumes_and_ranges[j].first.second; + else + ranges.emplace_back(volumes_and_ranges[j].first); // slicing in parallel - sliced_volumes.emplace_back(volume_id, map_volume_to_region[volume_id], this->_slice_volume(slice_zs, *model_volume)); - } + sliced_volumes.emplace_back(volume_id, (int)region_id, this->slice_volume(slice_zs, ranges, *model_volume)); + i = j; + } else + ++ i; } + } // Second clip the volumes in the order they are presented at the user interface. BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - start"; tbb::parallel_for( @@ -1604,7 +1639,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id; // slicing in parallel - std::vector expolygons_by_layer = this->_slice_region(region_id, slice_zs, true); + std::vector expolygons_by_layer = this->slice_modifiers(region_id, slice_zs); m_print->throw_if_canceled(); if (expolygons_by_layer.empty()) continue; @@ -1620,7 +1655,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) Layer *layer = m_layers[layer_id]; LayerRegion *layerm = layer->m_regions[region_id]; LayerRegion *other_layerm = layer->m_regions[other_region_id]; - if (layerm == nullptr || other_layerm == nullptr) + if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty()) continue; Polygons other_slices = to_polygons(other_layerm->slices); ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id])); @@ -1753,46 +1788,127 @@ end: BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - end"; } -std::vector PrintObject::_slice_region(size_t region_id, const std::vector &z, bool modifier) +// To be used only if there are no layer span specific configurations applied, which would lead to z ranges being generated for this region. +std::vector PrintObject::slice_region(size_t region_id, const std::vector &z) const { - std::vector volumes; + std::vector volumes; if (region_id < this->region_volumes.size()) { - for (int volume_id : this->region_volumes[region_id]) { - const ModelVolume *volume = this->model_object()->volumes[volume_id]; - if (modifier ? volume->is_modifier() : volume->is_model_part()) - volumes.emplace_back(volume); - } + for (const std::pair &volume_and_range : this->region_volumes[region_id]) { + const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second]; + if (volume->is_model_part()) + volumes.emplace_back(volume); + } } - return this->_slice_volumes(z, volumes); + return this->slice_volumes(z, volumes); } -std::vector PrintObject::slice_support_enforcers() const +// Z ranges are not applicable to modifier meshes, therefore a sinle volume will be found in volume_and_range at most once. +std::vector PrintObject::slice_modifiers(size_t region_id, const std::vector &slice_zs) const +{ + std::vector out; + if (region_id < this->region_volumes.size()) + { + std::vector> volume_ranges; + const std::vector> &volumes_and_ranges = this->region_volumes[region_id]; + volume_ranges.reserve(volumes_and_ranges.size()); + for (size_t i = 0; i < volumes_and_ranges.size(); ) { + int volume_id = volumes_and_ranges[i].second; + const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; + if (model_volume->is_modifier()) { + std::vector ranges; + ranges.emplace_back(volumes_and_ranges[i].first); + size_t j = i + 1; + for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) { + if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON) + ranges.back().second = volumes_and_ranges[j].first.second; + else + ranges.emplace_back(volumes_and_ranges[j].first); + } + volume_ranges.emplace_back(std::move(ranges)); + i = j; + } else + ++ i; + } + + if (! volume_ranges.empty()) + { + bool equal_ranges = true; + for (size_t i = 1; i < volume_ranges.size(); ++ i) { + assert(! volume_ranges[i].empty()); + if (volume_ranges.front() != volume_ranges[i]) { + equal_ranges = false; + break; + } + } + + if (equal_ranges && volume_ranges.front().size() == 1 && volume_ranges.front().front() == t_layer_height_range(0, DBL_MAX)) { + // No modifier in this region was split to layer spans. + std::vector volumes; + for (const std::pair &volume_and_range : this->region_volumes[region_id]) { + const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second]; + if (volume->is_modifier()) + volumes.emplace_back(volume); + } + out = this->slice_volumes(slice_zs, volumes); + } else { + // Some modifier in this region was split to layer spans. + std::vector merge; + for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { + const std::vector> &volumes_and_ranges = this->region_volumes[region_id]; + for (size_t i = 0; i < volumes_and_ranges.size(); ) { + int volume_id = volumes_and_ranges[i].second; + const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; + if (model_volume->is_modifier()) { + BOOST_LOG_TRIVIAL(debug) << "Slicing modifiers - volume " << volume_id; + // Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume. + std::vector ranges; + ranges.emplace_back(volumes_and_ranges[i].first); + size_t j = i + 1; + for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) + ranges.emplace_back(volumes_and_ranges[j].first); + // slicing in parallel + std::vector this_slices = this->slice_volume(slice_zs, ranges, *model_volume); + if (out.empty()) { + out = std::move(this_slices); + merge.assign(out.size(), false); + } else { + for (size_t i = 0; i < out.size(); ++ i) + if (! this_slices[i].empty()) + if (! out[i].empty()) { + append(out[i], this_slices[i]); + merge[i] = true; + } else + out[i] = std::move(this_slices[i]); + } + i = j; + } else + ++ i; + } + } + for (size_t i = 0; i < merge.size(); ++ i) + if (merge[i]) + out[i] = union_ex(out[i]); + } + } + } + + return out; +} + +std::vector PrintObject::slice_support_volumes(const ModelVolumeType &model_volume_type) const { std::vector volumes; for (const ModelVolume *volume : this->model_object()->volumes) - if (volume->is_support_enforcer()) + if (volume->type() == model_volume_type) volumes.emplace_back(volume); std::vector zs; zs.reserve(this->layers().size()); for (const Layer *l : this->layers()) zs.emplace_back((float)l->slice_z); - return this->_slice_volumes(zs, volumes); + return this->slice_volumes(zs, volumes); } -std::vector PrintObject::slice_support_blockers() const -{ - std::vector volumes; - for (const ModelVolume *volume : this->model_object()->volumes) - if (volume->is_support_blocker()) - volumes.emplace_back(volume); - std::vector zs; - zs.reserve(this->layers().size()); - for (const Layer *l : this->layers()) - zs.emplace_back((float)l->slice_z); - return this->_slice_volumes(zs, volumes); -} - -std::vector PrintObject::_slice_volumes(const std::vector &z, const std::vector &volumes) const +std::vector PrintObject::slice_volumes(const std::vector &z, const std::vector &volumes) const { std::vector layers; if (! volumes.empty()) { @@ -1829,34 +1945,71 @@ std::vector PrintObject::_slice_volumes(const std::vector &z, return layers; } -std::vector PrintObject::_slice_volume(const std::vector &z, const ModelVolume &volume) const +std::vector PrintObject::slice_volume(const std::vector &z, const ModelVolume &volume) const { std::vector layers; - // Compose mesh. - //FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them. - TriangleMesh mesh(volume.mesh()); - mesh.transform(volume.get_matrix(), true); - if (mesh.repaired) { - //FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it. - stl_check_facets_exact(&mesh.stl); + if (! z.empty()) { + // Compose mesh. + //FIXME better to split the mesh into separate shells, perform slicing over each shell separately and then to use a Boolean operation to merge them. + TriangleMesh mesh(volume.mesh()); + mesh.transform(volume.get_matrix(), true); + if (mesh.repaired) { + //FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it. + stl_check_facets_exact(&mesh.stl); + } + if (mesh.stl.stats.number_of_facets > 0) { + mesh.transform(m_trafo, true); + // apply XY shift + mesh.translate(- unscale(m_copies_shift(0)), - unscale(m_copies_shift(1)), 0); + // perform actual slicing + TriangleMeshSlicer mslicer; + const Print *print = this->print(); + auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();}); + // TriangleMeshSlicer needs the shared vertices. + mesh.require_shared_vertices(); + mslicer.init(&mesh, callback); + mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback); + m_print->throw_if_canceled(); + } } - if (mesh.stl.stats.number_of_facets > 0) { - mesh.transform(m_trafo, true); - // apply XY shift - mesh.translate(- unscale(m_copies_shift(0)), - unscale(m_copies_shift(1)), 0); - // perform actual slicing - TriangleMeshSlicer mslicer; - const Print *print = this->print(); - auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();}); - // TriangleMeshSlicer needs the shared vertices. - mesh.require_shared_vertices(); - mslicer.init(&mesh, callback); - mslicer.slice(z, float(m_config.slice_closing_radius.value), &layers, callback); - m_print->throw_if_canceled(); - } return layers; } +// Filter the zs not inside the ranges. The ranges are closed at the botton and open at the top, they are sorted lexicographically and non overlapping. +std::vector PrintObject::slice_volume(const std::vector &z, const std::vector &ranges, const ModelVolume &volume) const +{ + std::vector out; + if (! z.empty() && ! ranges.empty()) { + if (ranges.size() == 1 && z.front() >= ranges.front().first && z.back() < ranges.front().second) { + // All layers fit into a single range. + out = this->slice_volume(z, volume); + } else { + std::vector z_filtered; + std::vector> n_filtered; + z_filtered.reserve(z.size()); + n_filtered.reserve(2 * ranges.size()); + size_t i = 0; + for (const t_layer_height_range &range : ranges) { + for (; i < z.size() && z[i] < range.first; ++ i) ; + size_t first = i; + for (; i < z.size() && z[i] < range.second; ++ i) + z_filtered.emplace_back(z[i]); + if (i > first) + n_filtered.emplace_back(std::make_pair(first, i)); + } + if (! n_filtered.empty()) { + std::vector layers = this->slice_volume(z_filtered, volume); + out.assign(z.size(), ExPolygons()); + i = 0; + for (const std::pair &span : n_filtered) + for (size_t j = span.first; j < span.second; ++ j) + out[j] = std::move(layers[i ++]); + } + } + } + return out; +} + std::string PrintObject::_fix_slicing_errors() { // Collect layers with slicing errors. @@ -2120,7 +2273,7 @@ void PrintObject::clip_fill_surfaces() //Should the pw not be half of the current value? float pw = FLT_MAX; for (const LayerRegion *layerm : layer->m_regions) - pw = std::min(pw, layerm->flow(frPerimeter).scaled_width()); + pw = std::min(pw, (float)layerm->flow(frPerimeter).scaled_width()); // Append such thick perimeters to the areas that need support polygons_append(overhangs, offset2(perimeters, -pw, +pw)); } diff --git a/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp index 1c6476eae..6b0e3f895 100644 --- a/src/libslic3r/Slicing.cpp +++ b/src/libslic3r/Slicing.cpp @@ -153,29 +153,33 @@ SlicingParameters SlicingParameters::create_from_config( return params; } -// Convert layer_height_ranges to layer_height_profile. Both are referenced to z=0, meaning the raft layers are not accounted for +std::vector> layer_height_ranges(const t_layer_config_ranges &config_ranges) +{ + std::vector> out; + out.reserve(config_ranges.size()); + for (const auto &kvp : config_ranges) + out.emplace_back(kvp.first, kvp.second.option("layer_height")->getFloat()); + return out; +} + +// Convert layer_config_ranges to layer_height_profile. Both are referenced to z=0, meaning the raft layers are not accounted for // in the height profile and the printed object may be lifted by the raft thickness at the time of the G-code generation. std::vector layer_height_profile_from_ranges( const SlicingParameters &slicing_params, -// const t_layer_height_ranges &layer_height_ranges) const t_layer_config_ranges &layer_config_ranges) // #ys_FIXME_experiment { // 1) If there are any height ranges, trim one by the other to make them non-overlapping. Insert the 1st layer if fixed. std::vector> ranges_non_overlapping; -// ranges_non_overlapping.reserve(layer_height_ranges.size() * 4); ranges_non_overlapping.reserve(layer_config_ranges.size() * 4); // #ys_FIXME_experiment if (slicing_params.first_object_layer_height_fixed()) ranges_non_overlapping.push_back(std::pair( t_layer_height_range(0., slicing_params.first_object_layer_height), slicing_params.first_object_layer_height)); // The height ranges are sorted lexicographically by low / high layer boundaries. -// for (t_layer_height_ranges::const_iterator it_range = layer_height_ranges.begin(); it_range != layer_height_ranges.end(); ++ it_range) { - for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); - it_range != layer_config_ranges.end(); ++ it_range) { // #ys_FIXME_experiment + for (t_layer_config_ranges::const_iterator it_range = layer_config_ranges.begin(); it_range != layer_config_ranges.end(); ++ it_range) { coordf_t lo = it_range->first.first; coordf_t hi = std::min(it_range->first.second, slicing_params.object_print_z_height()); -// coordf_t height = it_range->second; - coordf_t height = it_range->second.option("layer_height")->getFloat(); // #ys_FIXME_experiment + coordf_t height = it_range->second.option("layer_height")->getFloat(); if (! ranges_non_overlapping.empty()) // Trim current low with the last high. lo = std::max(lo, ranges_non_overlapping.back().first.second); @@ -224,7 +228,7 @@ std::vector layer_height_profile_from_ranges( // Fill layer_height_profile by heights ensuring a prescribed maximum cusp height. std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, - const t_layer_height_ranges &layer_height_ranges, + const t_layer_config_ranges & /* layer_config_ranges */, const ModelVolumePtrs &volumes) { // 1) Initialize the SlicingAdaptive class with the object meshes. diff --git a/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp index ea5413e9c..7ebb3f329 100644 --- a/src/libslic3r/Slicing.hpp +++ b/src/libslic3r/Slicing.hpp @@ -130,17 +130,17 @@ inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters } typedef std::pair t_layer_height_range; -typedef std::map t_layer_height_ranges; typedef std::map t_layer_config_ranges; +extern std::vector> layer_height_ranges(const t_layer_config_ranges &config_ranges); + extern std::vector layer_height_profile_from_ranges( const SlicingParameters &slicing_params, -// const t_layer_height_ranges &layer_height_ranges); const t_layer_config_ranges &layer_config_ranges); extern std::vector layer_height_profile_adaptive( const SlicingParameters &slicing_params, - const t_layer_height_ranges &layer_height_ranges, + const t_layer_config_ranges &layer_config_ranges, const ModelVolumePtrs &volumes); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index fde35ca1e..0ad4f816a 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -829,7 +829,7 @@ namespace SupportMaterialInternal { assert(expansion_scaled >= 0.f); for (const ExtrusionPath &ep : loop.paths) if (ep.role() == erOverhangPerimeter && ! ep.polyline.empty()) { - float exp = 0.5f * scale_(ep.width) + expansion_scaled; + float exp = 0.5f * (float)scale_(ep.width) + expansion_scaled; if (ep.is_closed()) { if (ep.size() >= 3) { // This is a complete loop. @@ -2214,7 +2214,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf // Expand the bases of the support columns in the 1st layer. columns_base->polygons = diff( offset(columns_base->polygons, inflate_factor_1st_layer), - offset(m_object->layers().front()->slices.expolygons, scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); + offset(m_object->layers().front()->slices.expolygons, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS)); if (contacts != nullptr) columns_base->polygons = diff(columns_base->polygons, interface_polygons); } @@ -3226,7 +3226,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( // TODO: use brim ordering algorithm Polygons to_infill_polygons = to_polygons(to_infill); // TODO: use offset2_ex() - to_infill = offset_ex(to_infill, - 0.4 * float(flow.scaled_spacing())); + to_infill = offset_ex(to_infill, - 0.4f * float(flow.scaled_spacing())); extrusion_entities_append_paths( base_layer.extrusions, to_polylines(std::move(to_infill_polygons)), diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 8392e534a..d9bb67f57 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -600,12 +600,12 @@ void Bed3D::render_prusa_shader(bool transparent) const if (position_id != -1) { glsafe(::glEnableVertexAttribArray(position_id)); - glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)m_triangles.get_position_offset())); + glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(intptr_t)m_triangles.get_position_offset())); } if (tex_coords_id != -1) { glsafe(::glEnableVertexAttribArray(tex_coords_id)); - glsafe(::glVertexAttribPointer(tex_coords_id, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)m_triangles.get_tex_coords_offset())); + glsafe(::glVertexAttribPointer(tex_coords_id, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)(intptr_t)m_triangles.get_tex_coords_offset())); } glsafe(::glDrawArrays(GL_TRIANGLES, 0, (GLsizei)m_triangles.get_vertices_count())); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e8973f6e3..84a4db965 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1922,9 +1922,6 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode } object->ensure_on_bed(); - - // print.auto_assign_extruders(object); - // print.add_model_object(object); } #ifdef AUTOPLACEMENT_ON_LOAD diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 402b4248f..e681b8af1 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1129,7 +1129,6 @@ void Selection::copy_to_clipboard() dst_object->config = src_object->config; dst_object->sla_support_points = src_object->sla_support_points; dst_object->sla_points_status = src_object->sla_points_status; -// dst_object->layer_height_ranges = src_object->layer_height_ranges; dst_object->layer_config_ranges = src_object->layer_config_ranges; // #ys_FIXME_experiment dst_object->layer_height_profile = src_object->layer_height_profile; dst_object->origin_translation = src_object->origin_translation; diff --git a/t/print.t b/t/print.t index be2db3431..e76d226af 100644 --- a/t/print.t +++ b/t/print.t @@ -1,4 +1,4 @@ -use Test::More tests => 6; +use Test::More tests => 2; use strict; use warnings; @@ -31,6 +31,8 @@ use Slic3r::Test; ok abs(unscale($center->[Y]) - $print_center->[Y]) < 0.005, 'print is centered around print_center (Y)'; } +# This is really testing a path, which is no more used by the slicer, just by the test cases. +if (0) { # this represents the aggregate config from presets my $config = Slic3r::Config::new_from_defaults; @@ -40,7 +42,7 @@ use Slic3r::Test; # user sets a per-region option $print->print->objects->[0]->model_object->config->set('fill_density', 100); - $print->print->reload_object(0); +# $print->print->reload_object(0); is $print->print->regions->[0]->config->fill_density, 100, 'region config inherits model object config'; # user exports G-code, thus the default config is reapplied @@ -51,7 +53,7 @@ use Slic3r::Test; # user assigns object extruders $print->print->objects->[0]->model_object->config->set('extruder', 3); $print->print->objects->[0]->model_object->config->set('perimeter_extruder', 2); - $print->print->reload_object(0); +# $print->print->reload_object(0); is $print->print->regions->[0]->config->infill_extruder, 3, 'extruder setting is correctly expanded'; is $print->print->regions->[0]->config->perimeter_extruder, 2, 'extruder setting does not override explicitely specified extruders'; diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index c35f967f8..70313ff5e 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -100,7 +100,6 @@ _constant() %code%{ RETVAL = const_cast(&THIS->objects()); %}; Ref get_object(int idx) %code%{ RETVAL = THIS->objects()[idx]; %}; - void reload_object(int idx); size_t object_count() %code%{ RETVAL = THIS->objects().size(); %}; @@ -141,7 +140,6 @@ _constant() } %}; - void add_model_object(ModelObject* model_object, int idx = -1); bool apply_config_perl_tests_only(DynamicPrintConfig* config) %code%{ RETVAL = THIS->apply_config_perl_tests_only(*config); %}; bool has_infinite_skirt(); From 8bf6e69851657bbd9242d54d8e08f706fcdb1874 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Jun 2019 16:28:37 +0200 Subject: [PATCH 37/83] Removed the layer_height_ranges from the Perl bindings and unit tests. --- xs/t/19_model.t | 8 ++++---- xs/xsp/Model.xsp | 5 ----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/xs/t/19_model.t b/xs/t/19_model.t index d6f6d97a1..48a000e46 100644 --- a/xs/t/19_model.t +++ b/xs/t/19_model.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 4; +use Test::More tests => 3; { my $model = Slic3r::Model->new; @@ -14,9 +14,9 @@ use Test::More tests => 4; $object->origin_translation->translate(10,0,0); is_deeply \@{$object->origin_translation}, [10,0,0], 'origin_translation is modified by ref'; - my $lhr = [ [ 5, 10, 0.1 ] ]; - $object->set_layer_height_ranges($lhr); - is_deeply $object->layer_height_ranges, $lhr, 'layer_height_ranges roundtrip'; +# my $lhr = [ [ 5, 10, 0.1 ] ]; +# $object->set_layer_height_ranges($lhr); +# is_deeply $object->layer_height_ranges, $lhr, 'layer_height_ranges roundtrip'; } __END__ diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 6a2cc6080..af4cdce06 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -206,11 +206,6 @@ ModelMaterial::attributes() Ref model() %code%{ RETVAL = THIS->get_model(); %}; - t_layer_height_ranges layer_height_ranges() - %code%{ RETVAL = THIS->layer_height_ranges; %}; - void set_layer_height_ranges(t_layer_height_ranges ranges) - %code%{ THIS->layer_height_ranges = ranges; %}; - Ref origin_translation() %code%{ RETVAL = &THIS->origin_translation; %}; void set_origin_translation(Vec3d* point) From ac6969c992b8b260f804790edc10d98412ea8060 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Jun 2019 20:23:05 +0200 Subject: [PATCH 38/83] Reworked the Perl unit / integration tests to use the same Print interface that the application is using. Old interface used just for the integration tests was removed. --- lib/Slic3r.pm | 1 - lib/Slic3r/Print/Simple.pm | 104 -------------------- lib/Slic3r/Test.pm | 82 ++++++++-------- src/libslic3r/Model.hpp | 4 +- src/libslic3r/Print.cpp | 194 +------------------------------------ src/libslic3r/Print.hpp | 4 - t/combineinfill.t | 2 +- t/print.t | 27 +++--- t/skirt_brim.t | 4 +- xs/xsp/Config.xsp | 2 +- xs/xsp/Model.xsp | 1 + xs/xsp/Print.xsp | 6 +- 12 files changed, 72 insertions(+), 359 deletions(-) delete mode 100644 lib/Slic3r/Print/Simple.pm diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 44100db8c..94f0b5658 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -50,7 +50,6 @@ use Slic3r::Point; use Slic3r::Polygon; use Slic3r::Polyline; use Slic3r::Print::Object; -use Slic3r::Print::Simple; use Slic3r::Surface; our $build = eval "use Slic3r::Build; 1"; diff --git a/lib/Slic3r/Print/Simple.pm b/lib/Slic3r/Print/Simple.pm deleted file mode 100644 index 2ab68f4d3..000000000 --- a/lib/Slic3r/Print/Simple.pm +++ /dev/null @@ -1,104 +0,0 @@ -# A simple wrapper to quickly print a single model without a GUI. -# Used by the command line slic3r.pl, by command line utilities pdf-slic3s.pl and view-toolpaths.pl, -# and by the quick slice menu of the Slic3r GUI. -# -# It creates and owns an instance of Slic3r::Print to perform the slicing -# and it accepts an instance of Slic3r::Model from the outside. - -package Slic3r::Print::Simple; -use Moo; - -use Slic3r::Geometry qw(X Y); - -has '_print' => ( - is => 'ro', - default => sub { Slic3r::Print->new }, - handles => [qw(apply_config_perl_tests_only extruders output_filepath - total_used_filament total_extruded_volume - placeholder_parser process)], -); - -has 'duplicate' => ( - is => 'rw', - default => sub { 1 }, -); - -has 'scale' => ( - is => 'rw', - default => sub { 1 }, -); - -has 'rotate' => ( - is => 'rw', - default => sub { 0 }, -); - -has 'duplicate_grid' => ( - is => 'rw', - default => sub { [1,1] }, -); - -has 'print_center' => ( - is => 'rw', - default => sub { Slic3r::Pointf->new(100,100) }, -); - -has 'dont_arrange' => ( - is => 'rw', - default => sub { 0 }, -); - -has 'output_file' => ( - is => 'rw', -); - -sub set_model { - # $model is of type Slic3r::Model - my ($self, $model) = @_; - - # make method idempotent so that the object is reusable - $self->_print->clear_objects; - - # make sure all objects have at least one defined instance - my $need_arrange = $model->add_default_instances && ! $self->dont_arrange; - - # apply scaling and rotation supplied from command line if any - foreach my $instance (map @{$_->instances}, @{$model->objects}) { - $instance->set_scaling_factor($instance->scaling_factor * $self->scale); - $instance->set_rotation($instance->rotation + $self->rotate); - } - - if ($self->duplicate_grid->[X] > 1 || $self->duplicate_grid->[Y] > 1) { - $model->duplicate_objects_grid($self->duplicate_grid->[X], $self->duplicate_grid->[Y], $self->_print->config->duplicate_distance); - } elsif ($need_arrange) { - $model->duplicate_objects($self->duplicate, $self->_print->config->min_object_distance); - } elsif ($self->duplicate > 1) { - # if all input objects have defined position(s) apply duplication to the whole model - $model->duplicate($self->duplicate, $self->_print->config->min_object_distance); - } - $_->translate(0,0,-$_->bounding_box->z_min) for @{$model->objects}; - $model->center_instances_around_point($self->print_center) if (! $self->dont_arrange); - - foreach my $model_object (@{$model->objects}) { - $self->_print->auto_assign_extruders($model_object); - $self->_print->add_model_object($model_object); - } -} - -sub export_gcode { - my ($self) = @_; - $self->_print->validate; - $self->_print->export_gcode($self->output_file // ''); -} - -sub export_png { - my ($self) = @_; - - $self->_before_export; - - $self->_print->export_png(output_file => $self->output_file); - - $self->_after_export; -} - -1; diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index d1b99e48c..570bca41b 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -146,60 +146,66 @@ sub mesh { } sub model { - my ($model_name, %params) = @_; + my ($model_names, %params) = @_; + $model_names = [ $model_names ] if ! ref($model_names); - my $input_file = "${model_name}.stl"; - my $mesh = mesh($model_name, %params); -# $mesh->write_ascii("out/$input_file"); - my $model = Slic3r::Model->new; - my $object = $model->add_object(input_file => $input_file); - $model->set_material($model_name); - $object->add_volume(mesh => $mesh, material_id => $model_name); - $object->add_instance( - offset => Slic3r::Pointf->new(0,0), - # 3D full transform - rotation => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0), - scaling_factor => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1), - # old transform -# rotation => $params{rotation} // 0, -# scaling_factor => $params{scale} // 1, - ); + + for my $model_name (@$model_names) { + my $input_file = "${model_name}.stl"; + my $mesh = mesh($model_name, %params); + # $mesh->write_ascii("out/$input_file"); + + my $object = $model->add_object(input_file => $input_file); + $model->set_material($model_name); + $object->add_volume(mesh => $mesh, material_id => $model_name); + $object->add_instance( + offset => Slic3r::Pointf->new(0,0), + # 3D full transform + rotation => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0), + scaling_factor => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1), + # old transform + # rotation => $params{rotation} // 0, + # scaling_factor => $params{scale} // 1, + ); + } return $model; } sub init_print { my ($models, %params) = @_; + my $model; + if (ref($models) eq 'ARRAY') { + $model = model($models, %params); + } elsif (ref($models)) { + $model = $models; + } else { + $model = model([$models], %params); + } my $config = Slic3r::Config->new; $config->apply($params{config}) if $params{config}; $config->set('gcode_comments', 1) if $ENV{SLIC3R_TESTS_GCODE}; my $print = Slic3r::Print->new; - $print->apply_config_perl_tests_only($config); - - $models = [$models] if ref($models) ne 'ARRAY'; - $models = [ map { ref($_) ? $_ : model($_, %params) } @$models ]; - for my $model (@$models) { - die "Unknown model in test" if !defined $model; - if (defined $params{duplicate} && $params{duplicate} > 1) { - $model->duplicate($params{duplicate} // 1, $print->config->min_object_distance); - } - $model->arrange_objects($print->config->min_object_distance); - $model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100)); - foreach my $model_object (@{$model->objects}) { - $print->auto_assign_extruders($model_object); - $print->add_model_object($model_object); - } + die "Unknown model in test" if !defined $model; + if (defined $params{duplicate} && $params{duplicate} > 1) { + $model->duplicate($params{duplicate} // 1, $config->min_object_distance); } - # Call apply_config_perl_tests_only one more time, so that the layer height profiles are updated over all PrintObjects. - $print->apply_config_perl_tests_only($config); + $model->arrange_objects($config->min_object_distance); + $model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100)); + foreach my $model_object (@{$model->objects}) { + $model_object->ensure_on_bed; + $print->auto_assign_extruders($model_object); + } + + $print->apply($model, $config); $print->validate; # We return a proxy object in order to keep $models alive as required by the Print API. return Slic3r::Test::Print->new( - print => $print, - models => $models, + print => $print, + model => $model, ); } @@ -250,7 +256,7 @@ sub add_facet { package Slic3r::Test::Print; use Moo; -has 'print' => (is => 'ro', required => 1, handles => [qw(process apply_config_perl_tests_only)]); -has 'models' => (is => 'ro', required => 1); +has 'print' => (is => 'ro', required => 1, handles => [qw(process apply)]); +has 'model' => (is => 'ro', required => 1); 1; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index c1850df98..bac8ae507 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -597,8 +597,8 @@ public: Model() {} ~Model() { this->clear_objects(); this->clear_materials(); } - /* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */ - /* (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). */ + // To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" + // (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). Model(const Model &rhs) : ModelBase(-1) { this->assign_copy(rhs); } explicit Model(Model &&rhs) : ModelBase(-1) { this->assign_copy(std::move(rhs)); } Model& operator=(const Model &rhs) { this->assign_copy(rhs); return *this; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 5e4f25334..227123f72 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -328,198 +328,6 @@ double Print::max_allowed_layer_height() const return nozzle_diameter_max; } -// Caller is responsible for supplying models whose objects don't collide -// and have explicit instance positions. -void Print::add_model_object_perl_tests_only(ModelObject* model_object, int idx) -{ - tbb::mutex::scoped_lock lock(this->state_mutex()); - // Add a copy of this ModelObject to this Print. - m_model.objects.emplace_back(ModelObject::new_copy(*model_object)); - m_model.objects.back()->set_model(&m_model); - // Initialize a new print object and store it at the given position. - PrintObject *object = new PrintObject(this, model_object, true); - if (idx != -1) { - delete m_objects[idx]; - m_objects[idx] = object; - } else - m_objects.emplace_back(object); - // Invalidate all print steps. - this->invalidate_all_steps(); - - // Set the transformation matrix without translation from the first instance. - if (! model_object->instances.empty()) { - // Trafo and bounding box, both in world coordinate system. - Transform3d trafo = model_object->instances.front()->get_matrix(); - BoundingBoxf3 bbox = model_object->instance_bounding_box(0); - // Now shift the object up to align it with the print bed. - trafo.data()[14] -= bbox.min(2); - // and reset the XY translation. - trafo.data()[12] = 0; - trafo.data()[13] = 0; - object->set_trafo(trafo); - } - - int volume_id = 0; - for (const ModelVolume *volume : model_object->volumes) { - if (! volume->is_model_part() && ! volume->is_modifier()) - continue; - // Get the config applied to this volume. - PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, *volume, 99999); - // Find an existing print region with the same config. - int region_id = -1; - for (int i = 0; i < (int)m_regions.size(); ++ i) - if (config.equals(m_regions[i]->config())) { - region_id = i; - break; - } - // If no region exists with the same config, create a new one. - if (region_id == -1) { - region_id = (int)m_regions.size(); - this->add_region(config); - } - // Assign volume to a region. - object->add_region_volume((unsigned int)region_id, volume_id, t_layer_height_range(0, DBL_MAX)); - ++ volume_id; - } - - // Apply config to print object. - object->config_apply(this->default_object_config()); - { - //normalize_and_apply_config(object->config(), model_object->config); - DynamicPrintConfig src_normalized(model_object->config); - src_normalized.normalize(); - object->config_apply(src_normalized, true); - } -} - -// This function is only called through the Perl-C++ binding from the unit tests, should be -// removed when unit tests are rewritten to C++. -bool Print::apply_config_perl_tests_only(DynamicPrintConfig config) -{ - tbb::mutex::scoped_lock lock(this->state_mutex()); - - - // Perl unit tests were failing in case the preset was not normalized (e.g. https://github.com/prusa3d/PrusaSlicer/issues/2288 was caused - // by too short max_layer_height vector. Calling the necessary function Preset::normalize(...) is not currently possible because there is no - // access to preset. This should be solved when the unit tests are rewritten to C++. For now we just copy-pasted code from Preset.cpp - // to make sure the unit tests pass (functions set_num_extruders and nozzle_options()). - auto *nozzle_diameter = dynamic_cast(config.option("nozzle_diameter", true)); - assert(nozzle_diameter != nullptr); - const auto &defaults = FullPrintConfig::defaults(); - for (const std::string &key : { "nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset", - "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", - "retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe", - "retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour" }) - { - auto *opt = config.option(key, true); - assert(opt != nullptr); - assert(opt->is_vector()); - unsigned int num_extruders = (unsigned int)nozzle_diameter->values.size(); - static_cast(opt)->resize(num_extruders, defaults.option(key)); - } - - // we get a copy of the config object so we can modify it safely - config.normalize(); - - // apply variables to placeholder parser - this->placeholder_parser().apply_config(config); - - // handle changes to print config - t_config_option_keys print_diff = m_config.diff(config); - m_config.apply_only(config, print_diff, true); - bool invalidated = this->invalidate_state_by_config_options(print_diff); - - // handle changes to object config defaults - m_default_object_config.apply(config, true); - for (PrintObject *object : m_objects) { - // we don't assume that config contains a full ObjectConfig, - // so we base it on the current print-wise default - PrintObjectConfig new_config = this->default_object_config(); - // we override the new config with object-specific options - normalize_and_apply_config(new_config, object->model_object()->config); - // check whether the new config is different from the current one - t_config_option_keys diff = object->config().diff(new_config); - object->config_apply_only(new_config, diff, true); - invalidated |= object->invalidate_state_by_config_options(diff); - } - - // handle changes to regions config defaults - m_default_region_config.apply(config, true); - - // All regions now have distinct settings. - // Check whether applying the new region config defaults we'd get different regions. - bool rearrange_regions = false; - { - // Collect the already visited region configs into other_region_configs, - // so one may check for duplicates. - std::vector other_region_configs; - for (size_t region_id = 0; region_id < m_regions.size(); ++ region_id) { - PrintRegion ®ion = *m_regions[region_id]; - PrintRegionConfig this_region_config; - bool this_region_config_set = false; - for (PrintObject *object : m_objects) { - if (region_id < object->region_volumes.size()) { - for (const std::pair &volume_and_range : object->region_volumes[region_id]) { - const ModelVolume &volume = *object->model_object()->volumes[volume_and_range.second]; - if (this_region_config_set) { - // If the new config for this volume differs from the other - // volume configs currently associated to this region, it means - // the region subdivision does not make sense anymore. - if (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, volume, 99999))) { - rearrange_regions = true; - goto exit_for_rearrange_regions; - } - } else { - this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, volume, 99999); - this_region_config_set = true; - } - for (const PrintRegionConfig &cfg : other_region_configs) { - // If the new config for this volume equals any of the other - // volume configs that are not currently associated to this - // region, it means the region subdivision does not make - // sense anymore. - if (cfg.equals(this_region_config)) { - rearrange_regions = true; - goto exit_for_rearrange_regions; - } - } - } - } - } - if (this_region_config_set) { - t_config_option_keys diff = region.config().diff(this_region_config); - if (! diff.empty()) { - region.config_apply_only(this_region_config, diff, false); - for (PrintObject *object : m_objects) - if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty()) - invalidated |= object->invalidate_state_by_config_options(diff); - } - other_region_configs.emplace_back(std::move(this_region_config)); - } - } - } - -exit_for_rearrange_regions: - - if (rearrange_regions) { - // The current subdivision of regions does not make sense anymore. - // We need to remove all objects and re-add them. - ModelObjectPtrs model_objects; - model_objects.reserve(m_objects.size()); - for (PrintObject *object : m_objects) - model_objects.push_back(object->model_object()); - this->clear(); - for (ModelObject *mo : model_objects) - this->add_model_object_perl_tests_only(mo); - invalidated = true; - } - - for (PrintObject *object : m_objects) - object->update_slicing_parameters(); - - return invalidated; -} - // Add or remove support modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new // in the exact order and with the same IDs. // It is expected, that the model_object_dst already contains the non-support volumes of model_object_new in the correct order. @@ -1247,7 +1055,7 @@ std::string Print::validate() const Geometry::assemble_transform(Vec3d::Zero(), rotation, model_instance0->get_scaling_factor(), model_instance0->get_mirror())), float(scale_(0.5 * m_config.extruder_clearance_radius.value)), jtRound, float(scale_(0.1))).front(); // Now we check that no instance of convex_hull intersects any of the previously checked object instances. - for (const Point © : print_object->m_copies) { + for (const Point © : print_object->copies()) { Polygon convex_hull = convex_hull0; convex_hull.translate(copy); if (! intersection(convex_hulls_other, convex_hull).empty()) diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index c024a3ad2..c3fa5e062 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -294,10 +294,6 @@ public: ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override; - // The following three methods are used by the Perl tests only. Get rid of them! - void add_model_object_perl_tests_only(ModelObject* model_object, int idx = -1); - bool apply_config_perl_tests_only(DynamicPrintConfig config); - void process() override; // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file. // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r). diff --git a/t/combineinfill.t b/t/combineinfill.t index 8aa0ff5e3..282bf467a 100644 --- a/t/combineinfill.t +++ b/t/combineinfill.t @@ -89,7 +89,7 @@ plan tests => 8; # we disable combination after infill has been generated $config->set('infill_every_layers', 1); - $print->apply_config_perl_tests_only($config); + $print->apply($print->print->model->clone, $config); $print->process; ok !(defined first { @{$_->get_region(0)->fill_surfaces} == 0 } diff --git a/t/print.t b/t/print.t index e76d226af..2144e80c1 100644 --- a/t/print.t +++ b/t/print.t @@ -1,4 +1,4 @@ -use Test::More tests => 2; +use Test::More tests => 6; use strict; use warnings; @@ -31,30 +31,33 @@ use Slic3r::Test; ok abs(unscale($center->[Y]) - $print_center->[Y]) < 0.005, 'print is centered around print_center (Y)'; } -# This is really testing a path, which is no more used by the slicer, just by the test cases. -if (0) { # this represents the aggregate config from presets my $config = Slic3r::Config::new_from_defaults; + # Define 4 extruders. + $config->set('nozzle_diameter', [0.4, 0.4, 0.4, 0.4]); # user adds one object to the plater my $print = Slic3r::Test::init_print(my $model = Slic3r::Test::model('20mm_cube'), config => $config); # user sets a per-region option - $print->print->objects->[0]->model_object->config->set('fill_density', 100); -# $print->print->reload_object(0); + my $model2 = $model->clone; + $model2->get_object(0)->config->set('fill_density', 100); + $print->apply($model2, $config); + is $print->print->regions->[0]->config->fill_density, 100, 'region config inherits model object config'; # user exports G-code, thus the default config is reapplied - $print->print->apply_config_perl_tests_only($config); - - is $print->print->regions->[0]->config->fill_density, 100, 'apply_config() does not override per-object settings'; + $model2->get_object(0)->config->erase('fill_density'); + $print->apply($model2, $config); + + is $print->print->regions->[0]->config->fill_density, 20, 'region config is resetted'; # user assigns object extruders - $print->print->objects->[0]->model_object->config->set('extruder', 3); - $print->print->objects->[0]->model_object->config->set('perimeter_extruder', 2); -# $print->print->reload_object(0); - + $model2->get_object(0)->config->set('extruder', 3); + $model2->get_object(0)->config->set('perimeter_extruder', 2); + $print->apply($model2, $config); + is $print->print->regions->[0]->config->infill_extruder, 3, 'extruder setting is correctly expanded'; is $print->print->regions->[0]->config->perimeter_extruder, 2, 'extruder setting does not override explicitely specified extruders'; } diff --git a/t/skirt_brim.t b/t/skirt_brim.t index b05435784..beb3c94c5 100644 --- a/t/skirt_brim.t +++ b/t/skirt_brim.t @@ -91,6 +91,8 @@ use Slic3r::Test; { my $config = Slic3r::Config::new_from_defaults; + # Define 4 extruders. + $config->set('nozzle_diameter', [0.4, 0.4, 0.4, 0.4]); $config->set('layer_height', 0.4); $config->set('first_layer_height', 0.4); $config->set('skirts', 1); @@ -106,7 +108,7 @@ use Slic3r::Test; # we enable support material after skirt has been generated $config->set('support_material', 1); - $print->apply_config_perl_tests_only($config); + $print->apply($print->print->model->clone, $config); my $skirt_length = 0; my @extrusion_points = (); diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index 4d48a2c6f..e193a2321 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -49,7 +49,7 @@ void erase(t_config_option_key opt_key); void normalize(); %name{setenv} void setenv_(); - double min_object_distance() %code{% RETVAL = PrintConfig::min_object_distance(THIS); %}; + double min_object_distance() %code{% PrintConfig cfg; cfg.apply(*THIS, true); RETVAL = cfg.min_object_distance(); %}; static DynamicPrintConfig* load(char *path) %code%{ auto config = new DynamicPrintConfig(); diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index af4cdce06..35b1c01ce 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -211,6 +211,7 @@ ModelMaterial::attributes() void set_origin_translation(Vec3d* point) %code%{ THIS->origin_translation = *point; %}; + void ensure_on_bed(); bool needed_repair() const; int materials_count() const; int facets_count(); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 70313ff5e..df5f48587 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -70,6 +70,8 @@ _constant() Print(); ~Print(); + Ref model() + %code%{ RETVAL = const_cast(&THIS->model()); %}; Ref config() %code%{ RETVAL = const_cast(static_cast(&THIS->config())); %}; Ref placeholder_parser() @@ -140,8 +142,8 @@ _constant() } %}; - bool apply_config_perl_tests_only(DynamicPrintConfig* config) - %code%{ RETVAL = THIS->apply_config_perl_tests_only(*config); %}; + bool apply(Model *model, DynamicPrintConfig* config) + %code%{ RETVAL = THIS->apply(*model, *config); %}; bool has_infinite_skirt(); std::vector extruders() const; int validate() %code%{ From b7a949a53e1bb6b1694b1ce2e6d747760fb371b4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Jun 2019 20:40:17 +0200 Subject: [PATCH 39/83] Fix for C++11 --- src/libslic3r/Print.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 227123f72..8590a1a0d 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -572,8 +572,8 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON); return (it == m_ranges.end()) ? nullptr : it->second; } - auto begin() const { return m_ranges.cbegin(); } - auto end() const { return m_ranges.cend(); } + std::vector>::const_iterator begin() const { return m_ranges.cbegin(); } + std::vector>::const_iterator end() const { return m_ranges.cend(); } private: std::vector> m_ranges; }; From 7de5a42df3d59b928d3cfb1213278bd1cfbb8d59 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Jun 2019 21:07:26 +0200 Subject: [PATCH 40/83] Fixed compilation on clang / OSX (missing float.h) --- src/libslic3r/Print.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 8590a1a0d..60bd18a59 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -12,6 +12,8 @@ //#include "PrintExport.hpp" +#include + #include #include #include From c198d826af9ead36c511b63b88363335e72487e0 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 24 Jun 2019 15:43:16 +0200 Subject: [PATCH 41/83] Setting min_z bigger than max_z cause an increase of the max_z --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 12c1022ce..1426ccf02 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -82,13 +82,14 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) auto editor = new LayerRangeEditor(m_parent, double_to_string(range.first), etMinZ, set_focus_fn, [range, set_focus, this](coordf_t min_z, bool enter_pressed) { - if (fabs(min_z - range.first) < EPSILON || min_z > range.second) { + if (fabs(min_z - range.first) < EPSILON) { m_selection_type = etUndef; return false; } // data for next focusing - const t_layer_height_range& new_range = { min_z, range.second }; + coordf_t max_z = min_z < range.second ? range.second : min_z + 0.5; + const t_layer_height_range& new_range = { min_z, max_z/*range.second*/ }; set_focus(new_range, etMinZ, enter_pressed); return wxGetApp().obj_list()->edit_layer_range(range, new_range); From 3d755e1bbe642becb73c9f64910616787eade373 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 25 Jun 2019 09:20:58 +0200 Subject: [PATCH 42/83] Removed 'Use legacy OpenGL 1.1 rendering' option --- src/slic3r/GUI/AppConfig.cpp | 7 +++---- src/slic3r/GUI/GLCanvas3D.cpp | 13 +++---------- src/slic3r/GUI/GLCanvas3D.hpp | 4 +--- src/slic3r/GUI/GLCanvas3DManager.cpp | 10 +++------- src/slic3r/GUI/GLCanvas3DManager.hpp | 1 - src/slic3r/GUI/Preferences.cpp | 13 +------------ 6 files changed, 11 insertions(+), 37 deletions(-) diff --git a/src/slic3r/GUI/AppConfig.cpp b/src/slic3r/GUI/AppConfig.cpp index 51bee9e75..3b6210058 100644 --- a/src/slic3r/GUI/AppConfig.cpp +++ b/src/slic3r/GUI/AppConfig.cpp @@ -54,10 +54,9 @@ void AppConfig::set_defaults() if (get("preset_update").empty()) set("preset_update", "1"); - // Use OpenGL 1.1 even if OpenGL 2.0 is available. This is mainly to support some buggy Intel HD Graphics drivers. - // github.com/prusa3d/PrusaSlicer/issues/233 - if (get("use_legacy_opengl").empty()) - set("use_legacy_opengl", "0"); + // remove old 'use_legacy_opengl' parameter from this config, if present + if (!get("use_legacy_opengl").empty()) + erase("", "use_legacy_opengl"); #if __APPLE__ if (get("use_retina_opengl").empty()) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index cf8a49ea2..c828e0ec6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -198,8 +198,7 @@ void GLCanvas3D::Shader::_reset() #endif // !ENABLE_TEXTURES_FROM_SVG GLCanvas3D::LayersEditing::LayersEditing() - : m_use_legacy_opengl(false) - , m_enabled(false) + : m_enabled(false) , m_z_texture_id(0) , m_model_object(nullptr) , m_object_max_z(0.f) @@ -274,12 +273,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id) bool GLCanvas3D::LayersEditing::is_allowed() const { - return !m_use_legacy_opengl && m_shader.is_initialized() && m_shader.get_shader()->shader_program_id > 0 && m_z_texture_id > 0; -} - -void GLCanvas3D::LayersEditing::set_use_legacy_opengl(bool use_legacy_opengl) -{ - m_use_legacy_opengl = use_legacy_opengl; + return m_shader.is_initialized() && m_shader.get_shader()->shader_program_id > 0 && m_z_texture_id > 0; } bool GLCanvas3D::LayersEditing::is_enabled() const @@ -1253,7 +1247,7 @@ void GLCanvas3D::post_event(wxEvent &&event) wxPostEvent(m_canvas, event); } -bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) +bool GLCanvas3D::init(bool useVBOs) { if (m_initialized) return true; @@ -1311,7 +1305,6 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) return false; m_use_VBOs = useVBOs; - m_layers_editing.set_use_legacy_opengl(use_legacy_opengl); // on linux the gl context is not valid until the canvas is not shown on screen // we defer the geometry finalization of volumes until the first call to render() diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d39a910b3..5a4287903 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -197,7 +197,6 @@ class GLCanvas3D static const float THICKNESS_BAR_WIDTH; static const float THICKNESS_RESET_BUTTON_HEIGHT; - bool m_use_legacy_opengl; bool m_enabled; Shader m_shader; unsigned int m_z_texture_id; @@ -250,7 +249,6 @@ class GLCanvas3D void select_object(const Model &model, int object_id); bool is_allowed() const; - void set_use_legacy_opengl(bool use_legacy_opengl); bool is_enabled() const; void set_enabled(bool enabled); @@ -492,7 +490,7 @@ public: wxGLCanvas* get_wxglcanvas() { return m_canvas; } const wxGLCanvas* get_wxglcanvas() const { return m_canvas; } - bool init(bool useVBOs, bool use_legacy_opengl); + bool init(bool useVBOs); void post_event(wxEvent &&event); void set_as_dirty(); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 4f64b4e87..a1430ef22 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -192,7 +192,6 @@ GLCanvas3DManager::GLInfo GLCanvas3DManager::s_gl_info; GLCanvas3DManager::GLCanvas3DManager() : m_context(nullptr) , m_gl_initialized(false) - , m_use_legacy_opengl(false) , m_use_VBOs(false) { } @@ -268,8 +267,7 @@ void GLCanvas3DManager::init_gl() { glewInit(); const AppConfig* config = GUI::get_app_config(); - m_use_legacy_opengl = (config == nullptr) || (config->get("use_legacy_opengl") == "1"); - m_use_VBOs = !m_use_legacy_opengl && s_gl_info.is_version_greater_or_equal_to(2, 0); + m_use_VBOs = s_gl_info.is_version_greater_or_equal_to(2, 0); m_gl_initialized = true; if (GLEW_EXT_texture_compression_s3tc) s_compressed_textures_supported = true; @@ -325,16 +323,14 @@ bool GLCanvas3DManager::init(GLCanvas3D& canvas) if (!m_gl_initialized) init_gl(); - return canvas.init(m_use_VBOs, m_use_legacy_opengl); + return canvas.init(m_use_VBOs); } void GLCanvas3DManager::detect_multisample(int* attribList) { int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; const AppConfig* app_config = GUI::get_app_config(); - bool enable_multisample = app_config != nullptr - && app_config->get("use_legacy_opengl") != "1" - && wxVersion >= 30003; + bool enable_multisample = wxVersion >= 30003; s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled; // Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 26c2558d0..7a600dcbd 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -75,7 +75,6 @@ private: wxGLContext* m_context; static GLInfo s_gl_info; bool m_gl_initialized; - bool m_use_legacy_opengl; bool m_use_VBOs; static EMultisampleState s_multisample; static bool s_compressed_textures_supported; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 7b3187012..827d1f4e0 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -97,16 +97,6 @@ void PreferencesDialog::build() option = Option (def,"show_incompatible_presets"); m_optgroup->append_single_option_line(option); - // TODO: remove? - def.label = L("Use legacy OpenGL 1.1 rendering"); - def.type = coBool; - def.tooltip = L("If you have rendering issues caused by a buggy OpenGL 2.0 driver, " - "you may try to check this checkbox. This will disable the layer height " - "editing and anti aliasing, so it is likely better to upgrade your graphics driver."); - def.set_default_value(new ConfigOptionBool{ app_config->get("use_legacy_opengl") == "1" }); - option = Option (def,"use_legacy_opengl"); - m_optgroup->append_single_option_line(option); - #if __APPLE__ def.label = L("Use Retina resolution for the 3D scene"); def.type = coBool; @@ -150,8 +140,7 @@ void PreferencesDialog::build() void PreferencesDialog::accept() { - if (m_values.find("no_defaults") != m_values.end() || - m_values.find("use_legacy_opengl") != m_values.end()) { + if (m_values.find("no_defaults") != m_values.end()) { warning_catcher(this, wxString::Format(_(L("You need to restart %s to make the changes effective.")), SLIC3R_APP_NAME)); } From 2f806dedc762c1ee810be44820aaff8de8cb5d07 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 25 Jun 2019 09:51:43 +0200 Subject: [PATCH 43/83] Fixed rendering of selection rectangle with perspective camera --- src/slic3r/GUI/GLSelectionRectangle.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index 327cb1fde..684563bff 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -68,7 +68,8 @@ namespace GUI { if (!is_dragging()) return; - float zoom = (float)canvas.get_camera().get_zoom(); + const Camera& camera = canvas.get_camera(); + float zoom = (float)camera.get_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; Size cnv_size = canvas.get_canvas_size(); @@ -96,6 +97,11 @@ namespace GUI { glsafe(::glPushMatrix()); glsafe(::glLoadIdentity()); + // ensure that the rectangle is renderered inside the frustrum + glsafe(::glTranslated(0.0, 0.0, -(camera.get_near_z() + 0.5))); + // ensure that the overlay fits the frustrum near z plane + double gui_scale = camera.get_gui_scale(); + glsafe(::glScaled(gui_scale, gui_scale, 1.0)); glsafe(::glPushAttrib(GL_ENABLE_BIT)); glsafe(::glLineStipple(4, 0xAAAA)); From 84027a3d3bbf48d61fc238621b1b0b16004f3280 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 25 Jun 2019 14:50:27 +0200 Subject: [PATCH 44/83] avrdude: warnings cleanup --- src/avrdude/arduino.c | 13 ++- src/avrdude/avr.c | 24 ++-- src/avrdude/avr910.c | 2 +- src/avrdude/avrdude-slic3r.cpp | 6 +- src/avrdude/avrdude.h | 2 + src/avrdude/avrpart.c | 4 +- src/avrdude/buspirate.c | 4 +- src/avrdude/butterfly.c | 2 +- src/avrdude/config.c | 6 +- src/avrdude/config_gram.c | 2 +- src/avrdude/config_gram.y | 2 +- src/avrdude/fileio.c | 43 +++---- src/avrdude/lists.c | 12 +- src/avrdude/main.c | 6 +- src/avrdude/pindefs.c | 2 +- src/avrdude/ser_win32.c | 12 +- src/avrdude/serbb_win32.c | 8 +- src/avrdude/stk500.c | 12 +- src/avrdude/stk500v2.c | 205 ++++++++++++++++++--------------- src/avrdude/term.c | 26 ++--- 20 files changed, 206 insertions(+), 187 deletions(-) diff --git a/src/avrdude/arduino.c b/src/avrdude/arduino.c index 53e5ed822..e6008adeb 100644 --- a/src/avrdude/arduino.c +++ b/src/avrdude/arduino.c @@ -41,6 +41,7 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) { unsigned char buf[32]; + (void)p; /* Signature byte reads are always 3 bytes. */ @@ -83,9 +84,9 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m) static int prusa_init_external_flash(PROGRAMMER * pgm) { // Note: send/receive as in _the firmare_ send & receives - const char entry_magic_send [] = "start\n"; - const char entry_magic_receive[] = "w25x20cl_enter\n"; - const char entry_magic_cfm [] = "w25x20cl_cfm\n"; + const char entry_magic_send[] = "start\n"; + const unsigned char entry_magic_receive[] = "w25x20cl_enter\n"; + const char entry_magic_cfm[] = "w25x20cl_cfm\n"; const size_t buffer_len = 32; // Should be large enough for the above messages int res; @@ -94,7 +95,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm) // 1. receive the "start" command recv_size = sizeof(entry_magic_send) - 1; - res = serial_recv(&pgm->fd, buffer, recv_size); + res = serial_recv(&pgm->fd, (unsigned char *)buffer, recv_size); if (res < 0) { avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname); return -1; @@ -111,7 +112,7 @@ static int prusa_init_external_flash(PROGRAMMER * pgm) // 3. Receive the entry confirmation command recv_size = sizeof(entry_magic_cfm) - 1; - res = serial_recv(&pgm->fd, buffer, recv_size); + res = serial_recv(&pgm->fd, (unsigned char *)buffer, recv_size); if (res < 0) { avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname); return -1; @@ -142,7 +143,7 @@ static int arduino_open(PROGRAMMER * pgm, char * port) // Sometimes there may be line noise generating input on the printer's USB-to-serial IC // Here we try to clean its input buffer with a sequence of newlines (a minimum of 9 is needed): - const char cleanup_newlines[] = "\n\n\n\n\n\n\n\n\n\n"; + const unsigned char cleanup_newlines[] = "\n\n\n\n\n\n\n\n\n\n"; if (serial_send(&pgm->fd, cleanup_newlines, sizeof(cleanup_newlines) - 1) < 0) { return -1; } diff --git a/src/avrdude/avr.c b/src/avrdude/avr.c index 73dcaf4ff..defae75d5 100644 --- a/src/avrdude/avr.c +++ b/src/avrdude/avr.c @@ -341,7 +341,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, avr_tpi_setup_rw(pgm, mem, 0, TPI_NVMCMD_NO_OPERATION); /* load bytes */ - for (lastaddr = i = 0; i < mem->size; i++) { + for (lastaddr = i = 0; i < (unsigned)mem->size; i++) { RETURN_IF_CANCEL(); if (vmem == NULL || (vmem->tags[i] & TAG_ALLOCATED) != 0) @@ -374,7 +374,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, /* quickly scan number of pages to be written to first */ for (pageaddr = 0, npages = 0; - pageaddr < mem->size; + pageaddr < (unsigned)mem->size; pageaddr += mem->page_size) { /* check whether this page must be read */ for (i = pageaddr; @@ -391,7 +391,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, } for (pageaddr = 0, failure = 0, nread = 0; - !failure && pageaddr < mem->size; + !failure && pageaddr < (unsigned)mem->size; pageaddr += mem->page_size) { RETURN_IF_CANCEL(); /* check whether this page must be read */ @@ -437,7 +437,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, } } - for (i=0; i < mem->size; i++) { + for (i = 0; i < (unsigned)mem->size; i++) { RETURN_IF_CANCEL(); if (vmem == NULL || (vmem->tags[i] & TAG_ALLOCATED) != 0) @@ -634,18 +634,18 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, writeop = mem->op[AVR_OP_WRITE_HI]; else writeop = mem->op[AVR_OP_WRITE_LO]; - caddr = addr / 2; + caddr = (unsigned short)(addr / 2); } else if (mem->paged && mem->op[AVR_OP_LOADPAGE_LO]) { if (addr & 0x01) writeop = mem->op[AVR_OP_LOADPAGE_HI]; else writeop = mem->op[AVR_OP_LOADPAGE_LO]; - caddr = addr / 2; + caddr = (unsigned short)(addr / 2); } else { writeop = mem->op[AVR_OP_WRITE]; - caddr = addr; + caddr = (unsigned short)addr; } if (writeop == NULL) { @@ -723,7 +723,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, gettimeofday (&tv, NULL); prog_time = (tv.tv_sec * 1000000) + tv.tv_usec; } while ((r != data) && - ((prog_time-start_time) < mem->max_write_delay)); + ((prog_time - start_time) < (unsigned long)mem->max_write_delay)); } /* @@ -878,7 +878,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, } /* write words, low byte first */ - for (lastaddr = i = 0; i < wsize; i += 2) { + for (lastaddr = i = 0; i < (unsigned)wsize; i += 2) { RETURN_IF_CANCEL(); if ((m->tags[i] & TAG_ALLOCATED) != 0 || (m->tags[i + 1] & TAG_ALLOCATED) != 0) { @@ -915,7 +915,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, /* quickly scan number of pages to be written to first */ for (pageaddr = 0, npages = 0; - pageaddr < wsize; + pageaddr < (unsigned)wsize; pageaddr += m->page_size) { /* check whether this page must be written to */ for (i = pageaddr; @@ -928,7 +928,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, } for (pageaddr = 0, failure = 0, nwritten = 0; - !failure && pageaddr < wsize; + !failure && pageaddr < (unsigned)wsize; pageaddr += m->page_size) { RETURN_IF_CANCEL(); /* check whether this page must be written to */ @@ -968,7 +968,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size, page_tainted = 0; flush_page = 0; - for (i=0; ibuf[i]; report_progress(i, wsize, NULL); diff --git a/src/avrdude/avr910.c b/src/avrdude/avr910.c index aa5cc07a9..17a4ab69f 100644 --- a/src/avrdude/avr910.c +++ b/src/avrdude/avr910.c @@ -676,7 +676,7 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, avr910_set_addr(pgm, addr / rd_size); while (addr < max_addr) { - if ((max_addr - addr) < blocksize) { + if ((max_addr - addr) < (unsigned)blocksize) { blocksize = max_addr - addr; } cmd[1] = (blocksize >> 8) & 0xff; diff --git a/src/avrdude/avrdude-slic3r.cpp b/src/avrdude/avrdude-slic3r.cpp index 0140d93ed..7eff436e2 100644 --- a/src/avrdude/avrdude-slic3r.cpp +++ b/src/avrdude/avrdude-slic3r.cpp @@ -93,7 +93,7 @@ void AvrDude::priv::unset_handlers() int AvrDude::priv::run_one(const std::vector &args) { - std::vector c_args {{ const_cast(PACKAGE) }}; + std::vector c_args { const_cast(PACKAGE) }; std::string command_line { PACKAGE }; for (const auto &arg : args) { @@ -105,7 +105,7 @@ int AvrDude::priv::run_one(const std::vector &args) { HandlerGuard guard(*this); - message_fn(command_line.c_str(), command_line.size()); + message_fn(command_line.c_str(), (unsigned)command_line.size()); const auto res = ::avrdude_main(static_cast(c_args.size()), c_args.data()); @@ -200,7 +200,7 @@ AvrDude::Ptr AvrDude::run() auto &message_fn = self->p->message_fn; if (message_fn) { message_fn(msg, sizeof(msg)); - message_fn(what, std::strlen(what)); + message_fn(what, (unsigned)std::strlen(what)); message_fn("\n", 1); } diff --git a/src/avrdude/avrdude.h b/src/avrdude/avrdude.h index ff464f46f..bc784cec6 100644 --- a/src/avrdude/avrdude.h +++ b/src/avrdude/avrdude.h @@ -64,6 +64,8 @@ int avrdude_main(int argc, char * argv []); #include #include +#define strdup _strdup + #ifdef UNICODE #error "UNICODE should not be defined for avrdude bits on Windows" #endif diff --git a/src/avrdude/avrpart.c b/src/avrdude/avrpart.c index d0bb951ee..1c7d6af00 100644 --- a/src/avrdude/avrpart.c +++ b/src/avrdude/avrpart.c @@ -358,7 +358,7 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc) int matches; int l; - l = strlen(desc); + l = (int)strlen(desc); matches = 0; match = NULL; for (ln=lfirst(p->mem); ln; ln=lnext(ln)) { @@ -662,7 +662,7 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose) prefix); px = prefix; - i = strlen(prefix) + 5; + i = (int)strlen(prefix) + 5; buf = (char *)malloc(i); if (buf == NULL) { /* ugh, this is not important enough to bail, just ignore it */ diff --git a/src/avrdude/buspirate.c b/src/avrdude/buspirate.c index 5875d4283..dc8c68fbe 100644 --- a/src/avrdude/buspirate.c +++ b/src/avrdude/buspirate.c @@ -128,7 +128,7 @@ static int buspirate_recv_bin(struct programmer_t *pgm, unsigned char *buf, size avrdude_message(MSG_DEBUG, "%s: buspirate_recv_bin():\n", progname); dump_mem(MSG_DEBUG, buf, len); - return len; + return (int)len; } static int buspirate_expect_bin(struct programmer_t *pgm, @@ -249,7 +249,7 @@ static int buspirate_send(struct programmer_t *pgm, const char *str) static int buspirate_is_prompt(const char *str) { - int strlen_str = strlen(str); + int strlen_str = (int)strlen(str); /* Prompt ends with '>' or '> ' * all other input probably ends with '\n' */ return (str[strlen_str - 1] == '>' || str[strlen_str - 2] == '>'); diff --git a/src/avrdude/butterfly.c b/src/avrdude/butterfly.c index beb5e04de..8f582e72a 100644 --- a/src/avrdude/butterfly.c +++ b/src/avrdude/butterfly.c @@ -675,7 +675,7 @@ static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, butterfly_set_addr(pgm, addr / rd_size); } while (addr < max_addr) { - if ((max_addr - addr) < blocksize) { + if ((max_addr - addr) < (unsigned)blocksize) { blocksize = max_addr - addr; }; cmd[1] = (blocksize >> 8) & 0xff; diff --git a/src/avrdude/config.c b/src/avrdude/config.c index 1c0ff5525..b82fb29cb 100644 --- a/src/avrdude/config.c +++ b/src/avrdude/config.c @@ -240,7 +240,7 @@ TOKEN * string(char * text) return NULL; /* yyerror already called */ } - len = strlen(text); + len = (int)strlen(text); tkn->value.type = V_STR; tkn->value.string = (char *) malloc(len+1); @@ -351,7 +351,7 @@ int read_config(const char * file) } typedef struct yy_buffer_state *YY_BUFFER_STATE; -extern YY_BUFFER_STATE yy_scan_bytes(char *base, size_t size); +extern YY_BUFFER_STATE yy_scan_bytes(const char *base, size_t size); extern void yy_delete_buffer(YY_BUFFER_STATE b); int read_config_builtin() @@ -363,7 +363,7 @@ int read_config_builtin() // Note: Can't use yy_scan_buffer, it's buggy (?), leads to fread from a null FILE* // and so unfortunatelly we have to use the copying variant here - YY_BUFFER_STATE buffer = yy_scan_bytes(avrdude_slic3r_conf, avrdude_slic3r_conf_size); + YY_BUFFER_STATE buffer = yy_scan_bytes((const char *)avrdude_slic3r_conf, avrdude_slic3r_conf_size); if (buffer == NULL) { avrdude_message(MSG_INFO, "%s: read_config_builtin: Failed to initialize parsing buffer\n", progname); return -1; diff --git a/src/avrdude/config_gram.c b/src/avrdude/config_gram.c index c1a65b13e..2d32fe739 100644 --- a/src/avrdude/config_gram.c +++ b/src/avrdude/config_gram.c @@ -3640,7 +3640,7 @@ static int parse_cmdbits(OPCODE * op) break; } - len = strlen(s); + len = (int)strlen(s); if (len == 0) { yyerror("invalid bit specifier \"\""); diff --git a/src/avrdude/config_gram.y b/src/avrdude/config_gram.y index 0aa95a8e8..6a062352b 100644 --- a/src/avrdude/config_gram.y +++ b/src/avrdude/config_gram.y @@ -1493,7 +1493,7 @@ static int parse_cmdbits(OPCODE * op) break; } - len = strlen(s); + len = (int)strlen(s); if (len == 0) { yyerror("invalid bit specifier \"\""); diff --git a/src/avrdude/fileio.c b/src/avrdude/fileio.c index 7803497a0..7f4c8edee 100644 --- a/src/avrdude/fileio.c +++ b/src/avrdude/fileio.c @@ -264,7 +264,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) unsigned char cksum; int rc; - len = strlen(rec); + len = (int)strlen(rec); offset = 1; cksum = 0; @@ -274,7 +274,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; - ihex->reclen = strtoul(buf, &e, 16); + ihex->reclen = (unsigned char)strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; @@ -294,7 +294,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; - ihex->rectyp = strtoul(buf, &e, 16); + ihex->rectyp = (unsigned char)strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; @@ -308,7 +308,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; - ihex->data[j] = strtoul(buf, &e, 16); + ihex->data[j] = (char)strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; cksum += ihex->data[j]; @@ -320,7 +320,7 @@ static int ihex_readrec(struct ihexrec * ihex, char * rec) for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; - ihex->cksum = strtoul(buf, &e, 16); + ihex->cksum = (char)strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; @@ -361,7 +361,7 @@ static int ihex2b(char * infile, FILE * inf, while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { lineno++; - len = strlen(buffer); + len = (int)strlen(buffer); if (buffer[len-1] == '\n') buffer[--len] = 0; if (buffer[0] != ':') @@ -388,7 +388,7 @@ static int ihex2b(char * infile, FILE * inf, return -1; } nextaddr = ihex.loadofs + baseaddr - fileoffset; - if (nextaddr + ihex.reclen > bufsize) { + if (nextaddr + ihex.reclen > (unsigned)bufsize) { avrdude_message(MSG_INFO, "%s: ERROR: address 0x%04x out of range at line %d of %s\n", progname, nextaddr+ihex.reclen, lineno, infile); return -1; @@ -502,10 +502,11 @@ static int b2srec(unsigned char * inbuf, int bufsize, cksum += n + addr_width + 1; - for (i=addr_width; i>0; i--) + for (i = addr_width; i>0; i--) { cksum += (nextaddr >> (i-1) * 8) & 0xff; + } - for (i=nextaddr; ireclen = strtoul(buf, &e, 16); + srec->reclen = (char)strtoul(buf, &e, 16); cksum += srec->reclen; srec->reclen -= (addr_width+1); if (e == buf || *e != 0) @@ -594,7 +595,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) for (i=0; iloadofs = strtoull(buf, &e, 16); + srec->loadofs = strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; @@ -608,7 +609,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; - srec->data[j] = strtoul(buf, &e, 16); + srec->data[j] = (char)strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; cksum += srec->data[j]; @@ -620,7 +621,7 @@ static int srec_readrec(struct ihexrec * srec, char * rec) for (i=0; i<2; i++) buf[i] = rec[offset++]; buf[i] = 0; - srec->cksum = strtoul(buf, &e, 16); + srec->cksum = (char)strtoul(buf, &e, 16); if (e == buf || *e != 0) return -1; @@ -650,7 +651,7 @@ static int srec2b(char * infile, FILE * inf, while (fgets((char *)buffer,MAX_LINE_LEN,inf)!=NULL) { lineno++; - len = strlen(buffer); + len = (int)strlen(buffer); if (buffer[len-1] == '\n') buffer[--len] = 0; if (buffer[0] != 0x53) @@ -729,7 +730,7 @@ static int srec2b(char * infile, FILE * inf, return -1; } nextaddr -= fileoffset; - if (nextaddr + srec.reclen > bufsize) { + if (nextaddr + srec.reclen > (unsigned)bufsize) { avrdude_message(MSG_INFO, msg, progname, nextaddr+srec.reclen, "", lineno, infile); return -1; @@ -740,7 +741,7 @@ static int srec2b(char * infile, FILE * inf, } if (nextaddr+srec.reclen > maxaddr) maxaddr = nextaddr+srec.reclen; - reccount++; + reccount++; } } @@ -1143,12 +1144,12 @@ static int fileio_rbin(struct fioparms * fio, switch (fio->op) { case FIO_READ: - rc = fread(buf, 1, size, f); + rc = (int)fread(buf, 1, size, f); if (rc > 0) memset(mem->tags, TAG_ALLOCATED, rc); break; case FIO_WRITE: - rc = fwrite(buf, 1, size, f); + rc = (int)fwrite(buf, 1, size, f); break; default: avrdude_message(MSG_INFO, "%s: fileio: invalid operation=%d\n", @@ -1190,7 +1191,7 @@ static int fileio_imm(struct fioparms * fio, progname, p); return -1; } - mem->buf[loc] = b; + mem->buf[loc] = (char)b; mem->tags[loc++] = TAG_ALLOCATED; p = strtok(NULL, " ,"); rc = loc; @@ -1452,7 +1453,7 @@ static int fmt_autodetect(char * fname, unsigned section) } buf[MAX_LINE_LEN-1] = 0; - len = strlen((char *)buf); + len = (int)strlen((char *)buf); if (buf[len-1] == '\n') buf[--len] = 0; diff --git a/src/avrdude/lists.c b/src/avrdude/lists.c index cab88364e..063507ed3 100644 --- a/src/avrdude/lists.c +++ b/src/avrdude/lists.c @@ -444,7 +444,7 @@ lcreat ( void * liststruct, int elements ) l->poolsize = DEFAULT_POOLSIZE; } else { - l->poolsize = elements*sizeof(LISTNODE)+sizeof(NODEPOOL); + l->poolsize = (short)(elements*sizeof(LISTNODE)+sizeof(NODEPOOL)); } l->n_ln_pool = (l->poolsize-sizeof(NODEPOOL))/sizeof(LISTNODE); @@ -803,7 +803,7 @@ lget_n ( LISTID lid, unsigned int n ) CKLMAGIC(l); - if ((n<1)||(n>lsize(l))) { + if ((n < 1) || (n > (unsigned)lsize(l))) { return NULL; } @@ -844,7 +844,7 @@ lget_ln ( LISTID lid, unsigned int n ) CKLMAGIC(l); - if ((n<1)||(n>lsize(l))) { + if ((n < 1) || (n > (unsigned)lsize(l))) { return NULL; } @@ -941,7 +941,7 @@ insert_ln ( LIST * l, LISTNODE * ln, void * data_ptr ) | | Insert data before the nth item in the list. -----------------------------------------------------------------*/ -int +int lins_n ( LISTID lid, void * data_ptr, unsigned int n ) { int i; @@ -952,7 +952,7 @@ lins_n ( LISTID lid, void * data_ptr, unsigned int n ) CKLMAGIC(l); - if ((n<1)||(n>(l->num+1))) { + if ((n < 1) || (n > (unsigned)(l->num+1))) { return -1; } @@ -1193,7 +1193,7 @@ lrmv_n ( LISTID lid, unsigned int n ) CKLMAGIC(l); - if ((n<1)||(n>l->num)) { + if ((n < 1) || (n > (unsigned)l->num)) { return NULL; } diff --git a/src/avrdude/main.c b/src/avrdude/main.c index 8f9040349..60be7ec3a 100644 --- a/src/avrdude/main.c +++ b/src/avrdude/main.c @@ -107,7 +107,7 @@ int avrdude_message(const int msglvl, const char *format, ...) if (rc > 0 && rc < MSGBUFFER_SIZE) { avrdude_message_handler(msgbuffer, rc, avrdude_message_handler_user_p); } else { - avrdude_message_handler(format_error, strlen(format_error), avrdude_message_handler_user_p); + avrdude_message_handler(format_error, (unsigned)strlen(format_error), avrdude_message_handler_user_p); } } @@ -567,7 +567,7 @@ int avrdude_main(int argc, char * argv []) // #endif - len = strlen(progname) + 2; + len = (int)strlen(progname) + 2; for (i=0; ifd.pfd = (void *)hComPort; @@ -326,8 +326,8 @@ static void serbb_close(PROGRAMMER *pgm) pgm->setpin(pgm, PIN_AVR_RESET, 1); CloseHandle (hComPort); } - avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle 0x%x\n", - progname, (int)hComPort); + avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle %p\n", + progname, (void *)hComPort); hComPort = INVALID_HANDLE_VALUE; } diff --git a/src/avrdude/stk500.c b/src/avrdude/stk500.c index efb7078bc..256076cc6 100644 --- a/src/avrdude/stk500.c +++ b/src/avrdude/stk500.c @@ -504,7 +504,7 @@ static int stk500_initialize(PROGRAMMER * pgm, AVRPART * p) } else { buf[9] = 0xff; - buf[10] = 0xff; + buf[10] = 0xff; buf[13] = 0; buf[14] = 0; buf[17] = 0; @@ -821,7 +821,7 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, break; } - for (prusa3d_semicolon_workaround_round = 0; prusa3d_semicolon_workaround_round < (has_semicolon ? 2 : 1); ++ prusa3d_semicolon_workaround_round) { + for (prusa3d_semicolon_workaround_round = 0; prusa3d_semicolon_workaround_round < (has_semicolon ? 2u : 1u); prusa3d_semicolon_workaround_round++) { /* build command block and avoid multiple send commands as it leads to a crash of the silabs usb serial driver on mac os x */ i = 0; @@ -834,7 +834,7 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, buf[i++] = block_size & 0x0f; buf[i++] = memtype; if (has_semicolon) { - for (j = 0; j < block_size; ++i, ++ j) { + for (j = 0; j < (unsigned)block_size; ++i, ++ j) { buf[i] = m->buf[addr + j]; if (buf[i] == ';') buf[i] |= (prusa3d_semicolon_workaround_round ? 0xf0 : 0x0f); @@ -1088,8 +1088,8 @@ static int stk500_set_sck_period(PROGRAMMER * pgm, double v) min = 8.0 / STK500_XTAL; max = 255 * min; - dur = v / min + 0.5; - + dur = (int)(v / min + 0.5); + if (v < min) { dur = 1; avrdude_message(MSG_INFO, "%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n", @@ -1099,7 +1099,7 @@ static int stk500_set_sck_period(PROGRAMMER * pgm, double v) avrdude_message(MSG_INFO, "%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n", progname, v / 1e-6, dur * min / 1e-6); } - + return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur); } diff --git a/src/avrdude/stk500v2.c b/src/avrdude/stk500v2.c index 9bc629ba4..33bdf8eea 100644 --- a/src/avrdude/stk500v2.c +++ b/src/avrdude/stk500v2.c @@ -130,58 +130,58 @@ struct jtagispentry #define SZ_SPI_MULTI (USHRT_MAX - 1) }; -static const struct jtagispentry jtagispcmds[] = { - /* generic */ - { CMD_SET_PARAMETER, 2 }, - { CMD_GET_PARAMETER, 3 }, - { CMD_OSCCAL, 2 }, - { CMD_LOAD_ADDRESS, 2 }, - /* ISP mode */ - { CMD_ENTER_PROGMODE_ISP, 2 }, - { CMD_LEAVE_PROGMODE_ISP, 2 }, - { CMD_CHIP_ERASE_ISP, 2 }, - { CMD_PROGRAM_FLASH_ISP, 2 }, - { CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE }, - { CMD_PROGRAM_EEPROM_ISP, 2 }, - { CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE }, - { CMD_PROGRAM_FUSE_ISP, 3 }, - { CMD_READ_FUSE_ISP, 4 }, - { CMD_PROGRAM_LOCK_ISP, 3 }, - { CMD_READ_LOCK_ISP, 4 }, - { CMD_READ_SIGNATURE_ISP, 4 }, - { CMD_READ_OSCCAL_ISP, 4 }, - { CMD_SPI_MULTI, SZ_SPI_MULTI }, - /* all HV modes */ - { CMD_SET_CONTROL_STACK, 2 }, - /* HVSP mode */ - { CMD_ENTER_PROGMODE_HVSP, 2 }, - { CMD_LEAVE_PROGMODE_HVSP, 2 }, - { CMD_CHIP_ERASE_HVSP, 2 }, - { CMD_PROGRAM_FLASH_HVSP, 2 }, - { CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE }, - { CMD_PROGRAM_EEPROM_HVSP, 2 }, - { CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE }, - { CMD_PROGRAM_FUSE_HVSP, 2 }, - { CMD_READ_FUSE_HVSP, 3 }, - { CMD_PROGRAM_LOCK_HVSP, 2 }, - { CMD_READ_LOCK_HVSP, 3 }, - { CMD_READ_SIGNATURE_HVSP, 3 }, - { CMD_READ_OSCCAL_HVSP, 3 }, - /* PP mode */ - { CMD_ENTER_PROGMODE_PP, 2 }, - { CMD_LEAVE_PROGMODE_PP, 2 }, - { CMD_CHIP_ERASE_PP, 2 }, - { CMD_PROGRAM_FLASH_PP, 2 }, - { CMD_READ_FLASH_PP, SZ_READ_FLASH_EE }, - { CMD_PROGRAM_EEPROM_PP, 2 }, - { CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE }, - { CMD_PROGRAM_FUSE_PP, 2 }, - { CMD_READ_FUSE_PP, 3 }, - { CMD_PROGRAM_LOCK_PP, 2 }, - { CMD_READ_LOCK_PP, 3 }, - { CMD_READ_SIGNATURE_PP, 3 }, - { CMD_READ_OSCCAL_PP, 3 }, -}; +// static const struct jtagispentry jtagispcmds[] = { +// /* generic */ +// { CMD_SET_PARAMETER, 2 }, +// { CMD_GET_PARAMETER, 3 }, +// { CMD_OSCCAL, 2 }, +// { CMD_LOAD_ADDRESS, 2 }, +// /* ISP mode */ +// { CMD_ENTER_PROGMODE_ISP, 2 }, +// { CMD_LEAVE_PROGMODE_ISP, 2 }, +// { CMD_CHIP_ERASE_ISP, 2 }, +// { CMD_PROGRAM_FLASH_ISP, 2 }, +// { CMD_READ_FLASH_ISP, SZ_READ_FLASH_EE }, +// { CMD_PROGRAM_EEPROM_ISP, 2 }, +// { CMD_READ_EEPROM_ISP, SZ_READ_FLASH_EE }, +// { CMD_PROGRAM_FUSE_ISP, 3 }, +// { CMD_READ_FUSE_ISP, 4 }, +// { CMD_PROGRAM_LOCK_ISP, 3 }, +// { CMD_READ_LOCK_ISP, 4 }, +// { CMD_READ_SIGNATURE_ISP, 4 }, +// { CMD_READ_OSCCAL_ISP, 4 }, +// { CMD_SPI_MULTI, SZ_SPI_MULTI }, +// /* all HV modes */ +// { CMD_SET_CONTROL_STACK, 2 }, +// /* HVSP mode */ +// { CMD_ENTER_PROGMODE_HVSP, 2 }, +// { CMD_LEAVE_PROGMODE_HVSP, 2 }, +// { CMD_CHIP_ERASE_HVSP, 2 }, +// { CMD_PROGRAM_FLASH_HVSP, 2 }, +// { CMD_READ_FLASH_HVSP, SZ_READ_FLASH_EE }, +// { CMD_PROGRAM_EEPROM_HVSP, 2 }, +// { CMD_READ_EEPROM_HVSP, SZ_READ_FLASH_EE }, +// { CMD_PROGRAM_FUSE_HVSP, 2 }, +// { CMD_READ_FUSE_HVSP, 3 }, +// { CMD_PROGRAM_LOCK_HVSP, 2 }, +// { CMD_READ_LOCK_HVSP, 3 }, +// { CMD_READ_SIGNATURE_HVSP, 3 }, +// { CMD_READ_OSCCAL_HVSP, 3 }, +// /* PP mode */ +// { CMD_ENTER_PROGMODE_PP, 2 }, +// { CMD_LEAVE_PROGMODE_PP, 2 }, +// { CMD_CHIP_ERASE_PP, 2 }, +// { CMD_PROGRAM_FLASH_PP, 2 }, +// { CMD_READ_FLASH_PP, SZ_READ_FLASH_EE }, +// { CMD_PROGRAM_EEPROM_PP, 2 }, +// { CMD_READ_EEPROM_PP, SZ_READ_FLASH_EE }, +// { CMD_PROGRAM_FUSE_PP, 2 }, +// { CMD_READ_FUSE_PP, 3 }, +// { CMD_PROGRAM_LOCK_PP, 2 }, +// { CMD_READ_LOCK_PP, 3 }, +// { CMD_READ_SIGNATURE_PP, 3 }, +// { CMD_READ_OSCCAL_PP, 3 }, +// }; /* * From XML file: @@ -379,15 +379,15 @@ static void stk500v2_jtag3_teardown(PROGRAMMER * pgm) } -static unsigned short -b2_to_u16(unsigned char *b) -{ - unsigned short l; - l = b[0]; - l += (unsigned)b[1] << 8; +// static unsigned short +// b2_to_u16(unsigned char *b) +// { +// unsigned short l; +// l = b[0]; +// l += (unsigned)b[1] << 8; - return l; -} +// return l; +// } static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len) { @@ -399,16 +399,16 @@ static int stk500v2_send_mk2(PROGRAMMER * pgm, unsigned char * data, size_t len) return 0; } -static unsigned short get_jtagisp_return_size(unsigned char cmd) -{ - int i; +// static unsigned short get_jtagisp_return_size(unsigned char cmd) +// { +// int i; - for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++) - if (jtagispcmds[i].cmd == cmd) - return jtagispcmds[i].size; +// for (i = 0; i < sizeof jtagispcmds / sizeof jtagispcmds[0]; i++) +// if (jtagispcmds[i].cmd == cmd) +// return jtagispcmds[i].size; - return 0; -} +// return 0; +// } /* * Send the data as a JTAG ICE mkII encapsulated ISP packet. @@ -504,7 +504,7 @@ static int stk500v2_send(PROGRAMMER * pgm, unsigned char * data, size_t len) buf[0] = MESSAGE_START; buf[1] = PDATA(pgm)->command_sequence; - buf[2] = len / 256; + buf[2] = (char)(len / 256); buf[3] = len % 256; buf[4] = TOKEN; memcpy(buf+5, data, len); @@ -1128,7 +1128,8 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p) { unsigned char buf[16]; char msg[100]; /* see remarks above about size needed */ - int rv, tries; + int rv; + // int tries; PDATA(pgm)->lastpart = p; @@ -1143,7 +1144,7 @@ static int stk500v2_program_enable(PROGRAMMER * pgm, AVRPART * p) /* Activate AVR-style (low active) RESET */ stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01); - tries = 0; + // tries = 0; // retry: buf[0] = CMD_ENTER_PROGMODE_ISP; buf[1] = p->timeout; @@ -1882,7 +1883,7 @@ static int stk500hv_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0) return -1; } else { - buf[1] = addr; + buf[1] = (char)addr; } avrdude_message(MSG_NOTICE2, "%s: stk500hv_read_byte(): Sending read memory command: ", @@ -2137,7 +2138,7 @@ static int stk500hv_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (stk500v2_loadaddr(pgm, use_ext_addr | (paddr >> addrshift)) < 0) return -1; } else { - buf[1] = addr; + buf[1] = (char)addr; buf[2] = data; if (mode == PPMODE) { buf[3] = pulsewidth; @@ -2298,7 +2299,7 @@ static int stk500v2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int page_size, unsigned int addr, unsigned int n_bytes) { -static int page = 0; +// static int page = 0; unsigned int block_size, last_addr, addrshift, use_ext_addr; unsigned int maxaddr = addr + n_bytes; unsigned char commandbuf[10]; @@ -2833,10 +2834,10 @@ static int stk500v2_set_fosc(PROGRAMMER * pgm, double v) progname, v, unit, STK500V2_XTAL / 2e6); fosc = STK500V2_XTAL / 2; } else - fosc = (unsigned)v; + fosc = (int)v; for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { - if (fosc >= STK500V2_XTAL / (256 * ps[idx] * 2)) { + if (fosc >= (int)(STK500V2_XTAL / (256 * ps[idx] * 2))) { /* this prescaler value can handle our frequency */ prescale = idx + 1; cmatch = (unsigned)(STK500V2_XTAL / (2 * fosc * ps[idx])) - 1; @@ -3065,8 +3066,8 @@ static int stk600_set_fosc(PROGRAMMER * pgm, double v) { unsigned int oct, dac; - oct = 1.443 * log(v / 1039.0); - dac = 2048 - (2078.0 * pow(2, (double)(10 + oct))) / v; + oct = (unsigned)(1.443 * log(v / 1039.0)); + dac = (unsigned)(2048.0 - (2078.0 * pow(2, (double)(10 + oct))) / v); return stk500v2_setparm2(pgm, PARAM2_CLOCK_CONF, (oct << 12) | (dac << 2)); } @@ -3075,7 +3076,7 @@ static int stk600_set_sck_period(PROGRAMMER * pgm, double v) { unsigned int sck; - sck = ceil((16e6 / (2 * 1.0 / v)) - 1); + sck = (unsigned)ceil((16e6 / (2 * 1.0 / v)) - 1); if (sck >= 4096) sck = 4095; @@ -3093,7 +3094,7 @@ static int stk500v2_jtag3_set_sck_period(PROGRAMMER * pgm, double v) else if (v > 1E-3) sck = 1; else - sck = 1.0 / (1000.0 * v); + sck = (unsigned)(1.0 / (1000.0 * v)); value[0] = CMD_SET_SCK; value[1] = sck & 0xff; @@ -3143,7 +3144,7 @@ static int stk500v2_setparm_real(PROGRAMMER * pgm, unsigned char parm, unsigned static int stk500v2_setparm(PROGRAMMER * pgm, unsigned char parm, unsigned char value) { - unsigned char current_value; + unsigned char current_value = 0; int res; res = stk500v2_getparm(pgm, parm, ¤t_value); @@ -3214,8 +3215,15 @@ static const char *stk600_get_cardname(const struct carddata *table, static void stk500v2_display(PROGRAMMER * pgm, const char * p) { - unsigned char maj, min, hdw, topcard, maj_s1, min_s1, maj_s2, min_s2; - unsigned int rev; + unsigned char maj = 0; + unsigned char min = 0; + unsigned char hdw = 0; + unsigned char topcard = 0; + unsigned char maj_s1 = 0; + unsigned char min_s1 = 0; + unsigned char maj_s2 = 0; + unsigned char min_s2 = 0; + unsigned int rev = 0; const char *topcard_name, *pgmname; switch (PDATA(pgm)->pgmtype) { @@ -3294,13 +3302,20 @@ f_to_kHz_MHz(double f, const char **unit) static void stk500v2_print_parms1(PROGRAMMER * pgm, const char * p) { - unsigned char vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration =0; //XXX 0 is not correct, check caller - unsigned int sck_stk600, clock_conf, dac, oct, varef; - unsigned char vtarget_jtag[4]; + unsigned char vtarget = 0; + unsigned char vadjust = 0; + unsigned char sck_duration = 0; + unsigned char osc_pscale = 0; + unsigned char osc_cmatch = 0; + unsigned varef = 0; + unsigned sck_stk600 = 0; + unsigned clock_conf = 0; + unsigned dac, oct; + // unsigned char vtarget_jtag[4]; int prescale; double f; const char *unit; - void *mycookie; + // void *mycookie; if (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) { return; @@ -3963,10 +3978,10 @@ static int stk600_xprog_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, b[0] = XPRG_CMD_WRITE_MEM; b[1] = memcode; b[2] = 0; /* pagemode: non-paged write */ - b[3] = addr >> 24; - b[4] = addr >> 16; - b[5] = addr >> 8; - b[6] = addr; + b[3] = (char)(addr >> 24); + b[4] = (char)(addr >> 16); + b[5] = (char)(addr >> 8); + b[6] = (char)addr; b[7] = 0; b[8] = write_size; b[9] = data; @@ -4011,10 +4026,10 @@ static int stk600_xprog_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, addr += mem->offset; b[0] = XPRG_CMD_READ_MEM; - b[2] = addr >> 24; - b[3] = addr >> 16; - b[4] = addr >> 8; - b[5] = addr; + b[2] = (char)(addr >> 24); + b[3] = (char)(addr >> 16); + b[4] = (char)(addr >> 8); + b[5] = (char)addr; b[6] = 0; b[7] = 1; if (stk600_xprog_command(pgm, b, 8, 3) < 0) { diff --git a/src/avrdude/term.c b/src/avrdude/term.c index 012f6f1a5..182367cf2 100644 --- a/src/avrdude/term.c +++ b/src/avrdude/term.c @@ -281,7 +281,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, maxsize = mem->size; - if (addr >= maxsize) { + if (addr >= (unsigned long)maxsize) { if (argc == 2) { /* wrap around */ addr = 0; @@ -294,7 +294,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, } /* trim len if nessary to not read past the end of memory */ - if ((addr + len) > maxsize) + if ((addr + len) > (unsigned long)maxsize) len = maxsize - addr; buf = malloc(len); @@ -303,7 +303,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, return -1; } - for (i=0; iread_byte(pgm, p, mem, addr+i, &buf[i]); if (rc != 0) { avrdude_message(MSG_INFO, "error reading %s address 0x%05lx of part %s\n", @@ -364,7 +364,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, return -1; } - if (addr > maxsize) { + if (addr > (unsigned long)maxsize) { avrdude_message(MSG_INFO, "%s (write): address 0x%05lx is out of range for %s memory\n", progname, addr, memtype); return -1; @@ -373,7 +373,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, /* number of bytes to write at the specified address */ len = argc - 3; - if ((addr + len) > maxsize) { + if ((addr + len) > (unsigned long)maxsize) { avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed " "range for %s memory\n", progname, memtype); @@ -386,8 +386,8 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, return -1; } - for (i=3; ierr_led(pgm, OFF); - for (werror=0, i=0; i Date: Tue, 25 Jun 2019 16:54:11 +0200 Subject: [PATCH 45/83] semver: warnings cleanup --- src/semver/semver.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/semver/semver.c b/src/semver/semver.c index 527738644..e8bd6edcf 100644 --- a/src/semver/semver.c +++ b/src/semver/semver.c @@ -22,6 +22,10 @@ static const size_t MAX_SIZE = sizeof(char) * 255; static const int MAX_SAFE_INT = (unsigned int) -1 >> 1; +#ifdef _WIN32 + #define strdup _strdup +#endif + /** * Define comparison operators, storing the * ASCII code per each symbol in hexadecimal notation. @@ -50,8 +54,8 @@ strcut (char *str, int begin, int len) { if((int)l < 0 || (int)l > MAX_SAFE_INT) return -1; - if (len < 0) len = l - begin + 1; - if (begin + len > (int)l) len = l - begin; + if (len < 0) len = (int)l - begin + 1; + if (begin + len > (int)l) len = (int)l - begin; memmove(str + begin, str + begin + len, l - len + 1 - begin); return len; @@ -104,7 +108,7 @@ parse_int (const char *s) { static char * parse_slice (char *buf, char sep) { char *pr, *part; - int plen; + size_t plen; /* Find separator in buf */ pr = strchr(buf, sep); @@ -210,8 +214,9 @@ semver_parse_version (const char *str, semver_t *ver) { static int compare_prerelease (char *x, char *y) { char *lastx, *lasty, *xptr, *yptr, *endptr; - int xlen, ylen, xisnum, yisnum, xnum, ynum; - int xn, yn, min, res; + size_t xlen, ylen, xn, yn, min; + int xisnum, yisnum, xnum, ynum; + int res; if (x == NULL && y == NULL) return 0; if (y == NULL && x) return -1; if (x == NULL && y) return 1; @@ -572,7 +577,7 @@ semver_clean (char *s) { for (i = 0; i < len; i++) { if (contains(s[i], VALID_CHARS, mlen) == 0) { - res = strcut(s, i, 1); + res = strcut(s, (int)i, 1); if(res == -1) return -1; --len; --i; } From 4fb904357f9b3d727bb1dd8130cc7252f50e2e1e Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 25 Jun 2019 17:23:53 +0200 Subject: [PATCH 46/83] Warnings cleanup in BonjourDialog, ConfigWizard, FirmwareDialog, GLGizmoCut, ImGuiWrapper --- src/slic3r/GUI/BonjourDialog.cpp | 2 +- src/slic3r/GUI/ConfigWizard.cpp | 6 ++-- src/slic3r/GUI/FirmwareDialog.cpp | 3 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 44 +--------------------------- src/slic3r/GUI/ImGuiWrapper.cpp | 4 +-- 5 files changed, 8 insertions(+), 51 deletions(-) diff --git a/src/slic3r/GUI/BonjourDialog.cpp b/src/slic3r/GUI/BonjourDialog.cpp index 1885dda7b..0e05a517c 100644 --- a/src/slic3r/GUI/BonjourDialog.cpp +++ b/src/slic3r/GUI/BonjourDialog.cpp @@ -171,7 +171,7 @@ void BonjourDialog::on_reply(BonjourReplyEvent &e) // Filter replies based on selected technology const auto model = e.reply.txt_data.find("model"); const bool sl1 = model != e.reply.txt_data.end() && model->second == "SL1"; - if (tech == ptFFF && sl1 || tech == ptSLA && !sl1) { + if ((tech == ptFFF && sl1) || (tech == ptSLA && !sl1)) { return; } diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index aacbfdc52..8b08f6f7f 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -330,8 +330,8 @@ PagePrinters::PagePrinters(ConfigWizard *parent, wxString title, wxString shortn const auto families = vendor.families(); for (const auto &family : families) { const auto filter = [&](const VendorProfile::PrinterModel &model) { - return (model.technology == ptFFF && technology & T_FFF - || model.technology == ptSLA && technology & T_SLA) + return ((model.technology == ptFFF && technology & T_FFF) + || (model.technology == ptSLA && technology & T_SLA)) && model.family == family; }; @@ -810,7 +810,7 @@ void ConfigWizardIndex::on_paint(wxPaintEvent & evt) const Item& item = items[i]; unsigned x = em_w/2 + item.indent * em_w; - if (i == item_active || item_hover >= 0 && i == (size_t)item_hover) { + if (i == item_active || (item_hover >= 0 && i == (size_t)item_hover)) { dc.DrawBitmap(bullet_blue.bmp(), x, y + yoff_icon, false); } else if (i < item_active) { dc.DrawBitmap(bullet_black.bmp(), x, y + yoff_icon, false); } diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index 15a09aa71..7865aecf2 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -442,8 +442,7 @@ void FirmwareDialog::priv::avr109_lookup_port(Avr109Pid usb_pid) auto ports = Utils::scan_serial_ports_extended(); ports.erase(std::remove_if(ports.begin(), ports.end(), [=](const SerialPortInfo &port ) { return port.id_vendor != USB_VID_PRUSA || - port.id_product != usb_pid.boot && - port.id_product != usb_pid.app; + (port.id_product != usb_pid.boot && port.id_product != usb_pid.app); }), ports.end()); if (ports.size() == 0) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 8934bc52b..17db953d4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -15,48 +15,6 @@ namespace Slic3r { namespace GUI { - -class GLGizmoCutPanel : public wxPanel -{ -public: - GLGizmoCutPanel(wxWindow *parent); - - void display(bool display); -private: - bool m_active; - wxCheckBox *m_cb_rotate; - wxButton *m_btn_cut; - wxButton *m_btn_cancel; -}; - -GLGizmoCutPanel::GLGizmoCutPanel(wxWindow *parent) - : wxPanel(parent) - , m_active(false) - , m_cb_rotate(new wxCheckBox(this, wxID_ANY, _(L("Rotate lower part upwards")))) - , m_btn_cut(new wxButton(this, wxID_OK, _(L("Perform cut")))) - , m_btn_cancel(new wxButton(this, wxID_CANCEL, _(L("Cancel")))) -{ - enum { MARGIN = 5 }; - - auto *sizer = new wxBoxSizer(wxHORIZONTAL); - - auto *label = new wxStaticText(this, wxID_ANY, _(L("Cut object:"))); - sizer->Add(label, 0, wxALL | wxALIGN_CENTER, MARGIN); - sizer->Add(m_cb_rotate, 0, wxALL | wxALIGN_CENTER, MARGIN); - sizer->AddStretchSpacer(); - sizer->Add(m_btn_cut, 0, wxALL | wxALIGN_CENTER, MARGIN); - sizer->Add(m_btn_cancel, 0, wxALL | wxALIGN_CENTER, MARGIN); - - SetSizer(sizer); -} - -void GLGizmoCutPanel::display(bool display) -{ - Show(display); - GetParent()->Layout(); -} - - const double GLGizmoCut::Offset = 10.0; const double GLGizmoCut::Margin = 20.0; const std::array GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 }; @@ -188,7 +146,7 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, co m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); ImGui::PushItemWidth(m_imgui->scaled(5.0f)); - bool _value_changed = ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f"); + ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f"); m_imgui->checkbox(_(L("Keep upper part")), m_keep_upper); m_imgui->checkbox(_(L("Keep lower part")), m_keep_lower); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index ca1538bf7..b6abf641a 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -326,9 +326,9 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector& int selection_out = -1; bool res = false; - const char *selection_str = selection < options.size() ? options[selection].c_str() : ""; + const char *selection_str = selection < (int)options.size() ? options[selection].c_str() : ""; if (ImGui::BeginCombo("", selection_str)) { - for (int i = 0; i < options.size(); i++) { + for (int i = 0; i < (int)options.size(); i++) { if (ImGui::Selectable(options[i].c_str(), i == selection)) { selection_out = i; } From 85575e5615d44e5bc46963f446b2b406464c1150 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 25 Jun 2019 17:25:24 +0200 Subject: [PATCH 47/83] Fix: IsTriviallyCopyable on clang --- src/libslic3r/Utils.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index e76fccdb8..adf7f57a7 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -167,7 +167,7 @@ template size_t next_highest_power_of_2(T v, extern std::string xml_escape(std::string text); -#if defined __GNUC__ & __GNUC__ < 5 +#if defined __GNUC__ && __GNUC__ < 5 && !defined __clang__ // Older GCCs don't have std::is_trivially_copyable // cf. https://gcc.gnu.org/onlinedocs/gcc-4.9.4/libstdc++/manual/manual/status.html#status.iso.2011 #warning "GCC version < 5, faking std::is_trivially_copyable" From a38bcdde6681c81559e0aa7a01361d62ef2118eb Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 25 Jun 2019 17:41:24 +0200 Subject: [PATCH 48/83] avrdude: Fix types in embedded config --- src/avrdude/avrdude-slic3r.conf.h | 6 +++--- src/avrdude/conf-generate.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/avrdude/avrdude-slic3r.conf.h b/src/avrdude/avrdude-slic3r.conf.h index 7cc901336..905b14ee8 100644 --- a/src/avrdude/avrdude-slic3r.conf.h +++ b/src/avrdude/avrdude-slic3r.conf.h @@ -1,5 +1,5 @@ /* WARN: This file is auto-generated from `avrdude-slic3r.conf` */ -unsigned char avrdude_slic3r_conf[] = { +const unsigned char avrdude_slic3r_conf[] = { 0x0a, 0x23, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x62, 0x61, 0x73, 0x69, 0x63, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, @@ -1184,5 +1184,5 @@ unsigned char avrdude_slic3r_conf[] = { 0x20, 0x20, 0x3b, 0x0a, 0x0a, 0x0a, 0, 0 }; -size_t avrdude_slic3r_conf_size = 14178; -size_t avrdude_slic3r_conf_size_yy = 14180; +const size_t avrdude_slic3r_conf_size = 14178; +const size_t avrdude_slic3r_conf_size_yy = 14180; diff --git a/src/avrdude/conf-generate.cpp b/src/avrdude/conf-generate.cpp index f2761ba22..4aa80ae0a 100644 --- a/src/avrdude/conf-generate.cpp +++ b/src/avrdude/conf-generate.cpp @@ -21,7 +21,7 @@ int main(int argc, char const *argv[]) } std::cout << "/* WARN: This file is auto-generated from `" << filename << "` */" << std::endl; - std::cout << "unsigned char " << symbol << "[] = {"; + std::cout << "const unsigned char " << symbol << "[] = {"; char c; std::cout << std::hex; @@ -34,8 +34,8 @@ int main(int argc, char const *argv[]) std::cout << "\n 0, 0\n};\n"; std::cout << std::dec; - std::cout << "size_t " << symbol << "_size = " << size << ";" << std::endl; - std::cout << "size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl; + std::cout << "const size_t " << symbol << "_size = " << size << ";" << std::endl; + std::cout << "const size_t " << symbol << "_size_yy = " << size + 2 << ";" << std::endl; return 0; } From d818d1b429044f547699f2625d2a74501528968f Mon Sep 17 00:00:00 2001 From: BeldrothTheGold Date: Sat, 15 Jun 2019 19:10:14 -0600 Subject: [PATCH 49/83] Add debug option to display picking pass to screen --- src/libslic3r/Technologies.hpp | 2 ++ src/slic3r/GUI/GLCanvas3D.cpp | 2 ++ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index a5f93b24f..86a00480b 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -15,6 +15,8 @@ #define ENABLE_RENDER_STATISTICS 0 // Shows an imgui dialog with camera related data #define ENABLE_CAMERA_STATISTICS 0 +// Render the picking pass instead of the main scene +#define ENABLE_RENDER_PICKING_PASS 0 //==================== diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c828e0ec6..5d73c9248 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1625,6 +1625,7 @@ void GLCanvas3D::render() _picking_pass(); } +#if !ENABLE_RENDER_PICKING_PASS // draw scene glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); _render_background(); @@ -1654,6 +1655,7 @@ void GLCanvas3D::render() _render_current_gizmo(); _render_selection_sidebar_hints(); +#endif // !ENABLE_RENDER_PICKING_PASS #if ENABLE_SHOW_CAMERA_TARGET _render_camera_target(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index cfe07a61c..7e2b558d9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -259,6 +259,10 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const void GLGizmoSlaSupports::on_render_for_picking(const Selection& selection) const { +#if ENABLE_RENDER_PICKING_PASS + m_z_shift = selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z(); +#endif + glsafe(::glEnable(GL_DEPTH_TEST)); render_points(selection, true); } From ac82cbe0cc6d9123611e24a5aabbad1a1bb4c9de Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 26 Jun 2019 09:48:52 +0200 Subject: [PATCH 50/83] Fix of #2548 --- src/slic3r/GUI/Plater.cpp | 38 +++++++++++++++++++++++++++++++++++--- src/slic3r/GUI/Plater.hpp | 14 +++++++++++++- src/slic3r/GUI/Tab.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f68267cef..ceedece60 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1260,6 +1260,7 @@ struct Plater::priv Preview *preview; BackgroundSlicingProcess background_process; + bool suppressed_backround_processing_update { false }; // A class to handle UI jobs like arranging and optimizing rotation. // These are not instant jobs, the user has to be informed about their @@ -1694,7 +1695,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) panels.push_back(preview); this->background_process_timer.SetOwner(this->q, 0); - this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->update_restart_background_process(false, false); }); + this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) + { + if (!this->suppressed_backround_processing_update) + this->update_restart_background_process(false, false); + }); update(); @@ -4176,9 +4181,25 @@ void Plater::changed_objects(const std::vector& object_idxs) this->p->schedule_background_process(); } -void Plater::schedule_background_process() +void Plater::schedule_background_process(bool schedule/* = true*/) { - this->p->schedule_background_process(); + if (schedule) + this->p->schedule_background_process(); + + this->p->suppressed_backround_processing_update = false; +} + +bool Plater::is_background_process_running() const +{ + return this->p->background_process_timer.IsRunning(); +} + +void Plater::suppress_background_process(const bool stop_background_process) +{ + if (stop_background_process) + this->p->background_process_timer.Stop(); + + this->p->suppressed_backround_processing_update = true; } void Plater::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) { p->fix_through_netfabb(obj_idx, vol_idx); } @@ -4254,4 +4275,15 @@ bool Plater::can_copy_to_clipboard() const return true; } +SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() : + m_was_running(wxGetApp().plater()->is_background_process_running()) +{ + wxGetApp().plater()->suppress_background_process(m_was_running); +} + +SuppressBackgroundProcessingUpdate::~SuppressBackgroundProcessingUpdate() +{ + wxGetApp().plater()->schedule_background_process(m_was_running); +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 2851af654..5b1347891 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -175,7 +175,9 @@ public: void reslice_SLA_supports(const ModelObject &object); void changed_object(int obj_idx); void changed_objects(const std::vector& object_idxs); - void schedule_background_process(); + void schedule_background_process(bool schedule = true); + bool is_background_process_running() const; + void suppress_background_process(const bool stop_background_process) ; void fix_through_netfabb(const int obj_idx, const int vol_idx = -1); void send_gcode(); @@ -219,8 +221,18 @@ public: private: struct priv; std::unique_ptr p; + + friend class SuppressBackgroundProcessingUpdate; }; +class SuppressBackgroundProcessingUpdate +{ +public: + SuppressBackgroundProcessingUpdate(); + ~SuppressBackgroundProcessingUpdate(); +private: + bool m_was_running; +}; }} diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 22aecf38d..6e8b8a471 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2314,6 +2314,40 @@ void TabPrinter::build_unregular_pages() auto optgroup = page->new_optgroup(_(L("Size"))); optgroup->append_single_option_line("nozzle_diameter", extruder_idx); + + optgroup->m_on_change = [this, extruder_idx](const t_config_option_key& opt_key, boost::any value) + { + if (m_extruders_count > 1 && opt_key.find_first_of("nozzle_diameter") != std::string::npos) + { + SuppressBackgroundProcessingUpdate sbpu; + const double new_nd = boost::any_cast(value); + std::vector nozzle_diameters = static_cast(m_config->option("nozzle_diameter"))->values; + + // if value was changed + if (fabs(nozzle_diameters[extruder_idx == 0 ? 1 : 0] - new_nd) > EPSILON) + { + const wxString msg_text = _(L("Do you want to change the diameter for all extruders?")); + auto dialog = new wxMessageDialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); + + DynamicPrintConfig new_conf = *m_config; + if (dialog->ShowModal() == wxID_YES) { + for (size_t i = 0; i < nozzle_diameters.size(); i++) { + if (i==extruder_idx) + continue; + nozzle_diameters[i] = new_nd; + } + } + else + nozzle_diameters[extruder_idx] = nozzle_diameters[extruder_idx == 0 ? 1 : 0]; + + new_conf.set_key_value("nozzle_diameter", new ConfigOptionFloats(nozzle_diameters)); + load_config(new_conf); + } + } + + update_dirty(); + update(); + }; optgroup = page->new_optgroup(_(L("Layer height limits"))); optgroup->append_single_option_line("min_layer_height", extruder_idx); From 14b32c4f166f094bc10fae06c88c5234cd94b292 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jun 2019 10:33:42 +0200 Subject: [PATCH 51/83] Make an order in using scale and unscale, remove some warnings. --- src/libnest2d/tests/test.cpp | 552 +++++++++++++-------------- src/libslic3r/MTUtils.hpp | 91 +++++ src/libslic3r/MinAreaBoundingBox.cpp | 68 ++-- src/libslic3r/ModelArrange.cpp | 2 +- src/libslic3r/SLA/SLABasePool.cpp | 15 +- src/libslic3r/SLAPrint.cpp | 34 +- src/libslic3r/libslic3r.h | 14 - 7 files changed, 408 insertions(+), 368 deletions(-) diff --git a/src/libnest2d/tests/test.cpp b/src/libnest2d/tests/test.cpp index 5741e87b4..363a3930c 100644 --- a/src/libnest2d/tests/test.cpp +++ b/src/libnest2d/tests/test.cpp @@ -10,10 +10,6 @@ #include "boost/multiprecision/integer.hpp" #include "boost/rational.hpp" -//#include "../tools/Int128.hpp" - -//#include "gte/Mathematics/GteMinimumAreaBox2.h" - //#include "../tools/libnfpglue.hpp" //#include "../tools/nfp_svgnest_glue.hpp" @@ -42,151 +38,151 @@ struct NfpImpl std::vector& prusaParts() { static std::vector ret; - + if(ret.empty()) { ret.reserve(PRINTER_PART_POLYGONS.size()); for(auto& inp : PRINTER_PART_POLYGONS) ret.emplace_back(inp); } - + return ret; } TEST(BasicFunctionality, Angles) { - + using namespace libnest2d; - + Degrees deg(180); Radians rad(deg); Degrees deg2(rad); - + ASSERT_DOUBLE_EQ(rad, Pi); ASSERT_DOUBLE_EQ(deg, 180); ASSERT_DOUBLE_EQ(deg2, 180); ASSERT_DOUBLE_EQ(rad, Radians(deg)); ASSERT_DOUBLE_EQ( Degrees(rad), deg); - + ASSERT_TRUE(rad == deg); - + Segment seg = {{0, 0}, {12, -10}}; - + ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 270 && Degrees(seg.angleToXaxis()) < 360); - + seg = {{0, 0}, {12, 10}}; - + ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 0 && Degrees(seg.angleToXaxis()) < 90); - + seg = {{0, 0}, {-12, 10}}; - + ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 90 && Degrees(seg.angleToXaxis()) < 180); - + seg = {{0, 0}, {-12, -10}}; - + ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 180 && Degrees(seg.angleToXaxis()) < 270); - + seg = {{0, 0}, {1, 0}}; - + ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 0); - + seg = {{0, 0}, {0, 1}}; - + ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 90); - - + + seg = {{0, 0}, {-1, 0}}; - + ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 180); - - + + seg = {{0, 0}, {0, -1}}; - + ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 270); - + } // Simple test, does not use gmock TEST(BasicFunctionality, creationAndDestruction) { using namespace libnest2d; - + Item sh = { {0, 0}, {1, 0}, {1, 1}, {0, 1} }; - + ASSERT_EQ(sh.vertexCount(), 4u); - + Item sh2 ({ {0, 0}, {1, 0}, {1, 1}, {0, 1} }); - + ASSERT_EQ(sh2.vertexCount(), 4u); - + // copy Item sh3 = sh2; - + ASSERT_EQ(sh3.vertexCount(), 4u); - + sh2 = {}; - + ASSERT_EQ(sh2.vertexCount(), 0u); ASSERT_EQ(sh3.vertexCount(), 4u); - + } TEST(GeometryAlgorithms, boundingCircle) { using namespace libnest2d; using placers::boundingCircle; - + PolygonImpl p = {{{0, 10}, {10, 0}, {0, -10}, {0, 10}}, {}}; Circle c = boundingCircle(p); - + ASSERT_EQ(c.center().X, 0); ASSERT_EQ(c.center().Y, 0); ASSERT_DOUBLE_EQ(c.radius(), 10); - + shapelike::translate(p, PointImpl{10, 10}); c = boundingCircle(p); - + ASSERT_EQ(c.center().X, 10); ASSERT_EQ(c.center().Y, 10); ASSERT_DOUBLE_EQ(c.radius(), 10); - + auto parts = prusaParts(); - + int i = 0; for(auto& part : parts) { c = boundingCircle(part.transformedShape()); if(std::isnan(c.radius())) std::cout << "fail: radius is nan" << std::endl; - + else for(auto v : shapelike::contour(part.transformedShape()) ) { - auto d = pointlike::distance(v, c.center()); - if(d > c.radius() ) { - auto e = std::abs( 1.0 - d/c.radius()); - ASSERT_LE(e, 1e-3); + auto d = pointlike::distance(v, c.center()); + if(d > c.radius() ) { + auto e = std::abs( 1.0 - d/c.radius()); + ASSERT_LE(e, 1e-3); + } } - } i++; } - + } TEST(GeometryAlgorithms, Distance) { using namespace libnest2d; - + Point p1 = {0, 0}; - + Point p2 = {10, 0}; Point p3 = {10, 10}; - + ASSERT_DOUBLE_EQ(pointlike::distance(p1, p2), 10); ASSERT_DOUBLE_EQ(pointlike::distance(p1, p3), sqrt(200)); - + Segment seg(p1, p3); - -// ASSERT_DOUBLE_EQ(pointlike::distance(p2, seg), 7.0710678118654755); - + + // ASSERT_DOUBLE_EQ(pointlike::distance(p2, seg), 7.0710678118654755); + auto result = pointlike::horizontalDistance(p2, seg); - + auto check = [](TCompute val, TCompute expected) { if(std::is_floating_point>::value) ASSERT_DOUBLE_EQ(static_cast(val), @@ -194,44 +190,44 @@ TEST(GeometryAlgorithms, Distance) { else ASSERT_EQ(val, expected); }; - + ASSERT_TRUE(result.second); check(result.first, 10); - + result = pointlike::verticalDistance(p2, seg); ASSERT_TRUE(result.second); check(result.first, -10); - + result = pointlike::verticalDistance(Point{10, 20}, seg); ASSERT_TRUE(result.second); check(result.first, 10); - - + + Point p4 = {80, 0}; Segment seg2 = { {0, 0}, {0, 40} }; - + result = pointlike::horizontalDistance(p4, seg2); - + ASSERT_TRUE(result.second); check(result.first, 80); - + result = pointlike::verticalDistance(p4, seg2); // Point should not be related to the segment ASSERT_FALSE(result.second); - + } TEST(GeometryAlgorithms, Area) { using namespace libnest2d; - + Rectangle rect(10, 10); - + ASSERT_EQ(rect.area(), 100); - + Rectangle rect2 = {100, 100}; - + ASSERT_EQ(rect2.area(), 10000); - + Item item = { {61, 97}, {70, 151}, @@ -242,33 +238,33 @@ TEST(GeometryAlgorithms, Area) { {61, 77}, {61, 97} }; - + ASSERT_TRUE(shapelike::area(item.transformedShape()) > 0 ); } TEST(GeometryAlgorithms, IsPointInsidePolygon) { using namespace libnest2d; - + Rectangle rect(10, 10); - + Point p = {1, 1}; - + ASSERT_TRUE(rect.isInside(p)); - + p = {11, 11}; - + ASSERT_FALSE(rect.isInside(p)); - - + + p = {11, 12}; - + ASSERT_FALSE(rect.isInside(p)); - - + + p = {3, 3}; - + ASSERT_TRUE(rect.isInside(p)); - + } //TEST(GeometryAlgorithms, Intersections) { @@ -294,21 +290,21 @@ TEST(GeometryAlgorithms, LeftAndDownPolygon) { using namespace libnest2d; using namespace libnest2d; - + Box bin(100, 100); BottomLeftPlacer placer(bin); - + Item item = {{70, 75}, {88, 60}, {65, 50}, {60, 30}, {80, 20}, {42, 20}, {35, 35}, {35, 55}, {40, 75}, {70, 75}}; - + Item leftControl = { {40, 75}, - {35, 55}, - {35, 35}, - {42, 20}, - {0, 20}, - {0, 75}, - {40, 75}}; - + {35, 55}, + {35, 35}, + {42, 20}, + {0, 20}, + {0, 75}, + {40, 75}}; + Item downControl = {{88, 60}, {88, 0}, {35, 0}, @@ -318,22 +314,22 @@ TEST(GeometryAlgorithms, LeftAndDownPolygon) {60, 30}, {65, 50}, {88, 60}}; - + Item leftp(placer.leftPoly(item)); - + ASSERT_TRUE(shapelike::isValid(leftp.rawShape()).first); ASSERT_EQ(leftp.vertexCount(), leftControl.vertexCount()); - + for(unsigned long i = 0; i < leftControl.vertexCount(); i++) { ASSERT_EQ(getX(leftp.vertex(i)), getX(leftControl.vertex(i))); ASSERT_EQ(getY(leftp.vertex(i)), getY(leftControl.vertex(i))); } - + Item downp(placer.downPoly(item)); - + ASSERT_TRUE(shapelike::isValid(downp.rawShape()).first); ASSERT_EQ(downp.vertexCount(), downControl.vertexCount()); - + for(unsigned long i = 0; i < downControl.vertexCount(); i++) { ASSERT_EQ(getX(downp.vertex(i)), getX(downControl.vertex(i))); ASSERT_EQ(getY(downp.vertex(i)), getY(downControl.vertex(i))); @@ -344,7 +340,7 @@ TEST(GeometryAlgorithms, LeftAndDownPolygon) TEST(GeometryAlgorithms, ArrangeRectanglesTight) { using namespace libnest2d; - + std::vector rects = { {80, 80}, {60, 90}, @@ -366,17 +362,17 @@ TEST(GeometryAlgorithms, ArrangeRectanglesTight) {5, 5}, {5, 5}, {20, 20} }; - - + + Nester arrange(Box(210, 250)); - + auto groups = arrange(rects.begin(), rects.end()); - + ASSERT_EQ(groups.size(), 1u); ASSERT_EQ(groups[0].size(), rects.size()); - + // check for no intersections, no containment: - + for(auto result : groups) { bool valid = true; for(Item& r1 : result) { @@ -389,14 +385,14 @@ TEST(GeometryAlgorithms, ArrangeRectanglesTight) } } } - + } TEST(GeometryAlgorithms, ArrangeRectanglesLoose) { using namespace libnest2d; - -// std::vector rects = { {40, 40}, {10, 10}, {20, 20} }; + + // std::vector rects = { {40, 40}, {10, 10}, {20, 20} }; std::vector rects = { {80, 80}, {60, 90}, @@ -418,17 +414,17 @@ TEST(GeometryAlgorithms, ArrangeRectanglesLoose) {5, 5}, {5, 5}, {20, 20} }; - + Coord min_obj_distance = 5; - + Nester arrange(Box(210, 250), - min_obj_distance); - + min_obj_distance); + auto groups = arrange(rects.begin(), rects.end()); - + ASSERT_EQ(groups.size(), 1u); ASSERT_EQ(groups[0].size(), rects.size()); - + // check for no intersections, no containment: auto result = groups[0]; bool valid = true; @@ -441,7 +437,7 @@ TEST(GeometryAlgorithms, ArrangeRectanglesLoose) } } } - + } namespace { @@ -449,68 +445,68 @@ using namespace libnest2d; template void exportSVG(std::vector>& result, const Bin& bin, int idx = 0) { - - + + std::string loc = "out"; - + static std::string svg_header = -R"raw( + R"raw( )raw"; - + int i = idx; auto r = result; -// for(auto r : result) { - std::fstream out(loc + std::to_string(i) + ".svg", std::fstream::out); - if(out.is_open()) { - out << svg_header; - Item rbin( Rectangle(bin.width(), bin.height()) ); - for(unsigned i = 0; i < rbin.vertexCount(); i++) { - auto v = rbin.vertex(i); - setY(v, -getY(v)/SCALE + 500 ); - setX(v, getX(v)/SCALE); - rbin.setVertex(i, v); - } - out << shapelike::serialize(rbin.rawShape()) << std::endl; - for(Item& sh : r) { - Item tsh(sh.transformedShape()); - for(unsigned i = 0; i < tsh.vertexCount(); i++) { - auto v = tsh.vertex(i); - setY(v, -getY(v)/SCALE + 500); - setX(v, getX(v)/SCALE); - tsh.setVertex(i, v); - } - out << shapelike::serialize(tsh.rawShape()) << std::endl; - } - out << "\n" << std::endl; + // for(auto r : result) { + std::fstream out(loc + std::to_string(i) + ".svg", std::fstream::out); + if(out.is_open()) { + out << svg_header; + Item rbin( Rectangle(bin.width(), bin.height()) ); + for(unsigned i = 0; i < rbin.vertexCount(); i++) { + auto v = rbin.vertex(i); + setY(v, -getY(v)/SCALE + 500 ); + setX(v, getX(v)/SCALE); + rbin.setVertex(i, v); } - out.close(); - -// i++; -// } + out << shapelike::serialize(rbin.rawShape()) << std::endl; + for(Item& sh : r) { + Item tsh(sh.transformedShape()); + for(unsigned i = 0; i < tsh.vertexCount(); i++) { + auto v = tsh.vertex(i); + setY(v, -getY(v)/SCALE + 500); + setX(v, getX(v)/SCALE); + tsh.setVertex(i, v); + } + out << shapelike::serialize(tsh.rawShape()) << std::endl; + } + out << "\n" << std::endl; + } + out.close(); + + // i++; + // } } } TEST(GeometryAlgorithms, BottomLeftStressTest) { using namespace libnest2d; - + const Coord SCALE = 1000000; auto& input = prusaParts(); - + Box bin(210*SCALE, 250*SCALE); BottomLeftPlacer placer(bin); - + auto it = input.begin(); auto next = it; int i = 0; while(it != input.end() && ++next != input.end()) { placer.pack(*it); placer.pack(*next); - + auto result = placer.getItems(); bool valid = true; - + if(result.size() == 2) { Item& r1 = result[0]; Item& r2 = result[1]; @@ -525,7 +521,7 @@ TEST(GeometryAlgorithms, BottomLeftStressTest) { std::cout << "something went terribly wrong!" << std::endl; FAIL(); } - + placer.clearItems(); it++; i++; @@ -534,9 +530,9 @@ TEST(GeometryAlgorithms, BottomLeftStressTest) { TEST(GeometryAlgorithms, convexHull) { using namespace libnest2d; - + ClipperLib::Path poly = PRINTER_PART_POLYGONS[0]; - + auto chull = sl::convexHull(poly); ASSERT_EQ(chull.size(), poly.size()); @@ -545,7 +541,7 @@ TEST(GeometryAlgorithms, convexHull) { TEST(GeometryAlgorithms, NestTest) { std::vector input = prusaParts(); - + PackGroup result = libnest2d::nest(input, Box(250000000, 210000000), [](unsigned cnt) { @@ -553,16 +549,17 @@ TEST(GeometryAlgorithms, NestTest) { << "parts left: " << cnt << std::endl; }); - + ASSERT_LE(result.size(), 2); - - int partsum = std::accumulate(result.begin(), - result.end(), - 0, - [](int s, - const decltype(result)::value_type &bin) { - return s += bin.size(); - }); + + size_t partsum = std::accumulate(result.begin(), + result.end(), + size_t(0), + [](int s, + const decltype( + result)::value_type &bin) { + return s += bin.size(); + }); ASSERT_EQ(input.size(), partsum); } @@ -647,7 +644,7 @@ std::vector nfp_testdata = { {118, 101}, {117, 103}, {117, 107} - }, + }, { {102, 116}, {111, 126}, @@ -658,7 +655,7 @@ std::vector nfp_testdata = { {147, 84}, {102, 84}, {102, 116}, - } + } }, { { @@ -674,7 +671,7 @@ std::vector nfp_testdata = { {108, 70}, {99, 102}, {99, 122}, - }, + }, { {107, 124}, {128, 125}, @@ -691,7 +688,7 @@ std::vector nfp_testdata = { {108, 85}, {107, 86}, {107, 124}, - } + } }, { { @@ -706,7 +703,7 @@ std::vector nfp_testdata = { {132, 57}, {91, 98}, {91, 100}, - }, + }, { {101, 90}, {103, 98}, @@ -724,74 +721,74 @@ std::vector nfp_testdata = { {102, 87}, {101, 89}, {101, 90}, - } + } } }; -std::vector nfp_concave_testdata = { - { // ItemPair - { - { - {533726, 142141}, - {532359, 143386}, - {530141, 142155}, - {528649, 160091}, - {533659, 157607}, - {538669, 160091}, - {537178, 142155}, - {534959, 143386}, - {533726, 142141}, - } - }, - { - { - {118305, 11603}, - {118311, 26616}, - {113311, 26611}, - {109311, 29604}, - {109300, 44608}, - {109311, 49631}, - {113300, 52636}, - {118311, 52636}, - {118308, 103636}, - {223830, 103636}, - {236845, 90642}, - {236832, 11630}, - {232825, 11616}, - {210149, 11616}, - {211308, 13625}, - {209315, 17080}, - {205326, 17080}, - {203334, 13629}, - {204493, 11616}, - {118305, 11603}, - } - }, - } + std::vector nfp_concave_testdata = { + { // ItemPair + { + { + {533726, 142141}, + {532359, 143386}, + {530141, 142155}, + {528649, 160091}, + {533659, 157607}, + {538669, 160091}, + {537178, 142155}, + {534959, 143386}, + {533726, 142141}, + } + }, + { + { + {118305, 11603}, + {118311, 26616}, + {113311, 26611}, + {109311, 29604}, + {109300, 44608}, + {109311, 49631}, + {113300, 52636}, + {118311, 52636}, + {118308, 103636}, + {223830, 103636}, + {236845, 90642}, + {236832, 11630}, + {232825, 11616}, + {210149, 11616}, + {211308, 13625}, + {209315, 17080}, + {205326, 17080}, + {203334, 13629}, + {204493, 11616}, + {118305, 11603}, + } + }, + } }; template void testNfp(const std::vector& testdata) { using namespace libnest2d; - + Box bin(210*SCALE, 250*SCALE); - + int testcase = 0; - + auto& exportfun = exportSVG; - + auto onetest = [&](Item& orbiter, Item& stationary, unsigned /*testidx*/){ testcase++; - + orbiter.translate({210*SCALE, 0}); - + auto&& nfp = nfp::noFitPolygon(stationary.rawShape(), orbiter.transformedShape()); - + placers::correctNfpPosition(nfp, stationary, orbiter); - + auto valid = shapelike::isValid(nfp.first); - + /*Item infp(nfp.first); if(!valid.first) { std::cout << "test instance: " << testidx << " " @@ -799,46 +796,46 @@ void testNfp(const std::vector& testdata) { std::vector> inp = {std::ref(infp)}; exportfun(inp, bin, testidx); }*/ - + ASSERT_TRUE(valid.first); - + Item infp(nfp.first); - + int i = 0; auto rorbiter = orbiter.transformedShape(); auto vo = nfp::referenceVertex(rorbiter); - + ASSERT_TRUE(stationary.isInside(infp)); - + for(auto v : infp) { auto dx = getX(v) - getX(vo); auto dy = getY(v) - getY(vo); - + Item tmp = orbiter; - + tmp.translate({dx, dy}); - + bool touching = Item::touches(tmp, stationary); - + if(!touching || !valid.first) { std::vector> inp = { std::ref(stationary), std::ref(tmp), std::ref(infp) }; - + exportfun(inp, bin, testcase*i++); } - + ASSERT_TRUE(touching); } }; - + unsigned tidx = 0; for(auto& td : testdata) { auto orbiter = td.orbiter; auto stationary = td.stationary; onetest(orbiter, stationary, tidx++); } - + tidx = 0; for(auto& td : testdata) { auto orbiter = td.stationary; @@ -858,19 +855,19 @@ TEST(GeometryAlgorithms, nfpConvexConvex) { TEST(GeometryAlgorithms, pointOnPolygonContour) { using namespace libnest2d; - + Rectangle input(10, 10); - + placers::EdgeCache ecache(input); - + auto first = *input.begin(); ASSERT_TRUE(getX(first) == getX(ecache.coords(0))); ASSERT_TRUE(getY(first) == getY(ecache.coords(0))); - + auto last = *std::prev(input.end()); ASSERT_TRUE(getX(last) == getX(ecache.coords(1.0))); ASSERT_TRUE(getY(last) == getY(ecache.coords(1.0))); - + for(int i = 0; i <= 100; i++) { auto v = ecache.coords(i*(0.01)); ASSERT_TRUE(shapelike::touches(v, input.transformedShape())); @@ -879,24 +876,24 @@ TEST(GeometryAlgorithms, pointOnPolygonContour) { TEST(GeometryAlgorithms, mergePileWithPolygon) { using namespace libnest2d; - + Rectangle rect1(10, 15); Rectangle rect2(15, 15); Rectangle rect3(20, 15); - + rect2.translate({10, 0}); rect3.translate({25, 0}); - + TMultiShape pile; pile.push_back(rect1.transformedShape()); pile.push_back(rect2.transformedShape()); - + auto result = nfp::merge(pile, rect3.transformedShape()); - + ASSERT_EQ(result.size(), 1); - + Rectangle ref(45, 15); - + ASSERT_EQ(shapelike::area(result.front()), ref.area()); } @@ -908,7 +905,7 @@ long double refMinAreaBox(const PolygonImpl& p) { long double min_area = std::numeric_limits::max(); - + auto update_min = [&min_area, &it, &itx, &p]() { Segment s(*it, *itx); @@ -935,67 +932,39 @@ template struct BoostGCD { }; using Unit = int64_t; -using Ratio = boost::rational;// Rational; - -//double gteMinAreaBox(const PolygonImpl& p) { - -// using GteCoord = ClipperLib::cInt; -// using GtePoint = gte::Vector2; - -// gte::MinimumAreaBox2 mb; - -// std::vector points; -// points.reserve(p.Contour.size()); - -// for(auto& pt : p.Contour) points.emplace_back(GtePoint{GteCoord(pt.X), GteCoord(pt.Y)}); - -// mb(int(points.size()), points.data(), 0, nullptr, true); - -// auto min_area = double(mb.GetArea()); - -// return min_area; -//} +using Ratio = boost::rational; } TEST(RotatingCalipers, MinAreaBBCClk) { -// PolygonImpl poly({{-50, 30}, {-50, -50}, {50, -50}, {50, 50}, {-40, 50}}); - -// PolygonImpl poly({{-50, 0}, {50, 0}, {0, 100}}); - auto u = [](ClipperLib::cInt n) { return n*1000000; }; PolygonImpl poly({ {u(0), u(0)}, {u(4), u(1)}, {u(2), u(4)}}); - long double arearef = refMinAreaBox(poly); long double area = minAreaBoundingBox(poly).area(); -// double gtearea = gteMinAreaBox(poly); ASSERT_LE(std::abs(area - arearef), 500e6 ); -// ASSERT_LE(std::abs(gtearea - arearef), 500 ); -// ASSERT_DOUBLE_EQ(gtearea, arearef); } TEST(RotatingCalipers, AllPrusaMinBB) { - size_t idx = 0; + // /size_t idx = 0; long double err_epsilon = 500e6l; for(ClipperLib::Path rinput : PRINTER_PART_POLYGONS) { -// ClipperLib::Path rinput = PRINTER_PART_POLYGONS[idx]; -// rinput.pop_back(); -// std::reverse(rinput.begin(), rinput.end()); + // ClipperLib::Path rinput = PRINTER_PART_POLYGONS[idx]; + // rinput.pop_back(); + // std::reverse(rinput.begin(), rinput.end()); -// PolygonImpl poly(removeCollinearPoints(rinput, 1000000)); + // PolygonImpl poly(removeCollinearPoints(rinput, 1000000)); PolygonImpl poly(rinput); long double arearef = refMinAreaBox(poly); auto bb = minAreaBoundingBox(rinput); long double area = cast(bb.area()); -// double area = gteMinAreaBox(poly); bool succ = std::abs(arearef - area) < err_epsilon; - std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " - << arearef << " actual: " << area << std::endl; + // std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " +// << arearef << " actual: " << area << std::endl; ASSERT_TRUE(succ); } @@ -1006,21 +975,20 @@ TEST(RotatingCalipers, AllPrusaMinBB) { PolygonImpl poly(removeCollinearPoints(rinput, 1000000)); - long double arearef = refMinAreaBox(poly); auto bb = minAreaBoundingBox(poly); long double area = cast(bb.area()); -// double area = gteMinAreaBox(poly); + bool succ = std::abs(arearef - area) < err_epsilon; - std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " - << arearef << " actual: " << area << std::endl; + // std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " +// << arearef << " actual: " << area << std::endl; ASSERT_TRUE(succ); } } int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index b261a79be..df248ca5d 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -7,6 +7,9 @@ #include // for std::forward #include +#include "libslic3r.h" +#include "Point.hpp" + namespace Slic3r { /// Handy little spin mutex for the cached meshes. @@ -248,6 +251,94 @@ template inline X ceil_i(X x, Y y) return (x % y) ? x / y + 1 : x / y; } +// A shorter C++14 style form of the enable_if metafunction +template +using enable_if_t = typename std::enable_if::type; + +// ///////////////////////////////////////////////////////////////////////////// +// Type safe conversions to and from scaled and unscaled coordinates +// ///////////////////////////////////////////////////////////////////////////// + +// A meta-predicate which is true for integers wider than or equal to coord_t +template struct is_scaled_coord +{ + static const SLIC3R_CONSTEXPR bool value = + std::is_integral::value && + std::numeric_limits::digits >= + std::numeric_limits::digits; +}; + +// Meta predicates for floating, 'scaled coord' and generic arithmetic types +template +using FloatingOnly = enable_if_t::value, T>; + +template +using ScaledCoordOnly = enable_if_t::value, T>; + +template +using ArithmeticOnly = enable_if_t::value, T>; + +// A shorter form for a generic Eigen vector which is widely used in PrusaSlicer +template +using EigenVec = Eigen::Matrix; + +// Semantics are the following: +// Upscaling (scaled()): only from floating point types (or Vec) to either +// floating point or integer 'scaled coord' coordinates. +// Downscaling (unscaled()): from arithmetic types (or Vec) to either +// floating point only + +// Conversion definition from unscaled to floating point scaled +template, + class = FloatingOnly> +inline SLIC3R_CONSTEXPR Tout scaled(const Tin &v) SLIC3R_NOEXCEPT +{ + return static_cast(v / static_cast(SCALING_FACTOR)); +} + +// Conversion definition from unscaled to integer 'scaled coord'. +// TODO: is the rounding necessary ? Here it is to show that it can be different +// but it does not have to be. Using std::round means loosing noexcept and +// constexpr modifiers +template> +inline SLIC3R_CONSTEXPR ScaledCoordOnly scaled(const Tin &v) SLIC3R_NOEXCEPT +{ + //return static_cast(std::round(v / SCALING_FACTOR)); + return static_cast(v / static_cast(SCALING_FACTOR)); +} + +// Conversion for Eigen vectors (N dimensional points) +template> +inline EigenVec, N> scaled(const EigenVec &v) +{ + return v.template cast() / SCALING_FACTOR; +} + +// Conversion from arithmetic scaled type to floating point unscaled +template, + class = FloatingOnly> +inline SLIC3R_CONSTEXPR Tout unscaled(const Tin &v) SLIC3R_NOEXCEPT +{ + return static_cast(v * static_cast(SCALING_FACTOR)); +} + +// Unscaling for Eigen vectors. Input base type can be arithmetic, output base +// type can only be floating point. +template, + class = FloatingOnly> +inline SLIC3R_CONSTEXPR EigenVec unscaled( + const EigenVec &v) SLIC3R_NOEXCEPT +{ + return v.template cast() * SCALING_FACTOR; +} + } // namespace Slic3r #endif // MTUTILS_HPP diff --git a/src/libslic3r/MinAreaBoundingBox.cpp b/src/libslic3r/MinAreaBoundingBox.cpp index 6fc1b3327..fafb54a58 100644 --- a/src/libslic3r/MinAreaBoundingBox.cpp +++ b/src/libslic3r/MinAreaBoundingBox.cpp @@ -39,7 +39,7 @@ template<> inline Slic3r::Points& contour(Slic3r::Polygon& sh) { return sh.point template<> inline const Slic3r::Points& contour(const Slic3r::Polygon& sh) { return sh.points; } template<> Slic3r::Points::iterator begin(Slic3r::Points& pts, const PathTag&) { return pts.begin();} -template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.begin(); } +template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.cbegin(); } template<> Slic3r::Points::iterator end(Slic3r::Points& pts, const PathTag&) { return pts.end();} template<> Slic3r::Points::const_iterator cend(const Slic3r::Points& pts, const PathTag&) { return pts.cend(); } @@ -71,62 +71,67 @@ using Rational = boost::rational<__int128>; MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc) { - const Polygon& chull = pc == pcConvex ? p : libnest2d::sl::convexHull(p); - - libnest2d::RotatedBox box = - libnest2d::minAreaBoundingBox(chull); - - m_right = box.right_extent(); - m_bottom = box.bottom_extent(); - m_axis = box.axis(); + const Polygon &chull = pc == pcConvex ? p : + libnest2d::sl::convexHull(p); + + libnest2d::RotatedBox box = + libnest2d::minAreaBoundingBox(chull); + + m_right = libnest2d::cast(box.right_extent()); + m_bottom = libnest2d::cast(box.bottom_extent()); + m_axis = box.axis(); } MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc) { - const ExPolygon& chull = pc == pcConvex ? p : libnest2d::sl::convexHull(p); - - libnest2d::RotatedBox box = - libnest2d::minAreaBoundingBox(chull); - - m_right = box.right_extent(); - m_bottom = box.bottom_extent(); - m_axis = box.axis(); + const ExPolygon &chull = pc == pcConvex ? p : + libnest2d::sl::convexHull(p); + + libnest2d::RotatedBox box = + libnest2d::minAreaBoundingBox(chull); + + m_right = libnest2d::cast(box.right_extent()); + m_bottom = libnest2d::cast(box.bottom_extent()); + m_axis = box.axis(); } MinAreaBoundigBox::MinAreaBoundigBox(const Points &pts, PolygonLevel pc) { - const Points& chull = pc == pcConvex ? pts : libnest2d::sl::convexHull(pts); - - libnest2d::RotatedBox box = - libnest2d::minAreaBoundingBox(chull); - - m_right = box.right_extent(); - m_bottom = box.bottom_extent(); - m_axis = box.axis(); + const Points &chull = pc == pcConvex ? pts : + libnest2d::sl::convexHull(pts); + + libnest2d::RotatedBox box = + libnest2d::minAreaBoundingBox(chull); + + m_right = libnest2d::cast(box.right_extent()); + m_bottom = libnest2d::cast(box.bottom_extent()); + m_axis = box.axis(); } double MinAreaBoundigBox::angle_to_X() const { double ret = std::atan2(m_axis.y(), m_axis.x()); - auto s = std::signbit(ret); - if(s) ret += 2 * PI; + auto s = std::signbit(ret); + if (s) ret += 2 * PI; return -ret; } long double MinAreaBoundigBox::width() const { - return std::abs(m_bottom) / std::sqrt(libnest2d::pl::magnsq(m_axis)); + return std::abs(m_bottom) / + std::sqrt(libnest2d::pl::magnsq(m_axis)); } long double MinAreaBoundigBox::height() const { - return std::abs(m_right) / std::sqrt(libnest2d::pl::magnsq(m_axis)); + return std::abs(m_right) / + std::sqrt(libnest2d::pl::magnsq(m_axis)); } long double MinAreaBoundigBox::area() const { long double asq = libnest2d::pl::magnsq(m_axis); - return m_bottom * m_right / asq; + return m_bottom * m_right / asq; } void remove_collinear_points(Polygon &p) @@ -138,5 +143,4 @@ void remove_collinear_points(ExPolygon &p) { p = libnest2d::removeCollinearPoints(p, Unit(0)); } - -} +} // namespace Slic3r diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index 36f7e3971..bc0f933d1 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -610,7 +610,7 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model, if(tolerance > EPSILON) { Polygons pp { p }; - pp = p.simplify(double(scaled(tolerance))); + pp = p.simplify(scaled(tolerance)); if (!pp.empty()) p = pp.front(); } diff --git a/src/libslic3r/SLA/SLABasePool.cpp b/src/libslic3r/SLA/SLABasePool.cpp index 3b199c4eb..04cbd7824 100644 --- a/src/libslic3r/SLA/SLABasePool.cpp +++ b/src/libslic3r/SLA/SLABasePool.cpp @@ -5,6 +5,7 @@ #include "SLABoostAdapter.hpp" #include "ClipperUtils.hpp" #include "Tesselate.hpp" +#include "MTUtils.hpp" // For debugging: //#include @@ -203,7 +204,7 @@ void offset(ExPolygon& sh, coord_t distance) { } ClipperOffset offs; - offs.ArcTolerance = 0.01*scaled(1.0); + offs.ArcTolerance = scaled(0.01); Paths result; offs.AddPath(ctour, jtRound, etClosedPolygon); offs.AddPaths(holes, jtRound, etClosedPolygon); @@ -351,7 +352,7 @@ Contour3D round_edges(const ExPolygon& base_plate, double x2 = xx*xx; double stepy = std::sqrt(r2 - x2); - offset(ob, s*scaled(xx)); + offset(ob, s * scaled(xx)); wh = ceilheight_mm - radius_mm + stepy; Contour3D pwalls; @@ -375,7 +376,7 @@ Contour3D round_edges(const ExPolygon& base_plate, double xx = radius_mm - i*stepx; double x2 = xx*xx; double stepy = std::sqrt(r2 - x2); - offset(ob, s*scaled(xx)); + offset(ob, s * scaled(xx)); wh = ceilheight_mm - radius_mm - stepy; Contour3D pwalls; @@ -476,7 +477,7 @@ ExPolygons concave_hull(const ExPolygons& polys, double max_dist_mm = 50, double dx = x(c) - x(cc), dy = y(c) - y(cc); double l = std::sqrt(dx * dx + dy * dy); double nx = dx / l, ny = dy / l; - double max_dist = scaled(max_dist_mm); + double max_dist = scaled(max_dist_mm); ExPolygon& expo = punion[idx++]; BoundingBox querybb(expo); @@ -492,7 +493,7 @@ ExPolygons concave_hull(const ExPolygons& polys, double max_dist_mm = 50, ctour.reserve(3); ctour.emplace_back(cc); - Point d(coord_t(scaled(1.)*nx), coord_t(scaled(1.)*ny)); + Point d(scaled(nx), scaled(ny)); ctour.emplace_back(c + Point( -y(d), x(d) )); ctour.emplace_back(c + Point( y(d), -x(d) )); offset(r, scaled(1.)); @@ -529,14 +530,14 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h, ExPolygons tmp; tmp.reserve(count); for(ExPolygons& o : out) for(ExPolygon& e : o) { - auto&& exss = e.simplify(scaled(0.1)); + auto&& exss = e.simplify(scaled(0.1)); for(ExPolygon& ep : exss) tmp.emplace_back(std::move(ep)); } ExPolygons utmp = unify(tmp); for(auto& o : utmp) { - auto&& smp = o.simplify(scaled(0.1)); + auto&& smp = o.simplify(scaled(0.1)); output.insert(output.end(), smp.begin(), smp.end()); } } diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index c73ae5650..7ae481ffb 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -668,7 +668,7 @@ void SLAPrint::process() double ilhd = m_material_config.initial_layer_height.getFloat(); auto ilh = float(ilhd); - auto ilhs = scaled(ilhd); + coord_t ilhs = scaled(ilhd); const size_t objcount = m_objects.size(); static const unsigned min_objstatus = 0; // where the per object operations start @@ -694,17 +694,15 @@ void SLAPrint::process() // We need to prepare the slice index... - double lhd = m_objects.front()->m_config.layer_height.getFloat(); - float lh = float(lhd); - auto lhs = scaled(lhd); - - auto &&bb3d = mesh.bounding_box(); - double minZ = bb3d.min(Z) - po.get_elevation(); - double maxZ = bb3d.max(Z); - auto minZf = float(minZ); - - auto minZs = scaled(minZ); - auto maxZs = scaled(maxZ); + double lhd = m_objects.front()->m_config.layer_height.getFloat(); + float lh = float(lhd); + coord_t lhs = scaled(lhd); + auto && bb3d = mesh.bounding_box(); + double minZ = bb3d.min(Z) - po.get_elevation(); + double maxZ = bb3d.max(Z); + auto minZf = float(minZ); + coord_t minZs = scaled(minZ); + coord_t maxZs = scaled(maxZ); po.m_slice_index.clear(); @@ -1013,9 +1011,6 @@ void SLAPrint::process() using ClipperPolygons = std::vector; namespace sl = libnest2d::shapelike; // For algorithms - // If the raster has vertical orientation, we will flip the coordinates -// bool flpXY = m_printer_config.display_orientation.getInt() == SLADisplayOrientation::sladoPortrait; - // Set up custom union and diff functions for clipper polygons auto polyunion = [] (const ClipperPolygons& subjects) { @@ -1066,8 +1061,8 @@ void SLAPrint::process() const int fade_layers_cnt = m_default_object_config.faded_layers.getInt();// 10 // [3;20] - const double width = scaled(m_printer_config.display_width.getFloat()); - const double height = scaled(m_printer_config.display_height.getFloat()); + const auto width = scaled(m_printer_config.display_width.getFloat()); + const auto height = scaled(m_printer_config.display_height.getFloat()); const double display_area = width*height; // get polygons for all instances in the object @@ -1123,11 +1118,6 @@ void SLAPrint::process() sl::translate(poly, ClipperPoint{instances[i].shift(X), instances[i].shift(Y)}); -// if (flpXY) { -// for(auto& p : poly.Contour) std::swap(p.X, p.Y); -// for(auto& h : poly.Holes) for(auto& p : h) std::swap(p.X, p.Y); -// } - polygons.emplace_back(std::move(poly)); } } diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 8cafae17c..dc2b6a4ec 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -61,20 +61,6 @@ typedef double coordf_t; #define SLIC3R_NOEXCEPT noexcept #endif -template inline SLIC3R_CONSTEXPR coord_t scaled(Tf val) -{ - static_assert (std::is_floating_point::value, "Floating point only"); - return coord_t(val / Tf(SCALING_FACTOR)); -} - -template inline SLIC3R_CONSTEXPR Tf unscaled(coord_t val) -{ - static_assert (std::is_floating_point::value, "Floating point only"); - return Tf(val * Tf(SCALING_FACTOR)); -} - -inline SLIC3R_CONSTEXPR float unscaledf(coord_t val) { return unscaled(val); } - inline std::string debug_out_path(const char *name, ...) { char buffer[2048]; From 6ff434aba3367e2111b1ff809ea744ca39347a56 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jun 2019 11:10:41 +0200 Subject: [PATCH 52/83] Fixes some ModelArrange warnings --- src/libslic3r/MTUtils.hpp | 9 --------- src/libslic3r/ModelArrange.cpp | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index df248ca5d..70603cd15 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -242,15 +242,6 @@ template bool all_of(const C &container) }); } -template inline X ceil_i(X x, Y y) -{ - static_assert(std::is_integral::value && - std::is_integral::value && sizeof(X) >= sizeof(Y), - ""); - - return (x % y) ? x / y + 1 : x / y; -} - // A shorter C++14 style form of the enable_if metafunction template using enable_if_t = typename std::enable_if::type; diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp index bc0f933d1..db36653b0 100644 --- a/src/libslic3r/ModelArrange.cpp +++ b/src/libslic3r/ModelArrange.cpp @@ -62,10 +62,10 @@ std::string toString(const Model& model, bool holes = true) { objinst->transform_mesh(&tmpmesh); ExPolygons expolys = tmpmesh.horizontal_projection(); for(auto& expoly_complex : expolys) { - - auto tmp = expoly_complex.simplify(1.0/SCALING_FACTOR); + + ExPolygons tmp = expoly_complex.simplify(scaled(1.)); if(tmp.empty()) continue; - auto expoly = tmp.front(); + ExPolygon expoly = tmp.front(); expoly.contour.make_clockwise(); for(auto& h : expoly.holes) h.make_counter_clockwise(); @@ -633,8 +633,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model, if(item.vertexCount() > 3) { item.rotation(Geometry::rotation_diff_z(rotation0, objinst->get_rotation())); item.translation({ - ClipperLib::cInt(objinst->get_offset(X)/SCALING_FACTOR), - ClipperLib::cInt(objinst->get_offset(Y)/SCALING_FACTOR) + scaled(objinst->get_offset(X)), + scaled(objinst->get_offset(Y)) }); ret.emplace_back(objinst, item); } @@ -658,8 +658,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model, Item item(std::move(pn)); item.rotation(wti.rotation), item.translation({ - ClipperLib::cInt(wti.pos(0)/SCALING_FACTOR), - ClipperLib::cInt(wti.pos(1)/SCALING_FACTOR) + scaled(wti.pos(0)), + scaled(wti.pos(1)) }); ret.emplace_back(nullptr, item); } @@ -822,7 +822,9 @@ bool arrange(Model &model, // The model with the geometries auto& cfn = stopcondition; - coord_t md = ceil_i(min_obj_distance, 2) - SCALED_EPSILON; + // Integer ceiling the min distance from the bed perimeters + coord_t md = min_obj_distance - SCALED_EPSILON; + md = (md % 2) ? md / 2 + 1 : md / 2; auto binbb = Box({libnest2d::Coord{bbb.min(0)} - md, libnest2d::Coord{bbb.min(1)} - md}, From d845332de1e393e7a0d7f37379f6de0a31b4ee82 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 26 Jun 2019 11:49:02 +0200 Subject: [PATCH 53/83] Fixed a crash when using place to bed function with the layer editing active This was caused by trying to render a deleted layer height profile. Other gizmos were not affected because they are not dragging at the time of their action, so the profile was correctly recalculated for them. --- src/slic3r/GUI/GLCanvas3D.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c828e0ec6..bed3b754b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -457,8 +457,10 @@ void GLCanvas3D::LayersEditing::_render_profile(const Rect& bar_rect) const { //FIXME show some kind of legend. + if (!m_slicing_parameters) + return; + // Make the vertical bar a bit wider so the layer height curve does not touch the edge of the bar region. - assert(m_slicing_parameters != nullptr); float scale_x = bar_rect.get_width() / (float)(1.12 * m_slicing_parameters->max_layer_height); float scale_y = bar_rect.get_height() / m_object_max_z; float x = bar_rect.get_left() + (float)m_slicing_parameters->layer_height * scale_x; From d2136ab6253ced47b6ccca2a9256fb265083d734 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 26 Jun 2019 13:12:25 +0200 Subject: [PATCH 54/83] ObjectList no longer caps number of extruders to 9 (fixes https://github.com/prusa3d/PrusaSlicer/issues/2558) --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index d7d1a1af7..e926dcf97 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -460,7 +460,7 @@ void ObjectList::update_extruder_in_config(const wxDataViewItem& item) if (!m_config || selection.empty()) return; - const int extruder = selection.size() > 1 ? 0 : atoi(selection.c_str()); + const int extruder = /*selection.size() > 1 ? 0 : */atoi(selection.c_str()); m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); // update scene From 7e52edb88c411339a0203df3049029f4394b8d7d Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jun 2019 13:23:08 +0200 Subject: [PATCH 55/83] Try to supress warnings from bundled IGL under Windows. --- src/libigl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libigl/CMakeLists.txt b/src/libigl/CMakeLists.txt index 0852fad72..3daac757b 100644 --- a/src/libigl/CMakeLists.txt +++ b/src/libigl/CMakeLists.txt @@ -10,5 +10,5 @@ if(libigl_FOUND) target_link_libraries(libigl INTERFACE igl::core) else() message(STATUS "IGL NOT found, using bundled version...") - target_include_directories(libigl INTERFACE SYSTEM ${LIBDIR}/libigl) + target_include_directories(libigl SYSTEM BEFORE INTERFACE ${LIBDIR}/libigl) endif() From 624a6aefb4b9dc73aae2e5e95cecd62fc1a78f56 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 26 Jun 2019 13:29:49 +0200 Subject: [PATCH 56/83] Fixed crashes after loading some AMFs. --- src/libslic3r/Model.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 596f80671..9d68f7141 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1564,8 +1564,10 @@ void ModelVolume::center_geometry_after_creation() Vec3d shift = this->mesh().bounding_box().center(); if (!shift.isApprox(Vec3d::Zero())) { - m_mesh->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2)); - m_convex_hull->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2)); + if (m_mesh) + m_mesh->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2)); + if (m_convex_hull) + m_convex_hull->translate(-(float)shift(0), -(float)shift(1), -(float)shift(2)); translate(shift); } } From 104a289cfe48d20cfdea03cac0e10c1e7ca7beee Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 26 Jun 2019 13:30:20 +0200 Subject: [PATCH 57/83] Implemented interface for updating 3DScene after set a focus to some editor --- src/slic3r/GUI/GLCanvas3D.cpp | 5 +++ src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/GUI_ObjectLayers.cpp | 50 ++++++++++++++++++----------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 16 ++++++--- 4 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ffaa2d20c..138946166 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3310,6 +3310,11 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc } } +void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type) +{ + printf("min_z = %.2f, max_z = %.2f, type=%d\n", range.first, range.second, type); +} + void GLCanvas3D::update_ui_from_settings() { #if ENABLE_RETINA_GL diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d39a910b3..95fd123eb 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -12,6 +12,7 @@ #include "Camera.hpp" #include "Selection.hpp" #include "Gizmos/GLGizmosManager.hpp" +#include "GUI_ObjectLayers.hpp" #include @@ -606,6 +607,7 @@ public: void reset_all_gizmos() { m_gizmos.reset_all_states(); } void handle_sidebar_focus_event(const std::string& opt_key, bool focus_on); + void handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type); void update_ui_from_settings(); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index 1426ccf02..d854e54b3 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -4,6 +4,7 @@ #include "OptionsGroup.hpp" #include "PresetBundle.hpp" #include "libslic3r/Model.hpp" +#include "GLCanvas3D.hpp" #include @@ -62,13 +63,13 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) { const bool is_last_edited_range = range == m_selectable_range; - auto set_focus_fn = [range, this](const EditorType type) + auto set_focus_data = [range, this](const EditorType type) { m_selectable_range = range; m_selection_type = type; }; - auto set_focus = [range, this](const t_layer_height_range& new_range, EditorType type, bool enter_pressed) + auto update_focus_data = [range, this](const t_layer_height_range& new_range, EditorType type, bool enter_pressed) { // change selectable range for new one, if enter was pressed or if same range was selected if (enter_pressed || m_selectable_range == range) @@ -79,8 +80,8 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // Add control for the "Min Z" - auto editor = new LayerRangeEditor(m_parent, double_to_string(range.first), etMinZ, - set_focus_fn, [range, set_focus, this](coordf_t min_z, bool enter_pressed) + auto editor = new LayerRangeEditor(this, double_to_string(range.first), etMinZ, + set_focus_data, [range, update_focus_data, this](coordf_t min_z, bool enter_pressed) { if (fabs(min_z - range.first) < EPSILON) { m_selection_type = etUndef; @@ -89,8 +90,8 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // data for next focusing coordf_t max_z = min_z < range.second ? range.second : min_z + 0.5; - const t_layer_height_range& new_range = { min_z, max_z/*range.second*/ }; - set_focus(new_range, etMinZ, enter_pressed); + const t_layer_height_range& new_range = { min_z, max_z }; + update_focus_data(new_range, etMinZ, enter_pressed); return wxGetApp().obj_list()->edit_layer_range(range, new_range); }); @@ -100,8 +101,8 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // Add control for the "Max Z" - editor = new LayerRangeEditor(m_parent, double_to_string(range.second), etMaxZ, - set_focus_fn, [range, set_focus, this](coordf_t max_z, bool enter_pressed) + editor = new LayerRangeEditor(this, double_to_string(range.second), etMaxZ, + set_focus_data, [range, update_focus_data, this](coordf_t max_z, bool enter_pressed) { if (fabs(max_z - range.second) < EPSILON || range.first > max_z) { m_selection_type = etUndef; @@ -110,7 +111,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // data for next focusing const t_layer_height_range& new_range = { range.first, max_z }; - set_focus(new_range, etMaxZ, enter_pressed); + update_focus_data(new_range, etMaxZ, enter_pressed); return wxGetApp().obj_list()->edit_layer_range(range, new_range); }); @@ -120,9 +121,9 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range) // Add control for the "Layer height" - editor = new LayerRangeEditor(m_parent, + editor = new LayerRangeEditor(this, double_to_string(m_object->layer_config_ranges[range].option("layer_height")->getFloat()), - etLayerHeight, set_focus_fn, [range, this](coordf_t layer_height, bool) + etLayerHeight, set_focus_data, [range, this](coordf_t layer_height, bool) { return wxGetApp().obj_list()->edit_layer_range(range, layer_height); }); @@ -203,6 +204,12 @@ void ObjectLayers::update_layers_list() m_parent->Layout(); } +void ObjectLayers::update_scene_from_editor_selection() const +{ + // needed to show the visual hints in 3D scene + wxGetApp().plater()->canvas3D()->handle_layers_data_focus_event(m_selectable_range, m_selection_type); +} + void ObjectLayers::UpdateAndShow(const bool show) { if (show) @@ -217,17 +224,17 @@ void ObjectLayers::msw_rescale() m_bmp_add.msw_rescale(); } -LayerRangeEditor::LayerRangeEditor( wxWindow* parent, +LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, const wxString& value, EditorType type, - std::function set_focus_fn, + std::function set_focus_data_fn, std::function edit_fn ) : m_valid_value(value), m_type(type), - m_set_focus(set_focus_fn), - wxTextCtrl(parent, wxID_ANY, value, wxDefaultPosition, - wxSize(8 * em_unit(parent), wxDefaultCoord), wxTE_PROCESS_ENTER) + m_set_focus_data(set_focus_data_fn), + wxTextCtrl(parent->m_parent, wxID_ANY, value, wxDefaultPosition, + wxSize(8 * em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER) { this->SetFont(wxGetApp().normal_font()); @@ -258,7 +265,7 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, * */ LayerRangeEditor* new_editor = dynamic_cast(e.GetWindow()); if (new_editor) - new_editor->set_focus(); + new_editor->set_focus_data(); #endif // not __WXGTK__ // If LayersList wasn't updated/recreated, we should call e.Skip() if (m_type & etLayerHeight) { @@ -279,10 +286,17 @@ LayerRangeEditor::LayerRangeEditor( wxWindow* parent, } }, this->GetId()); + this->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e) + { + set_focus_data(); + parent->update_scene_from_editor_selection(); + e.Skip(); + }, this->GetId()); + #ifdef __WXGTK__ // Workaround! To take information about selectable range this->Bind(wxEVT_LEFT_DOWN, [this](wxEvent& e) { - set_focus(); + set_focus_data(); e.Skip(); }, this->GetId()); #endif //__WXGTK__ diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index e3366e03e..f19217fbe 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -19,6 +19,8 @@ class ConfigOptionsGroup; typedef double coordf_t; typedef std::pair t_layer_height_range; +class ObjectLayers; + enum EditorType { etUndef = 0, @@ -34,19 +36,19 @@ class LayerRangeEditor : public wxTextCtrl wxString m_valid_value; EditorType m_type; - std::function m_set_focus; + std::function m_set_focus_data; public: - LayerRangeEditor( wxWindow* parent, + LayerRangeEditor( ObjectLayers* parent, const wxString& value = wxEmptyString, EditorType type = etUndef, - std::function set_focus_fn = [](EditorType) {;}, - std::function edit_fn = [](coordf_t, bool) {return false; } + std::function set_focus_data_fn = [](EditorType) {;}, + std::function edit_fn = [](coordf_t, bool) {return false; } ); ~LayerRangeEditor() {} EditorType type() const {return m_type;} - void set_focus() const { m_set_focus(m_type);} + void set_focus_data() const { m_set_focus_data(m_type);} private: coordf_t get_value(); @@ -71,8 +73,12 @@ public: void create_layers_list(); void update_layers_list(); + void update_scene_from_editor_selection() const; + void UpdateAndShow(const bool show) override; void msw_rescale(); + + friend class LayerRangeEditor; }; }} From a07088a8d99499ef3dd770fb95a83d52e10b60b5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 26 Jun 2019 14:25:05 +0200 Subject: [PATCH 58/83] #2561 - Fixed freezing of perspective camera when zooming-in --- src/slic3r/GUI/Camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 6cb8ff520..242d00a07 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -24,7 +24,7 @@ namespace GUI { const double Camera::DefaultDistance = 1000.0; double Camera::FrustrumMinZSize = 50.0; double Camera::FrustrumZMargin = 10.0; -double Camera::FovMinDeg = 5.0; +double Camera::FovMinDeg = 0.5; double Camera::FovMaxDeg = 75.0; Camera::Camera() From dd108f4513c8dcd105dfd8ecd399c36eaa615cfe Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jun 2019 14:59:39 +0200 Subject: [PATCH 59/83] Hotfix for inconsistent slice index --- src/libslic3r/MTUtils.hpp | 4 ++-- src/libslic3r/SLAPrint.cpp | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index 70603cd15..ce26887f2 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -286,7 +286,7 @@ template> inline SLIC3R_CONSTEXPR Tout scaled(const Tin &v) SLIC3R_NOEXCEPT { - return static_cast(v / static_cast(SCALING_FACTOR)); + return static_cast(v / static_cast(SCALING_FACTOR)); } // Conversion definition from unscaled to integer 'scaled coord'. @@ -297,7 +297,7 @@ template> inline SLIC3R_CONSTEXPR ScaledCoordOnly scaled(const Tin &v) SLIC3R_NOEXCEPT { //return static_cast(std::round(v / SCALING_FACTOR)); - return static_cast(v / static_cast(SCALING_FACTOR)); + return static_cast(v / static_cast(SCALING_FACTOR)); } // Conversion for Eigen vectors (N dimensional points) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 7ae481ffb..1902e74ae 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -720,8 +720,9 @@ void SLAPrint::process() if(slindex_it == po.m_slice_index.end()) //TRN To be shown at the status bar on SLA slicing error. - throw std::runtime_error(L("Slicing had to be stopped " - "due to an internal error.")); + throw std::runtime_error( + L("Slicing had to be stopped due to an internal error: " + "Inconsistent slice index.")); po.m_model_height_levels.clear(); po.m_model_height_levels.reserve(po.m_slice_index.size()); From 74b420d608623793f00a94f1cde97c3c1e3c0306 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jun 2019 17:06:41 +0200 Subject: [PATCH 60/83] Remove option for igl static build due to Eigen version mismatch . --- deps/CMakeLists.txt | 9 +++++---- deps/deps-unix-common.cmake | 2 +- deps/deps-windows.cmake | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 5bc33c896..d8e72370b 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -36,10 +36,11 @@ set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir" CACHE PATH "Destination direct option(DEP_DEBUG "Build debug variants (only applicable on Windows)" ON) option(DEP_WX_STABLE "Build against wxWidgets stable 3.0 as opposed to default 3.1 (Linux only)" OFF) -# IGL static library in release mode produces 50MB binary. On the build server, it should be -# disabled and used in header-only mode. On developer machines, it can be enabled to speed -# up conpilation and suppress warnings coming from IGL. -option(DEP_BUILD_IGL_STATIC "Build IGL as a static library. Might cause link errors and increase binary size." OFF) +# On developer machines, it can be enabled to speed up compilation and suppress warnings coming from IGL. +# FIXME: +# Enabling this option is not safe. IGL will compile itself with its own version of Eigen while +# Slic3r compiles with a different version which will cause runtime errors. +# option(DEP_BUILD_IGL_STATIC "Build IGL as a static library. Might cause link errors and increase binary size." OFF) message(STATUS "PrusaSlicer deps DESTDIR: ${DESTDIR}") message(STATUS "PrusaSlicer deps debug build: ${DEP_DEBUG}") diff --git a/deps/deps-unix-common.cmake b/deps/deps-unix-common.cmake index c44a6ec20..3614e9444 100644 --- a/deps/deps-unix-common.cmake +++ b/deps/deps-unix-common.cmake @@ -54,7 +54,7 @@ ExternalProject_Add(dep_libigl -DLIBIGL_BUILD_PYTHON=OFF -DLIBIGL_BUILD_TESTS=OFF -DLIBIGL_BUILD_TUTORIALS=OFF - -DLIBIGL_USE_STATIC_LIBRARY=${DEP_BUILD_IGL_STATIC} + -DLIBIGL_USE_STATIC_LIBRARY=OFF #${DEP_BUILD_IGL_STATIC} -DLIBIGL_WITHOUT_COPYLEFT=OFF -DLIBIGL_WITH_CGAL=OFF -DLIBIGL_WITH_COMISO=OFF diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index d7daf8425..0b3fcb13c 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -264,7 +264,7 @@ ExternalProject_Add(dep_libigl -DLIBIGL_BUILD_PYTHON=OFF -DLIBIGL_BUILD_TESTS=OFF -DLIBIGL_BUILD_TUTORIALS=OFF - -DLIBIGL_USE_STATIC_LIBRARY=${DEP_BUILD_IGL_STATIC} + -DLIBIGL_USE_STATIC_LIBRARY=OFF #${DEP_BUILD_IGL_STATIC} -DLIBIGL_WITHOUT_COPYLEFT=OFF -DLIBIGL_WITH_CGAL=OFF -DLIBIGL_WITH_COMISO=OFF From ec28e55ff00617b711cd46f0302d93219e3c3702 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 26 Jun 2019 18:03:13 +0200 Subject: [PATCH 61/83] Get rid of the test.cpp warning --- src/libnest2d/tests/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnest2d/tests/test.cpp b/src/libnest2d/tests/test.cpp index 363a3930c..2f2b9beb5 100644 --- a/src/libnest2d/tests/test.cpp +++ b/src/libnest2d/tests/test.cpp @@ -555,7 +555,7 @@ TEST(GeometryAlgorithms, NestTest) { size_t partsum = std::accumulate(result.begin(), result.end(), size_t(0), - [](int s, + [](size_t s, const decltype( result)::value_type &bin) { return s += bin.size(); From da3583b1db45ede894b5c6345b3fb853b0bb6eac Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 27 Jun 2019 09:48:19 +0200 Subject: [PATCH 62/83] Fix of https://github.com/prusa3d/PrusaSlicer/issues/2516 --- src/libslic3r/Config.cpp | 8 ++++---- src/libslic3r/Config.hpp | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 0738b77c6..76329ccee 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -732,18 +732,18 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra, } // Store the option value. const bool existing = this->has(opt_key); - if (keys != nullptr && !existing) { + if (keys != nullptr && ! existing) { // Save the order of detected keys. keys->push_back(opt_key); } ConfigOption *opt_base = this->option(opt_key, true); ConfigOptionVectorBase *opt_vector = opt_base->is_vector() ? static_cast(opt_base) : nullptr; if (opt_vector) { + if (! existing) + // remove the default values + opt_vector->clear(); // Vector values will be chained. Repeated use of a parameter will append the parameter or parameters // to the end of the value. - if (!existing) - // remove the default values - opt_vector->deserialize("", true); if (opt_base->type() == coBools) static_cast(opt_base)->values.push_back(!no); else diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index ee4bc4e46..a7192a558 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -167,8 +167,10 @@ public: // Set a single vector item from either a scalar option or the first value of a vector option.vector of ConfigOptions. // This function is useful to split values from multiple extrder / filament settings into separate configurations. virtual void set_at(const ConfigOption *rhs, size_t i, size_t j) = 0; - + // Resize the vector of values, copy the newly added values from opt_default if provided. virtual void resize(size_t n, const ConfigOption *opt_default = nullptr) = 0; + // Clear the values vector. + virtual void clear() = 0; // Get size of this vector. virtual size_t size() const = 0; @@ -277,6 +279,8 @@ public: } } + // Clear the values vector. + void clear() override { this->values.clear(); } size_t size() const override { return this->values.size(); } bool empty() const override { return this->values.empty(); } From 90d1ac2c8f67329ae2cfeee9bf8ce24086db923a Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 27 Jun 2019 11:25:04 +0200 Subject: [PATCH 63/83] Tech ENABLE_RENDER_PICKING_PASS extended so that user can switch between picking pass texture rendering and regular rendering by pressing [T] key --- src/libslic3r/Technologies.hpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 20 ++++++++++++++++++-- src/slic3r/GUI/GLCanvas3D.hpp | 4 ++++ src/slic3r/GUI/KBShortcutsDialog.cpp | 3 +++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 86a00480b..f05bc0b57 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -15,7 +15,7 @@ #define ENABLE_RENDER_STATISTICS 0 // Shows an imgui dialog with camera related data #define ENABLE_CAMERA_STATISTICS 0 -// Render the picking pass instead of the main scene +// Render the picking pass instead of the main scene (use [T] key to toggle between regular rendering and picking pass only rendering) #define ENABLE_RENDER_PICKING_PASS 0 diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c3fd020e0..9bb6f4553 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1224,6 +1224,9 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar , m_cursor_type(Standard) , m_color_by("volume") , m_reload_delayed(false) +#if ENABLE_RENDER_PICKING_PASS + , m_show_picking_texture(false) +#endif // ENABLE_RENDER_PICKING_PASS , m_render_sla_auxiliaries(true) { if (m_canvas != nullptr) { @@ -1627,7 +1630,10 @@ void GLCanvas3D::render() _picking_pass(); } -#if !ENABLE_RENDER_PICKING_PASS +#if ENABLE_RENDER_PICKING_PASS + if (!m_picking_enabled || !m_show_picking_texture) + { +#endif // ENABLE_RENDER_PICKING_PASS // draw scene glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); _render_background(); @@ -1657,7 +1663,9 @@ void GLCanvas3D::render() _render_current_gizmo(); _render_selection_sidebar_hints(); -#endif // !ENABLE_RENDER_PICKING_PASS +#if ENABLE_RENDER_PICKING_PASS + } +#endif // ENABLE_RENDER_PICKING_PASS #if ENABLE_SHOW_CAMERA_TARGET _render_camera_target(); @@ -2399,6 +2407,14 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'k': { m_camera.select_next_type(); m_dirty = true; break; } case 'O': case 'o': { set_camera_zoom(-1.0); break; } +#if ENABLE_RENDER_PICKING_PASS + case 'T': + case 't': { + m_show_picking_texture = !m_show_picking_texture; + m_dirty = true; + break; + } +#endif // ENABLE_RENDER_PICKING_PASS case 'Z': case 'z': { m_selection.is_empty() ? zoom_to_volumes() : zoom_to_selection(); break; } default: { evt.Skip(); break; } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 5a4287903..c891ed06f 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -477,6 +477,10 @@ private: GCodePreviewVolumeIndex m_gcode_preview_volume_index; +#if ENABLE_RENDER_PICKING_PASS + bool m_show_picking_texture; +#endif // ENABLE_RENDER_PICKING_PASS + #if ENABLE_RENDER_STATISTICS RenderStats m_render_stats; #endif // ENABLE_RENDER_STATISTICS diff --git a/src/slic3r/GUI/KBShortcutsDialog.cpp b/src/slic3r/GUI/KBShortcutsDialog.cpp index 1af658ed3..955c4b60b 100644 --- a/src/slic3r/GUI/KBShortcutsDialog.cpp +++ b/src/slic3r/GUI/KBShortcutsDialog.cpp @@ -154,6 +154,9 @@ void KBShortcutsDialog::fill_shortcuts() plater_shortcuts.push_back(Shortcut("I", L("Zoom in"))); plater_shortcuts.push_back(Shortcut("O", L("Zoom out"))); plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo / Clear selection"))); +#if ENABLE_RENDER_PICKING_PASS + plater_shortcuts.push_back(Shortcut("T", L("Toggle picking pass texture rendering on/off"))); +#endif // ENABLE_RENDER_PICKING_PASS m_full_shortcuts.push_back(std::make_pair(_(L("Plater Shortcuts")), std::make_pair(plater_shortcuts, szRight))); From 1058721dba84f0c7e35a34d7b7b23382004307c1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 27 Jun 2019 13:42:50 +0200 Subject: [PATCH 64/83] Added visual hints in 3D scene for layers editing --- src/slic3r/GUI/GLCanvas3D.cpp | 11 +- src/slic3r/GUI/GUI_ObjectLayers.cpp | 2 + src/slic3r/GUI/Selection.cpp | 154 +++++++++++++++++++++------- src/slic3r/GUI/Selection.hpp | 5 +- 4 files changed, 126 insertions(+), 46 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 60afcb653..bdfd0507a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3307,7 +3307,8 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type) { - printf("min_z = %.2f, max_z = %.2f, type=%d\n", range.first, range.second, type); + std::string field = "layer_" + std::to_string(type) + "_" + std::to_string(range.first) + "_" + std::to_string(range.second); + handle_sidebar_focus_event(field, true); } void GLCanvas3D::update_ui_from_settings() @@ -4275,13 +4276,7 @@ void GLCanvas3D::_render_sla_slices() const void GLCanvas3D::_render_selection_sidebar_hints() const { - if (m_use_VBOs) - m_shader.start_using(); - - m_selection.render_sidebar_hints(m_sidebar_field); - - if (m_use_VBOs) - m_shader.stop_using(); + m_selection.render_sidebar_hints(m_sidebar_field, m_shader); } diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index d854e54b3..ff0f55aef 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -257,6 +257,8 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e) { + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); + if (!m_enter_pressed) { #ifndef __WXGTK__ /* Update data for next editor selection. diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index c6c85e21f..82bc52d3a 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1070,61 +1070,68 @@ void Selection::render_center(bool gizmo_is_dragging) const } #endif // ENABLE_RENDER_SELECTION_CENTER -void Selection::render_sidebar_hints(const std::string& sidebar_field) const +void Selection::render_sidebar_hints(const std::string& sidebar_field, const Shader& shader) const { if (sidebar_field.empty()) return; - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - glsafe(::glEnable(GL_DEPTH_TEST)); + if (!boost::starts_with(sidebar_field, "layer")) + { + shader.start_using(); + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + glsafe(::glEnable(GL_LIGHTING)); + } - glsafe(::glEnable(GL_LIGHTING)); + glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glPushMatrix()); - const Vec3d& center = get_bounding_box().center(); - - if (is_single_full_instance() && ! wxGetApp().obj_manipul()->get_world_coordinates()) + if (!boost::starts_with(sidebar_field, "layer")) { - glsafe(::glTranslated(center(0), center(1), center(2))); - if (!boost::starts_with(sidebar_field, "position")) + const Vec3d& center = get_bounding_box().center(); + + if (is_single_full_instance() && !wxGetApp().obj_manipul()->get_world_coordinates()) { - Transform3d orient_matrix = Transform3d::Identity(); - if (boost::starts_with(sidebar_field, "scale")) - orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - else if (boost::starts_with(sidebar_field, "rotation")) + glsafe(::glTranslated(center(0), center(1), center(2))); + if (!boost::starts_with(sidebar_field, "position")) { - if (boost::ends_with(sidebar_field, "x")) + Transform3d orient_matrix = Transform3d::Identity(); + if (boost::starts_with(sidebar_field, "scale")) orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - else if (boost::ends_with(sidebar_field, "y")) + else if (boost::starts_with(sidebar_field, "rotation")) { - const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation(); - if (rotation(0) == 0.0) + if (boost::ends_with(sidebar_field, "x")) orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - else - orient_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); + else if (boost::ends_with(sidebar_field, "y")) + { + const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation(); + if (rotation(0) == 0.0) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else + orient_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); + } } + + glsafe(::glMultMatrixd(orient_matrix.data())); } + } + else if (is_single_volume() || is_single_modifier()) + { + glsafe(::glTranslated(center(0), center(1), center(2))); + Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + if (!boost::starts_with(sidebar_field, "position")) + orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true); glsafe(::glMultMatrixd(orient_matrix.data())); } - } - else if (is_single_volume() || is_single_modifier()) - { - glsafe(::glTranslated(center(0), center(1), center(2))); - Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - if (!boost::starts_with(sidebar_field, "position")) - orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true); - - glsafe(::glMultMatrixd(orient_matrix.data())); - } - else - { - glsafe(::glTranslated(center(0), center(1), center(2))); - if (requires_local_axes()) + else { - Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); - glsafe(::glMultMatrixd(orient_matrix.data())); + glsafe(::glTranslated(center(0), center(1), center(2))); + if (requires_local_axes()) + { + Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } } } @@ -1136,10 +1143,16 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const render_sidebar_scale_hints(sidebar_field); else if (boost::starts_with(sidebar_field, "size")) render_sidebar_size_hints(sidebar_field); + else if (boost::starts_with(sidebar_field, "layer")) + render_sidebar_layers_hints(sidebar_field); glsafe(::glPopMatrix()); - glsafe(::glDisable(GL_LIGHTING)); + if (!boost::starts_with(sidebar_field, "layer")) + { + glsafe(::glDisable(GL_LIGHTING)); + shader.stop_using(); + } } bool Selection::requires_local_axes() const @@ -1709,6 +1722,75 @@ void Selection::render_sidebar_size_hints(const std::string& sidebar_field) cons render_sidebar_scale_hints(sidebar_field); } +void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) const +{ + static const double Margin = 10.0; + + std::string field = sidebar_field; + + // extract max_z + std::string::size_type pos = field.rfind("_"); + if (pos == std::string::npos) + return; + + double max_z = std::stod(field.substr(pos + 1)); + + // extract min_z + field = field.substr(0, pos); + pos = field.rfind("_"); + if (pos == std::string::npos) + return; + + double min_z = std::stod(field.substr(pos + 1)); + + // extract type + field = field.substr(0, pos); + pos = field.rfind("_"); + if (pos == std::string::npos) + return; + + int type = std::stoi(field.substr(pos + 1)); + + const BoundingBoxf3& box = get_bounding_box(); + + const float min_x = box.min(0) - Margin; + const float max_x = box.max(0) + Margin; + const float min_y = box.min(1) - Margin; + const float max_y = box.max(1) + Margin; + + glsafe(::glEnable(GL_DEPTH_TEST)); + glsafe(::glDisable(GL_CULL_FACE)); + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + + // Draw the min_z plane + ::glBegin(GL_QUADS); + if (type == 1) + ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); + else + ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); + ::glVertex3f(min_x, min_y, min_z); + ::glVertex3f(max_x, min_y, min_z); + ::glVertex3f(max_x, max_y, min_z); + ::glVertex3f(min_x, max_y, min_z); + glsafe(::glEnd()); + + // Draw the max_z plane + ::glBegin(GL_QUADS); + if (type == 2) + ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); + else + ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); + ::glVertex3f(min_x, min_y, max_z); + ::glVertex3f(max_x, min_y, max_z); + ::glVertex3f(max_x, max_y, max_z); + ::glVertex3f(min_x, max_y, max_z); + glsafe(::glEnd()); + + glsafe(::glEnable(GL_CULL_FACE)); + glsafe(::glDisable(GL_BLEND)); +} + void Selection::render_sidebar_position_hint(Axis axis) const { m_arrow.set_color(AXES_COLOR[axis], 3); diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 802f8d284..31b68917e 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -11,8 +11,8 @@ typedef class GLUquadric GLUquadricObj; #endif // ENABLE_RENDER_SELECTION_CENTER namespace Slic3r { +class Shader; namespace GUI { - class TransformationType { public: @@ -302,7 +302,7 @@ public: #if ENABLE_RENDER_SELECTION_CENTER void render_center(bool gizmo_is_dragging) const; #endif // ENABLE_RENDER_SELECTION_CENTER - void render_sidebar_hints(const std::string& sidebar_field) const; + void render_sidebar_hints(const std::string& sidebar_field, const Shader& shader) const; bool requires_local_axes() const; @@ -332,6 +332,7 @@ private: void render_sidebar_rotation_hints(const std::string& sidebar_field) const; void render_sidebar_scale_hints(const std::string& sidebar_field) const; void render_sidebar_size_hints(const std::string& sidebar_field) const; + void render_sidebar_layers_hints(const std::string& sidebar_field) const; void render_sidebar_position_hint(Axis axis) const; void render_sidebar_rotation_hint(Axis axis) const; void render_sidebar_scale_hint(Axis axis) const; From cecc1345508b684dd90f648df29a2d2b012031fb Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 27 Jun 2019 13:54:51 +0200 Subject: [PATCH 65/83] Rewrote layers information export/import to/from 3mf using Boost Property Tree (xml_parser) --- src/libslic3r/Format/3mf.cpp | 144 +++++++++++++++-------------------- 1 file changed, 62 insertions(+), 82 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 45b8fe52f..19802da84 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -16,6 +16,12 @@ #include #include +#include +#include +#include +#include +namespace pt = boost::property_tree; + #include #include #include "miniz_extension.hpp" @@ -34,7 +40,7 @@ const std::string RELATIONSHIPS_FILE = "_rels/.rels"; const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config"; const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config"; const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt"; -const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Slic3r_PE_layer_config_ranges.txt"; +const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Prusa_Slicer_layer_config_ranges.xml"; const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt"; const char* MODEL_TAG = "model"; @@ -796,43 +802,20 @@ namespace Slic3r { return; } - if (buffer.back() == '|') - buffer.pop_back(); + std::istringstream iss(buffer); // wrap returned xml to istringstream + pt::ptree objects_tree; + pt::read_xml(iss, objects_tree); - std::vector objects; - boost::split(objects, buffer, boost::is_any_of("|"), boost::token_compress_off); - - for (std::string& object : objects) + for (const auto& object : objects_tree.get_child("objects")) { - // delete all spaces - boost::replace_all(object, " ", ""); - - std::vector object_data; - boost::split(object_data, object, boost::is_any_of("*"), boost::token_compress_off); - /* there should be at least one layer config range in the object - * object_data[0] => object information - * object_data[i>=1] => range information - */ - if (object_data.size() < 2) { - add_error("Error while reading object data"); - continue; - } - - std::vector object_data_id; - boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off); - if (object_data_id.size() != 2) { - add_error("Error while reading object id"); - continue; - } - - // get object information - int object_id = std::atoi(object_data_id[1].c_str()); - if (object_id == 0) { + pt::ptree object_tree = object.second; + int obj_idx = object_tree.get(".id", -1); + if (obj_idx <= 0) { add_error("Found invalid object id"); continue; } - IdToLayerConfigRangesMap::iterator object_item = m_layer_config_ranges.find(object_id); + IdToLayerConfigRangesMap::iterator object_item = m_layer_config_ranges.find(obj_idx); if (object_item != m_layer_config_ranges.end()) { add_error("Found duplicated layer config range"); continue; @@ -840,56 +823,26 @@ namespace Slic3r { t_layer_config_ranges config_ranges; - // get ranges information - for (size_t i = 1; i < object_data.size(); ++i) + for (const auto& range : object_tree.get_child("ranges")) { - if (object_data[i].back() == '\n') - object_data[i].pop_back(); - - std::vector range_data; - boost::split(range_data, object_data[i], boost::is_any_of("\n"), boost::token_compress_off); - /* There should be at least two options for layer config range - * range_data[0] => Z range information - * range_data[i>=1] => configuration for the range - */ - if (range_data.size() < 3) { - add_error("Found invalid layer config range"); - continue; - } - - std::vector z_range_str; - boost::split(z_range_str, range_data[0], boost::is_any_of("="), boost::token_compress_off); - if (z_range_str.size() != 2) { - add_error("Error while reading layer config range"); - continue; - } - - std::vector z_values; - boost::split(z_values, z_range_str[1], boost::is_any_of(";"), boost::token_compress_off); - if (z_values.size() != 2) { - add_error("Found invalid layer config range"); - continue; - } + pt::ptree range_tree = range.second; + double min_z = range_tree.get(".min_z"); + double max_z = range_tree.get(".max_z"); // get Z range information - t_layer_height_range z_range = { (coordf_t)std::atof(z_values[0].c_str()) , (coordf_t)std::atof(z_values[1].c_str()) }; - DynamicPrintConfig& config = config_ranges[z_range]; + DynamicPrintConfig& config = config_ranges[{ min_z, max_z }]; - // get configuration options for the range - for (size_t j = 1; j < range_data.size(); ++j) + for (const auto& option : range_tree.get_child("config")) { - std::vector key_val; - boost::split(key_val, range_data[j], boost::is_any_of("="), boost::token_compress_off); - if (key_val.size() != 2) { - add_error("Error while reading config value"); - continue; - } - config.set_deserialize(key_val[0], key_val[1]); + std::string opt_key = option.second.get(".opt_key"); + std::string value = option.second.data(); + + config.set_deserialize(opt_key, value); } } if (!config_ranges.empty()) - m_layer_config_ranges.insert(IdToLayerConfigRangesMap::value_type(object_id, config_ranges)); + m_layer_config_ranges.insert(IdToLayerConfigRangesMap::value_type(obj_idx, config_ranges)); } } } @@ -2152,7 +2105,7 @@ namespace Slic3r { bool _3MF_Exporter::_add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model) { std::string out = ""; - char buffer[1024]; + pt::ptree tree; unsigned int object_cnt = 0; for (const ModelObject* object : model.objects) @@ -2161,26 +2114,53 @@ namespace Slic3r { const t_layer_config_ranges& ranges = object->layer_config_ranges; if (!ranges.empty()) { - sprintf(buffer, "object_id=%d\n", object_cnt); - out += buffer; + pt::ptree& obj_tree = tree.add("objects.object",""); + + obj_tree.put(".id", object_cnt); + obj_tree.add("ranges", ""); // Store the layer config ranges. for (const auto& range : ranges) { + pt::ptree& range_tree = obj_tree.add("ranges.range", ""); + // store minX and maxZ - sprintf(buffer, "*z_range = %f;%f\n", range.first.first, range.first.second); - out += buffer; + range_tree.put(".min_z", range.first.first); + range_tree.put(".max_z", range.first.second); + range_tree.add("config",""); // store range configuration const DynamicPrintConfig& config = range.second; - for (const std::string& key : config.keys()) - out += " " + key + " = " + config.serialize(key) + "\n"; + for (const std::string& opt_key : config.keys()) + { + pt::ptree& opt_tree = range_tree.add("config.option", config.serialize(opt_key)); + opt_tree.put(".opt_key", opt_key); + } } - - out += "|"; } } + if (!tree.empty()) + { + std::ostringstream oss; + boost::property_tree::write_xml(oss, tree); + out = oss.str(); + + // Post processing of the output string for a better preview + // JUST + // boost::replace_all(out, "><", ">\n<"); + // OR more "beautification" + boost::replace_all(out, ">\n \n \n \n \n \n \n \n \n Date: Thu, 27 Jun 2019 14:13:07 +0200 Subject: [PATCH 66/83] Fixed small typo --- src/libslic3r/Format/3mf.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 19802da84..b526f68b5 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include namespace pt = boost::property_tree; @@ -2156,7 +2155,7 @@ namespace Slic3r { boost::replace_all(out, ">\n \n \n \n ", ">\n "); boost::replace_all(out, ">\n \n Date: Thu, 27 Jun 2019 14:42:55 +0200 Subject: [PATCH 67/83] Removed memory leaks due to GUI_App::app_config, GUI_App::preset_bundle and GUI_App::preset_updater not being deleted --- src/slic3r/GUI/GUI_App.cpp | 12 ++++++++++++ src/slic3r/GUI/GUI_App.hpp | 1 + 2 files changed, 13 insertions(+) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 4f1c3adc8..0e79a3d02 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -141,6 +141,18 @@ GUI_App::GUI_App() , m_imgui(new ImGuiWrapper()) {} +GUI_App::~GUI_App() +{ + if (app_config != nullptr) + delete app_config; + + if (preset_bundle != nullptr) + delete preset_bundle; + + if (preset_updater != nullptr) + delete preset_updater; +} + bool GUI_App::OnInit() { try { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 3f8b23e2d..5a4da22d3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -95,6 +95,7 @@ public: bool initialized() const { return m_initialized; } GUI_App(); + ~GUI_App(); static unsigned get_colour_approx_luma(const wxColour &colour); static bool dark_mode(); From 97bb4a80cc9dc3a16d940e51974b31fa17e9cc54 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 27 Jun 2019 15:16:36 +0200 Subject: [PATCH 68/83] Removed memory leaks due to Sidebar::priv::object_manipulation, Sidebar::priv::object_settings and Sidebar::priv::frequently_changed_parameters not being deleted --- src/slic3r/GUI/Plater.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 472394d43..65cf326df 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -614,10 +614,10 @@ struct Sidebar::priv PresetComboBox *combo_printer; wxBoxSizer *sizer_params; - FreqChangedParams *frequently_changed_parameters; - ObjectList *object_list; - ObjectManipulation *object_manipulation; - ObjectSettings *object_settings; + FreqChangedParams *frequently_changed_parameters{ nullptr }; + ObjectList *object_list{ nullptr }; + ObjectManipulation *object_manipulation{ nullptr }; + ObjectSettings *object_settings{ nullptr }; ObjectInfo *object_info; SlicedInfo *sliced_info; @@ -626,10 +626,23 @@ struct Sidebar::priv wxButton *btn_send_gcode; priv(Plater *plater) : plater(plater) {} + ~priv(); void show_preset_comboboxes(); }; +Sidebar::priv::~priv() +{ + if (object_manipulation != nullptr) + delete object_manipulation; + + if (object_settings != nullptr) + delete object_settings; + + if (frequently_changed_parameters != nullptr) + delete frequently_changed_parameters; +} + void Sidebar::priv::show_preset_comboboxes() { const bool showSLA = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA; From 6cfb9bec363f6d485bcf8b5b73747df8c793e320 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 27 Jun 2019 15:23:03 +0200 Subject: [PATCH 69/83] Removed memory leaks due to Plater::priv::config not being deleted --- src/slic3r/GUI/Plater.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 65cf326df..a0deb52e3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1526,6 +1526,7 @@ struct Plater::priv static const std::regex pattern_prusa; priv(Plater *q, MainFrame *main_frame); + ~priv(); void update(bool force_full_scene_refresh = false); void select_view(const std::string& direction); @@ -1795,6 +1796,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) camera.set_type(get_config("use_perspective_camera")); } +Plater::priv::~priv() +{ + if (config != nullptr) + delete config; +} + void Plater::priv::update(bool force_full_scene_refresh) { // the following line, when enabled, causes flickering on NVIDIA graphics cards From 0b940ec0895cac520eea06c5e1582544a582c019 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 27 Jun 2019 15:57:29 +0200 Subject: [PATCH 70/83] Some code improvements --- src/libslic3r/Format/3mf.cpp | 33 +++++++++++++++------------------ src/slic3r/GUI/Selection.cpp | 3 +++ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index b526f68b5..b866e640e 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -822,8 +822,10 @@ namespace Slic3r { t_layer_config_ranges config_ranges; - for (const auto& range : object_tree.get_child("ranges")) + for (const auto& range : object_tree) { + if (range.first != "range") + continue; pt::ptree range_tree = range.second; double min_z = range_tree.get(".min_z"); double max_z = range_tree.get(".max_z"); @@ -831,8 +833,10 @@ namespace Slic3r { // get Z range information DynamicPrintConfig& config = config_ranges[{ min_z, max_z }]; - for (const auto& option : range_tree.get_child("config")) + for (const auto& option : range_tree) { + if (option.first != "option") + continue; std::string opt_key = option.second.get(".opt_key"); std::string value = option.second.data(); @@ -2116,23 +2120,21 @@ namespace Slic3r { pt::ptree& obj_tree = tree.add("objects.object",""); obj_tree.put(".id", object_cnt); - obj_tree.add("ranges", ""); // Store the layer config ranges. for (const auto& range : ranges) { - pt::ptree& range_tree = obj_tree.add("ranges.range", ""); + pt::ptree& range_tree = obj_tree.add("range", ""); // store minX and maxZ range_tree.put(".min_z", range.first.first); range_tree.put(".max_z", range.first.second); - range_tree.add("config",""); // store range configuration const DynamicPrintConfig& config = range.second; for (const std::string& opt_key : config.keys()) { - pt::ptree& opt_tree = range_tree.add("config.option", config.serialize(opt_key)); + pt::ptree& opt_tree = range_tree.add("option", config.serialize(opt_key)); opt_tree.put(".opt_key", opt_key); } } @@ -2145,19 +2147,14 @@ namespace Slic3r { boost::property_tree::write_xml(oss, tree); out = oss.str(); - // Post processing of the output string for a better preview - // JUST - // boost::replace_all(out, "><", ">\n<"); - // OR more "beautification" + // Post processing("beautification") of the output string for a better preview boost::replace_all(out, ">\n \n \n \n \n \n ", ">\n "); - boost::replace_all(out, ">\n \n \n \n ", ">\n "); + boost::replace_all(out, ">", ">\n "); + // OR just + boost::replace_all(out, "><", ">\n<"); } if (!out.empty()) diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 82bc52d3a..9939c291e 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -331,6 +331,9 @@ void Selection::clear() // resets the cache in the sidebar wxGetApp().obj_manipul()->reset_cache(); + + // #et_FIXME fake KillFocus from sidebar + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); } // Update the selection based on the new instance IDs. From 1a529cb77815cf2b392104611462da5b3d3641a2 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 28 Jun 2019 11:35:54 +0200 Subject: [PATCH 71/83] PresetUpdater: Fix: Index installed too early --- src/slic3r/Utils/PresetUpdater.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 8c3ced31a..bc600fcad 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -402,15 +402,8 @@ Updates PresetUpdater::priv::get_config_updates() const } } - copy_file_fix(idx.path(), bundle_path_idx); - const auto ver_current = idx.find(vp.config_version); const bool ver_current_found = ver_current != idx.end(); - if (! ver_current_found) { - auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str(); - BOOST_LOG_TRIVIAL(error) << message; - GUI::show_error(nullptr, GUI::from_u8(message)); - } BOOST_LOG_TRIVIAL(debug) << boost::format("Vendor: %1%, version installed: %2%%3%, version cached: %4%") % vp.name @@ -418,6 +411,13 @@ Updates PresetUpdater::priv::get_config_updates() const % (ver_current_found ? "" : " (not found in index!)") % recommended->config_version.to_string(); + if (! ver_current_found) { + auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str(); + BOOST_LOG_TRIVIAL(error) << message; + GUI::show_error(nullptr, GUI::from_u8(message)); + continue; + } + if (ver_current_found && !ver_current->is_current_slic3r_supported()) { BOOST_LOG_TRIVIAL(warning) << "Current Slic3r incompatible with installed bundle: " << bundle_path.string(); updates.incompats.emplace_back(std::move(bundle_path), *ver_current, vp.name); @@ -459,10 +459,16 @@ Updates PresetUpdater::priv::get_config_updates() const found = true; } } - if (! found) + + if (found) { + // 'Install' the index in the vendor directory. This is used to memoize + // offered updates and to not offer the same update again if it was cancelled by the user. + copy_file_fix(idx.path(), bundle_path_idx); + } else { BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources") % idx.vendor() % recommended->config_version.to_string(); + } } } From a934c2e79c64273db45e7bc22835eb147488d81b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 1 Jul 2019 14:56:28 +0200 Subject: [PATCH 72/83] Changed a behavior logic of a value reverting for presets, derived from default. LOCKs and ARROWs work now in a same way like for presets, derived from system presets. --- src/slic3r/GUI/Preset.cpp | 20 ++++++++++++--- src/slic3r/GUI/Tab.cpp | 52 +++++++++++++++------------------------ src/slic3r/GUI/Tab.hpp | 6 +++++ 3 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 7192d485c..b8add9fc7 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -824,11 +824,25 @@ const Preset* PresetCollection::get_selected_preset_parent() const if (this->get_selected_idx() == -1) // This preset collection has no preset activated yet. Only the get_edited_preset() is valid. return nullptr; - const std::string &inherits = this->get_edited_preset().inherits(); +// const std::string &inherits = this->get_edited_preset().inherits(); +// if (inherits.empty()) +// return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; + + std::string inherits = this->get_edited_preset().inherits(); if (inherits.empty()) - return this->get_selected_preset().is_system ? &this->get_selected_preset() : nullptr; + { + if (this->get_selected_preset().is_system || this->get_selected_preset().is_default) + return &this->get_selected_preset(); + if (this->get_selected_preset().is_external) + return nullptr; + + inherits = m_type != Preset::Type::TYPE_PRINTER ? "- default -" : + this->get_edited_preset().printer_technology() == ptFFF ? + "- default FFF -" : "- default SLA -" ; + } + const Preset* preset = this->find_preset(inherits, false); - return (preset == nullptr || preset->is_default || preset->is_external) ? nullptr : preset; + return (preset == nullptr/* || preset->is_default*/ || preset->is_external) ? nullptr : preset; } const Preset* PresetCollection::get_preset_parent(const Preset& child) const diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6e8b8a471..cd43d95c4 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -423,7 +423,7 @@ void Tab::update_changed_ui() const ScalableBitmap *sys_icon = &m_bmp_value_lock; const ScalableBitmap *icon = &m_bmp_value_revert; - const wxColour *color = &m_sys_label_clr; + const wxColour *color = m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr; const wxString *sys_tt = &m_tt_value_lock; const wxString *tt = &m_tt_value_revert; @@ -590,7 +590,7 @@ void Tab::update_changed_tree_ui() } } - const wxColor *clr = sys_page ? &m_sys_label_clr : + const wxColor *clr = sys_page ? (m_is_default_preset ? &m_default_text_clr : &m_sys_label_clr) : modified_page ? &m_modified_label_clr : &m_default_text_clr; @@ -2584,11 +2584,14 @@ void Tab::load_current_preset() // Reload preset pages with the new configuration values. reload_config(); - m_bmp_non_system = m_presets->get_selected_preset_parent() ? &m_bmp_value_unlock : &m_bmp_white_bullet; - m_ttg_non_system = m_presets->get_selected_preset_parent() ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; - m_tt_non_system = m_presets->get_selected_preset_parent() ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; + const Preset* selected_preset_parent = m_presets->get_selected_preset_parent(); + m_is_default_preset = selected_preset_parent != nullptr && selected_preset_parent->is_default; - m_undo_to_sys_btn->Enable(!preset.is_default); + m_bmp_non_system = selected_preset_parent ? &m_bmp_value_unlock : &m_bmp_white_bullet; + m_ttg_non_system = selected_preset_parent ? &m_ttg_value_unlock : &m_ttg_white_bullet_ns; + m_tt_non_system = selected_preset_parent ? &m_tt_value_unlock : &m_ttg_white_bullet_ns; + +// m_undo_to_sys_btn->Enable(!preset.is_default); #if 0 // use CallAfter because some field triggers schedule on_change calls using CallAfter, @@ -3174,18 +3177,18 @@ void Tab::fill_icon_descriptions() { m_icon_descriptions.emplace_back(&m_bmp_value_lock, L("LOCKED LOCK"), // TRN Description for "LOCKED LOCK" - L("indicates that the settings are the same as the system values for the current option group")); + L("indicates that the settings are the same as the system (or default) values for the current option group")); m_icon_descriptions.emplace_back(&m_bmp_value_unlock, L("UNLOCKED LOCK"), // TRN Description for "UNLOCKED LOCK" - L("indicates that some settings were changed and are not equal to the system values for " + L("indicates that some settings were changed and are not equal to the system (or default) values for " "the current option group.\n" "Click the UNLOCKED LOCK icon to reset all settings for current option group to " - "the system values.")); + "the system (or default) values.")); m_icon_descriptions.emplace_back(&m_bmp_white_bullet, L("WHITE BULLET"), // TRN Description for "WHITE BULLET" - L("for the left button: \tindicates a non-system preset,\n" + L("for the left button: \tindicates a non-system (or non-default) preset,\n" "for the right button: \tindicates that the settings hasn't been modified.")); m_icon_descriptions.emplace_back(&m_bmp_value_revert, L("BACK ARROW"), @@ -3198,29 +3201,14 @@ void Tab::fill_icon_descriptions() void Tab::set_tooltips_text() { -// m_undo_to_sys_btn->SetToolTip(_(L( "LOCKED LOCK icon indicates that the settings are the same as the system values " -// "for the current option group.\n" -// "UNLOCKED LOCK icon indicates that some settings were changed and are not equal " -// "to the system values for the current option group.\n" -// "WHITE BULLET icon indicates a non system preset.\n\n" -// "Click the UNLOCKED LOCK icon to reset all settings for current option group to " -// "the system values."))); -// -// m_undo_btn->SetToolTip(_(L( "WHITE BULLET icon indicates that the settings are the same as in the last saved" -// "preset for the current option group.\n" -// "BACK ARROW icon indicates that the settings were changed and are not equal to " -// "the last saved preset for the current option group.\n\n" -// "Click the BACK ARROW icon to reset all settings for the current option group to " -// "the last saved preset."))); - // --- Tooltip text for reset buttons (for whole options group) // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - m_ttg_value_lock = _(L("LOCKED LOCK icon indicates that the settings are the same as the system values " + m_ttg_value_lock = _(L("LOCKED LOCK icon indicates that the settings are the same as the system (or default) values " "for the current option group")); m_ttg_value_unlock = _(L("UNLOCKED LOCK icon indicates that some settings were changed and are not equal " - "to the system values for the current option group.\n" - "Click to reset all settings for current option group to the system values.")); - m_ttg_white_bullet_ns = _(L("WHITE BULLET icon indicates a non system preset.")); + "to the system (or default) values for the current option group.\n" + "Click to reset all settings for current option group to the system (or default) values.")); + m_ttg_white_bullet_ns = _(L("WHITE BULLET icon indicates a non system (or non default) preset.")); m_ttg_non_system = &m_ttg_white_bullet_ns; // Text to be shown on the "Undo user changes" button next to each input field. m_ttg_white_bullet = _(L("WHITE BULLET icon indicates that the settings are the same as in the last saved " @@ -3231,10 +3219,10 @@ void Tab::set_tooltips_text() // --- Tooltip text for reset buttons (for each option in group) // Text to be shown on the "Revert to system" aka "Lock to system" button next to each input field. - m_tt_value_lock = _(L("LOCKED LOCK icon indicates that the value is the same as the system value.")); + m_tt_value_lock = _(L("LOCKED LOCK icon indicates that the value is the same as the system (or default) value.")); m_tt_value_unlock = _(L("UNLOCKED LOCK icon indicates that the value was changed and is not equal " - "to the system value.\n" - "Click to reset current value to the system value.")); + "to the system (or default) value.\n" + "Click to reset current value to the system (or default) value.")); // m_tt_white_bullet_ns= _(L("WHITE BULLET icon indicates a non system preset.")); m_tt_non_system = &m_ttg_white_bullet_ns; // Text to be shown on the "Undo user changes" button next to each input field. diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 6bbe15f7f..73b6bb08d 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -142,6 +142,12 @@ protected: PresetDependencies m_compatible_printers; PresetDependencies m_compatible_prints; + /* Indicates, that default preset or preset inherited from default is selected + * This value is used for a options color updating + * (use green color only for options, which values are equal to system values) + */ + bool m_is_default_preset {false}; + ScalableButton* m_undo_btn; ScalableButton* m_undo_to_sys_btn; ScalableButton* m_question_btn; From e5e7496cea88cd18afa9a83a95e1ed596c5a69c5 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 1 Jul 2019 16:56:38 +0200 Subject: [PATCH 73/83] Some changes for options tooltips --- src/slic3r/GUI/Field.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 7f42db4d7..e84e9637f 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -113,11 +113,19 @@ wxString Field::get_tooltip_text(const wxString& default_string) wxString tooltip_text(""); wxString tooltip = _(m_opt.tooltip); edit_tooltip(tooltip); + + std::string opt_id = m_opt_id; + auto hash_pos = opt_id.find("#"); + if (hash_pos != std::string::npos) { + opt_id.replace(hash_pos, 1,"["); + opt_id += "]"; + } + if (tooltip.length() > 0) tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " + - (boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + default_string + - (boost::iends_with(m_opt_id, "_gcode") ? "" : "\n") + - _(L("parameter name")) + "\t: " + m_opt_id; + (boost::iends_with(opt_id, "_gcode") ? "\n" : "") + default_string + + (boost::iends_with(opt_id, "_gcode") ? "" : "\n") + + _(L("parameter name")) + "\t: " + opt_id; return tooltip_text; } From b835075fd64e82c36ea821cd326b3f3ecd005356 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 2 Jul 2019 10:34:30 +0200 Subject: [PATCH 74/83] Visual hints for layers editing enabled whenever a layer is selected into the objects list --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 20 +++++++++++++------- src/slic3r/GUI/GUI_ObjectLayers.hpp | 5 ++++- src/slic3r/GUI/GUI_ObjectList.cpp | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index ff0f55aef..f9d3a8956 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -197,17 +197,25 @@ void ObjectLayers::update_layers_list() // Add new control according to the selected item if (type & itLayerRoot) + { + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); + m_selectable_range = { 0.0, 0.0 }; create_layers_list(); + } else - create_layer(objects_ctrl->GetModel()->GetLayerRangeByItem(item)); - + { + t_layer_height_range range = objects_ctrl->GetModel()->GetLayerRangeByItem(item); + create_layer(range); + update_scene_from_editor_selection(range, etLayerHeight); + } + m_parent->Layout(); } -void ObjectLayers::update_scene_from_editor_selection() const +void ObjectLayers::update_scene_from_editor_selection(const t_layer_height_range& range, EditorType type) const { // needed to show the visual hints in 3D scene - wxGetApp().plater()->canvas3D()->handle_layers_data_focus_event(m_selectable_range, m_selection_type); + wxGetApp().plater()->canvas3D()->handle_layers_data_focus_event(range, type); } void ObjectLayers::UpdateAndShow(const bool show) @@ -257,8 +265,6 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e) { - wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); - if (!m_enter_pressed) { #ifndef __WXGTK__ /* Update data for next editor selection. @@ -291,7 +297,7 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, this->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e) { set_focus_data(); - parent->update_scene_from_editor_selection(); + parent->update_scene_from_editor_selection(parent->get_selectable_range(), parent->get_selection_type()); e.Skip(); }, this->GetId()); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index f19217fbe..253cbf0a4 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -73,11 +73,14 @@ public: void create_layers_list(); void update_layers_list(); - void update_scene_from_editor_selection() const; + void update_scene_from_editor_selection(const t_layer_height_range& range, EditorType type) const; void UpdateAndShow(const bool show) override; void msw_rescale(); + const t_layer_height_range& get_selectable_range() const { return m_selectable_range; } + EditorType get_selection_type() const { return m_selection_type; } + friend class LayerRangeEditor; }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 03f9cd45f..af1a9908d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2067,6 +2067,7 @@ void ObjectList::part_selection_changed() Sidebar& panel = wxGetApp().sidebar(); panel.Freeze(); + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations); wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings); wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers); From f09fb92b619ea94e7ea6f02edd393a4dfe5d7976 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 2 Jul 2019 11:43:07 +0200 Subject: [PATCH 75/83] Fix build against system-provided qhull --- src/libslic3r/TriangleMesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 56accfefa..fbfff90fb 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -547,9 +547,9 @@ TriangleMesh TriangleMesh::convex_hull_3d() const #if REALfloat qhull.runQhull("", 3, (int)this->its.vertices.size(), (const realT*)(this->its.vertices.front().data()), "Qt"); #else - src_vertices.reserve(this->its.vertices() * 3); + src_vertices.reserve(this->its.vertices.size() * 3); // We will now fill the vector with input points for computation: - for (const stl_vertex &v : ths->its.vertices.size()) + for (const stl_vertex &v : this->its.vertices) for (int i = 0; i < 3; ++ i) src_vertices.emplace_back(v(i)); qhull.runQhull("", 3, (int)src_vertices.size() / 3, src_vertices.data(), "Qt"); From 136e5156bc0b9fcbeeda52dcbab8f9f993ba639e Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 2 Jul 2019 13:13:17 +0200 Subject: [PATCH 76/83] Fixed colot_print issues: * Disabled color change information for the SLA and FFF-multimaterial presets * Corrected switch between "color print" and "feature type" on Preview --- src/libslic3r/GCode.cpp | 4 ++- src/slic3r/GUI/GLCanvas3D.cpp | 3 ++- src/slic3r/GUI/GUI_Preview.cpp | 47 ++++++++++++++++++++++----------- src/slic3r/GUI/GUI_Preview.hpp | 2 ++ src/slic3r/GUI/Plater.cpp | 3 +++ src/slic3r/GUI/wxExtensions.cpp | 10 +++++-- 6 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index c42669de0..c03431a30 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1405,7 +1405,9 @@ void GCode::process_layer( m_colorprint_heights.erase(m_colorprint_heights.begin()); colorprint_change = true; } - if (colorprint_change && print.extruders().size()==1) + + // we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count + if (colorprint_change && print./*extruders()*/config().nozzle_diameter.size()==1) gcode += "M600\n"; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 9bb6f4553..74b3e685a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -912,7 +912,8 @@ GLCanvas3D::LegendTexture::LegendTexture() void GLCanvas3D::LegendTexture::fill_color_print_legend_values(const GCodePreviewData& preview_data, const GLCanvas3D& canvas, std::vector>& cp_legend_values) { - if (preview_data.extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint) + if (preview_data.extrusion.view_type == GCodePreviewData::Extrusion::ColorPrint && + wxGetApp().extruders_edited_cnt() == 1) // show color change legend only for single-material presets { auto& config = wxGetApp().preset_bundle->project_config; const std::vector& color_print_values = config.option("colorprint_heights")->values; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 671c49eef..0ba447c1b 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -541,6 +541,26 @@ void Preview::on_checkbox_shells(wxCommandEvent& evt) refresh_print(); } +void Preview::update_view_type() +{ + const DynamicPrintConfig& config = wxGetApp().preset_bundle->project_config; + + const wxString& choice = !config.option("colorprint_heights")->values.empty() && + wxGetApp().extruders_edited_cnt()==1 ? + _(L("Color Print")) : + config.option("wiping_volumes_matrix")->values.size() > 1 ? + _(L("Tool")) : + _(L("Feature type")); + + int type = m_choice_view_type->FindString(choice); + if (m_choice_view_type->GetSelection() != type) { + m_choice_view_type->SetSelection(type); + if (0 <= type && type < (int)GCodePreviewData::Extrusion::Num_View_Types) + m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type; + m_preferred_color_mode = "feature"; + } +} + void Preview::create_double_slider() { m_slider = new DoubleSlider(this, wxID_ANY, 0, 0, 0, 100); @@ -553,23 +573,13 @@ void Preview::create_double_slider() Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { - auto& config = wxGetApp().preset_bundle->project_config; - ((config.option("colorprint_heights"))->values) = (m_slider->GetTicksValues()); - m_schedule_background_process(); + wxGetApp().preset_bundle->project_config.option("colorprint_heights")->values = m_slider->GetTicksValues(); + m_schedule_background_process(); - const wxString& choise = !config.option("colorprint_heights")->values.empty() ? _(L("Color Print")) : - config.option("wiping_volumes_matrix")->values.size() > 1 ? - _(L("Tool")) : _(L("Feature type")); + update_view_type(); - int type = m_choice_view_type->FindString(choise); - if (m_choice_view_type->GetSelection() != type) { - m_choice_view_type->SetSelection(type); - if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types)) - m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type; - m_preferred_color_mode = "feature"; - } - reload_print(); - }); + reload_print(); + }); } // Find an index of a value in a sorted vector, which is in . @@ -787,9 +797,14 @@ void Preview::load_print_as_fff(bool keep_z_range) // Load the real G-code preview. m_canvas->load_gcode_preview(*m_gcode_preview_data, colors); m_loaded = true; - } else + } else { + // disable color change information for multi-material presets + if (wxGetApp().extruders_edited_cnt() > 1) + color_print_values.clear(); + // Load the initial preview based on slices, not the final G-code. m_canvas->load_preview(colors, color_print_values); + } show_hide_ui_elements(gcode_preview_data_valid ? "full" : "simple"); // recalculates zs and update sliders accordingly std::vector zs = m_canvas->get_current_print_zs(true); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 993e260e4..e86d0e430 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -127,6 +127,8 @@ public: void move_double_slider(wxKeyEvent& evt); void edit_double_slider(wxKeyEvent& evt); + void update_view_type(); + private: bool init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a0deb52e3..09ab91ef1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3947,6 +3947,9 @@ void Plater::reslice() } else if (!p->background_process.empty() && !p->background_process.idle()) p->show_action_buttons(true); + + // update type of preview + p->preview->update_view_type(); } void Plater::reslice_SLA_supports(const ModelObject &object) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index aed423674..55044138f 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -2027,6 +2027,9 @@ void DoubleSlider::draw_thumbs(wxDC& dc, const wxCoord& lower_pos, const wxCoord void DoubleSlider::draw_ticks(wxDC& dc) { + if (!m_is_enabled_tick_manipulation) + return; + dc.SetPen(m_is_enabled_tick_manipulation ? DARK_GREY_PEN : LIGHT_GREY_PEN ); int height, width; get_size(&width, &height); @@ -2044,6 +2047,9 @@ void DoubleSlider::draw_ticks(wxDC& dc) void DoubleSlider::draw_colored_band(wxDC& dc) { + if (!m_is_enabled_tick_manipulation) + return; + int height, width; get_size(&width, &height); @@ -2113,7 +2119,7 @@ void DoubleSlider::draw_one_layer_icon(wxDC& dc) void DoubleSlider::draw_revert_icon(wxDC& dc) { - if (m_ticks.empty()) + if (m_ticks.empty() || !m_is_enabled_tick_manipulation) return; int width, height; @@ -2218,7 +2224,7 @@ void DoubleSlider::OnLeftDown(wxMouseEvent& event) m_selection == ssLower ? correct_lower_value() : correct_higher_value(); if (!m_selection) m_selection = ssHigher; } - else if (is_point_in_rect(pos, m_rect_revert_icon)) { + else if (is_point_in_rect(pos, m_rect_revert_icon) && m_is_enabled_tick_manipulation) { // discard all color changes SetLowerValue(m_min_value); SetHigherValue(m_max_value); From 2a71665de90f043d25a9b8f52281a1fc1072fdf2 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 2 Jul 2019 15:10:59 +0200 Subject: [PATCH 77/83] Follow-up of d07b3fb08b5f8e81899a4772f8219fde49ef2126 -> Show current bed shape for custom bed in bed shape dialog --- src/slic3r/GUI/BedShapeDialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index cec0f5067..20aa68ef2 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -234,8 +234,8 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points) // This is a custom bed shape, use the polygon provided. m_shape_options_book->SetSelection(SHAPE_CUSTOM); // Copy the polygon to the canvas, make a copy of the array. - m_canvas->m_bed_shape = points->values; - update_shape(); + m_loaded_bed_shape = points->values; + update_shape(); } void BedShapePanel::update_preview() From 0bcad2a5c52b774eba6472077cbe6cb786c20f27 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 2 Jul 2019 15:26:11 +0200 Subject: [PATCH 78/83] Fix for the last commit --- src/slic3r/GUI/GUI_ObjectLayers.cpp | 22 ++++++++++------------ src/slic3r/GUI/GUI_ObjectLayers.hpp | 7 +++---- src/slic3r/GUI/GUI_ObjectList.cpp | 20 ++++++++++++++++++-- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectLayers.cpp b/src/slic3r/GUI/GUI_ObjectLayers.cpp index f9d3a8956..b30d3ecd3 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.cpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.cpp @@ -197,25 +197,17 @@ void ObjectLayers::update_layers_list() // Add new control according to the selected item if (type & itLayerRoot) - { - wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); - m_selectable_range = { 0.0, 0.0 }; create_layers_list(); - } else - { - t_layer_height_range range = objects_ctrl->GetModel()->GetLayerRangeByItem(item); - create_layer(range); - update_scene_from_editor_selection(range, etLayerHeight); - } + create_layer(objects_ctrl->GetModel()->GetLayerRangeByItem(item)); m_parent->Layout(); } -void ObjectLayers::update_scene_from_editor_selection(const t_layer_height_range& range, EditorType type) const +void ObjectLayers::update_scene_from_editor_selection() const { // needed to show the visual hints in 3D scene - wxGetApp().plater()->canvas3D()->handle_layers_data_focus_event(range, type); + wxGetApp().plater()->canvas3D()->handle_layers_data_focus_event(m_selectable_range, m_selection_type); } void ObjectLayers::UpdateAndShow(const bool show) @@ -232,6 +224,12 @@ void ObjectLayers::msw_rescale() m_bmp_add.msw_rescale(); } +void ObjectLayers::reset_selection() +{ + m_selectable_range = { 0.0, 0.0 }; + m_selection_type = etLayerHeight; +} + LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, const wxString& value, EditorType type, @@ -297,7 +295,7 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent, this->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e) { set_focus_data(); - parent->update_scene_from_editor_selection(parent->get_selectable_range(), parent->get_selection_type()); + parent->update_scene_from_editor_selection(); e.Skip(); }, this->GetId()); diff --git a/src/slic3r/GUI/GUI_ObjectLayers.hpp b/src/slic3r/GUI/GUI_ObjectLayers.hpp index 253cbf0a4..f274183e2 100644 --- a/src/slic3r/GUI/GUI_ObjectLayers.hpp +++ b/src/slic3r/GUI/GUI_ObjectLayers.hpp @@ -73,13 +73,12 @@ public: void create_layers_list(); void update_layers_list(); - void update_scene_from_editor_selection(const t_layer_height_range& range, EditorType type) const; + void update_scene_from_editor_selection() const; void UpdateAndShow(const bool show) override; void msw_rescale(); - - const t_layer_height_range& get_selectable_range() const { return m_selectable_range; } - EditorType get_selection_type() const { return m_selection_type; } + void reset_selection(); + void set_selectable_range(const t_layer_height_range& range) { m_selectable_range = range; } friend class LayerRangeEditor; }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index af1a9908d..5c421705b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -578,6 +578,22 @@ void ObjectList::selection_changed() wxPostEvent(this, event); } + if (const wxDataViewItem item = GetSelection()) + { + const ItemType type = m_objects_model->GetItemType(item); + // to correct visual hints for layers editing on the Scene + if (type & (itLayer|itLayerRoot)) { + wxGetApp().obj_layers()->reset_selection(); + + if (type & itLayerRoot) + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); + else { + wxGetApp().obj_layers()->set_selectable_range(m_objects_model->GetLayerRangeByItem(item)); + wxGetApp().obj_layers()->update_scene_from_editor_selection(); + } + } + } + part_selection_changed(); } @@ -1864,7 +1880,7 @@ void ObjectList::layers_editing() // set some default value if (ranges.empty()) - ranges[{ 0.0f, 0.6f }] = get_default_layer_config(obj_idx); + ranges[{ 0.0f, 2.0f }] = get_default_layer_config(obj_idx); // create layer root item layers_item = add_layer_root_item(obj_item); @@ -2330,7 +2346,7 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre if (current_range == last_range) { - const t_layer_height_range& new_range = { last_range.second, last_range.second + 0.5f }; + const t_layer_height_range& new_range = { last_range.second, last_range.second + 2.0f }; ranges[new_range] = get_default_layer_config(obj_idx); add_layer_item(new_range, layers_item); } From 90daffccf2b5fa0a5ab21cec8581e8bf1e92e72f Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 2 Jul 2019 15:49:18 +0200 Subject: [PATCH 79/83] View dependent order of rendering for layers editing visual hints to keep the correct transparency --- src/slic3r/GUI/Plater.cpp | 5 +++++ src/slic3r/GUI/Plater.hpp | 2 ++ src/slic3r/GUI/Selection.cpp | 30 +++++++++++++++++------------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 98b7c1303..0a154034f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4273,6 +4273,11 @@ void Plater::msw_rescale() GetParent()->Layout(); } +const Camera& Plater::get_camera() const +{ + return p->camera; +} + bool Plater::can_delete() const { return p->can_delete(); } bool Plater::can_delete_all() const { return p->can_delete_all(); } bool Plater::can_increase_instances() const { return p->can_increase_instances(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index c3f8927c0..34fd7984e 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -220,6 +220,8 @@ public: void msw_rescale(); + const Camera& get_camera() const; + private: struct priv; std::unique_ptr p; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 9939c291e..bea94e2e6 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -6,7 +6,8 @@ #include "GUI_ObjectManipulation.hpp" #include "GUI_ObjectList.hpp" #include "Gizmos/GLGizmoBase.hpp" -#include "slic3r/GUI/3DScene.hpp" +#include "3DScene.hpp" +#include "Camera.hpp" #include @@ -1761,33 +1762,36 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co const float min_y = box.min(1) - Margin; const float max_y = box.max(1) + Margin; + // view dependend order of rendering to keep correct transparency + bool camera_on_top = wxGetApp().plater()->get_camera().get_theta() <= 90.0f; + float z1 = camera_on_top ? min_z : max_z; + float z2 = camera_on_top ? max_z : min_z; + glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_CULL_FACE)); glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - // Draw the min_z plane ::glBegin(GL_QUADS); - if (type == 1) + if ((camera_on_top && (type == 1)) || (!camera_on_top && (type == 2))) ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); - ::glVertex3f(min_x, min_y, min_z); - ::glVertex3f(max_x, min_y, min_z); - ::glVertex3f(max_x, max_y, min_z); - ::glVertex3f(min_x, max_y, min_z); + ::glVertex3f(min_x, min_y, z1); + ::glVertex3f(max_x, min_y, z1); + ::glVertex3f(max_x, max_y, z1); + ::glVertex3f(min_x, max_y, z1); glsafe(::glEnd()); - // Draw the max_z plane ::glBegin(GL_QUADS); - if (type == 2) + if ((camera_on_top && (type == 2)) || (!camera_on_top && (type == 1))) ::glColor4f(1.0f, 0.38f, 0.0f, 1.0f); else ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); - ::glVertex3f(min_x, min_y, max_z); - ::glVertex3f(max_x, min_y, max_z); - ::glVertex3f(max_x, max_y, max_z); - ::glVertex3f(min_x, max_y, max_z); + ::glVertex3f(min_x, min_y, z2); + ::glVertex3f(max_x, min_y, z2); + ::glVertex3f(max_x, max_y, z2); + ::glVertex3f(min_x, max_y, z2); glsafe(::glEnd()); glsafe(::glEnable(GL_CULL_FACE)); From d101ed709c79c305433a14e780be63428f3da12f Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 3 Jul 2019 08:58:05 +0200 Subject: [PATCH 80/83] Button 'Load shape from STL' centered into its panel in bed shape dialog --- src/slic3r/GUI/BedShapeDialog.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 20aa68ef2..4dc7d0f79 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -92,13 +92,15 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) Line line{ "", "" }; line.full_width = 1; line.widget = [this](wxWindow* parent) { - auto btn = new wxButton(parent, wxID_ANY, _(L("Load shape from STL...")), wxDefaultPosition, wxDefaultSize); - - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(btn); + auto shape_btn = new wxButton(parent, wxID_ANY, _(L("Load shape from STL..."))); + wxSizer* shape_sizer = new wxBoxSizer(wxHORIZONTAL); + shape_sizer->Add(shape_btn, 1, wxEXPAND); - btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) - { + wxSizer* sizer = new wxBoxSizer(wxVERTICAL); + sizer->Add(shape_sizer, 1, wxEXPAND); + + shape_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent& e) + { load_stl(); })); From 7a7316fcbf79a51087266bf57373c8428760eac5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 3 Jul 2019 09:19:07 +0200 Subject: [PATCH 81/83] Fixed compile warnings in Bed3D --- src/slic3r/GUI/3DBed.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 68a74f61c..fc07581e6 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -44,8 +44,8 @@ public: const float* get_vertices_data() const; unsigned int get_vertices_data_size() const { return (unsigned int)m_vertices.size() * get_vertex_data_size(); } unsigned int get_vertex_data_size() const { return (unsigned int)(5 * sizeof(float)); } - unsigned int get_position_offset() const { return 0; } - unsigned int get_tex_coords_offset() const { return (unsigned int)(3 * sizeof(float)); } + size_t get_position_offset() const { return 0; } + size_t get_tex_coords_offset() const { return (size_t)(3 * sizeof(float)); } unsigned int get_vertices_count() const { return (unsigned int)m_vertices.size(); } #else const float* get_vertices() const { return m_vertices.data(); } From 2c0f0c85a5335405c09a9ff4fa84d2636de0d68d Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 3 Jul 2019 10:06:22 +0200 Subject: [PATCH 82/83] Fixed bed shape dialog layout --- src/slic3r/GUI/BedShapeDialog.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 4dc7d0f79..d52204d4a 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -53,15 +53,12 @@ void BedShapeDialog::on_dpi_changed(const wxRect &suggested_rect) void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) { -// on_change(nullptr); - - auto box = new wxStaticBox(this, wxID_ANY, _(L("Shape"))); - auto sbsizer = new wxStaticBoxSizer(box, wxVERTICAL); + auto sbsizer = new wxStaticBoxSizer(wxVERTICAL, this, _(L("Shape"))); // shape options m_shape_options_book = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxSize(25*wxGetApp().em_unit(), -1), wxCHB_TOP); - sbsizer->Add(m_shape_options_book); + sbsizer->Add(m_shape_options_book); auto optgroup = init_shape_options_page(_(L("Rectangular"))); ConfigOptionDef def; @@ -108,8 +105,8 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) }; optgroup->append_line(line); - Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent e) - { + Bind(wxEVT_CHOICEBOOK_PAGE_CHANGED, ([this](wxCommandEvent& e) + { update_shape(); })); @@ -119,8 +116,8 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) // main sizer auto top_sizer = new wxBoxSizer(wxHORIZONTAL); - top_sizer->Add(sbsizer, 0, wxEXPAND | wxLeft | wxTOP | wxBOTTOM, 10); - if (m_canvas) + top_sizer->Add(sbsizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 10); + if (m_canvas) top_sizer->Add(m_canvas, 1, wxEXPAND | wxALL, 10) ; SetSizerAndFit(top_sizer); @@ -137,8 +134,7 @@ void BedShapePanel::build_panel(ConfigOptionPoints* default_pt) // Create a panel for a rectangular / circular / custom bed shape. ConfigOptionsGroupShp BedShapePanel::init_shape_options_page(const wxString& title) { - - auto panel = new wxPanel(m_shape_options_book); + auto panel = new wxPanel(m_shape_options_book); ConfigOptionsGroupShp optgroup; optgroup = std::make_shared(panel, _(L("Settings"))); From 74f9a5432f3f72423137b5cd9a56fc2c33e57845 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 4 Jul 2019 14:25:40 +0200 Subject: [PATCH 83/83] Reset previous layers range selection before selection Layers Item --- src/slic3r/GUI/GUI_ObjectList.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 5c421705b..4c4a30227 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1888,6 +1888,10 @@ void ObjectList::layers_editing() if (!layers_item.IsOk()) return; + // to correct visual hints for layers editing on the Scene, reset previous selection + wxGetApp().obj_layers()->reset_selection(); + wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false); + // select LayerRoor item and expand select_item(layers_item); Expand(layers_item);