OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::ObjectList Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/GUI_ObjectList.hpp>

Inheritance diagram for Slic3r::GUI::ObjectList:
Collaboration diagram for Slic3r::GUI::ObjectList:

Classes

struct  Clipboard
struct  dragged_item_data

Public Types

enum  SELECTION_MODE {
  smUndef = 0 , smVolume = 1 , smInstance = 2 , smLayer = 4 ,
  smSettings = 8 , smLayerRoot = 16
}
enum  OBJECT_ORGANIZE_TYPE { ortByPlate = 0 , ortByModule = 1 }

Public Member Functions

 ObjectList (wxWindow *parent)
 ~ObjectList () override
void set_min_height ()
void update_min_height ()
ObjectDataViewModel * GetModel () const
ModelConfig * config () const
std::vector< ModelObject * > * objects () const
ModelObject * object (const int obj_idx) const
void create_objects_ctrl ()
void update_objects_list_filament_column (size_t filaments_count)
void update_objects_list_filament_column_when_delete_filament (size_t filament_id, size_t filaments_count, int replace_filament_id=-1)
void update_filament_colors ()
void set_filament_column_hidden (const bool hide) const
void set_variable_height_column_hidden (const bool hide) const
void set_color_paint_hidden (const bool hide) const
void set_support_paint_hidden (const bool hide) const
void set_sinking_hidden (const bool hide) const
void update_filament_in_config (const wxDataViewItem &item)
void update_name_in_model (const wxDataViewItem &item) const
void update_name_in_list (int obj_idx, int vol_idx) const
void update_filament_values_for_items (const size_t filaments_count)
void update_filament_values_for_items_when_delete_filament (const size_t filament_id, const int replace_id=-1)
void update_plate_values_for_items ()
void update_name_for_items ()
void get_selected_item_indexes (int &obj_idx, int &vol_idx, const wxDataViewItem &item=wxDataViewItem(0))
void get_selection_indexes (std::vector< int > &obj_idxs, std::vector< int > &vol_idxs)
int get_repaired_errors_count (const int obj_idx, const int vol_idx=-1) const
MeshErrorsInfo get_mesh_errors_info (const int obj_idx, const int vol_idx=-1, wxString *sidebar_info=nullptr, int *non_manifold_edges=nullptr) const
MeshErrorsInfo get_mesh_errors_info (wxString *sidebar_info=nullptr, int *non_manifold_edges=nullptr)
void set_tooltip_for_item (const wxPoint &pt)
void selection_changed ()
void show_context_menu (const bool evt_context_menu)
void extruder_editing ()
void key_event (wxKeyEvent &event)
bool dispatch_shortcut (Shortcut shortcut)
void copy ()
void paste ()
void cut ()
void clone ()
bool cut_to_clipboard ()
bool copy_to_clipboard ()
bool paste_from_clipboard ()
void undo ()
void redo ()
void increase_instances ()
void decrease_instances ()
void add_category_to_settings_from_selection (const std::vector< std::pair< std::string, bool > > &category_options, wxDataViewItem item)
void add_category_to_settings_from_frequent (const std::vector< std::string > &category_options, wxDataViewItem item)
void show_settings (const wxDataViewItem settings_item)
bool is_instance_or_object_selected ()
void load_subobject (ModelVolumeType type, bool from_galery=false)
void load_modifier (const wxArrayString &input_files, ModelObject &model_object, std::vector< ModelVolume * > &added_volumes, ModelVolumeType type, bool from_galery=false)
void load_generic_subobject (const std::string &type_name, const ModelVolumeType type)
void load_shape_object (const std::string &type_name)
void load_mesh_object (const TriangleMesh &mesh, const wxString &name, bool center=true)
void load_mesh_object (const std::vector< std::pair< const TriangleMesh *, wxString > > &parts, const wxString &name, bool center=true)
void switch_to_object_process ()
bool del_object (const int obj_idx, bool refresh_immediately=true)
void del_subobject_item (wxDataViewItem &item)
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_from_cut_object (bool is_connector, bool is_model_part=false, bool is_negative_volume=false)
bool del_subobject_from_object (const int obj_idx, const int idx, const int type)
void del_info_item (const int obj_idx, InfoItemType type)
void split ()
void merge (bool to_multipart_object)
void layers_editing ()
void boolean ()
wxDataViewItem add_layer_root_item (const wxDataViewItem obj_item)
wxDataViewItem add_settings_item (wxDataViewItem parent_item, const DynamicPrintConfig *config)
DynamicPrintConfig get_default_layer_config (const int obj_idx)
bool get_volume_by_item (const wxDataViewItem &item, ModelVolume *&volume)
bool is_splittable (bool to_objects)
bool selected_instances_of_same_object ()
bool can_split_instances ()
bool can_merge_to_multipart_object () const
bool can_merge_to_single_object () const
bool can_mesh_boolean () const
bool has_selected_cut_object () const
void invalidate_cut_info_for_selection ()
void invalidate_cut_info_for_object (int obj_idx)
void delete_all_connectors_for_selection ()
void delete_all_connectors_for_object (int obj_idx)
wxPoint get_mouse_position_in_control () const
int get_selected_obj_idx () const
ModelConfig & get_item_config (const wxDataViewItem &item) const
void changed_object (const int obj_idx=-1) const
void part_selection_changed ()
void add_objects_to_list (std::vector< size_t > obj_idxs, bool call_selection_changed=true, bool notify_partplate=true, bool do_info_update=true)
void add_object_to_list (size_t obj_idx, bool call_selection_changed=true, bool notify_partplate=true, bool do_info_update=true)
wxDataViewItemArray add_volumes_to_object_in_list (size_t obj_idx, std::function< bool(const ModelVolume *)> add_to_selection=nullptr)
void delete_object_from_list ()
void delete_object_from_list (const size_t obj_idx)
void delete_volume_from_list (const size_t obj_idx, const size_t vol_idx)
void delete_instance_from_list (const size_t obj_idx, const size_t inst_idx)
void delete_from_model_and_list (const ItemType type, const int obj_idx, const int sub_obj_idx)
void delete_from_model_and_list (const std::vector< ItemForDelete > &items_for_delete)
void update_lock_icons_for_model ()
void delete_all_objects_from_list ()
void increase_object_instances (const size_t obj_idx, const size_t num)
void decrease_object_instances (const size_t obj_idx, const size_t num)
void unselect_objects ()
void select_object_item (bool is_msr_gizmo)
void remove ()
void del_layer_range (const t_layer_height_range &range)
void add_layer_range_after_current (const t_layer_height_range current_range)
wxString can_add_new_range_after_current (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)
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, bool suppress_ui_update=false)
void init ()
bool multiple_selection () const
bool is_selected (const ItemType type) const
bool is_connectors_item_selected () const
bool is_connectors_item_selected (const wxDataViewItemArray &sels) const
int get_selected_layers_range_idx () const
void set_selected_layers_range_idx (const int range_idx)
void set_selection_mode (SELECTION_MODE mode)
void update_selections ()
void update_selections_on_canvas ()
void select_item (const wxDataViewItem &item)
void select_item (std::function< wxDataViewItem()> get_item)
void select_items (const wxDataViewItemArray &sels)
void select_item (const ObjectVolumeID &ov_id)
void select_items (const std::vector< ObjectVolumeID > &ov_ids)
void select_all ()
void select_item_all_children ()
void update_selection_mode ()
bool check_last_selection (wxString &msg_str)
void fix_multiselection_conflicts ()
void fix_cut_selection ()
bool fix_cut_selection (wxDataViewItemArray &sels)
ModelVolume * get_selected_model_volume ()
void set_volume_type (ModelVolumeType new_type, bool preserve_ps_subtype=true)
ModelVolumeType get_selected_volume_type ()
void last_volume_is_deleted (const int obj_idx)
void update_and_show_object_settings_item ()
void update_settings_item_and_selection (wxDataViewItem item, wxDataViewItemArray &selections)
void update_object_list_by_printer_technology ()
void update_info_items (size_t obj_idx, wxDataViewItemArray *selections=nullptr, bool added_object=false, bool color_mode_changed=false)
void update_variable_layer_obj_num (ObjectDataViewModelNode *obj_node, size_t layer_data_count)
void instances_to_separated_object (const int obj_idx, const std::set< int > &inst_idx)
void instances_to_separated_objects (const int obj_idx)
void split_instances ()
void rename_item ()
void fix_through_cgal ()
void fix_all_through_cgal (bool all_plates)
void fix_through_cgal (const std::vector< int > &obj_idxs, const std::vector< int > &vol_idxs)
void simplify ()
void smooth_mesh ()
void update_item_error_icon (const int obj_idx, int vol_idx) const
void copy_layers_to_clipboard ()
void paste_layers_into_list ()
void copy_settings_to_clipboard ()
void paste_settings_into_list ()
bool can_paste_settings_into_list ()
bool clipboard_is_empty () const
void paste_volumes_into_list (int obj_idx, const ModelVolumePtrs &volumes)
void paste_objects_into_list (const std::vector< size_t > &object_idxs)
void msw_rescale ()
void sys_color_changed ()
void update_after_undo_redo ()
void update_printable_state (int obj_idx, int instance_idx)
void toggle_printable_state ()
void toggle_auto_drop ()
void enable_layers_editing ()
void set_extruder_for_selected_items (const int extruder)
wxDataViewItemArray reorder_volumes_and_get_selection (int obj_idx, std::function< bool(const ModelVolume *)> add_to_selection=nullptr)
void apply_volumes_order ()
void on_plate_added (PartPlate *part_plate)
void on_plate_deleted (int plate_index)
void reload_all_plates (bool notify_partplate=false)
void on_plate_selected (int plate_index)
void notify_instance_updated (int obj_idx)
void object_config_options_changed (const ObjectVolumeID &ov_id)
void printable_state_changed (const std::vector< ModelObject * > model_objects)
void printable_state_changed (const std::vector< ObjectVolumeID > &ov_ids)
void assembly_plate_object_name ()
void selected_object (ObjectDataViewModelNode *item)

Private Member Functions

void ensure_current_item_visible ()
void OnContextMenu (wxDataViewEvent &event)
void list_manipulation (const wxPoint &mouse_pos, bool evt_context_menu=false)
void update_name_column_width () const
void OnBeginDrag (wxDataViewEvent &event)
void OnDropPossible (wxDataViewEvent &event)
void OnDrop (wxDataViewEvent &event)
bool can_drop (const wxDataViewItem &item, int &src_obj_id, int &src_plate, int &dest_obj_id, int &dest_plate) const
void ItemValueChanged (wxDataViewEvent &event)
void OnStartEditing (wxDataViewEvent &event)
void OnEditingStarted (wxDataViewEvent &event)
void OnEditingDone (wxDataViewEvent &event)
void apply_object_instance_transfrom_to_all_volumes (ModelObject *model_object, bool need_update_assemble_matrix=true)

Private Attributes

SELECTION_MODE m_selection_mode {smUndef}
int m_selected_layers_range_idx {-1}
Clipboard m_clipboard
struct Slic3r::GUI::ObjectList::dragged_item_data m_dragged_data
ObjectDataViewModel * m_objects_model { nullptr }
ModelConfig * m_config {nullptr}
std::vector< ModelObject * > * m_objects { nullptr }
size_t m_variable_layer_obj_num = 0
BitmapComboBox * m_extruder_editor { nullptr }
std::vector< wxBitmap * > m_bmp_vector
int m_selected_object_id = -1
bool m_prevent_list_events = false
bool m_prevent_list_manipulation = false
bool m_prevent_update_filament_in_config = false
bool m_prevent_canvas_selection_update = false
wxDataViewItem m_last_selected_item {nullptr}
size_t m_items_count { size_t(-1) }
std::vector< int > m_columns_width
wxSize m_last_size

Detailed Description

Member Enumeration Documentation

◆ OBJECT_ORGANIZE_TYPE

Enumerator
ortByPlate 
ortByModule 
110 {
111 ortByPlate = 0,
112 ortByModule = 1,
113 };
@ ortByModule
Definition GUI_ObjectList.hpp:112
@ ortByPlate
Definition GUI_ObjectList.hpp:111

◆ SELECTION_MODE

Enumerator
smUndef 
smVolume 
smInstance 
smLayer 
smSettings 
smLayerRoot 
100 {
101 smUndef = 0,
102 smVolume = 1,
103 smInstance = 2,
104 smLayer = 4,
105 smSettings = 8, // used for undo/redo
106 smLayerRoot = 16, // used for undo/redo
107 };
@ smInstance
Definition GUI_ObjectList.hpp:103
@ smLayerRoot
Definition GUI_ObjectList.hpp:106
@ smLayer
Definition GUI_ObjectList.hpp:104
@ smUndef
Definition GUI_ObjectList.hpp:101
@ smVolume
Definition GUI_ObjectList.hpp:102
@ smSettings
Definition GUI_ObjectList.hpp:105

Constructor & Destructor Documentation

◆ ObjectList()

Slic3r::GUI::ObjectList::ObjectList ( wxWindow * parent)
193 :
194 wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE | wxNO_BORDER | wxDV_NO_HEADER) // ORCA: Remove border and header
195{
196 wxGetApp().UpdateDVCDarkUI(this, true);
197
198#ifdef __linux__
199 // Temporary fix for incorrect dark mode application regarding list item's text color.
200 // See: https://github.com/OrcaSlicer/OrcaSlicer/issues/2086
201 this->SetForegroundColour(*wxBLACK);
202#endif
203
204 SetFont(Label::sysFont(13));
205#ifdef __WXMSW__
206 static auto render = new wxRenderer;
207 wxRendererNative::Set(render);
208#endif
209
210 // create control
212
213 //BBS: add part plate related event
214 //Bind(EVT_PARTPLATE_LIST_PLATE_SELECT, &ObjectList::on_select_plate, this);
215
216 // describe control behavior
217 Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent& event) {
218 // detect the current mouse position here, to pass it to list_manipulation() method
219 // if we detect it later, the user may have moved the mouse pointer while calculations are performed, and this would mess-up the HitTest() call performed into list_manipulation()
220 if (!GetScreenRect().Contains(wxGetMousePosition())) {
221 return;
222 }
223#ifndef __WXOSX__
224 const wxPoint mouse_pos = this->get_mouse_position_in_control();
225#endif
226
227#ifndef __APPLE__
228 // On Windows and Linux:
229 // It's not invoked KillFocus event for "temporary" panels (like "Manipulation panel", "Settings", "Layer ranges"),
230 // if we change selection in object list.
231 // But, if we call SetFocus() for ObjectList it will cause an invoking of a KillFocus event for "temporary" panels
232 this->SetFocus();
233#else
234 // To avoid selection update from SetSelection() and UnselectAll() under osx
236 return;
237#endif // __APPLE__
238
239 /* For multiple selection with pressed SHIFT,
240 * event.GetItem() returns value of a first item in selection list
241 * instead of real last clicked item.
242 * So, let check last selected item in such strange way
243 */
244#ifdef __WXMSW__
245 // Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
246 int new_selected_column = -1;
247#endif //__WXMSW__
248 if (wxGetKeyState(WXK_SHIFT))
249 {
250 wxDataViewItemArray sels;
251 GetSelections(sels);
252 if (! sels.empty() && sels.front() == m_last_selected_item)
253 m_last_selected_item = sels.back();
254 else
255 m_last_selected_item = event.GetItem();
256 }
257 else {
258 wxDataViewItem new_selected_item = event.GetItem();
259 // BBS: use wxDataViewCtrl's internal mechanism
260#if 0
261#ifdef __WXMSW__
262 // Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
263 wxDataViewItem item;
264 wxDataViewColumn *col;
265 this->HitTest(this->get_mouse_position_in_control(), item, col);
266 new_selected_column = (col == nullptr) ? -1 : (int)col->GetModelColumn();
267 if (new_selected_item == m_last_selected_item && m_last_selected_column != -1 && m_last_selected_column != new_selected_column) {
268 // Mouse clicked on another column of the active row. Simulate keyboard enter to enter the editing mode of the current column.
269 wxUIActionSimulator sim;
270 sim.Char(WXK_RETURN);
271 }
272#endif //__WXMSW__
273#endif
274 m_last_selected_item = new_selected_item;
275 }
276#ifdef __WXMSW__
277 m_last_selected_column = new_selected_column;
278#endif //__WXMSW__
279
280 ObjectDataViewModelNode* sel_node = (ObjectDataViewModelNode*)event.GetItem().GetID();
281 if (sel_node && (sel_node->GetType() & ItemType::itPlate)) {
282 if (wxGetApp().plater()->is_preview_shown()) {
283 wxGetApp().plater()->select_sliced_plate(sel_node->GetPlateIdx());
284 } else {
285 wxGetApp().plater()->select_plate(sel_node->GetPlateIdx());
286 }
287 wxGetApp().plater()->deselect_all();
288 }
289 else {
291 }
292#ifndef __WXMSW__
294#endif //__WXMSW__
295
296#ifndef __WXOSX__
297 list_manipulation(mouse_pos);
298#endif //__WXOSX__
299 });
300
301#ifdef __WXOSX__
302 // Key events are not correctly processed by the wxDataViewCtrl on OSX.
303 // Our patched wxWidgets process the keyboard accelerators.
304 // On the other hand, using accelerators will break in-place editing on Windows & Linux/GTK (there is no in-place editing working on OSX for wxDataViewCtrl for now).
305 m_shortcut_id_base = wxWindow::NewControlId(int(Shortcut::Count));
306 for (size_t i = 0; i < size_t(Shortcut::Count); ++i)
307 this->Bind(wxEVT_MENU, [this, shortcut = Shortcut(i)](wxCommandEvent&) { dispatch_shortcut(shortcut); }, m_shortcut_id_base + int(i));
308 for (int i = 1; i < 10; i++)
309 this->Bind(wxEVT_MENU, [this, i](wxCommandEvent &evt) {
310 if (filaments_count() > 1 && i <= filaments_count())
312 }, wxID_LAST+i);
313 update_shortcut_accelerators();
314#else //__WXOSX__
315 Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX
316#endif
317
318#ifdef __WXMSW__
319 GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) {
320 // BBS
321 // this->SetFocus();
323 event.Skip();
324 });
325#endif //__WXMSW__
326
327 Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, &ObjectList::OnContextMenu, this);
328
329 // BBS
330 Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, &ObjectList::OnBeginDrag, this);
331 Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, &ObjectList::OnDropPossible, this);
332 Bind(wxEVT_DATAVIEW_ITEM_DROP, &ObjectList::OnDrop, this);
333
334 Bind(wxEVT_DATAVIEW_ITEM_START_EDITING, &ObjectList::OnStartEditing, this);
335 Bind(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, &ObjectList::OnEditingStarted, this);
336 Bind(wxEVT_DATAVIEW_ITEM_EDITING_DONE, &ObjectList::OnEditingDone, this);
337
338 Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &ObjectList::ItemValueChanged, this);
339
340 // BBS: dont need to do extra setting for a deleted object
341 //Bind(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED, [this](wxCommandEvent& e) { last_volume_is_deleted(e.GetInt()); });
342
343 Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) {
344 if (m_last_size == this->GetSize()) {
345 e.Skip();
346 return;
347 } else {
348 m_last_size = this->GetSize();
349 }
350
352
353 // BBS
354 this->CallAfter([this]() { ensure_current_item_visible(); });
355
356 e.Skip();
357 }));
358 m_last_size = this->GetSize();
359}
static wxFont sysFont(int size, bool bold=false)
Definition Label.cpp:28
void selection_changed()
Definition GUI_ObjectList.cpp:1267
void OnStartEditing(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:6667
wxSize m_last_size
Definition GUI_ObjectList.hpp:534
void OnEditingDone(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:6776
void OnEditingStarted(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:6700
void OnBeginDrag(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:1896
void create_objects_ctrl()
Definition GUI_ObjectList.cpp:400
bool dispatch_shortcut(Shortcut shortcut)
Definition GUI_ObjectList.cpp:1876
bool m_prevent_list_events
Definition GUI_ObjectList.hpp:187
void update_name_column_width() const
Definition GUI_ObjectList.cpp:1095
void list_manipulation(const wxPoint &mouse_pos, bool evt_context_menu=false)
Definition GUI_ObjectList.cpp:1531
void key_event(wxKeyEvent &event)
Definition GUI_ObjectList.cpp:1837
void OnDrop(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:2049
wxPoint get_mouse_position_in_control() const
Definition GUI_ObjectList.hpp:352
void set_extruder_for_selected_items(const int extruder)
Definition GUI_ObjectList.cpp:6812
wxDataViewItem m_last_selected_item
Definition GUI_ObjectList.hpp:199
void OnDropPossible(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:2038
void ItemValueChanged(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:6609
void OnContextMenu(wxDataViewEvent &event)
Definition GUI_ObjectList.cpp:1517
void ensure_current_item_visible()
Definition GUI_ObjectList.hpp:220
void set_tooltip_for_item(const wxPoint &pt)
Definition GUI_ObjectList.cpp:666
wxMouseEvent
Definition CameraPopup.cpp:47
Shortcut
Definition Shortcuts.hpp:25
@ Count
Definition Shortcuts.hpp:54
static Plater * plater()
Definition GUI_Factories.cpp:400
@ itPlate
Definition ObjectDataViewModel.hpp:36
static int filaments_count()
Definition GUI_Factories.cpp:65

References Slic3r::GUI::Count, create_objects_ctrl(), dispatch_shortcut(), ensure_current_item_visible(), Slic3r::GUI::filaments_count(), get_mouse_position_in_control(), Slic3r::GUI::ObjectDataViewModelNode::GetPlateIdx(), Slic3r::GUI::ObjectDataViewModelNode::GetType(), ItemValueChanged(), Slic3r::GUI::itPlate, key_event(), list_manipulation(), m_last_selected_item, m_last_size, m_prevent_list_events, OnBeginDrag(), OnContextMenu(), OnDrop(), OnDropPossible(), OnEditingDone(), OnEditingStarted(), OnStartEditing(), Slic3r::GUI::plater(), selection_changed(), set_extruder_for_selected_items(), set_tooltip_for_item(), Label::sysFont(), update_name_column_width(), and Slic3r::GUI::wxMouseEvent.

Referenced by update_name_column_width().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~ObjectList()

Slic3r::GUI::ObjectList::~ObjectList ( )
override
362{
363 if (m_objects_model)
364 m_objects_model->DecRef();
365}
ObjectDataViewModel * m_objects_model
Definition GUI_ObjectList.hpp:177

References m_objects_model.

Member Function Documentation

◆ add_category_to_settings_from_frequent()

void Slic3r::GUI::ObjectList::add_category_to_settings_from_frequent ( const std::vector< std::string > & category_options,
wxDataViewItem item )
2191{
2192 const ItemType item_type = m_objects_model->GetItemType(item);
2193
2194 if (!m_config)
2195 m_config = &get_item_config(item);
2196
2197 assert(m_config);
2198 auto opt_keys = m_config->keys();
2199
2200 const std::string snapshot_text = item_type & itLayer ? _u8L("Height range settings added") :
2201 item_type & itVolume ? _u8L("Part settings added") :
2202 _u8L("Object settings added");
2203 take_snapshot(snapshot_text);
2204
2205 const DynamicPrintConfig& from_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
2206 for (auto& opt_key : options)
2207 {
2208 if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end()) {
2209 const ConfigOption* option = from_config.option(opt_key);
2210 if (!option) {
2211 // if current option doesn't exist in prints.get_edited_preset(),
2212 // get it from default config values
2213 option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key);
2214 }
2215 m_config->set_key_value(opt_key, option->clone());
2216 }
2217 }
2218
2219 // Add settings item for object/sub-object and show them
2220 if (!(item_type & (itPlate | itObject | itVolume | itLayer)))
2221 item = m_objects_model->GetObject(item);
2222
2224}
static DynamicPrintConfig * new_from_defaults_keys(const std::vector< std::string > &keys)
Definition PrintConfig.cpp:10311
ModelConfig * m_config
Definition GUI_ObjectList.hpp:178
void show_settings(const wxDataViewItem settings_item)
Definition GUI_ObjectList.cpp:2226
ModelConfig & get_item_config(const wxDataViewItem &item) const
Definition GUI_ObjectList.cpp:735
wxDataViewItem add_settings_item(wxDataViewItem parent_item, const DynamicPrintConfig *config)
Definition GUI_ObjectList.cpp:3954
static void take_snapshot(const std::string &snapshot_name)
Definition GUI_ObjectList.cpp:141
ItemType
Definition ObjectDataViewModel.hpp:34
@ itObject
Definition ObjectDataViewModel.hpp:37
@ itLayer
Definition ObjectDataViewModel.hpp:43
@ itVolume
Definition ObjectDataViewModel.hpp:38
RaycastManager::TrItems::iterator find(RaycastManager::TrItems &items, const RaycastManager::TrKey &key)
Definition RaycastManager.cpp:298
#define _u8L(s)
Definition I18N.hpp:11

References _u8L, add_settings_item(), Slic3r::ConfigOption::clone(), get_item_config(), Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itPlate, Slic3r::GUI::itVolume, m_config, m_objects_model, Slic3r::DynamicPrintConfig::new_from_defaults_keys(), Slic3r::ConfigBase::option(), show_settings(), and Slic3r::GUI::take_snapshot().

Referenced by Slic3r::GUI::create_freq_settings_popupmenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_category_to_settings_from_selection()

void Slic3r::GUI::ObjectList::add_category_to_settings_from_selection ( const std::vector< std::pair< std::string, bool > > & category_options,
wxDataViewItem item )
2147{
2148 if (category_options.empty())
2149 return;
2150
2151 const ItemType item_type = m_objects_model->GetItemType(item);
2152
2153 if (!m_config)
2154 m_config = &get_item_config(item);
2155
2156 assert(m_config);
2157 auto opt_keys = m_config->keys();
2158
2159 const std::string snapshot_text = item_type & itLayer ? _u8L("Layer setting added") :
2160 item_type & itVolume ? _u8L("Part setting added") :
2161 _u8L("Object setting added");
2162 take_snapshot(snapshot_text);
2163
2164 const DynamicPrintConfig& from_config = printer_technology() == ptFFF ?
2165 wxGetApp().preset_bundle->prints.get_edited_preset().config :
2166 wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
2167
2168 for (auto& opt : category_options) {
2169 auto& opt_key = opt.first;
2170 if (find(opt_keys.begin(), opt_keys.end(), opt_key) != opt_keys.end() && !opt.second)
2171 m_config->erase(opt_key);
2172
2173 if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() && opt.second) {
2174 const ConfigOption* option = from_config.option(opt_key);
2175 if (!option) {
2176 // if current option doesn't exist in prints.get_edited_preset(),
2177 // get it from default config values
2178 option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key);
2179 }
2180 m_config->set_key_value(opt_key, option->clone());
2181 }
2182 }
2183
2184 // Add settings item for object/sub-object and show them
2185 if (!(item_type & (itPlate | itObject | itVolume | itLayer)))
2186 item = m_objects_model->GetObject(item);
2188}
static PrinterTechnology printer_technology()
Definition GUI_Factories.cpp:60
@ ptFFF
Definition Config.hpp:231

References _u8L, add_settings_item(), Slic3r::ConfigOption::clone(), get_item_config(), Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itPlate, Slic3r::GUI::itVolume, m_config, m_objects_model, Slic3r::DynamicPrintConfig::new_from_defaults_keys(), Slic3r::ConfigBase::option(), Slic3r::GUI::printer_technology(), Slic3r::ptFFF, show_settings(), and Slic3r::GUI::take_snapshot().

Here is the call graph for this function:

◆ add_layer_item()

void Slic3r::GUI::ObjectList::add_layer_item ( const t_layer_height_range & range,
const wxDataViewItem layers_item,
const int layer_idx = -1 )
4794{
4795 const int obj_idx = m_objects_model->GetObjectIdByItem(layers_item);
4796 if (obj_idx < 0) return;
4797
4798 const DynamicPrintConfig& config = object(obj_idx)->layer_config_ranges[range].get();
4799 if (!config.has("extruder"))
4800 return;
4801
4802 const auto layer_item = m_objects_model->AddLayersChild(layers_item,
4803 range,
4804 config.opt_int("extruder"),
4805 layer_idx);
4806 add_settings_item(layer_item, &config);
4807}
ModelObject * object(const int obj_idx) const
Definition GUI_ObjectList.cpp:7139
ModelConfig * config() const
Definition GUI_ObjectList.hpp:234
t_layer_config_ranges layer_config_ranges
Definition Model.hpp:397
auto range(Cont &&cont)
Definition libslic3r.h:405

References add_settings_item(), config(), Slic3r::ModelObject::layer_config_ranges, m_objects_model, object(), and Slic3r::range().

Referenced by add_layer_range_after_current(), add_layer_root_item(), and edit_layer_range().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_layer_range_after_current()

void Slic3r::GUI::ObjectList::add_layer_range_after_current ( const t_layer_height_range current_range)
4671{
4672 const int obj_idx = get_selected_obj_idx();
4673 assert(obj_idx >= 0);
4674 if (obj_idx < 0)
4675 // This should not happen.
4676 return;
4677
4678 const wxDataViewItem layers_item = GetSelection();
4679
4680 auto& ranges = object(obj_idx)->layer_config_ranges;
4681 auto it_range = ranges.find(current_range);
4682 assert(it_range != ranges.end());
4683 if (it_range == ranges.end())
4684 // This shoudl not happen.
4685 return;
4686
4687 auto it_next_range = it_range;
4688 bool changed = false;
4689 if (++ it_next_range == ranges.end())
4690 {
4691 // Adding a new layer height range after the last one.
4692 // BBS: remove snapshot name "Add Height Range"
4693 take_snapshot("");
4694 changed = true;
4695
4696 const t_layer_height_range new_range = { current_range.second, current_range.second + 2. };
4697 ranges[new_range].assign_config(get_default_layer_config(obj_idx));
4698 add_layer_item(new_range, layers_item);
4699 }
4700 else if (const std::pair<coordf_t, coordf_t> &next_range = it_next_range->first; current_range.second <= next_range.first)
4701 {
4702 const int layer_idx = m_objects_model->GetItemIdByLayerRange(obj_idx, next_range);
4703 assert(layer_idx >= 0);
4704 if (layer_idx >= 0)
4705 {
4706 if (current_range.second == next_range.first)
4707 {
4708 // Splitting the next layer height range to two.
4709 const auto old_config = ranges.at(next_range);
4710 const coordf_t delta = next_range.second - next_range.first;
4711 // Layer height of the current layer.
4712 const coordf_t old_min_layer_height = get_min_layer_height(old_config.opt_int("extruder"));
4713 // Layer height of the layer to be inserted.
4714 const coordf_t new_min_layer_height = get_min_layer_height(0);
4715 if (delta >= old_min_layer_height + new_min_layer_height - EPSILON) {
4716 const coordf_t middle_layer_z = (new_min_layer_height > 0.5 * delta) ?
4717 next_range.second - new_min_layer_height :
4718 next_range.first + std::max(old_min_layer_height, 0.5 * delta);
4719 t_layer_height_range new_range = { middle_layer_z, next_range.second };
4720
4721 // BBS: remove snapshot name "Add Height Range"
4722 Plater::TakeSnapshot snapshot(wxGetApp().plater(), "");
4723 changed = true;
4724
4725 // create new 2 layers instead of deleted one
4726 // delete old layer
4727
4728 wxDataViewItem layer_item = m_objects_model->GetItemByLayerRange(obj_idx, next_range);
4729 del_subobject_item(layer_item);
4730
4731 ranges[new_range] = old_config;
4732 add_layer_item(new_range, layers_item, layer_idx);
4733
4734 new_range = { current_range.second, middle_layer_z };
4735 ranges[new_range].assign_config(get_default_layer_config(obj_idx));
4736 add_layer_item(new_range, layers_item, layer_idx);
4737 }
4738 }
4739 else if (next_range.first - current_range.second >= get_min_layer_height(0) - EPSILON)
4740 {
4741 // Filling in a gap between the current and a new layer height range with a new one.
4742 // BBS: remove snapshot name "Add Height Range"
4743 take_snapshot("");
4744 changed = true;
4745
4746 const t_layer_height_range new_range = { current_range.second, next_range.first };
4747 ranges[new_range].assign_config(get_default_layer_config(obj_idx));
4748 add_layer_item(new_range, layers_item, layer_idx);
4749 }
4750 }
4751 }
4752
4753 if (changed)
4754 changed_object(obj_idx);
4755
4756 // The layer range panel is updated even if this function does not change the layer ranges, as the panel update
4757 // may have been postponed from the "kill focus" event of a text field, if the focus was lost for the "add layer" button.
4758 // select item to update layers sizer
4759 select_item(layers_item);
4760}
#define EPSILON
Definition ColorUtils.cpp:64
void add_layer_item(const t_layer_height_range &range, const wxDataViewItem layers_item, const int layer_idx=-1)
Definition GUI_ObjectList.cpp:4791
DynamicPrintConfig get_default_layer_config(const int obj_idx)
Definition GUI_ObjectList.cpp:3494
int get_selected_obj_idx() const
Definition GUI_ObjectList.cpp:727
void changed_object(const int obj_idx=-1) const
Definition GUI_ObjectList.cpp:3716
void select_item(const wxDataViewItem &item)
Definition GUI_ObjectList.cpp:5269
void del_subobject_item(wxDataViewItem &item)
Definition GUI_ObjectList.cpp:2736
static double get_min_layer_height(const int extruder_idx)
Definition GUI_ObjectList.cpp:4650
double coordf_t
Definition GUI_ObjectLayers.hpp:26
std::pair< coordf_t, coordf_t > t_layer_height_range
Definition GUI_ObjectLayers.hpp:27

References add_layer_item(), changed_object(), del_subobject_item(), EPSILON, get_default_layer_config(), Slic3r::GUI::get_min_layer_height(), get_selected_obj_idx(), Slic3r::ModelObject::layer_config_ranges, m_objects_model, object(), Slic3r::GUI::plater(), select_item(), and Slic3r::GUI::take_snapshot().

Here is the call graph for this function:

◆ add_layer_root_item()

wxDataViewItem Slic3r::GUI::ObjectList::add_layer_root_item ( const wxDataViewItem obj_item)
3476{
3477 const int obj_idx = m_objects_model->GetIdByItem(obj_item);
3478 if (obj_idx < 0 ||
3479 object(obj_idx)->layer_config_ranges.empty() ||
3481 return wxDataViewItem(nullptr);
3482
3483 // create LayerRoot item
3484 wxDataViewItem layers_item = m_objects_model->AddLayersRoot(obj_item);
3485
3486 // and create Layer item(s) according to the layer_config_ranges
3487 for (const auto& range : object(obj_idx)->layer_config_ranges)
3488 add_layer_item(range.first, layers_item);
3489
3490 Expand(layers_item);
3491 return layers_item;
3492}
@ ptSLA
Definition Config.hpp:233

References add_layer_item(), m_objects_model, Slic3r::GUI::printer_technology(), Slic3r::ptSLA, and Slic3r::range().

Referenced by add_object_to_list(), layers_editing(), paste_layers_into_list(), and update_object_list_by_printer_technology().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_object_to_list()

void Slic3r::GUI::ObjectList::add_object_to_list ( size_t obj_idx,
bool call_selection_changed = true,
bool notify_partplate = true,
bool do_info_update = true )
4215{
4216 auto model_object = (*m_objects)[obj_idx];
4217 //BBS start add obj_idx for debug
4218 PartPlateList& list = wxGetApp().plater()->get_partplate_list();
4219 if (notify_partplate) {
4220 list.notify_instance_update(obj_idx, 0, true);
4221 }
4222 //int plate_idx = list.find_instance_belongs(obj_idx, 0);
4223 //std::string item_name_str = (boost::format("[P%1%][O%2%]%3%") % plate_idx % std::to_string(obj_idx) % model_object->name).str();
4224 //std::string item_name_str = (boost::format("[P%1%]%2%") % plate_idx % model_object->name).str();
4225 //const wxString& item_name = from_u8(item_name_str);
4226 const wxString& item_name = from_u8(model_object->name);
4227 std::string warning_bitmap = get_warning_icon_name(model_object->mesh().stats());
4228 const auto item = m_objects_model->AddObject(model_object, warning_bitmap, model_object->is_cut());
4229 Expand(m_objects_model->GetParent(item));
4230
4231 {
4232 Slic3r::LifecycleEventContext ctx;
4233 ctx.name = model_object->name;
4236 }
4237
4238 if (!do_info_update)
4239 return;
4240
4241 update_info_items(obj_idx, nullptr, call_selection_changed);
4242
4244
4245 // add instances to the object, if it has those
4246 if (model_object->instances.size()>1)
4247 {
4248 std::vector<bool> print_idicator(model_object->instances.size());
4249 std::vector<int> plate_idicator(model_object->instances.size());
4250 for (size_t i = 0; i < model_object->instances.size(); ++i) {
4251 print_idicator[i] = model_object->instances[i]->printable;
4252 plate_idicator[i] = list.find_instance_belongs(obj_idx, i);
4253 }
4254
4255 const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx);
4256 m_objects_model->AddInstanceChild(object_item, print_idicator, plate_idicator);
4257 Expand(m_objects_model->GetInstanceRootItem(object_item));
4258 }
4259 else
4260 m_objects_model->SetPrintableState(model_object->instances[0]->printable ? piPrintable : piUnprintable, obj_idx);
4261
4262 m_objects_model->SetObjectVariableHeightState(model_object->layer_height_profile.get().size() > 4 ? hiVariable : hiUnVariable, m_objects_model->GetItemById(obj_idx));
4263
4264 // add settings to the object, if it has those
4265 add_settings_item(item, &model_object->config.get());
4266
4267 // Add layers if it has
4268 add_layer_root_item(item);
4269
4270#ifndef __WXOSX__
4271 if (call_selection_changed) {
4272 UnselectAll();
4273 Select(item);
4275 }
4276#endif //__WXMSW__
4277}
wxDataViewItemArray add_volumes_to_object_in_list(size_t obj_idx, std::function< bool(const ModelVolume *)> add_to_selection=nullptr)
Definition GUI_ObjectList.cpp:4297
void update_info_items(size_t obj_idx, wxDataViewItemArray *selections=nullptr, bool added_object=false, bool color_mode_changed=false)
Definition GUI_ObjectList.cpp:4039
wxDataViewItem add_layer_root_item(const wxDataViewItem obj_item)
Definition GUI_ObjectList.cpp:3475
static std::string get_warning_icon_name(const TriangleMeshStats &stats)
Definition GUI_ObjectList.cpp:600
wxString from_u8(const std::string &str)
Definition GUI.cpp:544
@ hiVariable
Definition ObjectDataViewModel.hpp:71
@ hiUnVariable
Definition ObjectDataViewModel.hpp:70
@ piUnprintable
Definition ObjectDataViewModel.hpp:65
@ piPrintable
Definition ObjectDataViewModel.hpp:64
std::string name
Definition LifecycleEvents.hpp:75
@ ObjectAdded
Definition LifecycleEvents.hpp:36
@ Ok
Definition LifecycleEvents.hpp:68
LifecycleEvtCode code
Definition LifecycleEvents.hpp:79
void fire_lifecycle_event(LifecycleEvent event, const LifecycleEventContext &ctx)
Definition LifecycleEvents.hpp:234

References add_layer_root_item(), add_settings_item(), add_volumes_to_object_in_list(), Slic3r::LifecycleEventContext::code, Slic3r::GUI::PartPlateList::find_instance_belongs(), Slic3r::fire_lifecycle_event(), Slic3r::GUI::from_u8(), Slic3r::GUI::get_warning_icon_name(), Slic3r::GUI::hiUnVariable, Slic3r::GUI::hiVariable, m_objects_model, Slic3r::LifecycleEventContext::name, Slic3r::GUI::PartPlateList::notify_instance_update(), Slic3r::ObjectAdded, Slic3r::Ok, Slic3r::GUI::piPrintable, Slic3r::GUI::piUnprintable, selection_changed(), and update_info_items().

Referenced by Slic3r::GUI::Plater::_calib_pa_pattern(), add_objects_to_list(), boolean(), instances_to_separated_object(), instances_to_separated_objects(), merge(), paste_objects_into_list(), and reload_all_plates().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_objects_to_list()

void Slic3r::GUI::ObjectList::add_objects_to_list ( std::vector< size_t > obj_idxs,
bool call_selection_changed = true,
bool notify_partplate = true,
bool do_info_update = true )
4201{
4202#ifdef __WXOSX__
4203 AssociateModel(nullptr);
4204#endif
4205 for (const size_t idx : obj_idxs) {
4206 add_object_to_list(idx, call_selection_changed, notify_partplate, do_info_update);
4207 }
4208#ifdef __WXOSX__
4209 AssociateModel(m_objects_model);
4210#endif
4211}
void add_object_to_list(size_t obj_idx, bool call_selection_changed=true, bool notify_partplate=true, bool do_info_update=true)
Definition GUI_ObjectList.cpp:4214

References add_object_to_list(), and m_objects_model.

Here is the call graph for this function:

◆ add_settings_item()

wxDataViewItem Slic3r::GUI::ObjectList::add_settings_item ( wxDataViewItem parent_item,
const DynamicPrintConfig * config )
3955{
3956 wxDataViewItem ret = wxDataViewItem(nullptr);
3957
3958 if (!parent_item)
3959 return ret;
3960
3961 const bool is_object_settings = m_objects_model->GetItemType(parent_item) == itObject;
3962 const bool is_volume_settings = m_objects_model->GetItemType(parent_item) == itVolume;
3963 const bool is_layer_settings = m_objects_model->GetItemType(parent_item) == itLayer;
3964 if (!is_object_settings) {
3965 ModelVolumeType volume_type = m_objects_model->GetVolumeType(parent_item);
3966 // Precise Seam is non-printing helper geometry — no per-volume settings
3967 if (volume_type == ModelVolumeType::NEGATIVE_VOLUME || volume_type == ModelVolumeType::SUPPORT_BLOCKER || volume_type == ModelVolumeType::SUPPORT_ENFORCER || is_precise_seam(volume_type))
3968 return ret;
3969 }
3970
3971 SettingsFactory::Bundle cat_options = SettingsFactory::get_bundle(config, is_object_settings, is_layer_settings);
3972 if (is_layer_settings) {
3973 auto tab_object = dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab());
3974 auto object_cfg = tab_object->get_config();
3975 if (config->opt_float("layer_height") == object_cfg->opt_float("layer_height")) {
3976 SettingsFactory::Bundle new_cat_options;
3977 for (auto cat_opt : cat_options) {
3978 std::vector<std::string> temp;
3979 for (auto value : cat_opt.second) {
3980 if (value != "layer_height")
3981 temp.push_back(value);
3982 }
3983 if (!temp.empty())
3984 new_cat_options[cat_opt.first] = temp;
3985 }
3986 cat_options = new_cat_options;
3987 }
3988 }
3989
3990 if (cat_options.empty()) {
3991#if NEW_OBJECT_SETTING
3992 ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
3993 if (node) node->set_action_icon(false);
3994 m_objects_model->ItemChanged(parent_item);
3995 return parent_item;
3996#else
3997 return ret;
3998#endif
3999 }
4000
4001 std::vector<std::string> categories;
4002 categories.reserve(cat_options.size());
4003 for (auto& cat : cat_options)
4004 categories.push_back(cat.first);
4005
4006 if (m_objects_model->GetItemType(parent_item) & itInstance)
4007 parent_item = m_objects_model->GetObject(parent_item);
4008
4009#if NEW_OBJECT_SETTING
4010 ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode*>(parent_item.GetID());
4011 if (node) node->set_action_icon(true);
4012 m_objects_model->ItemChanged(parent_item);
4013 return parent_item;
4014#else
4015 ret = m_objects_model->IsSettingsItem(parent_item) ? parent_item : m_objects_model->GetSettingsItem(parent_item);
4016
4017 if (!ret) ret = m_objects_model->AddSettingsChild(parent_item);
4018
4019 m_objects_model->UpdateSettingsDigest(ret, categories);
4020 Expand(parent_item);
4021
4022 return ret;
4023#endif
4024}
@ itInstance
Definition ObjectDataViewModel.hpp:40
ModelVolumeType
Definition Model.hpp:355
@ SUPPORT_BLOCKER
Definition Model.hpp:360
@ NEGATIVE_VOLUME
Definition Model.hpp:358
@ SUPPORT_ENFORCER
Definition Model.hpp:361
bool is_precise_seam(ModelVolumeType t)
Definition Model.hpp:373
static Bundle get_bundle(const DynamicPrintConfig *config, bool is_object_settings, bool is_layer_settings=false)
Definition GUI_Factories.cpp:299
std::map< std::string, std::vector< std::string > > Bundle
Definition GUI_Factories.hpp:34

References config(), Slic3r::GUI::SettingsFactory::get_bundle(), Slic3r::GUI::Tab::get_config(), Slic3r::is_precise_seam(), Slic3r::GUI::itInstance, Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_objects_model, Slic3r::NEGATIVE_VOLUME, Slic3r::GUI::ObjectDataViewModelNode::set_action_icon(), Slic3r::SUPPORT_BLOCKER, and Slic3r::SUPPORT_ENFORCER.

Referenced by add_category_to_settings_from_frequent(), add_category_to_settings_from_selection(), add_layer_item(), add_object_to_list(), add_volumes_to_object_in_list(), del_subobject_from_object(), object_config_options_changed(), paste_settings_into_list(), split(), and update_settings_item_and_selection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ add_volumes_to_object_in_list()

wxDataViewItemArray Slic3r::GUI::ObjectList::add_volumes_to_object_in_list ( size_t obj_idx,
std::function< bool(const ModelVolume *)> add_to_selection = nullptr )
4298{
4299 const bool is_prevent_list_events = m_prevent_list_events;
4300 m_prevent_list_events = true;
4301
4302 wxDataViewItem object_item = m_objects_model->GetItemById(int(obj_idx));
4303 m_objects_model->DeleteVolumeChildren(object_item);
4304
4305 wxDataViewItemArray items;
4306
4307 const ModelObject *object = (*m_objects)[obj_idx];
4308 // add volumes to the object
4309 if (can_add_volumes_to_object(object)) {
4310 if (object->volumes.size() > 1) {
4311 wxString obj_item_name = from_u8(object->name);
4312 if (m_objects_model->GetName(object_item) != obj_item_name)
4313 m_objects_model->SetName(obj_item_name, object_item);
4314 }
4315
4316 int volume_idx{-1};
4317 auto& ui_and_3d_volume_map = m_objects_model->get_ui_and_3d_volume_map();
4318 for (auto item : ui_and_3d_volume_map) {
4319 if (item.first == obj_idx) {
4320 item.second.clear();
4321 }
4322 }
4323 int ui_volume_idx = 0;
4324 for (const ModelVolume *volume : object->volumes) {
4325 ++volume_idx;
4326 if (object->is_cut() && volume->is_cut_connector())
4327 continue;
4328
4329 const wxDataViewItem &vol_item = m_objects_model->AddVolumeChild(
4330 object_item,
4331 from_u8(volume->name),
4332 volume->type(),
4333 volume->is_text(),
4334 volume->is_svg(),
4335 get_warning_icon_name(volume->mesh().stats()),
4336 volume->config.has("extruder") ? volume->config.extruder() : 0,
4337 false);
4338 ui_and_3d_volume_map[obj_idx][ui_volume_idx] = volume_idx;
4339 ui_volume_idx++;
4340 add_settings_item(vol_item, &volume->config.get());
4341
4342 if (add_to_selection && add_to_selection(volume))
4343 items.Add(vol_item);
4344 }
4345 Expand(object_item);
4346 }
4347
4348 m_prevent_list_events = is_prevent_list_events;
4349 return items;
4350}
static bool can_add_volumes_to_object(const ModelObject *object)
Definition GUI_ObjectList.cpp:4279

References add_settings_item(), Slic3r::GUI::can_add_volumes_to_object(), Slic3r::ModelVolume::config, Slic3r::ModelConfig::extruder(), Slic3r::GUI::from_u8(), Slic3r::ModelConfig::get(), Slic3r::GUI::get_warning_icon_name(), Slic3r::ModelConfig::has(), Slic3r::ModelVolume::is_cut_connector(), Slic3r::ModelVolume::is_svg(), Slic3r::ModelVolume::is_text(), m_objects_model, m_prevent_list_events, Slic3r::ModelVolume::mesh(), Slic3r::ModelVolume::name, object(), Slic3r::TriangleMesh::stats(), and Slic3r::ModelVolume::type().

Referenced by add_object_to_list(), delete_all_connectors_for_object(), invalidate_cut_info_for_object(), and reorder_volumes_and_get_selection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ apply_object_instance_transfrom_to_all_volumes()

void Slic3r::GUI::ObjectList::apply_object_instance_transfrom_to_all_volumes ( ModelObject * model_object,
bool need_update_assemble_matrix = true )
private
7148{
7149 const Geometry::Transformation &instance_transformation = model_object->instances[0]->get_transformation();
7150 Vec3d original_instance_center = instance_transformation.get_offset();
7151
7152 if (need_update_assemble_matrix) {
7153 // apply the instance_transform(except offset) to assemble_transform
7154 Geometry::Transformation instance_transformation_copy = instance_transformation;
7155 instance_transformation_copy.set_offset(Vec3d(0, 0, 0)); // remove the effect of offset
7156 const Transform3d &instance_inverse_matrix = instance_transformation_copy.get_matrix().inverse();
7157 const Transform3d &assemble_matrix = model_object->instances[0]->get_assemble_transformation().get_matrix();
7158 Transform3d new_assemble_transform = assemble_matrix * instance_inverse_matrix;
7159 model_object->instances[0]->set_assemble_from_transform(new_assemble_transform);
7160 }
7161
7162 // apply the instance_transform to volumn
7163 const Transform3d &transformation_matrix = instance_transformation.get_matrix();
7164 for (ModelVolume *volume : model_object->volumes) {
7165 const Transform3d &volume_matrix = volume->get_matrix();
7166 Transform3d new_matrix = transformation_matrix * volume_matrix;
7167 volume->set_transformation(new_matrix);
7168 }
7169 model_object->instances[0]->set_transformation(Geometry::Transformation());
7170
7171 model_object->ensure_on_bed();
7172 // keep new instance center the same as the original center
7173 model_object->translate(-original_instance_center);
7174 model_object->translate_instances(original_instance_center);
7175
7176 // update the cache data in selection to keep the data of ModelVolume and GLVolume are consistent
7177 wxGetApp().plater()->update();
7178}
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96

References Slic3r::ModelObject::ensure_on_bed(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::ModelVolume::get_matrix(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::ModelObject::instances, Slic3r::Geometry::Transformation::set_offset(), Slic3r::ModelVolume::set_transformation(), Slic3r::ModelObject::translate(), Slic3r::ModelObject::translate_instances(), and Slic3r::ModelObject::volumes.

Referenced by load_generic_subobject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ apply_volumes_order()

void Slic3r::GUI::ObjectList::apply_volumes_order ( )
7005{
7006 if (!m_objects)
7007 return;
7008
7009 for (size_t obj_idx = 0; obj_idx < m_objects->size(); obj_idx++)
7011}
wxDataViewItemArray reorder_volumes_and_get_selection(int obj_idx, std::function< bool(const ModelVolume *)> add_to_selection=nullptr)
Definition GUI_ObjectList.cpp:6986
std::vector< ModelObject * > * m_objects
Definition GUI_ObjectList.hpp:179

References m_objects, and reorder_volumes_and_get_selection().

Here is the call graph for this function:

◆ assembly_plate_object_name()

void Slic3r::GUI::ObjectList::assembly_plate_object_name ( )
1031{
1032 m_objects_model->assembly_name();
1033}

References m_objects_model.

◆ boolean()

void Slic3r::GUI::ObjectList::boolean ( )
3398{
3399 std::vector<int> obj_idxs, vol_idxs;
3400 get_selection_indexes(obj_idxs, vol_idxs);
3401 if (obj_idxs.empty() && vol_idxs.empty())
3402 return;
3403
3404 Plater::TakeSnapshot snapshot(wxGetApp().plater(), "boolean");
3405
3406 ModelObject* object = (*m_objects)[obj_idxs.front()];
3407
3408 const bool keep_painting = wxGetApp().app_config->get_bool("keep_painting");
3409 std::vector<std::optional<TriangleSelector::SavedPainting>> saved_paintings;
3410 if (keep_painting) {
3411 // Save painting of all the positive parts
3412 saved_paintings.reserve(object->volumes.size());
3413 for (const ModelVolume* vol : object->volumes) {
3414 if (vol && vol->mesh_ptr() && vol->is_model_part() && vol->is_any_painted()) {
3415 saved_paintings.emplace_back(vol->save_painting());
3416 if (saved_paintings.back()) {
3417 saved_paintings.back()->mesh.transform(vol->get_matrix(), true);
3418 }
3419 }
3420 }
3421 }
3422
3423 TriangleMesh mesh = Plater::combine_mesh_fff(*object, -1, [](const std::string& msg) {return wxGetApp().notification_manager()->push_plater_error_notification(msg); });
3424
3425 // add mesh to model as a new object, keep the original object's name and config
3426 Model* model = object->get_model();
3427 ModelObject* new_object = model->add_object();
3428 new_object->name = object->name;
3429 new_object->config.assign_config(object->config);
3430 if (new_object->instances.empty())
3431 new_object->add_instance();
3432 ModelVolume* new_volume = new_object->add_volume(mesh);
3433
3434 // Remap paint
3435 if (keep_painting) {
3436 for (auto& saved_painting : saved_paintings) {
3437 if (saved_painting) {
3438 // For each original painted volume, we need to apply to each instance
3439 // because we merged all instances into one in `combine_mesh_fff`
3440
3441 // First we save the non-instance-translated mesh
3442 TriangleMesh vols_mesh(std::move(saved_painting->mesh));
3443
3444 for (const ModelInstance* i : object->instances) {
3445 // Then for each instance, we apply the paint at the given instance place
3446 saved_painting->mesh = vols_mesh;
3447 saved_painting->mesh.transform(i->get_matrix());
3448
3449 // Then paint it
3450 new_volume->restore_painting(saved_painting, true);
3451 }
3452
3453 }
3454 }
3455 }
3456
3457 // BBS: ensure on bed but no need to ensure locate in the center around origin
3458 new_object->ensure_on_bed();
3459 new_object->center_around_origin();
3460 new_object->translate_instances(-new_object->origin_translation);
3461 new_object->origin_translation = Vec3d::Zero();
3462
3463 // BBS: notify it before move
3465
3466 // remove selected objects
3467 remove();
3468
3469 // Add new object(UNION) to the object_list
3470 add_object_to_list(m_objects->size() - 1);
3471 select_item(m_objects_model->GetItemById(m_objects->size() - 1));
3473}
void get_selection_indexes(std::vector< int > &obj_idxs, std::vector< int > &vol_idxs)
Definition GUI_ObjectList.cpp:564
void remove()
Definition GUI_ObjectList.cpp:4577
void update_selections_on_canvas()
Definition GUI_ObjectList.cpp:5149
void notify_instance_updated(int obj_idx)
Definition GUI_ObjectList.cpp:6970
static TriangleMesh combine_mesh_fff(const ModelObject &mo, int instance_id, std::function< void(const std::string &)> notify_func={})
Definition Plater.cpp:19986

References Slic3r::ModelObject::add_instance(), add_object_to_list(), Slic3r::ModelObject::add_volume(), Slic3r::ModelConfig::assign_config(), Slic3r::ModelObject::center_around_origin(), Slic3r::GUI::Plater::combine_mesh_fff(), Slic3r::ModelObject::config, Slic3r::ModelObject::ensure_on_bed(), Slic3r::ModelInstance::get_matrix(), Slic3r::ModelVolume::get_matrix(), get_selection_indexes(), Slic3r::ModelObject::instances, Slic3r::ModelVolume::is_any_painted(), Slic3r::ModelVolume::is_model_part(), m_objects, m_objects_model, Slic3r::ModelVolume::mesh_ptr(), Slic3r::ModelObject::name, notify_instance_updated(), object(), Slic3r::ModelObject::origin_translation, Slic3r::GUI::plater(), remove(), Slic3r::ModelVolume::restore_painting(), Slic3r::ModelVolume::save_painting(), select_item(), Slic3r::TriangleMesh::transform(), Slic3r::ModelObject::translate_instances(), and update_selections_on_canvas().

Here is the call graph for this function:

◆ can_add_new_range_after_current()

wxString Slic3r::GUI::ObjectList::can_add_new_range_after_current ( t_layer_height_range current_range)
4766{
4767 const int obj_idx = get_selected_obj_idx();
4768 assert(obj_idx >= 0);
4769 if (obj_idx < 0)
4770 // This should not happen.
4771 return "ObjectList assert";
4772
4773 auto& ranges = object(obj_idx)->layer_config_ranges;
4774 auto it_range = ranges.find(current_range);
4775 assert(it_range != ranges.end());
4776 if (it_range == ranges.end())
4777 // This shoudl not happen.
4778 return "ObjectList assert";
4779
4780 auto it_next_range = it_range;
4781 if (++ it_next_range == ranges.end())
4782 // Adding a layer after the last layer is always possible.
4783 return "";
4784
4785 // BBS: remove all layer range message
4786
4787 // All right, new layer height range could be inserted.
4788 return "";
4789}

References get_selected_obj_idx(), Slic3r::ModelObject::layer_config_ranges, and object().

Here is the call graph for this function:

◆ can_drop()

bool Slic3r::GUI::ObjectList::can_drop ( const wxDataViewItem & item,
int & src_obj_id,
int & src_plate,
int & dest_obj_id,
int & dest_plate ) const
private
1965{
1966 if (!item.IsOk()
1967 || (m_objects_model->GetItemType(item) != m_dragged_data.type())
1968 || !(m_dragged_data.type() & (itVolume|itObject)))
1969 return false;
1970
1971 if (m_dragged_data.type() & itObject){
1972 int from_obj_id = m_dragged_data.obj_idx();
1973 int to_obj_id = m_objects_model->GetIdByItem(item);
1974 PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list();
1975
1976 int from_plate = partplate_list.find_instance(from_obj_id, 0);
1977 if (from_plate == -1)
1978 return false;
1979 int to_plate = partplate_list.find_instance(to_obj_id, 0);
1980 if ((to_plate == -1) || (from_plate != to_plate))
1981 return false;
1982
1983 src_obj_id = from_obj_id;
1984 dest_obj_id = to_obj_id;
1985 src_plate = from_plate;
1986 dest_plate = to_plate;
1987
1988 // move instance(s) or object on "empty place" of ObjectList
1989 // if ( (m_dragged_data.type() & (itInstance | itObject)) && !item.IsOk() )
1990 // return true;
1991 }
1992 else if (m_dragged_data.type() & itVolume) { // move volumes inside one object only
1993 if (m_dragged_data.obj_idx() != m_objects_model->GetObjectIdByItem(item))
1994 return false;
1995 wxDataViewItem dragged_item = m_objects_model->GetItemByVolumeId(m_dragged_data.obj_idx(), m_dragged_data.sub_obj_idx());
1996 if (!dragged_item)
1997 return false;
1998 ModelVolumeType item_v_type = m_objects_model->GetVolumeType(item);
1999 ModelVolumeType dragged_item_v_type = m_objects_model->GetVolumeType(dragged_item);
2000
2001 if (dragged_item_v_type == item_v_type && dragged_item_v_type != ModelVolumeType::MODEL_PART)
2002 return true;
2003
2004 // Use tree item types: hidden cut connectors make tree indices differ from volumes indices.
2005 if (is_precise_seam(dragged_item_v_type) && is_precise_seam(item_v_type))
2006 // Allow reordering only within the strong or weak modifier group.
2007 return is_precise_seam_strong(dragged_item_v_type) == is_precise_seam_strong(item_v_type);
2008
2009 if ((dragged_item_v_type != item_v_type) || // we can't reorder volumes outside of types
2010 item_v_type >= ModelVolumeType::SUPPORT_BLOCKER) // support blockers/enforcers can't change its place
2011 return false;
2012
2013 bool only_one_solid_part = true;
2014 auto& volumes = (*m_objects)[m_dragged_data.obj_idx()]->volumes;
2015 for (size_t cnt, id = cnt = 0; id < volumes.size() && cnt < 2; id ++)
2016 if (volumes[id]->type() == ModelVolumeType::MODEL_PART) {
2017 if (++cnt > 1)
2018 only_one_solid_part = false;
2019 }
2020
2021 if (dragged_item_v_type == ModelVolumeType::MODEL_PART) {
2022 if (only_one_solid_part)
2023 return false;
2024 return (m_objects_model->GetVolumeIdByItem(item) == 0 ||
2025 (m_dragged_data.sub_obj_idx()==0 && volumes[1]->type() == ModelVolumeType::MODEL_PART) ||
2026 (m_dragged_data.sub_obj_idx()!=0 && volumes[0]->type() == ModelVolumeType::MODEL_PART));
2027 }
2028 if ((dragged_item_v_type == ModelVolumeType::NEGATIVE_VOLUME || dragged_item_v_type == ModelVolumeType::PARAMETER_MODIFIER)) {
2029 if (only_one_solid_part)
2030 return false;
2031 return m_objects_model->GetVolumeIdByItem(item) != 0;
2032 }
2033 return false;
2034 }
2035 return true;
2036}
struct Slic3r::GUI::ObjectList::dragged_item_data m_dragged_data
bool is_precise_seam_strong(ModelVolumeType t)
Definition Model.hpp:374
@ PARAMETER_MODIFIER
Definition Model.hpp:359
@ MODEL_PART
Definition Model.hpp:357

References Slic3r::GUI::PartPlateList::find_instance(), Slic3r::is_precise_seam(), Slic3r::is_precise_seam_strong(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_dragged_data, m_objects_model, Slic3r::MODEL_PART, Slic3r::NEGATIVE_VOLUME, Slic3r::PARAMETER_MODIFIER, and Slic3r::SUPPORT_BLOCKER.

Referenced by OnDrop(), and OnDropPossible().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ can_merge_to_multipart_object()

bool Slic3r::GUI::ObjectList::can_merge_to_multipart_object ( ) const
3675{
3677 return false;
3678
3679 if (printer_technology() == ptSLA)
3680 return false;
3681
3682 wxDataViewItemArray sels;
3683 GetSelections(sels);
3684 if (sels.IsEmpty())
3685 return false;
3686
3687 // should be selected just objects
3688 for (wxDataViewItem item : sels)
3689 if (!(m_objects_model->GetItemType(item) & (itObject | itInstance)))
3690 return false;
3691
3692 return true;
3693}
bool has_selected_cut_object() const
Definition GUI_ObjectList.cpp:3580

References has_selected_cut_object(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, m_objects_model, Slic3r::GUI::printer_technology(), and Slic3r::ptSLA.

Here is the call graph for this function:

◆ can_merge_to_single_object()

bool Slic3r::GUI::ObjectList::can_merge_to_single_object ( ) const
3696{
3697 int obj_idx = get_selected_obj_idx();
3698 if (obj_idx < 0)
3699 return false;
3700
3701 // selected object should be multipart
3702 return (*m_objects)[obj_idx]->volumes.size() > 1;
3703}

References get_selected_obj_idx(), and m_objects.

Here is the call graph for this function:

◆ can_mesh_boolean()

bool Slic3r::GUI::ObjectList::can_mesh_boolean ( ) const
3706{
3707 int obj_idx = get_selected_obj_idx();
3708 if (obj_idx < 0)
3709 return false;
3710
3711 // selected object should be multi mesh
3712 return (*m_objects)[obj_idx]->volumes.size() > 1 || ((*m_objects)[obj_idx]->volumes.size() == 1 && (*m_objects)[obj_idx]->volumes[0]->is_splittable());
3713}
bool is_splittable(bool to_objects)
Definition GUI_ObjectList.cpp:3531

References get_selected_obj_idx(), is_splittable(), and m_objects.

Here is the call graph for this function:

◆ can_paste_settings_into_list()

bool Slic3r::GUI::GUI::ObjectList::can_paste_settings_into_list ( )
1390{
1391 wxDataViewItemArray sels;
1392 GetSelections(sels);
1393 if (sels.empty())
1394 return false;
1395 return m_clipboard.get_type() == (m_objects_model->GetItemType(sels.front()) | itSettings);
1396}
Clipboard m_clipboard
Definition GUI_ObjectList.hpp:139
@ itSettings
Definition ObjectDataViewModel.hpp:41

References Slic3r::GUI::itSettings, m_clipboard, and m_objects_model.

◆ can_split_instances()

bool Slic3r::GUI::ObjectList::can_split_instances ( )
3575{
3576 const Selection& selection = scene_selection();
3577 return selection.is_multiple_full_instance() || selection.is_single_full_instance();
3578}
@ Selection
Definition Shortcuts.hpp:72
static const Selection & scene_selection()
Definition GUI_ObjectList.cpp:121

References Slic3r::GUI::Selection::is_multiple_full_instance(), Slic3r::GUI::Selection::is_single_full_instance(), and Slic3r::GUI::scene_selection().

Here is the call graph for this function:

◆ changed_object()

void Slic3r::GUI::ObjectList::changed_object ( const int obj_idx = -1) const
3717{
3718 wxGetApp().plater()->changed_object(obj_idx < 0 ? get_selected_obj_idx() : obj_idx);
3719}

References get_selected_obj_idx().

Referenced by add_layer_range_after_current(), del_instances_from_object(), del_layer_from_object(), del_layers_from_object(), del_settings_from_config(), del_subobject_from_object(), delete_all_connectors_for_object(), edit_layer_range(), edit_layer_range(), merge(), OnDrop(), paste_layers_into_list(), reorder_volumes_and_get_selection(), and split().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_last_selection()

bool Slic3r::GUI::ObjectList::check_last_selection ( wxString & msg_str)
5423{
5425 return true;
5426
5427 const bool is_shift_pressed = wxGetKeyState(WXK_SHIFT);
5428
5429 /* We can't mix Volumes, Layers and Objects/Instances.
5430 * So, show information about it
5431 */
5432 const ItemType type = m_objects_model->GetItemType(m_last_selected_item);
5433
5434 // check a case of a selection of the same type items from different Objects
5435 auto impossible_multi_selection = [type, this](const ItemType item_type, const SELECTION_MODE selection_mode) {
5436 if (!(type & item_type && m_selection_mode & selection_mode))
5437 return false;
5438
5439 wxDataViewItemArray sels;
5440 GetSelections(sels);
5441 for (const auto& sel : sels)
5442 if (sel != m_last_selected_item &&
5443 m_objects_model->GetObject(sel) != m_objects_model->GetObject(m_last_selected_item))
5444 return true;
5445
5446 return false;
5447 };
5448
5449 if (impossible_multi_selection(itVolume, smVolume) ||
5450 impossible_multi_selection(itLayer, smLayer ) ||
5451 type & itSettings ||
5452 (type & itVolume && !(m_selection_mode & smVolume )) ||
5453 (type & itLayer && !(m_selection_mode & smLayer )) ||
5454 (type & itInstance && !(m_selection_mode & smInstance))
5455 )
5456 {
5457 // Inform user why selection isn't completed
5458 // BBS: change "Object or Instance" to "Object"
5459 const wxString item_type = m_selection_mode & smInstance ? _(L("Object")) :
5460 m_selection_mode & smVolume ? _(L("Part")) : _(L("Layer"));
5461
5463 msg_str = wxString::Format(_(L("Selection conflicts")) + "\n\n" +
5464 _(L("If the first selected item is an object, the second should also be an object.")) + "\n");
5465 }
5466 else {
5467 msg_str = wxString::Format(_(L("Selection conflicts")) + "\n\n" +
5468 _(L("If the first selected item is a part, the second should be a part in the same object.")) + "\n");
5469 }
5470
5471 // Unselect last selected item, if selection is without SHIFT
5472 if (!is_shift_pressed) {
5473 Unselect(m_last_selected_item);
5474 show_info(this, msg_str, _(L("Info")));
5475 }
5476
5477 return is_shift_pressed;
5478 }
5479
5480 return true;
5481}
#define _(s)
Definition 3mf.cpp:306
#define L(s)
Definition ExtrusionEntity.cpp:25
SELECTION_MODE m_selection_mode
Definition GUI_ObjectList.hpp:136
SELECTION_MODE
Definition GUI_ObjectList.hpp:100
void show_info(wxWindow *parent, const wxString &message, const wxString &title)
Definition GUI.cpp:316

References _, Slic3r::GUI::itInstance, Slic3r::GUI::itLayer, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, L, m_last_selected_item, m_objects_model, m_selection_mode, Slic3r::GUI::show_info(), smInstance, smLayer, and smVolume.

Referenced by fix_multiselection_conflicts().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ clipboard_is_empty()

bool Slic3r::GUI::ObjectList::clipboard_is_empty ( ) const
inline
475{ return m_clipboard.empty(); }

References m_clipboard.

◆ clone()

void Slic3r::GUI::ObjectList::clone ( )
1771{
1772 wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_CLONE));
1773}

References Slic3r::GUI::plater().

Referenced by dispatch_shortcut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ config()

ModelConfig * Slic3r::GUI::ObjectList::config ( ) const
inline
234{ return m_config; }

References m_config.

Referenced by add_layer_item(), add_settings_item(), copy_settings_to_clipboard(), edit_layer_range(), edit_layer_range(), get_default_layer_config(), merge(), paste_settings_into_list(), set_extruder_for_selected_items(), split(), and update_filament_in_config().

Here is the caller graph for this function:

◆ copy()

void Slic3r::GUI::ObjectList::copy ( )
1756{
1757 wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY));
1758}

References Slic3r::GUI::plater().

Referenced by dispatch_shortcut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_layers_to_clipboard()

void Slic3r::GUI::ObjectList::copy_layers_to_clipboard ( )
1307{
1308 wxDataViewItemArray sel_layers;
1309 GetSelections(sel_layers);
1310
1311 const int obj_idx = m_objects_model->GetObjectIdByItem(sel_layers.front());
1312 if (obj_idx < 0 || (int)m_objects->size() <= obj_idx)
1313 return;
1314
1315 const t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges;
1316 t_layer_config_ranges& cache_ranges = m_clipboard.get_ranges_cache();
1317
1318 if (sel_layers.Count() == 1 && m_objects_model->GetItemType(sel_layers.front()) & itLayerRoot)
1319 {
1320 cache_ranges.clear();
1321 cache_ranges = ranges;
1322 return;
1323 }
1324
1325 for (const auto& layer_item : sel_layers)
1326 if (m_objects_model->GetItemType(layer_item) & itLayer) {
1327 auto range = m_objects_model->GetLayerRangeByItem(layer_item);
1328 auto it = ranges.find(range);
1329 if (it != ranges.end())
1330 cache_ranges[it->first] = it->second;
1331 }
1332}
@ itLayerRoot
Definition ObjectDataViewModel.hpp:42
std::map< t_layer_height_range, ModelConfig > t_layer_config_ranges
Definition Slicing.hpp:160

References Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::ModelObject::layer_config_ranges, m_clipboard, m_objects, m_objects_model, object(), and Slic3r::range().

Referenced by copy_to_clipboard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_settings_to_clipboard()

void Slic3r::GUI::ObjectList::copy_settings_to_clipboard ( )
1365{
1366 wxDataViewItem item = GetSelection();
1367 assert(item.IsOk());
1368 if (m_objects_model->GetItemType(item) & itSettings)
1369 item = m_objects_model->GetParent(item);
1370
1371 wxDataViewItemArray items;
1372 items.push_back(item);
1373 while ((m_objects_model->GetItemType(items.back()) & itObject) == 0) {
1374 if (m_objects_model->GetItemType(items.back()) & itLayerRoot)
1375 items.back() = m_objects_model->GetParent(items.back());
1376 else
1377 items.push_back(m_objects_model->GetParent(items.back()));
1378 }
1379 auto &config = m_clipboard.get_config_cache();
1380 config.clear();
1381 while (!items.empty()) {
1382 config.apply(get_item_config(items.back()).get());
1383 items.pop_back();
1384 }
1385
1386 m_clipboard.set_type(ItemType(m_objects_model->GetItemType(item) | itSettings));
1387}
const DynamicPrintConfig & get() const
Definition PrintConfig.hpp:2645

References config(), Slic3r::ModelConfig::get(), get_item_config(), Slic3r::GUI::itLayerRoot, Slic3r::GUI::itObject, Slic3r::GUI::itSettings, m_clipboard, and m_objects_model.

Referenced by copy_to_clipboard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_to_clipboard()

bool Slic3r::GUI::ObjectList::copy_to_clipboard ( )
1781{
1782 wxDataViewItemArray sels;
1783 GetSelections(sels);
1784 if (sels.IsEmpty())
1785 return false;
1786 ItemType type = m_objects_model->GetItemType(sels.front());
1787 if (!(type & (itSettings | itLayer | itLayerRoot))) {
1788 m_clipboard.reset();
1789 return false;
1790 }
1791
1792 if (type & itSettings)
1794 if (type & (itLayer | itLayerRoot))
1796
1797 m_clipboard.set_type(type);
1798 return true;
1799}
void copy_layers_to_clipboard()
Definition GUI_ObjectList.cpp:1306
void copy_settings_to_clipboard()
Definition GUI_ObjectList.cpp:1364

References copy_layers_to_clipboard(), copy_settings_to_clipboard(), Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itSettings, m_clipboard, and m_objects_model.

Referenced by cut_to_clipboard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_objects_ctrl()

void Slic3r::GUI::ObjectList::create_objects_ctrl ( )
401{
402 // BBS
403#if 0
404 /* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
405 * 1. set a height of the list to some big value
406 * 2. change it to the normal(meaningful) min value after first whole Mainframe updating/layouting
407 */
408 SetMinSize(wxSize(-1, 3000));
409#endif
410
411 m_objects_model = new ObjectDataViewModel;
412 AssociateModel(m_objects_model);
413 m_objects_model->SetAssociatedControl(this);
414#if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
415 EnableDragSource(wxDF_UNICODETEXT);
416 EnableDropTarget(wxDF_UNICODETEXT);
417#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
418
419 const int em = wxGetApp().em_unit();
420
430
431 // column ItemName(Icon+Text) of the view control:
432 // And Icon can be consisting of several bitmaps
433 BitmapTextRenderer* bmp_text_renderer = new BitmapTextRenderer();
434 bmp_text_renderer->set_can_create_editor_ctrl_function([this]() {
435 auto type = m_objects_model->GetItemType(GetSelection());
436 return type & (itVolume | itObject | itPlate);
437 });
438
439 // BBS
440 wxDataViewColumn* name_col = new wxDataViewColumn(_L("Name"), bmp_text_renderer,
441 colName, m_columns_width[colName] * em, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE);
442 //name_col->SetBitmap(create_scaled_bitmap("organize", nullptr, FromDIP(18)));
443 AppendColumn(name_col);
444
445 // column Variable height Property (Icon) of the view control:
446 AppendBitmapColumn(" ", colHeight, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, 3 * em,
447 wxALIGN_CENTER_HORIZONTAL, 0);
448
449 // column PrintableProperty (Icon) of the view control:
450 AppendBitmapColumn(" ", colPrint, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colPrint]*em,
451 wxALIGN_CENTER_HORIZONTAL, 0);
452
453 // column Extruder of the view control:
454 BitmapChoiceRenderer* bmp_choice_renderer = new BitmapChoiceRenderer();
455 const auto get_filament_context_item = [this]() {
456#ifdef __WXOSX__
457 return m_filament_editor_item.IsOk() ? m_filament_editor_item : GetSelection();
458#else
459 return GetSelection();
460#endif
461 };
462 bmp_choice_renderer->set_can_create_editor_ctrl_function([this, get_filament_context_item]() {
463 const wxDataViewItem item = get_filament_context_item();
464 return m_objects_model->GetItemType(item) & (itVolume | itLayer | itObject);
465 });
466 bmp_choice_renderer->set_default_extruder_idx([this, get_filament_context_item]() {
467 const wxDataViewItem item = get_filament_context_item();
468 return m_objects_model->GetDefaultExtruderIdx(item);
469 });
470 bmp_choice_renderer->set_has_default_extruder([this, get_filament_context_item]() {
471 const wxDataViewItem item = get_filament_context_item();
472 return m_objects_model->GetVolumeType(item) == ModelVolumeType::PARAMETER_MODIFIER ||
473 m_objects_model->GetItemType(item) == itLayer;
474 });
475 AppendColumn(new wxDataViewColumn(_L("Fila."), bmp_choice_renderer,
476 colFilament, m_columns_width[colFilament] * em, wxALIGN_CENTER_HORIZONTAL, 0));
477
478 // BBS
479 AppendBitmapColumn(" ", colSupportPaint, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colSupportPaint] * em,
480 wxALIGN_CENTER_HORIZONTAL, 0);
481 AppendBitmapColumn(" ", colColorPaint, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colColorPaint] * em,
482 wxALIGN_CENTER_HORIZONTAL, 0);
483 AppendBitmapColumn(" ", colSinking, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colSinking] * em,
484 wxALIGN_CENTER_HORIZONTAL, 0);
485
486 // column ItemEditing of the view control:
487 AppendBitmapColumn(" ", colEditing, wxOSX ? wxDATAVIEW_CELL_EDITABLE : wxDATAVIEW_CELL_INERT, m_columns_width[colEditing] * em,
488 wxALIGN_CENTER_HORIZONTAL, 0);
489
490
491 // On macOS, bypass wxDataViewCtrl::EditItem() for this custom renderer to avoid
492 // native text editing of wxCustomRendererObject.
493 this->Bind(wxEVT_DATAVIEW_ITEM_ACTIVATED, [this](wxDataViewEvent& event) {
494 if (event.GetColumn() == colFilament) {
495#ifdef __WXOSX__
496 start_filament_editor(event.GetItem());
497#else
498 // Trigger the editor opening manually
499 this->EditItem(event.GetItem(), GetColumn(colFilament));
500#endif
501 return;
502 }
503
504 // Double-clicking an object/part/instance row frames it in the 3D view,
505 // matching the "Fit camera to scene or selected object" canvas button.
506 // The preceding single click has already synced the canvas selection via
507 // wxEVT_DATAVIEW_SELECTION_CHANGED, so we just trigger the zoom here.
508 // No-op in slice-preview mode: the camera is shared with the editor
509 // canvas, so zooming there would move the preview view too — and the
510 // preview canvas's own toolbar button intentionally resets to the bed.
511 const wxDataViewItem item = event.GetItem();
512 if (!item.IsOk())
513 return;
514 if (wxGetApp().plater()->is_preview_shown())
515 return;
516 const ItemType type = m_objects_model->GetItemType(item);
517 if (type & (itObject | itVolume | itInstance)) {
518 if (GLCanvas3D* canvas = wxGetApp().plater()->get_current_canvas3D())
519 canvas->zoom_to_selection();
520 }
521 });
522
523 //for (int cn = colName; cn < colCount; cn++) {
524 // GetColumn(cn)->SetResizeable(cn == colName);
525 //}
526
527 // For some reason under OSX on 4K(5K) monitors in wxDataViewColumn constructor doesn't set width of column.
528 // Therefore, force set column width.
529#ifdef __WXOSX__
531 for (int cn = colName; cn < colCount; cn++)
532 GetColumn(cn)->SetWidth(m_columns_width[cn] * em);
533#endif
534
535 // Force an explicit row height on all platforms so the object-list spacing is
536 // consistent and the filament colour badge (2*em tall, see
537 // get_extruder_color_icons()) always fits. This is required on macOS, where wx
538 // 3.3's native wxDataViewCtrl uses a fixed font-line-height row and does NOT
539 // grow it to fit custom renderers' GetSize() (badges would otherwise overflow
540 // and merge into adjacent rows); on Windows/Linux the generic control normally
541 // derives the height from the renderers, but we set it here too so all
542 // platforms match.
543 SetRowHeight(2 * em + FromDIP(2));
544}
#define wxOSX
Definition Field.cpp:94
#define _L(s)
Definition OBJ.cpp:34
void set_has_default_extruder(std::function< bool()> has_default_extruder_fn)
Definition ExtraRenderers.hpp:170
void set_default_extruder_idx(std::function< int()> default_extruder_idx_fn)
Definition ExtraRenderers.hpp:169
void set_can_create_editor_ctrl_function(std::function< bool()> can_create_fn)
Definition ExtraRenderers.hpp:168
void set_can_create_editor_ctrl_function(std::function< bool()> can_create_fn)
Definition ExtraRenderers.hpp:128
std::vector< int > m_columns_width
Definition GUI_ObjectList.hpp:533
void dataview_remove_insets(wxDataViewCtrl *dv)
Definition GUI_UtilsMac.mm:10
@ colSinking
Definition ObjectDataViewModel.hpp:56
@ colColorPaint
Definition ObjectDataViewModel.hpp:55
@ colSupportPaint
Definition ObjectDataViewModel.hpp:54
@ colEditing
Definition ObjectDataViewModel.hpp:57
@ colHeight
Definition ObjectDataViewModel.hpp:50
@ colName
Definition ObjectDataViewModel.hpp:49
@ colFilament
Definition ObjectDataViewModel.hpp:52
@ colPrint
Definition ObjectDataViewModel.hpp:51
@ colCount
Definition ObjectDataViewModel.hpp:58

References _L, Slic3r::GUI::colColorPaint, Slic3r::GUI::colCount, Slic3r::GUI::colEditing, Slic3r::GUI::colFilament, Slic3r::GUI::colHeight, Slic3r::GUI::colName, Slic3r::GUI::colPrint, Slic3r::GUI::colSinking, Slic3r::GUI::colSupportPaint, Slic3r::GUI::dataview_remove_insets(), Slic3r::GUI::itInstance, Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itPlate, Slic3r::GUI::itVolume, m_columns_width, m_objects_model, Slic3r::PARAMETER_MODIFIER, Slic3r::GUI::plater(), BitmapChoiceRenderer::set_can_create_editor_ctrl_function(), BitmapTextRenderer::set_can_create_editor_ctrl_function(), BitmapChoiceRenderer::set_default_extruder_idx(), BitmapChoiceRenderer::set_has_default_extruder(), and wxOSX.

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cut()

void Slic3r::GUI::ObjectList::cut ( )
1766{
1767 wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_CUT));
1768}

References Slic3r::GUI::plater().

Referenced by dispatch_shortcut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cut_to_clipboard()

bool Slic3r::GUI::ObjectList::cut_to_clipboard ( )
1776{
1777 return copy_to_clipboard();
1778}
bool copy_to_clipboard()
Definition GUI_ObjectList.cpp:1780

References copy_to_clipboard().

Here is the call graph for this function:

◆ decrease_instances()

void Slic3r::GUI::ObjectList::decrease_instances ( )
1832{
1833 wxGetApp().plater()->decrease_instances(1);
1834}

Referenced by dispatch_shortcut().

Here is the caller graph for this function:

◆ decrease_object_instances()

void Slic3r::GUI::ObjectList::decrease_object_instances ( const size_t obj_idx,
const size_t num )
4500{
4501 select_item([this, obj_idx, num]() { return m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num); });
4502}

References m_objects_model, and select_item().

Referenced by Slic3r::GUI::Plater::decrease_instances().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_from_cut_object()

bool Slic3r::GUI::ObjectList::del_from_cut_object ( bool is_connector,
bool is_model_part = false,
bool is_negative_volume = false )
2888{
2889 const long buttons_style = is_cut_connector ? (wxYES | wxNO | wxCANCEL) : (wxYES | wxCANCEL);
2890
2891 const wxString title = is_cut_connector ? _L("Delete connector from object which is a part of cut") :
2892 is_model_part ? _L("Delete solid part from object which is a part of cut") :
2893 is_negative_volume ? _L("Delete negative volume from object which is a part of cut") : "";
2894
2895 const wxString msg_end = is_cut_connector ? ("\n" + _L("To save cut correspondence you can delete all connectors from all related objects.")) : "";
2896
2897 InfoDialog dialog(wxGetApp().plater(), title,
2898 (_L("This action will break a cut correspondence.\nAfter that, model consistency can\'t be guaranteed.\n\nTo manipulate with solid parts or negative volumes you have to invalidate cut information first.") + msg_end ),
2899 false, buttons_style | wxCANCEL_DEFAULT | wxICON_WARNING);
2900
2901 dialog.SetButtonLabel(wxID_YES, _L("Invalidate cut info"));
2902 if (is_cut_connector)
2903 dialog.SetButtonLabel(wxID_NO, _L("Delete all connectors"));
2904
2905 const int answer = dialog.ShowModal();
2906 if (answer == wxID_CANCEL)
2907 return false;
2908
2909 if (answer == wxID_YES)
2911 else if (answer == wxID_NO)
2913 return true;
2914}
void invalidate_cut_info_for_selection()
Definition GUI_ObjectList.cpp:3598
void delete_all_connectors_for_selection()
Definition GUI_ObjectList.cpp:3628

References _L, delete_all_connectors_for_selection(), invalidate_cut_info_for_selection(), Slic3r::GUI::plater(), Slic3r::GUI::MsgDialog::SetButtonLabel(), and Slic3r::GUI::DPIAware< P >::ShowModal().

Referenced by del_info_item(), and del_subobject_from_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_info_item()

void Slic3r::GUI::ObjectList::del_info_item ( const int obj_idx,
InfoItemType type )
2779{
2780 Plater* plater = wxGetApp().plater();
2781 GLCanvas3D* cnv = plater->canvas3D();
2782
2783 switch (type) {
2785 cnv->get_gizmos_manager().reset_all_states();
2786 Plater::TakeSnapshot snapshot(plater, "Remove support painting");
2787 for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
2788 mv->supported_facets.reset();
2789 break;
2790 }
2791
2792 // BBS: remove CustomSeam
2793
2795 if (!del_from_cut_object(true)) {
2796 // there is no need to post EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS if nothing was changed
2797 return;
2798 }
2799 break;
2800
2802 cnv->get_gizmos_manager().reset_all_states();
2803 Plater::TakeSnapshot snapshot(plater, "Remove color painting");
2804 for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
2805 mv->mmu_segmentation_facets.reset();
2806 break;
2807 }
2808
2810 cnv->get_gizmos_manager().reset_all_states();
2811 Plater::TakeSnapshot snapshot(plater, _u8L("Remove paint-on fuzzy skin"));
2812 for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
2813 mv->fuzzy_skin_facets.reset();
2814 break;
2815 }
2816
2817 // BBS: remove Sinking
2818 case InfoItemType::Undef : assert(false); break;
2819 }
2820 cnv->post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
2821}
void post_event(wxEvent &&event)
Definition GLCanvas3D.cpp:1691
bool del_from_cut_object(bool is_connector, bool is_model_part=false, bool is_negative_volume=false)
Definition GUI_ObjectList.cpp:2887
GLCanvas3D * canvas3D()
Definition Plater.cpp:22070
@ CustomSupports
Definition ObjectDataViewModel.hpp:77
@ MmSegmentation
Definition ObjectDataViewModel.hpp:79
@ Undef
Definition ObjectDataViewModel.hpp:76
@ FuzzySkin
Definition ObjectDataViewModel.hpp:80
@ CutConnectors
Definition ObjectDataViewModel.hpp:82
@ Plater
Definition Shortcuts.hpp:21

References _u8L, Slic3r::GUI::CustomSupports, Slic3r::GUI::CutConnectors, del_from_cut_object(), Slic3r::GUI::FuzzySkin, Slic3r::GUI::GLCanvas3D::get_gizmos_manager(), m_objects, Slic3r::GUI::MmSegmentation, Slic3r::GUI::plater(), Slic3r::GUI::GLCanvas3D::post_event(), Slic3r::GUI::GLGizmosManager::reset_all_states(), and Slic3r::GUI::Undef.

Referenced by del_subobject_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_instances_from_object()

void Slic3r::GUI::ObjectList::del_instances_from_object ( const int obj_idx)
2851{
2852 auto& instances = (*m_objects)[obj_idx]->instances;
2853 if (instances.size() <= 1)
2854 return;
2855
2856 // BBS: remove snapshot name "Delete All Instances from Object"
2857 take_snapshot("");
2858
2859 while ( instances.size()> 1)
2860 instances.pop_back();
2861
2862 (*m_objects)[obj_idx]->invalidate_bounding_box(); // ? #ys_FIXME
2863
2864 changed_object(obj_idx);
2865}

References changed_object(), and Slic3r::GUI::take_snapshot().

Referenced by del_subobject_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_layer_from_object()

void Slic3r::GUI::ObjectList::del_layer_from_object ( const int obj_idx,
const t_layer_height_range & layer_range )
2868{
2869 const auto del_range = object(obj_idx)->layer_config_ranges.find(layer_range);
2870 if (del_range == object(obj_idx)->layer_config_ranges.end())
2871 return;
2872
2873 take_snapshot(_u8L("Remove height range"));
2874
2875 object(obj_idx)->layer_config_ranges.erase(del_range);
2876
2877 changed_object(obj_idx);
2878}

References _u8L, changed_object(), Slic3r::ModelObject::layer_config_ranges, object(), and Slic3r::GUI::take_snapshot().

Referenced by del_subobject_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_layer_range()

void Slic3r::GUI::ObjectList::del_layer_range ( const t_layer_height_range & range)
4633{
4634 const int obj_idx = get_selected_obj_idx();
4635 if (obj_idx < 0) return;
4636
4638
4639 wxDataViewItem selectable_item = GetSelection();
4640
4641 if (ranges.size() == 1)
4642 selectable_item = m_objects_model->GetParent(selectable_item);
4643
4644 wxDataViewItem layer_item = m_objects_model->GetItemByLayerRange(obj_idx, range);
4645 del_subobject_item(layer_item);
4646
4647 select_item(selectable_item);
4648}

References del_subobject_item(), get_selected_obj_idx(), Slic3r::ModelObject::layer_config_ranges, m_objects_model, object(), Slic3r::range(), and select_item().

Here is the call graph for this function:

◆ del_layers_from_object()

void Slic3r::GUI::ObjectList::del_layers_from_object ( const int obj_idx)
2881{
2882 object(obj_idx)->layer_config_ranges.clear();
2883
2884 changed_object(obj_idx);
2885}

References changed_object(), Slic3r::ModelObject::layer_config_ranges, and object().

Referenced by del_subobject_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_object()

bool Slic3r::GUI::ObjectList::del_object ( const int obj_idx,
bool refresh_immediately = true )
2731{
2732 return wxGetApp().plater()->delete_object_from_model(obj_idx, refresh_immediately);
2733}

Referenced by delete_from_model_and_list(), and delete_from_model_and_list().

Here is the caller graph for this function:

◆ del_settings_from_config()

void Slic3r::GUI::ObjectList::del_settings_from_config ( const wxDataViewItem & parent_item)
2824{
2825 const bool is_layer_settings = m_objects_model->GetItemType(parent_item) == itLayer;
2826
2827 const size_t opt_cnt = m_config->keys().size();
2828 if ((opt_cnt == 1 && m_config->has("extruder")) ||
2829 (is_layer_settings && opt_cnt == 2 && m_config->has("extruder") && m_config->has("layer_height")))
2830 return;
2831
2832 take_snapshot(_u8L("Delete Settings"));
2833
2834 int extruder = m_config->has("extruder") ? m_config->extruder() : -1;
2835
2836 coordf_t layer_height = 0.0;
2837 if (is_layer_settings)
2838 layer_height = m_config->opt_float("layer_height");
2839
2840 m_config->reset();
2841
2842 if (extruder >= 0)
2843 m_config->set_key_value("extruder", new ConfigOptionInt(extruder));
2844 if (is_layer_settings)
2845 m_config->set_key_value("layer_height", new ConfigOptionFloat(layer_height));
2846
2848}
static std::string layer_height
Definition Tab.cpp:4294
zaa_minimize_perimeter_height ConfigOptionFloat
Definition PrintConfig.hpp:1954

References _u8L, changed_object(), Slic3r::ConfigOptionFloat, Slic3r::GUI::itLayer, Slic3r::GUI::layer_height, m_config, m_objects_model, and Slic3r::GUI::take_snapshot().

Referenced by del_subobject_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_subobject_from_object()

bool Slic3r::GUI::ObjectList::del_subobject_from_object ( const int obj_idx,
const int idx,
const int type )
2917{
2918 assert(idx >= 0);
2919
2920 // BBS: support partplage logic
2921 int n_plates = wxGetApp().plater()->get_partplate_list().get_plate_count();
2922 if ((obj_idx >= 1000 && obj_idx < 1000 + n_plates) || idx<0)
2923 // Cannot delete a wipe tower or volume with negative id
2924 return false;
2925
2926 ModelObject* object = (*m_objects)[obj_idx];
2927
2928 if (type == itVolume) {
2929 const auto volume = object->volumes[idx];
2930
2931 // if user is deleting the last solid part, throw error
2932 int solid_cnt = 0;
2933 for (auto vol : object->volumes)
2934 if (vol->is_model_part())
2935 ++solid_cnt;
2936 if (volume->is_model_part() && solid_cnt == 1) {
2937 Slic3r::GUI::show_error(nullptr, _L("Deleting the last solid part is not allowed."));
2938 return false;
2939 }
2940 if (object->is_cut() && (volume->is_model_part() || volume->is_negative_volume())) {
2941 del_from_cut_object(volume->is_cut_connector(), volume->is_model_part(), volume->is_negative_volume());
2942 // in any case return false to break the deletion
2943 return false;
2944 }
2945
2946 take_snapshot(_u8L("Delete part"));
2947
2948 object->delete_volume(idx);
2949
2950 if (object->volumes.size() == 1) {
2951 const auto last_volume = object->volumes[0];
2952 if (!last_volume->config.empty()) {
2953 object->config.apply(last_volume->config);
2954 last_volume->config.reset();
2955
2956 // update extruder color in ObjectList
2957 wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx);
2958 if (obj_item) {
2959 // BBS
2960 if (last_volume->config.has("extruder")) {
2961 int extruder_id = last_volume->config.opt_int("extruder");
2962 object->config.set("extruder", extruder_id);
2963 }
2964 wxString extruder = object->config.has("extruder") ? wxString::Format("%d", object->config.extruder()) : _devL("1");
2965 m_objects_model->SetExtruder(extruder, obj_item);
2966 }
2967 // add settings to the object, if it has them
2968 add_settings_item(obj_item, &object->config.get());
2969 }
2970 }
2971 //BBS: notify partplate the modify
2972 notify_instance_updated(obj_idx);
2973 }
2974 else if (type == itInstance) {
2975 if (object->instances.size() == 1) {
2976 // BBS: remove snapshot name "Last instance of an object cannot be deleted."
2977 Slic3r::GUI::show_error(nullptr, "");
2978 return false;
2979 }
2980
2981 // BBS: remove snapshot name "Delete Instance"
2982 take_snapshot("");
2983 object->delete_instance(idx);
2984 }
2985 else
2986 return false;
2987
2988 changed_object(obj_idx);
2989
2990 return true;
2991}
void show_error(wxWindow *parent, const wxString &message, bool has_code_excerpts)
Definition GUI.cpp:296
#define _devL(s)
Definition I18N.hpp:8

References _devL, _L, _u8L, add_settings_item(), changed_object(), del_from_cut_object(), Slic3r::GUI::itInstance, Slic3r::GUI::itVolume, m_objects_model, notify_instance_updated(), object(), Slic3r::GUI::show_error(), and Slic3r::GUI::take_snapshot().

Referenced by del_subobject_item(), delete_from_model_and_list(), delete_from_model_and_list(), instances_to_separated_object(), and instances_to_separated_objects().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ del_subobject_item()

void Slic3r::GUI::ObjectList::del_subobject_item ( wxDataViewItem & item)
2737{
2738 if (!item) return;
2739
2740 int obj_idx, idx;
2741 ItemType type;
2742
2743 m_objects_model->GetItemInfo(item, type, obj_idx, idx);
2744 if (type == itUndef)
2745 return;
2746
2747 wxDataViewItem parent = m_objects_model->GetParent(item);
2748
2749 InfoItemType item_info_type = m_objects_model->GetInfoItemType(item);
2750 if (type & itSettings)
2752 else if (type & itInstanceRoot && obj_idx != -1)
2754 else if (type & itLayerRoot && obj_idx != -1)
2755 del_layers_from_object(obj_idx);
2756 else if (type & itLayer && obj_idx != -1)
2757 del_layer_from_object(obj_idx, m_objects_model->GetLayerRangeByItem(item));
2758 else if (type & itInfo && obj_idx != -1)
2759 del_info_item(obj_idx, item_info_type);
2760 else if (idx == -1)
2761 return;
2762 else if (!del_subobject_from_object(obj_idx, idx, type))
2763 return;
2764
2765 // If last volume item with warning was deleted, unmark object item
2766 if (type & itVolume) {
2767 const std::string& icon_name = get_warning_icon_name(object(obj_idx)->get_object_stl_stats());
2768 m_objects_model->UpdateWarningIcon(parent, icon_name);
2769 }
2770
2771 if (!(type & itInfo) || item_info_type != InfoItemType::CutConnectors) {
2772 // Connectors Item is already updated/deleted inside the del_info_item()
2773 m_objects_model->Delete(item);
2774 update_info_items(obj_idx);
2775 }
2776}
bool del_subobject_from_object(const int obj_idx, const int idx, const int type)
Definition GUI_ObjectList.cpp:2916
void del_info_item(const int obj_idx, InfoItemType type)
Definition GUI_ObjectList.cpp:2778
void del_settings_from_config(const wxDataViewItem &parent_item)
Definition GUI_ObjectList.cpp:2823
void del_instances_from_object(const int obj_idx)
Definition GUI_ObjectList.cpp:2850
void del_layers_from_object(const int obj_idx)
Definition GUI_ObjectList.cpp:2880
void del_layer_from_object(const int obj_idx, const t_layer_height_range &layer_range)
Definition GUI_ObjectList.cpp:2867
InfoItemType
Definition ObjectDataViewModel.hpp:75
@ itInfo
Definition ObjectDataViewModel.hpp:44
@ itUndef
Definition ObjectDataViewModel.hpp:35
@ itInstanceRoot
Definition ObjectDataViewModel.hpp:39

References Slic3r::GUI::CutConnectors, del_info_item(), del_instances_from_object(), del_layer_from_object(), del_layers_from_object(), del_settings_from_config(), del_subobject_from_object(), Slic3r::GUI::get_warning_icon_name(), Slic3r::GUI::itInfo, Slic3r::GUI::itInstanceRoot, Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itSettings, Slic3r::GUI::itUndef, Slic3r::GUI::itVolume, m_objects_model, and update_info_items().

Referenced by add_layer_range_after_current(), del_layer_range(), and remove().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_all_connectors_for_object()

void Slic3r::GUI::ObjectList::delete_all_connectors_for_object ( int obj_idx)
3639{
3640 ModelObject* init_obj = object(obj_idx);
3641 if (!init_obj->is_cut())
3642 return;
3643
3644 take_snapshot(_u8L("Delete all connectors"));
3645
3646 const CutObjectBase cut_id = init_obj->cut_id;
3647 // Delete all connectors for related objects (which have the same cut_id)
3648 Model& model = wxGetApp().plater()->model();
3649 for (int idx = int(m_objects->size())-1; idx >= 0; idx--)
3650 if (ModelObject* obj = object(idx); obj->cut_id.is_equal(cut_id)) {
3651 obj->delete_connectors();
3652
3653 if (obj->volumes.empty() || !obj->has_solid_mesh()) {
3654 const std::string deleted_obj_name = obj->name;
3655 model.delete_object(idx);
3656 {
3657 Slic3r::LifecycleEventContext ctx;
3658 ctx.name = deleted_obj_name;
3661 }
3662 m_objects_model->Delete(m_objects_model->GetItemById(idx));
3663 continue;
3664 }
3665
3666 update_info_items(idx);
3668 changed_object(int(idx));
3669 }
3670
3672}
void update_lock_icons_for_model()
Definition GUI_ObjectList.cpp:4477
@ ObjectDeleted
Definition LifecycleEvents.hpp:37

References _u8L, add_volumes_to_object_in_list(), changed_object(), Slic3r::LifecycleEventContext::code, Slic3r::ModelObject::cut_id, Slic3r::Model::delete_object(), Slic3r::fire_lifecycle_event(), Slic3r::ModelObject::is_cut(), Slic3r::CutObjectBase::is_equal(), m_objects, m_objects_model, Slic3r::LifecycleEventContext::name, object(), Slic3r::ObjectDeleted, Slic3r::Ok, Slic3r::GUI::take_snapshot(), update_info_items(), and update_lock_icons_for_model().

Referenced by delete_all_connectors_for_selection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_all_connectors_for_selection()

void Slic3r::GUI::ObjectList::delete_all_connectors_for_selection ( )
3629{
3630 const wxDataViewItem item = GetSelection();
3631 if (item) {
3632 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
3633 if (obj_idx >= 0)
3634 delete_all_connectors_for_object(size_t(obj_idx));
3635 }
3636}
void delete_all_connectors_for_object(int obj_idx)
Definition GUI_ObjectList.cpp:3638

References delete_all_connectors_for_object(), and m_objects_model.

Referenced by del_from_cut_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_all_objects_from_list()

void Slic3r::GUI::ObjectList::delete_all_objects_from_list ( )
4486{
4487 m_prevent_list_events = true;
4489 m_prevent_list_events = false;
4491}
void reload_all_plates(bool notify_partplate=false)
Definition GUI_ObjectList.cpp:6917
void part_selection_changed()
Definition GUI_ObjectList.cpp:3721

References m_prevent_list_events, part_selection_changed(), and reload_all_plates().

Here is the call graph for this function:

◆ delete_from_model_and_list() [1/2]

void Slic3r::GUI::ObjectList::delete_from_model_and_list ( const ItemType type,
const int obj_idx,
const int sub_obj_idx )
4379{
4380 if (!(type&(itObject|itVolume|itInstance)))
4381 return;
4382
4383 take_snapshot(_u8L("Delete selected"));
4384
4385 if (type&itObject) {
4386 bool was_cut = object(obj_idx)->is_cut();
4387 // For variable layer height, the size of layer data is larger than 4
4388 bool vari_layer_height = (object(obj_idx)->layer_height_profile.get().size() > 4);
4389 if (del_object(obj_idx)) {
4390 delete_object_from_list(obj_idx);
4391 if (was_cut)
4393 if (vari_layer_height) {
4396 }
4397 }
4398 }
4399 else {
4400 del_subobject_from_object(obj_idx, sub_obj_idx, type);
4401
4402 type == itVolume ? delete_volume_from_list(obj_idx, sub_obj_idx) :
4403 delete_instance_from_list(obj_idx, sub_obj_idx);
4404 }
4405}
void delete_instance_from_list(const size_t obj_idx, const size_t inst_idx)
Definition GUI_ObjectList.cpp:4373
size_t m_variable_layer_obj_num
Definition GUI_ObjectList.hpp:180
void delete_object_from_list()
Definition GUI_ObjectList.cpp:4352
void set_variable_height_column_hidden(const bool hide) const
Definition GUI_ObjectList.cpp:1120
void delete_volume_from_list(const size_t obj_idx, const size_t vol_idx)
Definition GUI_ObjectList.cpp:4368
bool del_object(const int obj_idx, bool refresh_immediately=true)
Definition GUI_ObjectList.cpp:2730
std::vector< coordf_t > get() const
Definition Model.hpp:224
bool is_cut() const
Definition Model.hpp:577
LayerHeightProfile layer_height_profile
Definition Model.hpp:400

References _u8L, del_object(), del_subobject_from_object(), delete_instance_from_list(), delete_object_from_list(), delete_volume_from_list(), Slic3r::LayerHeightProfile::get(), Slic3r::ModelObject::is_cut(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, Slic3r::ModelObject::layer_height_profile, m_variable_layer_obj_num, object(), set_variable_height_column_hidden(), Slic3r::GUI::take_snapshot(), and update_lock_icons_for_model().

Referenced by remove().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_from_model_and_list() [2/2]

void Slic3r::GUI::ObjectList::delete_from_model_and_list ( const std::vector< ItemForDelete > & items_for_delete)
4408{
4409 if (items_for_delete.empty())
4410 return;
4411
4412 m_prevent_list_events = true;
4413 //BBS
4414 bool need_update = false;
4415
4416 std::set<size_t> modified_objects_ids;
4417 for (std::vector<ItemForDelete>::const_reverse_iterator item = items_for_delete.rbegin(); item != items_for_delete.rend(); ++item) {
4418 if (!(item->type&(itObject | itVolume | itInstance)))
4419 continue;
4420 if (item->type&itObject) {
4421 // refresh after del_object
4422 need_update = true;
4423 bool refresh_immediately = false;
4424 bool was_cut = object(item->obj_idx)->is_cut();
4425 // For variable layer height, the size of layer data is larger than 4
4426 bool vari_layer_height = (object(item->obj_idx)->layer_height_profile.get().size() > 4);
4427 if (!del_object(item->obj_idx, refresh_immediately))
4428 return;
4429 m_objects_model->Delete(m_objects_model->GetItemById(item->obj_idx));
4430 if (was_cut)
4432 if (vari_layer_height) {
4435 }
4436 }
4437 else {
4438 if (!del_subobject_from_object(item->obj_idx, item->sub_obj_idx, item->type))
4439 return; //continue;
4440 if (item->type&itVolume) {
4441 m_objects_model->Delete(m_objects_model->GetItemByVolumeId(item->obj_idx, item->sub_obj_idx));
4442 // BBS
4443#if 0
4444 ModelObject* obj = object(item->obj_idx);
4445 if (obj->volumes.size() == 1) {
4446 wxDataViewItem parent = m_objects_model->GetItemById(item->obj_idx);
4447 if (obj->config.has("extruder")) {
4448 const wxString extruder = wxString::Format("%d", obj->config.extruder());
4449 m_objects_model->SetExtruder(extruder, parent);
4450 }
4451 // If last volume item with warning was deleted, unmark object item
4452 m_objects_model->UpdateWarningIcon(parent, get_warning_icon_name(obj->get_object_stl_stats()));
4453 }
4454#endif
4455 wxGetApp().plater()->canvas3D()->ensure_on_bed(item->obj_idx, printer_technology() != ptSLA);
4456 }
4457 else
4458 m_objects_model->Delete(m_objects_model->GetItemByInstanceId(item->obj_idx, item->sub_obj_idx));
4459 }
4460
4461 modified_objects_ids.insert(static_cast<size_t>(item->obj_idx));
4462 }
4463
4464 if (need_update) {
4465 wxGetApp().plater()->update();
4466 wxGetApp().plater()->object_list_changed();
4467 }
4468
4469 for (size_t id : modified_objects_ids) {
4471 }
4472
4473 m_prevent_list_events = true;
4475}

References Slic3r::ModelObject::config, del_object(), del_subobject_from_object(), Slic3r::ModelConfig::extruder(), Slic3r::LayerHeightProfile::get(), Slic3r::ModelObject::get_object_stl_stats(), Slic3r::GUI::get_warning_icon_name(), Slic3r::ModelConfig::has(), Slic3r::ModelObject::is_cut(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, Slic3r::ModelObject::layer_height_profile, m_objects_model, m_prevent_list_events, m_variable_layer_obj_num, object(), part_selection_changed(), Slic3r::GUI::printer_technology(), Slic3r::ptSLA, set_variable_height_column_hidden(), update_info_items(), update_lock_icons_for_model(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ delete_instance_from_list()

void Slic3r::GUI::ObjectList::delete_instance_from_list ( const size_t obj_idx,
const size_t inst_idx )
4374{
4375 select_item([this, obj_idx, inst_idx]() { return m_objects_model->Delete(m_objects_model->GetItemByInstanceId(obj_idx, inst_idx)); });
4376}

References m_objects_model, and select_item().

Referenced by delete_from_model_and_list(), instances_to_separated_object(), and instances_to_separated_objects().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_object_from_list() [1/2]

void Slic3r::GUI::ObjectList::delete_object_from_list ( )
4353{
4354 auto item = GetSelection();
4355 if (!item)
4356 return;
4357 if (m_objects_model->GetParent(item) == wxDataViewItem(nullptr))
4358 select_item([this, item]() { return m_objects_model->Delete(item); });
4359 else
4360 select_item([this, item]() { return m_objects_model->Delete(m_objects_model->GetParent(item)); });
4361}

References m_objects_model, and select_item().

Referenced by Slic3r::GUI::Plater::apply_cut_object_to_model(), and delete_from_model_and_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete_object_from_list() [2/2]

void Slic3r::GUI::ObjectList::delete_object_from_list ( const size_t obj_idx)
4364{
4365 select_item([this, obj_idx]() { return m_objects_model->Delete(m_objects_model->GetItemById(obj_idx)); });
4366}

References m_objects_model, and select_item().

Here is the call graph for this function:

◆ delete_volume_from_list()

void Slic3r::GUI::ObjectList::delete_volume_from_list ( const size_t obj_idx,
const size_t vol_idx )
4369{
4370 select_item([this, obj_idx, vol_idx]() { return m_objects_model->Delete(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx)); });
4371}

References m_objects_model, and select_item().

Referenced by delete_from_model_and_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dispatch_shortcut()

bool Slic3r::GUI::ObjectList::dispatch_shortcut ( Shortcut shortcut)
1877{
1878 switch (shortcut) {
1879 case Shortcut::DeleteSelected: remove(); break;
1881 case Shortcut::Copy: copy(); break;
1882 case Shortcut::Paste: paste(); break;
1883 case Shortcut::Cut: cut(); break;
1884 case Shortcut::Undo: undo(); break;
1885 case Shortcut::Redo: redo(); break;
1886 case Shortcut::CloneSelected: clone(); break;
1891 default: return false;
1892 }
1893 return true;
1894}
void toggle_auto_drop()
Definition GUI_ObjectList.cpp:7081
void cut()
Definition GUI_ObjectList.cpp:1765
void clone()
Definition GUI_ObjectList.cpp:1770
void select_item_all_children()
Definition GUI_ObjectList.cpp:5375
void copy()
Definition GUI_ObjectList.cpp:1755
void increase_instances()
Definition GUI_ObjectList.cpp:1826
void paste()
Definition GUI_ObjectList.cpp:1760
void redo()
Definition GUI_ObjectList.cpp:1821
void toggle_printable_state()
Definition GUI_ObjectList.cpp:7024
void undo()
Definition GUI_ObjectList.cpp:1816
void decrease_instances()
Definition GUI_ObjectList.cpp:1831
@ RemoveInstance
Definition Shortcuts.hpp:35
@ Undo
Definition Shortcuts.hpp:33
@ Paste
Definition Shortcuts.hpp:33
@ ToggleAutoDrop
Definition Shortcuts.hpp:35
@ Redo
Definition Shortcuts.hpp:33
@ Copy
Definition Shortcuts.hpp:33
@ SelectAll
Definition Shortcuts.hpp:31
@ TogglePrintable
Definition Shortcuts.hpp:35
@ DeleteSelected
Definition Shortcuts.hpp:33
@ CloneSelected
Definition Shortcuts.hpp:33
@ AddInstance
Definition Shortcuts.hpp:35
@ Cut
Definition Shortcuts.hpp:33

References Slic3r::GUI::AddInstance, clone(), Slic3r::GUI::CloneSelected, Slic3r::GUI::Copy, copy(), Slic3r::GUI::Cut, cut(), decrease_instances(), Slic3r::GUI::DeleteSelected, increase_instances(), Slic3r::GUI::Paste, paste(), Slic3r::GUI::Redo, redo(), remove(), Slic3r::GUI::RemoveInstance, select_item_all_children(), Slic3r::GUI::SelectAll, toggle_auto_drop(), toggle_printable_state(), Slic3r::GUI::ToggleAutoDrop, Slic3r::GUI::TogglePrintable, Slic3r::GUI::Undo, and undo().

Referenced by ObjectList(), and key_event().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ edit_layer_range() [1/2]

bool Slic3r::GUI::ObjectList::edit_layer_range ( const t_layer_height_range & range,
const t_layer_height_range & new_range,
bool suppress_ui_update = false )
4836{
4837 // Use m_selected_object_id instead of get_selected_obj_idx()
4838 // because of get_selected_obj_idx() return obj_idx for currently selected item.
4839 // But edit_layer_range(...) function can be called, when Selection in ObjectList could be changed
4840 const int obj_idx = m_selected_object_id;
4841 if (obj_idx < 0) return false;
4842
4843 // BBS: remove snapeshot name "Edit Height Range"
4844 take_snapshot("");
4845
4846 const ItemType sel_type = m_objects_model->GetItemType(GetSelection());
4847
4848 auto& ranges = object(obj_idx)->layer_config_ranges;
4849
4850 {
4851 ModelConfig config = std::move(ranges[range]);
4852 ranges.erase(range);
4853 ranges[new_range] = std::move(config);
4854 }
4855
4856 changed_object(obj_idx);
4857
4858 wxDataViewItem root_item = m_objects_model->GetLayerRootItem(m_objects_model->GetItemById(obj_idx));
4859 // To avoid update selection after deleting of a selected item (under GTK)
4860 // set m_prevent_list_events to true
4861 m_prevent_list_events = true;
4862 m_objects_model->DeleteChildren(root_item);
4863
4864 if (root_item.IsOk()) {
4865 // create Layer item(s) according to the layer_config_ranges
4866 for (const auto& r : ranges)
4867 add_layer_item(r.first, root_item);
4868 }
4869
4870 // if this function was invoked from wxEVT_CHANGE_SELECTION selected item could be other than itLayer or itLayerRoot
4871 if (!dont_update_ui && (sel_type & (itLayer | itLayerRoot)))
4872 select_item(sel_type&itLayer ? m_objects_model->GetItemByLayerRange(obj_idx, new_range) : root_item);
4873
4874 Expand(root_item);
4875
4876 m_prevent_list_events = false;
4877 return true;
4878}
int m_selected_object_id
Definition GUI_ObjectList.hpp:186

References add_layer_item(), changed_object(), config(), Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::ModelObject::layer_config_ranges, m_objects_model, m_prevent_list_events, m_selected_object_id, object(), Slic3r::range(), select_item(), and Slic3r::GUI::take_snapshot().

Here is the call graph for this function:

◆ edit_layer_range() [2/2]

bool Slic3r::GUI::ObjectList::edit_layer_range ( const t_layer_height_range & range,
coordf_t layer_height )
4810{
4811 // Use m_selected_object_id instead of get_selected_obj_idx()
4812 // because of get_selected_obj_idx() return obj_idx for currently selected item.
4813 // But edit_layer_range(...) function can be called, when Selection in ObjectList could be changed
4814 const int obj_idx = m_selected_object_id ;
4815 if (obj_idx < 0)
4816 return false;
4817
4818 ModelConfig* config = &object(obj_idx)->layer_config_ranges[range];
4819 if (fabs(layer_height - config->opt_float("layer_height")) < EPSILON)
4820 return false;
4821
4822 const int extruder_idx = config->opt_int("extruder");
4823
4824 if (layer_height >= get_min_layer_height(extruder_idx) &&
4825 layer_height <= get_max_layer_height(extruder_idx))
4826 {
4827 config->set_key_value("layer_height", new ConfigOptionFloat(layer_height));
4828 changed_object(obj_idx);
4829 return true;
4830 }
4831
4832 return false;
4833}
static double get_max_layer_height(const int extruder_idx)
Definition GUI_ObjectList.cpp:4656

References changed_object(), config(), Slic3r::ConfigOptionFloat, EPSILON, Slic3r::GUI::get_max_layer_height(), Slic3r::GUI::get_min_layer_height(), Slic3r::ModelObject::layer_config_ranges, Slic3r::GUI::layer_height, m_selected_object_id, object(), and Slic3r::range().

Here is the call graph for this function:

◆ enable_layers_editing()

void Slic3r::GUI::ObjectList::enable_layers_editing ( )
7120{
7121 wxDataViewItemArray sels;
7122 GetSelections(sels);
7123 if (sels.IsEmpty())
7124 return;
7125
7126 wxDataViewItem frst_item = sels[0];
7127
7128 ItemType type = m_objects_model->GetItemType(frst_item);
7129 if (!(type & itObject))
7130 return;
7131 //take_snapshot("");
7132
7133 auto view3d = wxGetApp().plater()->get_view3D_canvas3D();
7134 if (view3d != nullptr && m_objects_model->IsVariableHeight(frst_item)){
7135 view3d->enable_layers_editing(true);
7136 }
7137}

References Slic3r::GUI::itObject, and m_objects_model.

Referenced by list_manipulation().

Here is the caller graph for this function:

◆ ensure_current_item_visible()

void Slic3r::GUI::ObjectList::ensure_current_item_visible ( )
inlineprivate
221 {
222 if (const auto &item = this->GetCurrentItem())
223 this->EnsureVisible(item);
224 }

Referenced by ObjectList(), selected_object(), and update_selections().

Here is the caller graph for this function:

◆ extruder_editing()

void Slic3r::GUI::ObjectList::extruder_editing ( )
1717{
1718 wxDataViewItem item = GetSelection();
1719 if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
1720 return;
1721
1722 const int column_width = GetColumn(colFilament)->GetWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X) + 5;
1723
1724 wxPoint pos = this->get_mouse_position_in_control();
1725 wxSize size = wxSize(column_width, -1);
1726 pos.x = GetColumn(colName)->GetWidth() + GetColumn(colPrint)->GetWidth() + GetColumn(colHeight)->GetWidth() + 5;
1727 pos.y -= GetTextExtent("m").y;
1728
1729 apply_extruder_selector(&m_extruder_editor, this, "1", pos, size);
1730
1731 m_extruder_editor->SetSelection(m_objects_model->GetExtruderNumber(item));
1732 m_extruder_editor->Show();
1733
1734 auto set_extruder = [this]()
1735 {
1736 wxDataViewItem item = GetSelection();
1737 if (!item) return;
1738
1739 const int selection = m_extruder_editor->GetSelection();
1740 if (selection >= 0)
1741 m_objects_model->SetExtruder(m_extruder_editor->GetString(selection), item);
1742
1743 m_extruder_editor->Hide();
1745 };
1746
1747 // to avoid event propagation to other sidebar items
1748 m_extruder_editor->Bind(wxEVT_COMBOBOX, [set_extruder](wxCommandEvent& evt)
1749 {
1750 set_extruder();
1751 evt.StopPropagation();
1752 });
1753}
void update_filament_in_config(const wxDataViewItem &item)
Definition GUI_ObjectList.cpp:1145
BitmapComboBox * m_extruder_editor
Definition GUI_ObjectList.hpp:182
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
void apply_extruder_selector(Slic3r::GUI::BitmapComboBox **ctrl, wxWindow *parent, const std::string &first_item, wxPoint pos, wxSize size, bool use_thin_icon)
Definition wxExtensions.cpp:799

References apply_extruder_selector(), Slic3r::GUI::colFilament, Slic3r::GUI::colHeight, Slic3r::GUI::colName, Slic3r::GUI::colPrint, get_mouse_position_in_control(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_extruder_editor, m_objects_model, and update_filament_in_config().

Referenced by list_manipulation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fix_all_through_cgal()

void Slic3r::GUI::ObjectList::fix_all_through_cgal ( bool all_plates)
6309{
6310 std::vector<int> obj_idxs;
6311 if (all_plates) {
6312 for (int obj_idx = 0; obj_idx < int(m_objects->size()); ++obj_idx)
6313 obj_idxs.push_back(obj_idx);
6314 } else {
6315 for (const ModelObject *mo : wxGetApp().plater()->get_partplate_list().get_selected_plate()->get_objects_on_this_plate())
6316 obj_idxs.push_back(int(std::find(m_objects->begin(), m_objects->end(), mo) - m_objects->begin()));
6317 std::sort(obj_idxs.begin(), obj_idxs.end());
6318 obj_idxs.erase(std::unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
6319 }
6320 fix_through_cgal(obj_idxs, {});
6321}
void fix_through_cgal()
Definition GUI_ObjectList.cpp:6301

References fix_through_cgal(), m_objects, and Slic3r::GUI::plater().

Here is the call graph for this function:

◆ fix_cut_selection() [1/2]

void Slic3r::GUI::ObjectList::fix_cut_selection ( )
5558{
5559 wxDataViewItemArray sels;
5560 GetSelections(sels);
5561 if (fix_cut_selection(sels)) {
5562 m_prevent_list_events = true;
5563
5564 // If some part is selected, unselect all items except of selected parts of the current object
5565 UnselectAll();
5566 SetSelections(sels);
5567
5568 m_prevent_list_events = false;
5569 }
5570}
void fix_cut_selection()
Definition GUI_ObjectList.cpp:5557

References fix_cut_selection(), and m_prevent_list_events.

Referenced by fix_cut_selection(), selection_changed(), and update_selections().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fix_cut_selection() [2/2]

bool Slic3r::GUI::ObjectList::fix_cut_selection ( wxDataViewItemArray & sels)
5573{
5574 if (wxGetApp().plater()->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Scale) {
5575 for (const auto &item : sels) {
5576 if (m_objects_model->GetItemType(item) & (itInstance | itObject) ||
5577 (m_objects_model->GetItemType(item) & itSettings && m_objects_model->GetItemType(m_objects_model->GetParent(item)) & itObject)) {
5578 bool is_instance_selection = m_objects_model->GetItemType(item) & itInstance;
5579
5580 int object_idx = m_objects_model->GetObjectIdByItem(item);
5581 int inst_idx = is_instance_selection ? m_objects_model->GetInstanceIdByItem(item) : 0;
5582
5583 if (auto obj = object(object_idx); obj->is_cut()) {
5584 sels.Clear();
5585
5586 auto cut_id = obj->cut_id;
5587
5588 int objects_cnt = int((*m_objects).size());
5589 for (int obj_idx = 0; obj_idx < objects_cnt; ++obj_idx) {
5590 auto object = (*m_objects)[obj_idx];
5591 if (object->is_cut() && object->cut_id.has_same_id(cut_id))
5592 sels.Add(is_instance_selection ? m_objects_model->GetItemByInstanceId(obj_idx, inst_idx) : m_objects_model->GetItemById(obj_idx));
5593 }
5594 return true;
5595 }
5596 }
5597 }
5598 }
5599 return false;
5600}
@ Scale
Definition GLGizmosManager.hpp:90

References Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::GUI::itSettings, m_objects_model, object(), Slic3r::GUI::plater(), and Slic3r::GUI::GLGizmosManager::Scale.

Here is the call graph for this function:

◆ fix_multiselection_conflicts()

void Slic3r::GUI::ObjectList::fix_multiselection_conflicts ( )
5484{
5485 if (GetSelectedItemsCount() <= 1) {
5487 return;
5488 }
5489
5490 wxString msg_string;
5491 if (!check_last_selection(msg_string))
5492 return;
5493
5494 m_prevent_list_events = true;
5495
5496 wxDataViewItemArray sels;
5497 GetSelections(sels);
5498
5500 {
5501 // identify correct parent of the initial selected item
5502 const wxDataViewItem& parent = m_objects_model->GetParent(m_last_selected_item == sels.front() ? sels.back() : sels.front());
5503
5504 sels.clear();
5505 wxDataViewItemArray children; // selected volumes from current parent
5506 m_objects_model->GetChildren(parent, children);
5507
5508 const ItemType item_type = m_selection_mode & smVolume ? itVolume : itLayer;
5509
5510 for (const auto& child : children)
5511 if (IsSelected(child) && m_objects_model->GetItemType(child) & item_type)
5512 sels.Add(child);
5513
5514 // If some part is selected, unselect all items except of selected parts of the current object
5515 UnselectAll();
5516 SetSelections(sels);
5517 }
5518 else
5519 {
5520 for (const auto& item : sels)
5521 {
5522 if (!IsSelected(item)) // if this item is unselected now (from previous actions)
5523 continue;
5524
5525 if (m_objects_model->GetItemType(item) & itSettings) {
5526 Unselect(item);
5527 continue;
5528 }
5529
5530 const wxDataViewItem& parent = m_objects_model->GetParent(item);
5531 if (parent != wxDataViewItem(nullptr) && IsSelected(parent))
5532 Unselect(parent);
5533 else
5534 {
5535 wxDataViewItemArray unsels;
5536 m_objects_model->GetAllChildren(item, unsels);
5537 for (const auto& unsel_item : unsels)
5538 Unselect(unsel_item);
5539 }
5540
5541 if (m_objects_model->GetItemType(item) & itVolume)
5542 Unselect(item);
5543
5545 }
5546 }
5547
5548 if (!msg_string.IsEmpty())
5549 show_info(this, msg_string, _(L("Info")));
5550
5551 if (!IsSelected(m_last_selected_item))
5552 m_last_selected_item = wxDataViewItem(nullptr);
5553
5554 m_prevent_list_events = false;
5555}
void update_selection_mode()
Definition GUI_ObjectList.cpp:5404
bool check_last_selection(wxString &msg_str)
Definition GUI_ObjectList.cpp:5422

References _, check_last_selection(), Slic3r::GUI::itLayer, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, L, m_last_selected_item, m_objects_model, m_prevent_list_events, m_selection_mode, Slic3r::GUI::show_info(), smInstance, smLayer, smVolume, and update_selection_mode().

Referenced by selection_changed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fix_through_cgal() [1/2]

void Slic3r::GUI::ObjectList::fix_through_cgal ( )
6302{
6303 std::vector<int> obj_idxs, vol_idxs;
6304 get_selection_indexes(obj_idxs, vol_idxs);
6305 fix_through_cgal(obj_idxs, vol_idxs);
6306}

References fix_through_cgal(), and get_selection_indexes().

Referenced by fix_all_through_cgal(), fix_through_cgal(), and list_manipulation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ fix_through_cgal() [2/2]

void Slic3r::GUI::ObjectList::fix_through_cgal ( const std::vector< int > & obj_idxs,
const std::vector< int > & vol_idxs )
6324{
6325 // Do not fix anything when a gizmo is open. There might be issues with updates
6326 // and what is worse, the snapshot time would refer to the internal stack.
6327 if (obj_idxs.empty() || !wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::Undefined))
6328 return;
6329
6330 // model_name
6331 std::vector<std::string> succes_models;
6332 // model_name failing reason
6333 std::vector<std::pair<std::string, std::string>> failed_models;
6334 size_t unchanged_models = 0;
6335 bool painting_removed = false;
6336
6337 std::vector<std::string> model_names;
6338
6339 if (vol_idxs.empty()) {
6340 for (int obj_idx : obj_idxs)
6341 if (object(obj_idx))
6342 model_names.push_back(object(obj_idx)->name);
6343 }
6344 else {
6345 ModelObject* obj = object(obj_idxs.front());
6346 if (obj) {
6347 for (int vol_idx : vol_idxs)
6348 model_names.push_back(obj->volumes[vol_idx]->name);
6349 }
6350 }
6351
6352 auto plater = wxGetApp().plater();
6353 const bool keep_painting = GUI::wxGetApp().app_config->get_bool("keep_painting");
6354
6355 auto fix_and_update_progress = [&](const int obj_idx, const int vol_idx, int model_idx, ProgressDialog& progress_dlg)
6356 {
6357 ModelObject *mo = object(obj_idx);
6358 if (!mo)
6359 return false;
6360
6361 const std::string& model_name = model_names[model_idx];
6362 wxString msg = _L("Repairing model object");
6363 if (model_names.size() == 1)
6364 msg += ": " + from_u8(model_name) + "\n";
6365 else if (model_names.size() > 10)
6366 msg += ": " + from_u8(model_name) + wxString::Format(" (%d/%d)", model_idx + 1, int(model_names.size())) + "\n";
6367 else {
6368 msg += ":\n";
6369 for (int i = 0; i < int(model_names.size()); ++i)
6370 msg += (i == model_idx ? " > " : " ") + from_u8(model_names[i]) + "\n";
6371 msg += "\n";
6372 }
6373
6374 auto count_painted = [mo]() { return std::count_if(mo->volumes.begin(), mo->volumes.end(), [](const ModelVolume *mv) { return mv->is_any_painted(); }); };
6375 const auto painted_before = count_painted();
6376 std::string res;
6377 bool modified = false;
6378 if (!fix_model_with_cgal_gui(*mo, vol_idx, progress_dlg, msg, res, keep_painting, &modified))
6379 return false;
6380
6381 if (modified) {
6382 painting_removed = painting_removed || count_painted() < painted_before;
6383 mo->ensure_on_bed();
6384 plater->changed_mesh(obj_idx);
6387 update_item_error_icon(obj_idx, vol_idx);
6388 update_info_items(obj_idx);
6389 }
6390
6391 if (!res.empty())
6392 failed_models.push_back({ model_name, res });
6393 else if (modified)
6394 succes_models.push_back(model_name);
6395 else
6396 ++unchanged_models;
6397 return true;
6398 };
6399
6400 Plater::TakeSnapshot snapshot(plater, _u8L("Repairing model object"));
6401
6402 // Open a progress dialog.
6403 ProgressDialog progress_dlg(_L("Repairing model object"), "", 100, find_toplevel_parent(plater),
6404 wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT, true);
6405 int model_idx{ 0 };
6406 if (vol_idxs.empty()) {
6407 int vol_idx{ -1 };
6408 for (int obj_idx : obj_idxs) {
6409 if (!fix_and_update_progress(obj_idx, vol_idx, model_idx, progress_dlg))
6410 break;
6411 model_idx++;
6412 }
6413 }
6414 else {
6415 int obj_idx{ obj_idxs.front() };
6416 for (int vol_idx : vol_idxs) {
6417 if (!fix_and_update_progress(obj_idx, vol_idx, model_idx, progress_dlg))
6418 break;
6419 model_idx++;
6420 }
6421 }
6422 // Close the progress dialog
6423 progress_dlg.Update(100, "");
6424
6425 if (painting_removed)
6427
6428 // Show info notification
6429 std::vector<wxString> blocks;
6430 wxString bullet_suf = "\n - ";
6431 if (!succes_models.empty()) {
6432 wxString block = _L_PLURAL("The following model object has been repaired", "The following model objects have been repaired", succes_models.size()) + ":";
6433 for (auto& model : succes_models)
6434 block += bullet_suf + from_u8(model);
6435 blocks.push_back(block);
6436 }
6437 if (!failed_models.empty()) {
6438 wxString block = _L_PLURAL("Failed to repair the following model object", "Failed to repair the following model objects", failed_models.size()) + ":";
6439 for (auto& model : failed_models)
6440 block += bullet_suf + from_u8(model.first) + ": " + _(model.second);
6441 blocks.push_back(block);
6442 }
6443 if (unchanged_models > 0)
6444 blocks.push_back(format_wxstr(_L_PLURAL("%1$d model object needed no repair.", "%1$d model objects needed no repair.", unchanged_models), unchanged_models));
6445 wxString msg;
6446 for (const wxString &block : blocks)
6447 msg += (msg.IsEmpty() ? "" : "\n\n") + block;
6448 if (msg.IsEmpty())
6449 msg = _L("Repairing was canceled");
6451}
@ Undefined
Definition GLGizmosManager.hpp:109
@ PrintInfoShortNotificationLevel
Definition NotificationManager.hpp:220
void push_notification(const NotificationType type, int timestamp=0)
Definition NotificationManager.cpp:1892
void update_plate_values_for_items()
Definition GUI_ObjectList.cpp:911
void update_item_error_icon(const int obj_idx, int vol_idx) const
Definition GUI_ObjectList.cpp:6563
int notify_instance_update(int obj_id, int instance_id, bool is_new=false)
Definition PartPlate.cpp:7237
const NotificationManager * get_notification_manager() const
Definition Plater.cpp:23864
PartPlateList & get_partplate_list()
Definition Plater.cpp:22578
Sidebar & sidebar()
Definition Plater.cpp:16046
void notify_painting_removed()
Definition Plater.cpp:22210
void changed_mesh(int obj_idx)
Definition Plater.cpp:22218
ObjectList * obj_list()
Definition Plater.cpp:6638
wxTopLevelWindow * find_toplevel_parent(wxWindow *window)
Definition GUI_Utils.cpp:155
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:22
@ CgalFinished
Definition NotificationManager.hpp:149
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
bool fix_model_with_cgal_gui(ModelObject &model_object, int volume_idx, GUI::ProgressDialog &progress_dialog, const wxString &msg_header, std::string &fix_result, bool keep_painting, bool *modified)
Definition FixModelByCgal.cpp:35
#define _L_PLURAL(s, plural, n)
Definition I18N.hpp:96

References _, _L, _L_PLURAL, _u8L, Slic3r::GUI::CgalFinished, Slic3r::ModelObject::ensure_on_bed(), Slic3r::GUI::find_toplevel_parent(), Slic3r::fix_model_with_cgal_gui(), Slic3r::GUI::format_wxstr(), Slic3r::GUI::from_u8(), Slic3r::GUI::into_u8(), object(), Slic3r::GUI::plater(), Slic3r::GUI::NotificationManager::PrintInfoShortNotificationLevel, Slic3r::GUI::GLGizmosManager::Undefined, Slic3r::GUI::ProgressDialog::Update(), update_info_items(), update_item_error_icon(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ get_default_layer_config()

DynamicPrintConfig Slic3r::GUI::ObjectList::get_default_layer_config ( const int obj_idx)
3495{
3496 DynamicPrintConfig config;
3497 coordf_t layer_height = object(obj_idx)->config.has("layer_height") ?
3498 object(obj_idx)->config.opt_float("layer_height") :
3499 wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("layer_height");
3500 config.set_key_value("layer_height",new ConfigOptionFloat(layer_height));
3501 // BBS
3502 int extruder = object(obj_idx)->config.has("extruder") ?
3503 object(obj_idx)->config.opt_int("extruder") :
3504 wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("extruder");
3505 config.set_key_value("extruder", new ConfigOptionInt(0));
3506
3507 return config;
3508}
bool has(const t_config_option_key &opt_key) const
Definition PrintConfig.hpp:2651
int opt_int(const t_config_option_key &opt_key) const
Definition PrintConfig.hpp:2653
double opt_float(const t_config_option_key &opt_key) const
Definition PrintConfig.hpp:2655
ModelConfigObject config
Definition Model.hpp:395

References config(), Slic3r::ModelObject::config, Slic3r::ConfigOptionFloat, Slic3r::ModelConfig::has(), Slic3r::GUI::layer_height, object(), Slic3r::ModelConfig::opt_float(), and Slic3r::ModelConfig::opt_int().

Referenced by add_layer_range_after_current(), and layers_editing().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_item_config()

ModelConfig & Slic3r::GUI::ObjectList::get_item_config ( const wxDataViewItem & item) const
736{
737 static ModelConfig s_empty_config;
738
739 assert(item);
740 const ItemType type = m_objects_model->GetItemType(item);
741
742 if (type & itPlate)
743 return s_empty_config;
744
745 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
746 const int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1;
747
748 assert(obj_idx >= 0 || ((type & itVolume) && vol_idx >=0));
749 return type & itVolume ?(*m_objects)[obj_idx]->volumes[vol_idx]->config :
750 type & itLayer ?(*m_objects)[obj_idx]->layer_config_ranges[m_objects_model->GetLayerRangeByItem(item)] :
751 (*m_objects)[obj_idx]->config;
752}

References Slic3r::GUI::itLayer, Slic3r::GUI::itPlate, Slic3r::GUI::itVolume, and m_objects_model.

Referenced by add_category_to_settings_from_frequent(), add_category_to_settings_from_selection(), copy_settings_to_clipboard(), Slic3r::GUI::create_settings_popupmenu(), part_selection_changed(), paste_settings_into_list(), set_extruder_for_selected_items(), update_filament_in_config(), and update_settings_item_and_selection().

Here is the caller graph for this function:

◆ get_mesh_errors_info() [1/2]

MeshErrorsInfo Slic3r::GUI::ObjectList::get_mesh_errors_info ( const int obj_idx,
const int vol_idx = -1,
wxString * sidebar_info = nullptr,
int * non_manifold_edges = nullptr ) const
606{
607 if (obj_idx < 0)
608 return { {}, {} }; // hide tooltip
609
610 const TriangleMeshStats& stats = vol_idx == -1 ?
611 (*m_objects)[obj_idx]->get_object_stl_stats() :
612 (*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stats();
613
614 if (!stats.repaired() && stats.manifold()) {
615 //if (sidebar_info)
616 // *sidebar_info = _L("No errors");
617 return { {}, {} }; // hide tooltip
618 }
619
620 wxString tooltip, auto_repaired_info, remaining_info;
621
622 // Create tooltip string, if there are errors
623 if (stats.repaired()) {
624 const int errors = get_repaired_errors_count(obj_idx, vol_idx);
625 auto_repaired_info = format_wxstr(_L_PLURAL("%1$d error repaired", "%1$d errors repaired", errors), errors);
626 tooltip += auto_repaired_info + "\n";
627 }
628 if (!stats.manifold()) {
629 remaining_info = format_wxstr(_L_PLURAL("Error: %1$d non-manifold edge.", "Error: %1$d non-manifold edges.", stats.open_edges), stats.open_edges);
630
631 tooltip += _L("Remaining errors") + ":\n";
632 tooltip += "\t" + format_wxstr(_L_PLURAL("%1$d non-manifold edge", "%1$d non-manifold edges", stats.open_edges), stats.open_edges) + "\n";
633 }
634
635 if (sidebar_info) {
636 *sidebar_info = stats.manifold() ? auto_repaired_info : (remaining_info + (stats.repaired() ? ("\n" + auto_repaired_info) : ""));
637 }
638
639 if (non_manifold_edges)
640 *non_manifold_edges = stats.open_edges;
641
642 if (!sidebar_info)
643 tooltip += "\n" + _L("Click the icon to repair model object");
644
645 return { tooltip, get_warning_icon_name(stats) };
646}
int get_repaired_errors_count(const int obj_idx, const int vol_idx=-1) const
Definition GUI_ObjectList.cpp:595

References _L, _L_PLURAL, Slic3r::GUI::format_wxstr(), get_repaired_errors_count(), Slic3r::GUI::get_warning_icon_name(), Slic3r::TriangleMeshStats::manifold(), Slic3r::TriangleMeshStats::open_edges, and Slic3r::TriangleMeshStats::repaired().

Referenced by get_mesh_errors_info(), and set_tooltip_for_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_mesh_errors_info() [2/2]

MeshErrorsInfo Slic3r::GUI::ObjectList::get_mesh_errors_info ( wxString * sidebar_info = nullptr,
int * non_manifold_edges = nullptr )
649{
650 wxDataViewItem item = GetSelection();
651 if (!item)
652 return { "", "" };
653
654 int obj_idx, vol_idx;
655 get_selected_item_indexes(obj_idx, vol_idx);
656
657 if (obj_idx < 0) { // child of ObjectItem is selected
658 if (sidebar_info)
659 obj_idx = m_objects_model->GetObjectIdByItem(item);
660 else
661 return { "", "" };
662 }
663 return get_mesh_errors_info(obj_idx, vol_idx, sidebar_info, non_manifold_edges);
664}
void get_selected_item_indexes(int &obj_idx, int &vol_idx, const wxDataViewItem &item=wxDataViewItem(0))
Definition GUI_ObjectList.cpp:546
MeshErrorsInfo get_mesh_errors_info(const int obj_idx, const int vol_idx=-1, wxString *sidebar_info=nullptr, int *non_manifold_edges=nullptr) const
Definition GUI_ObjectList.cpp:605

References get_mesh_errors_info(), get_selected_item_indexes(), and m_objects_model.

Here is the call graph for this function:

◆ get_mouse_position_in_control()

wxPoint Slic3r::GUI::ObjectList::get_mouse_position_in_control ( ) const
inline
352{ return wxGetMousePosition() - this->GetScreenPosition(); }

Referenced by ObjectList(), extruder_editing(), and OnContextMenu().

Here is the caller graph for this function:

◆ get_repaired_errors_count()

int Slic3r::GUI::ObjectList::get_repaired_errors_count ( const int obj_idx,
const int vol_idx = -1 ) const
596{
597 return obj_idx >= 0 ? (*m_objects)[obj_idx]->get_repaired_errors_count(vol_idx) : 0;
598}

Referenced by get_mesh_errors_info().

Here is the caller graph for this function:

◆ get_selected_item_indexes()

void Slic3r::GUI::ObjectList::get_selected_item_indexes ( int & obj_idx,
int & vol_idx,
const wxDataViewItem & item = wxDataViewItem(0) )
547{
548 const wxDataViewItem item = input_item == wxDataViewItem(nullptr) ? GetSelection() : input_item;
549
550 if (!item)
551 {
552 obj_idx = vol_idx = -1;
553 return;
554 }
555
556 const ItemType type = m_objects_model->GetItemType(item);
557
558 obj_idx = type & itObject ? m_objects_model->GetIdByItem(item) :
559 type & itVolume ? m_objects_model->GetIdByItem(m_objects_model->GetObject(item)) : -1;
560
561 vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1;
562}

References Slic3r::GUI::itObject, Slic3r::GUI::itVolume, and m_objects_model.

Referenced by get_mesh_errors_info(), list_manipulation(), OnEditingStarted(), and show_context_menu().

Here is the caller graph for this function:

◆ get_selected_layers_range_idx()

int Slic3r::GUI::ObjectList::get_selected_layers_range_idx ( ) const
4920{
4921 const wxDataViewItem& item = GetSelection();
4922 if (!item)
4923 return -1;
4924
4925 const ItemType type = m_objects_model->GetItemType(item);
4926 if (type & itSettings && m_objects_model->GetItemType(m_objects_model->GetParent(item)) != itLayer)
4927 return -1;
4928
4929 return m_objects_model->GetLayerIdByItem(type & itLayer ? item : m_objects_model->GetParent(item));
4930}

References Slic3r::GUI::itLayer, Slic3r::GUI::itSettings, and m_objects_model.

Referenced by Slic3r::GUI::Plater::priv::take_snapshot(), and Slic3r::GUI::Plater::priv::undo_redo_to().

Here is the caller graph for this function:

◆ get_selected_model_volume()

ModelVolume * Slic3r::GUI::ObjectList::get_selected_model_volume ( )
5603{
5604 wxDataViewItem item = GetSelection();
5605 if (!item)
5606 return nullptr;
5607 if (m_objects_model->GetItemType(item) != itVolume) {
5608 if (m_objects_model->GetItemType(m_objects_model->GetParent(item)) == itVolume)
5609 item = m_objects_model->GetParent(item);
5610 else
5611 return nullptr;
5612 }
5613
5614 const auto vol_idx = m_objects_model->GetVolumeIdByItem(item);
5615 const auto obj_idx = get_selected_obj_idx();
5616 if (vol_idx < 0 || obj_idx < 0)
5617 return nullptr;
5618
5619 return (*m_objects)[obj_idx]->volumes[vol_idx];
5620}

References get_selected_obj_idx(), Slic3r::GUI::itVolume, m_objects, and m_objects_model.

Referenced by get_selected_volume_type().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_selected_obj_idx()

int Slic3r::GUI::ObjectList::get_selected_obj_idx ( ) const
728{
729 if (GetSelectedItemsCount() == 1)
730 return m_objects_model->GetIdByItem(m_objects_model->GetObject(GetSelection()));
731
732 return -1;
733}

References m_objects_model.

Referenced by add_layer_range_after_current(), can_add_new_range_after_current(), can_merge_to_single_object(), can_mesh_boolean(), changed_object(), del_layer_range(), get_selected_model_volume(), get_volume_by_item(), is_splittable(), load_generic_subobject(), load_modifier(), split(), and Slic3r::GUI::ObjectLayers::update_layers_list().

Here is the caller graph for this function:

◆ get_selected_volume_type()

ModelVolumeType Slic3r::GUI::ObjectList::get_selected_volume_type ( )
5826{
5827 ModelVolume* volume = get_selected_model_volume();
5828 if (volume)
5829 return volume->type();
5831}
ModelVolume * get_selected_model_volume()
Definition GUI_ObjectList.cpp:5602
@ INVALID
Definition Model.hpp:356

References get_selected_model_volume(), Slic3r::INVALID, and Slic3r::ModelVolume::type().

Here is the call graph for this function:

◆ get_selection_indexes()

void Slic3r::GUI::ObjectList::get_selection_indexes ( std::vector< int > & obj_idxs,
std::vector< int > & vol_idxs )
565{
566 wxDataViewItemArray sels;
567 GetSelections(sels);
568 if (sels.IsEmpty())
569 return;
570
571 if ( m_objects_model->GetItemType(sels[0]) & itVolume ||
572 (sels.Count()==1 && m_objects_model->GetItemType(m_objects_model->GetParent(sels[0])) & itVolume) ) {
573 for (wxDataViewItem item : sels) {
574 obj_idxs.emplace_back(m_objects_model->GetIdByItem(m_objects_model->GetObject(item)));
575
576 if (sels.Count() == 1 && m_objects_model->GetItemType(m_objects_model->GetParent(item)) & itVolume)
577 item = m_objects_model->GetParent(item);
578
579 assert(m_objects_model->GetItemType(item) & itVolume);
580 vol_idxs.emplace_back(m_objects_model->GetVolumeIdByItem(item));
581 }
582 }
583 else {
584 for (wxDataViewItem item : sels) {
585 const ItemType type = m_objects_model->GetItemType(item);
586 obj_idxs.emplace_back(type & itObject ? m_objects_model->GetIdByItem(item) :
587 m_objects_model->GetIdByItem(m_objects_model->GetObject(item)));
588 }
589 }
590
591 std::sort(obj_idxs.begin(), obj_idxs.end(), std::less<int>());
592 obj_idxs.erase(std::unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
593}

References Slic3r::GUI::itObject, Slic3r::GUI::itVolume, and m_objects_model.

Referenced by boolean(), fix_through_cgal(), and smooth_mesh().

Here is the caller graph for this function:

◆ get_volume_by_item()

bool Slic3r::GUI::ObjectList::get_volume_by_item ( const wxDataViewItem & item,
ModelVolume *& volume )
3511{
3512 auto obj_idx = get_selected_obj_idx();
3513 if (!item || obj_idx < 0)
3514 return false;
3515 const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
3516 const bool split_part = m_objects_model->GetItemType(item) == itVolume;
3517
3518 // object is selected
3519 if (volume_id < 0) {
3520 if ( split_part || (*m_objects)[obj_idx]->volumes.size() > 1 )
3521 return false;
3522 volume = (*m_objects)[obj_idx]->volumes[0];
3523 }
3524 // volume is selected
3525 else
3526 volume = (*m_objects)[obj_idx]->volumes[volume_id];
3527
3528 return true;
3529}

References get_selected_obj_idx(), Slic3r::GUI::itVolume, m_objects, and m_objects_model.

Referenced by is_splittable(), and split().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetModel()

ObjectDataViewModel * Slic3r::GUI::ObjectList::GetModel ( ) const
inline
233{ return m_objects_model; }

References m_objects_model.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_printable(), Slic3r::GUI::MenuFactory::append_menu_item_set_printable(), and Slic3r::GUI::ObjectLayers::update_layers_list().

Here is the caller graph for this function:

◆ has_selected_cut_object()

bool Slic3r::GUI::ObjectList::has_selected_cut_object ( ) const
3581{
3582 wxDataViewItemArray sels;
3583 GetSelections(sels);
3584 if (sels.IsEmpty())
3585 return false;
3586
3587 for (wxDataViewItem item : sels) {
3588 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
3589 // ys_FIXME: The obj_idx<size condition is a workaround for https://github.com/prusa3d/PrusaSlicer/issues/11186,
3590 // but not the correct fix. The deleted item probably should not be in sels in the first place.
3591 if (obj_idx >= 0 && obj_idx < int(m_objects->size()) && object(obj_idx)->is_cut())
3592 return true;
3593 }
3594
3595 return false;
3596}

References m_objects, and m_objects_model.

Referenced by can_merge_to_multipart_object().

Here is the caller graph for this function:

◆ increase_instances()

void Slic3r::GUI::ObjectList::increase_instances ( )
1827{
1828 wxGetApp().plater()->increase_instances(1);
1829}

Referenced by dispatch_shortcut().

Here is the caller graph for this function:

◆ increase_object_instances()

void Slic3r::GUI::ObjectList::increase_object_instances ( const size_t obj_idx,
const size_t num )
4494{
4495 select_item([this, obj_idx, num]() { return m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num); });
4497}

References m_objects_model, select_item(), and selection_changed().

Referenced by Slic3r::GUI::Plater::increase_instances().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init()

void Slic3r::GUI::ObjectList::init ( )
4881{
4882 m_objects_model->Init();
4883 m_objects = &wxGetApp().model().objects;
4884}

References m_objects, and m_objects_model.

◆ instances_to_separated_object()

void Slic3r::GUI::ObjectList::instances_to_separated_object ( const int obj_idx,
const std::set< int > & inst_idx )
6191{
6192 if ((*m_objects)[obj_idx]->instances.size() == inst_idxs.size())
6193 {
6195 return;
6196 }
6197
6198 // create new object from selected instance
6199 ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
6200 for (int inst_idx = int(model_object->instances.size()) - 1; inst_idx >= 0; inst_idx--)
6201 {
6202 if (find(inst_idxs.begin(), inst_idxs.end(), inst_idx) != inst_idxs.end())
6203 continue;
6204 model_object->delete_instance(inst_idx);
6205 }
6206
6207 // Add new object to the object_list
6208 const size_t new_obj_indx = static_cast<size_t>(m_objects->size() - 1);
6209 add_object_to_list(new_obj_indx);
6210
6211 for (std::set<int>::const_reverse_iterator it = inst_idxs.rbegin(); it != inst_idxs.rend(); ++it)
6212 {
6213 // delete selected instance from the object
6215 delete_instance_from_list(obj_idx, *it);
6216 }
6217
6218 // update printable state for new volumes on canvas3D
6219 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object(new_obj_indx);
6220 update_info_items(new_obj_indx);
6221}
void instances_to_separated_objects(const int obj_idx)
Definition GUI_ObjectList.cpp:6223

References Slic3r::Model::add_object(), add_object_to_list(), del_subobject_from_object(), Slic3r::ModelObject::delete_instance(), delete_instance_from_list(), Slic3r::ModelObject::get_model(), Slic3r::ModelObject::instances, instances_to_separated_objects(), Slic3r::GUI::itInstance, m_objects, and update_info_items().

Referenced by merge(), and split_instances().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ instances_to_separated_objects()

void Slic3r::GUI::ObjectList::instances_to_separated_objects ( const int obj_idx)
6224{
6225 const int inst_cnt = (*m_objects)[obj_idx]->instances.size();
6226
6227 std::vector<size_t> object_idxs;
6228
6229 for (int i = inst_cnt-1; i > 0 ; i--)
6230 {
6231 // create new object from initial
6232 ModelObject* object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
6233 for (int inst_idx = object->instances.size() - 1; inst_idx >= 0; inst_idx--)
6234 {
6235 if (inst_idx == i)
6236 continue;
6237 // delete unnecessary instances
6238 object->delete_instance(inst_idx);
6239 }
6240
6241 // Add new object to the object_list
6242 const size_t new_obj_indx = static_cast<size_t>(m_objects->size() - 1);
6243 add_object_to_list(new_obj_indx);
6244 object_idxs.push_back(new_obj_indx);
6245
6246 // delete current instance from the initial object
6248 delete_instance_from_list(obj_idx, i);
6249 }
6250
6251 // update printable state for new volumes on canvas3D
6252 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(object_idxs);
6253 for (size_t object : object_idxs)
6254 update_info_items(object);
6255}

References Slic3r::Model::add_object(), add_object_to_list(), del_subobject_from_object(), delete_instance_from_list(), Slic3r::ModelObject::get_model(), Slic3r::GUI::itInstance, m_objects, object(), and update_info_items().

Referenced by instances_to_separated_object(), merge(), and split_instances().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ invalidate_cut_info_for_object()

void Slic3r::GUI::ObjectList::invalidate_cut_info_for_object ( int obj_idx)
3609{
3610 ModelObject* init_obj = object(obj_idx);
3611 if (!init_obj->is_cut())
3612 return;
3613
3614 take_snapshot(_u8L("Invalidate cut info"));
3615
3616 const CutObjectBase cut_id = init_obj->cut_id;
3617 // invalidate cut for related objects (which have the same cut_id)
3618 for (size_t idx = 0; idx < m_objects->size(); idx++)
3619 if (ModelObject* obj = object(int(idx)); obj->cut_id.is_equal(cut_id)) {
3620 obj->invalidate_cut();
3621 update_info_items(idx);
3623 }
3624
3626}

References _u8L, add_volumes_to_object_in_list(), Slic3r::ModelObject::cut_id, Slic3r::ModelObject::is_cut(), Slic3r::CutObjectBase::is_equal(), m_objects, object(), Slic3r::GUI::take_snapshot(), update_info_items(), and update_lock_icons_for_model().

Referenced by invalidate_cut_info_for_selection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ invalidate_cut_info_for_selection()

void Slic3r::GUI::ObjectList::invalidate_cut_info_for_selection ( )
3599{
3600 const wxDataViewItem item = GetSelection();
3601 if (item) {
3602 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
3603 if (obj_idx >= 0)
3604 invalidate_cut_info_for_object(size_t(obj_idx));
3605 }
3606}
void invalidate_cut_info_for_object(int obj_idx)
Definition GUI_ObjectList.cpp:3608

References invalidate_cut_info_for_object(), and m_objects_model.

Referenced by del_from_cut_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_connectors_item_selected() [1/2]

bool Slic3r::GUI::ObjectList::is_connectors_item_selected ( ) const
4901{
4902 const wxDataViewItem &item = GetSelection();
4903 if (item)
4904 return m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors;
4905
4906 return false;
4907}

References Slic3r::GUI::CutConnectors, Slic3r::GUI::itInfo, and m_objects_model.

Referenced by set_volume_type(), and update_selections().

Here is the caller graph for this function:

◆ is_connectors_item_selected() [2/2]

bool Slic3r::GUI::ObjectList::is_connectors_item_selected ( const wxDataViewItemArray & sels) const
4910{
4911 for (auto item : sels)
4912 if (m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors)
4913 return true;
4914
4915 return false;
4916}

References Slic3r::GUI::CutConnectors, Slic3r::GUI::itInfo, and m_objects_model.

◆ is_instance_or_object_selected()

bool Slic3r::GUI::ObjectList::is_instance_or_object_selected ( )
2239{
2240 const Selection& selection = scene_selection();
2241 return selection.is_single_full_instance() || selection.is_single_full_object();
2242}

References Slic3r::GUI::Selection::is_single_full_instance(), Slic3r::GUI::Selection::is_single_full_object(), and Slic3r::GUI::scene_selection().

Here is the call graph for this function:

◆ is_selected()

bool Slic3r::GUI::ObjectList::is_selected ( const ItemType type) const
4892{
4893 const wxDataViewItem& item = GetSelection();
4894 if (item)
4895 return m_objects_model->GetItemType(item) == type;
4896
4897 return false;
4898}

References m_objects_model.

Referenced by Slic3r::GUI::Plater::priv::take_snapshot(), Slic3r::GUI::Plater::priv::undo_redo_to(), and update_selections().

Here is the caller graph for this function:

◆ is_splittable()

bool Slic3r::GUI::ObjectList::is_splittable ( bool to_objects)
3532{
3533 const wxDataViewItem item = GetSelection();
3534 if (!item) return false;
3535
3536 if (to_objects)
3537 {
3538 ItemType type = m_objects_model->GetItemType(item);
3539 if (type == itVolume)
3540 return false;
3541 if (type == itObject || m_objects_model->GetItemType(m_objects_model->GetParent(item)) == itObject) {
3542 auto obj_idx = get_selected_obj_idx();
3543 if (obj_idx < 0)
3544 return false;
3545 if ((*m_objects)[obj_idx]->volumes.size() > 1)
3546 return true;
3547 return (*m_objects)[obj_idx]->volumes[0]->is_splittable();
3548 }
3549 return false;
3550 }
3551
3552 ModelVolume* volume;
3553 if (!get_volume_by_item(item, volume) || !volume)
3554 return false;
3555
3556 return volume->is_splittable();
3557}
bool get_volume_by_item(const wxDataViewItem &item, ModelVolume *&volume)
Definition GUI_ObjectList.cpp:3510

References get_selected_obj_idx(), get_volume_by_item(), Slic3r::ModelVolume::is_splittable(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_objects, and m_objects_model.

Referenced by can_mesh_boolean().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ItemValueChanged()

void Slic3r::GUI::ObjectList::ItemValueChanged ( wxDataViewEvent & event)
private
6610{
6611 if (event.GetColumn() == colName)
6612 update_name_in_model(event.GetItem());
6613 else if (event.GetColumn() == colFilament) {
6614 wxDataViewItem item = event.GetItem();
6615 if (m_objects_model->GetItemType(item) == itObject)
6616 m_objects_model->UpdateVolumesExtruderBitmap(item, true);
6618 }
6619}
void update_name_in_model(const wxDataViewItem &item) const
Definition GUI_ObjectList.cpp:1192

References Slic3r::GUI::colFilament, Slic3r::GUI::colName, Slic3r::GUI::itObject, m_objects_model, update_filament_in_config(), and update_name_in_model().

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ key_event()

void Slic3r::GUI::ObjectList::key_event ( wxKeyEvent & event)
1838{
1839 const std::optional<Shortcut> shortcut = wxGetApp().shortcuts().lookup(ShortcutContext::ObjectList, KeyChord::from_event(event));
1840 if (shortcut.has_value() && dispatch_shortcut(*shortcut))
1841 return;
1842 if (filaments_count() > 1) {
1843 std::vector<wxChar> numbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
1844 wxChar key_char = event.GetUnicodeKey();
1845 if (std::find(numbers.begin(), numbers.end(), key_char) != numbers.end()) {
1846 long extruder_number;
1847 if (wxNumberFormatter::FromString(wxString(key_char), &extruder_number) &&
1848 filaments_count() >= extruder_number)
1849 set_extruder_for_selected_items(int(extruder_number));
1850 }
1851 else
1852 event.Skip();
1853 }
1854 else
1855 event.Skip();
1856}
@ ObjectList
Definition Shortcuts.hpp:21
static KeyChord from_event(const wxKeyEvent &evt)
Definition KeyChord.cpp:343

References dispatch_shortcut(), Slic3r::GUI::filaments_count(), Slic3r::GUI::KeyChord::from_event(), Slic3r::GUI::ObjectList, and set_extruder_for_selected_items().

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ last_volume_is_deleted()

void Slic3r::GUI::ObjectList::last_volume_is_deleted ( const int obj_idx)
6058{
6059 // BBS: object (obj_idx calc in obj list) is already removed from m_objects in Plater::priv::remove().
6060#if 0
6061 if (obj_idx < 0 || size_t(obj_idx) >= m_objects->size() || (*m_objects)[obj_idx]->volumes.size() != 1)
6062 return;
6063
6064 auto volume = (*m_objects)[obj_idx]->volumes.front();
6065
6066 // clear volume's config values
6067 volume->config.reset();
6068
6069 // set a default extruder value, since user can't add it manually
6070 // BBS
6071 volume->config.set_key_value("extruder", new ConfigOptionInt(1));
6072#endif
6073}

References Slic3r::ModelVolume::config, m_objects, Slic3r::ModelConfig::reset(), and Slic3r::ModelConfig::set_key_value().

Here is the call graph for this function:

◆ layers_editing()

void Slic3r::GUI::ObjectList::layers_editing ( )
3338{
3339 // Height ranges give each range its own layer height, varying the mixed sub-layer heights just
3340 // like an adaptive profile, so this raises the same warning as variable layer height and shares
3341 // its do-not-show-again flag.
3342 const auto& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
3343 if (print_config.opt_bool("enable_mixed_color_sublayer")) {
3344 if (wxGetApp().app_config->get("no_warn_mixed_sublayer_variable_layer") != "1") {
3345 // Orca: parent to the plater like the sibling site in Plater::priv::on_action_layersediting
3346 // (BBS passes nullptr, which MsgDialog remaps to the main frame).
3347 MessageDialog dlg(wxGetApp().plater(),
3348 _L("Using variable layer height together with mixed color sublayer may result in poor color mixing quality."),
3349 _L("Warning"), wxICON_WARNING | wxOK);
3350 dlg.show_dsa_button();
3351 dlg.ShowModal();
3352 if (dlg.get_checkbox_state())
3353 wxGetApp().app_config->set("no_warn_mixed_sublayer_variable_layer", "1");
3354 }
3355 }
3356
3357 const Selection& selection = scene_selection();
3358 const int obj_idx = selection.get_object_idx();
3359 wxDataViewItem item = obj_idx >= 0 && GetSelectedItemsCount() > 1 && selection.is_single_full_object() ?
3360 m_objects_model->GetItemById(obj_idx) :
3361 GetSelection();
3362
3363 if (!item)
3364 return;
3365
3366 const wxDataViewItem obj_item = m_objects_model->GetObject(item);
3367 wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(obj_item);
3368
3369 // if it doesn't exist now
3370 if (!layers_item.IsOk())
3371 {
3373
3374 // set some default value
3375 if (ranges.empty()) {
3376 // BBS: remove snapshot name "Add layers"
3377 take_snapshot(_u8L("Add layers"));
3378 ranges[{ 0.0f, 2.0f }].assign_config(get_default_layer_config(obj_idx));
3379 }
3380
3381 // create layer root item
3382 layers_item = add_layer_root_item(obj_item);
3383 }
3384 if (!layers_item.IsOk())
3385 return;
3386
3387 // to correct visual hints for layers editing on the Scene, reset previous selection
3388 wxGetApp().obj_layers()->reset_selection();
3389 wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
3390
3391 // select LayerRoor item and expand
3392 select_item(layers_item);
3393 Expand(layers_item);
3394}

References _L, _u8L, add_layer_root_item(), Slic3r::GUI::MsgDialog::get_checkbox_state(), get_default_layer_config(), Slic3r::GUI::Selection::get_object_idx(), Slic3r::GUI::Selection::is_single_full_object(), Slic3r::ModelObject::layer_config_ranges, m_objects_model, object(), Slic3r::GUI::plater(), Slic3r::GUI::scene_selection(), select_item(), Slic3r::GUI::MsgDialog::show_dsa_button(), Slic3r::GUI::DPIAware< P >::ShowModal(), and Slic3r::GUI::take_snapshot().

Here is the call graph for this function:

◆ list_manipulation()

void Slic3r::GUI::ObjectList::list_manipulation ( const wxPoint & mouse_pos,
bool evt_context_menu = false )
private
1532{
1533 if (m_prevent_list_manipulation) return;
1534
1535 // Interesting fact: when mouse_pos.x < 0, HitTest(mouse_pos, item, col) returns item = null, but column = last column.
1536 // So, when mouse was moved to scene immediately after clicking in ObjectList, in the scene will be shown context menu for the Editing column.
1537 if (mouse_pos.x < 0)
1538 return;
1539
1540 wxDataViewItem item;
1541 wxDataViewColumn* col = nullptr;
1542 HitTest(mouse_pos, item, col);
1543
1545 m_extruder_editor->Hide();
1546
1547 /* Note: Under OSX right click doesn't send "selection changed" event.
1548 * It means that Selection() will be return still previously selected item.
1549 * Thus under OSX we should force UnselectAll(), when item and col are nullptr,
1550 * and select new item otherwise.
1551 */
1552
1553 // BBS
1554 //if (!item)
1555 {
1556 if (col == nullptr) {
1557 if (wxOSX && !multiple_selection())
1558 UnselectAll();
1559 else if (!evt_context_menu)
1560 // Case, when last item was deleted and under GTK was called wxEVT_DATAVIEW_SELECTION_CHANGED,
1561 // which invoked next list_manipulation(false)
1562 return;
1563 }
1564
1565 if (evt_context_menu) {
1566 show_context_menu(evt_context_menu);
1567 return;
1568 }
1569 }
1570
1571 if (wxOSX && item && col) {
1572 wxDataViewItemArray sels;
1573 GetSelections(sels);
1574 UnselectAll();
1575 if (sels.Count() > 1)
1576 SetSelections(sels);
1577 else
1578 Select(item);
1579 }
1580
1581 if (col != nullptr)
1582 {
1583 const wxString title = col->GetTitle();
1584 ColumnNumber col_num = (ColumnNumber)col->GetModelColumn();
1585 if (col_num == colHeight)
1587 else if (col_num == colPrint)
1589 else if (col_num == colSupportPaint) {
1590 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
1591 if (node && node->HasSupportPainting()) {
1592 GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
1593 if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::FdmSupports)
1594 gizmos_mgr.open_gizmo(GLGizmosManager::EType::FdmSupports);
1595 else
1596 gizmos_mgr.reset_all_states();
1597 }
1598 }
1599 else if (col_num == colColorPaint) {
1600 if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() != GLCanvas3D::CanvasAssembleView) {
1601 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
1602 if (node && node->HasColorPainting()) {
1603 GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
1604 if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmSegmentation)
1605 gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmSegmentation);
1606 else
1607 gizmos_mgr.reset_all_states();
1608 }
1609 }
1610 }
1611 else if (col_num == colSinking) {
1612 Plater * plater = wxGetApp().plater();
1613 GLCanvas3D *cnv = plater->canvas3D();
1614 if (cnv->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasPreview) {//ban reload_scene in Preview scene
1615 return;
1616 }
1617 int obj_idx, vol_idx;
1618 get_selected_item_indexes(obj_idx, vol_idx, item);
1619 if (obj_idx != -1) {
1620 Plater::TakeSnapshot snapshot(plater, _u8L("Shift objects to bed"));
1621 // Shift on request also when auto drop is off, which ensure_on_bed() skips.
1622 ModelObject* mo = (*m_objects)[obj_idx];
1623 mo->translate_instances(-mo->min_z() * Vec3d::UnitZ());
1624 cnv->reload_scene(true, true);
1625 update_info_items(obj_idx);
1626 notify_instance_updated(obj_idx);
1627 }
1628 }
1629 else if (col_num == colEditing) {
1630 //show_context_menu(evt_context_menu);
1631 int obj_idx, vol_idx;
1632
1633 get_selected_item_indexes(obj_idx, vol_idx, item);
1634 //wxGetApp().plater()->PopupObjectTable(obj_idx, vol_idx, mouse_pos);
1635 if (m_objects_model->GetItemType(item) & itPlate)
1636 dynamic_cast<TabPrintPlate*>(wxGetApp().get_plate_tab())->reset_model_config();
1637 else if (m_objects_model->GetItemType(item) & itLayer)
1638 dynamic_cast<TabPrintLayer*>(wxGetApp().get_layer_tab())->reset_model_config();
1639 else if (item.IsOk())
1640 dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab(vol_idx >= 0))->reset_model_config();
1641 wxGetApp().params_panel()->notify_object_config_changed();
1642 }
1643 else if (col_num == colName)
1644 {
1645 if (m_objects_model->HasWarningIcon(item) &&
1646 mouse_pos.x > 2 * wxGetApp().em_unit() && mouse_pos.x < 4 * wxGetApp().em_unit())
1648 else if (evt_context_menu)
1649 show_context_menu(evt_context_menu); // show context menu for "Name" column too
1650 }
1651 // workaround for extruder editing under OSX
1652 else if (wxOSX && evt_context_menu && col_num == colFilament)
1654 }
1655
1656#ifndef __WXMSW__
1657 GetMainWindow()->SetToolTip(""); // hide tooltip
1658#endif //__WXMSW__
1659}
@ CanvasAssembleView
Definition GLCanvas3D.hpp:628
@ CanvasPreview
Definition GLCanvas3D.hpp:627
@ MmSegmentation
Definition GLGizmosManager.hpp:97
@ FdmSupports
Definition GLGizmosManager.hpp:94
void show_context_menu(const bool evt_context_menu)
Definition GUI_ObjectList.cpp:1661
bool multiple_selection() const
Definition GUI_ObjectList.cpp:4886
void enable_layers_editing()
Definition GUI_ObjectList.cpp:7119
bool m_prevent_list_manipulation
Definition GUI_ObjectList.hpp:190
void extruder_editing()
Definition GUI_ObjectList.cpp:1716
ColumnNumber
Definition ObjectDataViewModel.hpp:48
int em_unit(wxWindow *win)
Definition wxExtensions.cpp:424

References _u8L, Slic3r::GUI::GLCanvas3D::CanvasAssembleView, Slic3r::GUI::GLCanvas3D::CanvasPreview, Slic3r::GUI::colColorPaint, Slic3r::GUI::colEditing, Slic3r::GUI::colFilament, Slic3r::GUI::colHeight, Slic3r::GUI::colName, Slic3r::GUI::colPrint, Slic3r::GUI::colSinking, Slic3r::GUI::colSupportPaint, em_unit(), enable_layers_editing(), extruder_editing(), Slic3r::GUI::GLGizmosManager::FdmSupports, fix_through_cgal(), Slic3r::GUI::GLCanvas3D::get_canvas_type(), Slic3r::GUI::GLGizmosManager::get_current_type(), get_selected_item_indexes(), Slic3r::GUI::ObjectDataViewModelNode::HasColorPainting(), Slic3r::GUI::ObjectDataViewModelNode::HasSupportPainting(), Slic3r::GUI::itLayer, Slic3r::GUI::itPlate, m_extruder_editor, m_objects_model, m_prevent_list_manipulation, Slic3r::ModelObject::min_z(), Slic3r::GUI::GLGizmosManager::MmSegmentation, multiple_selection(), notify_instance_updated(), Slic3r::GUI::GLGizmosManager::open_gizmo(), Slic3r::GUI::plater(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::GUI::GLGizmosManager::reset_all_states(), show_context_menu(), toggle_printable_state(), Slic3r::ModelObject::translate_instances(), update_info_items(), and wxOSX.

Referenced by ObjectList(), and OnContextMenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_generic_subobject()

void Slic3r::GUI::ObjectList::load_generic_subobject ( const std::string & type_name,
const ModelVolumeType type )

Any changes of the Object's composition is duplicated for all Object's Instances So, It's enough to take a bounding box of a first selected Instance and calculate Part(generic_subobject) position

2533{
2534 // BBS: single snapshot
2535 Plater::SingleSnapshot single(wxGetApp().plater());
2536
2537 if (type == ModelVolumeType::INVALID) {
2538 load_shape_object(type_name);
2539 return;
2540 }
2541
2542 const int obj_idx = get_selected_obj_idx();
2543 if (obj_idx < 0)
2544 return;
2545
2546 const Selection& selection = scene_selection();
2547 assert(obj_idx == selection.get_object_idx());
2548
2552 int instance_idx = *selection.get_instance_idxs().begin();
2553 assert(instance_idx != -1);
2554 if (instance_idx == -1)
2555 return;
2556
2557 take_snapshot(_u8L("Add primitive"));
2558
2559 // Selected object
2560 ModelObject &model_object = *(*m_objects)[obj_idx];
2561 // Bounding box of the selected instance in world coordinate system including the translation, without modifiers.
2562 BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
2563
2564 TriangleMesh mesh = create_mesh(type_name, instance_bb);
2565
2566 // Mesh will be centered when loading.
2567 ModelVolume *new_volume = model_object.add_volume(std::move(mesh), type);
2568
2569 // First (any) GLVolume of the selected instance. They all share the same instance matrix.
2570 const GLVolume* v = selection.get_first_volume();
2571 // Transform the new modifier to be aligned with the print bed.
2572 new_volume->set_transformation(v->get_instance_transformation().get_matrix_no_offset().inverse());
2573 const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
2574 // Set the modifier position.
2575 auto offset = (type_name == "Slab") ?
2576 // Slab: Lift to print bed
2577 Vec3d(0., 0., 0.5 * mesh_bb.size().z() + instance_bb.min.z() - v->get_instance_offset().z()) :
2578 // Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
2579 Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - v->get_instance_offset();
2580 new_volume->set_offset(v->get_instance_transformation().get_matrix_no_offset().inverse() * offset);
2581
2582 // BBS: backup
2583 Slic3r::save_object_mesh(model_object);
2584
2585 const wxString name = _L("Generic") + "-" + _(type_name);
2586 new_volume->name = into_u8(name);
2587
2588 // set a default extruder value, since user can't add it manually
2589 // BBS
2590 int extruder_id = 0;
2591 if (new_volume->type() == ModelVolumeType::MODEL_PART && model_object.config.has("extruder"))
2592 extruder_id = model_object.config.opt_int("extruder");
2593 new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id));
2594 new_volume->source.is_from_builtin_objects = true;
2595
2596 select_item([this, obj_idx, new_volume]() {
2597 wxDataViewItem sel_item;
2598
2599 wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [new_volume](const ModelVolume* volume) { return volume == new_volume; });
2600 if (!items.IsEmpty())
2601 sel_item = items.front();
2602
2603 return sel_item;
2604 });
2605 if (type == ModelVolumeType::MODEL_PART)
2606 // update printable state on canvas
2607 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
2608
2609 // apply the instance transform to all volumes and reset instance transform except the offset
2611
2613
2614 //BBS: notify partplate the modify
2615 notify_instance_updated(obj_idx);
2616
2617 //BBS Switch to Objects List after add a modifier
2618 wxGetApp().params_panel()->switch_to_object(true);
2619
2620 //Show Dialog
2621 if (wxGetApp().app_config->get("do_not_show_modifer_tips").empty()) {
2622 TipsDialog dlg(wxGetApp().mainframe, _L("Add Modifier"), _L("Switch to per-object setting mode to edit modifier settings."), "do_not_show_modifer_tips");
2623 dlg.ShowModal();
2624 }
2625}
void apply_object_instance_transfrom_to_all_volumes(ModelObject *model_object, bool need_update_assemble_matrix=true)
Definition GUI_ObjectList.cpp:7147
void load_shape_object(const std::string &type_name)
Definition GUI_ObjectList.cpp:2638
static TriangleMesh create_mesh(const std::string &type_name, const BoundingBoxf3 &bb)
Definition GUI_ObjectList.cpp:2504
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
void save_object_mesh(ModelObject &object)
Definition bbs_3mf.cpp:9754

References _, _L, _u8L, Slic3r::ModelObject::add_volume(), apply_object_instance_transfrom_to_all_volumes(), Slic3r::TriangleMesh::bounding_box(), Slic3r::ModelObject::config, Slic3r::ModelVolume::config, Slic3r::GUI::create_mesh(), Slic3r::GUI::Selection::get_first_volume(), Slic3r::GUI::Selection::get_instance_idxs(), Slic3r::GLVolume::get_instance_offset(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::GUI::Selection::get_object_idx(), get_selected_obj_idx(), Slic3r::ModelConfig::has(), Slic3r::ModelObject::instance_bounding_box(), Slic3r::GUI::into_u8(), Slic3r::INVALID, Slic3r::ModelVolume::Source::is_from_builtin_objects, load_shape_object(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::ModelVolume::mesh(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::MODEL_PART, Slic3r::ModelVolume::name, notify_instance_updated(), Slic3r::offset(), Slic3r::ModelConfig::opt_int(), Slic3r::GUI::plater(), reorder_volumes_and_get_selection(), Slic3r::save_object_mesh(), Slic3r::GUI::scene_selection(), select_item(), selection_changed(), Slic3r::ModelConfig::set_key_value(), Slic3r::ModelVolume::set_offset(), Slic3r::ModelVolume::set_transformation(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::BoundingBox3Base< PointType >::size(), Slic3r::ModelVolume::source, Slic3r::GUI::take_snapshot(), and Slic3r::ModelVolume::type().

Referenced by Slic3r::GUI::Plater::_calib_pa_pattern().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_mesh_object() [1/2]

void Slic3r::GUI::ObjectList::load_mesh_object ( const std::vector< std::pair< const TriangleMesh *, wxString > > & parts,
const wxString & name,
bool center = true )
2674{
2675 // Add mesh to model as a new object
2676 Model& model = wxGetApp().plater()->model();
2677
2678#ifdef _DEBUG
2680#endif /* _DEBUG */
2681
2682 std::vector<size_t> object_idxs;
2683 BoundingBoxf3 bb;
2684 ModelObject* new_object = model.add_object();
2685 new_object->name = into_u8(name);
2686 new_object->add_instance(); // each object should have at least one instance
2687
2688 // add_volume() centres each part on its own geometry, so the part offsets carry the
2689 // meshes' placement relative to each other.
2690 for (const auto& [mesh, part_name] : parts) {
2691 bb.merge(mesh->bounding_box());
2692 ModelVolume* new_volume = new_object->add_volume(*mesh);
2693 new_volume->name = into_u8(part_name);
2694 }
2695 new_object->sort_volumes(true);
2696 // set a default extruder value, since user can't add it manually
2697 // BBS
2698 new_object->config.set_key_value("extruder", new ConfigOptionInt(1));
2699 new_object->invalidate_bounding_box();
2700 new_object->translate(-bb.center());
2701
2702 // BBS: backup
2703 Slic3r::save_object_mesh(*new_object);
2704
2705 // BBS: find an empty cell to put the copied object
2706 auto start_point = wxGetApp().plater()->build_volume().bed_center();
2707 auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
2708
2709 new_object->instances[0]->set_offset(center ? to_3d(Vec2d(empty_cell(0), empty_cell(1)), -new_object->origin_translation.z()) : bb.center());
2710
2711 new_object->ensure_on_bed();
2712
2713 //BBS init assmeble transformation
2714 Geometry::Transformation t = new_object->instances[0]->get_transformation();
2715 new_object->instances[0]->set_assemble_transformation(t);
2716
2717 object_idxs.push_back(model.objects.size() - 1);
2718#ifdef _DEBUG
2720#endif /* _DEBUG */
2721
2722 paste_objects_into_list(object_idxs);
2723
2724#ifdef _DEBUG
2726#endif /* _DEBUG */
2727}
void paste_objects_into_list(const std::vector< size_t > &object_idxs)
Definition GUI_ObjectList.cpp:1484
void check_model_ids_validity(const Model &model)
Definition Model.cpp:4375
Eigen::Matrix< typename Derived::Scalar, 3, 1, Eigen::DontAlign > to_3d(const Eigen::MatrixBase< Derived > &pt, const typename Derived::Scalar z)
Definition Point.hpp:153
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67

References Slic3r::ModelObject::add_instance(), Slic3r::Model::add_object(), Slic3r::ModelObject::add_volume(), Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::center(), Slic3r::check_model_ids_validity(), Slic3r::ModelObject::config, Slic3r::ModelObject::ensure_on_bed(), Slic3r::ModelObject::instances, Slic3r::GUI::into_u8(), Slic3r::ModelObject::invalidate_bounding_box(), Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::ModelObject::name, Slic3r::ModelVolume::name, Slic3r::Model::objects, Slic3r::ModelObject::origin_translation, paste_objects_into_list(), Slic3r::save_object_mesh(), Slic3r::ModelConfig::set_key_value(), Slic3r::ModelObject::sort_volumes(), Slic3r::to_3d(), and Slic3r::ModelObject::translate().

Here is the call graph for this function:

◆ load_mesh_object() [2/2]

void Slic3r::GUI::ObjectList::load_mesh_object ( const TriangleMesh & mesh,
const wxString & name,
bool center = true )
2669{
2670 load_mesh_object(std::vector<std::pair<const TriangleMesh*, wxString>>{{&mesh, name}}, name, center);
2671}
void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center=true)
Definition GUI_ObjectList.cpp:2668

References Slic3r::center(), and load_mesh_object().

Referenced by load_mesh_object(), and load_shape_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_modifier()

void Slic3r::GUI::ObjectList::load_modifier ( const wxArrayString & input_files,
ModelObject & model_object,
std::vector< ModelVolume * > & added_volumes,
ModelVolumeType type,
bool from_galery = false )

Any changes of the Object's composition is duplicated for all Object's Instances So, It's enough to take a bounding box of a first selected Instance and calculate Part(generic_subobject) position

2363{
2364 // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
2365 //if (type == ModelVolumeType::MODEL_PART)
2366 // return;
2367
2368 wxWindow* parent = wxGetApp().tab_panel()->GetPage(0);
2369
2370 ProgressDialog dlg(_L("Loading") + dots, "", 100, wxGetApp().mainframe, wxPD_AUTO_HIDE);
2371
2372 wxBusyCursor busy;
2373
2374 const int obj_idx = get_selected_obj_idx();
2375 if (obj_idx < 0)
2376 return;
2377
2378 const Selection& selection = scene_selection();
2379 assert(obj_idx == selection.get_object_idx());
2380
2384 int instance_idx = *selection.get_instance_idxs().begin();
2385 assert(instance_idx != -1);
2386 if (instance_idx == -1)
2387 return;
2388
2389 // Bounding box of the selected instance in world coordinate system including the translation, without modifiers.
2390 const BoundingBoxf3 instance_bb = model_object.instance_bounding_box(instance_idx);
2391
2392 // First (any) GLVolume of the selected instance. They all share the same instance matrix.
2393 const GLVolume* v = selection.get_first_volume();
2394 const Geometry::Transformation inst_transform = v->get_instance_transformation();
2395 const Transform3d inv_inst_transform = inst_transform.get_matrix_no_offset().inverse();
2396 const Vec3d instance_offset = v->get_instance_offset();
2397
2398 for (size_t i = 0; i < input_files.size(); ++i) {
2399 const std::string input_file = input_files.Item(i).ToUTF8().data();
2400
2401 dlg.Update(static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size())),
2402 _L("Loading file") + ": " + from_path(boost::filesystem::path(input_file).filename()));
2403 dlg.Fit();
2404
2405 bool is_user_cancel = false;
2406 Model model;
2407 try {
2408 if (boost::iends_with(input_file, ".stp") ||
2409 boost::iends_with(input_file, ".step")) {
2410 double linear = string_to_double_decimal_point(wxGetApp().app_config->get("linear_deflection"));
2411 if (linear <= 0) linear = 0.003;
2412 double angle = string_to_double_decimal_point(wxGetApp().app_config->get("angle_deflection"));
2413 if (angle <= 0) angle = 0.5;
2414 bool split_compound = wxGetApp().app_config->get_bool("is_split_compound");
2415 model = Model::read_from_step(
2416 input_file, LoadStrategy::LoadModel, nullptr, nullptr,
2417 [&is_user_cancel, &linear, &angle, &split_compound](Slic3r::Step& file, double& linear_value,
2418 double& angle_value, bool& is_split) -> int {
2419 if (wxGetApp().app_config->get_bool("enable_step_mesh_setting")) {
2420 StepMeshDialog mesh_dlg(nullptr, file, linear, angle);
2421 if (mesh_dlg.ShowModal() == wxID_OK) {
2422 linear_value = mesh_dlg.get_linear_deflection();
2423 angle_value = mesh_dlg.get_angle_deflection();
2424 is_split = mesh_dlg.get_split_compound_value();
2425 return 1;
2426 }
2427 } else {
2428 linear_value = linear;
2429 angle_value = angle;
2430 is_split = split_compound;
2431 return 1;
2432 }
2433 is_user_cancel = true;
2434 return -1;
2435 },
2436 linear, angle, split_compound);
2437 } else {
2438 model = Model::read_from_file(input_file, nullptr, nullptr, LoadStrategy::LoadModel);
2439 }
2440 }
2441 catch (std::exception&) {
2442 if (!is_user_cancel) {
2443 // auto msg = _L("Error!") + " " + input_file + " : " + e.what() + ".";
2444 auto msg = _L("Error!") + " " + _L("Failed to get the model data in the current file.");
2445 show_error(parent, msg);
2446 }
2447 return;
2448 }
2449
2450 if (from_galery)
2451 model.center_instances_around_point(Vec2d::Zero());
2452 else {
2453 for (auto object : model.objects) {
2454 if (model_object.origin_translation != Vec3d::Zero()) {
2455 object->center_around_origin();
2456 const Vec3d delta = model_object.origin_translation - object->origin_translation;
2457 for (auto volume : object->volumes) {
2458 volume->translate(delta);
2459 }
2460 }
2461 }
2462 }
2463
2464 model.add_default_instances();
2465 TriangleMesh mesh = model.mesh();
2466 // Mesh will be centered when loading.
2467 ModelVolume* new_volume = model_object.add_volume(std::move(mesh), type);
2468 new_volume->name = boost::filesystem::path(input_file).filename().string();
2469
2470 // adjust offset as prusaslicer ObjectList::load_from_files does (works) instead of BBS method
2472 //TriangleMesh object_mesh = model_object.volumes[0]->mesh();
2473 //new_volume->set_offset(new_volume->mesh().get_init_shift() - object_mesh.get_init_shift());
2474
2475 // set a default extruder value, since user can't add it manually
2476 // BBS
2477 int extruder_id = 0;
2478 if (new_volume->type() == ModelVolumeType::MODEL_PART && model_object.config.has("extruder"))
2479 extruder_id = model_object.config.opt_int("extruder");
2480 new_volume->config.set_key_value("extruder", new ConfigOptionInt(extruder_id));
2481 // update source data
2482 new_volume->source.input_file = input_file;
2483 new_volume->source.object_idx = obj_idx;
2484 new_volume->source.volume_idx = int(model_object.volumes.size()) - 1;
2485 if (model.objects.size() == 1 && model.objects.front()->volumes.size() == 1)
2486 new_volume->source.mesh_offset = model.objects.front()->volumes.front()->source.mesh_offset;
2487
2488 if (from_galery) {
2489 // Transform the new modifier to be aligned with the print bed.
2490 const BoundingBoxf3 mesh_bb = new_volume->mesh().bounding_box();
2491 new_volume->set_transformation(Geometry::Transformation::volume_to_bed_transformation(inst_transform, mesh_bb));
2492 // Set the modifier position.
2493 // Translate the new modifier to be pickable: move to the left front corner of the instance's bounding box, lift to print bed.
2494 const Vec3d offset = Vec3d(instance_bb.max.x(), instance_bb.min.y(), instance_bb.min.z()) + 0.5 * mesh_bb.size() - instance_offset;
2495 new_volume->set_offset(inv_inst_transform * offset);
2496 }
2497 else
2498 new_volume->set_offset(new_volume->source.mesh_offset - model_object.volumes.front()->source.mesh_offset);
2499
2500 added_volumes.push_back(new_volume);
2501 }
2502}
static Transformation volume_to_bed_transformation(const Transformation &instance_transformation, const BoundingBoxf3 &bbox)
Definition Geometry.cpp:675
static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config=nullptr, ConfigSubstitutionContext *config_substitutions=nullptr, LoadStrategy options=LoadStrategy::AddDefaultInstances, PlateDataPtrs *plate_data=nullptr, std::vector< Preset * > *project_presets=nullptr, bool *is_xxx=nullptr, Semver *file_version=nullptr, Import3mfProgressFn proFn=nullptr, ImportstlProgressFn stlFn=nullptr, BBLProject *project=nullptr, int plate_id=0)
Definition Model.cpp:318
static Model read_from_step(const std::string &input_file, LoadStrategy options, ImportStepProgressFn stepFn, StepIsUtf8Fn stepIsUtf8Fn, std::function< int(Slic3r::Step &, double &, double &, bool &)> step_mesh_fn, double linear_deflection, double angle_deflection, bool is_split_compound)
Definition Model.cpp:240
wxString from_path(const boost::filesystem::path &path)
Definition GUI.cpp:555
static wxString dots("...", wxConvUTF8)
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
@ LoadModel
Definition bbs_3mf.hpp:222
double string_to_double_decimal_point(const std::string_view str, size_t *pos)
Definition LocalesUtils.cpp:86

References _L, Slic3r::Model::add_default_instances(), Slic3r::ModelObject::add_volume(), Slic3r::angle(), Slic3r::TriangleMesh::bounding_box(), Slic3r::Model::center_instances_around_point(), Slic3r::ModelObject::config, Slic3r::ModelVolume::config, Slic3r::GUI::dots(), Slic3r::GUI::from_path(), StepMeshDialog::get_angle_deflection(), Slic3r::GUI::Selection::get_first_volume(), Slic3r::GUI::Selection::get_instance_idxs(), Slic3r::GLVolume::get_instance_offset(), Slic3r::GLVolume::get_instance_transformation(), StepMeshDialog::get_linear_deflection(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::GUI::Selection::get_object_idx(), get_selected_obj_idx(), StepMeshDialog::get_split_compound_value(), Slic3r::ModelConfig::has(), Slic3r::ModelVolume::Source::input_file, Slic3r::ModelObject::instance_bounding_box(), Slic3r::LoadModel, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::Model::mesh(), Slic3r::ModelVolume::mesh(), Slic3r::ModelVolume::Source::mesh_offset, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::MODEL_PART, Slic3r::ModelVolume::name, object(), Slic3r::ModelVolume::Source::object_idx, Slic3r::Model::objects, Slic3r::offset(), Slic3r::ModelConfig::opt_int(), Slic3r::ModelObject::origin_translation, Slic3r::Model::read_from_file(), Slic3r::Model::read_from_step(), Slic3r::GUI::scene_selection(), Slic3r::ModelConfig::set_key_value(), Slic3r::ModelVolume::set_offset(), Slic3r::ModelVolume::set_transformation(), Slic3r::GUI::show_error(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::BoundingBox3Base< PointType >::size(), Slic3r::ModelVolume::source, Slic3r::string_to_double_decimal_point(), Slic3r::ModelVolume::type(), Slic3r::GUI::ProgressDialog::Update(), Slic3r::ModelVolume::Source::volume_idx, Slic3r::Geometry::Transformation::volume_to_bed_transformation(), and Slic3r::ModelObject::volumes.

Referenced by load_subobject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_shape_object()

void Slic3r::GUI::ObjectList::load_shape_object ( const std::string & type_name)
2639{
2640 const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
2641 //assert(selection.get_object_idx() == -1); // Add nothing is something is selected on 3DScene
2642 if (selection.get_object_idx() != -1)
2643 return;
2644
2645 const int obj_idx = m_objects->size();
2646 if (obj_idx < 0)
2647 return;
2648
2649 Plater::TakeSnapshot snapshot(wxGetApp().plater(), _u8L("Add Primitive"));
2650
2651 // Create mesh
2652 BoundingBoxf3 bb;
2653 TriangleMesh mesh = create_mesh(type_name, bb);
2654 // Rotate the largest overhang area toward the part cooling fan so new shapes start in a
2655 // cooling friendly orientation. Skip the plain cube: the pressure advance pattern
2656 // calibration reuses it as an axis-aligned anchor and scales it by its bounding box,
2657 // so its orientation must stay fixed.
2658 const Slic3r::DynamicPrintConfig& full_config = wxGetApp().preset_bundle->full_config();
2659 if (type_name != "Cube" && full_config.has("fan_direction") && full_config.has("auxiliary_fan")) {
2660 FanDirection config_dir = full_config.option<ConfigOptionEnum<FanDirection>>("fan_direction")->value;
2661 orientation::orient_for_cooling(mesh, config_dir);
2662 }
2663 // BBS: remove "Shape" prefix
2664 load_mesh_object(mesh, _(type_name));
2665 wxGetApp().mainframe->update_title();
2666}
ConfigOption * option(const t_config_option_key &opt_key, bool create=false)
Definition Config.hpp:2768
bool has(const t_config_option_key &opt_key) const
Definition Config.hpp:2697
void orient_for_cooling(TriangleMesh &mesh, const FanDirection &fan_dir)
Definition Orient.cpp:650
FanDirection
Definition PrintConfig.hpp:531

References _, _u8L, Slic3r::GUI::create_mesh(), Slic3r::GUI::Selection::get_object_idx(), Slic3r::ConfigOptionResolver::has(), load_mesh_object(), m_objects, Slic3r::ConfigBase::option(), Slic3r::orientation::orient_for_cooling(), and Slic3r::GUI::plater().

Referenced by load_generic_subobject().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ load_subobject()

void Slic3r::GUI::ObjectList::load_subobject ( ModelVolumeType type,
bool from_galery = false )
2245{
2246 wxDataViewItem item = GetSelection();
2247 // we can add volumes for Object or Instance
2248 if (!item || !(m_objects_model->GetItemType(item)&(itObject|itInstance)))
2249 return;
2250 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
2251
2252 if (obj_idx < 0) return;
2253
2254 // Get object item, if Instance is selected
2255 if (m_objects_model->GetItemType(item)&itInstance)
2256 item = m_objects_model->GetItemById(obj_idx);
2257
2258 wxArrayString input_files;
2259 /*if (from_galery) {
2260 GalleryDialog dlg(this);
2261 if (dlg.ShowModal() != wxID_CLOSE)
2262 dlg.get_input_files(input_files);
2263 }
2264 else*/
2265 wxGetApp().import_model(wxGetApp().tab_panel()->GetPage(0), input_files);
2266
2267 if (input_files.IsEmpty())
2268 return;
2269
2270 take_snapshot((type == ModelVolumeType::MODEL_PART) ? _u8L("Load Part") : _u8L("Load Modifier"));
2271
2272 std::vector<ModelVolume*> volumes;
2273 // ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
2274 /*
2275 if (type == ModelVolumeType::MODEL_PART)
2276 load_part(*(*m_objects)[obj_idx], volumes, type, from_galery);
2277 else*/
2278 load_modifier(input_files, *(*m_objects)[obj_idx], volumes, type, from_galery);
2279
2280 if (volumes.empty())
2281 return;
2282
2283 wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [volumes](const ModelVolume* volume) {
2284 return std::find(volumes.begin(), volumes.end(), volume) != volumes.end(); });
2285
2286 if (type == ModelVolumeType::MODEL_PART)
2287 // update printable state on canvas
2288 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
2289
2290 if (items.size() > 1) {
2292 m_last_selected_item = wxDataViewItem(nullptr);
2293 }
2294 select_items(items);
2295
2297
2298 //BBS: notify partplate the modify
2299 notify_instance_updated(obj_idx);
2300}
void select_items(const wxDataViewItemArray &sels)
Definition GUI_ObjectList.cpp:5347
void load_modifier(const wxArrayString &input_files, ModelObject &model_object, std::vector< ModelVolume * > &added_volumes, ModelVolumeType type, bool from_galery=false)
Definition GUI_ObjectList.cpp:2362

References _u8L, Slic3r::GUI::itInstance, Slic3r::GUI::itObject, load_modifier(), m_last_selected_item, m_objects, m_objects_model, m_selection_mode, Slic3r::MODEL_PART, notify_instance_updated(), reorder_volumes_and_get_selection(), select_items(), selection_changed(), smVolume, and Slic3r::GUI::take_snapshot().

Here is the call graph for this function:

◆ merge()

void Slic3r::GUI::ObjectList::merge ( bool to_multipart_object)
3051{
3052 wxBusyCursor wait;
3053 // merge selected objects to the multipart object
3054 if (to_multipart_object) {
3055 auto get_object_idxs = [this](std::vector<int>& obj_idxs, wxDataViewItemArray& sels)
3056 {
3057 // check selections and split instances to the separated objects...
3058 bool instance_selection = false;
3059 for (wxDataViewItem item : sels)
3060 if (m_objects_model->GetItemType(item) & itInstance) {
3061 instance_selection = true;
3062 break;
3063 }
3064
3065 if (!instance_selection) {
3066 for (wxDataViewItem item : sels) {
3067 assert(m_objects_model->GetItemType(item) & itObject);
3068 obj_idxs.emplace_back(m_objects_model->GetIdByItem(item));
3069 }
3070 return;
3071 }
3072
3073 // map of obj_idx -> set of selected instance_idxs
3074 std::map<int, std::set<int>> sel_map;
3075 std::set<int> empty_set;
3076 for (wxDataViewItem item : sels) {
3077 if (m_objects_model->GetItemType(item) & itObject) {
3078 int obj_idx = m_objects_model->GetIdByItem(item);
3079 int inst_cnt = (*m_objects)[obj_idx]->instances.size();
3080 if (inst_cnt == 1)
3081 sel_map.emplace(obj_idx, empty_set);
3082 else
3083 for (int i = 0; i < inst_cnt; i++)
3084 sel_map[obj_idx].emplace(i);
3085 continue;
3086 }
3087 int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetObject(item));
3088 sel_map[obj_idx].emplace(m_objects_model->GetInstanceIdByItem(item));
3089 }
3090
3091 // all objects, created from the instances will be added to the end of list
3092 int new_objects_cnt = 0; // count of this new objects
3093
3094 for (auto map_item : sel_map) {
3095 int obj_idx = map_item.first;
3096 // object with just 1 instance
3097 if (map_item.second.empty()) {
3098 obj_idxs.emplace_back(obj_idx);
3099 continue;
3100 }
3101
3102 // object with selected all instances
3103 if ((*m_objects)[map_item.first]->instances.size() == map_item.second.size()) {
3105 // first instance stay on its own place and another all add to the end of list :
3106 obj_idxs.emplace_back(obj_idx);
3107 new_objects_cnt += map_item.second.size() - 1;
3108 continue;
3109 }
3110
3111 // object with selected some of instances
3112 instances_to_separated_object(obj_idx, map_item.second);
3113
3114 if (map_item.second.size() == 1)
3115 new_objects_cnt += 1;
3116 else {// we should split to separate instances last object
3118 // all instances will stay at the end of list :
3119 new_objects_cnt += map_item.second.size();
3120 }
3121 }
3122
3123 // all instatnces are extracted to the separate objects and should be selected
3124 m_prevent_list_events = true;
3125 sels.Clear();
3126 for (int obj_idx : obj_idxs)
3127 sels.Add(m_objects_model->GetItemById(obj_idx));
3128 int obj_cnt = m_objects->size();
3129 for (int obj_idx = obj_cnt - new_objects_cnt; obj_idx < obj_cnt; obj_idx++) {
3130 sels.Add(m_objects_model->GetItemById(obj_idx));
3131 obj_idxs.emplace_back(obj_idx);
3132 }
3133 UnselectAll();
3134 SetSelections(sels);
3135 assert(!sels.IsEmpty());
3136 m_prevent_list_events = false;
3137 };
3138
3139 std::vector<int> obj_idxs;
3140 wxDataViewItemArray sels;
3141 GetSelections(sels);
3142 assert(!sels.IsEmpty());
3143
3144 Plater::TakeSnapshot snapshot(wxGetApp().plater(), _u8L("Assemble"));
3145
3146 get_object_idxs(obj_idxs, sels);
3147
3148 // resulted objects merge to the one
3149 Model* model = (*m_objects)[0]->get_model();
3150 ModelObject* new_object = model->add_object();
3151 new_object->name = _u8L("Assembly");
3152 ModelConfig &config = new_object->config;
3153
3154 Slic3r::SaveObjectGaurd gaurd(*new_object);
3155
3156 for (int obj_idx : obj_idxs) {
3157 ModelObject* object = (*m_objects)[obj_idx];
3158
3159 const Geometry::Transformation& transformation = object->instances[0]->get_transformation();
3160 //const Vec3d scale = transformation.get_scaling_factor();
3161 //const Vec3d mirror = transformation.get_mirror();
3162 //const Vec3d rotation = transformation.get_rotation();
3163
3164 if (object->id() == (*m_objects)[obj_idxs.front()]->id())
3165 new_object->add_instance();
3166 const Transform3d& transformation_matrix = transformation.get_matrix();
3167
3168 // merge volumes
3169 for (const ModelVolume* volume : object->volumes) {
3170 ModelVolume* new_volume = new_object->add_volume(*volume);
3171
3172 //BBS: keep volume's transform
3173 const Transform3d& volume_matrix = new_volume->get_matrix();
3174 Transform3d new_matrix = transformation_matrix * volume_matrix;
3175 new_volume->set_transformation(new_matrix);
3176 //set rotation
3177 /*const Vec3d vol_rot = new_volume->get_rotation() + rotation;
3178 new_volume->set_rotation(vol_rot);
3179
3180 // set scale
3181 const Vec3d vol_sc_fact = new_volume->get_scaling_factor().cwiseProduct(scale);
3182 new_volume->set_scaling_factor(vol_sc_fact);
3183
3184 // set mirror
3185 const Vec3d vol_mirror = new_volume->get_mirror().cwiseProduct(mirror);
3186 new_volume->set_mirror(vol_mirror);
3187
3188 // set offset
3189 const Vec3d vol_offset = volume_offset_correction* new_volume->get_offset();
3190 new_volume->set_offset(vol_offset);*/
3191
3192 //BBS: add config from old objects
3193 //for object config, it has settings of PrintObjectConfig and PrintRegionConfig
3194 //for volume config, it only has settings of PrintRegionConfig
3195 //so we can not copy settings from object to volume
3196 //but we can copy settings from volume to object
3197 if (object->volumes.size() > 1){
3198 new_volume->config.assign_config(volume->config);
3199 }
3200 auto option = new_volume->config.option("extruder");
3201 if (!option) {
3202 auto opt = object->config.option("extruder");
3203 if (opt) { new_volume->config.set_key_value("extruder", new ConfigOptionInt(opt->getInt())); }
3204 }
3205 }
3206 new_object->sort_volumes(true);
3207
3208 // merge settings
3209 auto new_opt_keys = config.keys();
3210 const ModelConfig& from_config = object->config;
3211 auto opt_keys = from_config.keys();
3212
3213 for (auto& opt_key : opt_keys) {
3214 if (find(new_opt_keys.begin(), new_opt_keys.end(), opt_key) == new_opt_keys.end()) {
3215 const ConfigOption* option = from_config.option(opt_key);
3216 if (!option) {
3217 // if current option doesn't exist in prints.get_edited_preset(),
3218 // get it from default config values
3219 option = DynamicPrintConfig::new_from_defaults_keys({ opt_key })->option(opt_key);
3220 }
3221 config.set_key_value(opt_key, option->clone());
3222 }
3223 }
3224 // save extruder value if it was set
3225 if (object->volumes.size() == 1 && find(opt_keys.begin(), opt_keys.end(), "extruder") != opt_keys.end()) {
3226 ModelVolume* volume = new_object->volumes.back();
3227 const ConfigOption* option = from_config.option("extruder");
3228 if (option)
3229 volume->config.set_key_value("extruder", option->clone());
3230 }
3231
3232 // merge printable and auto_drop values
3233 // non-default have priority -> if one object has printable == false,
3234 // then merged object will also have printable == false
3235 if (object->instances[0]->printable == false) {
3236 new_object->printable = false;
3237 new_object->instances[0]->printable = false;
3238 }
3239 if (object->auto_drop == false) {
3240 new_object->auto_drop = false;
3241 }
3242
3243 // merge layers
3244 for (const auto& range : object->layer_config_ranges)
3245 new_object->layer_config_ranges.emplace(range);
3246
3247 // merge brim ears
3248 BrimPoints temp_brim_points = object->brim_points;
3249 for(auto& p : temp_brim_points) {
3250 p.set_transform(transformation_matrix);
3251 new_object->brim_points.push_back(p);
3252 }
3253 }
3254
3255 //BBS: ensure on bed, and no need to center around origin
3256 new_object->ensure_on_bed();
3257 new_object->center_around_origin();
3258 new_object->translate_instances(-new_object->origin_translation);
3259 new_object->origin_translation = Vec3d::Zero();
3260 //BBS init asssmble transformation
3261 Geometry::Transformation new_object_trsf = new_object->instances[0]->get_transformation();
3262 new_object->instances[0]->set_assemble_transformation(new_object_trsf);
3263
3264 const Transform3d& new_object_inverse_matrix = new_object_trsf.get_matrix().inverse();
3265 for (auto& p : new_object->brim_points) {
3266 p.set_transform(new_object_inverse_matrix);
3267 }
3268 //BBS: notify it before remove
3270
3271 // remove selected objects
3272 remove();
3273
3274 // Add new object(merged) to the object_list
3275 add_object_to_list(m_objects->size() - 1);
3276 if (new_object->printable == false) {
3277 wxGetApp().obj_list()->printable_state_changed({new_object});
3278 }
3279 select_item(m_objects_model->GetItemById(m_objects->size() - 1));
3281 }
3282 // merge all parts to the one single object
3283 // all part's settings will be lost
3284 else {
3285 wxDataViewItem item = GetSelection();
3286 if (!item)
3287 return;
3288 const int obj_idx = m_objects_model->GetIdByItem(item);
3289 if (obj_idx == -1)
3290 return;
3291
3292 Plater::TakeSnapshot snapshot(wxGetApp().plater(), _u8L("Merge parts to an object"));
3293
3294 ModelObject* model_object = (*m_objects)[obj_idx];
3295 model_object->merge();
3296
3297 m_objects_model->DeleteVolumeChildren(item);
3298
3299 changed_object(obj_idx);
3300 }
3301}
void instances_to_separated_object(const int obj_idx, const std::set< int > &inst_idx)
Definition GUI_ObjectList.cpp:6190
std::vector< BrimPoint > BrimPoints
Definition BrimEarsPoint.hpp:66

References _u8L, Slic3r::ModelObject::add_instance(), Slic3r::Model::add_object(), add_object_to_list(), Slic3r::ModelObject::add_volume(), Slic3r::ModelConfig::assign_config(), Slic3r::ModelObject::auto_drop, Slic3r::ModelObject::brim_points, Slic3r::ModelObject::center_around_origin(), changed_object(), Slic3r::ConfigOption::clone(), config(), Slic3r::ModelObject::config, Slic3r::ModelVolume::config, Slic3r::ModelObject::ensure_on_bed(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::ModelVolume::get_matrix(), Slic3r::ModelObject::instances, instances_to_separated_object(), instances_to_separated_objects(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::ModelConfig::keys(), Slic3r::ModelObject::layer_config_ranges, m_objects, m_objects_model, m_prevent_list_events, Slic3r::ModelObject::merge(), Slic3r::ModelObject::name, Slic3r::DynamicPrintConfig::new_from_defaults_keys(), notify_instance_updated(), object(), Slic3r::ModelConfig::option(), Slic3r::ModelObject::origin_translation, Slic3r::GUI::plater(), Slic3r::ModelObject::printable, Slic3r::range(), remove(), select_item(), Slic3r::ModelConfig::set_key_value(), Slic3r::ModelVolume::set_transformation(), Slic3r::ModelObject::sort_volumes(), Slic3r::ModelObject::translate_instances(), update_selections_on_canvas(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ msw_rescale()

void Slic3r::GUI::ObjectList::msw_rescale ( )
6581{
6583
6584 const int em = wxGetApp().em_unit();
6585
6586 for (int cn = colName; cn < colCount; cn++)
6587 GetColumn(cn)->SetWidth(m_columns_width[cn] * em);
6588
6589 // Keep the explicit row height (see create_objects_ctrl) in sync with the
6590 // rescaled em so the filament colour badge keeps fitting after a DPI or theme
6591 // change.
6592 SetRowHeight(2 * em + FromDIP(2));
6593
6594 // rescale/update existing items with bitmaps
6595 m_objects_model->Rescale();
6596
6597 Layout();
6598}
void set_min_height()
Definition GUI_ObjectList.cpp:367

References Slic3r::GUI::colCount, Slic3r::GUI::colName, m_columns_width, m_objects_model, and set_min_height().

Referenced by sys_color_changed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ multiple_selection()

bool Slic3r::GUI::ObjectList::multiple_selection ( ) const
4887{
4888 return GetSelectedItemsCount() > 1;
4889}

Referenced by list_manipulation(), OnBeginDrag(), part_selection_changed(), show_context_menu(), and Slic3r::GUI::ObjectLayers::update_layers_list().

Here is the caller graph for this function:

◆ notify_instance_updated()

void Slic3r::GUI::ObjectList::notify_instance_updated ( int obj_idx)
6971{
6972 const int inst_cnt = (*m_objects)[obj_idx]->instances.size();
6973 PartPlateList& list = wxGetApp().plater()->get_partplate_list();
6974 for (int index = 0; index < inst_cnt; index ++)
6975 list.notify_instance_update(obj_idx, index);
6976}

References Slic3r::GUI::PartPlateList::notify_instance_update().

Referenced by boolean(), del_subobject_from_object(), list_manipulation(), load_generic_subobject(), load_subobject(), merge(), OnEditingStarted(), paste_volumes_into_list(), and split().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ object()

ModelObject * Slic3r::GUI::ObjectList::object ( const int obj_idx) const

◆ object_config_options_changed()

void Slic3r::GUI::ObjectList::object_config_options_changed ( const ObjectVolumeID & ov_id)
955{
956 if (ov_id.object == nullptr)
957 return;
958
959 ModelObjectPtrs& objects = wxGetApp().model().objects;
960 ModelObject* mo = ov_id.object;
961 ModelVolume* mv = ov_id.volume;
962
963 wxDataViewItem obj_item = m_objects_model->GetObjectItem(mo);
964 if (mv != nullptr) {
965 size_t vol_idx;
966 for (vol_idx = 0; vol_idx < mo->volumes.size(); vol_idx++) {
967 if (mo->volumes[vol_idx] == mv)
968 break;
969 }
970 assert(vol_idx < mo->volumes.size());
971
972 SettingsFactory::Bundle cat_options = SettingsFactory::get_bundle(&mv->config.get(), false);
973 wxDataViewItem vol_item = m_objects_model->GetVolumeItem(obj_item, vol_idx);
974 if (cat_options.size() > 0) {
975 add_settings_item(vol_item, &mv->config.get());
976 }
977 else {
978 m_objects_model->DeleteSettings(vol_item);
979 }
980 }
981 else {
982 SettingsFactory::Bundle cat_options = SettingsFactory::get_bundle(&mo->config.get(), true);
983 if (cat_options.size() > 0) {
984 add_settings_item(obj_item, &mo->config.get());
985 }
986 else {
987 m_objects_model->DeleteSettings(obj_item);
988 }
989 }
990}
std::vector< ModelObject * > * objects() const
Definition GUI_ObjectList.hpp:235
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13

References add_settings_item(), Slic3r::ModelObject::config, Slic3r::ModelVolume::config, Slic3r::ModelConfig::get(), Slic3r::GUI::SettingsFactory::get_bundle(), m_objects_model, Slic3r::GUI::ObjectVolumeID::object, objects(), Slic3r::GUI::ObjectVolumeID::volume, and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ objects()

std::vector< ModelObject * > * Slic3r::GUI::ObjectList::objects ( ) const
inline
235{ return m_objects; }

References m_objects.

Referenced by object_config_options_changed(), select_items(), and anonymous_namespace{EmbossJob.cpp}::update_name_in_list().

Here is the caller graph for this function:

◆ on_plate_added()

void Slic3r::GUI::ObjectList::on_plate_added ( PartPlate * part_plate)
6902{
6903 wxDataViewItem plate_item = m_objects_model->AddPlate(part_plate);
6904}

References m_objects_model.

◆ on_plate_deleted()

void Slic3r::GUI::ObjectList::on_plate_deleted ( int plate_index)
6907{
6908 m_objects_model->DeletePlate(plate_idx);
6909
6910 wxDataViewItemArray top_list;
6911 m_objects_model->GetChildren(wxDataViewItem(nullptr), top_list);
6912 for (wxDataViewItem item : top_list) {
6913 Expand(item);
6914 }
6915}

References m_objects_model.

◆ on_plate_selected()

void Slic3r::GUI::ObjectList::on_plate_selected ( int plate_index)
6958{
6959 wxDataViewItem item = m_objects_model->GetItemByPlateId(plate_index);
6960 wxDataViewItem sel = GetSelection();
6961
6962 if (sel == item)
6963 return;
6964
6965 UnselectAll();
6966 Select(item);
6967}

References m_objects_model.

Referenced by select_items().

Here is the caller graph for this function:

◆ OnBeginDrag()

void Slic3r::GUI::ObjectList::OnBeginDrag ( wxDataViewEvent & event)
private
1897{
1898 const bool mult_sel = multiple_selection();
1899 if (mult_sel) {
1900 event.Veto();
1901 return;
1902 }
1903
1904 const wxDataViewItem item(event.GetItem());
1905 const ItemType& type = m_objects_model->GetItemType(item);
1906 if (!(type & (itVolume | itObject))) {
1907 event.Veto();
1908 return;
1909 }
1910
1911 if (type & itObject) {
1912 m_dragged_data.init(m_objects_model->GetIdByItem(item), type);
1913 }
1914 else if (type & itVolume){
1915 m_dragged_data.init(m_objects_model->GetObjectIdByItem(item), m_objects_model->GetVolumeIdByItem(item), type);
1916 }
1917#if 0
1918 if ((mult_sel && !selected_instances_of_same_object()) ||
1919 (!mult_sel && (GetSelection() != item)) ) {
1920 event.Veto();
1921 return;
1922 }
1923
1924 if (!(type & (itVolume | itObject | itInstance))) {
1925 event.Veto();
1926 return;
1927 }
1928
1929 if (mult_sel)
1930 {
1931 m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),type);
1932 std::set<int>& sub_obj_idxs = m_dragged_data.inst_idxs();
1933 wxDataViewItemArray sels;
1934 GetSelections(sels);
1935 for (auto sel : sels )
1936 sub_obj_idxs.insert(m_objects_model->GetInstanceIdByItem(sel));
1937 }
1938 else if (type & itObject)
1939 m_dragged_data.init(m_objects_model->GetIdByItem(item), type);
1940 else
1941 m_dragged_data.init(m_objects_model->GetObjectIdByItem(item),
1942 type&itVolume ? m_objects_model->GetVolumeIdByItem(item) :
1943 m_objects_model->GetInstanceIdByItem(item),
1944 type);
1945#endif
1946
1947 /* Under MSW or OSX, DnD moves an item to the place of another selected item
1948 * But under GTK, DnD moves an item between another two items.
1949 * And as a result - call EVT_CHANGE_SELECTION to unselect all items.
1950 * To prevent such behavior use m_prevent_list_events
1951 **/
1952 m_prevent_list_events = true;//it's needed for GTK
1953
1954 /* Under GTK, DnD requires to the wxTextDataObject been initialized with some valid value,
1955 * so set some nonempty string
1956 */
1957 wxTextDataObject* obj = new wxTextDataObject;
1958 obj->SetText("Some text");//it's needed for GTK
1959
1960 event.SetDataObject(obj);
1961 event.SetDragFlags(wxDrag_DefaultMove); // allows both copy and move;
1962}
bool selected_instances_of_same_object()
Definition GUI_ObjectList.cpp:3559

References Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_dragged_data, m_objects_model, m_prevent_list_events, multiple_selection(), and selected_instances_of_same_object().

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnContextMenu()

void Slic3r::GUI::ObjectList::OnContextMenu ( wxDataViewEvent & event)
private
1518{
1519 // The mouse position returned by get_mouse_position_in_control() here is the one at the time the mouse button is released (mouse up event)
1520 wxPoint mouse_pos = this->get_mouse_position_in_control();
1521
1522 // Do not show the context menu if the user pressed the right mouse button on the 3D scene and released it on the objects list
1523 GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
1524 bool evt_context_menu = (canvas != nullptr) ? !canvas->is_mouse_dragging() : true;
1525 if (!evt_context_menu)
1526 canvas->mouse_up_cleanup();
1527
1528 list_manipulation(mouse_pos, evt_context_menu);
1529}

References get_mouse_position_in_control(), Slic3r::GUI::GLCanvas3D::is_mouse_dragging(), list_manipulation(), and Slic3r::GUI::GLCanvas3D::mouse_up_cleanup().

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnDrop()

void Slic3r::GUI::ObjectList::OnDrop ( wxDataViewEvent & event)
private
2050{
2051 const wxDataViewItem& item = event.GetItem();
2052
2053 int src_obj_id, src_plate, dest_obj_id, dest_plate;
2054 if (!can_drop(item, src_obj_id, src_plate, dest_obj_id, dest_plate))
2055 {
2056 event.Veto();
2057 m_dragged_data.clear();
2058 return;
2059 }
2060
2061//#if 1
2062 take_snapshot(_u8L("Object order changed"));
2063
2064 if(m_dragged_data.type() & itObject){
2065 int delta = dest_obj_id < src_obj_id ? -1 : 1;
2066 PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list();
2067 /*int cnt = 0, cur_id = src_obj_id, next_id, total = abs(src_obj_id - dest_obj_id);
2068 //for (cur_id = src_obj_id; cnt < total; id += delta, cnt++)
2069 next_id = src_obj_id + delta;
2070 while (cnt < total)
2071 {
2072 int cur_plate = partplate_list.find_instance(next_id, 0);
2073 if (cur_plate != src_plate) {
2074 cnt ++;
2075 next_id += delta;
2076 continue;
2077 }
2078 std::swap((*m_objects)[cur_id], (*m_objects)[next_id]);
2079 cur_id = next_id;
2080 cnt ++;
2081 next_id += delta;
2082 }*/
2083
2084 int cnt = 0;
2085 for (int id = src_obj_id; cnt < abs(src_obj_id - dest_obj_id); id += delta, cnt++)
2086 std::swap((*m_objects)[id], (*m_objects)[id + delta]);
2087
2088 select_item(m_objects_model->ReorganizeObjects(src_obj_id, dest_obj_id));
2089
2090 partplate_list.reload_all_objects(false, src_plate);
2091 changed_object(src_obj_id);
2092 }
2093 else if (m_dragged_data.type() & itVolume) {
2094 int from_volume_id = m_dragged_data.sub_obj_idx();
2095 int to_volume_id = m_objects_model->GetVolumeIdByItem(item);
2096 int delta = to_volume_id < from_volume_id ? -1 : 1;
2097
2098 const int obj_idx = m_dragged_data.obj_idx();
2099 // Object-indexed UI maps may be stale after another object is removed or reordered.
2100 if (obj_idx < 0 || size_t(obj_idx) >= m_objects->size()) {
2101 event.Veto();
2102 m_dragged_data.clear();
2103 return;
2104 }
2105 const ModelObject *object = (*m_objects)[obj_idx];
2106 auto &volumes = (*m_objects)[obj_idx]->volumes;
2107 std::vector<size_t> visible_volume_indices;
2108 visible_volume_indices.reserve(volumes.size());
2109 for (size_t idx = 0; idx < volumes.size(); ++idx)
2110 // Match add_volumes_to_object_in_list: only connectors of cut objects are hidden.
2111 if (!(object->is_cut() && volumes[idx]->is_cut_connector()))
2112 visible_volume_indices.push_back(idx);
2113
2114 // Validate the entire move before any swap; these checks must also protect Release builds.
2115 if (from_volume_id < 0 || to_volume_id < 0 ||
2116 size_t(from_volume_id) >= visible_volume_indices.size() || size_t(to_volume_id) >= visible_volume_indices.size()) {
2117 event.Veto();
2118 m_dragged_data.clear();
2119 return;
2120 }
2121
2122 // Move through visible slots only, keeping hidden cut connectors at their original indices.
2123 // The local mapping stays valid because no hidden volume changes slots during the move.
2124 for (int id = from_volume_id; id != to_volume_id; id += delta) {
2125 const size_t current_idx = visible_volume_indices[id];
2126 const size_t next_idx = visible_volume_indices[id + delta];
2127 std::swap(volumes[current_idx], volumes[next_idx]);
2128 }
2129
2130 // Later selection/filament handlers use this cache; repair it for the moved object too.
2131 auto &ui_to_model = m_objects_model->get_ui_and_3d_volume_map()[obj_idx];
2132 ui_to_model.clear();
2133 for (size_t idx = 0; idx < visible_volume_indices.size(); ++idx)
2134 ui_to_model[int(idx)] = int(visible_volume_indices[idx]);
2135
2136 select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, m_objects_model->GetParent(item)));
2137
2138 changed_object(m_dragged_data.obj_idx());
2139 }
2140
2141 m_dragged_data.clear();
2142
2143 wxGetApp().plater()->set_current_canvas_as_dirty();
2144}
bool can_drop(const wxDataViewItem &item, int &src_obj_id, int &src_plate, int &dest_obj_id, int &dest_plate) const
Definition GUI_ObjectList.cpp:1964

References _u8L, can_drop(), changed_object(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_dragged_data, m_objects, m_objects_model, object(), Slic3r::GUI::PartPlateList::reload_all_objects(), select_item(), Slic3r::GUI::take_snapshot(), and Slic3r::ModelObject::volumes.

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnDropPossible()

void Slic3r::GUI::ObjectList::OnDropPossible ( wxDataViewEvent & event)
private
2039{
2040 const wxDataViewItem& item = event.GetItem();
2041
2042 int src_obj_id, src_plate, dest_obj_id, dest_plate;
2043 if (!can_drop(item, src_obj_id, src_plate, dest_obj_id, dest_plate)) {
2044 event.Veto();
2045 m_prevent_list_events = false;
2046 }
2047}

References can_drop(), and m_prevent_list_events.

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnEditingDone()

void Slic3r::GUI::ObjectList::OnEditingDone ( wxDataViewEvent & event)
private
6777{
6778 if (event.GetColumn() != colName)
6779 return;
6780
6781 if (event.IsEditCancelled()) {
6782 if (m_objects_model->GetItemType(event.GetItem()) & itPlate) {
6783 int plate_idx = -1;
6784 m_objects_model->GetItemType(event.GetItem(), plate_idx);
6785 if (plate_idx >= 0) {
6786 auto plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
6787 m_objects_model->SetCurSelectedPlateFullName(plate_idx, plate->get_plate_name());
6788 }
6789 }
6790 }
6791
6792 const auto renderer = dynamic_cast<BitmapTextRenderer*>(GetColumn(colName)->GetRenderer());
6793#if __WXOSX__
6794 SetAcceleratorTable(m_accel);
6795#endif
6796
6797 if (renderer->WasCanceled())
6798 wxTheApp->CallAfter([this]{ Plater::show_illegal_characters_warning(this); });
6799
6800#ifdef __WXMSW__
6801 // Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
6802 // Here the last active column is forgotten, so when leaving the editing mode, the next mouse click will not enter the editing mode of the newly selected column.
6803 m_last_selected_column = -1;
6804#endif //__WXMSW__
6805
6806 Plater* plater = wxGetApp().plater();
6807 if (plater)
6809}
void set_current_canvas_as_dirty()
Definition Plater.cpp:22140
static void show_illegal_characters_warning(wxWindow *parent)
Definition Plater.cpp:432

References Slic3r::GUI::colName, Slic3r::GUI::itPlate, m_objects_model, Slic3r::GUI::plater(), and Slic3r::GUI::Plater::show_illegal_characters_warning().

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnEditingStarted()

void Slic3r::GUI::ObjectList::OnEditingStarted ( wxDataViewEvent & event)
private
6701{
6702#ifdef __WXMSW__
6703 m_last_selected_column = -1;
6704#else
6705 event.Veto(); // Not edit with NSTableView's text
6706 auto col = event.GetColumn();
6707 auto item = event.GetItem();
6708 if (col == colPrint) {
6710 return;
6711 } else if (col == colSupportPaint) {
6712 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
6713 if (node->HasSupportPainting()) {
6714 GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
6715 if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::FdmSupports)
6716 gizmos_mgr.open_gizmo(GLGizmosManager::EType::FdmSupports);
6717 else
6718 gizmos_mgr.reset_all_states();
6719 }
6720 return;
6721 }
6722 else if (col == colColorPaint) {
6723 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
6724 if (node->HasColorPainting()) {
6725 GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
6726 if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmSegmentation)
6727 gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmSegmentation);
6728 else
6729 gizmos_mgr.reset_all_states();
6730 }
6731 return;
6732 }
6733 else if (col == colSinking) {
6734 Plater * plater = wxGetApp().plater();
6735 GLCanvas3D *cnv = plater->canvas3D();
6736 Plater::TakeSnapshot snapshot(plater, _u8L("Shift objects to bed"));
6737 int obj_idx, vol_idx;
6738 get_selected_item_indexes(obj_idx, vol_idx, item);
6739 // Shift on request also when auto drop is off, which ensure_on_bed() skips.
6740 ModelObject* mo = (*m_objects)[obj_idx];
6741 mo->translate_instances(-mo->min_z() * Vec3d::UnitZ());
6742 cnv->reload_scene(true, true);
6743 update_info_items(obj_idx);
6744 notify_instance_updated(obj_idx);
6745 }
6746 else if (col == colEditing) {
6747 //show_context_menu(evt_context_menu);
6748 int obj_idx, vol_idx;
6749
6750 get_selected_item_indexes(obj_idx, vol_idx, item);
6751 //wxGetApp().plater()->PopupObjectTable(obj_idx, vol_idx, mouse_pos);
6752 dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab(vol_idx >= 0))->reset_model_config();
6753 return;
6754 }
6755#ifdef __WXOSX__
6756 if (col == colFilament) {
6757 start_filament_editor(item);
6758 return;
6759 }
6760#endif // __WXOSX__
6761 if (col != colFilament && col != colName)
6762 return;
6763 auto column = GetColumn(col);
6764 const auto renderer = column->GetRenderer();
6765 if (!renderer->GetEditorCtrl()) {
6766 renderer->StartEditing(item, GetItemRect(item, column));
6767 if (col == colName) // TODO: for colName editing, disable shortcuts
6768 SetAcceleratorTable(wxNullAcceleratorTable);
6769 }
6770#ifdef __WXOSX__
6771 SetCustomRendererPtr(dynamic_cast<wxDataViewCustomRenderer*>(renderer));
6772#endif
6773#endif //__WXMSW__
6774}

References _u8L, Slic3r::GUI::colColorPaint, Slic3r::GUI::colEditing, Slic3r::GUI::colFilament, Slic3r::GUI::colName, Slic3r::GUI::colPrint, Slic3r::GUI::colSinking, Slic3r::GUI::colSupportPaint, Slic3r::GUI::GLGizmosManager::FdmSupports, Slic3r::GUI::GLGizmosManager::get_current_type(), get_selected_item_indexes(), Slic3r::GUI::ObjectDataViewModelNode::HasColorPainting(), Slic3r::GUI::ObjectDataViewModelNode::HasSupportPainting(), Slic3r::ModelObject::min_z(), Slic3r::GUI::GLGizmosManager::MmSegmentation, notify_instance_updated(), Slic3r::GUI::GLGizmosManager::open_gizmo(), Slic3r::GUI::plater(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::GUI::GLGizmosManager::reset_all_states(), toggle_printable_state(), Slic3r::ModelObject::translate_instances(), and update_info_items().

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnStartEditing()

void Slic3r::GUI::GUI::ObjectList::OnStartEditing ( wxDataViewEvent & event)
private
6668{
6669 auto col = event.GetColumn();
6670 auto item = event.GetItem();
6671#ifdef __WXOSX__
6672 if (col == colFilament) {
6673 if (m_starting_filament_editor)
6674 return;
6675
6676 event.Veto();
6677 CallAfter([this, item] {
6678 if (!is_live_model_item(item))
6679 return;
6680 start_filament_editor(item);
6681 });
6682 return;
6683 }
6684#endif // __WXOSX__
6685
6686 if (col == colName) {
6687 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
6688 if (node->GetType() & itPlate) {
6689 int plate_idx = node->GetPlateIdx();
6690 if (plate_idx >= 0) {
6691 auto plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
6692 m_objects_model->SetName(from_u8(plate->get_plate_name()), GetSelection());
6693 }
6694 }
6695 }
6696}

References Slic3r::GUI::colFilament, Slic3r::GUI::colName, Slic3r::GUI::from_u8(), Slic3r::GUI::ObjectDataViewModelNode::GetPlateIdx(), Slic3r::GUI::ObjectDataViewModelNode::GetType(), Slic3r::GUI::itPlate, and m_objects_model.

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ part_selection_changed()

void Slic3r::GUI::ObjectList::part_selection_changed ( )
3722{
3723 if (wxGetApp().is_closing())
3724 return;
3725
3727 int obj_idx = -1;
3728 int volume_id = -1;
3729 m_config = nullptr;
3730 wxString og_name = wxEmptyString;
3731
3732 bool update_and_show_manipulations = false;
3733 bool update_and_show_settings = false;
3734 bool update_and_show_layers = false;
3735
3736 bool enable_manipulation{true};
3737 bool disable_ss_manipulation{false};
3738 bool disable_ununiform_scale{false};
3739
3740 const auto item = GetSelection();
3741 if (item && m_objects_model->GetItemType(item) == itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) {
3742 og_name = _L("Cut Connectors information");
3743
3744 update_and_show_manipulations = true;
3745 enable_manipulation = false;
3746 disable_ununiform_scale = true;
3747 }
3748 else if (item && (m_objects_model->GetItemType(item) & itPlate)) {
3749 // BBS
3750 // TODO: og for plate
3751 }
3752 else if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot )) {
3753 const Selection& selection = scene_selection();
3754
3755 if (selection.is_single_full_object()) {
3756 og_name = _L("Object manipulation");
3757 update_and_show_manipulations = true;
3758
3759 obj_idx = selection.get_object_idx();
3760 ModelObject *object = (*m_objects)[obj_idx];
3761 m_config = &object->config;
3762 disable_ss_manipulation = object->is_cut();
3763 }
3764 else {
3765 og_name = _L("Group manipulation");
3766
3767 // don't show manipulation panel for case of all Object's parts selection
3768 update_and_show_manipulations = !selection.is_single_full_instance();
3769
3770 if (int obj_idx = selection.get_object_idx(); obj_idx >= 0) {
3771 if (selection.is_any_volume() || selection.is_any_modifier())
3772 enable_manipulation = !(*m_objects)[obj_idx]->is_cut();
3773 else // if (item && m_objects_model->GetItemType(item) == itInstanceRoot)
3774 disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
3775 }
3776 else {
3777 wxDataViewItemArray sels;
3778 GetSelections(sels);
3779 if (selection.is_single_full_object() || selection.is_multiple_full_instance()) {
3780 int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
3781 disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
3782 } else if (selection.is_mixed() || selection.is_multiple_full_object()) {
3783 std::map<CutObjectBase, std::set<int>> cut_objects;
3784
3785 // find cut objects
3786 for (auto item : sels) {
3787 int obj_idx = m_objects_model->GetObjectIdByItem(item);
3788 const ModelObject *obj = object(obj_idx);
3789 if (obj && obj->is_cut()) {
3790 if (cut_objects.find(obj->cut_id) == cut_objects.end())
3791 cut_objects[obj->cut_id] = std::set<int>{obj_idx};
3792 else
3793 cut_objects.at(obj->cut_id).insert(obj_idx);
3794 }
3795 }
3796
3797 // check if selected cut objects are "full selected"
3798 for (auto cut_object : cut_objects)
3799 if (cut_object.first.check_sum() != cut_object.second.size()) {
3800 disable_ss_manipulation = true;
3801 break;
3802 }
3803 disable_ununiform_scale = !cut_objects.empty();
3804 }
3805 }
3806 }
3807
3808 // BBS: multi config editing
3809 update_and_show_settings = true;
3810 }
3811 else {
3812 if (item) {
3813 // BBS
3814 const ItemType type = m_objects_model->GetItemType(item);
3815 const wxDataViewItem parent = m_objects_model->GetParent(item);
3816 const ItemType parent_type = m_objects_model->GetItemType(parent);
3817 obj_idx = m_objects_model->GetObjectIdByItem(item);
3818
3819 if ((type & itObject) || type == itInfo) {
3820 m_config = &(*m_objects)[obj_idx]->config;
3821 update_and_show_manipulations = true;
3822
3823 if (type == itInfo) {
3824 InfoItemType info_type = m_objects_model->GetInfoItemType(item);
3825 switch (info_type)
3826 {
3828 // BBS: remove CustomSeam
3829 //case InfoItemType::CustomSeam:
3832 {
3834 /*info_type == InfoItemType::CustomSeam ? GLGizmosManager::EType::Seam :*/
3837 GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
3838 if (gizmos_mgr.get_current_type() != gizmo_type)
3839 gizmos_mgr.open_gizmo(gizmo_type);
3840 break;
3841 }
3842 // BBS: remove Sinking
3843 //case InfoItemType::Sinking: { break; }
3844 default: { break; }
3845 }
3846 } else {
3847 // BBS: select object to edit config
3848 m_config = &(*m_objects)[obj_idx]->config;
3849 update_and_show_settings = true;
3850 disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
3851 }
3852 }
3853 else {
3854 if (type & itSettings) {
3855 if (parent_type & itObject) {
3856 og_name = _L("Object Settings to Modify");
3857 m_config = &(*m_objects)[obj_idx]->config;
3858 }
3859 else if (parent_type & itVolume) {
3860 og_name = _L("Part Settings to Modify");
3861 volume_id = m_objects_model->GetVolumeIdByItem(parent);
3862 m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
3863 }
3864 else if (parent_type & itLayer) {
3865 og_name = _L("Layer Range Settings to Modify");
3866 m_config = &get_item_config(parent);
3867 }
3868 update_and_show_settings = true;
3869 }
3870 else if (type & itVolume) {
3871 og_name = _L("Part manipulation");
3872 volume_id = m_objects_model->GetVolumeIdByItem(item);
3873 m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
3874 update_and_show_manipulations = true;
3875 m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
3876 update_and_show_settings = true;
3877
3878 const ModelVolume *volume = (*m_objects)[obj_idx]->volumes[volume_id];
3879 enable_manipulation = !((*m_objects)[obj_idx]->is_cut() && (volume->is_cut_connector() || volume->is_model_part()));
3880 }
3881 else if (type & itInstance) {
3882 og_name = _L("Instance manipulation");
3883 update_and_show_manipulations = true;
3884
3885 // fill m_config by object's values
3886 m_config = &(*m_objects)[obj_idx]->config;
3887 disable_ss_manipulation = (*m_objects)[obj_idx]->is_cut();
3888 }
3889 else if (type & (itLayerRoot | itLayer)) {
3890 og_name = type & itLayerRoot ? _L("Height ranges") : _L("Settings for height range");
3891 update_and_show_layers = true;
3892 update_and_show_settings = true;
3893
3894 if (type & itLayer)
3895 m_config = &get_item_config(item);
3896 }
3897 }
3898 }
3899 }
3900
3901 m_selected_object_id = obj_idx;
3902
3903 if (update_and_show_manipulations) {
3904 // BBS
3905 //wxGetApp().obj_manipul()->get_og()->set_name(" " + og_name + " ");
3906
3907 if (item) {
3908 // wxGetApp().obj_manipul()->get_og()->set_value("object_name", m_objects_model->GetName(item));
3909 // BBS
3910 //wxGetApp().obj_manipul()->update_item_name(m_objects_model->GetName(item));
3911 //wxGetApp().obj_manipul()->update_warning_icon_state(get_mesh_errors_info(obj_idx, volume_id));
3912 }
3913
3914 GLGizmosManager &gizmos_mgr = wxGetApp().plater()->canvas3D()->get_gizmos_manager();
3915
3916 if (GLGizmoScale3D *scale = dynamic_cast<GLGizmoScale3D *>(gizmos_mgr.get_gizmo(GLGizmosManager::Scale)))
3917 scale->enable_ununiversal_scale(!disable_ununiform_scale);
3918 }
3919
3920#if !NEW_OBJECT_SETTING
3921 if (update_and_show_settings)
3922 wxGetApp().obj_settings()->get_og()->set_name(" " + og_name + " ");
3923#endif
3924
3925 if (!this->IsShown())
3926 update_and_show_layers = false;
3927 if (printer_technology() == ptSLA)
3928 update_and_show_layers = false;
3929 else if (update_and_show_layers) {
3930 ;//wxGetApp().obj_layers()->get_og()->set_name(" " + og_name + " ");
3931 }
3932
3934
3935 Sidebar& panel = wxGetApp().sidebar();
3936 panel.Freeze();
3937
3938
3939 const ItemType type = m_objects_model->GetItemType(item);
3940 if (!(type & itLayer)) {
3941 wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
3942 }
3943 // BBS
3944 //wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations);
3945 wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
3946 wxGetApp().obj_layers() ->UpdateAndShow(update_and_show_layers);
3947 wxGetApp().plater()->show_object_info();
3948
3949 panel.Layout();
3950 panel.Thaw();
3951}
int scale(const int val)
Definition WipeTowerDialog.cpp:58
EType
Definition GLGizmosManager.hpp:86
@ FuzzySkin
Definition GLGizmosManager.hpp:96
void update_min_height()
Definition GUI_ObjectList.cpp:378

References _L, Slic3r::GUI::CustomSupports, Slic3r::ModelObject::cut_id, Slic3r::GUI::CutConnectors, Slic3r::GUI::GLGizmosManager::FdmSupports, Slic3r::GUI::GLGizmosManager::FuzzySkin, Slic3r::GUI::FuzzySkin, Slic3r::GUI::GLGizmosManager::get_current_type(), Slic3r::GUI::GLGizmosManager::get_gizmo(), get_item_config(), Slic3r::GUI::Selection::get_object_idx(), Slic3r::GUI::Selection::is_any_modifier(), Slic3r::GUI::Selection::is_any_volume(), Slic3r::ModelObject::is_cut(), Slic3r::ModelVolume::is_cut_connector(), Slic3r::GUI::Selection::is_mixed(), Slic3r::ModelVolume::is_model_part(), Slic3r::GUI::Selection::is_multiple_full_instance(), Slic3r::GUI::Selection::is_multiple_full_object(), Slic3r::GUI::Selection::is_single_full_instance(), Slic3r::GUI::Selection::is_single_full_object(), Slic3r::GUI::itInfo, Slic3r::GUI::itInstance, Slic3r::GUI::itInstanceRoot, Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itObject, Slic3r::GUI::itPlate, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, m_config, m_extruder_editor, m_objects_model, m_selected_object_id, Slic3r::GUI::GLGizmosManager::MmSegmentation, Slic3r::GUI::MmSegmentation, multiple_selection(), object(), Slic3r::GUI::GLGizmosManager::open_gizmo(), Slic3r::GUI::printer_technology(), Slic3r::ptSLA, Slic3r::GUI::GLGizmosManager::Scale, scale(), Slic3r::GUI::scene_selection(), and update_min_height().

Referenced by delete_all_objects_from_list(), delete_from_model_and_list(), paste_settings_into_list(), select_item(), select_item(), select_items(), select_object_item(), selection_changed(), unselect_objects(), update_and_show_object_settings_item(), and update_selections().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ paste()

void Slic3r::GUI::ObjectList::paste ( )
1761{
1762 wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE));
1763}

References Slic3r::GUI::plater().

Referenced by dispatch_shortcut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ paste_from_clipboard()

bool Slic3r::GUI::ObjectList::paste_from_clipboard ( )
1802{
1803 if (!(m_clipboard.get_type() & (itSettings | itLayer | itLayerRoot))) {
1804 m_clipboard.reset();
1805 return false;
1806 }
1807
1808 if (m_clipboard.get_type() & itSettings)
1810 else if (m_clipboard.get_type() & (itLayer | itLayerRoot))
1812
1813 return true;
1814}
void paste_settings_into_list()
Definition GUI_ObjectList.cpp:1398
void paste_layers_into_list()
Definition GUI_ObjectList.cpp:1334

References Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itSettings, m_clipboard, paste_layers_into_list(), and paste_settings_into_list().

Here is the call graph for this function:

◆ paste_layers_into_list()

void Slic3r::GUI::ObjectList::paste_layers_into_list ( )
1335{
1336 const int obj_idx = m_objects_model->GetObjectIdByItem(GetSelection());
1337 t_layer_config_ranges& cache_ranges = m_clipboard.get_ranges_cache();
1338
1339 if (obj_idx < 0 || (int)m_objects->size() <= obj_idx ||
1340 cache_ranges.empty() || printer_technology() == ptSLA)
1341 return;
1342
1343 const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx);
1344 wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item);
1345 if (layers_item)
1346 m_objects_model->Delete(layers_item);
1347
1349
1350 // and create Layer item(s) according to the layer_config_ranges
1351 for (const auto& range : cache_ranges)
1352 ranges.emplace(range);
1353
1354 layers_item = add_layer_root_item(object_item);
1355
1356 changed_object(obj_idx);
1357
1358 select_item(layers_item);
1359#ifndef __WXOSX__
1361#endif //no __WXOSX__
1362}

References add_layer_root_item(), changed_object(), Slic3r::ModelObject::layer_config_ranges, m_clipboard, m_objects, m_objects_model, object(), Slic3r::GUI::printer_technology(), Slic3r::ptSLA, Slic3r::range(), select_item(), and selection_changed().

Referenced by paste_from_clipboard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ paste_objects_into_list()

void Slic3r::GUI::ObjectList::paste_objects_into_list ( const std::vector< size_t > & object_idxs)
1485{
1486 if (object_idxs.empty())
1487 return;
1488
1489 wxDataViewItemArray items;
1490 for (const size_t object : object_idxs)
1491 {
1492 add_object_to_list(object);
1493 items.Add(m_objects_model->GetItemById(object));
1494 }
1495
1496 wxGetApp().plater()->changed_objects(object_idxs);
1497
1498 select_items(items);
1500}

References add_object_to_list(), m_objects_model, select_items(), and selection_changed().

Referenced by anonymous_namespace{EmbossJob.cpp}::CreateObjectJob::finalize(), and load_mesh_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ paste_settings_into_list()

void Slic3r::GUI::ObjectList::paste_settings_into_list ( )
1399{
1400 wxDataViewItemArray sels;
1401 GetSelections(sels);
1402 take_snapshot(_u8L("Paste settings"));
1403
1404 std::unique_ptr<t_config_option_keys> global_keys; // need copy from global
1405
1406 for (auto item : sels) {
1407
1408 if (m_objects_model->GetItemType(item) & itSettings)
1409 item = m_objects_model->GetParent(item);
1410
1411 ItemType item_type = m_objects_model->GetItemType(item);
1412 if(!(item_type & (itObject | itVolume |itLayer)))
1413 return;
1414
1415 DynamicPrintConfig& config_cache = m_clipboard.get_config_cache();
1416 assert(!config_cache.empty());
1417
1418 auto keys = config_cache.keys();
1419 auto part_options = SettingsFactory::get_options(true);
1420 auto config = &get_item_config(item);
1421 auto extruder = config->option("extruder") ? config->option("extruder")->clone() : nullptr;
1422 config->reset();
1423
1424 if (item_type & (itVolume | itLayer)) {
1425 if (global_keys == nullptr) {
1426 auto object = m_objects_model->GetParent(item);
1427 DynamicPrintConfig config;
1428 config.apply_only(*wxGetApp().get_tab(Preset::TYPE_PRINT)->get_config(), keys);
1429 config.apply_only(get_item_config(object).get(), keys);
1430 auto equals = config.equal(config_cache);
1431 global_keys.reset(new t_config_option_keys);
1432 auto keys2 = get_item_config(object).keys();
1433 std::copy_if(keys2.begin(), keys2.end(), std::back_inserter(*global_keys),
1434 [&equals](auto &e) { return std::find(equals.begin(), equals.end(), e) == equals.end(); });
1435 keys.erase(std::remove_if(keys.begin(), keys.end(),
1436 [&equals](auto &e) { return std::find(equals.begin(), equals.end(), e) != equals.end(); }), keys.end());
1437 }
1438 config->apply_only(*wxGetApp().get_tab(Preset::TYPE_PRINT)->get_config(), *global_keys);
1439 }
1440
1441 for (const std::string& opt_key: keys) {
1442 if (item_type & (itVolume | itLayer) &&
1443 std::find(part_options.begin(), part_options.end(), opt_key) == part_options.end())
1444 continue; // we can't to add object specific options for the part's(itVolume | itLayer) config
1445
1446 const ConfigOption* option = config_cache.option(opt_key);
1447 if (option)
1448 config->set_key_value(opt_key, option->clone());
1449 }
1450 if (extruder)
1451 config->set_key_value("extruder", extruder);
1452 else
1453 config->erase("extruder");
1454
1455 // Add settings item for object/sub-object and show them
1456 add_settings_item(item, &config->get());
1457 }
1458
1460}
t_config_option_keys keys() const
Definition PrintConfig.hpp:2650
@ TYPE_PRINT
Definition Preset.hpp:246
std::vector< std::string > t_config_option_keys
Definition Config.hpp:97
id get(id object, const void *key)
Definition MacIME.mm:22
static std::vector< std::string > get_options(bool is_part)
Definition GUI_Factories.cpp:201

References _u8L, add_settings_item(), Slic3r::ConfigOption::clone(), config(), Slic3r::DynamicConfig::empty(), get_item_config(), Slic3r::GUI::SettingsFactory::get_options(), Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, Slic3r::DynamicConfig::keys(), Slic3r::ModelConfig::keys(), m_clipboard, m_objects_model, Slic3r::ConfigBase::option(), part_selection_changed(), Slic3r::GUI::take_snapshot(), and Slic3r::Preset::TYPE_PRINT.

Referenced by paste_from_clipboard().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ paste_volumes_into_list()

void Slic3r::GUI::ObjectList::paste_volumes_into_list ( int obj_idx,
const ModelVolumePtrs & volumes )
1463{
1464 if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx))
1465 return;
1466
1467 if (volumes.empty())
1468 return;
1469
1470 wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [volumes](const ModelVolume* volume) {
1471 return std::find(volumes.begin(), volumes.end(), volume) != volumes.end(); });
1472 if (items.size() > 1) {
1474 m_last_selected_item = wxDataViewItem(nullptr);
1475 }
1476
1477 select_items(items);
1479
1480 //BBS: notify partplate the modify
1481 notify_instance_updated(obj_idx);
1482}

References m_last_selected_item, m_objects, m_selection_mode, notify_instance_updated(), reorder_volumes_and_get_selection(), select_items(), selection_changed(), and smVolume.

Here is the call graph for this function:

◆ printable_state_changed() [1/2]

void Slic3r::GUI::ObjectList::printable_state_changed ( const std::vector< ModelObject * > model_objects)
993{
994 std::vector<size_t> obj_idxs;
995 for (const ModelObject* mo : model_objects) {
996 if (mo == nullptr)
997 continue;
998
999 ModelInstance* mi = mo->instances[0];
1000 wxDataViewItem obj_item = m_objects_model->GetObjectItem(mo);
1001 m_objects_model->SetObjectPrintableState(mi->printable ? piPrintable : piUnprintable, obj_item);
1002
1003 int obj_idx = m_objects_model->GetObjectIdByItem(obj_item);
1004 obj_idxs.emplace_back(static_cast<size_t>(obj_idx));
1005 }
1006
1007 sort(obj_idxs.begin(), obj_idxs.end());
1008 obj_idxs.erase(unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
1009
1010 // update printable state on canvas
1011 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
1012
1013 // update scene
1014 wxGetApp().plater()->update();
1015}

References m_objects_model, Slic3r::GUI::piPrintable, Slic3r::GUI::piUnprintable, and Slic3r::ModelInstance::printable.

Referenced by printable_state_changed().

Here is the caller graph for this function:

◆ printable_state_changed() [2/2]

void Slic3r::GUI::ObjectList::printable_state_changed ( const std::vector< ObjectVolumeID > & ov_ids)
1018{
1019 std::vector<ModelObject*> model_objects;
1020 model_objects.reserve(ov_ids.size());
1021
1022 for (const ObjectVolumeID& ov_id : ov_ids) {
1023 if (ov_id.object != nullptr)
1024 model_objects.emplace_back(ov_id.object);
1025 }
1026
1027 printable_state_changed(model_objects);
1028}
void printable_state_changed(const std::vector< ModelObject * > model_objects)
Definition GUI_ObjectList.cpp:992

References printable_state_changed().

Here is the call graph for this function:

◆ redo()

void Slic3r::GUI::ObjectList::redo ( )
1822{
1823 wxGetApp().plater()->redo();
1824}

Referenced by dispatch_shortcut().

Here is the caller graph for this function:

◆ reload_all_plates()

void Slic3r::GUI::ObjectList::reload_all_plates ( bool notify_partplate = false)
6918{
6920
6921 // Unselect all objects before deleting them, so that no change of selection is emitted during deletion.
6922
6923 /* To avoid execution of selection_changed()
6924 * from wxEVT_DATAVIEW_SELECTION_CHANGED emitted from DeleteAll(),
6925 * wrap this two functions into m_prevent_list_events *
6926 * */
6927 m_prevent_list_events = true;
6928 this->UnselectAll();
6929 m_objects_model->ResetAll();
6930 m_prevent_list_events = false;
6931
6932 PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
6933 for (int i = 0; i < ppl.get_plate_count(); i++) {
6934 PartPlate* pp = ppl.get_plate(i);
6935 m_objects_model->AddPlate(pp, wxEmptyString);
6936 }
6937
6938 size_t obj_idx = 0;
6939 std::vector<size_t> obj_idxs;
6940 obj_idxs.reserve(m_objects->size());
6941 while (obj_idx < m_objects->size()) {
6942 add_object_to_list(obj_idx, false, notify_partplate);
6943 obj_idxs.push_back(obj_idx);
6944 ++obj_idx;
6945 }
6946
6948
6950
6951 // update scene
6952 wxGetApp().plater()->update();
6953 // update printable states on canvas
6954 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
6955}
void update_selections()
Definition GUI_ObjectList.cpp:4932
bool m_prevent_canvas_selection_update
Definition GUI_ObjectList.hpp:195

References add_object_to_list(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), m_objects, m_objects_model, m_prevent_canvas_selection_update, m_prevent_list_events, and update_selections().

Referenced by delete_all_objects_from_list(), and update_after_undo_redo().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove()

void Slic3r::GUI::ObjectList::remove ( )
4578{
4579 if (GetSelectedItemsCount() == 0)
4580 return;
4581
4582 auto delete_item = [this](wxDataViewItem item)
4583 {
4584 wxDataViewItem parent = m_objects_model->GetParent(item);
4585 ItemType type = m_objects_model->GetItemType(item);
4586 if (type & itObject)
4587 delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1);
4588 else {
4589 if (type & (itLayer | itInstance)) {
4590 // In case there is just one layer or two instances and we delete it, del_subobject_item will
4591 // also remove the parent item. Selection should therefore pass to the top parent (object).
4592 wxDataViewItemArray children;
4593 if (m_objects_model->GetChildren(parent, children) == (type & itLayer ? 1 : 2))
4594 parent = m_objects_model->GetObject(item);
4595 }
4596
4597 del_subobject_item(item);
4598 }
4599
4600 return parent;
4601 };
4602
4603 wxDataViewItemArray sels;
4604 GetSelections(sels);
4605
4606 wxDataViewItem parent = wxDataViewItem(nullptr);
4607
4608 if (sels.Count() == 1)
4609 parent = delete_item(GetSelection());
4610 else
4611 {
4612 SELECTION_MODE sels_mode = m_selection_mode;
4613 UnselectAll();
4614 update_selection(sels, sels_mode, m_objects_model);
4615
4616 Plater::TakeSnapshot snapshot = Plater::TakeSnapshot(wxGetApp().plater(), _u8L("Delete selected"));
4617
4618 for (auto& item : sels)
4619 {
4620 if (m_objects_model->InvalidItem(item)) // item can be deleted for this moment (like last 2 Instances or Volumes)
4621 continue;
4622 parent = delete_item(item);
4623 }
4624 }
4625
4626 if (parent && !m_objects_model->InvalidItem(parent)) {
4627 select_item(parent);
4629 }
4630}
void delete_from_model_and_list(const ItemType type, const int obj_idx, const int sub_obj_idx)
Definition GUI_ObjectList.cpp:4378
static void update_selection(wxDataViewItemArray &sels, ObjectList::SELECTION_MODE mode, ObjectDataViewModel *model)
Definition GUI_ObjectList.cpp:4533

References _u8L, del_subobject_item(), delete_from_model_and_list(), Slic3r::GUI::itInstance, Slic3r::GUI::itLayer, Slic3r::GUI::itObject, m_objects_model, m_selection_mode, Slic3r::GUI::plater(), select_item(), Slic3r::GUI::update_selection(), and update_selections_on_canvas().

Referenced by boolean(), dispatch_shortcut(), and merge().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rename_item()

void Slic3r::GUI::ObjectList::rename_item ( )
6281{
6282 const wxDataViewItem item = GetSelection();
6283 if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
6284 return ;
6285
6286 const wxString new_name = wxGetTextFromUser(_(L("Enter new name"))+":", _(L("Renaming")),
6287 m_objects_model->GetName(item), this);
6288
6289 if (new_name.IsEmpty())
6290 return;
6291
6294 return;
6295 }
6296
6297 if (m_objects_model->SetName(new_name, item))
6299}
static bool has_illegal_filename_characters(const wxString &name)
Definition Plater.cpp:416

References _, Slic3r::GUI::Plater::has_illegal_filename_characters(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, L, m_objects_model, Slic3r::GUI::Plater::show_illegal_characters_warning(), and update_name_in_model().

Here is the call graph for this function:

◆ reorder_volumes_and_get_selection()

wxDataViewItemArray Slic3r::GUI::ObjectList::reorder_volumes_and_get_selection ( int obj_idx,
std::function< bool(const ModelVolume *)> add_to_selection = nullptr )
6987{
6988 wxDataViewItemArray items;
6989 if (obj_idx < 0 || obj_idx >= m_objects->size()) {
6990 return items;
6991 }
6992 ModelObject* object = (*m_objects)[obj_idx];
6993 if (object->volumes.size() <= 1)
6994 return items;
6995
6996 object->sort_volumes(true);
6997 update_info_items(obj_idx, nullptr, true);
6998 items = add_volumes_to_object_in_list(obj_idx, std::move(add_to_selection));
6999
7000 changed_object(obj_idx);
7001 return items;
7002}

References add_volumes_to_object_in_list(), changed_object(), m_objects, object(), Slic3r::ModelObject::sort_volumes(), and update_info_items().

Referenced by apply_volumes_order(), load_generic_subobject(), load_subobject(), paste_volumes_into_list(), and set_volume_type().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_all()

void Slic3r::GUI::ObjectList::select_all ( )
5370{
5371 SelectAll();
5373}
@ SelectAll
Definition GLGizmosCommon.hpp:35

References Slic3r::GUI::SelectAll, and selection_changed().

Here is the call graph for this function:

◆ select_item() [1/3]

void Slic3r::GUI::ObjectList::select_item ( const ObjectVolumeID & ov_id)
5303{
5304 std::vector<ObjectVolumeID> ov_ids;
5305 ov_ids.push_back(ov_id);
5306 select_items(ov_ids);
5307}

References select_items().

Here is the call graph for this function:

◆ select_item() [2/3]

void Slic3r::GUI::ObjectList::select_item ( const wxDataViewItem & item)
5270{
5271 if (! item.IsOk()) { return; }
5272
5273 m_prevent_list_events = true;
5274
5275 UnselectAll();
5276 Select(item);
5278
5279 m_prevent_list_events = false;
5280}

References m_prevent_list_events, and part_selection_changed().

Referenced by add_layer_range_after_current(), boolean(), decrease_object_instances(), del_layer_range(), delete_instance_from_list(), delete_object_from_list(), delete_object_from_list(), delete_volume_from_list(), edit_layer_range(), increase_object_instances(), layers_editing(), load_generic_subobject(), merge(), OnDrop(), paste_layers_into_list(), remove(), selected_object(), show_settings(), and update_settings_item_and_selection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_item() [3/3]

void Slic3r::GUI::ObjectList::select_item ( std::function< wxDataViewItem()> get_item)
5283{
5284 if (!get_item)
5285 return;
5286
5287 m_prevent_list_events = true;
5289
5290 wxDataViewItem item = get_item();
5291 if (item.IsOk()) {
5292 UnselectAll();
5293 Select(item);
5295 }
5296
5298 m_prevent_list_events = false;
5299}

References m_prevent_list_events, m_prevent_list_manipulation, and part_selection_changed().

Here is the call graph for this function:

◆ select_item_all_children()

void Slic3r::GUI::ObjectList::select_item_all_children ( )
5376{
5377 if (wxGetApp().plater() && !wxGetApp().plater()->canvas3D()->get_gizmos_manager().is_allow_select_all()) {
5378 return;
5379 }
5380 wxDataViewItemArray sels;
5381
5382 // There is no selection before OR some object is selected => select all objects
5383 if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) {
5384 for (size_t i = 0; i < m_objects->size(); i++)
5385 sels.Add(m_objects_model->GetItemById(i));
5387 }
5388 else {
5389 const auto item = GetSelection();
5390 const ItemType item_type = m_objects_model->GetItemType(item);
5391 // Some volume/layer/instance is selected => select all volumes/layers/instances inside the current object
5392 if (item_type & (itVolume | itInstance | itLayer))
5393 m_objects_model->GetChildren(m_objects_model->GetParent(item), sels);
5394
5395 m_selection_mode = item_type&itVolume ? smVolume :
5396 item_type&itLayer ? smLayer : smInstance;
5397 }
5398
5399 SetSelections(sels);
5401}

References Slic3r::GUI::itInstance, Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_objects, m_objects_model, m_selection_mode, Slic3r::GUI::plater(), selection_changed(), smInstance, smLayer, and smVolume.

Referenced by dispatch_shortcut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_items() [1/2]

void Slic3r::GUI::ObjectList::select_items ( const std::vector< ObjectVolumeID > & ov_ids)
5310{
5311 ModelObjectPtrs& objects = wxGetApp().model().objects;
5312
5313 wxDataViewItemArray sel_items;
5314 for (auto ov_id : ov_ids) {
5315 if (ov_id.object == nullptr)
5316 continue;
5317
5318 ModelObject* mo = ov_id.object;
5319 ModelVolume* mv = ov_id.volume;
5320
5321 wxDataViewItem obj_item = m_objects_model->GetObjectItem(mo);
5322 if (mv != nullptr) {
5323 size_t vol_idx;
5324 for (vol_idx = 0; vol_idx < mo->volumes.size(); vol_idx++) {
5325 if (mo->volumes[vol_idx] == mv)
5326 break;
5327 }
5328 assert(vol_idx < mo->volumes.size());
5329
5330 wxDataViewItem vol_item = m_objects_model->GetVolumeItem(obj_item, vol_idx);
5331 if (vol_item.GetID() != nullptr) {
5332 sel_items.push_back(vol_item);
5333 }
5334 else {
5335 sel_items.push_back(obj_item);
5336 }
5337 }
5338 else {
5339 sel_items.push_back(obj_item);
5340 }
5341 }
5342
5343 select_items(sel_items);
5345}

References m_objects_model, objects(), select_items(), selection_changed(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ select_items() [2/2]

void Slic3r::GUI::ObjectList::select_items ( const wxDataViewItemArray & sels)
5348{
5349 m_prevent_list_events = true;
5351 m_last_selected_item = sels.empty() ? wxDataViewItem(nullptr) : sels.back();
5352
5353 UnselectAll();
5354
5355 if (!sels.empty()) {
5356 SetSelections(sels);
5357 }
5358 else {
5359 int curr_plate_idx = wxGetApp().plater()->get_partplate_list().get_curr_plate_index();
5360 on_plate_selected(curr_plate_idx);
5361 }
5362
5364
5366 m_prevent_list_events = false;
5367}
void on_plate_selected(int plate_index)
Definition GUI_ObjectList.cpp:6957

References m_last_selected_item, m_prevent_list_events, m_prevent_list_manipulation, on_plate_selected(), and part_selection_changed().

Referenced by load_subobject(), paste_objects_into_list(), paste_volumes_into_list(), select_item(), select_items(), and update_selections().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ select_object_item()

void Slic3r::GUI::ObjectList::select_object_item ( bool is_msr_gizmo)
4516{
4517 if (wxDataViewItem item = GetSelection()) {
4518 ItemType type = m_objects_model->GetItemType(item);
4519 bool is_volume_item = type == itVolume || (type == itSettings && m_objects_model->GetItemType(m_objects_model->GetParent(item)) == itVolume);
4520 if ((is_msr_gizmo && is_volume_item) || type == itObject)
4521 return;
4522
4523 if (wxDataViewItem obj_item = m_objects_model->GetTopParent(item)) {
4524 m_prevent_list_events = true;
4525 UnselectAll();
4526 Select(obj_item);
4528 m_prevent_list_events = false;
4529 }
4530 }
4531}

References Slic3r::GUI::itObject, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, m_objects_model, m_prevent_list_events, and part_selection_changed().

Here is the call graph for this function:

◆ selected_instances_of_same_object()

bool Slic3r::GUI::ObjectList::selected_instances_of_same_object ( )
3560{
3561 wxDataViewItemArray sels;
3562 GetSelections(sels);
3563
3564 const int obj_idx = m_objects_model->GetObjectIdByItem(sels.front());
3565
3566 for (auto item : sels) {
3567 if (! (m_objects_model->GetItemType(item) & itInstance) ||
3568 obj_idx != m_objects_model->GetObjectIdByItem(item))
3569 return false;
3570 }
3571 return true;
3572}

References Slic3r::GUI::itInstance, and m_objects_model.

Referenced by OnBeginDrag(), and show_context_menu().

Here is the caller graph for this function:

◆ selected_object()

void Slic3r::GUI::ObjectList::selected_object ( ObjectDataViewModelNode * item)
1036{
1037 if (!item) {
1038 return;
1039 }
1040 this->SetFocus();
1041 select_item(wxDataViewItem(item));
1044}

References ensure_current_item_visible(), select_item(), and selection_changed().

Here is the call graph for this function:

◆ selection_changed()

void Slic3r::GUI::ObjectList::selection_changed ( )
1268{
1269 if (wxGetApp().is_closing()) return;
1270 if (m_prevent_list_events) return;
1271
1273
1275
1276 // update object selection on Plater
1279
1280 // to update the toolbar and info sizer
1281 if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) {
1282 auto event = SimpleEvent(EVT_OBJ_LIST_OBJECT_SELECT);
1283 event.SetEventObject(this);
1284 wxPostEvent(this, event);
1285 }
1286
1287 if (const wxDataViewItem item = GetSelection())
1288 {
1289 const ItemType type = m_objects_model->GetItemType(item);
1290 // to correct visual hints for layers editing on the Scene
1291 if (type & (itLayer|itLayerRoot)) {
1292 wxGetApp().obj_layers()->reset_selection();
1293
1294 if (type & itLayerRoot)
1295 wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
1296 else {
1297 wxGetApp().obj_layers()->set_selectable_range(m_objects_model->GetLayerRangeByItem(item));
1298 wxGetApp().obj_layers()->update_scene_from_editor_selection();
1299 }
1300 }
1301 }
1302
1304}
void fix_multiselection_conflicts()
Definition GUI_ObjectList.cpp:5483

References fix_cut_selection(), fix_multiselection_conflicts(), Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itObject, m_objects_model, m_prevent_canvas_selection_update, m_prevent_list_events, part_selection_changed(), and update_selections_on_canvas().

Referenced by ObjectList(), add_object_to_list(), increase_object_instances(), load_generic_subobject(), load_subobject(), paste_layers_into_list(), paste_objects_into_list(), paste_volumes_into_list(), select_all(), select_item_all_children(), select_items(), and selected_object().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_color_paint_hidden()

void Slic3r::GUI::ObjectList::set_color_paint_hidden ( const bool hide) const
1128{
1129 GetColumn(colColorPaint)->SetHidden(hide);
1131}

References Slic3r::GUI::colColorPaint, and update_name_column_width().

Referenced by update_info_items().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_extruder_for_selected_items()

void Slic3r::GUI::ObjectList::set_extruder_for_selected_items ( const int extruder)
6813{
6814 // BBS: check extruder id
6815 std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
6816 if (extruder > colors.size())
6817 return;
6818
6819 wxDataViewItemArray sels;
6820 GetSelections(sels);
6821
6822 if (sels.empty())
6823 return;
6824
6825 take_snapshot(_u8L("Change Filaments"));
6826
6827 for (const wxDataViewItem& sel_item : sels)
6828 {
6829 /* We can change extruder for Object/Volume only.
6830 * So, if Instance is selected, get its Object item and change it
6831 */
6832 ItemType sel_item_type = m_objects_model->GetItemType(sel_item);
6833 // ORCA: Fix crash when setting filament for instance (item was used uninitialized)
6834 wxDataViewItem item = (sel_item_type & itInstance) ? m_objects_model->GetObject(sel_item) : sel_item;
6835 ItemType type = m_objects_model->GetItemType(item);
6836 if (type & itVolume) {
6837 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
6838 int vol_idx = m_objects_model->GetVolumeIdByItem(item);
6839 vol_idx = m_objects_model->get_real_volume_index_in_3d(obj_idx, vol_idx);
6840 if ((obj_idx < m_objects->size()) && (obj_idx < (*m_objects)[obj_idx]->volumes.size())) {
6841 auto volume_type = (*m_objects)[obj_idx]->volumes[vol_idx]->type();
6842 if (volume_type != ModelVolumeType::MODEL_PART && volume_type != ModelVolumeType::PARAMETER_MODIFIER)
6843 continue;
6844 }
6845 }
6846
6847 if (type & itLayerRoot)
6848 continue;
6849
6850 // BBS: handle extruder 0 for part, use it's parent extruder
6851 int new_extruder = extruder;
6852 if (extruder == 0) {
6853 if (type & itObject) {
6854 new_extruder = 1;
6855 }
6856 else if ((type & itVolume) && (m_objects_model->GetVolumeType(sel_item) == ModelVolumeType::MODEL_PART)) {
6857 new_extruder = m_objects_model->GetExtruderNumber(m_objects_model->GetParent(sel_item));
6858 }
6859 }
6860
6861 if (type & itInfo && m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) {
6862 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
6863 for (size_t i = 0; i < (*m_objects)[obj_idx]->volumes.size(); i++) {
6864 auto mv = (*m_objects)[obj_idx]->volumes[i];
6865 if (mv->is_cut_connector()) {
6866 ModelConfig &config = mv->config;
6867 if (config.has("extruder"))
6868 config.set("extruder", new_extruder);
6869 else
6870 config.set_key_value("extruder", new ConfigOptionInt(new_extruder));
6871 }
6872 }
6873 } else {
6874 ModelConfig &config = get_item_config(item);
6875 if (config.has("extruder"))
6876 config.set("extruder", new_extruder);
6877 else
6878 config.set_key_value("extruder", new ConfigOptionInt(new_extruder));
6879 }
6880
6881 // for object, clear all its part volume's extruder config
6882 if (type & itObject) {
6883 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
6884 for (ModelVolume* mv : node->m_model_object->volumes) {
6885 if (mv->type() == ModelVolumeType::MODEL_PART && mv->config.has("extruder"))
6886 mv->config.erase("extruder");
6887 }
6888 }
6889
6890 const wxString extruder_str = wxString::Format("%d", new_extruder);
6891 m_objects_model->SetExtruder(extruder_str, item);
6892 }
6893
6894 // update scene
6895 wxGetApp().plater()->update();
6896
6897 // BBS: update extruder/filament column
6898 Refresh();
6899}

References _u8L, config(), Slic3r::ModelVolume::config, Slic3r::GUI::CutConnectors, Slic3r::ModelConfig::erase(), get_item_config(), Slic3r::ModelConfig::has(), Slic3r::GUI::itInfo, Slic3r::GUI::itInstance, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, Slic3r::GUI::ObjectDataViewModelNode::m_model_object, m_objects, m_objects_model, Slic3r::MODEL_PART, Slic3r::PARAMETER_MODIFIER, Slic3r::GUI::take_snapshot(), Slic3r::ModelVolume::type(), and Slic3r::ModelObject::volumes.

Referenced by ObjectList(), and key_event().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_filament_column_hidden()

void Slic3r::GUI::ObjectList::set_filament_column_hidden ( const bool hide) const
1115{
1116 GetColumn(colFilament)->SetHidden(hide);
1118}

References Slic3r::GUI::colFilament, and update_name_column_width().

Referenced by update_objects_list_filament_column(), and update_objects_list_filament_column_when_delete_filament().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_min_height()

void Slic3r::GUI::ObjectList::set_min_height ( )
368{
369 // BBS
370#if 0
371 if (m_items_count == size_t(-1))
372 m_items_count = 7;
373 int list_min_height = lround(2.25 * (m_items_count + 1) * wxGetApp().em_unit()); // +1 is for height of control header
374 this->SetMinSize(wxSize(1, list_min_height));
375#endif
376}
size_t m_items_count
Definition GUI_ObjectList.hpp:218

References em_unit(), and m_items_count.

Referenced by msw_rescale(), and update_min_height().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_selected_layers_range_idx()

void Slic3r::GUI::ObjectList::set_selected_layers_range_idx ( const int range_idx)
inline
419{ m_selected_layers_range_idx = range_idx; }
int m_selected_layers_range_idx
Definition GUI_ObjectList.hpp:137

References m_selected_layers_range_idx.

Referenced by Slic3r::GUI::Plater::priv::undo_redo_to().

Here is the caller graph for this function:

◆ set_selection_mode()

void Slic3r::GUI::ObjectList::set_selection_mode ( SELECTION_MODE mode)
inline
420{ m_selection_mode = mode; }

References m_selection_mode.

Referenced by Slic3r::GUI::Plater::priv::undo_redo_to().

Here is the caller graph for this function:

◆ set_sinking_hidden()

void Slic3r::GUI::GUI::ObjectList::set_sinking_hidden ( const bool hide) const
1140{
1141 GetColumn(colSinking)->SetHidden(hide);
1143}

References Slic3r::GUI::colSinking, and update_name_column_width().

Referenced by update_info_items().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_support_paint_hidden()

void Slic3r::GUI::ObjectList::set_support_paint_hidden ( const bool hide) const
1134{
1135 GetColumn(colSupportPaint)->SetHidden(hide);
1137}

References Slic3r::GUI::colSupportPaint, and update_name_column_width().

Referenced by update_info_items().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_tooltip_for_item()

void Slic3r::GUI::ObjectList::set_tooltip_for_item ( const wxPoint & pt)
667{
668 wxDataViewItem item;
669 wxDataViewColumn* col;
670 HitTest(pt, item, col);
671
672 /* GetMainWindow() return window, associated with wxDataViewCtrl.
673 * And for this window we should to set tooltips.
674 * Just this->SetToolTip(tooltip) => has no effect.
675 */
676
677 if (!item || GetSelectedItemsCount() > 1)
678 {
679 GetMainWindow()->SetToolTip(""); // hide tooltip
680 return;
681 }
682
683 wxString tooltip = "";
684 ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
685
686 if (col->GetModelColumn() == (unsigned int)colEditing) {
687 if (node->IsActionEnabled())
688#ifdef __WXOSX__
689 tooltip = _(L("Right click the icon to drop the object settings"));
690#else
691 tooltip = _(L("Click the icon to reset all settings of the object"));
692#endif //__WXMSW__
693 }
694 else if (col->GetModelColumn() == (unsigned int)colPrint)
695#ifdef __WXOSX__
696 tooltip = _(L("Right click the icon to drop the object printable property"));
697#else
698 tooltip = _(L("Click the icon to toggle printable properties of the object"));
699#endif //__WXMSW__
700 // BBS
701 else if (col->GetModelColumn() == (unsigned int)colSupportPaint) {
702 if (node->HasSupportPainting())
703 tooltip = _(L("Click the icon to edit support painting of the object"));
704
705 }
706 else if (col->GetModelColumn() == (unsigned int)colColorPaint) {
707 if (node->HasColorPainting())
708 tooltip = _(L("Click the icon to edit color painting for the object"));
709 }
710 else if (col->GetModelColumn() == (unsigned int)colSinking) {
711 if (node->HasSinking())
712 tooltip = _(L("Click the icon to shift this object to the bed"));
713 }
714 else if (col->GetModelColumn() == (unsigned int)colName && (pt.x >= 2 * wxGetApp().em_unit() && pt.x <= 4 * wxGetApp().em_unit()))
715 {
716 if (const ItemType type = m_objects_model->GetItemType(item);
717 type & (itObject | itVolume)) {
718 int obj_idx = m_objects_model->GetObjectIdByItem(item);
719 int vol_idx = type & itVolume ? m_objects_model->GetVolumeIdByItem(item) : -1;
720 tooltip = get_mesh_errors_info(obj_idx, vol_idx).tooltip;
721 }
722 }
723
724 GetMainWindow()->SetToolTip(tooltip);
725}
wxString tooltip
Definition GUI_ObjectList.hpp:92

References _, Slic3r::GUI::colColorPaint, Slic3r::GUI::colEditing, Slic3r::GUI::colName, Slic3r::GUI::colPrint, Slic3r::GUI::colSinking, Slic3r::GUI::colSupportPaint, em_unit(), get_mesh_errors_info(), Slic3r::GUI::ObjectDataViewModelNode::HasColorPainting(), Slic3r::GUI::ObjectDataViewModelNode::HasSinking(), Slic3r::GUI::ObjectDataViewModelNode::HasSupportPainting(), Slic3r::GUI::ObjectDataViewModelNode::IsActionEnabled(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, L, m_objects_model, and Slic3r::GUI::MeshErrorsInfo::tooltip.

Referenced by ObjectList().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_variable_height_column_hidden()

void Slic3r::GUI::ObjectList::set_variable_height_column_hidden ( const bool hide) const
1121{
1122 GetColumn(colHeight)->SetHidden(hide);
1124}

References Slic3r::GUI::colHeight, and update_name_column_width().

Referenced by delete_from_model_and_list(), and delete_from_model_and_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_volume_type()

void Slic3r::GUI::ObjectList::set_volume_type ( ModelVolumeType new_type,
bool preserve_ps_subtype = true )
5869{
5870 struct VolumeSelection {
5871 int object_idx;
5872 ModelVolume* volume;
5873 };
5874
5875 // --- Collect selected volumes from the object tree, falling back to the 3D canvas ---
5876 std::vector<VolumeSelection> volumes;
5877 auto add_volume = [&volumes](int obj_idx, ModelVolume* volume) {
5878 if (volume == nullptr)
5879 return;
5880 auto it = std::find_if(volumes.begin(), volumes.end(), [volume](const VolumeSelection& other) { return other.volume == volume; });
5881 if (it == volumes.end())
5882 volumes.push_back({ obj_idx, volume });
5883 };
5884
5885 wxDataViewItemArray sels;
5886 GetSelections(sels);
5887 for (auto item : sels) {
5888 wxDataViewItem volume_item = item;
5889 ItemType type = m_objects_model->GetItemType(item);
5890 if (!(type & itVolume)) {
5891 if ((type & itSettings) && (m_objects_model->GetItemType(m_objects_model->GetParent(item)) & itVolume))
5892 volume_item = m_objects_model->GetParent(item);
5893 else
5894 continue;
5895 }
5896
5897 const int obj_idx = m_objects_model->GetObjectIdByItem(volume_item);
5898 const int vol_idx = m_objects_model->GetVolumeIdByItem(volume_item);
5899 if (obj_idx < 0 || vol_idx < 0 || obj_idx >= m_objects->size())
5900 continue;
5901
5902 const int real_idx = m_objects_model->get_real_volume_index_in_3d(obj_idx, vol_idx);
5903 if (real_idx < 0 || real_idx >= (*m_objects)[obj_idx]->volumes.size())
5904 continue;
5905
5906 add_volume(obj_idx, (*m_objects)[obj_idx]->volumes[real_idx]);
5907 }
5908
5909 auto collect_from_canvas = [&add_volume](GLCanvas3D* canvas) {
5910 if (canvas == nullptr)
5911 return;
5912 const Selection& selection = canvas->get_selection();
5913 for (auto idx : selection.get_volume_idxs()) {
5914 const GLVolume* gl_volume = selection.get_volume(idx);
5915 if (gl_volume == nullptr || gl_volume->object_idx() < 0)
5916 continue;
5917 ModelVolume* volume = get_model_volume(*gl_volume, selection.get_model()->objects);
5918 add_volume(gl_volume->object_idx(), volume);
5919 }
5920 };
5921
5922 if (volumes.empty()) {
5923 collect_from_canvas(wxGetApp().plater()->canvas3D());
5924 if (volumes.empty()) {
5925 auto canvas_type = wxGetApp().plater()->get_current_canvas3D()->get_canvas_type();
5927 collect_from_canvas(wxGetApp().plater()->get_view3D_canvas3D());
5928 }
5929 if (volumes.empty())
5930 return;
5931 }
5932
5933 // Defense-in-depth safety net against issue #5070: SVG/text volumes carry emboss metadata
5934 // (text_configuration, emboss_shape) that only makes sense for Part / Negative Part / Modifier.
5935 // ModelVolume::set_type() does not clear that metadata, so converting such volumes to
5936 // Support Blocker / Support Enforcer leaves stale emboss state attached to a support volume
5937 // and historically crashed (originally fixed in the now-disabled change_part_type() by hiding
5938 // Support entries in the old choice dialog; the UI-side guard for the current submenu lives
5939 // in MenuFactory::append_menu_item_change_type, see #13120).
5940 // The same rationale applies to any Precise Seam subtype.
5941 // This block must never be reachable under a healthy UI; if it ever logs, the UI guard has
5942 // been bypassed (new entry point, refactor, plugin, etc.) and should be investigated.
5944 || is_precise_seam(new_type)) {
5945 const bool has_text_or_svg = std::any_of(volumes.begin(), volumes.end(),
5946 [](const VolumeSelection& sel) { return sel.volume->is_svg() || sel.volume->is_text(); });
5947 if (has_text_or_svg) {
5948 BOOST_LOG_TRIVIAL(error) << __FUNCTION__
5949 << ": blocked attempt to set SUPPORT_BLOCKER/ENFORCER or Precise Seam on SVG/text volume; "
5950 << "UI guard should have prevented this -- possible regression in the Change Type menu";
5951 return;
5952 }
5953 }
5954
5955 // --- Subtype preservation for the generic "Precise Seam" entry ---
5956 // The Change Type submenu uses PRECISE_SEAM_CENTER as the single "Precise Seam" entry
5957 // and calls with preserve_ps_subtype=true: volumes that are already Precise Seam keep
5958 // their subtype (LEFT/RIGHT/etc.); only non-PS volumes get converted to the default
5959 // CENTER subtype.
5960 //
5961 // The "Precise Seam Type" subtype submenu calls with preserve_ps_subtype=false: the
5962 // user explicitly picked CENTER and all selected PS volumes must be set to CENTER
5963 // verbatim (otherwise CENTER would become unreachable for mixed-subtype selections,
5964 // since preservation would keep every volume at its current subtype and any_diff would
5965 // be false — the reason for this two-parameter split).
5966 auto effective_new_type = [new_type, preserve_ps_subtype](const ModelVolume* v) -> ModelVolumeType {
5967 if (preserve_ps_subtype && new_type == ModelVolumeType::PRECISE_SEAM_CENTER && v->is_precise_seam())
5968 return v->type();
5969 return new_type;
5970 };
5971
5972 // --- Any-change check using the effective target type ---
5973 const bool any_diff = std::any_of(volumes.begin(), volumes.end(),
5974 [&effective_new_type](const VolumeSelection& sel) {
5975 return sel.volume->type() != effective_new_type(sel.volume);
5976 });
5977
5978 if (!any_diff)
5979 return;
5980
5981 // --- Last-solid-part guard (pre-existing behavior) ---
5982 // When converting away from MODEL_PART, ensure at least one solid part remains per object.
5983 if (new_type != ModelVolumeType::MODEL_PART) {
5984 std::map<int, int> total_part_cnt;
5985 std::map<int, int> selected_part_cnt;
5986
5987 for (const auto& sel : volumes) {
5988 if (total_part_cnt.find(sel.object_idx) == total_part_cnt.end()) {
5989 int count = 0;
5990 for (auto vol : (*m_objects)[sel.object_idx]->volumes)
5991 if (vol->type() == ModelVolumeType::MODEL_PART)
5992 ++count;
5993 total_part_cnt.emplace(sel.object_idx, count);
5994 }
5995 if (sel.volume->type() == ModelVolumeType::MODEL_PART)
5996 ++selected_part_cnt[sel.object_idx];
5997 }
5998
5999 for (const auto& sel : selected_part_cnt) {
6000 auto it = total_part_cnt.find(sel.first);
6001 if (it != total_part_cnt.end() && it->second > 0 && sel.second == it->second) {
6002 Slic3r::GUI::show_error(nullptr, _(L("The type of the last solid object part cannot be changed.")));
6003 return;
6004 }
6005 }
6006 }
6007
6008 take_snapshot(_u8L("Change part type"));
6009
6010 // --- Apply type changes with Precise Seam group-aware repositioning ---
6011 // Note: `changed_volumes` / `touched_objects` track every processed volume, including
6012 // subtype-preservation no-ops. Tracking no-ops is intentional — it ensures such
6013 // volumes remain selected after the post-apply rebuild. Without that, a cross-object
6014 // mixed selection like [Part, PS_LEFT] clicking "Change type → Precise Seam" would
6015 // silently deselect the preserved PS_LEFT: only the Part's object would enter
6016 // touched_objects, and the final SetSelections(new_selection) would drop PS_LEFT.
6017 std::set<const ModelVolume*> changed_volumes;
6018 std::set<int> touched_objects;
6019 for (const auto& sel : volumes) {
6020 const ModelVolumeType target = effective_new_type(sel.volume);
6021 const ModelVolumeType old_type = sel.volume->type();
6022
6023 // Record the volume for reselection before the no-op short-circuit (see comment above).
6024 changed_volumes.insert(sel.volume);
6025 touched_objects.insert(sel.object_idx);
6026
6027 if (old_type == target)
6028 continue; // subtype-preservation no-op — nothing to write/move
6029
6030 sel.volume->set_type(target);
6031
6032 // If the change crosses a PS group boundary, move the volume to the end of volumes[]
6033 // so the stable sort in reorder_volumes_and_get_selection() places it at the end of
6034 // its new group (see precise_seam_group_changed() for details).
6035 if (precise_seam_group_changed(old_type, target))
6036 move_volume_to_end((*m_objects)[sel.object_idx], sel.volume);
6037 }
6038
6039 // --- Rebuild selection to follow the changed volumes ---
6040 wxDataViewItemArray new_selection;
6041 for (int obj_idx : touched_objects) {
6042 wxDataViewItemArray sel_items = reorder_volumes_and_get_selection(obj_idx, [&changed_volumes](const ModelVolume* volume) {
6043 return changed_volumes.find(volume) != changed_volumes.end();
6044 });
6045 for (const auto& item : sel_items)
6046 new_selection.push_back(item);
6047 }
6048
6049 if (!new_selection.IsEmpty()) {
6050 m_prevent_list_events = true;
6051 UnselectAll();
6052 SetSelections(new_selection);
6053 m_prevent_list_events = false;
6054 }
6055}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
@ CanvasView3D
Definition GLCanvas3D.hpp:626
bool is_connectors_item_selected() const
Definition GUI_ObjectList.cpp:4900
static void move_volume_to_end(ModelObject *obj, ModelVolume *volume)
Definition GUI_ObjectList.cpp:5857
static ModelVolume * get_model_volume(const Selection &selection, Model &model)
Definition GLGizmoBrimEars.cpp:66
static bool precise_seam_group_changed(ModelVolumeType old_type, ModelVolumeType new_type)
Definition GUI_ObjectList.cpp:5844
@ PRECISE_SEAM_CENTER
Definition Model.hpp:364

References _, _u8L, Slic3r::GUI::GLCanvas3D::CanvasView3D, count, Slic3r::GUI::Selection::get_model(), Slic3r::GUI::get_model_volume(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), is_connectors_item_selected(), Slic3r::is_precise_seam(), Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, L, m_objects, m_objects_model, m_prevent_list_events, Slic3r::MODEL_PART, Slic3r::GUI::move_volume_to_end(), Slic3r::GLVolume::object_idx(), Slic3r::Model::objects, Slic3r::GUI::plater(), Slic3r::PRECISE_SEAM_CENTER, Slic3r::GUI::precise_seam_group_changed(), reorder_volumes_and_get_selection(), Slic3r::GUI::show_error(), Slic3r::SUPPORT_BLOCKER, Slic3r::SUPPORT_ENFORCER, and Slic3r::GUI::take_snapshot().

Here is the call graph for this function:

◆ show_context_menu()

void Slic3r::GUI::ObjectList::show_context_menu ( const bool evt_context_menu)
1662{
1663 // BBS Disable menu popup if current canvas is Preview
1664 if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasPreview)
1665 return;
1666
1667 wxMenu* menu {nullptr};
1668 Plater* plater = wxGetApp().plater();
1669
1670 if (multiple_selection())
1671 {
1673 menu = plater->instance_menu();
1674 else
1675 menu = plater->multi_selection_menu();
1676 }
1677 else {
1678 const auto item = GetSelection();
1679 if (item)
1680 {
1681 const ItemType type = m_objects_model->GetItemType(item);
1682 if (!(type & (itPlate | itObject | itVolume | itInstance)))
1683 return;
1684 if (type & itVolume) {
1685 int obj_idx, vol_idx;
1686 get_selected_item_indexes(obj_idx, vol_idx, item);
1687 if (obj_idx < 0 || vol_idx < 0)
1688 return;
1689 const ModelVolume *volume = object(obj_idx)->volumes[vol_idx];
1690
1691 menu = volume->is_text() ? plater->text_part_menu() :
1692 volume->is_svg() ? plater->svg_part_menu() : // ORCA fixes missing "Edit SVG" item for Add/Negative/Modifier SVG objects in object list
1693 plater->part_menu();
1694 }
1695 else
1696 menu = type & itPlate ? plater->plate_menu() :
1697 type & itInstance ? plater->instance_menu() :
1700 if (type & itPlate) {
1701 int plate_idx = -1;
1702 const ItemType type0 = m_objects_model->GetItemType(item, plate_idx);
1703 if (plate_idx >= 0) {
1705 }
1706 }
1707 }
1708 else if (evt_context_menu)
1709 menu = plater->default_menu();
1710 }
1711
1712 if (menu)
1713 plater->PopupMenu(menu);
1714}
wxMenu * default_menu()
Definition Plater.cpp:24128
wxMenu * svg_part_menu()
Definition Plater.cpp:24126
bool PopupMenu(wxMenu *menu, const wxPoint &pos=wxDefaultPosition)
Definition Plater.cpp:24009
wxMenu * sla_object_menu()
Definition Plater.cpp:24127
wxMenu * text_part_menu()
Definition Plater.cpp:24125
wxMenu * part_menu()
Definition Plater.cpp:24124
wxMenu * multi_selection_menu()
Definition Plater.cpp:24131
wxMenu * plate_menu()
Definition Plater.cpp:24122
wxMenu * instance_menu()
Definition Plater.cpp:24129
wxMenu * object_menu()
Definition Plater.cpp:24123
void SetPlateIndexByRightMenuInLeftUI(int)
Definition Plater.cpp:24134
ModelVolumePtrs volumes
Definition Model.hpp:393

References Slic3r::GUI::GLCanvas3D::CanvasPreview, get_selected_item_indexes(), Slic3r::ModelVolume::is_svg(), Slic3r::ModelVolume::is_text(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::GUI::itPlate, Slic3r::GUI::itVolume, m_objects_model, multiple_selection(), object(), Slic3r::GUI::plater(), Slic3r::GUI::printer_technology(), Slic3r::ptFFF, selected_instances_of_same_object(), and Slic3r::ModelObject::volumes.

Referenced by list_manipulation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ show_settings()

void Slic3r::GUI::ObjectList::show_settings ( const wxDataViewItem settings_item)
2227{
2228 if (!settings_item)
2229 return;
2230
2231 select_item(settings_item);
2232
2233 // update object selection on Plater
2236}

References m_prevent_canvas_selection_update, select_item(), and update_selections_on_canvas().

Referenced by add_category_to_settings_from_frequent(), and add_category_to_settings_from_selection().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ simplify()

void Slic3r::GUI::ObjectList::simplify ( )
6454{
6455 auto plater = wxGetApp().plater();
6456 GLGizmosManager& gizmos_mgr = plater->get_view3D_canvas3D()->get_gizmos_manager();
6457
6458 // Do not simplify when a gizmo is open. There might be issues with updates
6459 // and what is worse, the snapshot time would refer to the internal stack.
6460 if (! gizmos_mgr.check_gizmos_closed_except(GLGizmosManager::EType::Simplify))
6461 return;
6462
6463 if (gizmos_mgr.get_current_type() == GLGizmosManager::Simplify) {
6464 // close first
6465 gizmos_mgr.open_gizmo(GLGizmosManager::EType::Simplify);
6466 }
6468}
const GLGizmosManager & get_gizmos_manager() const
Definition GLCanvas3D.hpp:1031
@ Simplify
Definition GLGizmosManager.hpp:103
bool open_gizmo(EType type)
Definition GLGizmosManager.cpp:458
GLCanvas3D * get_view3D_canvas3D()
Definition Plater.cpp:22082

References Slic3r::GUI::GLGizmosManager::check_gizmos_closed_except(), Slic3r::GUI::GLGizmosManager::get_current_type(), Slic3r::GUI::GLGizmosManager::open_gizmo(), Slic3r::GUI::plater(), and Slic3r::GUI::GLGizmosManager::Simplify.

Here is the call graph for this function:

◆ smooth_mesh()

void Slic3r::GUI::GUI::ObjectList::smooth_mesh ( )
6471{
6472 wxBusyCursor cursor;
6473 auto plater = wxGetApp().plater();
6474 if (!plater) { return; }
6475 plater->take_snapshot("smooth_mesh");
6476 std::vector<int> obj_idxs, vol_idxs;
6477 get_selection_indexes(obj_idxs, vol_idxs);
6478 auto object_idx = obj_idxs.front();
6479 ModelObject *obj{nullptr};
6480 auto show_warning_dlg = [](int cur_face_count,std::string name,bool is_part) {
6481 int limit_face_count = 1000000;
6482 if (cur_face_count > limit_face_count) {
6483 auto name_str = wxString::FromUTF8(name);
6484 auto content = wxString::Format(_L("\"%s\" will exceed 1 million faces after this subdivision, which may increase slicing time. Do you want to continue?"), name_str);
6485 WarningDialog dlg(static_cast<wxWindow *>(wxGetApp().mainframe), (is_part ? _L("Part") : _L("Object")) + " " + content, wxEmptyString, wxYES_NO);
6486 if (dlg.ShowModal() == wxID_NO) {
6487 return true;
6488 }
6489 return false;
6490 }
6491 return false;
6492 };
6493 auto show_smooth_mesh_error_dlg = [](std::string name) {
6494 auto name_str = wxString::FromUTF8(name);
6495 auto content = wxString::Format(_L("\"%s\" part's mesh contains errors. Please repair it first."), name_str);
6496 WarningDialog dlg(static_cast<wxWindow *>(wxGetApp().mainframe), content, wxEmptyString, wxOK);
6497 dlg.ShowModal();
6498 };
6499 const bool keep_painting = GUI::wxGetApp().app_config->get_bool("keep_painting");
6500 bool has_show_smooth_mesh_error_dlg = false;
6501 if (vol_idxs.empty()) {
6502 obj = object(object_idx);
6503 auto future_face_count = static_cast<int>(obj->facets_count()) * 4;
6504 if (show_warning_dlg(future_face_count, obj->name,false)) {
6505 return;
6506 }
6507 for (auto mv : obj->volumes) {
6508 bool ok;
6509 auto result_mesh = TriangleMeshDeal::smooth_triangle_mesh(mv->mesh(), ok);
6510 if (ok) {
6511 const std::optional<TriangleSelector::SavedPainting> saved_painting = keep_painting ?
6512 mv->save_painting() :
6513 std::optional<TriangleSelector::SavedPainting>{};
6514 mv->set_mesh(result_mesh);
6515 mv->restore_painting(saved_painting);
6516 mv->calculate_convex_hull();
6517 mv->invalidate_convex_hull_2d();
6518 mv->set_new_unique_id();
6519 } else {
6520 if (!has_show_smooth_mesh_error_dlg) {
6521 show_smooth_mesh_error_dlg(mv->name);
6522 has_show_smooth_mesh_error_dlg = true;
6523 }
6524 }
6525 }
6526 obj->invalidate_bounding_box();
6527 obj->ensure_on_bed();
6528 plater->changed_mesh(object_idx);
6529 } else {
6530 obj = object(obj_idxs.front());
6531 for (int vol_idx : vol_idxs) {
6532 auto mv = obj->volumes[vol_idx];
6533 auto future_face_count = static_cast<int>(mv->mesh().facets_count()) * 4;
6534 if (show_warning_dlg(future_face_count, mv->name,true)) {
6535 return;
6536 }
6537 bool ok;
6538 auto result_mesh = TriangleMeshDeal::smooth_triangle_mesh(mv->mesh(),ok);
6539 if (ok) {
6540 const std::optional<TriangleSelector::SavedPainting> saved_painting = keep_painting ?
6541 mv->save_painting() :
6542 std::optional<TriangleSelector::SavedPainting>{};
6543 mv->set_mesh(result_mesh);
6544 mv->restore_painting(saved_painting);
6545 mv->calculate_convex_hull();
6546 mv->invalidate_convex_hull_2d();
6547 mv->set_new_unique_id();
6548 } else {
6549 if (!has_show_smooth_mesh_error_dlg) {
6550 show_smooth_mesh_error_dlg(mv->name);
6551 has_show_smooth_mesh_error_dlg = true;
6552 }
6553 }
6554 }
6555 }
6556 if (obj) {
6557 obj->invalidate_bounding_box();
6558 obj->ensure_on_bed();
6559 plater->changed_mesh(object_idx);
6560 }
6561}
void take_snapshot(const std::string &snapshot_name)
Definition Plater.cpp:21281
static TriangleMesh smooth_triangle_mesh(const TriangleMesh &mesh, bool &ok)
Definition TriangleMeshDeal.cpp:11

References _L, Slic3r::ModelObject::ensure_on_bed(), Slic3r::ModelObject::facets_count(), get_selection_indexes(), Slic3r::ModelObject::invalidate_bounding_box(), Slic3r::ModelObject::name, object(), Slic3r::GUI::plater(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::TriangleMeshDeal::smooth_triangle_mesh(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ split()

void Slic3r::GUI::ObjectList::split ( )
2994{
2995 const auto item = GetSelection();
2996 const int obj_idx = get_selected_obj_idx();
2997 if (!item || obj_idx < 0)
2998 return;
2999
3000 ModelVolume* volume;
3001 if (!get_volume_by_item(item, volume)) return;
3002 DynamicPrintConfig& config = printer_config();
3003 // BBS
3004 const ConfigOptionStrings* filament_colors = config.option<ConfigOptionStrings>("filament_colour", false);
3005 const auto filament_cnt = (filament_colors == nullptr) ? size_t(1) : filament_colors->size();
3006 if (!volume->is_splittable()) {
3007 wxMessageBox(_(L("The target object contains only one part and can not be split.")));
3008 return;
3009 }
3010
3011 take_snapshot(_u8L("Split to parts"));
3012
3013 volume->split(filament_cnt, wxGetApp().app_config->get_bool("keep_painting"));
3014
3015 wxBusyCursor wait;
3016
3017 auto model_object = (*m_objects)[obj_idx];
3018
3019 auto parent = m_objects_model->GetObject(item);
3020 if (parent)
3021 m_objects_model->DeleteVolumeChildren(parent);
3022 else
3023 parent = item;
3024
3025 for (const ModelVolume* volume : model_object->volumes) {
3026 const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(parent, from_u8(volume->name),
3027 volume->type(),// is_modifier() ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART,
3028 volume->is_text(),
3029 volume->is_svg(),
3030 get_warning_icon_name(volume->mesh().stats()),
3031 volume->config.has("extruder") ? volume->config.extruder() : 0,
3032 false);
3033 // add settings to the part, if it has those
3034 add_settings_item(vol_item, &volume->config.get());
3035 }
3036
3037 model_object->input_file.clear();
3038
3039 if (parent == item)
3040 Expand(parent);
3041
3042 changed_object(obj_idx);
3043
3044 //BBS: notify partplate the modify
3045 notify_instance_updated(obj_idx);
3046
3047 update_info_items(obj_idx);
3048}
static DynamicPrintConfig & printer_config()
Definition GUI_ObjectList.cpp:131

References _, _u8L, add_settings_item(), changed_object(), config(), Slic3r::ModelVolume::config, Slic3r::ModelConfig::extruder(), Slic3r::GUI::from_u8(), Slic3r::ModelConfig::get(), get_selected_obj_idx(), get_volume_by_item(), Slic3r::GUI::get_warning_icon_name(), Slic3r::ModelConfig::has(), Slic3r::ModelVolume::is_splittable(), Slic3r::ModelVolume::is_svg(), Slic3r::ModelVolume::is_text(), L, m_objects_model, Slic3r::ModelVolume::mesh(), Slic3r::ModelVolume::name, notify_instance_updated(), Slic3r::GUI::printer_config(), Slic3r::ConfigOptionVector< T >::size(), Slic3r::ModelVolume::split(), Slic3r::TriangleMesh::stats(), Slic3r::GUI::take_snapshot(), Slic3r::ModelVolume::type(), and update_info_items().

Here is the call graph for this function:

◆ split_instances()

void Slic3r::GUI::ObjectList::split_instances ( )
6258{
6259 const Selection& selection = scene_selection();
6260 const int obj_idx = selection.get_object_idx();
6261 if (obj_idx == -1)
6262 return;
6263
6264 Plater::TakeSnapshot snapshot(wxGetApp().plater(), _u8L("Instances to Separated Objects"));
6265
6266 if (selection.is_single_full_object())
6267 {
6269 return;
6270 }
6271
6272 const int inst_idx = selection.get_instance_idx();
6273 const std::set<int> inst_idxs = inst_idx < 0 ?
6274 selection.get_instance_idxs() :
6275 std::set<int>{ inst_idx };
6276
6277 instances_to_separated_object(obj_idx, inst_idxs);
6278}

References _u8L, Slic3r::GUI::Selection::get_instance_idx(), Slic3r::GUI::Selection::get_instance_idxs(), Slic3r::GUI::Selection::get_object_idx(), instances_to_separated_object(), instances_to_separated_objects(), Slic3r::GUI::Selection::is_single_full_object(), Slic3r::GUI::plater(), and Slic3r::GUI::scene_selection().

Here is the call graph for this function:

◆ switch_to_object_process()

void Slic3r::GUI::ObjectList::switch_to_object_process ( )
2628{
2629 wxGetApp().params_panel()->switch_to_object(true);
2630
2631 // Show Dialog
2632 if (wxGetApp().app_config->get("do_not_show_object_process_tips").empty()) {
2633 TipsDialog dlg(wxGetApp().mainframe, _L("Edit Process Settings"), _L("Switch to per-object setting mode to edit process settings of selected objects."), "do_not_show_object_process_tips");
2634 dlg.ShowModal();
2635 }
2636}

References _L, and Slic3r::GUI::DPIAware< P >::ShowModal().

Here is the call graph for this function:

◆ sys_color_changed()

void Slic3r::GUI::ObjectList::sys_color_changed ( )
6601{
6602 wxGetApp().UpdateDVCDarkUI(this, true);
6603
6604 msw_rescale();
6605
6606 if (m_objects_model) { m_objects_model->sys_color_changed(); }
6607}
void msw_rescale()
Definition GUI_ObjectList.cpp:6580

References m_objects_model, and msw_rescale().

Referenced by Slic3r::GUI::Sidebar::sys_color_changed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ toggle_auto_drop()

void Slic3r::GUI::ObjectList::toggle_auto_drop ( )
7082{
7083 wxDataViewItemArray sels;
7084 GetSelections(sels);
7085 if (sels.IsEmpty())
7086 return;
7087
7088 for (auto item : sels) {
7089 ItemType type = m_objects_model->GetItemType(item);
7090 if (!(type & (itObject | itInstance)))
7091 return;
7092 }
7093
7094 const bool current_auto_drop = wxGetApp().plater()->get_selection().get_auto_drop();
7095
7096 take_snapshot("");
7097
7098 std::vector<size_t> obj_idxs;
7099 for (auto item : sels) {
7100 int obj_idx = m_objects_model->GetObjectIdByItem(item);
7101 ModelObject* obj = object(obj_idx);
7102
7103 obj_idxs.emplace_back(static_cast<size_t>(obj_idx));
7104
7105 // auto_drop is shared by all instances of an object.
7106 obj->auto_drop = !current_auto_drop;
7107 if (current_auto_drop == false)
7108 obj->ensure_on_bed();
7109 }
7110
7111 sort(obj_idxs.begin(), obj_idxs.end());
7112 obj_idxs.erase(unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
7113
7114 // update scene
7115 wxGetApp().plater()->update();
7116 wxGetApp().plater()->reload_paint_after_background_process_apply();
7117}

References Slic3r::ModelObject::auto_drop, Slic3r::ModelObject::ensure_on_bed(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, m_objects_model, object(), and Slic3r::GUI::take_snapshot().

Referenced by dispatch_shortcut().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ toggle_printable_state()

void Slic3r::GUI::ObjectList::toggle_printable_state ( )
7025{
7026 wxDataViewItemArray sels;
7027 GetSelections(sels);
7028 if (sels.IsEmpty())
7029 return;
7030
7031 wxDataViewItem frst_item = sels[0];
7032
7033 ItemType type = m_objects_model->GetItemType(frst_item);
7034 if (!(type & (itObject | itInstance)))
7035 return;
7036
7037
7038 int obj_idx = m_objects_model->GetObjectIdByItem(frst_item);
7039 int inst_idx = type == itObject ? 0 : m_objects_model->GetInstanceIdByItem(frst_item);
7040 bool printable = !object(obj_idx)->instances[inst_idx]->printable;
7041
7042 // BBS: remove snapshot name "Set Printable group", "Set Unprintable group", "Set Printable"...
7043 take_snapshot("");
7044
7045 std::vector<size_t> obj_idxs;
7046 for (auto item : sels)
7047 {
7048 type = m_objects_model->GetItemType(item);
7049 if (!(type & (itObject | itInstance)))
7050 continue;
7051
7052 obj_idx = m_objects_model->GetObjectIdByItem(item);
7053 ModelObject* obj = object(obj_idx);
7054
7055 obj_idxs.emplace_back(static_cast<size_t>(obj_idx));
7056
7057 // set printable value for selected instance/instances in object
7058 if (type == itInstance) {
7059 inst_idx = m_objects_model->GetInstanceIdByItem(item);
7060 obj->instances[m_objects_model->GetInstanceIdByItem(item)]->printable = printable;
7061 }
7062 else
7063 for (auto inst : obj->instances)
7064 inst->printable = printable;
7065
7066 // update printable state in ObjectList
7067 m_objects_model->SetObjectPrintableState(printable ? piPrintable : piUnprintable, item);
7068 }
7069
7070 sort(obj_idxs.begin(), obj_idxs.end());
7071 obj_idxs.erase(unique(obj_idxs.begin(), obj_idxs.end()), obj_idxs.end());
7072
7073 // update printable state on canvas
7074 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
7075
7076 // update scene
7077 wxGetApp().plater()->update();
7078 wxGetApp().plater()->reload_paint_after_background_process_apply();
7079}
ModelInstancePtrs instances
Definition Model.hpp:390

References Slic3r::ModelObject::instances, Slic3r::GUI::itInstance, Slic3r::GUI::itObject, m_objects_model, object(), Slic3r::GUI::piPrintable, Slic3r::GUI::piUnprintable, and Slic3r::GUI::take_snapshot().

Referenced by dispatch_shortcut(), list_manipulation(), and OnEditingStarted().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ undo()

void Slic3r::GUI::ObjectList::undo ( )
1817{
1818 wxGetApp().plater()->undo();
1819}

Referenced by dispatch_shortcut().

Here is the caller graph for this function:

◆ unselect_objects()

void Slic3r::GUI::ObjectList::unselect_objects ( )
4505{
4506 if (!GetSelection())
4507 return;
4508
4509 m_prevent_list_events = true;
4510 UnselectAll();
4512 m_prevent_list_events = false;
4513}

References m_prevent_list_events, and part_selection_changed().

Referenced by Slic3r::GUI::Plater::priv::undo_redo_to(), and Slic3r::GUI::Sidebar::update_mode().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_after_undo_redo()

void Slic3r::GUI::ObjectList::update_after_undo_redo ( )
6979{
6980 Plater::SuppressSnapshots suppress(wxGetApp().plater());
6981 //BBS: undo/redo will rebuild all the plates before
6982 //no need to notify instance to partplate
6983 reload_all_plates(false);
6984}

References Slic3r::GUI::plater(), and reload_all_plates().

Here is the call graph for this function:

◆ update_and_show_object_settings_item()

void Slic3r::GUI::ObjectList::update_and_show_object_settings_item ( )
6076{
6077 //const wxDataViewItem item = GetSelection();
6078 //if (!item) return;
6079
6080 //const wxDataViewItem& obj_item = m_objects_model->IsSettingsItem(item) ? m_objects_model->GetParent(item) : item;
6081 //select_item([this, obj_item](){ return add_settings_item(obj_item, &get_item_config(obj_item).get()); });
6083}

References part_selection_changed().

Here is the call graph for this function:

◆ update_filament_colors()

void Slic3r::GUI::ObjectList::update_filament_colors ( )
1089{
1090 m_objects_model->UpdateColumValues(colFilament);
1091 // BBS: fix color not refresh
1092 Refresh();
1093}

References Slic3r::GUI::colFilament, and m_objects_model.

Referenced by Slic3r::GUI::Sidebar::sync_ams_list(), Slic3r::GUI::Sidebar::update_mixed_filament_list(), update_objects_list_filament_column(), and update_objects_list_filament_column_when_delete_filament().

Here is the caller graph for this function:

◆ update_filament_in_config()

void Slic3r::GUI::ObjectList::update_filament_in_config ( const wxDataViewItem & item)
1146{
1148 return;
1149
1150 ModelConfig* config = nullptr;
1151 const ItemType item_type = m_objects_model->GetItemType(item);
1152 if (item_type & itObject) {
1153 const int obj_idx = m_objects_model->GetIdByItem(item);
1154 config = &(*m_objects)[obj_idx]->config;
1155 }
1156 else {
1157 const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetObject(item));
1158 if (item_type & itVolume){
1159 const int ui_volume_idx = m_objects_model->GetVolumeIdByItem(item);
1160 if (obj_idx < 0 || ui_volume_idx < 0)
1161 return;
1162 int volume_in3d_idx = m_objects_model->get_real_volume_index_in_3d(obj_idx,ui_volume_idx);
1163 config = &(*m_objects)[obj_idx]->volumes[volume_in3d_idx]->config;
1164 }
1165 else if (item_type & itLayer)
1166 config = &get_item_config(item);
1167 }
1168
1169 if (!config)
1170 return;
1171
1172 m_config = config;
1173
1174 take_snapshot(_u8L("Change Filament"));
1175
1176 const int extruder = m_objects_model->GetExtruderNumber(item);
1177 m_config->set_key_value("extruder", new ConfigOptionInt(extruder));
1178
1179 // BBS
1180 if (item_type & itObject) {
1181 const int obj_idx = m_objects_model->GetIdByItem(item);
1182 for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes) {
1183 if (mv->config.has("extruder"))
1184 mv->config.erase("extruder");
1185 }
1186 }
1187
1188 // update scene
1189 wxGetApp().plater()->update();
1190}
bool m_prevent_update_filament_in_config
Definition GUI_ObjectList.hpp:192

References _u8L, config(), get_item_config(), Slic3r::GUI::itLayer, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_config, m_objects, m_objects_model, m_prevent_update_filament_in_config, and Slic3r::GUI::take_snapshot().

Referenced by extruder_editing(), and ItemValueChanged().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_filament_values_for_items()

void Slic3r::GUI::ObjectList::update_filament_values_for_items ( const size_t filaments_count)
755{
756 for (size_t i = 0; i < m_objects->size(); ++i)
757 {
758 wxDataViewItem item = m_objects_model->GetItemById(i);
759 if (!item) continue;
760
761 auto object = (*m_objects)[i];
762 wxString extruder;
763 if (!object->config.has("extruder") || size_t(object->config.extruder()) > filaments_count) {
764 extruder = "1";
765 object->config.set_key_value("extruder", new ConfigOptionInt(1));
766 }
767 else {
768 extruder = wxString::Format("%d", object->config.extruder());
769 }
770 m_objects_model->SetExtruder(extruder, item);
771
772 static const char *keys[] = {"support_filament", "support_interface_filament"};
773 for (auto key : keys)
774 if (object->config.has(key) && object->config.opt_int(key) > filaments_count)
775 object->config.erase(key);
776
777 if (object->volumes.size() > 1) {
778 for (size_t id = 0; id < object->volumes.size(); id++) {
779 item = m_objects_model->GetItemByVolumeId(i, id);
780 if (!item) continue;
781 if (!object->volumes[id]->config.has("extruder") ||
782 size_t(object->volumes[id]->config.extruder()) > filaments_count) {
783 extruder = wxString::Format("%d", object->config.extruder());
784 // Clear the stale per-volume assignment so it falls back to the object's
785 // extruder; otherwise the out-of-range index survives. Ported from
786 // BambuStudio (STUDIO-15763).
787 object->volumes[id]->config.erase("extruder");
788 }
789 else {
790 extruder = wxString::Format("%d", object->volumes[id]->config.extruder());
791 }
792
793 m_objects_model->SetExtruder(extruder, item);
794
795 for (auto key : keys)
796 if (object->volumes[id]->config.has(key) && object->volumes[id]->config.opt_int(key) > filaments_count)
797 object->volumes[id]->config.erase(key);
798 }
799 }
800 }
801
802 // BBS
803 wxGetApp().plater()->update();
804}

References Slic3r::GUI::filaments_count(), m_objects, m_objects_model, and object().

Referenced by update_objects_list_filament_column().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_filament_values_for_items_when_delete_filament()

void Slic3r::GUI::ObjectList::update_filament_values_for_items_when_delete_filament ( const size_t filament_id,
const int replace_id = -1 )
807{
808 int replace_filament_id = replace_id == -1 ? 1 : (replace_id + 1);
809 for (size_t i = 0; i < m_objects->size(); ++i) {
810 wxDataViewItem item = m_objects_model->GetItemById(i);
811 if (!item)
812 continue;
813
814 auto object = (*m_objects)[i];
815 wxString extruder;
816 if (!object->config.has("extruder")) {
817 extruder = std::to_string(1);
818 object->config.set_key_value("extruder", new ConfigOptionInt(1));
819 }
820 else if (size_t(object->config.extruder()) == filament_id + 1) {
821 extruder = std::to_string(replace_filament_id);
822 object->config.set_key_value("extruder", new ConfigOptionInt(replace_filament_id));
823 } else {
824 int new_extruder = object->config.extruder() > filament_id ? object->config.extruder() - 1 : object->config.extruder();
825 extruder = wxString::Format("%d", new_extruder);
826 object->config.set_key_value("extruder", new ConfigOptionInt(new_extruder));
827 }
828 m_objects_model->SetExtruder(extruder, item);
829
830 static const char *keys[] = {"support_filament", "support_interface_filament"};
831 for (auto key : keys) {
832 if (object->config.has(key)) {
833 if(object->config.opt_int(key) == filament_id + 1)
834 object->config.erase(key);
835 else {
836 int new_value = object->config.opt_int(key) > filament_id ? object->config.opt_int(key) - 1 : object->config.opt_int(key);
837 object->config.set_key_value(key, new ConfigOptionInt(new_value));
838 }
839 }
840 }
841
842 //if (object->volumes.size() > 1) {
843 for (size_t id = 0; id < object->volumes.size(); id++) {
844 item = m_objects_model->GetItemByVolumeId(i, id);
845 if (!item)
846 continue;
847
848 for (auto key : keys) {
849 if (object->volumes[id]->config.has(key)) {
850 if (object->volumes[id]->config.opt_int(key) == filament_id + 1)
851 object->volumes[id]->config.erase(key);
852 else {
853 int new_value = object->volumes[id]->config.opt_int(key) > filament_id ? object->volumes[id]->config.opt_int(key) - 1 :
854 object->volumes[id]->config.opt_int(key);
855 object->config.set_key_value(key, new ConfigOptionInt(new_value));
856 }
857 }
858 }
859
860 if (!object->volumes[id]->config.has("extruder")) {
861 continue;
862 }
863 else if (size_t(object->volumes[id]->config.extruder()) == filament_id + 1) {
864 object->volumes[id]->config.set_key_value("extruder", new ConfigOptionInt(replace_filament_id));
865 } else {
866 int new_extruder = object->volumes[id]->config.extruder() > filament_id ? object->volumes[id]->config.extruder() - 1 : object->volumes[id]->config.extruder();
867 extruder = wxString::Format("%d", new_extruder);
868 object->volumes[id]->config.set_key_value("extruder", new ConfigOptionInt(new_extruder));
869 }
870
871 m_objects_model->SetExtruder(extruder, item);
872 }
873 //}
874
875 item = m_objects_model->GetItemById(i);
876 ObjectDataViewModelNode *object_node = static_cast<ObjectDataViewModelNode *>(item.GetID());
877 if (object_node->GetChildCount() == 0)
878 continue;
879
880 // update height_range
881 for (size_t i = 0; i < object_node->GetChildCount(); i++) {
882 ObjectDataViewModelNode * layer_root_node = object_node->GetNthChild(i);
883 if (layer_root_node->GetType() != ItemType::itLayerRoot)
884 continue;
885 for (size_t j = 0; j < layer_root_node->GetChildCount(); j++) {
886 ObjectDataViewModelNode * layer_node = layer_root_node->GetNthChild(j);
887 auto layer_item = wxDataViewItem((void *) layer_root_node->GetNthChild(j));
888 if (!layer_item)
889 continue;
890 auto l_iter = object->layer_config_ranges.find(layer_node->GetLayerRange());
891 if (l_iter != object->layer_config_ranges.end()) {
892 auto& layer_range_item = *(l_iter);
893 if (layer_range_item.second.has("extruder") && layer_range_item.second.option("extruder")->getInt() == filament_id + 1) {
894 int new_extruder = replace_id == -1 ? 0 : (replace_id + 1);
895 extruder = wxString::Format("%d", new_extruder);
896 layer_range_item.second.set("extruder", new_extruder);
897 } else {
898 int layer_filament_id = layer_range_item.second.option("extruder")->getInt();
899 int new_extruder = layer_filament_id > filament_id ? layer_filament_id - 1 : layer_filament_id;
900 extruder = wxString::Format("%d", new_extruder);
901 layer_range_item.second.set("extruder", new_extruder);
902 }
903 m_objects_model->SetExtruder(extruder, layer_item);
904 }
905 }
906 }
907 }
908}

References Slic3r::GUI::ObjectDataViewModelNode::GetChildCount(), Slic3r::GUI::ObjectDataViewModelNode::GetLayerRange(), Slic3r::GUI::ObjectDataViewModelNode::GetNthChild(), Slic3r::GUI::ObjectDataViewModelNode::GetType(), Slic3r::GUI::itLayerRoot, m_objects, m_objects_model, and object().

Referenced by update_objects_list_filament_column_when_delete_filament().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_info_items()

void Slic3r::GUI::ObjectList::update_info_items ( size_t obj_idx,
wxDataViewItemArray * selections = nullptr,
bool added_object = false,
bool color_mode_changed = false )
4040{
4041 // BBS
4042 if (obj_idx >= m_objects->size())
4043 return;
4044
4045 const ModelObject* model_object = (*m_objects)[obj_idx];
4046 wxDataViewItem item_obj = m_objects_model->GetItemById(obj_idx);
4047 assert(item_obj.IsOk());
4048
4049 // Cut connectors
4050 {
4051 wxDataViewItem item = m_objects_model->GetInfoItemByType(item_obj, InfoItemType::CutConnectors);
4052 bool shows = item.IsOk();
4053 bool should_show = model_object->is_cut() && model_object->has_connectors() && model_object->volumes.size() > 1;
4054
4055 if (!shows && should_show) {
4056 m_objects_model->AddInfoChild(item_obj, InfoItemType::CutConnectors);
4057 Expand(item_obj);
4058 if (added_object)
4059 wxGetApp().notification_manager()->push_updated_item_info_notification(InfoItemType::CutConnectors);
4060 } else if (shows && !should_show) {
4061 if (!selections) Unselect(item);
4062 m_objects_model->Delete(item);
4063 if (selections) {
4064 if (selections->Index(item) != wxNOT_FOUND) {
4065 // If info item was deleted from the list,
4066 // it's need to be deleted from selection array, if it was there
4067 selections->Remove(item);
4068 // Select item_obj, if info_item doesn't exist for item anymore, but was selected
4069 if (selections->Index(item_obj) == wxNOT_FOUND) selections->Add(item_obj);
4070 }
4071 } else
4072 Select(item_obj);
4073 }
4074 }
4075
4076 {
4077 ObjectDataViewModelNode* obj_node = static_cast<ObjectDataViewModelNode*>(item_obj.GetID());
4078 auto layer_data_count = model_object->layer_height_profile.get().size();
4079 update_variable_layer_obj_num(obj_node, layer_data_count);
4080 // If the length of layer_height_profile is greater than 4, variable layer height is applied
4081 m_objects_model->SetObjectVariableHeightState(layer_data_count > 4 ? hiVariable : hiUnVariable, item_obj);
4082 }
4083
4084 {
4085 bool shows = m_objects_model->IsSupportPainted(item_obj);
4086 bool should_show = printer_technology() == ptFFF
4087 && std::any_of(model_object->volumes.begin(), model_object->volumes.end(),
4088 [](const ModelVolume* mv) {
4089 return !mv->supported_facets.empty();
4090 });
4091 if (shows && !should_show) {
4092 m_objects_model->SetSupportPaintState(false, item_obj);
4093 }
4094 else if (!shows && should_show) {
4095 m_objects_model->SetSupportPaintState(true, item_obj);
4096 }
4097 if (color_mode_changed && shows) {
4098 m_objects_model->SetSupportPaintState(true, item_obj,true);
4099 }
4100 }
4101
4102 {
4103 bool shows = m_objects_model->IsColorPainted(item_obj);
4104 bool should_show = printer_technology() == ptFFF
4105 && std::any_of(model_object->volumes.begin(), model_object->volumes.end(),
4106 [](const ModelVolume* mv) {
4107 return !mv->mmu_segmentation_facets.empty();
4108 });
4109 if (shows && !should_show) {
4110 m_objects_model->SetColorPaintState(false, item_obj);
4111 }
4112 else if (!shows && should_show) {
4113 m_objects_model->SetColorPaintState(true, item_obj);
4114 }
4115 if (color_mode_changed && shows) {
4116 m_objects_model->SetColorPaintState(true, item_obj, true);
4117 }
4118 }
4119
4120 {
4121 bool shows = m_objects_model->IsSinked(item_obj);
4122 bool should_show = printer_technology() == ptFFF
4123 && wxGetApp().plater()->canvas3D()->is_object_sinking(obj_idx);
4124 if (shows && !should_show) {
4125 m_objects_model->SetSinkState(false, item_obj);
4126 }
4127 else if (!shows && should_show) {
4128 m_objects_model->SetSinkState(true, item_obj);
4129 }
4130 if (color_mode_changed && shows) {
4131 m_objects_model->SetSinkState(true, item_obj, true);
4132 }
4133 }
4134
4135 {
4136 bool shows = this->GetColumn(colSupportPaint)->IsShown();
4137 bool should_show = false;
4138 for (ModelObject* mo : *m_objects) {
4139 for (ModelVolume* mv : mo->volumes) {
4140 if (!mv->supported_facets.empty()) {
4141 should_show = true;
4142 break;
4143 }
4144 }
4145 if (should_show)
4146 break;
4147 }
4148
4149 if (shows && !should_show) {
4150 this->set_support_paint_hidden(true);
4151 }
4152 else if (!shows && should_show) {
4153 this->set_support_paint_hidden(false);
4154 }
4155 }
4156
4157 {
4158 bool shows = this->GetColumn(colColorPaint)->IsShown();
4159 bool should_show = false;
4160 for (ModelObject* mo : *m_objects) {
4161 for (ModelVolume* mv : mo->volumes) {
4162 if (!mv->mmu_segmentation_facets.empty()) {
4163 should_show = true;
4164 break;
4165 }
4166 }
4167 if (should_show)
4168 break;
4169 }
4170
4171 if (shows && !should_show) {
4172 this->set_color_paint_hidden(true);
4173 }
4174 else if (!shows && should_show) {
4175 this->set_color_paint_hidden(false);
4176 }
4177 }
4178
4179 {
4180 bool shows = this->GetColumn(colSinking)->IsShown();
4181 bool should_show = false;
4182 for (int i = 0; i < m_objects->size(); ++i) {
4183 if (wxGetApp().plater()->canvas3D()->is_object_sinking(i)) {
4184 should_show = true;
4185 break;
4186 }
4187 if (should_show)
4188 break;
4189 }
4190
4191 if (shows && !should_show) {
4192 this->set_sinking_hidden(true);
4193 }
4194 else if (!shows && should_show) {
4195 this->set_sinking_hidden(false);
4196 }
4197 }
4198}
void set_sinking_hidden(const bool hide) const
Definition GUI_ObjectList.cpp:1139
void update_variable_layer_obj_num(ObjectDataViewModelNode *obj_node, size_t layer_data_count)
Definition GUI_ObjectList.cpp:4026
void set_color_paint_hidden(const bool hide) const
Definition GUI_ObjectList.cpp:1127
void set_support_paint_hidden(const bool hide) const
Definition GUI_ObjectList.cpp:1133

References Slic3r::GUI::colColorPaint, Slic3r::GUI::colSinking, Slic3r::GUI::colSupportPaint, Slic3r::GUI::CutConnectors, Slic3r::FacetsAnnotation::empty(), Slic3r::LayerHeightProfile::get(), Slic3r::ModelObject::has_connectors(), Slic3r::GUI::hiUnVariable, Slic3r::GUI::hiVariable, Slic3r::ModelObject::is_cut(), Slic3r::ModelObject::layer_height_profile, m_objects, m_objects_model, Slic3r::ModelVolume::mmu_segmentation_facets, Slic3r::GUI::plater(), Slic3r::GUI::printer_technology(), Slic3r::ptFFF, set_color_paint_hidden(), set_sinking_hidden(), set_support_paint_hidden(), Slic3r::ModelVolume::supported_facets, update_variable_layer_obj_num(), and Slic3r::ModelObject::volumes.

Referenced by add_object_to_list(), del_subobject_item(), delete_all_connectors_for_object(), delete_from_model_and_list(), fix_through_cgal(), instances_to_separated_object(), instances_to_separated_objects(), invalidate_cut_info_for_object(), list_manipulation(), OnEditingStarted(), reorder_volumes_and_get_selection(), split(), and update_object_list_by_printer_technology().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_item_error_icon()

void Slic3r::GUI::ObjectList::update_item_error_icon ( const int obj_idx,
int vol_idx ) const
6564{
6565 auto obj = object(obj_idx);
6566 if (wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx)) {
6567 const std::string& icon_name = get_warning_icon_name(obj->get_object_stl_stats());
6568 m_objects_model->UpdateWarningIcon(obj_item, icon_name);
6569 }
6570
6571 if (vol_idx < 0)
6572 return;
6573
6574 if (wxDataViewItem vol_item = m_objects_model->GetItemByVolumeId(obj_idx, vol_idx)) {
6575 const std::string& icon_name = get_warning_icon_name(obj->volumes[vol_idx]->mesh().stats());
6576 m_objects_model->UpdateWarningIcon(vol_item, icon_name);
6577 }
6578}

References Slic3r::GUI::get_warning_icon_name(), m_objects_model, and object().

Referenced by fix_through_cgal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_lock_icons_for_model()

void Slic3r::GUI::ObjectList::update_lock_icons_for_model ( )
4478{
4479 // update the icon for cut object
4480 for (size_t obj_idx = 0; obj_idx < (*m_objects).size(); ++obj_idx)
4481 if (!(*m_objects)[obj_idx]->is_cut())
4482 m_objects_model->UpdateCutObjectIcon(m_objects_model->GetItemById(int(obj_idx)), false);
4483}

References m_objects, and m_objects_model.

Referenced by delete_all_connectors_for_object(), delete_from_model_and_list(), delete_from_model_and_list(), and invalidate_cut_info_for_object().

Here is the caller graph for this function:

◆ update_min_height()

void Slic3r::GUI::ObjectList::update_min_height ( )
379{
380 wxDataViewItemArray all_items;
381 m_objects_model->GetAllChildren(wxDataViewItem(nullptr), all_items);
382 size_t items_cnt = all_items.Count();
383#if 0
384 if (items_cnt < 7)
385 items_cnt = 7;
386 else if (items_cnt >= 15)
387 items_cnt = 15;
388#else
389 items_cnt = 8;
390#endif
391
392 if (m_items_count == items_cnt)
393 return;
394
395 m_items_count = items_cnt;
397}

References m_items_count, m_objects_model, and set_min_height().

Referenced by part_selection_changed().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_name_column_width()

void Slic3r::GUI::ObjectList::update_name_column_width ( ) const
private
1096{
1097 wxSize client_size = this->GetClientSize();
1098 bool p_vbar = this->GetParent()->HasScrollbar(wxVERTICAL);
1099 bool p_hbar = this->GetParent()->HasScrollbar(wxHORIZONTAL);
1100
1101 auto em = em_unit(const_cast<ObjectList*>(this));
1102 // BBS: walkaround for wxDataViewCtrl::HasScrollbar() does not return correct status
1103 int others_width = 0;
1104 for (int cn = colName; cn < colCount; cn++) {
1105 if (cn != colName) {
1106 if (!GetColumn(cn)->IsHidden())
1107 others_width += m_columns_width[cn];
1108 }
1109 }
1110
1111 GetColumn(colName)->SetWidth(std::max(0, client_size.x - (others_width)*em));
1112}
ObjectList(wxWindow *parent)
Definition GUI_ObjectList.cpp:193

References ObjectList(), Slic3r::GUI::colCount, Slic3r::GUI::colName, em_unit(), and m_columns_width.

Referenced by ObjectList(), set_color_paint_hidden(), set_filament_column_hidden(), set_sinking_hidden(), set_support_paint_hidden(), set_variable_height_column_hidden(), and update_variable_layer_obj_num().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_name_for_items()

void Slic3r::GUI::ObjectList::update_name_for_items ( )
948{
949 m_objects_model->UpdateItemNames();
950
951 wxGetApp().plater()->update();
952}

References m_objects_model.

Referenced by Slic3r::GUI::Plater::_calib_pa_pattern().

Here is the caller graph for this function:

◆ update_name_in_list()

void Slic3r::GUI::ObjectList::update_name_in_list ( int obj_idx,
int vol_idx ) const
1254{
1255 if (obj_idx < 0) return;
1256 wxDataViewItem item = GetSelection();
1257 if (!item || !(m_objects_model->GetItemType(item) & (itVolume | itObject)))
1258 return;
1259
1260 wxString new_name = from_u8(object(obj_idx)->volumes[vol_idx]->name);
1261 if (new_name.IsEmpty() || m_objects_model->GetName(item) == new_name)
1262 return;
1263
1264 m_objects_model->SetName(new_name, item);
1265}

References Slic3r::GUI::from_u8(), Slic3r::GUI::itObject, Slic3r::GUI::itVolume, and m_objects_model.

Referenced by anonymous_namespace{EmbossJob.cpp}::update_name_in_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_name_in_model()

void Slic3r::GUI::ObjectList::update_name_in_model ( const wxDataViewItem & item) const
1193{
1194 if (m_objects_model->GetItemType(item) & itPlate) {
1195 std::string name = m_objects_model->GetName(item).ToUTF8().data();
1196 int plate_idx = -1;
1197 const ItemType type0 = m_objects_model->GetItemType(item, plate_idx);
1198 if (plate_idx >= 0) {
1199 auto plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
1200 if (plate->get_plate_name() != name) {
1201 plate->set_plate_name(name);
1202 }
1203 m_objects_model->SetCurSelectedPlateFullName(plate_idx, name);
1204 }
1205 return;
1206 }
1207
1208 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
1209 if (obj_idx < 0) return;
1210 const int volume_id = m_objects_model->GetVolumeIdByItem(item);
1211
1212 take_snapshot(volume_id < 0 ? _u8L("Rename Object") : _u8L("Rename Part"));
1213
1214 ModelObject* obj = object(obj_idx);
1215 if (m_objects_model->GetItemType(item) & itObject) {
1216 std::string name = m_objects_model->GetName(item).ToUTF8().data();
1217 if (obj->name != name) {
1218 const std::string previous_name = obj->name;
1219 obj->name = name;
1220 // if object has just one volume, rename this volume too
1221 if (obj->volumes.size() == 1)
1222 obj->volumes[0]->name = obj->name;
1224
1225 LifecycleEventContext ctx;
1226 ctx.name = name;
1227 ctx.previous_name = previous_name;
1228 ctx.id = std::to_string(obj->id().id);
1229 ctx.index = obj_idx;
1230 ctx.source = "object";
1232 }
1233 return;
1234 }
1235
1236 if (volume_id < 0) return;
1237 std::string name = m_objects_model->GetName(item).ToUTF8().data();
1238 if (obj->volumes[volume_id]->name == name)
1239 return;
1240
1241 const std::string previous_name = obj->volumes[volume_id]->name;
1242 obj->volumes[volume_id]->name = name;
1243
1244 LifecycleEventContext ctx;
1245 ctx.name = name;
1246 ctx.previous_name = previous_name;
1247 ctx.id = std::to_string(obj->volumes[volume_id]->id().id);
1248 ctx.index = volume_id;
1249 ctx.source = "volume";
1251}
@ ObjectRenamed
Definition LifecycleEvents.hpp:40

References _u8L, Slic3r::fire_lifecycle_event(), Slic3r::LifecycleEventContext::id, Slic3r::ObjectBase::id(), Slic3r::ObjectID::id, Slic3r::LifecycleEventContext::index, Slic3r::GUI::itObject, Slic3r::GUI::itPlate, m_objects_model, Slic3r::LifecycleEventContext::name, Slic3r::ModelObject::name, object(), Slic3r::ObjectRenamed, Slic3r::LifecycleEventContext::previous_name, Slic3r::save_object_mesh(), Slic3r::LifecycleEventContext::source, Slic3r::GUI::take_snapshot(), and Slic3r::ModelObject::volumes.

Referenced by ItemValueChanged(), and rename_item().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_object_list_by_printer_technology()

void Slic3r::GUI::ObjectList::update_object_list_by_printer_technology ( )
6125{
6127 wxDataViewItemArray sel;
6128 GetSelections(sel); // stash selection
6129
6130 wxDataViewItemArray object_items;
6131 m_objects_model->GetChildren(wxDataViewItem(nullptr), object_items);
6132
6133 for (auto& object_item : object_items) {
6134 // update custom supports info
6135 update_info_items(m_objects_model->GetObjectIdByItem(object_item), &sel);
6136
6137 // Update Settings Item for object
6138 update_settings_item_and_selection(object_item, sel);
6139
6140 // Update settings for Volumes
6141 wxDataViewItemArray all_object_subitems;
6142 m_objects_model->GetChildren(object_item, all_object_subitems);
6143 for (auto item : all_object_subitems)
6144 if (m_objects_model->GetItemType(item) & itVolume)
6145 // update settings for volume
6147
6148 // Update Layers Items
6149 wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item);
6150 if (!layers_item)
6151 layers_item = add_layer_root_item(object_item);
6152 else if (printer_technology() == ptSLA) {
6153 // If layers root item will be deleted from the list, so
6154 // it's need to be deleted from selection array, if it was there
6155 wxDataViewItemArray del_items;
6156 bool some_layers_was_selected = false;
6157 m_objects_model->GetAllChildren(layers_item, del_items);
6158 for (auto& del_item:del_items)
6159 if (sel.Index(del_item) != wxNOT_FOUND) {
6160 some_layers_was_selected = true;
6161 sel.Remove(del_item);
6162 }
6163 if (sel.Index(layers_item) != wxNOT_FOUND) {
6164 some_layers_was_selected = true;
6165 sel.Remove(layers_item);
6166 }
6167
6168 // delete all "layers" items
6169 m_objects_model->Delete(layers_item);
6170
6171 // Select object_item, if layers_item doesn't exist for item anymore, but was some of layer items was/were selected
6172 if (some_layers_was_selected)
6173 sel.Add(object_item);
6174 }
6175 else {
6176 wxDataViewItemArray all_obj_layers;
6177 m_objects_model->GetChildren(layers_item, all_obj_layers);
6178
6179 for (auto item : all_obj_layers)
6180 // update settings for layer
6182 }
6183 }
6184
6185 // restore selection:
6186 SetSelections(sel);
6188}
void update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray &selections)
Definition GUI_ObjectList.cpp:6086

References add_layer_root_item(), Slic3r::GUI::itVolume, m_objects_model, m_prevent_canvas_selection_update, Slic3r::GUI::printer_technology(), Slic3r::ptSLA, update_info_items(), and update_settings_item_and_selection().

Here is the call graph for this function:

◆ update_objects_list_filament_column()

void Slic3r::GUI::ObjectList::update_objects_list_filament_column ( size_t filaments_count)
1047{
1048 assert(filaments_count >= 1);
1049
1050 if (printer_technology() == ptSLA)
1051 filaments_count = 1;
1052
1054
1055 // BBS: update extruder values even when filaments_count is 1, because it may be reduced from value greater than 1
1056 if (m_objects)
1058
1060
1061 // set show/hide for this column
1063 //a workaround for a wrong last column width updating under OSX
1064 auto em = em_unit(this);
1065 GetColumn(colEditing)->SetWidth(m_columns_width[colEditing]*em);
1066
1068}
void update_filament_values_for_items(const size_t filaments_count)
Definition GUI_ObjectList.cpp:754
void set_filament_column_hidden(const bool hide) const
Definition GUI_ObjectList.cpp:1114
void update_filament_colors()
Definition GUI_ObjectList.cpp:1088

References Slic3r::GUI::colEditing, em_unit(), Slic3r::GUI::filaments_count(), m_columns_width, m_objects, m_prevent_update_filament_in_config, Slic3r::GUI::printer_technology(), Slic3r::ptSLA, set_filament_column_hidden(), update_filament_colors(), and update_filament_values_for_items().

Referenced by Slic3r::GUI::Plater::on_filament_count_change(), and Slic3r::GUI::Sidebar::update_mixed_filament_list().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_objects_list_filament_column_when_delete_filament()

void Slic3r::GUI::ObjectList::update_objects_list_filament_column_when_delete_filament ( size_t filament_id,
size_t filaments_count,
int replace_filament_id = -1 )
1071{
1073
1074 // BBS: update extruder values even when filaments_count is 1, because it may be reduced from value greater than 1
1075 if (m_objects)
1076 update_filament_values_for_items_when_delete_filament(filament_id, replace_filament_id);
1077
1079
1080 // set show/hide for this column
1082 // a workaround for a wrong last column width updating under OSX
1083 GetColumn(colEditing)->SetWidth(25);
1084
1086}
void update_filament_values_for_items_when_delete_filament(const size_t filament_id, const int replace_id=-1)
Definition GUI_ObjectList.cpp:806

References Slic3r::GUI::colEditing, Slic3r::GUI::filaments_count(), m_objects, m_prevent_update_filament_in_config, set_filament_column_hidden(), update_filament_colors(), and update_filament_values_for_items_when_delete_filament().

Referenced by Slic3r::GUI::Plater::on_filaments_delete().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_plate_values_for_items()

void Slic3r::GUI::ObjectList::update_plate_values_for_items ( )
912{
913#ifdef __WXOSX__
914 AssociateModel(nullptr);
915#endif
916 PartPlateList& list = wxGetApp().plater()->get_partplate_list();
917 for (size_t i = 0; i < m_objects->size(); ++i)
918 {
919 wxDataViewItem item = m_objects_model->GetItemById(i);
920 if (!item) continue;
921
922 int plate_idx = list.find_instance_belongs(i, 0);
923 wxDataViewItem old_parent = m_objects_model->GetParent(item);
924 ObjectDataViewModelNode* old_parent_node = (ObjectDataViewModelNode*)old_parent.GetID();
925 int old_plate_idx = old_parent_node->GetPlateIdx();
926 if (plate_idx == old_plate_idx)
927 continue;
928
929 // hotfix for wxDataViewCtrl selection not updated after wxDataViewModel::ItemDeleted()
930 Unselect(item);
931
932 bool is_old_parent_expanded = IsExpanded(old_parent);
933 bool is_expanded = IsExpanded(item);
934 m_objects_model->OnPlateChange(plate_idx, item);
935 if (is_old_parent_expanded)
936 Expand(old_parent);
937 ExpandAncestors(item);
938 Expand(item);
939 Select(item);
940 }
941#ifdef __WXOSX__
942 AssociateModel(m_objects_model);
943#endif
944}

References Slic3r::GUI::PartPlateList::find_instance_belongs(), Slic3r::GUI::ObjectDataViewModelNode::GetPlateIdx(), m_objects, and m_objects_model.

Here is the call graph for this function:

◆ update_printable_state()

void Slic3r::GUI::ObjectList::update_printable_state ( int obj_idx,
int instance_idx )
7014{
7015 ModelObject* object = (*m_objects)[obj_idx];
7016
7017 const PrintIndicator printable = object->instances[instance_idx]->printable ? piPrintable : piUnprintable;
7018 if (object->instances.size() == 1)
7019 instance_idx = -1;
7020
7021 m_objects_model->SetPrintableState(printable, obj_idx, instance_idx);
7022}
PrintIndicator
Definition ObjectDataViewModel.hpp:62

References m_objects_model, object(), Slic3r::GUI::piPrintable, and Slic3r::GUI::piUnprintable.

Here is the call graph for this function:

◆ update_selection_mode()

void Slic3r::GUI::ObjectList::update_selection_mode ( )
5405{
5407 // All items are unselected
5408 if (!GetSelection())
5409 {
5410 m_last_selected_item = wxDataViewItem(nullptr);
5412 return;
5413 }
5414
5415 const ItemType type = m_objects_model->GetItemType(GetSelection());
5417 type & itLayer ? smLayer :
5418 type & itVolume ? smVolume : smInstance;
5419}

References Slic3r::GUI::itLayer, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, m_last_selected_item, m_objects_model, m_selected_layers_range_idx, m_selection_mode, smInstance, smLayer, smUndef, and smVolume.

Referenced by fix_multiselection_conflicts().

Here is the caller graph for this function:

◆ update_selections()

void Slic3r::GUI::ObjectList::update_selections ( )
4933{
4934 if (wxGetApp().is_closing())
4935 return;
4936
4937 const Selection& selection = scene_selection();
4938 wxDataViewItemArray sels;
4939
4940#if 0
4941 if (m_selection_mode == smUndef) {
4942 PartPlate* pp = wxGetApp().plater()->get_partplate_list().get_selected_plate();
4943 assert(pp != nullptr);
4944 wxDataViewItem sel_plate = m_objects_model->GetItemByPlateId(pp->get_index());
4945 sels.Add(sel_plate);
4946 select_items(sels);
4947
4948 // Scroll selected Item in the middle of an object list
4950 return;
4951 }
4952#endif
4953
4956
4957 // We doesn't update selection if itSettings | itLayerRoot | itLayer Item for the current object/part is selected
4958 if (GetSelectedItemsCount() == 1 && m_objects_model->GetItemType(GetSelection()) & (itSettings | itLayerRoot | itLayer))
4959 {
4960 const auto item = GetSelection();
4961 if (selection.is_single_full_object()) {
4962 if (m_objects_model->GetItemType(m_objects_model->GetParent(item)) & itObject &&
4963 m_objects_model->GetObjectIdByItem(item) == selection.get_object_idx() )
4964 return;
4965 sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
4966 }
4967 else if (selection.is_single_volume() || selection.is_any_modifier()) {
4968 const auto gl_vol = selection.get_first_volume();
4969 if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
4970 return;
4971 }
4972 // but if there is selected only one of several instances by context menu,
4973 // then select this instance in ObjectList
4974 else if (selection.is_single_full_instance())
4975 sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), selection.get_instance_idx()));
4976 // Can be the case, when we have selected itSettings | itLayerRoot | itLayer in the ObjectList and selected object/instance in the Scene
4977 // and then select some object/instance in 3DScene using Ctrt+left click
4978 else {
4979 // Unselect all items in ObjectList
4980 m_last_selected_item = wxDataViewItem(nullptr);
4981 m_prevent_list_events = true;
4982 UnselectAll();
4983 m_prevent_list_events = false;
4984 // call this function again to update selection from the canvas
4986 return;
4987 }
4988 }
4989 else if (selection.is_single_full_object() || selection.is_multiple_full_object())
4990 {
4991 const Selection::ObjectIdxsToInstanceIdxsMap& objects_content = selection.get_content();
4992 // it's impossible to select Settings, Layer or LayerRoot for several objects
4993 if (!selection.is_multiple_full_object() && (m_selection_mode & (smSettings | smLayer | smLayerRoot)))
4994 {
4995 auto obj_idx = objects_content.begin()->first;
4996 wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx);
4998 {
5000 sels.Add(m_objects_model->GetSettingsItem(obj_item));
5001 else
5002 sels.Add(m_objects_model->GetSettingsItem(m_objects_model->GetItemByLayerId(obj_idx, m_selected_layers_range_idx)));
5003 }
5004 else if (m_selection_mode & smLayerRoot)
5005 sels.Add(m_objects_model->GetLayerRootItem(obj_item));
5006 else if (m_selection_mode & smLayer) {
5008 sels.Add(m_objects_model->GetItemByLayerId(obj_idx, m_selected_layers_range_idx));
5009 else
5010 sels.Add(obj_item);
5011 }
5012 }
5013 else {
5014 for (const auto& object : objects_content) {
5015 if (object.second.size() == 1) // object with 1 instance
5016 sels.Add(m_objects_model->GetItemById(object.first));
5017 else if (object.second.size() > 1) // object with several instances
5018 {
5019 wxDataViewItemArray current_sels;
5020 GetSelections(current_sels);
5021 const wxDataViewItem frst_inst_item = m_objects_model->GetItemByInstanceId(object.first, 0);
5022
5023 bool root_is_selected = false;
5024 for (const auto& item:current_sels)
5025 if (item == m_objects_model->GetParent(frst_inst_item) ||
5026 item == m_objects_model->GetObject(frst_inst_item)) {
5027 root_is_selected = true;
5028 sels.Add(item);
5029 break;
5030 }
5031 if (root_is_selected)
5032 continue;
5033
5034 const Selection::InstanceIdxsList& instances = object.second;
5035 for (const auto& inst : instances)
5036 sels.Add(m_objects_model->GetItemByInstanceId(object.first, inst));
5037 }
5038 } }
5039 }
5040 else if (selection.is_any_volume() || selection.is_any_modifier())
5041 {
5043 {
5044 const auto gl_vol = selection.get_first_volume();
5045 if (gl_vol->volume_idx() >= 0) {
5046 // Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
5047 // are not associated with ModelVolumes, but they are temporarily generated by the backend
5048 // (for example, SLA supports or SLA pad).
5049 wxDataViewItem vol_item = m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx());
5050 sels.Add(m_objects_model->GetSettingsItem(vol_item));
5051 }
5052 }
5053 else {
5054 for (auto idx : selection.get_volume_idxs()) {
5055 const auto gl_vol = selection.get_volume(idx);
5056 if (gl_vol->volume_idx() >= 0) {
5057 // Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
5058 // are not associated with ModelVolumes, but they are temporarily generated by the backend
5059 // (for example, SLA supports or SLA pad).
5060 int obj_idx = gl_vol->object_idx();
5061 int vol_idx = gl_vol->volume_idx();
5062 assert(obj_idx >= 0 && vol_idx >= 0);
5063 if (object(obj_idx)->volumes[vol_idx]->is_cut_connector())
5064 sels.Add(m_objects_model->GetInfoItemByType(m_objects_model->GetItemById(obj_idx), InfoItemType::CutConnectors));
5065 else {
5066 vol_idx = m_objects_model->get_real_volume_index_in_ui(obj_idx,vol_idx);
5067 sels.Add(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx));
5068 }
5069 }
5070 }
5072 }
5073 else if (selection.is_single_full_instance() || selection.is_multiple_full_instance())
5074 {
5075 for (auto idx : selection.get_instance_idxs()) {
5076 sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx));
5077 }
5078 }
5079 else if (selection.is_mixed())
5080 {
5081 const Selection::ObjectIdxsToInstanceIdxsMap& objects_content_list = selection.get_content();
5082
5083 for (auto idx : selection.get_volume_idxs()) {
5084 const auto gl_vol = selection.get_volume(idx);
5085 const auto& glv_obj_idx = gl_vol->object_idx();
5086 const auto& glv_ins_idx = gl_vol->instance_idx();
5087
5088 bool is_selected = false;
5089
5090 for (auto obj_ins : objects_content_list) {
5091 if (obj_ins.first == glv_obj_idx) {
5092 if (obj_ins.second.find(glv_ins_idx) != obj_ins.second.end() &&
5093 !selection.is_from_single_instance() ) // a case when volumes of different types are selected
5094 {
5095 if (glv_ins_idx == 0 && (*m_objects)[glv_obj_idx]->instances.size() == 1)
5096 sels.Add(m_objects_model->GetItemById(glv_obj_idx));
5097 else
5098 sels.Add(m_objects_model->GetItemByInstanceId(glv_obj_idx, glv_ins_idx));
5099
5100 is_selected = true;
5101 break;
5102 }
5103 }
5104 }
5105
5106 if (is_selected)
5107 continue;
5108
5109 const auto& glv_vol_idx = gl_vol->volume_idx();
5110 if (glv_vol_idx == 0 && (*m_objects)[glv_obj_idx]->volumes.size() == 1)
5111 sels.Add(m_objects_model->GetItemById(glv_obj_idx));
5112 else
5113 sels.Add(m_objects_model->GetItemByVolumeId(glv_obj_idx, glv_vol_idx));
5114 }
5115 }
5116
5117 if (sels.size() == 0 || m_selection_mode & smSettings)
5119
5121 m_prevent_list_events = true;
5122
5123 // If some part is selected, unselect all items except of selected parts of the current object
5124 UnselectAll();
5125 SetSelections(sels);
5126
5127 m_prevent_list_events = false;
5128
5129 // update object selection on Plater
5132
5133 // to update the toolbar and info sizer
5134 if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject || is_connectors_item_selected()) {
5135 auto event = SimpleEvent(EVT_OBJ_LIST_OBJECT_SELECT);
5136 event.SetEventObject(this);
5137 wxPostEvent(this, event);
5138 }
5140 }
5141 else {
5142 select_items(sels);
5143
5144 // Scroll selected Item in the middle of an object list
5146 }
5147}
bool is_selected(const ItemType type) const
Definition GUI_ObjectList.cpp:4891
std::map< int, InstanceIdxsList > ObjectIdxsToInstanceIdxsMap
Definition Selection.hpp:111
std::set< int > InstanceIdxsList
Definition Selection.hpp:110

References Slic3r::GUI::CutConnectors, ensure_current_item_visible(), fix_cut_selection(), Slic3r::GUI::Selection::get_content(), Slic3r::GUI::Selection::get_first_volume(), Slic3r::GUI::PartPlate::get_index(), Slic3r::GUI::Selection::get_instance_idx(), Slic3r::GUI::Selection::get_instance_idxs(), Slic3r::GUI::Selection::get_object_idx(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::GUI::Selection::is_any_modifier(), Slic3r::GUI::Selection::is_any_volume(), is_connectors_item_selected(), Slic3r::GUI::Selection::is_from_single_instance(), Slic3r::GUI::Selection::is_mixed(), Slic3r::GUI::Selection::is_multiple_full_instance(), Slic3r::GUI::Selection::is_multiple_full_object(), is_selected(), Slic3r::GUI::Selection::is_single_full_instance(), Slic3r::GUI::Selection::is_single_full_object(), Slic3r::GUI::Selection::is_single_volume(), Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itObject, Slic3r::GUI::itSettings, m_last_selected_item, m_objects, m_objects_model, m_prevent_canvas_selection_update, m_prevent_list_events, m_selected_layers_range_idx, m_selection_mode, Slic3r::GLVolume::object_idx(), part_selection_changed(), Slic3r::GUI::scene_selection(), select_items(), smInstance, smLayer, smLayerRoot, smSettings, smUndef, smVolume, update_selections(), and update_selections_on_canvas().

Referenced by Slic3r::GUI::Plater::priv::on_select_preset(), reload_all_plates(), Slic3r::GUI::Plater::priv::remove_curr_plate_all(), Slic3r::GUI::Plater::priv::select_all(), Slic3r::GUI::Plater::priv::select_curr_plate_all(), Slic3r::GUI::Sidebar::update_mode(), and update_selections().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_selections_on_canvas()

void Slic3r::GUI::ObjectList::update_selections_on_canvas ( )
5150{
5151 auto canvas_type = wxGetApp().plater()->get_current_canvas3D()->get_canvas_type();
5152 GLCanvas3D* canvas = canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView ? wxGetApp().plater()->get_current_canvas3D() : wxGetApp().plater()->get_view3D_canvas3D();
5153 Selection& selection = canvas->get_selection();
5154
5155 const int sel_cnt = GetSelectedItemsCount();
5156 if (sel_cnt == 0) {
5157 selection.remove_all();
5158 if (canvas_type != GLCanvas3D::ECanvasType::CanvasPreview)
5159 wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
5160 return;
5161 }
5162
5163 std::vector<unsigned int> volume_idxs;
5165 bool single_selection = sel_cnt == 1;
5166 auto add_to_selection = [this, &volume_idxs, &single_selection](const wxDataViewItem& item, const Selection& selection, int instance_idx, Selection::EMode& mode)
5167 {
5168 const ItemType& type = m_objects_model->GetItemType(item);
5169 const int obj_idx = m_objects_model->GetObjectIdByItem(item);
5170
5171 if (type == itVolume) {
5172 int vol_idx = m_objects_model->GetVolumeIdByItem(item);
5173 vol_idx = m_objects_model->get_real_volume_index_in_3d(obj_idx,vol_idx);
5174 std::vector<unsigned int> idxs = selection.get_volume_idxs_from_volume(obj_idx, std::max(instance_idx, 0), vol_idx);
5175 volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
5176 }
5177 else if (type == itInstance) {
5178 const int inst_idx = m_objects_model->GetInstanceIdByItem(item);
5179 mode = Selection::Instance;
5180 std::vector<unsigned int> idxs = selection.get_volume_idxs_from_instance(obj_idx, inst_idx);
5181 volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
5182 }
5183 else if (type == itInfo) {
5184 if (m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors) {
5185 mode = Selection::Volume;
5186
5187 // When selecting CutConnectors info item, select all object volumes, which are marked as a connector
5188 const ModelObject *obj = object(obj_idx);
5189 for (unsigned int vol_idx = 0; vol_idx < obj->volumes.size(); vol_idx++)
5190 if (obj->volumes[vol_idx]->is_cut_connector()) {
5191 std::vector<unsigned int> idxs = selection.get_volume_idxs_from_volume(obj_idx, std::max(instance_idx, 0), vol_idx);
5192 volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
5193 }
5194 } else {
5195 // When selecting an info item, select one instance of the
5196 // respective object - a gizmo may want to be opened.
5197 int inst_idx = selection.get_instance_idx();
5198 int scene_obj_idx = selection.get_object_idx();
5199 mode = Selection::Instance;
5200 // select first instance, unless an instance of the object is already selected
5201 if (scene_obj_idx == -1 || inst_idx == -1 || scene_obj_idx != obj_idx) inst_idx = 0;
5202 std::vector<unsigned int> idxs = selection.get_volume_idxs_from_instance(obj_idx, inst_idx);
5203 volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
5204 }
5205 }
5206 else
5207 {
5208 mode = Selection::Instance;
5209 single_selection &= (obj_idx != selection.get_object_idx());
5210 std::vector<unsigned int> idxs = selection.get_volume_idxs_from_object(obj_idx);
5211 volume_idxs.insert(volume_idxs.end(), idxs.begin(), idxs.end());
5212 }
5213 };
5214
5215 // stores current instance idx before to clear the selection
5216 int instance_idx = selection.get_instance_idx();
5217
5218 if (sel_cnt == 1) {
5219 wxDataViewItem item = GetSelection();
5220 if (m_objects_model->GetInfoItemType(item) == InfoItemType::CutConnectors)
5221 selection.remove_all();
5222
5223 if (m_objects_model->GetItemType(item) & (itSettings | itInstanceRoot | itLayerRoot | itLayer))
5224 add_to_selection(m_objects_model->GetParent(item), selection, instance_idx, mode);
5225 else
5226 add_to_selection(item, selection, instance_idx, mode);
5227 }
5228 else
5229 {
5230 wxDataViewItemArray sels;
5231 GetSelections(sels);
5232
5233 // clear selection before adding new elements
5234 selection.clear(); //OR remove_all()?
5235
5236 for (auto item : sels)
5237 {
5238 add_to_selection(item, selection, instance_idx, mode);
5239 }
5240 }
5241
5242 if (selection.contains_all_volumes(volume_idxs))
5243 {
5244 // remove
5245 volume_idxs = selection.get_missing_volume_idxs_from(volume_idxs);
5246 if (volume_idxs.size() > 0)
5247 {
5248 Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Remove selected from list", UndoRedo::SnapshotType::Selection);
5249 selection.remove_volumes(mode, volume_idxs);
5250 }
5251 }
5252 else
5253 {
5254 // add
5255 // to avoid lost of some volumes in selection
5256 // check non-selected volumes only if selection mode wasn't changed
5257 // OR there is no single selection
5258 if (selection.get_mode() == mode || !single_selection)
5259 volume_idxs = selection.get_unselected_volume_idxs_from(volume_idxs);
5260 Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Add selected to list", UndoRedo::SnapshotType::Selection);
5261 selection.add_volumes(mode, volume_idxs, single_selection);
5262 }
5263
5264 if (canvas_type != GLCanvas3D::ECanvasType::CanvasPreview)
5265 wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
5266 wxGetApp().plater()->canvas3D()->render();
5267}
EMode
Definition Selection.hpp:52
@ Instance
Definition Selection.hpp:54
@ Volume
Definition Selection.hpp:53
@ Selection
Definition UndoRedo.hpp:38

References Slic3r::GUI::Selection::add_volumes(), Slic3r::GUI::GLCanvas3D::CanvasAssembleView, Slic3r::GUI::GLCanvas3D::CanvasPreview, Slic3r::GUI::Selection::clear(), Slic3r::GUI::Selection::contains_all_volumes(), Slic3r::GUI::CutConnectors, Slic3r::GUI::Selection::get_instance_idx(), Slic3r::GUI::Selection::get_missing_volume_idxs_from(), Slic3r::GUI::Selection::get_mode(), Slic3r::GUI::Selection::get_object_idx(), Slic3r::GUI::GLCanvas3D::get_selection(), Slic3r::GUI::Selection::get_unselected_volume_idxs_from(), Slic3r::GUI::Selection::get_volume_idxs_from_instance(), Slic3r::GUI::Selection::get_volume_idxs_from_object(), Slic3r::GUI::Selection::get_volume_idxs_from_volume(), Slic3r::GUI::Selection::Instance, Slic3r::GUI::itInfo, Slic3r::GUI::itInstance, Slic3r::GUI::itInstanceRoot, Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itSettings, Slic3r::GUI::itVolume, m_objects_model, object(), Slic3r::GUI::plater(), Slic3r::GUI::Selection::remove_all(), Slic3r::GUI::Selection::remove_volumes(), Slic3r::UndoRedo::Selection, Slic3r::GUI::Selection::Volume, and Slic3r::ModelObject::volumes.

Referenced by boolean(), merge(), remove(), selection_changed(), show_settings(), and update_selections().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_settings_item_and_selection()

void Slic3r::GUI::ObjectList::update_settings_item_and_selection ( wxDataViewItem item,
wxDataViewItemArray & selections )
6087{
6088 const wxDataViewItem old_settings_item = m_objects_model->GetSettingsItem(item);
6089 const wxDataViewItem new_settings_item = add_settings_item(item, &get_item_config(item).get());
6090
6091 if (!new_settings_item && old_settings_item)
6092 m_objects_model->Delete(old_settings_item);
6093
6094 // if ols settings item was is selected area
6095 if (selections.Index(old_settings_item) != wxNOT_FOUND)
6096 {
6097 // If settings item was just updated
6098 if (old_settings_item == new_settings_item)
6099 {
6100 Sidebar& panel = wxGetApp().sidebar();
6101 panel.Freeze();
6102
6103 // update settings list
6104 wxGetApp().obj_settings()->UpdateAndShow(true);
6105
6106 panel.Layout();
6107 panel.Thaw();
6108 }
6109 else
6110 // If settings item was deleted from the list,
6111 // it's need to be deleted from selection array, if it was there
6112 {
6113 selections.Remove(old_settings_item);
6114
6115 // Select item, if settings_item doesn't exist for item anymore, but was selected
6116 if (selections.Index(item) == wxNOT_FOUND) {
6117 selections.Add(item);
6118 select_item(item); // to correct update of the SettingsList and ManipulationPanel sizers
6119 }
6120 }
6121 }
6122}

References add_settings_item(), get_item_config(), m_objects_model, Slic3r::GUI::Sidebar::obj_settings(), select_item(), and Slic3r::GUI::ObjectSettings::UpdateAndShow().

Referenced by update_object_list_by_printer_technology().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ update_variable_layer_obj_num()

void Slic3r::GUI::ObjectList::update_variable_layer_obj_num ( ObjectDataViewModelNode * obj_node,
size_t layer_data_count )
4026 {
4027 if (obj_node){
4028 if (obj_node->IsVaribaleHeight() == hiVariable && layer_data_count <= 4){
4030 }
4031 else if (obj_node->IsVaribaleHeight() == hiUnVariable && layer_data_count > 4){
4033 }
4034 GetColumn(colHeight)->SetHidden(m_variable_layer_obj_num == 0);
4036 }
4037}

References Slic3r::GUI::colHeight, Slic3r::GUI::hiUnVariable, Slic3r::GUI::hiVariable, Slic3r::GUI::ObjectDataViewModelNode::IsVaribaleHeight(), m_variable_layer_obj_num, and update_name_column_width().

Referenced by update_info_items().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_bmp_vector

std::vector<wxBitmap*> Slic3r::GUI::ObjectList::m_bmp_vector
private

◆ m_clipboard

◆ m_columns_width

std::vector<int> Slic3r::GUI::ObjectList::m_columns_width
private

◆ m_config

◆ m_dragged_data

struct Slic3r::GUI::ObjectList::dragged_item_data Slic3r::GUI::ObjectList::m_dragged_data
private

Referenced by can_drop(), OnBeginDrag(), and OnDrop().

◆ m_extruder_editor

BitmapComboBox* Slic3r::GUI::ObjectList::m_extruder_editor { nullptr }
private
182{ nullptr };

Referenced by extruder_editing(), list_manipulation(), and part_selection_changed().

◆ m_items_count

size_t Slic3r::GUI::ObjectList::m_items_count { size_t(-1) }
private
218{ size_t(-1) };

Referenced by set_min_height(), and update_min_height().

◆ m_last_selected_item

wxDataViewItem Slic3r::GUI::ObjectList::m_last_selected_item {nullptr}
private

◆ m_last_size

wxSize Slic3r::GUI::ObjectList::m_last_size
private

Referenced by ObjectList().

◆ m_objects

◆ m_objects_model

ObjectDataViewModel* Slic3r::GUI::ObjectList::m_objects_model { nullptr }
private
177{ nullptr };

Referenced by ~ObjectList(), add_category_to_settings_from_frequent(), add_category_to_settings_from_selection(), add_layer_item(), add_layer_range_after_current(), add_layer_root_item(), add_object_to_list(), add_objects_to_list(), add_settings_item(), add_volumes_to_object_in_list(), assembly_plate_object_name(), boolean(), can_drop(), can_merge_to_multipart_object(), can_paste_settings_into_list(), check_last_selection(), copy_layers_to_clipboard(), copy_settings_to_clipboard(), copy_to_clipboard(), create_objects_ctrl(), decrease_object_instances(), del_layer_range(), del_settings_from_config(), del_subobject_from_object(), del_subobject_item(), delete_all_connectors_for_object(), delete_all_connectors_for_selection(), delete_from_model_and_list(), delete_instance_from_list(), delete_object_from_list(), delete_object_from_list(), delete_volume_from_list(), edit_layer_range(), enable_layers_editing(), extruder_editing(), fix_cut_selection(), fix_multiselection_conflicts(), get_item_config(), get_mesh_errors_info(), get_selected_item_indexes(), get_selected_layers_range_idx(), get_selected_model_volume(), get_selected_obj_idx(), get_selection_indexes(), get_volume_by_item(), GetModel(), has_selected_cut_object(), increase_object_instances(), init(), invalidate_cut_info_for_selection(), is_connectors_item_selected(), is_connectors_item_selected(), is_selected(), is_splittable(), ItemValueChanged(), layers_editing(), list_manipulation(), load_subobject(), merge(), msw_rescale(), object_config_options_changed(), on_plate_added(), on_plate_deleted(), on_plate_selected(), OnBeginDrag(), OnDrop(), OnEditingDone(), OnStartEditing(), part_selection_changed(), paste_layers_into_list(), paste_objects_into_list(), paste_settings_into_list(), printable_state_changed(), reload_all_plates(), remove(), rename_item(), select_item_all_children(), select_items(), select_object_item(), selected_instances_of_same_object(), selection_changed(), set_extruder_for_selected_items(), set_tooltip_for_item(), set_volume_type(), show_context_menu(), split(), sys_color_changed(), toggle_auto_drop(), toggle_printable_state(), update_filament_colors(), update_filament_in_config(), update_filament_values_for_items(), update_filament_values_for_items_when_delete_filament(), update_info_items(), update_item_error_icon(), update_lock_icons_for_model(), update_min_height(), update_name_for_items(), update_name_in_list(), update_name_in_model(), update_object_list_by_printer_technology(), update_plate_values_for_items(), update_printable_state(), update_selection_mode(), update_selections(), update_selections_on_canvas(), and update_settings_item_and_selection().

◆ m_prevent_canvas_selection_update

bool Slic3r::GUI::ObjectList::m_prevent_canvas_selection_update = false
private

◆ m_prevent_list_events

◆ m_prevent_list_manipulation

bool Slic3r::GUI::ObjectList::m_prevent_list_manipulation = false
private

◆ m_prevent_update_filament_in_config

bool Slic3r::GUI::ObjectList::m_prevent_update_filament_in_config = false
private

◆ m_selected_layers_range_idx

int Slic3r::GUI::ObjectList::m_selected_layers_range_idx {-1}
private

◆ m_selected_object_id

int Slic3r::GUI::ObjectList::m_selected_object_id = -1
private

◆ m_selection_mode

◆ m_variable_layer_obj_num

size_t Slic3r::GUI::ObjectList::m_variable_layer_obj_num = 0
private

The documentation for this class was generated from the following files: