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

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

Collaboration diagram for Slic3r::GUI::Selection:

Classes

struct  VolumeCache
class  Clipboard
struct  Cache
struct  Planes

Public Types

enum  EMode : unsigned char { Volume , Instance }
enum  EType : unsigned char {
  Invalid , Empty , WipeTower , SingleModifier ,
  MultipleModifier , SingleVolume , MultipleVolume , SingleFullObject ,
  MultipleFullObject , SingleFullInstance , MultipleFullInstance , Mixed
}
enum class  SyncRotationType { NONE = 0 , GENERAL = 1 , RESET = 2 }
typedef std::set< unsigned int > IndicesList
typedef std::map< unsigned int, VolumeCache > VolumesCache
typedef std::set< int > InstanceIdxsList
typedef std::map< int, InstanceIdxsList > ObjectIdxsToInstanceIdxsMap

Public Member Functions

 Selection ()
void set_volumes (GLVolumePtrs *volumes)
bool init ()
bool is_enabled () const
void set_enabled (bool enable)
Model * get_model () const
void set_model (Model *model)
EMode get_mode () const
void set_mode (EMode mode)
int query_real_volume_idx_from_other_view (unsigned int object_idx, unsigned int instance_idx, unsigned int model_volume_idx)
void add (unsigned int volume_idx, bool as_single_selection=true, bool check_for_already_contained=false)
void remove (unsigned int volume_idx)
void add_object (unsigned int object_idx, bool as_single_selection=true)
void remove_object (unsigned int object_idx)
void add_instance (unsigned int object_idx, unsigned int instance_idx, bool as_single_selection=true)
void remove_instance (unsigned int object_idx, unsigned int instance_idx)
void add_volume (unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection=true)
void remove_volume (unsigned int object_idx, unsigned int volume_idx)
void add_volumes (EMode mode, const std::vector< unsigned int > &volume_idxs, bool as_single_selection=true)
void remove_volumes (EMode mode, const std::vector< unsigned int > &volume_idxs)
ModelVolume * get_selected_single_volume (int &out_object_idx, int &out_volume_idx) const
ModelObject * get_selected_single_object (int &out_object_idx) const
const ModelInstance * get_selected_single_intance () const
void add_curr_plate ()
void add_object_from_idx (std::vector< int > &object_idxs)
void remove_curr_plate ()
void clone (int numbers=1)
void center ()
void drop ()
bool can_drop () const
double get_drop_min_z () const
void center_plate (const int plate_idx)
void set_printable (bool printable)
bool get_auto_drop () const
void set_auto_drop (bool enabled)
void add_all ()
void remove_all ()
void set_deserialized (EMode mode, const std::vector< std::pair< size_t, size_t > > &volumes_and_instances)
void instances_changed (const std::vector< size_t > &instance_ids_selected)
void volumes_changed (const std::vector< size_t > &map_volume_old_to_new)
void clear ()
bool is_empty () const
bool is_wipe_tower () const
bool is_any_modifier () const
bool is_single_modifier () const
bool is_multiple_modifier () const
bool is_single_full_instance () const
bool is_multiple_full_instance () const
bool is_single_full_object () const
bool is_multiple_full_object () const
bool is_single_volume () const
bool is_multiple_volume () const
bool is_any_volume () const
bool is_any_connector () const
bool is_any_cut_volume () const
bool is_mixed () const
bool is_from_single_instance () const
bool is_from_single_object () const
bool is_sla_compliant () const
bool is_instance_mode () const
bool is_single_volume_or_modifier () const
bool is_single_volume_instance () const
bool is_single_text () const
bool contains_volume (unsigned int volume_idx) const
bool contains_all_volumes (const std::vector< unsigned int > &volume_idxs) const
bool contains_any_volume (const std::vector< unsigned int > &volume_idxs) const
bool contains_sinking_volumes (bool ignore_modifiers=true) const
bool matches (const std::vector< unsigned int > &volume_idxs) const
bool requires_uniform_scale () const
int get_object_idx () const
int get_instance_idx () const
const InstanceIdxsList & get_instance_idxs () const
const IndicesList & get_volume_idxs () const
const GLVolume * get_volume (unsigned int volume_idx) const
const GLVolume * get_first_volume () const
GLVolume * get_volume (unsigned int volume_idx)
const ObjectIdxsToInstanceIdxsMap & get_content () const
unsigned int volumes_count () const
const BoundingBoxf3 & get_bounding_box () const
const BoundingBoxf3 & get_unscaled_instance_bounding_box () const
const BoundingBoxf3 & get_scaled_instance_bounding_box () const
const BoundingBoxf3 & get_full_unscaled_instance_bounding_box () const
const BoundingBoxf3 & get_full_scaled_instance_bounding_box () const
const BoundingBoxf3 & get_full_unscaled_instance_local_bounding_box () const
const std::pair< BoundingBoxf3, Transform3d > & get_bounding_box_in_current_reference_system () const
std::pair< BoundingBoxf3, Transform3d > get_bounding_box_in_reference_system (ECoordinatesType type) const
const std::pair< Vec3d, double > get_bounding_sphere () const
void setup_cache ()
void translate (const Vec3d &displacement, TransformationType transformation_type)
void move_to_center (const Vec3d &displacement, bool local=false)
void rotate (const Vec3d &rotation, TransformationType transformation_type)
void flattening_rotate (const Vec3d &normal)
void scale (const Vec3d &scale, TransformationType transformation_type)
void scale_to_fit_print_volume (const DynamicPrintConfig &config)
void scale_and_translate (const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type)
void mirror (Axis axis, TransformationType transformation_type)
void translate (unsigned int object_idx, const Vec3d &displacement)
void translate (unsigned int object_idx, unsigned int instance_idx, const Vec3d &displacement)
void translate (unsigned int object_idx, unsigned int instance_idx, unsigned int volume_idx, const Vec3d &displacement, bool local=true)
void rotate (unsigned int object_idx, unsigned int instance_idx, const Transform3d &overwrite_tran)
void rotate (unsigned int object_idx, unsigned int instance_idx, unsigned int volume_idx, const Transform3d &overwrite_tran)
void notify_instance_update (int object_idx, int instance_idx)
EMode get_volume_selection_mode ()
void set_volume_selection_mode (EMode mode)
void lock_volume_selection_mode ()
void unlock_volume_selection_mode ()
void erase ()
void render (float scale_factor=1.0)
void render_sidebar_hints (const std::string &sidebar_field, bool uniform_scale)
bool requires_local_axes () const
void render_bounding_box (const BoundingBoxf3 &box, const ColorRGB &color, float scale)
void render_bounding_box (const BoundingBoxf3 &box, const Transform3d &trafo, const ColorRGB &color, float scale)
void cut_to_clipboard ()
void copy_to_clipboard ()
void paste_from_clipboard ()
std::set< std::pair< int, int > > get_selected_object_instances ()
const Clipboard & get_clipboard () const
void fill_color (int extruder_id)
std::vector< unsigned int > get_volume_idxs_from_object (unsigned int object_idx) const
std::vector< unsigned int > get_volume_idxs_from_instance (unsigned int object_idx, unsigned int instance_idx) const
std::vector< unsigned int > get_volume_idxs_from_volume (unsigned int object_idx, unsigned int instance_idx, unsigned int volume_idx) const
std::vector< unsigned int > get_volume_idxs_from_plate (const int plate_idx) const
std::vector< unsigned int > get_missing_volume_idxs_from (const std::vector< unsigned int > &volume_idxs) const
std::vector< unsigned int > get_unselected_volume_idxs_from (const std::vector< unsigned int > &volume_idxs) const
void synchronize_unselected_instances (SyncRotationType sync_rotation_type)
void synchronize_unselected_volumes ()

Private Member Functions

void update_valid ()
void update_type ()
void set_caches ()
void do_add_volume (unsigned int volume_idx)
void do_add_volumes (const std::vector< unsigned int > &volume_idxs)
void do_remove_volume (unsigned int volume_idx)
void do_remove_instance (unsigned int object_idx, unsigned int instance_idx)
void do_remove_object (unsigned int object_idx)
void set_bounding_boxes_dirty ()
void render_synchronized_volumes ()
void render_bounding_box (const BoundingBoxf3 &box, const Transform3d &trafo, const bool auto_drop, const ColorRGB &color)
void render_sidebar_position_hints (const std::string &sidebar_field, GLShaderProgram &shader, const Transform3d &matrix)
void render_sidebar_rotation_hints (const std::string &sidebar_field, GLShaderProgram &shader, const Transform3d &matrix)
void render_sidebar_scale_hints (const std::string &sidebar_field, bool gizmo_uniform_scale, GLShaderProgram &shader, const Transform3d &matrix)
void render_sidebar_layers_hints (const std::string &sidebar_field, GLShaderProgram &shader)
void ensure_on_bed ()
void ensure_not_below_bed ()
bool is_from_fully_selected_instance (unsigned int volume_idx) const
void paste_volumes_from_clipboard ()
void paste_objects_from_clipboard ()
void transform_instance_relative (GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot)
void transform_volume_relative (GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot)

Private Attributes

GLVolumePtrs * m_volumes
Model * m_model
bool m_enabled
bool m_valid
EMode m_mode
EType m_type
IndicesList m_list
Cache m_cache
Clipboard m_clipboard
std::optional< BoundingBoxf3 > m_bounding_box
std::optional< BoundingBoxf3 > m_unscaled_instance_bounding_box
std::optional< BoundingBoxf3 > m_scaled_instance_bounding_box
std::optional< BoundingBoxf3 > m_full_unscaled_instance_bounding_box
std::optional< BoundingBoxf3 > m_full_scaled_instance_bounding_box
std::optional< BoundingBoxf3 > m_full_unscaled_instance_local_bounding_box
std::optional< std::pair< BoundingBoxf3, Transform3d > > m_bounding_box_in_current_reference_system
std::optional< std::pair< Vec3d, double > > m_bounding_sphere
GLModel m_arrow
GLModel m_curved_arrow
GLModel m_box
bool m_auto_drop = true
Planes m_planes
float m_scale_factor
EMode m_volume_selection_mode { Instance }
bool m_volume_selection_locked { false }

Detailed Description


Class Documentation

◆ Slic3r::GUI::Selection::Cache

struct Slic3r::GUI::Selection::Cache
Collaboration diagram for Slic3r::GUI::Selection::Cache:
Class Members
ObjectIdxsToInstanceIdxsMap content
Vec3d dragging_center
Vec3d rotation_pivot
vector< unsigned int > sinking_volumes
VolumesCache volumes_data

◆ Slic3r::GUI::Selection::Planes

struct Slic3r::GUI::Selection::Planes
Collaboration diagram for Slic3r::GUI::Selection::Planes:
Class Members
array< Vec3f, 2 > check_points { Vec3f::Zero(), Vec3f::Zero() }
array< GLModel, 2 > models

Member Typedef Documentation

◆ IndicesList

typedef std::set<unsigned int> Slic3r::GUI::Selection::IndicesList

◆ InstanceIdxsList

◆ ObjectIdxsToInstanceIdxsMap

◆ VolumesCache

typedef std::map<unsigned int, VolumeCache> Slic3r::GUI::Selection::VolumesCache

Member Enumeration Documentation

◆ EMode

enum Slic3r::GUI::Selection::EMode : unsigned char
Enumerator
Volume 
Instance 
52 {
53 Volume,
55 };
@ Instance
Definition Selection.hpp:54
@ Volume
Definition Selection.hpp:53

◆ EType

enum Slic3r::GUI::Selection::EType : unsigned char
Enumerator
Invalid 
Empty 
WipeTower 
SingleModifier 
MultipleModifier 
SingleVolume 
MultipleVolume 
SingleFullObject 
MultipleFullObject 
SingleFullInstance 
MultipleFullInstance 
Mixed 
58 {
59 Invalid,
60 Empty,
70 Mixed
71 };
@ MultipleVolume
Definition Selection.hpp:65
@ SingleVolume
Definition Selection.hpp:64
@ MultipleFullInstance
Definition Selection.hpp:69
@ MultipleModifier
Definition Selection.hpp:63
@ Invalid
Definition Selection.hpp:59
@ SingleModifier
Definition Selection.hpp:62
@ Empty
Definition Selection.hpp:60
@ WipeTower
Definition Selection.hpp:61
@ MultipleFullObject
Definition Selection.hpp:67
@ SingleFullObject
Definition Selection.hpp:66
@ SingleFullInstance
Definition Selection.hpp:68
@ Mixed
Definition Selection.hpp:70

◆ SyncRotationType

Enumerator
NONE 
GENERAL 
RESET 
455 {
456 // Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
457 NONE = 0,
458 // Synchronize after rotation by an axis not parallel with Z.
459 GENERAL = 1,
460 // Synchronize after rotation reset.
461 RESET = 2
462 };
@ NONE
Definition SideTools.hpp:27

Constructor & Destructor Documentation

◆ Selection()

Slic3r::GUI::Selection::Selection ( )
146 : m_volumes(nullptr)
147 , m_model(nullptr)
148 , m_enabled(false)
150 , m_type(Empty)
151 , m_valid(false)
152 , m_scale_factor(1.0f)
153{
155}
void set_bounding_boxes_dirty()
Definition Selection.hpp:437
GLVolumePtrs * m_volumes
Definition Selection.hpp:154
EMode m_mode
Definition Selection.hpp:160
bool m_enabled
Definition Selection.hpp:158
float m_scale_factor
Definition Selection.hpp:204
EType m_type
Definition Selection.hpp:161
bool m_valid
Definition Selection.hpp:159
Model * m_model
Definition Selection.hpp:156

References Empty, Instance, m_enabled, m_mode, m_model, m_scale_factor, m_type, m_valid, m_volumes, and set_bounding_boxes_dirty().

Here is the call graph for this function:

Member Function Documentation

◆ add()

void Slic3r::GUI::Selection::add ( unsigned int volume_idx,
bool as_single_selection = true,
bool check_for_already_contained = false )
194{
195 if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx)
196 return;
197
198 const GLVolume* volume = (*m_volumes)[volume_idx];
199 //BBS: multiple wipe tower case should be considered
200 // wipe tower is already selected
201 //if (is_wipe_tower() && volume->is_wipe_tower)
202 // return;
203 if (!m_list.empty() && !is_wipe_tower() && volume->is_wipe_tower && !as_single_selection)
204 return;
205
206 bool keep_instance_mode = (m_mode == Instance) && !as_single_selection;
207 bool already_contained = check_for_already_contained && contains_volume(volume_idx);
208
209 // resets the current list if needed
210 bool needs_reset = as_single_selection && !already_contained;
211 needs_reset |= volume->is_wipe_tower;
212 needs_reset |= is_wipe_tower() && !volume->is_wipe_tower;
213 needs_reset |= as_single_selection && !is_any_modifier() && volume->is_modifier;
214 needs_reset |= is_any_modifier() && !volume->is_modifier;
215 if (!needs_reset && (is_any_modifier() || is_any_volume())) {
216 int obj_index = volume->object_idx();
217 int inst_index = volume->instance_idx();
218 int first = *(m_list.begin());
219 if (first < m_volumes->size()) {
220 const GLVolume* volume = (*m_volumes)[first];
221 if ((volume->object_idx() != obj_index) || (volume->instance_idx() != inst_index))
222 needs_reset = true;
223 }
224 }
225
226 if (!already_contained || needs_reset) {
227 wxGetApp().plater()->take_snapshot(std::string("Selection-Add!"), UndoRedo::SnapshotType::Selection);
228
229 if (needs_reset)
230 clear();
231
232 // BBS
233 if (!keep_instance_mode)
234 m_mode = volume->is_modifier ? Volume : m_volume_selection_mode;
235 }
236 else
237 // keep current mode
238 return;
239
240 switch (m_mode)
241 {
242 case Volume:
243 {
244 if (volume->volume_idx() >= 0 && (is_empty() || volume->instance_idx() == get_instance_idx()))
245 do_add_volume(volume_idx);
246
247 break;
248 }
249 case Instance:
250 {
251 Plater::SuppressSnapshots suppress(wxGetApp().plater());
252 add_instance(volume->object_idx(), volume->instance_idx(), as_single_selection);
253 break;
254 }
255 }
256
257 update_type();
259}
IndicesList m_list
Definition Selection.hpp:163
bool is_wipe_tower() const
Definition Selection.hpp:273
void update_type()
Definition Selection.cpp:2309
void do_add_volume(unsigned int volume_idx)
Definition Selection.cpp:2551
bool is_empty() const
Definition Selection.hpp:272
int get_instance_idx() const
Definition Selection.cpp:967
void clear()
Definition Selection.cpp:742
bool is_any_volume() const
Definition Selection.hpp:283
void add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection=true)
Definition Selection.cpp:328
bool is_any_modifier() const
Definition Selection.hpp:274
bool contains_volume(unsigned int volume_idx) const
Definition Selection.hpp:295
EMode m_volume_selection_mode
Definition Selection.hpp:207
static Plater * plater()
Definition GUI_Factories.cpp:400
@ Selection
Definition UndoRedo.hpp:38

References add_instance(), clear(), contains_volume(), do_add_volume(), get_instance_idx(), Instance, Slic3r::GLVolume::instance_idx(), is_any_modifier(), is_any_volume(), is_empty(), is_wipe_tower(), m_list, m_mode, m_valid, m_volume_selection_mode, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::GUI::plater(), Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), update_type(), Volume, and Slic3r::GLVolume::volume_idx().

Referenced by Slic3r::GUI::Plater::priv::reload_all_from_disk(), and Slic3r::GUI::Plater::priv::set_current_panel().

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

◆ add_all()

void Slic3r::GUI::Selection::add_all ( )
682{
683 if (!m_valid)
684 return;
685
686 unsigned int count = 0;
687 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
688 if (!(*m_volumes)[i]->is_wipe_tower)
689 ++count;
690 }
691
692 if ((unsigned int)m_list.size() == count)
693 return;
694
695 wxGetApp().plater()->take_snapshot(std::string("Selection-Add All!"), UndoRedo::SnapshotType::Selection);
696
698 clear();
699
700 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
701 if (!(*m_volumes)[i]->is_wipe_tower)
702 do_add_volume(i);
703 }
704
705 update_type();
707}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246

References clear(), count, do_add_volume(), Instance, is_wipe_tower(), m_list, m_mode, m_valid, m_volumes, Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ add_curr_plate()

void Slic3r::GUI::Selection::add_curr_plate ( )
474{
475 if (!m_valid)
476 return;
477
478 std::vector<unsigned int> volume_idxs = get_volume_idxs_from_plate(wxGetApp().plater()->get_partplate_list().get_curr_plate_index());
479 if (volume_idxs.empty())
480 return;
481
482 wxGetApp().plater()->take_snapshot(std::string("Selection-Add Curr Plate All!"));
484 clear();
485 do_add_volumes(volume_idxs);
486
487 update_type();
489}
void do_add_volumes(const std::vector< unsigned int > &volume_idxs)
Definition Selection.cpp:2560
std::vector< unsigned int > get_volume_idxs_from_plate(const int plate_idx) const
Definition Selection.cpp:2256

References clear(), do_add_volumes(), get_volume_idxs_from_plate(), Instance, m_mode, m_valid, Slic3r::GUI::plater(), set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ add_instance()

void Slic3r::GUI::Selection::add_instance ( unsigned int object_idx,
unsigned int instance_idx,
bool as_single_selection = true )
329{
330 if (!m_valid)
331 return;
332
333 const std::vector<unsigned int> volume_idxs = get_volume_idxs_from_instance(object_idx, instance_idx);
334 if ((!as_single_selection && contains_all_volumes(volume_idxs)) ||
335 (as_single_selection && matches(volume_idxs)))
336 return;
337
338 wxGetApp().plater()->take_snapshot(std::string("Selection-Add Instance"), UndoRedo::SnapshotType::Selection);
339
340 // resets the current list if needed
341 if (as_single_selection)
342 clear();
343
345
346 do_add_volumes(volume_idxs);
347
348 update_type();
350}
std::vector< unsigned int > get_volume_idxs_from_instance(unsigned int object_idx, unsigned int instance_idx) const
Definition Selection.cpp:2225
bool contains_all_volumes(const std::vector< unsigned int > &volume_idxs) const
Definition Selection.cpp:909
bool matches(const std::vector< unsigned int > &volume_idxs) const
Definition Selection.cpp:940

References clear(), contains_all_volumes(), do_add_volumes(), get_volume_idxs_from_instance(), Instance, m_mode, m_valid, matches(), Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), and update_type().

Referenced by add().

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

◆ add_object()

void Slic3r::GUI::Selection::add_object ( unsigned int object_idx,
bool as_single_selection = true )
292{
293 if (!m_valid)
294 return;
295
296 std::vector<unsigned int> volume_idxs = get_volume_idxs_from_object(object_idx);
297 if ((!as_single_selection && contains_all_volumes(volume_idxs)) ||
298 (as_single_selection && matches(volume_idxs)))
299 return;
300
301 wxGetApp().plater()->take_snapshot(std::string("Selection-Add Object"), UndoRedo::SnapshotType::Selection);
302
303 // resets the current list if needed
304 if (as_single_selection)
305 clear();
306
308
309 do_add_volumes(volume_idxs);
310
311 update_type();
313}
std::vector< unsigned int > get_volume_idxs_from_object(unsigned int object_idx) const
Definition Selection.cpp:2212

References clear(), contains_all_volumes(), do_add_volumes(), get_volume_idxs_from_object(), Instance, m_mode, m_valid, matches(), Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), and update_type().

Referenced by Slic3r::GUI::Plater::_calib_pa_select_added_objects(), Slic3r::GUI::GLGizmoSimplify::add_simplify_suggestion_notification(), Slic3r::GUI::Plater::apply_cut_object_to_model(), Slic3r::GUI::Plater::convert_unit(), and Slic3r::GUI::Plater::priv::split_object().

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

◆ add_object_from_idx()

void Slic3r::GUI::Selection::add_object_from_idx ( std::vector< int > & object_idxs)
491 {
492 if (!m_valid)
493 return;
494
496 clear();
497
498 for (int obj_idx = 0; obj_idx < object_idxs.size(); obj_idx++) {
499 std::vector<unsigned int> volume_idxs = get_volume_idxs_from_object(object_idxs[obj_idx]);
500 do_add_volumes(volume_idxs);
501 }
502
503 update_type();
505}

References clear(), do_add_volumes(), get_volume_idxs_from_object(), Instance, m_mode, m_valid, set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ add_volume()

void Slic3r::GUI::Selection::add_volume ( unsigned int object_idx,
unsigned int volume_idx,
int instance_idx,
bool as_single_selection = true )
366{
367 if (!m_valid)
368 return;
369
370 std::vector<unsigned int> volume_idxs = get_volume_idxs_from_volume(object_idx, instance_idx, volume_idx);
371 if ((!as_single_selection && contains_all_volumes(volume_idxs)) ||
372 (as_single_selection && matches(volume_idxs)))
373 return;
374
375 // resets the current list if needed
376 if (as_single_selection)
377 clear();
378
379 m_mode = Volume;
380
381 do_add_volumes(volume_idxs);
382
383 update_type();
385}
std::vector< unsigned int > get_volume_idxs_from_volume(unsigned int object_idx, unsigned int instance_idx, unsigned int volume_idx) const
Definition Selection.cpp:2239

References clear(), contains_all_volumes(), do_add_volumes(), get_volume_idxs_from_volume(), m_mode, m_valid, matches(), set_bounding_boxes_dirty(), update_type(), and Volume.

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

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

◆ add_volumes()

void Slic3r::GUI::Selection::add_volumes ( EMode mode,
const std::vector< unsigned int > & volume_idxs,
bool as_single_selection = true )
403{
404 if (!m_valid)
405 return;
406
407 if ((!as_single_selection && contains_all_volumes(volume_idxs)) ||
408 (as_single_selection && matches(volume_idxs)))
409 return;
410
411 // resets the current list if needed
412 if (as_single_selection)
413 clear();
414
415 m_mode = mode;
416 for (unsigned int i : volume_idxs) {
417 if (i < (unsigned int)m_volumes->size())
418 do_add_volume(i);
419 }
420
421 update_type();
423}

References clear(), contains_all_volumes(), do_add_volume(), m_mode, m_valid, m_volumes, matches(), set_bounding_boxes_dirty(), and update_type().

Referenced by Slic3r::GUI::ObjectList::update_selections_on_canvas().

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

◆ can_drop()

bool Slic3r::GUI::Selection::can_drop ( ) const
571{
572 return std::abs(get_drop_min_z()) > -SINKING_Z_THRESHOLD;
573}
double get_drop_min_z() const
Definition Selection.cpp:553
static const float SINKING_Z_THRESHOLD
Definition Model.hpp:1967

References get_drop_min_z(), and Slic3r::SINKING_Z_THRESHOLD.

Referenced by Slic3r::GUI::anonymous_namespace{NativeCommands.cpp}::build_command_catalog(), and Slic3r::GUI::GizmoObjectManipulation::update_reset_buttons_visibility().

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

◆ center()

void Slic3r::GUI::Selection::center ( )
540{
541 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_selected_plate();
542
543 // calc distance
544 Vec3d src_pos = this->get_bounding_box().center();
545 Vec3d tar_pos = plate->get_center_origin();
546 Vec3d distance = Vec3d(tar_pos.x() - src_pos.x(), tar_pos.y() - src_pos.y(), 0);
547
548 this->move_to_center(distance);
549 wxGetApp().plater()->get_view3D_canvas3D()->do_move(L("Move object"));
550 return;
551}
#define L(s)
Definition ExtrusionEntity.cpp:25
PointType center() const
Definition BoundingBox.cpp:237
void move_to_center(const Vec3d &displacement, bool local=false)
Definition Selection.cpp:1246
const BoundingBoxf3 & get_bounding_box() const
Definition Selection.cpp:994
float distance(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:19
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68

References Slic3r::BoundingBox3Base< PointType >::center(), get_bounding_box(), Slic3r::GUI::PartPlate::get_center_origin(), L, and move_to_center().

Referenced by get_bounding_box_in_reference_system(), render_sidebar_hints(), and scale_to_fit_print_volume().

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

◆ center_plate()

void Slic3r::GUI::Selection::center_plate ( const int plate_idx)
591 {
592
593 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
594
595
596 Vec3d src_pos = this->get_bounding_box().center();
597 Vec3d tar_pos = plate->get_center_origin();
598 Vec3d distance = Vec3d(tar_pos.x() - src_pos.x(), tar_pos.y() - src_pos.y(), 0);
599
600 this->move_to_center(distance);
601 wxGetApp().plater()->get_view3D_canvas3D()->do_move(L("Move object"));
602 return;
603}

References Slic3r::BoundingBox3Base< PointType >::center(), get_bounding_box(), Slic3r::GUI::PartPlate::get_center_origin(), L, and move_to_center().

Here is the call graph for this function:

◆ clear()

void Slic3r::GUI::Selection::clear ( )
743{
744 if (!m_valid)
745 return;
746
747 if (m_list.empty())
748 return;
749
750#if ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
751 // ensure that the volumes get the proper color before next call to render (expecially needed for transparent volumes)
752 for (unsigned int i : m_list) {
753 GLVolume& volume = *(*m_volumes)[i];
754 volume.selected = false;
755 bool is_transparent = volume.color.is_transparent();
756 if (is_transparent)
757 volume.force_transparent = true;
758 volume.set_render_color();
759 if (is_transparent)
760 volume.force_transparent = false;
761 }
762#else
763 for (unsigned int i : m_list) {
764 (*m_volumes)[i]->selected = false;
765 // ensure the volume gets the proper color before next call to render (expecially needed for transparent volumes)
766 (*m_volumes)[i]->set_render_color();
767 }
768#endif // ENABLE_MODIFIERS_ALWAYS_TRANSPARENT
769
770 m_list.clear();
771
772 update_type();
774
775 // BBS
776#if 0
777 // this happens while the application is closing
778 if (wxGetApp().obj_manipul() == nullptr)
779 return;
780
781 // resets the cache in the sidebar
782 wxGetApp().obj_manipul()->reset_cache();
783#endif
784
785 // #et_FIXME fake KillFocus from sidebar
786 // Skip on shutdown: Plater's pImpl is already freed, so plater()->canvas3D() would use-after-free.
787 if (wxGetApp().is_closing())
788 return;
789 wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
790}

References Slic3r::GLVolume::color, Slic3r::ColorRGBA::is_transparent(), m_list, m_valid, set_bounding_boxes_dirty(), Slic3r::GLVolume::set_render_color(), and update_type().

Referenced by Slic3r::GUI::Plater::_calib_pa_select_added_objects(), add(), add_all(), add_curr_plate(), add_instance(), add_object(), add_object_from_idx(), Slic3r::GUI::GLGizmoSimplify::add_simplify_suggestion_notification(), add_volume(), add_volumes(), Slic3r::GUI::Plater::priv::reload_all_from_disk(), remove_all(), remove_curr_plate(), Slic3r::GUI::Plater::priv::set_current_panel(), Slic3r::GUI::Plater::priv::update_after_undo_redo(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

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

◆ clone()

void Slic3r::GUI::Selection::clone ( int numbers = 1)
528{
529 if (numbers <= 0)
530 return;
531
532 wxGetApp().plater()->take_snapshot(std::string("Selection-clone"));
534 for (int i = 0; i < numbers; i++) {
536 }
537}
void copy_to_clipboard()
Definition Selection.cpp:2113
void paste_from_clipboard()
Definition Selection.cpp:2164

References copy_to_clipboard(), and paste_from_clipboard().

Here is the call graph for this function:

◆ contains_all_volumes()

bool Slic3r::GUI::Selection::contains_all_volumes ( const std::vector< unsigned int > & volume_idxs) const
910{
911 for (unsigned int i : volume_idxs) {
912 if (m_list.find(i) == m_list.end())
913 return false;
914 }
915
916 return true;
917}

References m_list.

Referenced by add_instance(), add_object(), add_volume(), add_volumes(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

Here is the caller graph for this function:

◆ contains_any_volume()

bool Slic3r::GUI::Selection::contains_any_volume ( const std::vector< unsigned int > & volume_idxs) const
920{
921 for (unsigned int i : volume_idxs) {
922 if (m_list.find(i) != m_list.end())
923 return true;
924 }
925
926 return false;
927}

References m_list.

◆ contains_sinking_volumes()

bool Slic3r::GUI::Selection::contains_sinking_volumes ( bool ignore_modifiers = true) const
930{
931 for (const GLVolume* v : *m_volumes) {
932 if (!ignore_modifiers || !v->is_modifier) {
933 if (v->is_sinking())
934 return true;
935 }
936 }
937 return false;
938}

References m_volumes.

◆ contains_volume()

bool Slic3r::GUI::Selection::contains_volume ( unsigned int volume_idx) const
inline
295{ return m_list.find(volume_idx) != m_list.end(); }

References m_list.

Referenced by add(), and remove().

Here is the caller graph for this function:

◆ copy_to_clipboard()

void Slic3r::GUI::Selection::copy_to_clipboard ( )
2114{
2115 if (!m_valid)
2116 return;
2117
2118 m_clipboard.reset();
2119
2120 // sort as the object list order
2121 std::vector<unsigned int> selected_list;
2122 selected_list.assign(m_list.begin(), m_list.end());
2123 std::sort(selected_list.begin(), selected_list.end(), [this](unsigned int left, unsigned int right) {
2124 return (*m_volumes)[left]->volume_idx() < (*m_volumes)[right]->volume_idx();
2125 });
2126
2127 for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content) {
2128 ModelObject* src_object = m_model->objects[object.first];
2129 ModelObject* dst_object = m_clipboard.add_object();
2130 dst_object->name = src_object->name;
2131 dst_object->input_file = src_object->input_file;
2132 dst_object->config.assign_config(src_object->config);
2133 dst_object->sla_support_points = src_object->sla_support_points;
2134 dst_object->sla_points_status = src_object->sla_points_status;
2135 dst_object->sla_drain_holes = src_object->sla_drain_holes;
2136 dst_object->brim_points = src_object->brim_points;
2137 dst_object->layer_config_ranges = src_object->layer_config_ranges; // #ys_FIXME_experiment
2138 dst_object->layer_height_profile.assign(src_object->layer_height_profile);
2139 dst_object->origin_translation = src_object->origin_translation;
2140
2141 for (int i : object.second) {
2142 dst_object->add_instance(*src_object->instances[i]);
2143 }
2144
2145 for (unsigned int i : selected_list) {
2146 // Copy the ModelVolumes only for the selected GLVolumes of the 1st selected instance.
2147 const GLVolume* volume = (*m_volumes)[i];
2148 if (volume->object_idx() == object.first && volume->instance_idx() == *object.second.begin()) {
2149 int volume_idx = volume->volume_idx();
2150 if (0 <= volume_idx && volume_idx < (int)src_object->volumes.size()) {
2151 ModelVolume* src_volume = src_object->volumes[volume_idx];
2152 ModelVolume* dst_volume = dst_object->add_volume(*src_volume);
2153 dst_volume->set_new_unique_id();
2154 }
2155 else
2156 assert(false);
2157 }
2158 }
2159 }
2160
2161 m_clipboard.set_mode(m_mode);
2162}
Cache m_cache
Definition Selection.hpp:164
Clipboard m_clipboard
Definition Selection.hpp:165

References Slic3r::ModelObject::add_instance(), Slic3r::ModelObject::add_volume(), Slic3r::LayerHeightProfile::assign(), Slic3r::ModelConfig::assign_config(), Slic3r::ModelObject::brim_points, Slic3r::ModelObject::config, Slic3r::ModelObject::input_file, Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::ModelObject::layer_config_ranges, Slic3r::ModelObject::layer_height_profile, m_cache, m_clipboard, m_list, m_mode, m_model, m_valid, Slic3r::ModelObject::name, Slic3r::GLVolume::object_idx(), Slic3r::ModelObject::origin_translation, Slic3r::ModelVolume::set_new_unique_id(), Slic3r::ModelObject::sla_drain_holes, Slic3r::ModelObject::sla_points_status, Slic3r::ModelObject::sla_support_points, Slic3r::GLVolume::volume_idx(), and Slic3r::ModelObject::volumes.

Referenced by Slic3r::GUI::CloneDialog::CloneDialog(), clone(), and cut_to_clipboard().

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

◆ cut_to_clipboard()

void Slic3r::GUI::Selection::cut_to_clipboard ( )
2108{
2110 erase();
2111}
void erase()
Definition Selection.cpp:1893

References copy_to_clipboard(), and erase().

Here is the call graph for this function:

◆ do_add_volume()

void Slic3r::GUI::Selection::do_add_volume ( unsigned int volume_idx)
private
2552{
2553 m_list.insert(volume_idx);
2554 GLVolume* v = (*m_volumes)[volume_idx];
2555 v->selected = true;
2556 if (v->hover == GLVolume::HS_Select || v->hover == GLVolume::HS_Deselect)
2557 v->hover = GLVolume::HS_Hover;
2558}
@ HS_Select
Definition 3DScene.hpp:124
@ HS_Hover
Definition 3DScene.hpp:123
@ HS_Deselect
Definition 3DScene.hpp:125

References Slic3r::GLVolume::hover, Slic3r::GLVolume::HS_Deselect, Slic3r::GLVolume::HS_Hover, Slic3r::GLVolume::HS_Select, and m_list.

Referenced by add(), add_all(), add_volumes(), do_add_volumes(), instances_changed(), and set_deserialized().

Here is the caller graph for this function:

◆ do_add_volumes()

void Slic3r::GUI::Selection::do_add_volumes ( const std::vector< unsigned int > & volume_idxs)
private
2561{
2562 for (unsigned int i : volume_idxs)
2563 {
2564 if (i < (unsigned int)m_volumes->size())
2565 do_add_volume(i);
2566 }
2567}

References do_add_volume(), and m_volumes.

Referenced by add_curr_plate(), add_instance(), add_object(), add_object_from_idx(), add_volume(), and remove_curr_plate().

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

◆ do_remove_instance()

void Slic3r::GUI::Selection::do_remove_instance ( unsigned int object_idx,
unsigned int instance_idx )
private
2581{
2582 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
2583 GLVolume* v = (*m_volumes)[i];
2584 if (v->object_idx() == (int)object_idx && v->instance_idx() == (int)instance_idx)
2586 }
2587}
void do_remove_volume(unsigned int volume_idx)
Definition Selection.cpp:2569

References do_remove_volume(), Slic3r::GLVolume::instance_idx(), m_volumes, and Slic3r::GLVolume::object_idx().

Referenced by remove(), and remove_instance().

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

◆ do_remove_object()

void Slic3r::GUI::Selection::do_remove_object ( unsigned int object_idx)
private
2590{
2591 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
2592 GLVolume* v = (*m_volumes)[i];
2593 if (v->object_idx() == (int)object_idx)
2595 }
2596}

References do_remove_volume(), m_volumes, and Slic3r::GLVolume::object_idx().

Referenced by remove_object().

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

◆ do_remove_volume()

void Slic3r::GUI::Selection::do_remove_volume ( unsigned int volume_idx)
private
2570{
2571 IndicesList::iterator v_it = m_list.find(volume_idx);
2572 if (v_it == m_list.end())
2573 return;
2574
2575 m_list.erase(v_it);
2576
2577 (*m_volumes)[volume_idx]->selected = false;
2578}

References m_list.

Referenced by do_remove_instance(), do_remove_object(), remove(), remove_volume(), and remove_volumes().

Here is the caller graph for this function:

◆ drop()

void Slic3r::GUI::Selection::drop ( )
576{
577 const double min_z = get_drop_min_z();
578 if (std::abs(min_z) < -SINKING_Z_THRESHOLD)
579 return; // already checked in can_drop()
580
581 wxGetApp().plater()->take_snapshot(L("Move object"));
582
583 // do_move() writes every volume back to the model and refreshes the view.
584 setup_cache();
585 TransformationType transformation_type;
586 transformation_type.set_relative();
587 translate(Vec3d(0, 0, -min_z), transformation_type);
588 wxGetApp().plater()->get_view3D_canvas3D()->do_move("");
589}
void translate(const Vec3d &displacement, TransformationType transformation_type)
Definition Selection.cpp:1279
void setup_cache()
Definition Selection.cpp:1238

References get_drop_min_z(), L, Slic3r::GUI::TransformationType::set_relative(), setup_cache(), Slic3r::SINKING_Z_THRESHOLD, and translate().

Here is the call graph for this function:

◆ ensure_not_below_bed()

void Slic3r::GUI::Selection::ensure_not_below_bed ( )
private
3160{
3161 typedef std::map<std::pair<int, int>, double> InstancesToZMap;
3162 InstancesToZMap instances_max_z;
3163
3164 for (size_t i = 0; i < m_volumes->size(); ++i) {
3165 GLVolume* volume = (*m_volumes)[i];
3166 if (!volume->is_wipe_tower && !volume->is_modifier) {
3167 const double max_z = volume->transformed_convex_hull_bounding_box().max.z();
3168 const std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
3169 InstancesToZMap::iterator it = instances_max_z.find(instance);
3170 if (it == instances_max_z.end())
3171 it = instances_max_z.insert({ instance, -DBL_MAX }).first;
3172
3173 it->second = std::max(it->second, max_z);
3174 }
3175 }
3176
3177 if (is_any_volume()) {
3178 for (unsigned int i : m_list) {
3179 GLVolume& volume = *(*m_volumes)[i];
3180 const std::pair<int, int> instance = std::make_pair(volume.object_idx(), volume.instance_idx());
3181 InstancesToZMap::const_iterator it = instances_max_z.find(instance);
3182 const double z_shift = SINKING_MIN_Z_THRESHOLD - it->second;
3183 if (it != instances_max_z.end() && z_shift > 0.0)
3184 volume.set_volume_offset(Z, volume.get_volume_offset(Z) + z_shift);
3185 }
3186 }
3187 else {
3188 for (GLVolume* volume : *m_volumes) {
3189 const std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
3190 InstancesToZMap::const_iterator it = instances_max_z.find(instance);
3191 if (it != instances_max_z.end() && it->second < SINKING_MIN_Z_THRESHOLD)
3192 volume->set_instance_offset(Z, volume->get_instance_offset(Z) + SINKING_MIN_Z_THRESHOLD - it->second);
3193 }
3194 }
3195}
static const double SINKING_MIN_Z_THRESHOLD
Definition Model.hpp:1968
@ Z
Definition libslic3r.h:143

References Slic3r::GLVolume::get_volume_offset(), Slic3r::GLVolume::instance_idx(), is_any_volume(), m_list, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::GLVolume::object_idx(), Slic3r::GLVolume::set_volume_offset(), Slic3r::SINKING_MIN_Z_THRESHOLD, Slic3r::GLVolume::transformed_convex_hull_bounding_box(), and Slic3r::Z.

Referenced by erase(), and translate().

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

◆ ensure_on_bed()

void Slic3r::GUI::Selection::ensure_on_bed ( )
private
3127{
3128 typedef std::map<std::pair<int, int>, double> InstancesToZMap;
3129 InstancesToZMap instances_min_z;
3130
3131 for (size_t i = 0; i < m_volumes->size(); ++i) {
3132 GLVolume* volume = (*m_volumes)[i];
3133 ModelObject* mo = m_model->objects[volume->object_idx()];
3134 if (mo->auto_drop == false
3135 || volume->is_wipe_tower
3136 || volume->is_modifier
3137 || std::find(m_cache.sinking_volumes.begin(), m_cache.sinking_volumes.end(), i) != m_cache.sinking_volumes.end())
3138 {
3139 continue;
3140 }
3141
3142 const double min_z = volume->transformed_convex_hull_bounding_box().min.z();
3143 std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
3144 InstancesToZMap::iterator it = instances_min_z.find(instance);
3145 if (it == instances_min_z.end())
3146 it = instances_min_z.insert(InstancesToZMap::value_type(instance, DBL_MAX)).first;
3147
3148 it->second = std::min(it->second, min_z);
3149 }
3150
3151 for (GLVolume* volume : *m_volumes) {
3152 std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
3153 InstancesToZMap::iterator it = instances_min_z.find(instance);
3154 if (it != instances_min_z.end())
3155 volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second);
3156 }
3157}

References Slic3r::ModelObject::auto_drop, Slic3r::GLVolume::instance_idx(), m_cache, m_model, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GLVolume::object_idx(), Slic3r::GLVolume::transformed_convex_hull_bounding_box(), and Slic3r::Z.

Here is the call graph for this function:

◆ erase()

void Slic3r::GUI::Selection::erase ( )
1894{
1895 if (!m_valid)
1896 return;
1897
1899 wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itObject, get_object_idx(), 0);
1900 else if (is_multiple_full_object()) {
1901 std::vector<ItemForDelete> items;
1902 items.reserve(m_cache.content.size());
1903 for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it) {
1904 items.emplace_back(ItemType::itObject, it->first, 0);
1905 }
1906 wxGetApp().obj_list()->delete_from_model_and_list(items);
1907 }
1908 else if (is_multiple_full_instance()) {
1909 std::set<std::pair<int, int>> instances_idxs;
1910 for (ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.begin(); obj_it != m_cache.content.end(); ++obj_it) {
1911 for (InstanceIdxsList::reverse_iterator inst_it = obj_it->second.rbegin(); inst_it != obj_it->second.rend(); ++inst_it) {
1912 instances_idxs.insert(std::make_pair(obj_it->first, *inst_it));
1913 }
1914 }
1915
1916 std::vector<ItemForDelete> items;
1917 items.reserve(instances_idxs.size());
1918 for (const std::pair<int, int>& i : instances_idxs) {
1919 items.emplace_back(ItemType::itInstance, i.first, i.second);
1920 }
1921 wxGetApp().obj_list()->delete_from_model_and_list(items);
1922 }
1923 else if (is_single_full_instance())
1924 wxGetApp().obj_list()->delete_from_model_and_list(ItemType::itInstance, get_object_idx(), get_instance_idx());
1925 else if (is_mixed()) {
1926 std::set<ItemForDelete> items_set;
1927 std::map<int, int> volumes_in_obj;
1928
1929 for (auto i : m_list) {
1930 const auto gl_vol = (*m_volumes)[i];
1931 const auto glv_obj_idx = gl_vol->object_idx();
1932 const auto model_object = m_model->objects[glv_obj_idx];
1933
1934 if (model_object->instances.size() == 1) {
1935 if (model_object->volumes.size() == 1)
1936 items_set.insert(ItemForDelete(ItemType::itObject, glv_obj_idx, -1));
1937 else {
1938 items_set.insert(ItemForDelete(ItemType::itVolume, glv_obj_idx, gl_vol->volume_idx()));
1939 int idx = (volumes_in_obj.find(glv_obj_idx) == volumes_in_obj.end()) ? 0 : volumes_in_obj.at(glv_obj_idx);
1940 volumes_in_obj[glv_obj_idx] = ++idx;
1941 }
1942 continue;
1943 }
1944
1945 const auto glv_ins_idx = gl_vol->instance_idx();
1946
1947 for (auto obj_ins : m_cache.content) {
1948 if (obj_ins.first == glv_obj_idx) {
1949 if (obj_ins.second.find(glv_ins_idx) != obj_ins.second.end()) {
1950 if (obj_ins.second.size() == model_object->instances.size())
1951 items_set.insert(ItemForDelete(ItemType::itObject, glv_obj_idx, -1));
1952 else
1953 items_set.insert(ItemForDelete(ItemType::itInstance, glv_obj_idx, glv_ins_idx));
1954
1955 break;
1956 }
1957 }
1958 }
1959 }
1960
1961 std::vector<ItemForDelete> items;
1962 items.reserve(items_set.size());
1963 for (const ItemForDelete& i : items_set) {
1964 if (i.type == ItemType::itVolume) {
1965 const int vol_in_obj_cnt = volumes_in_obj.find(i.obj_idx) == volumes_in_obj.end() ? 0 : volumes_in_obj.at(i.obj_idx);
1966 if (vol_in_obj_cnt == (int)m_model->objects[i.obj_idx]->volumes.size()) {
1967 if (i.sub_obj_idx == vol_in_obj_cnt - 1)
1968 items.emplace_back(ItemType::itObject, i.obj_idx, 0);
1969 continue;
1970 }
1971 }
1972 items.emplace_back(i.type, i.obj_idx, i.sub_obj_idx);
1973 }
1974
1975 wxGetApp().obj_list()->delete_from_model_and_list(items);
1976 }
1977 else {
1978 std::set<std::pair<int, int>> volumes_idxs;
1979 for (unsigned int i : m_list) {
1980 const GLVolume* v = (*m_volumes)[i];
1981 // Only remove volumes associated with ModelVolumes from the object list.
1982 // Temporary meshes (SLA supports or pads) are not managed by the object list.
1983 if (v->volume_idx() >= 0)
1984 volumes_idxs.insert(std::make_pair(v->object_idx(), v->volume_idx()));
1985 }
1986
1987 std::vector<ItemForDelete> items;
1988 items.reserve(volumes_idxs.size());
1989 for (const std::pair<int, int>& v : volumes_idxs) {
1990 items.emplace_back(ItemType::itVolume, v.first, v.second);
1991 }
1992
1993 wxGetApp().obj_list()->delete_from_model_and_list(items);
1995 }
1996}
int get_object_idx() const
Definition Selection.cpp:962
bool is_multiple_full_instance() const
Definition Selection.hpp:278
bool is_mixed() const
Definition Selection.hpp:286
bool is_single_full_instance() const
Definition Selection.cpp:848
void ensure_not_below_bed()
Definition Selection.cpp:3159
bool is_single_full_object() const
Definition Selection.hpp:279
bool is_multiple_full_object() const
Definition Selection.hpp:280
@ itObject
Definition ObjectDataViewModel.hpp:37
@ itInstance
Definition ObjectDataViewModel.hpp:40
@ itVolume
Definition ObjectDataViewModel.hpp:38

References ensure_not_below_bed(), get_instance_idx(), get_object_idx(), is_mixed(), is_multiple_full_instance(), is_multiple_full_object(), is_single_full_instance(), is_single_full_object(), Slic3r::GUI::itInstance, Slic3r::GUI::itObject, Slic3r::GUI::itVolume, m_cache, m_list, m_model, m_valid, Slic3r::GLVolume::object_idx(), and Slic3r::GLVolume::volume_idx().

Referenced by cut_to_clipboard(), and remove_curr_plate().

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

◆ fill_color()

void Slic3r::GUI::Selection::fill_color ( int extruder_id)
2208{
2209 wxGetApp().obj_list()->set_extruder_for_selected_items(extruder_id);
2210}

◆ flattening_rotate()

void Slic3r::GUI::Selection::flattening_rotate ( const Vec3d & normal)
1448{
1449 // We get the normal in untransformed coordinates. We must transform it using the instance matrix, find out
1450 // how to rotate the instance so it faces downwards and do the rotation. All that for all selected instances.
1451 // The function assumes that is_from_single_object() holds.
1452 assert(Slic3r::is_approx(normal.norm(), 1.));
1453
1454 if (!m_valid)
1455 return;
1456
1457 for (unsigned int i : m_list) {
1458 GLVolume& v = *(*m_volumes)[i];
1459 // Additional rotation to align the face normal with the down vector in the world coordinate space.
1460 const Geometry::Transformation& old_inst_trafo = v.get_instance_transformation();
1461 const Transform3d rotation_matrix = lay_on_face_rotation(normal, old_inst_trafo.get_matrix_no_offset());
1462 v.set_instance_transformation(old_inst_trafo.get_offset_matrix() * rotation_matrix * old_inst_trafo.get_matrix_no_offset());
1463 }
1464
1465#if !DISABLE_INSTANCES_SYNCH
1466 // Apply the same transformation also to other instances,
1467 // but respect their possibly diffrent z-rotation.
1468 if (m_mode == Instance)
1470#endif // !DISABLE_INSTANCES_SYNCH
1471
1473}
void synchronize_unselected_instances(SyncRotationType sync_rotation_type)
Definition Selection.cpp:3045
@ GENERAL
Definition Selection.hpp:459
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:320
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112
Transform3d lay_on_face_rotation(const Vec3d &normal, const Transform3d &instance_matrix_no_offset)
Definition LayOnFace.cpp:216

References GENERAL, Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::Geometry::Transformation::get_offset_matrix(), Instance, Slic3r::is_approx(), Slic3r::lay_on_face_rotation(), m_list, m_mode, m_valid, Slic3r::normal(), set_bounding_boxes_dirty(), Slic3r::GLVolume::set_instance_transformation(), and synchronize_unselected_instances().

Referenced by Slic3r::GUI::GLGizmoFlatten::on_mouse().

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

◆ get_auto_drop()

bool Slic3r::GUI::Selection::get_auto_drop ( ) const
637 {
638 // The wipe tower is not a ModelObject and has no auto_drop state;
639 // return the default to avoid indexing m_model->objects with its synthetic id.
640 if (!m_valid || is_wipe_tower())
641 return true;
642
643 std::set<int> object_idxs;
644 for (const auto& [obj_idx, inst_list] : m_cache.content) {
645 object_idxs.insert(obj_idx);
646 }
647
648 // Return false if one selected object has auto_drop disabled.
649 for (int obj_idx : object_idxs) {
650 ModelObject* object = m_model->objects[obj_idx];
651 if (!object->auto_drop)
652 return false;
653 }
654
655 return true;
656}

References Slic3r::ModelObject::auto_drop, is_wipe_tower(), m_cache, m_model, and m_valid.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_set_auto_drop(), render(), render_bounding_box(), render_bounding_box(), and render_synchronized_volumes().

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

◆ get_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::Selection::get_bounding_box ( ) const
995{
996 if (!m_bounding_box.has_value()) {
997 std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_bounding_box);
998 *bbox = BoundingBoxf3();
999 if (m_valid) {
1000 for (unsigned int i : m_list) {
1001 (*bbox)->merge((*m_volumes)[i]->transformed_convex_hull_bounding_box());
1002 }
1003 }
1004 }
1005 return *m_bounding_box;
1006}
std::optional< BoundingBoxf3 > m_bounding_box
Definition Selection.hpp:166

References m_bounding_box, m_list, m_valid, and m_volumes.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_center(), Slic3r::GUI::MenuFactory::append_menu_items_flush_options(), center(), center_plate(), get_drop_min_z(), Slic3r::GUI::GLGizmoMove3D::get_tooltip(), render_sidebar_hints(), render_sidebar_layers_hints(), scale_to_fit_print_volume(), set_caches(), and Slic3r::GUI::GizmoObjectManipulation::update_settings_value().

Here is the caller graph for this function:

◆ get_bounding_box_in_current_reference_system()

const std::pair< BoundingBoxf3, Transform3d > & Slic3r::GUI::Selection::get_bounding_box_in_current_reference_system ( ) const
1108{
1109 static int last_coordinates_type = -1;
1110
1111 assert(!is_empty());
1112
1113 ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
1114 if (m_mode == Instance && coordinates_type == ECoordinatesType::Local) coordinates_type = ECoordinatesType::World;
1115
1116 if (last_coordinates_type != int(coordinates_type)) const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system)->reset();
1117
1119 last_coordinates_type = int(coordinates_type);
1120 *const_cast<std::optional<std::pair<BoundingBoxf3, Transform3d>> *>(&m_bounding_box_in_current_reference_system) = get_bounding_box_in_reference_system(coordinates_type);
1121 }
1122
1124}
std::optional< std::pair< BoundingBoxf3, Transform3d > > m_bounding_box_in_current_reference_system
Definition Selection.hpp:185
std::pair< BoundingBoxf3, Transform3d > get_bounding_box_in_reference_system(ECoordinatesType type) const
Definition Selection.cpp:1126
ECoordinatesType
Definition GUI_Geometry.hpp:8
@ Local
Definition GUI_Geometry.hpp:11
@ World
Definition GUI_Geometry.hpp:9

References get_bounding_box_in_reference_system(), Instance, is_empty(), Slic3r::GUI::Local, m_bounding_box_in_current_reference_system, m_mode, and Slic3r::GUI::World.

Referenced by Slic3r::GUI::GLGizmoRotate::init_data_from_selection(), Slic3r::GUI::GLGizmoMove3D::on_render(), render(), render_sidebar_hints(), scale_and_translate(), Slic3r::GUI::GLGizmoScale3D::update_grabbers_data(), and Slic3r::GUI::GizmoObjectManipulation::update_settings_value().

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

◆ get_bounding_box_in_reference_system()

std::pair< BoundingBoxf3, Transform3d > Slic3r::GUI::Selection::get_bounding_box_in_reference_system ( ECoordinatesType type) const
1127{
1128 //
1129 // trafo to current reference system
1130 //
1131 Transform3d trafo;
1132 switch (type) {
1134 trafo = Transform3d::Identity();
1135 break;
1136 }
1139 break;
1140 }
1142 trafo = get_first_volume()->world_matrix();
1143 break;
1144 }
1145 }
1146
1147 //
1148 // trafo basis in world coordinates
1149 //
1150 Geometry::Transformation t(trafo);
1151 t.reset_scaling_factor();
1152 const Transform3d basis_trafo = t.get_matrix_no_offset();
1153 std::vector<Vec3d> axes = {Vec3d::UnitX(), Vec3d::UnitY(), Vec3d::UnitZ()};
1154 for (size_t i = 0; i < axes.size(); ++i) { axes[i] = basis_trafo * axes[i]; }
1155
1156 //
1157 // calculate bounding box aligned to trafo basis
1158 //
1159 Vec3d min = {DBL_MAX, DBL_MAX, DBL_MAX};
1160 Vec3d max = {-DBL_MAX, -DBL_MAX, -DBL_MAX};
1161 for (unsigned int id : m_list) {
1162 const GLVolume & vol = *get_volume(id);
1163 const Transform3d vol_world_rafo = vol.world_matrix();
1164 const TriangleMesh *mesh = vol.convex_hull();
1165 if (mesh == nullptr)
1166 mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
1167 assert(mesh != nullptr);
1168 for (const stl_vertex &v : mesh->its.vertices) {
1169 const Vec3d world_v = vol_world_rafo * v.cast<double>();
1170 for (int i = 0; i < 3; ++i) {
1171 const double i_comp = world_v.dot(axes[i]);
1172 min(i) = std::min(min(i), i_comp);
1173 max(i) = std::max(max(i), i_comp);
1174 }
1175 }
1176 }
1177
1178 const Vec3d box_size = max - min;
1179 Vec3d half_box_size = 0.5 * box_size;
1180 Geometry::Transformation out_trafo(trafo);
1181 Vec3d center = 0.5 * (min + max);
1182
1183 // Fix for non centered volume
1184 // by move with calculated center(to volume center) and extend half box size
1185 // e.g. for right aligned embossed text
1186 if (m_list.size() == 1 && type == ECoordinatesType::Local) {
1187 const GLVolume & vol = *get_volume(*m_list.begin());
1188 const Transform3d vol_world_trafo = vol.world_matrix();
1189 Vec3d world_zero = vol_world_trafo * Vec3d::Zero();
1190 for (size_t i = 0; i < 3; i++) {
1191 // move center to local volume zero
1192 center[i] = world_zero.dot(axes[i]);
1193 // extend half size to bigger distance from center
1194 half_box_size[i] = std::max(abs(center[i] - min[i]), abs(center[i] - max[i]));
1195 }
1196 }
1197
1198 const BoundingBoxf3 out_box(-half_box_size, half_box_size);
1199 out_trafo.set_offset(basis_trafo * center);
1200 return {out_box, out_trafo.get_matrix_no_scaling_factor()};
1201}
Transform3d world_matrix() const
Definition 3DScene.cpp:447
const Geometry::Transformation & get_instance_transformation() const
Definition 3DScene.hpp:278
void center()
Definition Selection.cpp:539
const GLVolume * get_first_volume() const
Definition Selection.hpp:317
const GLVolume * get_volume(unsigned int volume_idx) const
Definition Selection.cpp:984
const Transform3d & get_matrix() const
Definition Geometry.hpp:477
@ Instance
Definition GUI_Geometry.hpp:10

References center(), Slic3r::GLVolume::convex_hull(), get_first_volume(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::Geometry::Transformation::get_matrix_no_scaling_factor(), get_volume(), Slic3r::GUI::Instance, Slic3r::TriangleMesh::its, Slic3r::GUI::Local, m_list, m_model, Slic3r::GLVolume::object_idx(), Slic3r::Geometry::Transformation::reset_scaling_factor(), Slic3r::Geometry::Transformation::set_offset(), Slic3r::GLVolume::volume_idx(), Slic3r::GUI::World, and Slic3r::GLVolume::world_matrix().

Referenced by get_bounding_box_in_current_reference_system(), and Slic3r::GUI::GLGizmoRotate::init_data_from_selection().

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

◆ get_bounding_sphere()

const std::pair< Vec3d, double > Slic3r::GUI::Selection::get_bounding_sphere ( ) const
1204{
1205 if (!m_bounding_sphere.has_value()) {
1206 std::optional<std::pair<Vec3d, double>>* sphere = const_cast<std::optional<std::pair<Vec3d, double>>*>(&m_bounding_sphere);
1207 *sphere = { Vec3d::Zero(), 0.0 };
1208
1209 using K = CGAL::Simple_cartesian<float>;
1210 using Traits = CGAL::Min_sphere_of_points_d_traits_3<K, float>;
1211 using Min_sphere = CGAL::Min_sphere_of_spheres_d<Traits>;
1212 using Point = K::Point_3;
1213
1214 if (m_valid && !m_list.empty()) {
1215 std::vector<Point> points;
1216 for (unsigned int i : m_list) {
1217 const GLVolume& volume = *(*m_volumes)[i];
1218 const TriangleMesh* hull = volume.convex_hull();
1219 const indexed_triangle_set& its = (hull != nullptr) ?
1220 hull->its : m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh().its;
1221 const Transform3d& matrix = volume.world_matrix();
1222 for (const Vec3f& v : its.vertices) {
1223 const Vec3d vv = matrix * v.cast<double>();
1224 points.push_back(Point(vv.x(), vv.y(), vv.z()));
1225 }
1226 }
1227
1228 Min_sphere ms(points.begin(), points.end());
1229 const float* center_x = ms.center_cartesian_begin();
1230 (*sphere)->first = { *center_x, *(center_x + 1), *(center_x + 2) };
1231 (*sphere)->second = ms.radius();
1232 }
1233 }
1234
1235 return *m_bounding_sphere;
1236}
std::optional< std::pair< Vec3d, double > > m_bounding_sphere
Definition Selection.hpp:187
@ K
Definition CalibrationWizardSavePage.cpp:123
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
indexed_triangle_set sphere(double rho, Portion portion, double fa)
Definition SupportTreeMesher.cpp:14
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
CGAL::AABB_traits_3< EpicKernel, Primitive > Traits
Definition CutSurface.cpp:2806

References Slic3r::GLVolume::convex_hull(), Slic3r::TriangleMesh::its, Slic3r::GUI::K, m_bounding_sphere, m_list, m_model, m_valid, Slic3r::GLVolume::object_idx(), Slic3r::GLVolume::volume_idx(), and Slic3r::GLVolume::world_matrix().

Referenced by Slic3r::GUI::GLGizmoRotate::init_data_from_selection(), and set_caches().

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

◆ get_clipboard()

const Clipboard & Slic3r::GUI::Selection::get_clipboard ( ) const
inline
411{ return m_clipboard; }

References m_clipboard.

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

Here is the caller graph for this function:

◆ get_content()

const ObjectIdxsToInstanceIdxsMap & Slic3r::GUI::Selection::get_content ( ) const
inline
320{ return m_cache.content; }

References m_cache.

Referenced by Slic3r::GUI::GLGizmoAlignment::get_items_count(), Slic3r::GUI::GLGizmoAlignment::get_parent_box(), Slic3r::GUI::GLGizmoAlignment::get_selected_objects_info(), Slic3r::GUI::GLGizmoAlignment::is_parts_selection(), Slic3r::GUI::Plater::show_object_info(), and Slic3r::GUI::ObjectList::update_selections().

Here is the caller graph for this function:

◆ get_drop_min_z()

double Slic3r::GUI::Selection::get_drop_min_z ( ) const
554{
555 if (!m_valid)
556 return 0.;
557 if (m_mode == Volume)
558 return get_bounding_box().min.z();
559
560 double min_z = DBL_MAX;
561 for (const auto& [obj_idx, inst_idxs] : m_cache.content) {
562 if (obj_idx >= (int)m_model->objects.size())
563 continue; // wipe tower
564 for (int inst_idx : inst_idxs)
565 min_z = std::min(min_z, m_model->objects[obj_idx]->get_instance_min_z(inst_idx));
566 }
567 return min_z == DBL_MAX ? 0. : min_z;
568}

References get_bounding_box(), m_cache, m_mode, m_model, m_valid, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, and Volume.

Referenced by can_drop(), and drop().

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

◆ get_first_volume()

const GLVolume * Slic3r::GUI::Selection::get_first_volume ( ) const
inline
317{ return get_volume(*m_list.begin()); }

References get_volume(), and m_list.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_edit_svg(), Slic3r::GUI::MenuFactory::append_menu_item_edit_text(), Slic3r::GUI::calc_angle(), Slic3r::GUI::GLGizmoSVG::calculate_scale(), Slic3r::GUI::GLGizmoRotate3D::data_changed(), Slic3r::GUI::do_local_z_rotate(), Slic3r::GUI::dragging_rotate_gizmo(), Slic3r::GUI::Plater::export_stl(), get_bounding_box_in_reference_system(), Slic3r::GUI::GLGizmoCut3D::get_cut_matrix(), get_selected_single_object(), get_selected_single_volume(), Slic3r::GUI::GLGizmoScale3D::get_tooltip(), Slic3r::GUI::SceneRaycaster::hit(), anonymous_namespace{GLGizmoEmboss.cpp}::init_text_lines(), Slic3r::GUI::ObjectList::load_generic_subobject(), Slic3r::GUI::ObjectList::load_modifier(), Slic3r::GUI::GLGizmoFlatten::on_register_raycasters_for_picking(), Slic3r::GUI::GLGizmoFlatten::on_render(), Slic3r::GUI::GLGizmoMove3D::on_render(), Slic3r::GUI::Plater::priv::on_right_click(), Slic3r::GUI::CommonGizmosDataObjects::SelectionInfo::on_update(), Slic3r::GUI::GLGizmoAlignment::reference_basis(), Slic3r::GUI::Plater::priv::replace_with_stl(), Slic3r::GUI::GizmoObjectManipulation::reset_position_value(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), Slic3r::GUI::GLGizmoCut3D::transformed_bounding_box(), Slic3r::GUI::GLGizmoPainterBase::update_contours(), Slic3r::GUI::GLGizmoScale3D::update_grabbers_data(), Slic3r::GUI::GizmoObjectManipulation::update_reset_buttons_visibility(), Slic3r::GUI::ObjectList::update_selections(), and Slic3r::GUI::GizmoObjectManipulation::update_settings_value().

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

◆ get_full_scaled_instance_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::Selection::get_full_scaled_instance_bounding_box ( ) const
1070{
1071 assert(is_single_full_instance());
1072
1073 if (!m_full_scaled_instance_bounding_box.has_value()) {
1074 std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_scaled_instance_bounding_box);
1075 *bbox = BoundingBoxf3();
1076 if (m_valid) {
1077 for (unsigned int i : m_list) {
1078 const GLVolume &volume = *(*m_volumes)[i];
1079 Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
1080 trafo.translation().z() += volume.get_sla_shift_z();
1081 (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
1082 }
1083 }
1084 }
1086}
std::optional< BoundingBoxf3 > m_full_scaled_instance_bounding_box
Definition Selection.hpp:179

References Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::get_sla_shift_z(), Slic3r::GLVolume::get_volume_transformation(), is_single_full_instance(), m_full_scaled_instance_bounding_box, m_list, m_valid, and Slic3r::GLVolume::transformed_convex_hull_bounding_box().

Here is the call graph for this function:

◆ get_full_unscaled_instance_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::Selection::get_full_unscaled_instance_bounding_box ( ) const
1051{
1052 assert(is_single_full_instance());
1053
1054 if (!m_full_unscaled_instance_bounding_box.has_value()) {
1055 std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_bounding_box);
1056 *bbox = BoundingBoxf3();
1057 if (m_valid) {
1058 for (unsigned int i : m_list) {
1059 const GLVolume &volume = *(*m_volumes)[i];
1060 Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
1061 trafo.translation().z() += volume.get_sla_shift_z();
1062 (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
1063 }
1064 }
1065 }
1067}
std::optional< BoundingBoxf3 > m_full_unscaled_instance_bounding_box
Definition Selection.hpp:176

References Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_matrix_no_scaling_factor(), Slic3r::GLVolume::get_sla_shift_z(), Slic3r::GLVolume::get_volume_transformation(), is_single_full_instance(), m_full_unscaled_instance_bounding_box, m_list, m_valid, and Slic3r::GLVolume::transformed_convex_hull_bounding_box().

Referenced by Slic3r::GUI::GizmoObjectManipulation::change_size_value(), and scale_and_translate().

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

◆ get_full_unscaled_instance_local_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::Selection::get_full_unscaled_instance_local_bounding_box ( ) const
1089{
1090 assert(is_single_full_instance());
1091
1093 std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_local_bounding_box);
1094 *bbox = BoundingBoxf3();
1095 if (m_valid) {
1096 for (unsigned int i : m_list) {
1097 const GLVolume &volume = *(*m_volumes)[i];
1098 Transform3d trafo = volume.get_volume_transformation().get_matrix();
1099 trafo.translation().z() += volume.get_sla_shift_z();
1100 (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
1101 }
1102 }
1103 }
1105}
std::optional< BoundingBoxf3 > m_full_unscaled_instance_local_bounding_box
Definition Selection.hpp:182

References Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::get_sla_shift_z(), Slic3r::GLVolume::get_volume_transformation(), is_single_full_instance(), m_full_unscaled_instance_local_bounding_box, m_list, m_valid, and Slic3r::GLVolume::transformed_convex_hull_bounding_box().

Referenced by Slic3r::GUI::GizmoObjectManipulation::change_size_value(), scale_and_translate(), and Slic3r::GUI::GizmoObjectManipulation::update_settings_value().

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

◆ get_instance_idx()

int Slic3r::GUI::Selection::get_instance_idx ( ) const
968{
969 if (m_cache.content.size() == 1) {
970 const InstanceIdxsList& idxs = m_cache.content.begin()->second;
971 if (idxs.size() == 1)
972 return *idxs.begin();
973 }
974
975 return -1;
976}
std::set< int > InstanceIdxsList
Definition Selection.hpp:110

References m_cache.

Referenced by add(), Slic3r::GUI::GLGizmoTextureDisplacement::apply_projection_frame(), Slic3r::GUI::GLGizmoTextureDisplacement::capture_view_projection(), Slic3r::GUI::GLGizmoFlatten::data_changed(), erase(), Slic3r::GUI::Plater::export_stl(), Slic3r::GUI::CommonGizmosDataObjects::SelectionInfo::get_active_instance(), Slic3r::GUI::GLGizmoCut3D::get_cut_matrix(), Slic3r::GUI::GLGizmoAlignment::get_parent_box(), Slic3r::GUI::GLGizmoPainterBase::get_projected_height_range(), get_selected_single_intance(), Slic3r::GUI::GLGizmoPainterBase::gizmo_event(), is_from_single_instance(), is_single_full_instance(), Slic3r::GUI::GLGizmoPainterBase::mesh_trafo_matrices(), Slic3r::GUI::GLGizmoTextureDisplacement::on_mouse_adjust_texture(), Slic3r::GUI::GLGizmoBrimEars::on_render(), paste_volumes_from_clipboard(), Slic3r::GUI::GLGizmoCut3D::perform_cut(), Slic3r::GUI::GLGizmoCut3D::process_contours(), Slic3r::GUI::GLGizmoTextureDisplacement::render_adjust_texture_gizmo(), Slic3r::GUI::GLGizmoPainterBase::render_cursor_height_range(), Slic3r::GUI::GLGizmoTextureDisplacement::render_island_overlay(), Slic3r::GUI::GLGizmoTextureDisplacement::render_paint_overlay(), Slic3r::GUI::GLGizmoTextureDisplacement::render_painted_colors(), Slic3r::GUI::GLGizmoTextureDisplacement::render_painter_gizmo(), Slic3r::GUI::GLGizmoTextureDisplacement::render_preview_mesh(), Slic3r::GUI::GLGizmoTextureDisplacement::render_seam_overlay(), Slic3r::GUI::GLGizmoTextureDisplacement::render_shaded_preview_mesh(), Slic3r::GUI::GLGizmoTextureDisplacement::render_subdivide_preview(), Slic3r::GUI::GLGizmoPainterBase::render_triangles(), Slic3r::GUI::GLGizmoTextureDisplacement::render_uvcheck_mesh(), Slic3r::GUI::GLGizmoTextureDisplacement::render_wireframe_overlay(), Slic3r::GUI::GLGizmoTextureDisplacement::seam_edge_at(), Slic3r::GUI::GLGizmoTextureDisplacement::seam_vertex_at(), Slic3r::GUI::GLGizmoFdmSupports::select_facets_by_angle(), Slic3r::GUI::GLGizmoTextureDisplacement::select_visible_faces(), Slic3r::GUI::Plater::show_object_info(), Slic3r::GUI::ObjectList::split_instances(), Slic3r::GUI::GLGizmoCut3D::toggle_model_objects_visibility(), Slic3r::GUI::GLGizmoPainterBase::update_contours(), Slic3r::GUI::ObjectList::update_selections(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

Here is the caller graph for this function:

◆ get_instance_idxs()

const Selection::InstanceIdxsList & Slic3r::GUI::Selection::get_instance_idxs ( ) const
979{
980 assert(m_cache.content.size() == 1);
981 return m_cache.content.begin()->second;
982}

References m_cache.

Referenced by Slic3r::GUI::ObjectList::load_generic_subobject(), Slic3r::GUI::ObjectList::load_modifier(), Slic3r::GUI::ObjectList::split_instances(), and Slic3r::GUI::ObjectList::update_selections().

Here is the caller graph for this function:

◆ get_missing_volume_idxs_from()

std::vector< unsigned int > Slic3r::GUI::Selection::get_missing_volume_idxs_from ( const std::vector< unsigned int > & volume_idxs) const
2278{
2279 std::vector<unsigned int> idxs;
2280
2281 for (unsigned int i : m_list)
2282 {
2283 std::vector<unsigned int>::const_iterator it = std::find(volume_idxs.begin(), volume_idxs.end(), i);
2284 if (it == volume_idxs.end())
2285 idxs.push_back(i);
2286 }
2287
2288 return idxs;
2289}

References m_list.

Referenced by Slic3r::GUI::ObjectList::update_selections_on_canvas().

Here is the caller graph for this function:

◆ get_mode()

◆ get_model()

Model * Slic3r::GUI::Selection::get_model ( ) const
inline
219{ return m_model; }

References m_model.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_edit_svg(), Slic3r::GUI::MenuFactory::append_menu_item_edit_text(), Slic3r::GUI::calc_angle(), Slic3r::GUI::calc_surface_offset(), Slic3r::GUI::GLGizmoSVG::calculate_scale(), Slic3r::GUI::GLGizmoFlatten::data_changed(), Slic3r::GUI::do_local_z_rotate(), Slic3r::GUI::GLGizmoCut3D::get_cut_matrix(), anonymous_namespace{SurfaceDrag.cpp}::get_fix_transformation(), Slic3r::GUI::GLGizmoAlignment::get_items_count(), Slic3r::GUI::GLGizmoAlignment::get_parent_box(), Slic3r::GUI::GLGizmoAlignment::get_selected_objects_info(), Slic3r::GUI::GLGizmoAlignment::get_selected_part_volumes(), get_selected_single_object(), get_selected_single_volume(), Slic3r::GUI::get_selected_volume(), Slic3r::GUI::get_selected_volume(), Slic3r::GUI::get_volume(), Slic3r::GUI::GLGizmoMeasure::init_plane_glmodel(), anonymous_namespace{GLGizmoEmboss.cpp}::init_text_lines(), Slic3r::GUI::GLGizmoBrimEars::on_render(), Slic3r::GUI::GLGizmoEmboss::on_render(), Slic3r::GUI::Plater::priv::on_right_click(), Slic3r::GUI::CommonGizmosDataObjects::SelectionInfo::on_update(), Slic3r::GUI::GLGizmoCut3D::process_contours(), Slic3r::GUI::GLGizmoMeasure::register_single_mesh_pick(), Slic3r::GUI::Plater::priv::replace_all_with_stl(), Slic3r::GUI::GLGizmoSVG::set_volume_by_selection(), Slic3r::GUI::ObjectList::set_volume_type(), Slic3r::GUI::Emboss::start_create_volume_without_position(), Slic3r::GUI::GLGizmoCut3D::toggle_model_objects_visibility(), and Slic3r::GUI::world_matrix_fixed().

Here is the caller graph for this function:

◆ get_object_idx()

int Slic3r::GUI::Selection::get_object_idx ( ) const
963{
964 return (m_cache.content.size() == 1) ? m_cache.content.begin()->first : -1;
965}

References m_cache.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_settings(), Slic3r::GUI::MenuFactory::append_menu_items_flush_options(), Slic3r::GUI::GLGizmoSimplify::apply_simplify(), Slic3r::GUI::GLGizmoFlatten::data_changed(), erase(), Slic3r::GUI::Plater::export_stl(), Slic3r::GUI::GLGizmoCut3D::get_cut_matrix(), Slic3r::GUI::Plater::priv::get_export_file_path(), Slic3r::GUI::GLGizmoAlignment::get_parent_box(), Slic3r::GUI::get_selected_gl_volume(), Slic3r::GUI::Plater::priv::get_selected_object_idx(), Slic3r::GUI::GLGizmoAlignment::get_selected_part_volumes(), is_any_connector(), is_any_cut_volume(), is_from_single_object(), is_single_full_instance(), Slic3r::GUI::ObjectList::layers_editing(), Slic3r::GUI::ObjectList::load_generic_subobject(), Slic3r::GUI::ObjectList::load_modifier(), Slic3r::GUI::ObjectList::load_shape_object(), Slic3r::GUI::GLGizmoCut3D::on_is_activable(), Slic3r::GUI::GLGizmoBrimEars::on_mouse(), Slic3r::GUI::GLGizmoPainterBase::on_mouse(), Slic3r::GUI::GLGizmoBrimEars::on_render(), Slic3r::GUI::CommonGizmosDataObjects::SelectionInfo::on_update(), Slic3r::GUI::ObjectList::part_selection_changed(), paste_volumes_from_clipboard(), Slic3r::GUI::GLGizmoCut3D::perform_cut(), Slic3r::GUI::GLGizmoCut3D::process_contours(), Slic3r::GUI::GLGizmoPainterBase::render_cursor_height_range(), Slic3r::GUI::Plater::show_object_info(), Slic3r::GUI::ObjectList::split_instances(), Slic3r::GUI::Emboss::start_create_volume_without_position(), Slic3r::GUI::GLGizmoCut3D::toggle_model_objects_visibility(), Slic3r::GUI::GLGizmoPainterBase::update_contours(), Slic3r::GUI::ObjectList::update_selections(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

Here is the caller graph for this function:

◆ get_scaled_instance_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::Selection::get_scaled_instance_bounding_box ( ) const
1030{
1031 assert(is_single_full_instance());
1032
1033 if (!m_scaled_instance_bounding_box.has_value()) {
1034 std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_scaled_instance_bounding_box);
1035 *bbox = BoundingBoxf3();
1036 if (m_valid) {
1037 for (unsigned int i : m_list) {
1038 const GLVolume& volume = *(*m_volumes)[i];
1039 if (volume.is_modifier)
1040 continue;
1041 Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
1042 trafo.translation().z() += volume.get_sla_shift_z();
1043 (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
1044 }
1045 }
1046 }
1048}
std::optional< BoundingBoxf3 > m_scaled_instance_bounding_box
Definition Selection.hpp:173

References Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::get_sla_shift_z(), Slic3r::GLVolume::get_volume_transformation(), is_single_full_instance(), m_list, m_scaled_instance_bounding_box, m_valid, and Slic3r::GLVolume::transformed_convex_hull_bounding_box().

Here is the call graph for this function:

◆ get_selected_object_instances()

std::set< std::pair< int, int > > Slic3r::GUI::Selection::get_selected_object_instances ( )
2190{
2191 std::set<std::pair<int, int>> instances_idxs;
2192 // BBS only support multi full object now
2194 return instances_idxs;
2195
2196 for (ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.begin(); obj_it != m_cache.content.end(); ++obj_it)
2197 {
2198 for (InstanceIdxsList::reverse_iterator inst_it = obj_it->second.rbegin(); inst_it != obj_it->second.rend(); ++inst_it)
2199 {
2200 instances_idxs.insert(std::make_pair(obj_it->first, *inst_it));
2201 }
2202 }
2203
2204 return instances_idxs;
2205}

References is_multiple_full_object(), and m_cache.

Here is the call graph for this function:

◆ get_selected_single_intance()

const ModelInstance * Slic3r::GUI::Selection::get_selected_single_intance ( ) const
464{
465 int object_idx;
466 auto mo = get_selected_single_object(object_idx);
467 if (mo) {
468 return mo->instances[get_instance_idx()];
469 }
470 return nullptr;
471}
ModelObject * get_selected_single_object(int &out_object_idx) const
Definition Selection.cpp:453

References get_instance_idx(), and get_selected_single_object().

Here is the call graph for this function:

◆ get_selected_single_object()

ModelObject * Slic3r::GUI::Selection::get_selected_single_object ( int & out_object_idx) const
454{
456 const GLVolume *gl_volume = get_first_volume();
457 out_object_idx = gl_volume->object_idx();
458 return get_model()->objects[out_object_idx];
459 }
460 return nullptr;
461}
bool is_single_volume() const
Definition Selection.hpp:281
Model * get_model() const
Definition Selection.hpp:219
bool is_single_modifier() const
Definition Selection.hpp:275
ModelObjectPtrs objects
Definition Model.hpp:1702

References get_first_volume(), get_model(), is_single_full_object(), is_single_modifier(), is_single_volume(), Slic3r::GLVolume::object_idx(), and Slic3r::Model::objects.

Referenced by get_selected_single_intance().

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

◆ get_selected_single_volume()

ModelVolume * Slic3r::GUI::Selection::get_selected_single_volume ( int & out_object_idx,
int & out_volume_idx ) const
441{
443 const GLVolume *gl_volume = get_first_volume();
444 out_object_idx = gl_volume->object_idx();
445 ModelObject *model_object = get_model()->objects[out_object_idx];
446 out_volume_idx = gl_volume->volume_idx();
447 if (out_volume_idx < model_object->volumes.size())
448 return model_object->volumes[out_volume_idx];
449 }
450 return nullptr;
451}

References get_first_volume(), get_model(), is_single_modifier(), is_single_volume(), Slic3r::GLVolume::object_idx(), Slic3r::Model::objects, Slic3r::GLVolume::volume_idx(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ get_unscaled_instance_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::Selection::get_unscaled_instance_bounding_box ( ) const
1009{
1010 assert(is_single_full_instance());
1011
1012 if (!m_unscaled_instance_bounding_box.has_value()) {
1013 std::optional<BoundingBoxf3>* bbox = const_cast<std::optional<BoundingBoxf3>*>(&m_unscaled_instance_bounding_box);
1014 *bbox = BoundingBoxf3();
1015 if (m_valid) {
1016 for (unsigned int i : m_list) {
1017 const GLVolume& volume = *(*m_volumes)[i];
1018 if (volume.is_modifier)
1019 continue;
1020 Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
1021 trafo.translation().z() += volume.get_sla_shift_z();
1022 (*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
1023 }
1024 }
1025 }
1027}
std::optional< BoundingBoxf3 > m_unscaled_instance_bounding_box
Definition Selection.hpp:170

References Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_matrix_no_scaling_factor(), Slic3r::GLVolume::get_sla_shift_z(), Slic3r::GLVolume::get_volume_transformation(), is_single_full_instance(), m_list, m_unscaled_instance_bounding_box, m_valid, and Slic3r::GLVolume::transformed_convex_hull_bounding_box().

Referenced by Slic3r::GUI::GizmoObjectManipulation::update_settings_value().

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

◆ get_unselected_volume_idxs_from()

std::vector< unsigned int > Slic3r::GUI::Selection::get_unselected_volume_idxs_from ( const std::vector< unsigned int > & volume_idxs) const
2292{
2293 std::vector<unsigned int> idxs;
2294
2295 for (unsigned int i : volume_idxs)
2296 {
2297 if (m_list.find(i) == m_list.end())
2298 idxs.push_back(i);
2299 }
2300
2301 return idxs;
2302}

References m_list.

Referenced by Slic3r::GUI::ObjectList::update_selections_on_canvas().

Here is the caller graph for this function:

◆ get_volume() [1/2]

GLVolume * Slic3r::GUI::Selection::get_volume ( unsigned int volume_idx)
990{
991 return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
992}

References m_valid, and m_volumes.

◆ get_volume() [2/2]

const GLVolume * Slic3r::GUI::Selection::get_volume ( unsigned int volume_idx) const
985{
986 return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
987}

References m_valid, and m_volumes.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_set_visible(), Slic3r::GUI::GLGizmoBrimEars::auto_generate(), Slic3r::GUI::GLGizmoCut3D::bounding_box(), Slic3r::GUI::GLGizmoPainterBase::bounding_box(), anonymous_namespace{GLGizmoEmboss.cpp}::calc_fine_position(), Slic3r::GUI::Plater::priv::can_reload_from_disk(), anonymous_namespace{EmbossJob.cpp}::find_closest(), Slic3r::GUI::GLGizmoBrimEars::find_single(), Slic3r::GUI::GLGizmoBrimEars::first_layer_slicer(), get_bounding_box_in_reference_system(), get_first_volume(), Slic3r::GUI::get_model_volume(), Slic3r::GUI::get_selected_gl_volume(), Slic3r::GUI::GLGizmoAlignment::get_selected_part_volumes(), Slic3r::GUI::get_selected_volume(), Slic3r::GUI::GLGizmoBrimEars::gizmo_event(), Slic3r::GUI::GLGizmoCut3D::has_valid_groove(), Slic3r::GUI::GLGizmoMeshBoolean::on_render(), Slic3r::GUI::GLGizmoBrimEars::register_single_mesh_pick(), Slic3r::GUI::GLGizmoMeasure::register_single_mesh_pick(), Slic3r::GUI::Plater::priv::reload_from_disk(), Slic3r::GUI::GLGizmoBrimEars::render_points(), Slic3r::GUI::Plater::priv::replace_all_with_stl(), Slic3r::GUI::GizmoObjectManipulation::reset_position_value(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), Slic3r::GUI::selection_transform(), Slic3r::GUI::Plater::priv::set_current_panel(), Slic3r::GUI::ObjectList::set_volume_type(), Slic3r::GUI::GLGizmoCut3D::set_volumes_picking_state(), Slic3r::UndoRedo::StackImpl::take_snapshot(), Slic3r::GUI::GLGizmoCut3D::transformed_bounding_box(), Slic3r::GUI::GLGizmoBrimEars::unproject_on_mesh(), and Slic3r::GUI::ObjectList::update_selections().

Here is the caller graph for this function:

◆ get_volume_idxs()

const IndicesList & Slic3r::GUI::Selection::get_volume_idxs ( ) const
inline
315{ return m_list; }

References m_list.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_set_visible(), Slic3r::GUI::GLGizmoBrimEars::auto_generate(), Slic3r::GUI::GLGizmoCut3D::bounding_box(), Slic3r::GUI::GLGizmoPainterBase::bounding_box(), anonymous_namespace{GLGizmoEmboss.cpp}::calc_fine_position(), Slic3r::GUI::Plater::priv::can_reload_from_disk(), Slic3r::GUI::Plater::priv::can_replace_all_with_stl(), Slic3r::GUI::Plater::priv::can_replace_with_stl(), anonymous_namespace{EmbossJob.cpp}::find_closest(), Slic3r::GUI::GLGizmoBrimEars::find_single(), Slic3r::GUI::GLGizmoBrimEars::first_layer_slicer(), Slic3r::GUI::get_model_volume(), Slic3r::GUI::get_selected_gl_volume(), Slic3r::GUI::GLGizmoAlignment::get_selected_part_volumes(), Slic3r::GUI::get_selected_volume(), Slic3r::GUI::GLGizmoBrimEars::gizmo_event(), Slic3r::GUI::GLGizmoCut3D::has_valid_groove(), Slic3r::GUI::SceneRaycaster::hit(), Slic3r::GUI::GLGizmoPainterBase::on_is_activable(), Slic3r::GUI::GLGizmoMeshBoolean::on_render(), Slic3r::GUI::GLGizmoBrimEars::register_single_mesh_pick(), Slic3r::GUI::GLGizmoMeasure::register_single_mesh_pick(), Slic3r::GUI::Plater::priv::reload_all_from_disk(), Slic3r::GUI::Plater::priv::reload_from_disk(), Slic3r::GUI::GLGizmoBrimEars::render_points(), Slic3r::GUI::Plater::priv::replace_all_with_stl(), Slic3r::GUI::GizmoObjectManipulation::reset_position_value(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), Slic3r::GUI::selection_transform(), Slic3r::GUI::Plater::priv::set_current_panel(), Slic3r::GUI::ObjectList::set_volume_type(), Slic3r::GUI::GLGizmoCut3D::set_volumes_picking_state(), Slic3r::GUI::Plater::show_object_info(), Slic3r::UndoRedo::StackImpl::take_snapshot(), Slic3r::GUI::GLGizmoCut3D::transformed_bounding_box(), Slic3r::GUI::GLGizmoBrimEars::unproject_on_mesh(), and Slic3r::GUI::ObjectList::update_selections().

Here is the caller graph for this function:

◆ get_volume_idxs_from_instance()

std::vector< unsigned int > Slic3r::GUI::Selection::get_volume_idxs_from_instance ( unsigned int object_idx,
unsigned int instance_idx ) const
2226{
2227 std::vector<unsigned int> idxs;
2228
2229 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
2230 {
2231 const GLVolume* v = (*m_volumes)[i];
2232 if ((v->object_idx() == (int)object_idx) && (v->instance_idx() == (int)instance_idx))
2233 idxs.push_back(i);
2234 }
2235
2236 return idxs;
2237}

References Slic3r::GLVolume::instance_idx(), m_volumes, and Slic3r::GLVolume::object_idx().

Referenced by add_instance(), get_volume_idxs_from_plate(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

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

◆ get_volume_idxs_from_object()

std::vector< unsigned int > Slic3r::GUI::Selection::get_volume_idxs_from_object ( unsigned int object_idx) const
2213{
2214 std::vector<unsigned int> idxs;
2215
2216 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
2217 {
2218 if ((*m_volumes)[i]->object_idx() == (int)object_idx)
2219 idxs.push_back(i);
2220 }
2221
2222 return idxs;
2223}

References m_volumes.

Referenced by add_object(), add_object_from_idx(), Slic3r::GUI::Plater::priv::replace_all_with_stl(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

Here is the caller graph for this function:

◆ get_volume_idxs_from_plate()

std::vector< unsigned int > Slic3r::GUI::Selection::get_volume_idxs_from_plate ( const int plate_idx) const
2257{
2258 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
2259 std::vector<unsigned int> idxs;
2260 if (!plate)
2261 return idxs;
2262
2263 for (int obj_idx = 0; obj_idx < (int)m_model->objects.size(); obj_idx++) {
2264 const ModelObject* obj = m_model->objects[obj_idx];
2265 for (int inst_idx = 0; inst_idx < (int)obj->instances.size(); inst_idx++) {
2266 // on this plate or overlapping it in some way (fully inside, oversized or partly outside)
2267 if (plate->contain_instance(obj_idx, inst_idx) || plate->intersect_instance(obj_idx, inst_idx)) {
2268 std::vector<unsigned int> inst_idxs = get_volume_idxs_from_instance(obj_idx, inst_idx);
2269 idxs.insert(idxs.end(), inst_idxs.begin(), inst_idxs.end());
2270 }
2271 }
2272 }
2273
2274 return idxs;
2275}

References Slic3r::GUI::PartPlate::contain_instance(), get_volume_idxs_from_instance(), Slic3r::ModelObject::instances, Slic3r::GUI::PartPlate::intersect_instance(), and m_model.

Referenced by add_curr_plate(), and remove_curr_plate().

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

◆ get_volume_idxs_from_volume()

std::vector< unsigned int > Slic3r::GUI::Selection::get_volume_idxs_from_volume ( unsigned int object_idx,
unsigned int instance_idx,
unsigned int volume_idx ) const
2240{
2241 std::vector<unsigned int> idxs;
2242
2243 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
2244 {
2245 const GLVolume* v = (*m_volumes)[i];
2246 if ((v->object_idx() == (int)object_idx) && (v->volume_idx() == (int)volume_idx))
2247 {
2248 if (((int)instance_idx != -1) && (v->instance_idx() == (int)instance_idx))
2249 idxs.push_back(i);
2250 }
2251 }
2252
2253 return idxs;
2254}

References Slic3r::GLVolume::instance_idx(), m_volumes, Slic3r::GLVolume::object_idx(), and Slic3r::GLVolume::volume_idx().

Referenced by add_volume(), and Slic3r::GUI::ObjectList::update_selections_on_canvas().

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

◆ get_volume_selection_mode()

EMode Slic3r::GUI::Selection::get_volume_selection_mode ( )
inline

◆ init()

bool Slic3r::GUI::Selection::init ( )
166{
167 m_arrow.init_from(straight_arrow(10.0f, 5.0f, 5.0f, 10.0f, 1.0f));
168 m_curved_arrow.init_from(circular_arrow(16, 10.0f, 5.0f, 10.0f, 5.0f, 1.0f));
169#if ENABLE_RENDER_SELECTION_CENTER
170 m_vbo_sphere.init_from(its_make_sphere(0.75, PI / 12.0));
171#endif // ENABLE_RENDER_SELECTION_CENTER
172
173 return true;
174}
GLModel m_arrow
Definition Selection.hpp:193
GLModel m_curved_arrow
Definition Selection.hpp:194
static constexpr double PI
Definition libslic3r.h:81
GLModel::Geometry circular_arrow(unsigned int resolution, float radius, float tip_height, float tip_width, float stem_width, float thickness)
Definition GLModel.cpp:997
GLModel::Geometry straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness)
Definition GLModel.cpp:1161
indexed_triangle_set its_make_sphere(double radius, double fa)
Definition TriangleMesh.cpp:1128

References Slic3r::GUI::circular_arrow(), Slic3r::its_make_sphere(), m_arrow, m_curved_arrow, PI, and Slic3r::GUI::straight_arrow().

Here is the call graph for this function:

◆ instances_changed()

void Slic3r::GUI::Selection::instances_changed ( const std::vector< size_t > & instance_ids_selected)
794{
795 assert(m_valid);
796 assert(m_mode == Instance);
797 m_list.clear();
798 for (unsigned int volume_idx = 0; volume_idx < (unsigned int)m_volumes->size(); ++ volume_idx) {
799 const GLVolume *volume = (*m_volumes)[volume_idx];
800 auto it = std::lower_bound(instance_ids_selected.begin(), instance_ids_selected.end(), volume->geometry_id.second);
801 if (it != instance_ids_selected.end() && *it == volume->geometry_id.second)
802 this->do_add_volume(volume_idx);
803 }
804 update_type();
806}

References do_add_volume(), Slic3r::GLVolume::geometry_id, Instance, m_list, m_mode, m_valid, m_volumes, set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ is_any_connector()

bool Slic3r::GUI::Selection::is_any_connector ( ) const
827{
828 const int obj_idx = get_object_idx();
829
830 if ((is_any_volume() || is_any_modifier() || is_mixed()) && // some solid_part AND/OR modifier is selected
831 obj_idx >= 0 && m_model->objects[obj_idx]->is_cut()) {
832 const ModelVolumePtrs& obj_volumes = m_model->objects[obj_idx]->volumes;
833 for (size_t vol_idx = 0; vol_idx < obj_volumes.size(); vol_idx++)
834 if (obj_volumes[vol_idx]->is_cut_connector())
835 for (const GLVolume* v : *m_volumes)
836 if (v->object_idx() == obj_idx && v->volume_idx() == (int)vol_idx && v->selected)
837 return true;
838 }
839 return false;
840}
std::vector< ModelVolume * > ModelVolumePtrs
Definition Model.hpp:139

References get_object_idx(), is_any_modifier(), is_any_volume(), is_mixed(), m_model, and m_volumes.

Here is the call graph for this function:

◆ is_any_cut_volume()

bool Slic3r::GUI::Selection::is_any_cut_volume ( ) const
843{
844 const int obj_idx = get_object_idx();
845 return is_any_volume() && obj_idx >= 0 && m_model->objects[obj_idx]->is_cut();
846}

References get_object_idx(), is_any_volume(), and m_model.

Here is the call graph for this function:

◆ is_any_modifier()

bool Slic3r::GUI::Selection::is_any_modifier ( ) const
inline
bool is_multiple_modifier() const
Definition Selection.hpp:276

References is_multiple_modifier(), and is_single_modifier().

Referenced by add(), is_any_connector(), Slic3r::GUI::ObjectList::part_selection_changed(), and Slic3r::GUI::ObjectList::update_selections().

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

◆ is_any_volume()

bool Slic3r::GUI::Selection::is_any_volume ( ) const
inline
283{ return is_single_volume() || is_multiple_volume(); }
bool is_multiple_volume() const
Definition Selection.hpp:282

References is_multiple_volume(), and is_single_volume().

Referenced by add(), ensure_not_below_bed(), is_any_connector(), is_any_cut_volume(), Slic3r::GUI::GLGizmoMmuSegmentation::on_is_activable(), Slic3r::GUI::ObjectList::part_selection_changed(), and Slic3r::GUI::ObjectList::update_selections().

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

◆ is_empty()

◆ is_enabled()

bool Slic3r::GUI::Selection::is_enabled ( ) const
inline
216{ return m_enabled; }

References m_enabled.

◆ is_from_fully_selected_instance()

bool Slic3r::GUI::Selection::is_from_fully_selected_instance ( unsigned int volume_idx) const
private
3198{
3199 if (m_mode == Instance && wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) {
3200 return true;
3201 }
3202 struct SameInstance
3203 {
3204 int obj_idx;
3205 int inst_idx;
3206 GLVolumePtrs& volumes;
3207
3208 SameInstance(int obj_idx, int inst_idx, GLVolumePtrs& volumes) : obj_idx(obj_idx), inst_idx(inst_idx), volumes(volumes) {}
3209 bool operator () (unsigned int i) { return (volumes[i]->volume_idx() >= 0) && (volumes[i]->object_idx() == obj_idx) && (volumes[i]->instance_idx() == inst_idx); }
3210 };
3211
3212 if ((unsigned int)m_volumes->size() <= volume_idx)
3213 return false;
3214
3215 GLVolume* volume = (*m_volumes)[volume_idx];
3216 int object_idx = volume->object_idx();
3217 if ((int)m_model->objects.size() <= object_idx)
3218 return false;
3219
3220 unsigned int count = (unsigned int)std::count_if(m_list.begin(), m_list.end(), SameInstance(object_idx, volume->instance_idx(), *m_volumes));
3221 return count == (unsigned int)m_model->objects[object_idx]->volumes.size();
3222}
@ CanvasAssembleView
Definition GLCanvas3D.hpp:628
std::vector< GLVolume * > GLVolumePtrs
Definition 3DScene.hpp:412

References Slic3r::GUI::GLCanvas3D::CanvasAssembleView, count, Instance, Slic3r::GLVolume::instance_idx(), m_list, m_mode, m_model, m_volumes, Slic3r::GLVolume::object_idx(), and Slic3r::GUI::plater().

Referenced by move_to_center(), rotate(), and translate().

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

◆ is_from_single_instance()

bool Slic3r::GUI::Selection::is_from_single_instance ( ) const
inline
287{ return get_instance_idx() != -1; }

References get_instance_idx().

Referenced by Slic3r::GUI::Plater::priv::can_mirror(), Slic3r::GUI::Plater::can_paste_from_clipboard(), Slic3r::GUI::GLGizmoPainterBase::data_changed(), Slic3r::GUI::GLGizmoBrimEars::on_render(), paste_from_clipboard(), requires_local_axes(), transform_instance_relative(), and Slic3r::GUI::ObjectList::update_selections().

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

◆ is_from_single_object()

bool Slic3r::GUI::Selection::is_from_single_object ( ) const
880{
881 const int idx = get_object_idx();
882 return 0 <= idx && idx < 1000;
883}

References get_object_idx().

Referenced by Slic3r::GUI::GLGizmoFlatten::data_changed().

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

◆ is_instance_mode()

bool Slic3r::GUI::Selection::is_instance_mode ( ) const
inline
290{ return m_mode == Instance; }

References Instance, and m_mode.

◆ is_mixed()

bool Slic3r::GUI::Selection::is_mixed ( ) const
inline
286{ return m_type == Mixed; }

References m_type, and Mixed.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_settings(), erase(), is_any_connector(), Slic3r::GUI::ObjectList::part_selection_changed(), and Slic3r::GUI::ObjectList::update_selections().

Here is the caller graph for this function:

◆ is_multiple_full_instance()

◆ is_multiple_full_object()

◆ is_multiple_modifier()

bool Slic3r::GUI::Selection::is_multiple_modifier ( ) const
inline
276{ return m_type == MultipleModifier; }

References m_type, and MultipleModifier.

Referenced by is_any_modifier().

Here is the caller graph for this function:

◆ is_multiple_volume()

bool Slic3r::GUI::Selection::is_multiple_volume ( ) const
inline
282{ return m_type == MultipleVolume; }

References m_type, and MultipleVolume.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_per_object_process(), Slic3r::GUI::MenuFactory::append_menu_item_settings(), and is_any_volume().

Here is the caller graph for this function:

◆ is_single_full_instance()

bool Slic3r::GUI::Selection::is_single_full_instance ( ) const
849{
851 return true;
852
854 return get_instance_idx() != -1;
855
856 if (m_list.empty() || m_volumes->empty())
857 return false;
858
859 int object_idx = m_valid ? get_object_idx() : -1;
860 if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
861 return false;
862
863 int instance_idx = (*m_volumes)[*m_list.begin()]->instance_idx();
864
865 std::set<int> volumes_idxs;
866 for (unsigned int i : m_list) {
867 const GLVolume* v = (*m_volumes)[i];
868 if (object_idx != v->object_idx() || instance_idx != v->instance_idx())
869 return false;
870
871 int volume_idx = v->volume_idx();
872 if (volume_idx >= 0)
873 volumes_idxs.insert(volume_idx);
874 }
875
876 return m_model->objects[object_idx]->volumes.size() == volumes_idxs.size();
877}

References get_instance_idx(), get_object_idx(), Slic3r::GLVolume::instance_idx(), m_list, m_model, m_type, m_valid, m_volumes, Slic3r::GLVolume::object_idx(), SingleFullInstance, SingleFullObject, and Slic3r::GLVolume::volume_idx().

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_export_drc(), Slic3r::GUI::MenuFactory::append_menu_item_export_stl(), Slic3r::GUI::MenuFactory::append_menu_item_per_object_process(), Slic3r::GUI::MenuFactory::append_menu_item_per_object_settings(), Slic3r::GUI::ObjectList::can_split_instances(), Slic3r::GUI::GizmoObjectManipulation::change_absolute_rotation_value(), Slic3r::GUI::GizmoObjectManipulation::change_rotation_value(), Slic3r::GUI::GizmoObjectManipulation::change_scale_value(), Slic3r::GUI::GizmoObjectManipulation::change_size_value(), Slic3r::GUI::GLGizmoFlatten::data_changed(), Slic3r::GUI::GLGizmoRotate3D::data_changed(), Slic3r::GUI::GLGizmoScale3D::data_changed(), Slic3r::GUI::GizmoObjectManipulation::do_render_move_window(), erase(), Slic3r::GUI::face_selected_volume_to_camera(), get_full_scaled_instance_bounding_box(), get_full_unscaled_instance_bounding_box(), get_full_unscaled_instance_local_bounding_box(), get_scaled_instance_bounding_box(), Slic3r::GUI::GLGizmoMove3D::get_tooltip(), Slic3r::GUI::GLGizmoScale3D::get_tooltip(), get_unscaled_instance_bounding_box(), anonymous_namespace{SurfaceDrag.cpp}::is_embossed_object(), Slic3r::GUI::ObjectList::is_instance_or_object_selected(), is_single_volume_instance(), Slic3r::GUI::GLGizmoBrimEars::on_is_activable(), Slic3r::GUI::GLGizmoCut3D::on_is_activable(), Slic3r::GUI::GLGizmoMmuSegmentation::on_is_activable(), Slic3r::GUI::GLGizmoPainterBase::on_is_activable(), Slic3r::GUI::GLGizmoFlatten::on_mouse(), Slic3r::GUI::GLGizmoFlatten::on_render(), Slic3r::GUI::Plater::priv::on_right_click(), Slic3r::GUI::ObjectList::part_selection_changed(), render_sidebar_hints(), requires_uniform_scale(), Slic3r::GUI::GizmoObjectManipulation::reset_position_value(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), scale_and_translate(), Slic3r::GUI::selection_transform(), Slic3r::GUI::Plater::show_object_info(), Slic3r::GUI::GLGizmoScale3D::update_grabbers_data(), Slic3r::GUI::GizmoObjectManipulation::update_reset_buttons_visibility(), Slic3r::GUI::ObjectList::update_selections(), and Slic3r::GUI::GizmoObjectManipulation::update_settings_value().

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

◆ is_single_full_object()

◆ is_single_modifier()

bool Slic3r::GUI::Selection::is_single_modifier ( ) const
inline

◆ is_single_text()

bool Slic3r::GUI::Selection::is_single_text ( ) const
899{
901 return false;
902
903 const GLVolume* gl_volume = (*m_volumes)[*m_list.begin()];
904 const ModelVolume* model_volume = m_model->objects[gl_volume->object_idx()]->volumes[gl_volume->volume_idx()];
905
906 return model_volume && model_volume->text_configuration.has_value();
907}
bool is_single_volume_or_modifier() const
Definition Selection.hpp:291

References is_single_volume_or_modifier(), m_list, m_model, Slic3r::GLVolume::object_idx(), Slic3r::ModelVolume::text_configuration, and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ is_single_volume()

◆ is_single_volume_instance()

bool Slic3r::GUI::Selection::is_single_volume_instance ( ) const
inline
292{ return is_single_full_instance() && m_list.size() == 1; }

References is_single_full_instance(), and m_list.

Referenced by Slic3r::GUI::GLGizmoEmboss::on_render().

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

◆ is_single_volume_or_modifier()

◆ is_sla_compliant()

bool Slic3r::GUI::Selection::is_sla_compliant ( ) const
886{
887 if (m_mode == Volume)
888 return false;
889
890 for (unsigned int i : m_list) {
891 if ((*m_volumes)[i]->is_modifier)
892 return false;
893 }
894
895 return true;
896}

References m_list, m_mode, m_volumes, and Volume.

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

Here is the caller graph for this function:

◆ is_wipe_tower()

◆ lock_volume_selection_mode()

void Slic3r::GUI::Selection::lock_volume_selection_mode ( )
inline
bool m_volume_selection_locked
Definition Selection.hpp:208

References m_volume_selection_locked.

◆ matches()

bool Slic3r::GUI::Selection::matches ( const std::vector< unsigned int > & volume_idxs) const
941{
942 unsigned int count = 0;
943
944 for (unsigned int i : volume_idxs) {
945 if (m_list.find(i) != m_list.end())
946 ++count;
947 else
948 return false;
949 }
950
951 return count == (unsigned int)m_list.size();
952}

References count, and m_list.

Referenced by add_instance(), add_object(), add_volume(), and add_volumes().

Here is the caller graph for this function:

◆ mirror()

void Slic3r::GUI::Selection::mirror ( Axis axis,
TransformationType transformation_type )
1709{
1710 const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
1711 scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
1712}
void mirror(Axis axis, TransformationType transformation_type)
Definition Selection.cpp:1708
void scale_and_translate(const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type)
Definition Selection.cpp:1627
@ Y
Definition libslic3r.h:142
@ X
Definition libslic3r.h:141

References mirror(), scale_and_translate(), Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by Slic3r::GUI::GLGizmoEmboss::do_mirror(), Slic3r::GUI::GLGizmoSVG::draw_mirroring(), and mirror().

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

◆ move_to_center()

void Slic3r::GUI::Selection::move_to_center ( const Vec3d & displacement,
bool local = false )
1247{
1248 if (!m_valid)
1249 return;
1250
1251 EMode translation_type = m_mode;
1252 //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": %1%, displacement {%2%, %3%, %4%}") % __LINE__ % displacement(X) % displacement(Y) % displacement(Z);
1253
1254 set_caches();
1255 for (unsigned int i : m_list) {
1256 GLVolume& v = *(*m_volumes)[i];
1257 if (m_mode == Volume) {
1258 if (local)
1259 v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement);
1260 else {
1261 const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
1262 v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
1263 }
1264 }
1265 else if (m_mode == Instance) {
1267 v.set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement);
1268 }
1269 else {
1270 const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
1271 v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
1272 translation_type = Volume;
1273 }
1274 }
1275 }
1277}
EMode
Definition Selection.hpp:52
bool is_from_fully_selected_instance(unsigned int volume_idx) const
Definition Selection.cpp:3197
void set_caches()
Definition Selection.cpp:2537

References Instance, is_from_fully_selected_instance(), m_cache, m_list, m_mode, m_valid, set_bounding_boxes_dirty(), set_caches(), Slic3r::GLVolume::set_instance_offset(), Slic3r::GLVolume::set_volume_offset(), and Volume.

Referenced by center(), and center_plate().

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

◆ notify_instance_update()

void Slic3r::GUI::Selection::notify_instance_update ( int object_idx,
int instance_idx )
1841{
1842 //BBS: notify instance updates to part plater list
1843 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
1844
1845 if (object_idx == -1)
1846 {
1847 std::set<std::pair<int, int>> notify_set;
1848 for (unsigned int i : m_list)
1849 {
1850 int obj_index = (*m_volumes)[i]->object_idx();
1851 // Skip the wipe tower: its synthetic id (>= 1000) is not an index into m_model->objects.
1852 if (obj_index >= 1000)
1853 continue;
1854 //-1 means all the instance in this object
1855 if (instance_idx == -1)
1856 {
1857 ModelObject* object = m_model->objects[obj_index];
1858
1859 for (int instance_index = 0; instance_index < object->instances.size(); instance_index++)
1860 {
1861 std::pair<int, int> notify_index(obj_index, instance_index);
1862 if (notify_set.find(notify_index) == notify_set.end()) {
1863 plate_list.notify_instance_update(obj_index, instance_index);
1864 notify_set.insert(notify_index);
1865 }
1866 }
1867 }
1868 else {
1869 std::pair<int, int> notify_index(obj_index, instance_idx);
1870 if (notify_set.find(notify_index) == notify_set.end()) {
1871 plate_list.notify_instance_update(obj_index, instance_idx);
1872 notify_set.insert(notify_index);
1873 }
1874 }
1875 }
1876 }
1877 else
1878 {
1879 if (instance_idx == -1)
1880 {
1881 ModelObject* object = m_model->objects[object_idx];
1882
1883 for (int index = 0; index < object->instances.size(); index++)
1884 {
1885 plate_list.notify_instance_update(object_idx, index);
1886 }
1887 }
1888 else
1889 plate_list.notify_instance_update(object_idx, instance_idx);
1890 }
1891}

References m_list, m_model, and Slic3r::GUI::PartPlateList::notify_instance_update().

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

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

◆ paste_from_clipboard()

void Slic3r::GUI::Selection::paste_from_clipboard ( )
2165{
2166 if (!m_valid || m_clipboard.is_empty())
2167 return;
2168
2169 switch (m_clipboard.get_mode())
2170 {
2171 case Volume:
2172 {
2175
2176 break;
2177 }
2178 case Instance:
2179 {
2180 if (m_mode == Instance)
2182
2183 break;
2184 }
2185 }
2186}
void paste_volumes_from_clipboard()
Definition Selection.cpp:3224
void paste_objects_from_clipboard()
Definition Selection.cpp:3293
bool is_from_single_instance() const
Definition Selection.hpp:287

References Instance, is_from_single_instance(), m_clipboard, m_mode, m_valid, paste_objects_from_clipboard(), paste_volumes_from_clipboard(), and Volume.

Referenced by Slic3r::GUI::CloneDialog::CloneDialog(), and clone().

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

◆ paste_objects_from_clipboard()

void Slic3r::GUI::Selection::paste_objects_from_clipboard ( )
private
3294{
3295#ifdef _DEBUG
3297#endif /* _DEBUG */
3298
3299 std::vector<size_t> object_idxs;
3300 const ModelObjectPtrs& src_objects = m_clipboard.get_objects();
3301 PartPlate * plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
3302
3303 //BBS: if multiple objects are selected, move them as a whole after copy
3304 Vec2d shift_all = {0, 0};
3305 Vec2f empty_cell_all = {0, 0};
3306 if (src_objects.size() > 1) {
3307 BoundingBoxf3 bbox_all;
3308 for (const ModelObject *src_object : src_objects) {
3309 BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(size_t(0));
3310 bbox_all.merge(bbox);
3311 }
3312 auto bsize = bbox_all.size();
3313 if (bsize.x() < bsize.y())
3314 shift_all = {bbox_all.size().x(), 0};
3315 else
3316 shift_all = {0, bbox_all.size().y()};
3317 }
3318
3319 for (size_t i=0;i<src_objects.size();i++)
3320 {
3321 const ModelObject *src_object = src_objects[i];
3322 ModelObject* dst_object = m_model->add_object(*src_object);
3323
3324 // BBS: find an empty cell to put the copied object
3325 BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(size_t(0));
3326
3327 Vec3d displacement;
3328 bool in_current = plate->intersects(bbox);
3329 auto start_point = in_current ? bbox.center() : plate->get_build_volume().center();
3330 auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
3331 if (shift_all(0) != 0 || shift_all(1) != 0) {
3332 // BBS: if multiple objects are selected, move them as a whole after copy
3333 if (i == 0) empty_cell_all = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1,bbox.size()(1)+1});
3334 auto instance_shift = src_object->instances.front()->get_offset() - src_objects[0]->instances.front()->get_offset();
3335 displacement = {shift_all.x() + empty_cell_all.x() + instance_shift.x(), shift_all.y() + empty_cell_all.y() + instance_shift.y(), start_offset(2)};
3336 } else {
3337 // BBS: if only one object is copied, find an empty cell to put it
3338 auto point_offset = start_offset - start_point;
3339 auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1});
3340 displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
3341 }
3342
3343 for (ModelInstance* inst : dst_object->instances) {
3344 inst->set_offset(displacement);
3345
3346 //BBS init asssmble transformation
3347 Geometry::Transformation t = inst->get_transformation();
3348 inst->set_assemble_transformation(t);
3349 }
3350
3351 object_idxs.push_back(m_model->objects.size() - 1);
3352#ifdef _DEBUG
3354#endif /* _DEBUG */
3355 }
3356
3357 wxGetApp().obj_list()->paste_objects_into_list(object_idxs);
3358
3359#ifdef _DEBUG
3361#endif /* _DEBUG */
3362}
void check_model_ids_validity(const Model &model)
Definition Model.cpp:4375
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:64
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67

References Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::check_model_ids_validity(), Slic3r::GUI::PartPlate::get_build_volume(), Slic3r::ModelInstance::get_transformation(), Slic3r::ModelObject::instance_convex_hull_bounding_box(), Slic3r::ModelObject::instances, Slic3r::GUI::PartPlate::intersects(), m_clipboard, m_model, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::ModelInstance::set_assemble_transformation(), Slic3r::ModelInstance::set_offset(), and Slic3r::BoundingBox3Base< PointType >::size().

Referenced by paste_from_clipboard().

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

◆ paste_volumes_from_clipboard()

void Slic3r::GUI::Selection::paste_volumes_from_clipboard ( )
private
3225{
3226#ifdef _DEBUG
3228#endif /* _DEBUG */
3229
3230 int dst_obj_idx = get_object_idx();
3231 if ((dst_obj_idx < 0) || ((int)m_model->objects.size() <= dst_obj_idx))
3232 return;
3233
3234 ModelObject* dst_object = m_model->objects[dst_obj_idx];
3235
3236 int dst_inst_idx = get_instance_idx();
3237 if ((dst_inst_idx < 0) || ((int)dst_object->instances.size() <= dst_inst_idx))
3238 return;
3239
3240 ModelObject* src_object = m_clipboard.get_object(0);
3241 if (src_object != nullptr)
3242 {
3243 ModelInstance* dst_instance = dst_object->instances[dst_inst_idx];
3244 BoundingBoxf3 dst_instance_bb = dst_object->instance_bounding_box(dst_inst_idx);
3245 Transform3d src_matrix = src_object->instances[0]->get_transformation().get_matrix_no_offset();
3246 Transform3d dst_matrix = dst_instance->get_transformation().get_matrix_no_offset();
3247 bool from_same_object = (src_object->input_file == dst_object->input_file) && src_matrix.isApprox(dst_matrix);
3248
3249 // used to keep relative position of multivolume selections when pasting from another object
3250 BoundingBoxf3 total_bb;
3251
3252 ModelVolumePtrs volumes;
3253 for (ModelVolume* src_volume : src_object->volumes)
3254 {
3255 ModelVolume* dst_volume = dst_object->add_volume(*src_volume);
3256 dst_volume->set_new_unique_id();
3257 if (from_same_object)
3258 {
3259// // if the volume comes from the same object, apply the offset in world system
3260// double offset = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.05);
3261// dst_volume->translate(dst_matrix.inverse() * Vec3d(offset, offset, 0.0));
3262 }
3263 else
3264 {
3265 // if the volume comes from another object, apply the offset as done when adding modifiers
3266 // see ObjectList::load_generic_subobject()
3267 total_bb.merge(dst_volume->mesh().bounding_box().transformed(src_volume->get_matrix()));
3268 }
3269
3270 volumes.push_back(dst_volume);
3271#ifdef _DEBUG
3273#endif /* _DEBUG */
3274 }
3275
3276 // keeps relative position of multivolume selections
3277 if (!from_same_object)
3278 {
3279 for (ModelVolume* v : volumes)
3280 {
3281 v->set_offset((v->get_offset() - total_bb.center()) + dst_matrix.inverse() * (Vec3d(dst_instance_bb.max(0), dst_instance_bb.min(1), dst_instance_bb.min(2)) + 0.5 * total_bb.size() - dst_instance->get_transformation().get_offset()));
3282 }
3283 }
3284
3285 wxGetApp().obj_list()->paste_volumes_into_list(dst_obj_idx, volumes);
3286 }
3287
3288#ifdef _DEBUG
3290#endif /* _DEBUG */
3291}

References Slic3r::ModelObject::add_volume(), Slic3r::TriangleMesh::bounding_box(), Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::check_model_ids_validity(), get_instance_idx(), Slic3r::ModelVolume::get_matrix(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), get_object_idx(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::ModelInstance::get_transformation(), Slic3r::ModelObject::input_file, Slic3r::ModelObject::instance_bounding_box(), Slic3r::ModelObject::instances, m_clipboard, m_model, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::ModelVolume::mesh(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::ModelVolume::set_new_unique_id(), Slic3r::BoundingBox3Base< PointType >::size(), Slic3r::BoundingBoxf3::transformed(), and Slic3r::ModelObject::volumes.

Referenced by paste_from_clipboard().

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

◆ query_real_volume_idx_from_other_view()

int Slic3r::GUI::Selection::query_real_volume_idx_from_other_view ( unsigned int object_idx,
unsigned int instance_idx,
unsigned int model_volume_idx )
183{
184 for (int i = 0; i < m_volumes->size(); i++) {
185 auto v = (*m_volumes)[i];
186 if (v->object_idx() == object_idx && instance_idx == v->instance_idx() && model_volume_idx == v->volume_idx()) {
187 return i;
188 }
189 }
190 return -1;
191}

References m_volumes.

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

Here is the caller graph for this function:

◆ remove()

void Slic3r::GUI::Selection::remove ( unsigned int volume_idx)
262{
263 if (!m_valid || (unsigned int)m_volumes->size() <= volume_idx)
264 return;
265
266 if (!contains_volume(volume_idx))
267 return;
268
269 wxGetApp().plater()->take_snapshot(std::string("Selection-Remove!"), UndoRedo::SnapshotType::Selection);
270
271 GLVolume* volume = (*m_volumes)[volume_idx];
272
273 switch (m_mode)
274 {
275 case Volume:
276 {
277 do_remove_volume(volume_idx);
278 break;
279 }
280 case Instance:
281 {
282 do_remove_instance(volume->object_idx(), volume->instance_idx());
283 break;
284 }
285 }
286
287 update_type();
289}
void do_remove_instance(unsigned int object_idx, unsigned int instance_idx)
Definition Selection.cpp:2580

References contains_volume(), do_remove_instance(), do_remove_volume(), Instance, Slic3r::GLVolume::instance_idx(), m_mode, m_valid, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), update_type(), and Volume.

Here is the call graph for this function:

◆ remove_all()

void Slic3r::GUI::Selection::remove_all ( )
710{
711 if (!m_valid)
712 return;
713
714 if (is_empty())
715 return;
716
717// Not taking the snapshot with non-empty Redo stack will likely be more confusing than losing the Redo stack.
718// Let's wait for user feedback.
719// if (!wxGetApp().plater()->can_redo())
720 wxGetApp().plater()->take_snapshot(std::string("Selection-Remove All!"), UndoRedo::SnapshotType::Selection);
721
723 clear();
724}

References clear(), Instance, is_empty(), m_mode, m_valid, and Slic3r::UndoRedo::Selection.

Referenced by Slic3r::GUI::ObjectList::update_selections_on_canvas().

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

◆ remove_curr_plate()

void Slic3r::GUI::Selection::remove_curr_plate ( )
508{
509 if (!m_valid)
510 return;
511
512 std::vector<unsigned int> volume_idxs = get_volume_idxs_from_plate(wxGetApp().plater()->get_partplate_list().get_curr_plate_index());
513 if (volume_idxs.empty())
514 return;
515
516 wxGetApp().plater()->take_snapshot(std::string("Selection-Delete Curr Plate All"));
518 clear();
519 do_add_volumes(volume_idxs);
520
521 update_type();
523
524 erase();
525}

References clear(), do_add_volumes(), erase(), get_volume_idxs_from_plate(), Instance, m_mode, m_valid, Slic3r::GUI::plater(), set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ remove_instance()

void Slic3r::GUI::Selection::remove_instance ( unsigned int object_idx,
unsigned int instance_idx )
353{
354 if (!m_valid)
355 return;
356
357 wxGetApp().plater()->take_snapshot(std::string("Selection-Remove Instance"), UndoRedo::SnapshotType::Selection);
358
359 do_remove_instance(object_idx, instance_idx);
360
361 update_type();
363}

References do_remove_instance(), m_valid, Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ remove_object()

void Slic3r::GUI::Selection::remove_object ( unsigned int object_idx)
316{
317 if (!m_valid)
318 return;
319
320 wxGetApp().plater()->take_snapshot(std::string("Selection-Remove Object"), UndoRedo::SnapshotType::Selection);
321
322 do_remove_object(object_idx);
323
324 update_type();
326}
void do_remove_object(unsigned int object_idx)
Definition Selection.cpp:2589

References do_remove_object(), m_valid, Slic3r::UndoRedo::Selection, set_bounding_boxes_dirty(), and update_type().

Here is the call graph for this function:

◆ remove_volume()

void Slic3r::GUI::Selection::remove_volume ( unsigned int object_idx,
unsigned int volume_idx )
388{
389 if (!m_valid)
390 return;
391
392 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
393 GLVolume* v = (*m_volumes)[i];
394 if (v->object_idx() == (int)object_idx && v->volume_idx() == (int)volume_idx)
396 }
397
398 update_type();
400}

References do_remove_volume(), m_valid, m_volumes, Slic3r::GLVolume::object_idx(), set_bounding_boxes_dirty(), update_type(), and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ remove_volumes()

void Slic3r::GUI::Selection::remove_volumes ( EMode mode,
const std::vector< unsigned int > & volume_idxs )
426{
427 if (!m_valid)
428 return;
429
430 m_mode = mode;
431 for (unsigned int i : volume_idxs) {
432 if (i < (unsigned int)m_volumes->size())
434 }
435
436 update_type();
438}

References do_remove_volume(), m_mode, m_valid, m_volumes, set_bounding_boxes_dirty(), and update_type().

Referenced by Slic3r::GUI::ObjectList::update_selections_on_canvas().

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

◆ render()

void Slic3r::GUI::Selection::render ( float scale_factor = 1.0)
1999{
2000 if (!m_valid || is_empty())
2001 return;
2002
2003 m_scale_factor = scale_factor;
2004 // render cumulative bounding box of selected volumes
2005 const auto& [box, trafo] = get_bounding_box_in_current_reference_system();
2006 const bool auto_drop = get_auto_drop();
2007 render_bounding_box(box, trafo, auto_drop,
2008 wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView ? ColorRGB::YELLOW(): ColorRGB::WHITE());
2010}
static const ColorRGB YELLOW()
Definition Color.hpp:69
static const ColorRGB WHITE()
Definition Color.hpp:70
void render_bounding_box(const BoundingBoxf3 &box, const ColorRGB &color, float scale)
Definition Selection.hpp:394
bool get_auto_drop() const
Definition Selection.cpp:637
void render_synchronized_volumes()
Definition Selection.cpp:2598
const std::pair< BoundingBoxf3, Transform3d > & get_bounding_box_in_current_reference_system() const
Definition Selection.cpp:1107

References Slic3r::GUI::GLCanvas3D::CanvasAssembleView, get_auto_drop(), get_bounding_box_in_current_reference_system(), is_empty(), m_scale_factor, m_valid, Slic3r::GUI::plater(), render_bounding_box(), render_synchronized_volumes(), Slic3r::ColorRGB::WHITE(), and Slic3r::ColorRGB::YELLOW().

Here is the call graph for this function:

◆ render_bounding_box() [1/3]

void Slic3r::GUI::Selection::render_bounding_box ( const BoundingBoxf3 & box,
const ColorRGB & color,
float scale )
inline
394 {
396 render_bounding_box(box, Transform3d::Identity(), get_auto_drop(), color);
397 }
void scale(const Vec3d &scale, TransformationType transformation_type)
Definition Selection.cpp:1475

References get_auto_drop(), m_scale_factor, render_bounding_box(), and scale().

Referenced by render(), render_bounding_box(), render_bounding_box(), and render_synchronized_volumes().

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

◆ render_bounding_box() [2/3]

void Slic3r::GUI::Selection::render_bounding_box ( const BoundingBoxf3 & box,
const Transform3d & trafo,
const bool auto_drop,
const ColorRGB & color )
private
2638{
2639 const BoundingBoxf3& curr_box = m_box.get_bounding_box();
2640 const bool curr_auto_drop = m_auto_drop;
2641
2642 if (!m_box.is_initialized() || !is_approx(box.min, curr_box.min) || !is_approx(box.max, curr_box.max) || curr_auto_drop != auto_drop) {
2643 m_box.reset();
2644 m_auto_drop = auto_drop;
2645
2646 const Vec3f b_min = box.min.cast<float>();
2647 const Vec3f b_max = box.max.cast<float>();
2648 const Vec3f size = 0.2f * box.size().cast<float>();
2649
2650 // 48 brackets + (24 if auto_drop == false)
2651 int total_vertices = 48 + (auto_drop ? 0 : 24);
2652
2653 GLModel::Geometry init_data;
2655 init_data.reserve_vertices(total_vertices);
2656 init_data.reserve_indices(total_vertices);
2657
2658 // vertices
2659 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z()));
2660 init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_min.y(), b_min.z()));
2661 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z()));
2662 init_data.add_vertex(Vec3f(b_min.x(), b_min.y() + size.y(), b_min.z()));
2663 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z()));
2664 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_min.z() + size.z()));
2665
2666 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z()));
2667 init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_min.y(), b_min.z()));
2668 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z()));
2669 init_data.add_vertex(Vec3f(b_max.x(), b_min.y() + size.y(), b_min.z()));
2670 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z()));
2671 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_min.z() + size.z()));
2672
2673 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z()));
2674 init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_max.y(), b_min.z()));
2675 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z()));
2676 init_data.add_vertex(Vec3f(b_max.x(), b_max.y() - size.y(), b_min.z()));
2677 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z()));
2678 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_min.z() + size.z()));
2679
2680 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z()));
2681 init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_max.y(), b_min.z()));
2682 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z()));
2683 init_data.add_vertex(Vec3f(b_min.x(), b_max.y() - size.y(), b_min.z()));
2684 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z()));
2685 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_min.z() + size.z()));
2686
2687 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z()));
2688 init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_min.y(), b_max.z()));
2689 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z()));
2690 init_data.add_vertex(Vec3f(b_min.x(), b_min.y() + size.y(), b_max.z()));
2691 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z()));
2692 init_data.add_vertex(Vec3f(b_min.x(), b_min.y(), b_max.z() - size.z()));
2693
2694 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z()));
2695 init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_min.y(), b_max.z()));
2696 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z()));
2697 init_data.add_vertex(Vec3f(b_max.x(), b_min.y() + size.y(), b_max.z()));
2698 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z()));
2699 init_data.add_vertex(Vec3f(b_max.x(), b_min.y(), b_max.z() - size.z()));
2700
2701 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z()));
2702 init_data.add_vertex(Vec3f(b_max.x() - size.x(), b_max.y(), b_max.z()));
2703 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z()));
2704 init_data.add_vertex(Vec3f(b_max.x(), b_max.y() - size.y(), b_max.z()));
2705 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z()));
2706 init_data.add_vertex(Vec3f(b_max.x(), b_max.y(), b_max.z() - size.z()));
2707
2708 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z()));
2709 init_data.add_vertex(Vec3f(b_min.x() + size.x(), b_max.y(), b_max.z()));
2710 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z()));
2711 init_data.add_vertex(Vec3f(b_min.x(), b_max.y() - size.y(), b_max.z()));
2712 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z()));
2713 init_data.add_vertex(Vec3f(b_min.x(), b_max.y(), b_max.z() - size.z()));
2714
2715 // Indicate that auto_drop == false, by drawing an arrow on bottom corners
2716 if (!auto_drop) {
2717 float visual_scale = m_scale_factor;
2718 float head_s = 2.0f * visual_scale; // Width of the arrowhead wings
2719 float z_gap = 1.0f * visual_scale; // Gap between box and arrow tip
2720 float arrow_h = 5.0f * visual_scale; // Total height of the arrow stem
2721
2722 // 4 bottom corners
2723 std::vector<Vec3f> corners = {{b_min.x(), b_min.y(), b_min.z()},
2724 {b_max.x(), b_min.y(), b_min.z()},
2725 {b_max.x(), b_max.y(), b_min.z()},
2726 {b_min.x(), b_max.y(), b_min.z()}};
2727
2728 for (const auto& pt : corners) {
2729 Vec3f tip = {pt.x(), pt.y(), pt.z() - z_gap};
2730 Vec3f base = {pt.x(), pt.y(), tip.z() - arrow_h};
2731
2732 // Stem
2733 init_data.add_vertex(base);
2734 init_data.add_vertex(tip);
2735
2736 // Wings
2737 // Determine direction to the center of the footprint
2738 float dirX = (pt.x() == b_min.x()) ? head_s : -head_s;
2739 float dirY = (pt.y() == b_min.y()) ? head_s : -head_s;
2740
2741 // Wing 1 (X-Inward)
2742 init_data.add_vertex(tip);
2743 init_data.add_vertex(Vec3f(tip.x() + dirX, tip.y(), tip.z() - head_s));
2744
2745 // Wing 2 (Y-Inward)
2746 init_data.add_vertex(tip);
2747 init_data.add_vertex(Vec3f(tip.x(), tip.y() + dirY, tip.z() - head_s));
2748 }
2749 }
2750
2751 // Finalize indices
2752 for (unsigned int i = 0; i < init_data.vertices_count(); ++i) {
2753 init_data.add_index(i);
2754 }
2755
2756 m_box.init_from(std::move(init_data));
2757 }
2758
2760
2761#if SLIC3R_OPENGL_ES
2762 GLShaderProgram* shader = wxGetApp().get_shader("dashed_lines");
2763#else
2764 if (!OpenGLManager::get_gl_info().is_core_profile())
2766
2767 GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
2768#endif // SLIC3R_OPENGL_ES
2769 if (shader == nullptr)
2770 return;
2771
2772 shader->start_using();
2773 const Camera& camera = wxGetApp().plater()->get_camera();
2774 shader->set_uniform("view_model_matrix", camera.get_view_matrix() * trafo);
2775 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
2776#if !SLIC3R_OPENGL_ES
2777 if (OpenGLManager::get_gl_info().is_core_profile()) {
2778#endif // !SLIC3R_OPENGL_ES
2779 const std::array<int, 4>& viewport = camera.get_viewport();
2780 shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3])));
2781 shader->set_uniform("width", 1.5f);
2782 shader->set_uniform("gap_size", 0.0f);
2783#if !SLIC3R_OPENGL_ES
2784 }
2785#endif // !SLIC3R_OPENGL_ES
2786 m_box.set_color(to_rgba(color));
2787 m_box.render();
2788 shader->stop_using();
2789}
#define glsafe(cmd)
Definition OpenGLUtils.hpp:25
bool is_core_profile() const
Definition OpenGLManager.hpp:53
static const GLInfo & get_gl_info()
Definition OpenGLManager.hpp:106
bool m_auto_drop
Definition Selection.hpp:196
GLModel m_box
Definition Selection.hpp:195
#define glEnable
Definition gl.h:3667
#define GL_DEPTH_TEST
Definition gl.h:574
#define glLineWidth
Definition gl.h:4215
@ Camera
Definition Shortcuts.hpp:72
ColorRGBA to_rgba(const ColorRGB &other_rgb)
Definition Color.cpp:407

References Slic3r::GUI::GLModel::Geometry::add_index(), Slic3r::GUI::GLModel::Geometry::add_vertex(), Slic3r::GUI::GLModel::Geometry::format, Slic3r::GUI::OpenGLManager::get_gl_info(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), Slic3r::GUI::Camera::get_viewport(), GL_DEPTH_TEST, glEnable, glLineWidth, glsafe, Slic3r::is_approx(), Slic3r::GUI::OpenGLManager::GLInfo::is_core_profile(), Slic3r::GUI::GLModel::Geometry::Lines, m_auto_drop, m_box, m_scale_factor, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GUI::GLModel::Geometry::P3, Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::BoundingBox3Base< PointType >::size(), Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), Slic3r::to_rgba(), and Slic3r::GUI::GLModel::Geometry::vertices_count().

Here is the call graph for this function:

◆ render_bounding_box() [3/3]

void Slic3r::GUI::Selection::render_bounding_box ( const BoundingBoxf3 & box,
const Transform3d & trafo,
const ColorRGB & color,
float scale )
inline
399 {
401 render_bounding_box(box, trafo, get_auto_drop(), color);
402 }

References get_auto_drop(), m_scale_factor, render_bounding_box(), and scale().

Here is the call graph for this function:

◆ render_sidebar_hints()

void Slic3r::GUI::Selection::render_sidebar_hints ( const std::string & sidebar_field,
bool uniform_scale )
2044{
2045 if (sidebar_field.empty())
2046 return;
2047
2048 GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light");
2049 if (shader == nullptr)
2050 return;
2051
2052 shader->start_using();
2053
2055
2057 Transform3d orient_matrix = Transform3d::Identity();
2058
2059 if (!boost::starts_with(sidebar_field, "layer")) {
2060 shader->set_uniform("emission_factor", 0.05f);
2061 const auto &[box, box_trafo] = get_bounding_box_in_current_reference_system();
2062 // BBS
2063 if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
2064 center = box_trafo.translation();
2065 orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
2066 } else if (is_single_volume_or_modifier()) {
2067 if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
2068 if (wxGetApp().obj_manipul()->is_local_coordinates()) {
2069 orient_matrix = get_bounding_box_in_current_reference_system().second;
2070 orient_matrix.translation() = Vec3d::Zero();
2071 } else {
2072 orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
2073 center = box_trafo.translation();
2074 }
2075 }
2076 } else {
2077 if (requires_local_axes()) {
2078 orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
2079 }
2080 }
2081 }
2082 const Transform3d base_matrix = Geometry::assemble_transform(center);
2083
2084 if (!boost::starts_with(sidebar_field, "layer"))
2086 if (boost::starts_with(sidebar_field, "position"))
2087 render_sidebar_position_hints(sidebar_field, *shader, base_matrix * orient_matrix);
2088 else if (boost::starts_with(sidebar_field, "rotation"))
2089 render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
2090 else if (boost::starts_with(sidebar_field, "absolute_rotation"))
2091 render_sidebar_rotation_hints(sidebar_field, *shader, base_matrix * orient_matrix);
2092 else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
2093 //BBS: GUI refactor: add uniform_scale from gizmo
2094 render_sidebar_scale_hints(sidebar_field, uniform_scale, *shader, base_matrix * orient_matrix);
2095 else if (boost::starts_with(sidebar_field, "layer"))
2096 render_sidebar_layers_hints(sidebar_field, *shader);
2097
2098
2099 shader->stop_using();
2100}
bool requires_local_axes() const
Definition Selection.cpp:2102
void render_sidebar_rotation_hints(const std::string &sidebar_field, GLShaderProgram &shader, const Transform3d &matrix)
Definition Selection.cpp:2826
void render_sidebar_scale_hints(const std::string &sidebar_field, bool gizmo_uniform_scale, GLShaderProgram &shader, const Transform3d &matrix)
Definition Selection.cpp:2859
void render_sidebar_position_hints(const std::string &sidebar_field, GLShaderProgram &shader, const Transform3d &matrix)
Definition Selection.cpp:2796
void render_sidebar_layers_hints(const std::string &sidebar_field, GLShaderProgram &shader)
Definition Selection.cpp:2897
#define GL_DEPTH_BUFFER_BIT
Definition gl.h:558
#define glClear
Definition gl.h:3357
void assemble_transform(Transform3d &transform, const Vec3d &translation, const Vec3d &rotation, const Vec3d &scale, const Vec3d &mirror)
Definition Geometry.cpp:319

References Slic3r::Geometry::assemble_transform(), Slic3r::BoundingBox3Base< PointType >::center(), center(), get_bounding_box(), get_bounding_box_in_current_reference_system(), GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, glClear, glEnable, glsafe, is_single_full_instance(), is_single_volume_or_modifier(), m_list, render_sidebar_layers_hints(), render_sidebar_position_hints(), render_sidebar_rotation_hints(), render_sidebar_scale_hints(), requires_local_axes(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Here is the call graph for this function:

◆ render_sidebar_layers_hints()

void Slic3r::GUI::Selection::render_sidebar_layers_hints ( const std::string & sidebar_field,
GLShaderProgram & shader )
private
2898{
2899 static const float Margin = 10.0f;
2900
2901 std::string field = sidebar_field;
2902
2903 // extract max_z
2904 std::string::size_type pos = field.rfind("_");
2905 if (pos == std::string::npos)
2906 return;
2907
2908 const float max_z = float(string_to_double_decimal_point(field.substr(pos + 1)));
2909
2910 // extract min_z
2911 field = field.substr(0, pos);
2912 pos = field.rfind("_");
2913 if (pos == std::string::npos)
2914 return;
2915
2916 const float min_z = float(string_to_double_decimal_point(field.substr(pos + 1)));
2917
2918 // extract type
2919 field = field.substr(0, pos);
2920 pos = field.rfind("_");
2921 if (pos == std::string::npos)
2922 return;
2923
2924 const int type = std::stoi(field.substr(pos + 1));
2925
2926 const BoundingBoxf3& box = get_bounding_box();
2927
2928 // view dependend order of rendering to keep correct transparency
2929 const bool camera_on_top = wxGetApp().plater()->get_camera().is_looking_downward();
2930 const float z1 = camera_on_top ? min_z : max_z;
2931 const float z2 = camera_on_top ? max_z : min_z;
2932
2933 const Vec3f p1 = { float(box.min.x()) - Margin, float(box.min.y()) - Margin, z1 };
2934 const Vec3f p2 = { float(box.max.x()) + Margin, float(box.max.y()) + Margin, z2 };
2935
2940
2941 if (!m_planes.models[0].is_initialized() || !is_approx(m_planes.check_points[0], p1)) {
2942 m_planes.check_points[0] = p1;
2943 m_planes.models[0].reset();
2944
2945 GLModel::Geometry init_data;
2947 init_data.reserve_vertices(4);
2948 init_data.reserve_indices(6);
2949
2950 // vertices
2951 init_data.add_vertex(Vec3f(p1.x(), p1.y(), z1));
2952 init_data.add_vertex(Vec3f(p2.x(), p1.y(), z1));
2953 init_data.add_vertex(Vec3f(p2.x(), p2.y(), z1));
2954 init_data.add_vertex(Vec3f(p1.x(), p2.y(), z1));
2955
2956 // indices
2957 init_data.add_triangle(0, 1, 2);
2958 init_data.add_triangle(2, 3, 0);
2959
2960 m_planes.models[0].init_from(std::move(init_data));
2961 }
2962
2963 if (!m_planes.models[1].is_initialized() || !is_approx(m_planes.check_points[1], p2)) {
2964 m_planes.check_points[1] = p2;
2965 m_planes.models[1].reset();
2966
2967 GLModel::Geometry init_data;
2969 init_data.reserve_vertices(4);
2970 init_data.reserve_indices(6);
2971
2972 // vertices
2973 init_data.add_vertex(Vec3f(p1.x(), p1.y(), z2));
2974 init_data.add_vertex(Vec3f(p2.x(), p1.y(), z2));
2975 init_data.add_vertex(Vec3f(p2.x(), p2.y(), z2));
2976 init_data.add_vertex(Vec3f(p1.x(), p2.y(), z2));
2977
2978 // indices
2979 init_data.add_triangle(0, 1, 2);
2980 init_data.add_triangle(2, 3, 0);
2981
2982 m_planes.models[1].init_from(std::move(init_data));
2983 }
2984
2985 const Camera& camera = wxGetApp().plater()->get_camera();
2986 shader.set_uniform("view_model_matrix", camera.get_view_matrix());
2987 shader.set_uniform("projection_matrix", camera.get_projection_matrix());
2988
2989 m_planes.models[0].set_color((camera_on_top && type == 1) || (!camera_on_top && type == 2) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR);
2990 m_planes.models[0].render();
2991 m_planes.models[1].set_color((camera_on_top && type == 2) || (!camera_on_top && type == 1) ? SOLID_PLANE_COLOR : TRANSPARENT_PLANE_COLOR);
2992 m_planes.models[1].render();
2993
2996}
static const Slic3r::ColorRGBA TRANSPARENT_PLANE_COLOR
Definition Selection.cpp:68
static const Slic3r::ColorRGBA SOLID_PLANE_COLOR
Definition Selection.cpp:67
Planes m_planes
Definition Selection.hpp:202
#define GL_SRC_ALPHA
Definition gl.h:1621
#define GL_CULL_FACE
Definition gl.h:500
#define GL_BLEND
Definition gl.h:275
#define GL_ONE_MINUS_SRC_ALPHA
Definition gl.h:1239
#define glDisable
Definition gl.h:3607
#define glBlendFunc
Definition gl.h:3325
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
double string_to_double_decimal_point(const std::string_view str, size_t *pos)
Definition LocalesUtils.cpp:86

References Slic3r::GUI::GLModel::Geometry::add_triangle(), Slic3r::GUI::GLModel::Geometry::add_vertex(), Slic3r::GUI::GLModel::Geometry::format, get_bounding_box(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glDisable, glEnable, glsafe, Slic3r::is_approx(), m_planes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GUI::GLModel::Geometry::P3, Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), Slic3r::GLShaderProgram::set_uniform(), SOLID_PLANE_COLOR, Slic3r::string_to_double_decimal_point(), TRANSPARENT_PLANE_COLOR, and Slic3r::GUI::GLModel::Geometry::Triangles.

Referenced by render_sidebar_hints().

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

◆ render_sidebar_position_hints()

void Slic3r::GUI::Selection::render_sidebar_position_hints ( const std::string & sidebar_field,
GLShaderProgram & shader,
const Transform3d & matrix )
private
2797{
2798 const Camera& camera = wxGetApp().plater()->get_camera();
2799 const Transform3d& view_matrix = camera.get_view_matrix();
2800 shader.set_uniform("projection_matrix", camera.get_projection_matrix());
2801
2802 if (boost::ends_with(sidebar_field, "x")) {
2803 const Transform3d model_matrix = matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ());
2804 shader.set_uniform("view_model_matrix", view_matrix * model_matrix);
2805 const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
2806 shader.set_uniform("view_normal_matrix", view_normal_matrix);
2807 m_arrow.set_color(get_color(X));
2808 m_arrow.render();
2809 }
2810 else if (boost::ends_with(sidebar_field, "y")) {
2811 shader.set_uniform("view_model_matrix", view_matrix * matrix);
2812 shader.set_uniform("view_normal_matrix", (Matrix3d)Matrix3d::Identity());
2813 m_arrow.set_color(get_color(Y));
2814 m_arrow.render();
2815 }
2816 else if (boost::ends_with(sidebar_field, "z")) {
2817 const Transform3d model_matrix = matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitX());
2818 shader.set_uniform("view_model_matrix", view_matrix * model_matrix);
2819 const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
2820 shader.set_uniform("view_normal_matrix", view_normal_matrix);
2821 m_arrow.set_color(get_color(Z));
2822 m_arrow.render();
2823 }
2824}
static ColorRGBA get_color(Axis axis)
Definition Selection.cpp:2791
Eigen::Matrix< double, 3, 3, Eigen::DontAlign > Matrix3d
Definition Point.hpp:86

References Slic3r::Geometry::assemble_transform(), Slic3r::GUI::get_color(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), m_arrow, PI, Slic3r::GLShaderProgram::set_uniform(), Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by render_sidebar_hints().

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

◆ render_sidebar_rotation_hints()

void Slic3r::GUI::Selection::render_sidebar_rotation_hints ( const std::string & sidebar_field,
GLShaderProgram & shader,
const Transform3d & matrix )
private
2827{
2828 auto render_sidebar_rotation_hint = [this](GLShaderProgram& shader, const Transform3d& view_matrix, const Transform3d& model_matrix) {
2829 shader.set_uniform("view_model_matrix", view_matrix * model_matrix);
2830 Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
2831 shader.set_uniform("view_normal_matrix", view_normal_matrix);
2832 m_curved_arrow.render();
2833 const Transform3d matrix = model_matrix * Geometry::assemble_transform(Vec3d::Zero(), PI * Vec3d::UnitZ());
2834 shader.set_uniform("view_model_matrix", view_matrix * matrix);
2835 view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
2836 shader.set_uniform("view_normal_matrix", view_normal_matrix);
2837 m_curved_arrow.render();
2838 };
2839
2840 const Camera& camera = wxGetApp().plater()->get_camera();
2841 const Transform3d& view_matrix = camera.get_view_matrix();
2842 shader.set_uniform("projection_matrix", camera.get_projection_matrix());
2843
2844 if (boost::ends_with(sidebar_field, "x")) {
2845 m_curved_arrow.set_color(get_color(X));
2846 render_sidebar_rotation_hint(shader, view_matrix, matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY()));
2847 }
2848 else if (boost::ends_with(sidebar_field, "y")) {
2849 m_curved_arrow.set_color(get_color(Y));
2850 render_sidebar_rotation_hint(shader, view_matrix, matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX()));
2851 }
2852 else if (boost::ends_with(sidebar_field, "z")) {
2853 m_curved_arrow.set_color(get_color(Z));
2854 render_sidebar_rotation_hint(shader, view_matrix, matrix);
2855 }
2856}

References Slic3r::Geometry::assemble_transform(), Slic3r::GUI::get_color(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), m_curved_arrow, PI, Slic3r::GLShaderProgram::set_uniform(), Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by render_sidebar_hints().

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

◆ render_sidebar_scale_hints()

void Slic3r::GUI::Selection::render_sidebar_scale_hints ( const std::string & sidebar_field,
bool gizmo_uniform_scale,
GLShaderProgram & shader,
const Transform3d & matrix )
private
2860{
2861 // BBS
2862 //bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
2863 bool uniform_scale = requires_uniform_scale() || gizmo_uniform_scale;
2864
2865 auto render_sidebar_scale_hint = [this, uniform_scale](Axis axis, GLShaderProgram& shader, const Transform3d& view_matrix, const Transform3d& model_matrix) {
2866 m_arrow.set_color(uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis));
2867 Transform3d matrix = model_matrix * Geometry::assemble_transform(5.0 * Vec3d::UnitY());
2868 shader.set_uniform("view_model_matrix", view_matrix * matrix);
2869 Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
2870 shader.set_uniform("view_normal_matrix", view_normal_matrix);
2871 m_arrow.render();
2872
2873 matrix = model_matrix * Geometry::assemble_transform(-5.0 * Vec3d::UnitY(), PI * Vec3d::UnitZ());
2874 shader.set_uniform("view_model_matrix", view_matrix * matrix);
2875 view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
2876 shader.set_uniform("view_normal_matrix", view_normal_matrix);
2877 m_arrow.render();
2878 };
2879
2880 const Camera& camera = wxGetApp().plater()->get_camera();
2881 const Transform3d& view_matrix = camera.get_view_matrix();
2882 shader.set_uniform("projection_matrix", camera.get_projection_matrix());
2883
2884 if (boost::ends_with(sidebar_field, "x") || uniform_scale) {
2885 render_sidebar_scale_hint(X, shader, view_matrix, matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitZ()));
2886 }
2887
2888 if (boost::ends_with(sidebar_field, "y") || uniform_scale) {
2889 render_sidebar_scale_hint(Y, shader, view_matrix, matrix);
2890 }
2891
2892 if (boost::ends_with(sidebar_field, "z") || uniform_scale) {
2893 render_sidebar_scale_hint(Z, shader, view_matrix, matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitX()));
2894 }
2895}
static const Slic3r::ColorRGBA UNIFORM_SCALE_COLOR
Definition Selection.cpp:66
bool requires_uniform_scale() const
Definition Selection.cpp:954
Axis
Definition libslic3r.h:140

References Slic3r::Geometry::assemble_transform(), Slic3r::GUI::get_color(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), m_arrow, PI, requires_uniform_scale(), Slic3r::GLShaderProgram::set_uniform(), UNIFORM_SCALE_COLOR, Slic3r::X, Slic3r::Y, and Slic3r::Z.

Referenced by render_sidebar_hints().

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

◆ render_synchronized_volumes()

void Slic3r::GUI::Selection::render_synchronized_volumes ( )
private
2599{
2600 if (m_mode == Instance)
2601 return;
2602
2603 const ECoordinatesType coordinates_type = wxGetApp().obj_manipul()->get_coordinates_type();
2604 BoundingBoxf3 box;
2605 Transform3d trafo;
2606
2607 for (unsigned int i : m_list) {
2608 const GLVolume& volume = *(*m_volumes)[i];
2609 int object_idx = volume.object_idx();
2610 int volume_idx = volume.volume_idx();
2611 for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
2612 if (i == j)
2613 continue;
2614
2615 const GLVolume& v = *(*m_volumes)[j];
2616 if (v.object_idx() != object_idx || v.volume_idx() != volume_idx)
2617 continue;
2618
2619 if (coordinates_type == ECoordinatesType::World) {
2620 box = v.transformed_convex_hull_bounding_box();
2621 trafo = Transform3d::Identity();
2622 }
2623 else if (coordinates_type == ECoordinatesType::Local) {
2624 box = v.bounding_box();
2625 trafo = v.world_matrix();
2626 }
2627 else {
2628 box = v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix());
2629 trafo = v.get_instance_transformation().get_matrix();
2630 }
2631 const bool auto_drop = get_auto_drop();
2632 render_bounding_box(box, trafo, auto_drop, ColorRGB::YELLOW());
2633 }
2634 }
2635}

References Slic3r::GLVolume::bounding_box(), get_auto_drop(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::get_volume_transformation(), Instance, Slic3r::GUI::Local, m_list, m_mode, m_volumes, Slic3r::GLVolume::object_idx(), render_bounding_box(), Slic3r::GLVolume::transformed_convex_hull_bounding_box(), Slic3r::GLVolume::volume_idx(), Slic3r::GUI::World, Slic3r::GLVolume::world_matrix(), and Slic3r::ColorRGB::YELLOW().

Referenced by render().

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

◆ requires_local_axes()

bool Slic3r::GUI::Selection::requires_local_axes ( ) const
2103{
2104 return m_mode == Volume && is_from_single_instance();
2105}

References is_from_single_instance(), m_mode, and Volume.

Referenced by render_sidebar_hints().

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

◆ requires_uniform_scale()

bool Slic3r::GUI::Selection::requires_uniform_scale ( ) const
955{
957 return false;
958
959 return true;
960}

References is_single_full_instance(), is_single_modifier(), and is_single_volume().

Referenced by render_sidebar_scale_hints().

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

◆ rotate() [1/3]

void Slic3r::GUI::Selection::rotate ( const Vec3d & rotation,
TransformationType transformation_type )
1344{
1345 if (!m_valid)
1346 return;
1347
1348 assert(transformation_type.relative() || (transformation_type.absolute() && transformation_type.local()));
1349
1350 bool requires_general_synchronization = false;
1351
1352 for (unsigned int i : m_list) {
1353 Transform3d rotation_matrix = Geometry::rotation_transform(rotation);
1354 GLVolume& v = *(*m_volumes)[i];
1355 const VolumeCache& volume_data = m_cache.volumes_data[i];
1356 const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
1357 if (m_mode == Instance && !is_wipe_tower()) {
1359 if (transformation_type.instance()) {
1360 // ensure that the instance rotates as a rigid body
1361 Transform3d inst_rotation_matrix = inst_trafo.get_rotation_matrix();
1362 if (inst_trafo.is_left_handed()) {
1363 Geometry::TransformationSVD inst_svd(inst_trafo);
1364 inst_rotation_matrix = inst_svd.u * inst_svd.v.transpose();
1365 // ensure the rotation has the proper direction
1366 if (!rotation.normalized().cwiseAbs().isApprox(Vec3d::UnitX()))
1367 rotation_matrix = rotation_matrix.inverse();
1368 }
1369
1370 const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
1371 rotation_matrix = inst_matrix_no_offset.inverse() * inst_rotation_matrix * rotation_matrix * inst_rotation_matrix.inverse() * inst_matrix_no_offset;
1372
1373 // rotate around selection center
1374 const Vec3d inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * (m_cache.rotation_pivot - inst_trafo.get_offset());
1375 rotation_matrix = Geometry::translation_transform(inst_pivot) * rotation_matrix * Geometry::translation_transform(-inst_pivot);
1376
1377 // Detects if the rotation is equivalent to a world rotation around the Z axis
1378 // If not, force for a full synchronization of unselected instances
1379 if (!requires_general_synchronization) {
1380 const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
1381 const Transform3d old_world_rotation_matrix = (inst_trafo * vol_trafo).get_rotation_matrix();
1382 const Transform3d new_world_rotation_matrix = (inst_trafo * Geometry::Transformation(rotation_matrix) * vol_trafo).get_rotation_matrix();
1383 if (std::abs((old_world_rotation_matrix * Vec3d::UnitX()).z() - (new_world_rotation_matrix * Vec3d::UnitX()).z()) > EPSILON)
1384 requires_general_synchronization = true;
1385 else if (std::abs((old_world_rotation_matrix * Vec3d::UnitY()).z() - (new_world_rotation_matrix * Vec3d::UnitY()).z()) > EPSILON)
1386 requires_general_synchronization = true;
1387 else if (std::abs((old_world_rotation_matrix * Vec3d::UnitZ()).z() - (new_world_rotation_matrix * Vec3d::UnitZ()).z()) > EPSILON)
1388 requires_general_synchronization = true;
1389 }
1390 }
1391 transform_instance_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot);
1392 }
1393 else {
1395 assert(transformation_type.world());
1396 transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot);
1397 }
1398 else {
1399 if (transformation_type.instance()) {
1400 // ensure that the volume rotates as a rigid body
1401 const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix();
1402 rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix;
1403 }
1404 else {
1405 if (transformation_type.local()) {
1406 // ensure that the volume rotates as a rigid body
1407 const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
1408 const Transform3d vol_matrix_no_offset = vol_trafo.get_matrix_no_offset();
1409 const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix();
1410 Transform3d vol_rotation_matrix = vol_trafo.get_rotation_matrix();
1411 if (vol_trafo.is_left_handed()) {
1412 Geometry::TransformationSVD vol_svd(vol_trafo);
1413 vol_rotation_matrix = vol_svd.u * vol_svd.v.transpose();
1414 // ensure the rotation has the proper direction
1415 if (!rotation.normalized().cwiseAbs().isApprox(Vec3d::UnitX()))
1416 rotation_matrix = rotation_matrix.inverse();
1417 }
1418 rotation_matrix = vol_matrix_no_offset.inverse() * inst_scale_matrix.inverse() * vol_rotation_matrix * rotation_matrix *
1419 vol_rotation_matrix.inverse() * inst_scale_matrix * vol_matrix_no_offset;
1420 }
1421 }
1422 transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.rotation_pivot);
1423 }
1424 }
1425 }
1426
1427#if !DISABLE_INSTANCES_SYNCH
1428 if (m_mode == Instance) {
1429 int rot_axis_max = 0;
1430 rotation.cwiseAbs().maxCoeff(&rot_axis_max);
1431 const SyncRotationType type = (transformation_type.instance() && requires_general_synchronization) ||
1432 (!transformation_type.instance() && rot_axis_max != 2) ||
1433 rotation.isApprox(Vec3d::Zero()) ?
1436 }
1437 else if (m_mode == Volume)
1439#endif // !DISABLE_INSTANCES_SYNCH
1440
1442 if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
1443 wxGetApp().plater()->canvas3D()->requires_check_outside_state();
1444 }
1445}
#define EPSILON
Definition ColorUtils.cpp:64
void synchronize_unselected_volumes()
Definition Selection.cpp:3101
void transform_volume_relative(GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot)
Definition Selection.cpp:3381
void transform_instance_relative(GLVolume &volume, const VolumeCache &volume_data, TransformationType transformation_type, const Transform3d &transform, const Vec3d &world_pivot)
Definition Selection.cpp:3364
SyncRotationType
Definition Selection.hpp:455
@ NONE
Definition Selection.hpp:457
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:346
void rotation_transform(Transform3d &transform, const Vec3d &rotation)
Definition Geometry.cpp:359
Definition Selection.hpp:75

References Slic3r::GUI::TransformationType::absolute(), Slic3r::GUI::GLCanvas3D::CanvasAssembleView, EPSILON, GENERAL, Slic3r::GUI::Selection::VolumeCache::get_instance_transform(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::Geometry::Transformation::get_rotation_matrix(), Slic3r::Geometry::Transformation::get_scaling_factor_matrix(), Slic3r::GUI::Selection::VolumeCache::get_volume_transform(), Instance, Slic3r::GUI::TransformationType::instance(), is_from_fully_selected_instance(), Slic3r::Geometry::Transformation::is_left_handed(), is_single_volume_or_modifier(), is_wipe_tower(), Slic3r::GUI::TransformationType::local(), m_cache, m_list, m_mode, m_valid, NONE, Slic3r::GUI::plater(), Slic3r::GUI::TransformationType::relative(), Slic3r::Geometry::rotation_transform(), set_bounding_boxes_dirty(), synchronize_unselected_instances(), synchronize_unselected_volumes(), transform_instance_relative(), transform_volume_relative(), Slic3r::Geometry::translation_transform(), Slic3r::Geometry::TransformationSVD::u, Slic3r::Geometry::TransformationSVD::v, Volume, and Slic3r::GUI::TransformationType::world().

Referenced by Slic3r::GUI::GizmoObjectManipulation::change_absolute_rotation_value(), Slic3r::GUI::GizmoObjectManipulation::change_rotation_value(), Slic3r::GUI::do_local_z_rotate(), and Slic3r::GUI::dragging_rotate_gizmo().

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

◆ rotate() [2/3]

void Slic3r::GUI::Selection::rotate ( unsigned int object_idx,
unsigned int instance_idx,
const Transform3d & overwrite_tran )
1792{
1793 if (!m_valid) return;
1794
1795 for (unsigned int i : m_list) {
1796 GLVolume &v = *(*m_volumes)[i];
1797 if (v.object_idx() == (int) object_idx && v.instance_idx() == (int) instance_idx) {
1798 v.set_instance_transformation(overwrite_tran);
1799 }
1800 }
1801
1802 std::set<unsigned int> done; // prevent processing volumes twice
1803 done.insert(m_list.begin(), m_list.end());
1804 for (unsigned int i : m_list) {
1805 if (done.size() == m_volumes->size()) break;
1806
1807 int object_idx = (*m_volumes)[i]->object_idx();
1808 if (object_idx >= 1000) continue;
1809
1810 // Process unselected volumes of the object.
1811 for (unsigned int j = 0; j < (unsigned int) m_volumes->size(); ++j) {
1812 if (done.size() == m_volumes->size()) break;
1813
1814 if (done.find(j) != done.end()) continue;
1815
1816 GLVolume &v = *(*m_volumes)[j];
1817 if (v.object_idx() != object_idx || v.instance_idx() != (int) instance_idx)
1818 continue;
1819
1820 v.set_instance_transformation(overwrite_tran);
1821 done.insert(j);
1822 }
1823 }
1825}

References Slic3r::GLVolume::instance_idx(), m_list, m_valid, m_volumes, Slic3r::GLVolume::object_idx(), set_bounding_boxes_dirty(), and Slic3r::GLVolume::set_instance_transformation().

Here is the call graph for this function:

◆ rotate() [3/3]

void Slic3r::GUI::Selection::rotate ( unsigned int object_idx,
unsigned int instance_idx,
unsigned int volume_idx,
const Transform3d & overwrite_tran )
1827{
1828 if (!m_valid) return;
1829
1830 for (unsigned int i : m_list) {
1831 GLVolume &v = *(*m_volumes)[i];
1832 if (v.object_idx() == (int) object_idx && v.instance_idx() == (int) instance_idx && v.volume_idx() == (int) volume_idx) {
1833 v.set_volume_transformation(overwrite_tran);
1834 }
1835 }
1837}

References Slic3r::GLVolume::instance_idx(), m_list, m_valid, Slic3r::GLVolume::object_idx(), set_bounding_boxes_dirty(), Slic3r::GLVolume::set_volume_transformation(), and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ scale()

void Slic3r::GUI::Selection::scale ( const Vec3d & scale,
TransformationType transformation_type )
1476{
1477 scale_and_translate(scale, Vec3d::Zero(), transformation_type);
1478}

References scale(), and scale_and_translate().

Referenced by Slic3r::GUI::adjust_settings_for_flowrate_calib(), Slic3r::GUI::GizmoObjectManipulation::do_scale(), Slic3r::GUI::GLGizmoSVG::draw_size(), render_bounding_box(), render_bounding_box(), Slic3r::GUI::GLGizmoMeasure::render_dimensioning(), scale(), scale_and_translate(), and scale_to_fit_print_volume().

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

◆ scale_and_translate()

void Slic3r::GUI::Selection::scale_and_translate ( const Vec3d & scale,
const Vec3d & world_translation,
TransformationType transformation_type )
1628{
1629 if (!m_valid) return;
1630
1631 Vec3d relative_scale = scale;
1632 if (transformation_type.absolute()) {
1633 // converts to relative scale
1634 if (m_mode == Instance) {
1636 BoundingBoxf3 current_box = get_bounding_box_in_current_reference_system().first;
1637 BoundingBoxf3 original_box;
1638 if (transformation_type.world())
1640 else
1642
1643 relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(current_box.size());
1644 }
1645 }
1646 transformation_type.set_relative();
1647 }
1648
1649 for (unsigned int i : m_list) {
1650 GLVolume & v = *(*m_volumes)[i];
1651 const VolumeCache & volume_data = m_cache.volumes_data[i];
1652 const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
1653
1654 if (m_mode == Instance) {
1655 if (transformation_type.instance()) {
1656 const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
1657 const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
1658 Matrix3d inst_rotation, inst_scale;
1659 inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
1660 const Transform3d offset_trafo = Geometry::translation_transform(inst_trafo.get_offset() + world_translation);
1661 const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
1662 v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo *
1663 Geometry::translation_transform(-local_inst_pivot));
1664 } else
1665 transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(relative_scale),
1666 m_cache.dragging_center);
1667 // update the instance assemble transform
1668 ModelObject * object = m_model->objects[v.object_idx()];
1669 Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
1670 assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
1671 object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
1672 } else {
1674 assert(transformation_type.world());
1675 transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(scale),
1676 m_cache.dragging_center);
1677 } else {
1678 transformation_type.set_independent();
1679 Vec3d translation;
1680 if (transformation_type.local()) {
1681 translation = volume_data.get_volume_transform().get_matrix_no_offset().inverse() * inst_trafo.get_matrix_no_offset().inverse() * world_translation;
1682 }
1683 else if (transformation_type.instance())
1684 translation = inst_trafo.get_matrix_no_offset().inverse() * world_translation;
1685 else
1686 translation = world_translation;
1687 transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale),
1688 m_cache.dragging_center);
1689 }
1690 }
1691 }
1692
1693#if !DISABLE_INSTANCES_SYNCH
1694 if (m_mode == Instance)
1695 // even if there is no rotation, we pass SyncRotationType::GENERAL to force
1696 // synchronize_unselected_instances() to apply the scale to the other instances
1698 else if (m_mode == Volume)
1700#endif // !DISABLE_INSTANCES_SYNCH
1701
1703 if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
1704 wxGetApp().plater()->canvas3D()->requires_check_outside_state();
1705 }
1706}
const BoundingBoxf3 & get_full_unscaled_instance_bounding_box() const
Definition Selection.cpp:1050
const BoundingBoxf3 & get_full_unscaled_instance_local_bounding_box() const
Definition Selection.cpp:1088
void scale_transform(Transform3d &transform, double scale)
Definition Geometry.cpp:372

References Slic3r::GUI::TransformationType::absolute(), Slic3r::Geometry::assemble_transform(), Slic3r::GUI::GLCanvas3D::CanvasAssembleView, GENERAL, get_bounding_box_in_current_reference_system(), get_full_unscaled_instance_bounding_box(), get_full_unscaled_instance_local_bounding_box(), Slic3r::GLVolume::get_instance_scaling_factor(), Slic3r::GUI::Selection::VolumeCache::get_instance_transform(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::GUI::Selection::VolumeCache::get_volume_transform(), Instance, Slic3r::GUI::TransformationType::instance(), Slic3r::GLVolume::instance_idx(), is_single_full_instance(), is_single_volume_or_modifier(), Slic3r::GUI::TransformationType::local(), m_cache, m_list, m_mode, m_model, m_valid, Slic3r::GLVolume::object_idx(), Slic3r::GUI::plater(), scale(), Slic3r::Geometry::scale_transform(), set_bounding_boxes_dirty(), Slic3r::GUI::TransformationType::set_independent(), Slic3r::GLVolume::set_instance_transformation(), Slic3r::GUI::TransformationType::set_relative(), Slic3r::BoundingBox3Base< PointType >::size(), synchronize_unselected_instances(), synchronize_unselected_volumes(), transform_instance_relative(), transform_volume_relative(), Slic3r::Geometry::translation_transform(), Volume, and Slic3r::GUI::TransformationType::world().

Referenced by mirror(), Slic3r::GUI::GLGizmoScale3D::on_mouse(), and scale().

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

◆ scale_to_fit_print_volume()

void Slic3r::GUI::Selection::scale_to_fit_print_volume ( const DynamicPrintConfig & config)
1583{
1584 if (is_empty() || m_mode == Volume)
1585 return;
1586
1587 // adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings
1588 Vec3d box_size = get_bounding_box().size() + 0.01 * Vec3d::Ones();
1589
1590 const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config.option("printable_area"));
1591 if (opt != nullptr) {
1592 BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
1593 BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0 }, { unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config.opt_float("printable_height") });
1594 Vec3d print_volume_size = print_volume.size();
1595 double sx = (box_size(0) != 0.0) ? print_volume_size(0) / box_size(0) : 0.0;
1596 double sy = (box_size(1) != 0.0) ? print_volume_size(1) / box_size(1) : 0.0;
1597 double sz = (box_size(2) != 0.0) ? print_volume_size(2) / box_size(2) : 0.0;
1598 if (sx != 0.0 && sy != 0.0 && sz != 0.0)
1599 {
1600 double s = std::min(sx, std::min(sy, sz));
1601 if (s != 1.0) {
1602 wxGetApp().plater()->take_snapshot("Scale To Fit");
1603
1604 TransformationType type;
1605 type.set_world();
1606 type.set_relative();
1607 type.set_joint();
1608
1609 // apply scale
1611 scale(s * Vec3d::Ones(), type);
1612 wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot
1613
1614 // center selection on print bed
1616 translate(print_volume.center() - get_bounding_box().center());
1617 wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot
1618
1619 // BBS
1620 //wxGetApp().obj_manipul()->set_dirty();
1621 }
1622 }
1623 }
1624}
PointType size() const
Definition BoundingBox.cpp:187
static Polygon new_scale(const std::vector< Vec2d > &points)
Definition Polygon.hpp:38
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
T unscale(Q v)
Definition libslic3r.h:138
bool start_dragging(const Vec2d &mouse_pos, const Camera &camera, std::optional< SurfaceDrag > &surface_drag, GLCanvas3D &canvas, RaycastManager &raycast_manager, const std::optional< double > &up_limit)
Definition SurfaceDrag.cpp:508

References center(), get_bounding_box(), Slic3r::get_extents(), is_empty(), m_mode, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::Polygon::new_scale(), Slic3r::DynamicConfig::opt_float(), Slic3r::ConfigBase::option(), scale(), Slic3r::GUI::TransformationType::set_joint(), Slic3r::GUI::TransformationType::set_relative(), Slic3r::GUI::TransformationType::set_world(), Slic3r::BoundingBox3Base< PointType >::size(), translate(), Slic3r::unscale(), and Volume.

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

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

◆ set_auto_drop()

void Slic3r::GUI::Selection::set_auto_drop ( bool enabled)
659{
660 if (!m_valid)
661 return;
662
663 std::set<int> object_idxs;
664 for (const auto& [obj_idx, inst_list] : m_cache.content) {
665 object_idxs.insert(obj_idx);
666 }
667
668 std::string snapshot_text = (boost::format("%1%") % (enabled ? "Set Selection Auto-Drop Enabled" : "Set Selection Auto-Drop Disabled")).str();
669 wxGetApp().plater()->take_snapshot(snapshot_text);
670
671 // auto_drop is shared by all instances of an object.
672 for (int obj_idx : object_idxs) {
673 ModelObject* object = m_model->objects[obj_idx];
674 object->auto_drop = enabled;
675 }
676
677 // update scene
678 wxGetApp().plater()->update();
679}

References m_cache, m_model, and m_valid.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_set_auto_drop().

Here is the caller graph for this function:

◆ set_bounding_boxes_dirty()

◆ set_caches()

void Slic3r::GUI::Selection::set_caches ( )
private
2538{
2539 m_cache.volumes_data.clear();
2540 m_cache.sinking_volumes.clear();
2541 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
2542 const GLVolume& v = *(*m_volumes)[i];
2543 m_cache.volumes_data.emplace(i, VolumeCache(v.get_volume_transformation(), v.get_instance_transformation()));
2544 if (v.is_sinking())
2545 m_cache.sinking_volumes.push_back(i);
2546 }
2547 m_cache.dragging_center = get_bounding_box().center();
2548 m_cache.rotation_pivot = get_bounding_sphere().first;
2549}
const std::pair< Vec3d, double > get_bounding_sphere() const
Definition Selection.cpp:1203

References Slic3r::BoundingBox3Base< PointType >::center(), get_bounding_box(), get_bounding_sphere(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::GLVolume::get_volume_transformation(), Slic3r::GLVolume::is_sinking(), m_cache, and m_volumes.

Referenced by move_to_center(), and setup_cache().

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

◆ set_deserialized()

void Slic3r::GUI::Selection::set_deserialized ( EMode mode,
const std::vector< std::pair< size_t, size_t > > & volumes_and_instances )
727{
728 if (! m_valid)
729 return;
730
731 m_mode = mode;
732 for (unsigned int i : m_list)
733 (*m_volumes)[i]->selected = false;
734 m_list.clear();
735 for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++ i)
736 if (std::binary_search(volumes_and_instances.begin(), volumes_and_instances.end(), (*m_volumes)[i]->geometry_id))
737 do_add_volume(i);
738 update_type();
740}

References do_add_volume(), m_list, m_mode, m_valid, m_volumes, set_bounding_boxes_dirty(), and update_type().

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

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

◆ set_enabled()

void Slic3r::GUI::Selection::set_enabled ( bool enable)
inline
217{ m_enabled = enable; }

References m_enabled.

◆ set_mode()

void Slic3r::GUI::Selection::set_mode ( EMode mode)
inline
223{ m_mode = mode; }

References m_mode.

◆ set_model()

void Slic3r::GUI::Selection::set_model ( Model * model)
177{
178 m_model = model;
179 update_valid();
180}
void update_valid()
Definition Selection.cpp:2304

References m_model, and update_valid().

Here is the call graph for this function:

◆ set_printable()

void Slic3r::GUI::Selection::set_printable ( bool printable)
607{
608 if (!m_valid)
609 return;
610
611 std::set<std::pair<int, int>> instances_idxs;
612 for (const auto& [obj_idx, inst_list] : m_cache.content) {
613 for (int inst_idx : inst_list) {
614 instances_idxs.insert({obj_idx, inst_idx});
615 }
616 }
617
618 std::string snapshot_text = (boost::format("%1%") % (printable ? "Set Selection Printable" : "Set Selection Unprintable")).str();
619 wxGetApp().plater()->take_snapshot(snapshot_text);
620
621 // set printable value for all instances in object
622 for (const auto& [obj_idx, inst_idx] : instances_idxs)
623 {
624 ModelObject* object = m_model->objects[obj_idx];
625 for (auto inst : object->instances)
626 inst->printable = printable;
627 wxGetApp().obj_list()->update_printable_state(obj_idx, inst_idx);
628
629 //update printable state on canvas
630 wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t) obj_idx);
631 }
632
633 // update scene
634 wxGetApp().plater()->update();
635}

References Slic3r::ModelObject::instances, m_cache, m_model, and m_valid.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_set_printable().

Here is the caller graph for this function:

◆ set_volume_selection_mode()

void Slic3r::GUI::Selection::set_volume_selection_mode ( EMode mode)
inline

◆ set_volumes()

void Slic3r::GUI::Selection::set_volumes ( GLVolumePtrs * volumes)
159{
160 m_volumes = volumes;
161 update_valid();
162}

References m_volumes, and update_valid().

Here is the call graph for this function:

◆ setup_cache()

void Slic3r::GUI::Selection::setup_cache ( )
1239{
1240 if (!m_valid)
1241 return;
1242
1243 set_caches();
1244}

References m_valid, and set_caches().

Referenced by Slic3r::GUI::adjust_settings_for_flowrate_calib(), Slic3r::GUI::GLGizmoAlignment::align_objects_generic(), Slic3r::GUI::GLGizmoAlignment::align_to_center(), Slic3r::GUI::GizmoObjectManipulation::change_absolute_rotation_value(), Slic3r::GUI::GizmoObjectManipulation::change_position_value(), Slic3r::GUI::GizmoObjectManipulation::change_rotation_value(), Slic3r::GUI::GLGizmoAlignment::distribute_objects_generic(), Slic3r::GUI::do_local_z_move(), Slic3r::GUI::do_local_z_rotate(), Slic3r::GUI::GLGizmoEmboss::do_mirror(), Slic3r::GUI::GizmoObjectManipulation::do_scale(), Slic3r::GUI::GLGizmoSVG::draw_mirroring(), Slic3r::GUI::GLGizmoSVG::draw_size(), drop(), Slic3r::GUI::GLGizmoMeasure::render_dimensioning(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), Slic3r::GUI::selection_transform(), Slic3r::GUI::GLGizmoMeasure::set_distance(), Slic3r::GUI::GLGizmoMeasure::set_parallel_distance(), Slic3r::GUI::GLGizmoMeasure::set_to_around_center_of_faces(), Slic3r::GUI::GLGizmoMeasure::set_to_parallel(), Slic3r::GUI::GLGizmoMeasure::set_to_reverse_rotation(), and Slic3r::GUI::GLGizmoBase::use_grabbers().

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

◆ synchronize_unselected_instances()

void Slic3r::GUI::Selection::synchronize_unselected_instances ( SyncRotationType sync_rotation_type)
3046{
3047 std::set<unsigned int> done; // prevent processing volumes twice
3048 done.insert(m_list.begin(), m_list.end());
3049
3050 for (unsigned int i : m_list) {
3051 if (done.size() == m_volumes->size())
3052 break;
3053
3054 const GLVolume* volume_i = (*m_volumes)[i];
3055 const int object_idx = volume_i->object_idx();
3056 if (object_idx >= 1000)
3057 continue;
3058
3059 const int instance_idx = volume_i->instance_idx();
3060 const Transform3d& curr_inst_trafo_i = volume_i->get_instance_transformation().get_matrix();
3061 const Transform3d& old_inst_trafo_i = m_cache.volumes_data[i].get_instance_transform().get_matrix();
3062 bool mirrored = is_left_handed(curr_inst_trafo_i) != is_left_handed(old_inst_trafo_i);
3063// bool mirrored = curr_inst_trafo_i.linear().determinant() * old_inst_trafo_i.linear().determinant() < 0;
3064
3065 // Process unselected instances.
3066 for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
3067 if (done.size() == m_volumes->size())
3068 break;
3069 if (done.find(j) != done.end())
3070 continue;
3071 GLVolume* volume_j = (*m_volumes)[j];
3072 if (volume_j->object_idx() != object_idx || volume_j->instance_idx() == instance_idx)
3073 continue;
3074 const Transform3d& old_inst_trafo_j = m_cache.volumes_data[j].get_instance_transform().get_matrix();
3075 assert(is_rotation_xy_synchronized(old_inst_trafo_i, old_inst_trafo_j));
3076 Transform3d new_inst_trafo_j = volume_j->get_instance_transformation().get_matrix();
3077 if (sync_rotation_type == SyncRotationType::RESET) {
3078 Geometry::Transformation new_inst_trafo_j_no_rotation(new_inst_trafo_j);
3079 new_inst_trafo_j_no_rotation.reset_rotation();
3080 new_inst_trafo_j = new_inst_trafo_j_no_rotation.get_matrix();
3081 }
3082 else if (sync_rotation_type != SyncRotationType::NONE || mirrored)
3083 new_inst_trafo_j.linear() = (old_inst_trafo_j.linear() * old_inst_trafo_i.linear().inverse()) * curr_inst_trafo_i.linear();
3084
3085 // Instances of the same object must remain at the same height. auto_drop
3086 // only controls snapping after the move, not the instance transform itself.
3087 if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
3088 new_inst_trafo_j.translation().z() = curr_inst_trafo_i.translation().z();
3089
3090 assert(is_rotation_xy_synchronized(curr_inst_trafo_i, new_inst_trafo_j));
3091 volume_j->set_instance_transformation(new_inst_trafo_j);
3092 done.insert(j);
3093 }
3094 }
3095
3096#ifndef NDEBUG
3098#endif /* NDEBUG */
3099}
@ RESET
Definition Selection.hpp:461
static bool is_rotation_xy_synchronized(const Transform3d &rot_xyz_from, const Transform3d &rot_xyz_to)
Definition Selection.cpp:3009
static bool is_left_handed(const Transform3d::ConstLinearPart &m)
Definition Selection.cpp:2998
static void verify_instances_rotation_synchronized(const Model &model, const GLVolumePtrs &volumes)
Definition Selection.cpp:3022
@ ptSLA
Definition Config.hpp:233

References Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::instance_idx(), Slic3r::GUI::is_left_handed(), Slic3r::GUI::is_rotation_xy_synchronized(), m_cache, m_list, m_model, m_volumes, NONE, Slic3r::GLVolume::object_idx(), Slic3r::ptSLA, RESET, Slic3r::Geometry::Transformation::reset_rotation(), Slic3r::GLVolume::set_instance_transformation(), and Slic3r::GUI::verify_instances_rotation_synchronized().

Referenced by Slic3r::GUI::face_selected_volume_to_camera(), flattening_rotate(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), rotate(), scale_and_translate(), Slic3r::GUI::selection_transform(), and translate().

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

◆ synchronize_unselected_volumes()

void Slic3r::GUI::Selection::synchronize_unselected_volumes ( )
3102{
3103 for (unsigned int i : m_list) {
3104 const GLVolume* volume = (*m_volumes)[i];
3105 const int object_idx = volume->object_idx();
3106 if (object_idx >= 1000)
3107 continue;
3108
3109 const int volume_idx = volume->volume_idx();
3110 const Geometry::Transformation& trafo = volume->get_volume_transformation();
3111
3112 // Process unselected volumes.
3113 for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
3114 if (j == i)
3115 continue;
3116
3117 GLVolume* v = (*m_volumes)[j];
3118 if (v->object_idx() != object_idx || v->volume_idx() != volume_idx)
3119 continue;
3120
3121 v->set_volume_transformation(trafo);
3122 }
3123 }
3124}

References Slic3r::GLVolume::get_volume_transformation(), m_list, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::GLVolume::set_volume_transformation(), and Slic3r::GLVolume::volume_idx().

Referenced by Slic3r::GUI::GLGizmoAlignment::finish_operation(), Slic3r::GUI::GizmoObjectManipulation::reset_rotation_value(), rotate(), scale_and_translate(), and translate().

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

◆ transform_instance_relative()

void Slic3r::GUI::Selection::transform_instance_relative ( GLVolume & volume,
const VolumeCache & volume_data,
TransformationType transformation_type,
const Transform3d & transform,
const Vec3d & world_pivot )
private
3366{
3367 assert(transformation_type.relative());
3368
3369 const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
3370 if (transformation_type.world()) {
3371 const Vec3d inst_pivot = transformation_type.independent() && !is_from_single_instance() ? inst_trafo.get_offset() : world_pivot;
3373 volume.set_instance_transformation(trafo * inst_trafo.get_matrix());
3374 }
3375 else if (transformation_type.instance())
3376 volume.set_instance_transformation(inst_trafo.get_matrix() * transform);
3377 else
3378 assert(false);
3379}
Linef3 transform(const Linef3 &line, const Transform3d &t)
Definition Line.cpp:15

References Slic3r::GUI::Selection::VolumeCache::get_instance_transform(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::GUI::TransformationType::independent(), Slic3r::GUI::TransformationType::instance(), is_from_single_instance(), Slic3r::GUI::TransformationType::relative(), Slic3r::GLVolume::set_instance_transformation(), Slic3r::transform(), Slic3r::Geometry::translation_transform(), and Slic3r::GUI::TransformationType::world().

Referenced by rotate(), scale_and_translate(), and translate().

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

◆ transform_volume_relative()

void Slic3r::GUI::Selection::transform_volume_relative ( GLVolume & volume,
const VolumeCache & volume_data,
TransformationType transformation_type,
const Transform3d & transform,
const Vec3d & world_pivot )
private
3383{
3384 assert(transformation_type.relative());
3385
3386 const Geometry::Transformation& vol_trafo = volume_data.get_volume_transform();
3387 const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
3388
3389 if (transformation_type.world()) {
3390 const Vec3d inst_pivot = transformation_type.independent() ? vol_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
3391 const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
3392 const Transform3d trafo = Geometry::translation_transform(inst_pivot) * inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset * Geometry::translation_transform(-inst_pivot);
3393 volume.set_volume_transformation(trafo * vol_trafo.get_matrix());
3394 }
3395 else if (transformation_type.instance()) {
3396 const Vec3d inst_pivot = transformation_type.independent() ? vol_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
3398 volume.set_volume_transformation(trafo * vol_trafo.get_matrix());
3399 }
3400 else if (transformation_type.local())
3401 volume.set_volume_transformation(vol_trafo.get_matrix() * transform);
3402 else
3403 assert(false);
3404}

References Slic3r::GUI::Selection::VolumeCache::get_instance_transform(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::GUI::Selection::VolumeCache::get_volume_transform(), Slic3r::GUI::TransformationType::independent(), Slic3r::GUI::TransformationType::instance(), Slic3r::GUI::TransformationType::local(), Slic3r::GUI::TransformationType::relative(), Slic3r::GLVolume::set_volume_transformation(), Slic3r::transform(), Slic3r::Geometry::translation_transform(), and Slic3r::GUI::TransformationType::world().

Referenced by rotate(), scale_and_translate(), and translate().

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

◆ translate() [1/4]

void Slic3r::GUI::Selection::translate ( const Vec3d & displacement,
TransformationType transformation_type )
1280{
1281 if (!m_valid) return;
1282
1283 for (unsigned int i : m_list) {
1284 GLVolume & v = *(*m_volumes)[i];
1285 const VolumeCache &volume_data = m_cache.volumes_data[i];
1286 if (m_mode == Instance && !is_wipe_tower()) {
1288 if (transformation_type.instance()) {
1289 const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
1290 v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
1291 } else
1292 transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
1293 } else {
1294 if (v.is_wipe_tower) {//in world cs
1295 int plate_idx = v.object_idx() - 1000;
1296 const Polygons bed_polys{wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->get_shared_printable_polygon()};
1297 Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
1298 Vec3d actual_displacement = displacement;
1299 // Both preview volumes carry the brim in their bounding box, and the release
1300 // clamp holds it WIPE_TOWER_MARGIN inside — same margin, so drops don't snap.
1301 const double margin = WIPE_TOWER_MARGIN;
1302
1303 actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() *
1304 m_cache.volumes_data[i].get_instance_mirror_matrix())
1305 .inverse() *
1306 displacement;
1307 BoundingBoxf3 tower_bbox = v.bounding_box();
1308 tower_bbox.translate(actual_displacement + tower_origin);
1309 BoundingBox tower_bbox2d = BoundingBox(scaled(Vec2f(tower_bbox.min[0], tower_bbox.min[1])), scaled(Vec2f(tower_bbox.max[0], tower_bbox.max[1])));
1310 const Vec2f offset = WipeTower::move_box_inside_polygon(tower_bbox2d, bed_polys, scaled(margin));
1311 actual_displacement += Vec3d(offset[0], offset[1],0);
1312 v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + actual_displacement);
1313 }
1314 else if (transformation_type.local() && transformation_type.absolute()) {
1315 const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
1316 const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
1317 v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
1318 } else {
1319 Vec3d relative_disp = displacement;
1320 if (transformation_type.world() && transformation_type.instance())
1321 relative_disp = volume_data.get_instance_transform().get_scaling_factor_matrix().inverse() * relative_disp;
1322
1323 transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(relative_disp), m_cache.dragging_center);
1324 }
1325 }
1326 }
1327
1328#if !DISABLE_INSTANCES_SYNCH
1329 if (m_mode == Instance)
1331 else if (m_mode == Volume)
1333#endif // !DISABLE_INSTANCES_SYNCH
1334 if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
1336 }
1338 if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
1339 wxGetApp().plater()->canvas3D()->requires_check_outside_state();
1340 }
1341}
static Vec2f move_box_inside_polygon(const BoundingBox &box, const Polygons &polygons, coord_t offset=0)
Definition WipeTower.cpp:1826
static constexpr double WIPE_TOWER_MARGIN
Definition libslic3r.h:100
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582

References Slic3r::GUI::TransformationType::absolute(), Slic3r::GLVolume::bounding_box(), Slic3r::GUI::GLCanvas3D::CanvasAssembleView, ensure_not_below_bed(), Slic3r::GUI::Selection::VolumeCache::get_instance_transform(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::Geometry::Transformation::get_rotation_matrix(), Slic3r::Geometry::Transformation::get_scaling_factor_matrix(), Slic3r::GUI::Selection::VolumeCache::get_volume_transform(), Instance, Slic3r::GUI::TransformationType::instance(), is_from_fully_selected_instance(), is_wipe_tower(), Slic3r::GUI::TransformationType::local(), m_cache, m_list, m_mode, m_valid, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::WipeTower::move_box_inside_polygon(), NONE, Slic3r::GLVolume::object_idx(), Slic3r::offset(), Slic3r::GUI::plater(), Slic3r::scaled(), set_bounding_boxes_dirty(), Slic3r::GLVolume::set_instance_offset(), Slic3r::GLVolume::set_volume_offset(), synchronize_unselected_instances(), synchronize_unselected_volumes(), transform_instance_relative(), transform_volume_relative(), Slic3r::BoundingBox3Base< PointType >::translate(), Slic3r::Geometry::translation_transform(), Volume, WIPE_TOWER_MARGIN, and Slic3r::GUI::TransformationType::world().

Referenced by Slic3r::GUI::GLGizmoAlignment::align_objects_generic(), Slic3r::GUI::GLGizmoAlignment::align_to_center(), Slic3r::GUI::GLGizmoAlignment::apply_transformation(), Slic3r::GUI::GizmoObjectManipulation::change_position_value(), Slic3r::GUI::GLGizmoAlignment::distribute_objects_generic(), Slic3r::GUI::do_local_z_move(), drop(), Slic3r::GUI::GLGizmoMove3D::on_dragging(), and scale_to_fit_print_volume().

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

◆ translate() [2/4]

void Slic3r::GUI::Selection::translate ( unsigned int object_idx,
const Vec3d & displacement )
1715{
1716 if (!m_valid)
1717 return;
1718
1719 //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj %1%") % object_idx;
1720 //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": %1%, displacement {%2%, %3%, %4%}") % __LINE__ % displacement(X) % displacement(Y) % displacement(Z);
1721 for (unsigned int i : m_list) {
1722 GLVolume& v = *(*m_volumes)[i];
1723 if (v.object_idx() == (int)object_idx)
1724 v.set_instance_offset(v.get_instance_offset() + displacement);
1725 }
1726
1727 std::set<unsigned int> done; // prevent processing volumes twice
1728 done.insert(m_list.begin(), m_list.end());
1729
1730 for (unsigned int i : m_list) {
1731 if (done.size() == m_volumes->size())
1732 break;
1733
1734 int object_idx = (*m_volumes)[i]->object_idx();
1735 if (object_idx >= 1000)
1736 continue;
1737
1738 // Process unselected volumes of the object.
1739 for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) {
1740 if (done.size() == m_volumes->size())
1741 break;
1742
1743 if (done.find(j) != done.end())
1744 continue;
1745
1746 GLVolume& v = *(*m_volumes)[j];
1747 if (v.object_idx() != object_idx)
1748 continue;
1749
1750 v.set_instance_offset(v.get_instance_offset() + displacement);
1751 done.insert(j);
1752 }
1753 }
1754
1756}

References Slic3r::GLVolume::get_instance_offset(), m_list, m_valid, m_volumes, Slic3r::GLVolume::object_idx(), set_bounding_boxes_dirty(), and Slic3r::GLVolume::set_instance_offset().

Here is the call graph for this function:

◆ translate() [3/4]

void Slic3r::GUI::Selection::translate ( unsigned int object_idx,
unsigned int instance_idx,
const Vec3d & displacement )
1759{
1760 if (!m_valid)
1761 return;
1762
1763 //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj %1%, instance %2%") % object_idx % instance_idx;
1764 //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": %1%, displacement {%2%, %3%, %4%}") % __LINE__ % displacement(X) % displacement(Y) % displacement(Z);
1765 // Every volume of the instance, selected or not, so that the instance moves as a whole.
1766 for (GLVolume* v : *m_volumes) {
1767 if (v->object_idx() == (int)object_idx && v->instance_idx() == (int)instance_idx)
1768 v->set_instance_offset(v->get_instance_offset() + displacement);
1769 }
1770
1772}

References m_valid, m_volumes, and set_bounding_boxes_dirty().

Here is the call graph for this function:

◆ translate() [4/4]

void Slic3r::GUI::Selection::translate ( unsigned int object_idx,
unsigned int instance_idx,
unsigned int volume_idx,
const Vec3d & displacement,
bool local = true )
1775{
1776 if (!m_valid) return;
1777
1778 for (unsigned int i : m_list) {
1779 GLVolume &v = *(*m_volumes)[i];
1780 if (v.object_idx() == (int) object_idx && v.instance_idx() == (int) instance_idx && v.volume_idx() == (int) volume_idx) {
1781 Vec3d local_displacement = displacement;
1782 if (!local)
1783 local_displacement = v.get_instance_transformation().get_matrix_no_offset().inverse() * displacement;
1784 v.set_volume_offset(v.get_volume_offset() + local_displacement);
1785 }
1786 }
1787
1789}

References Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::GLVolume::get_volume_offset(), Slic3r::GLVolume::instance_idx(), m_list, m_valid, Slic3r::GLVolume::object_idx(), set_bounding_boxes_dirty(), Slic3r::GLVolume::set_volume_offset(), and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ unlock_volume_selection_mode()

void Slic3r::GUI::Selection::unlock_volume_selection_mode ( )
inline

◆ update_type()

void Slic3r::GUI::Selection::update_type ( )
private
2310{
2311 m_cache.content.clear();
2312 m_type = Mixed;
2313
2314 for (unsigned int i : m_list)
2315 {
2316 const GLVolume* volume = (*m_volumes)[i];
2317 int obj_idx = volume->object_idx();
2318 int inst_idx = volume->instance_idx();
2319 ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.find(obj_idx);
2320 if (obj_it == m_cache.content.end())
2321 obj_it = m_cache.content.insert(ObjectIdxsToInstanceIdxsMap::value_type(obj_idx, InstanceIdxsList())).first;
2322
2323 obj_it->second.insert(inst_idx);
2324 }
2325
2326 bool requires_disable = false;
2327
2328 if (!m_valid)
2329 m_type = Invalid;
2330 else
2331 {
2332 if (m_list.empty())
2333 m_type = Empty;
2334 else if (m_list.size() == 1)
2335 {
2336 const GLVolume* first = (*m_volumes)[*m_list.begin()];
2337 if (first->is_wipe_tower)
2338 m_type = WipeTower;
2339 else if (first->is_modifier)
2340 {
2342 requires_disable = true;
2343 }
2344 else
2345 {
2346 const ModelObject* model_object = m_model->objects[first->object_idx()];
2347 unsigned int volumes_count = (unsigned int)model_object->volumes.size();
2348 unsigned int instances_count = (unsigned int)model_object->instances.size();
2349 if (volumes_count * instances_count == 1)
2350 {
2352 // ensures the correct mode is selected
2353 m_mode = Instance;
2354 }
2355 else if (volumes_count == 1) // instances_count > 1
2356 {
2358 // ensures the correct mode is selected
2359 m_mode = Instance;
2360 }
2361 else
2362 {
2364 requires_disable = true;
2365 }
2366 }
2367 }
2368 else
2369 {
2370 unsigned int sla_volumes_count = 0;
2371 // Note: sla_volumes_count is a count of the selected sla_volumes per object instead of per instance, like a model_volumes_count is
2372 for (unsigned int i : m_list) {
2373 if ((*m_volumes)[i]->volume_idx() < 0)
2374 ++sla_volumes_count;
2375 }
2376
2377 if (m_cache.content.size() == 1) // single object
2378 {
2379 const ModelObject* model_object = m_model->objects[m_cache.content.begin()->first];
2380 unsigned int model_volumes_count = (unsigned int)model_object->volumes.size();
2381
2382 unsigned int instances_count = (unsigned int)model_object->instances.size();
2383 unsigned int selected_instances_count = (unsigned int)m_cache.content.begin()->second.size();
2384 if (model_volumes_count * instances_count + sla_volumes_count == (unsigned int)m_list.size())
2385 {
2387 // ensures the correct mode is selected
2388 m_mode = Instance;
2389 }
2390 else if (selected_instances_count == 1)
2391 {
2392 if (model_volumes_count + sla_volumes_count == (unsigned int)m_list.size())
2393 {
2395 // ensures the correct mode is selected
2396 m_mode = Instance;
2397 }
2398 else
2399 {
2400 unsigned int modifiers_count = 0;
2401 for (unsigned int i : m_list)
2402 {
2403 if ((*m_volumes)[i]->is_modifier)
2404 ++modifiers_count;
2405 }
2406
2407 if (modifiers_count == 0)
2409 else if (modifiers_count == (unsigned int)m_list.size())
2411
2412 requires_disable = true;
2413 }
2414 }
2415 else if ((selected_instances_count > 1) && (selected_instances_count * model_volumes_count + sla_volumes_count == (unsigned int)m_list.size()))
2416 {
2418 // ensures the correct mode is selected
2419 m_mode = Instance;
2420 }
2421 }
2422 else
2423 {
2424 unsigned int sels_cntr = 0;
2425 for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
2426 {
2427 bool is_wipe_tower = it->first >= 1000;
2428 int actual_obj_id = is_wipe_tower ? it->first - 1000 : it->first;
2429 const ModelObject *model_object = m_model->objects[actual_obj_id];
2430 unsigned int volumes_count = (unsigned int)model_object->volumes.size();
2431 unsigned int instances_count = (unsigned int)model_object->instances.size();
2432 sels_cntr += volumes_count * instances_count;
2433 }
2434 if (sels_cntr + sla_volumes_count == (unsigned int)m_list.size())
2435 {
2437 // ensures the correct mode is selected
2438 m_mode = Instance;
2439 }
2440 }
2441 }
2442 }
2443
2444 //BBS: remove the disable logic here
2445 /*int object_idx = get_object_idx();
2446 int instance_idx = get_instance_idx();
2447 for (GLVolume* v : *m_volumes)
2448 {
2449 v->disabled = requires_disable ? (v->object_idx() != object_idx) || (v->instance_idx() != instance_idx) : false;
2450 }*/
2451
2452#if ENABLE_SELECTION_DEBUG_OUTPUT
2453 std::cout << "Selection: ";
2454 std::cout << "mode: ";
2455 switch (m_mode)
2456 {
2457 case Volume:
2458 {
2459 std::cout << "Volume";
2460 break;
2461 }
2462 case Instance:
2463 {
2464 std::cout << "Instance";
2465 break;
2466 }
2467 }
2468
2469 std::cout << " - type: ";
2470
2471 switch (m_type)
2472 {
2473 case Invalid:
2474 {
2475 std::cout << "Invalid" << std::endl;
2476 break;
2477 }
2478 case Empty:
2479 {
2480 std::cout << "Empty" << std::endl;
2481 break;
2482 }
2483 case WipeTower:
2484 {
2485 std::cout << "WipeTower" << std::endl;
2486 break;
2487 }
2488 case SingleModifier:
2489 {
2490 std::cout << "SingleModifier" << std::endl;
2491 break;
2492 }
2493 case MultipleModifier:
2494 {
2495 std::cout << "MultipleModifier" << std::endl;
2496 break;
2497 }
2498 case SingleVolume:
2499 {
2500 std::cout << "SingleVolume" << std::endl;
2501 break;
2502 }
2503 case MultipleVolume:
2504 {
2505 std::cout << "MultipleVolume" << std::endl;
2506 break;
2507 }
2508 case SingleFullObject:
2509 {
2510 std::cout << "SingleFullObject" << std::endl;
2511 break;
2512 }
2513 case MultipleFullObject:
2514 {
2515 std::cout << "MultipleFullObject" << std::endl;
2516 break;
2517 }
2518 case SingleFullInstance:
2519 {
2520 std::cout << "SingleFullInstance" << std::endl;
2521 break;
2522 }
2524 {
2525 std::cout << "MultipleFullInstance" << std::endl;
2526 break;
2527 }
2528 case Mixed:
2529 {
2530 std::cout << "Mixed" << std::endl;
2531 break;
2532 }
2533 }
2534#endif // ENABLE_SELECTION_DEBUG_OUTPUT
2535}
unsigned int volumes_count() const
Definition Selection.hpp:322

References Empty, Instance, Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Invalid, is_wipe_tower(), m_cache, m_list, m_mode, m_model, m_type, m_valid, m_volumes, Mixed, MultipleFullInstance, MultipleFullObject, MultipleModifier, MultipleVolume, Slic3r::GLVolume::object_idx(), SingleFullInstance, SingleFullObject, SingleModifier, SingleVolume, Volume, Slic3r::ModelObject::volumes, volumes_count(), and WipeTower.

Referenced by add(), add_all(), add_curr_plate(), add_instance(), add_object(), add_object_from_idx(), add_volume(), add_volumes(), clear(), instances_changed(), remove(), remove_curr_plate(), remove_instance(), remove_object(), remove_volume(), remove_volumes(), set_deserialized(), and volumes_changed().

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

◆ update_valid()

void Slic3r::GUI::Selection::update_valid ( )
private
2305{
2306 m_valid = (m_volumes != nullptr) && (m_model != nullptr);
2307}

References m_model, m_valid, and m_volumes.

Referenced by set_model(), and set_volumes().

Here is the caller graph for this function:

◆ volumes_changed()

void Slic3r::GUI::Selection::volumes_changed ( const std::vector< size_t > & map_volume_old_to_new)
811{
812 assert(m_valid);
813 assert(m_mode == Volume);
814 IndicesList list_new;
815 for (unsigned int idx : m_list)
816 if (map_volume_old_to_new[idx] != size_t(-1)) {
817 unsigned int new_idx = (unsigned int)map_volume_old_to_new[idx];
818 (*m_volumes)[new_idx]->selected = true;
819 list_new.insert(new_idx);
820 }
821 m_list = std::move(list_new);
822 update_type();
824}
std::set< unsigned int > IndicesList
Definition Selection.hpp:49

References m_list, m_mode, m_valid, set_bounding_boxes_dirty(), update_type(), and Volume.

Here is the call graph for this function:

◆ volumes_count()

unsigned int Slic3r::GUI::Selection::volumes_count ( ) const
inline
322{ return (unsigned int)m_list.size(); }

References m_list.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_edit_svg(), Slic3r::GUI::MenuFactory::append_menu_item_edit_text(), Slic3r::GUI::do_local_z_rotate(), anonymous_namespace{SurfaceDrag.cpp}::is_embossed_object(), Slic3r::GUI::GLGizmoAssembly::on_is_activable(), Slic3r::GUI::GLGizmoMeasure::on_is_activable(), and update_type().

Here is the caller graph for this function:

Member Data Documentation

◆ m_arrow

GLModel Slic3r::GUI::Selection::m_arrow
private

◆ m_auto_drop

bool Slic3r::GUI::Selection::m_auto_drop = true
private

Referenced by render_bounding_box().

◆ m_bounding_box

std::optional<BoundingBoxf3> Slic3r::GUI::Selection::m_bounding_box
private

◆ m_bounding_box_in_current_reference_system

std::optional<std::pair<BoundingBoxf3, Transform3d> > Slic3r::GUI::Selection::m_bounding_box_in_current_reference_system
private

◆ m_bounding_sphere

std::optional<std::pair<Vec3d, double> > Slic3r::GUI::Selection::m_bounding_sphere
private

◆ m_box

GLModel Slic3r::GUI::Selection::m_box
private

Referenced by render_bounding_box().

◆ m_cache

◆ m_clipboard

◆ m_curved_arrow

GLModel Slic3r::GUI::Selection::m_curved_arrow
private

◆ m_enabled

bool Slic3r::GUI::Selection::m_enabled
private

Referenced by Selection(), is_enabled(), and set_enabled().

◆ m_full_scaled_instance_bounding_box

std::optional<BoundingBoxf3> Slic3r::GUI::Selection::m_full_scaled_instance_bounding_box
private

◆ m_full_unscaled_instance_bounding_box

std::optional<BoundingBoxf3> Slic3r::GUI::Selection::m_full_unscaled_instance_bounding_box
private

◆ m_full_unscaled_instance_local_bounding_box

std::optional<BoundingBoxf3> Slic3r::GUI::Selection::m_full_unscaled_instance_local_bounding_box
private

◆ m_list

◆ m_mode

◆ m_model

◆ m_planes

Planes Slic3r::GUI::Selection::m_planes
private

◆ m_scale_factor

float Slic3r::GUI::Selection::m_scale_factor
private

◆ m_scaled_instance_bounding_box

std::optional<BoundingBoxf3> Slic3r::GUI::Selection::m_scaled_instance_bounding_box
private

◆ m_type

◆ m_unscaled_instance_bounding_box

std::optional<BoundingBoxf3> Slic3r::GUI::Selection::m_unscaled_instance_bounding_box
private

◆ m_valid

◆ m_volume_selection_locked

bool Slic3r::GUI::Selection::m_volume_selection_locked { false }
private

◆ m_volume_selection_mode

EMode Slic3r::GUI::Selection::m_volume_selection_mode { Instance }
private

◆ m_volumes


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Selection.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Selection.cpp