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

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

Inheritance diagram for Slic3r::GUI::PartPlate:
Collaboration diagram for Slic3r::GUI::PartPlate:

Public Types

enum  HeightLimitMode { HEIGHT_LIMIT_NONE , HEIGHT_LIMIT_BOTTOM , HEIGHT_LIMIT_TOP , HEIGHT_LIMIT_BOTH }
enum class  ImexPlacementViolation { None , Object , PrimeTower }
using Timestamp = uint64_t

Public Member Functions

 PartPlate ()
 PartPlate (PartPlateList *partplate_list, Vec3d origin, int width, int depth, double height, Plater *platerObj, Model *modelObj, bool printable=true, PrinterTechnology tech=ptFFF)
 ~PartPlate ()
bool operator< (PartPlate &) const
void clear (bool clear_sliced_result=true)
BedType get_bed_type (bool load_from_project=false) const
void set_bed_type (BedType bed_type)
void reset_bed_type ()
void reset_skirt_start_angle ()
DynamicPrintConfig * config ()
void set_print_seq (PrintSequence print_seq=PrintSequence::ByDefault)
PrintSequence get_print_seq () const
PrintSequence get_real_print_seq (bool *plate_same_as_global=nullptr) const
std::vector< int > get_real_filament_maps (const DynamicConfig &g_config, bool *use_global_param=nullptr) const
std::vector< int > get_real_filament_volume_maps (const DynamicConfig &g_config, bool *use_global_param=nullptr) const
FilamentMapMode get_real_filament_map_mode (const DynamicConfig &g_config, bool *use_global_param=nullptr) const
FilamentMapMode get_filament_map_mode () const
void set_filament_map_mode (const FilamentMapMode &mode)
std::vector< int > get_filament_maps () const
void set_filament_maps (const std::vector< int > &f_maps)
std::vector< int > get_filament_volume_maps () const
void set_filament_volume_maps (const std::vector< int > &f_maps)
void clear_filament_volume_map ()
std::vector< int > get_filament_nozzle_maps () const
void set_filament_nozzle_maps (const std::vector< int > &f_maps)
void clear_filament_map ()
void clear_filament_map_mode ()
bool has_spiral_mode_config () const
bool get_spiral_vase_mode () const
void set_spiral_vase_mode (bool spiral_mode, bool as_global)
std::string get_imex_mode () const
std::string get_effective_imex_mode () const
void set_imex_mode (const std::string &mode)
void reset_imex_mode ()
std::map< int, int > get_imex_head_filament_map () const
void set_imex_head_filament_map (const std::map< int, int > &m)
void reset_imex_head_filament_map ()
ColorRGBA get_imex_head_filament_color (int physical_head) const
ColorRGBA get_imex_head_filament_color (int physical_head, const ConfigOptionInts &pem, const std::map< int, int > &plate_map) const
const std::vector< std::unique_ptr< GLVolume > > & get_imex_ghost_volumes () const
void update_imex_ghost_transforms (const std::function< std::optional< Transform3d >(int, int)> &primary_live_xf={})
void update_imex_ghost_colors ()
void invalidate_imex_ghosts ()
std::vector< Vec2d > get_plate_wrapping_detection_area () const
void set_index (int index)
int get_index ()
std::string get_plate_name () const
void generate_plate_name_texture ()
void set_plate_name (const std::string &name)
void set_timelapse_warning_code (int code)
int timelapse_warning_code ()
void get_print (PrintBase **print, GCodeResult **result, int *index)
void set_print (PrintBase *print, GCodeResult *result=nullptr, int index=-1)
std::string get_gcode_filename ()
bool is_valid_gcode_file ()
Vec3d get_center_origin ()
void set_pos_and_size (Vec3d &origin, int width, int depth, double height, bool with_instance_move, bool do_clear=true)
Vec2d get_size () const
ModelObjectPtrs get_objects ()
ModelObjectPtrs get_objects_on_this_plate ()
ModelInstance * get_instance (int obj_id, int instance_id)
BoundingBoxf3 get_objects_bounding_box ()
Vec3d get_origin ()
WipeTowerFootprint estimate_wipe_tower_footprint (const DynamicPrintConfig &config, int plate_extruder_size=0, bool use_global_objects=false) const
arrangement::ArrangePolygon estimate_wipe_tower_polygon (const DynamicPrintConfig &config, int plate_index, Vec3d &wt_pos, Vec3d &wt_size, int plate_extruder_size=0, bool use_global_objects=false, WipeTowerRelocation *relocation=nullptr) const
bool check_objects_empty_and_gcode3mf (std::vector< int > &result) const
std::vector< int > get_extruders (bool conside_custom_gcode=false, bool expand_mixed_slots=true) const
std::vector< int > get_extruders (bool conside_custom_gcode, const DynamicPrintConfig &glb_config, const DynamicPrintConfig &project_config, bool expand_mixed_slots=true) const
std::vector< int > get_extruders_under_cli (bool conside_custom_gcode, DynamicPrintConfig &full_config, bool expand_mixed_slots=true) const
std::vector< int > get_extruders_without_support (bool conside_custom_gcode=false) const
std::vector< int > get_used_filaments ()
const std::vector< FilamentInfo > & get_slice_filaments_info () const
int get_physical_extruder_by_filament_id (const DynamicConfig &g_config, int idx) const
int get_logical_extruder_by_filament_id (const DynamicConfig &g_config, int idx) const
std::vector< int > get_effective_exclusion_filament_maps (const DynamicConfig &g_config, size_t filament_count, size_t extruder_count) const
std::map< int, size_t > get_object_filament_extruders (const ModelObject &object, const DynamicConfig &g_config, size_t extruder_count) const
bool check_filament_printable (const DynamicPrintConfig &config, wxString &error_message)
bool check_tpu_printable_status (const DynamicPrintConfig &config, const std::vector< int > &tpu_filaments)
bool check_mixture_of_pla_and_petg (const DynamicPrintConfig &config)
bool check_single_extruder_mixed_filament_risk (const DynamicPrintConfig &config, std::string &warning_text) const
bool check_mixture_filament_compatible (const DynamicPrintConfig &config, std::string &error_msg)
bool check_compatible_of_nozzle_and_filament (const DynamicPrintConfig &config, const std::vector< std::string > &filament_presets, std::string &error_msg)
bool contain_instance (int obj_id, int instance_id)
bool contain_instance_totally (ModelObject *object, int instance_id) const
bool contain_instance_totally (int obj_id, int instance_id) const
bool contain_any_instance_totally (int obj_id) const
bool is_left_top_of (int obj_id, int instance_id)
bool check_outside (int obj_id, int instance_id, BoundingBoxf3 *bounding_box=nullptr)
void clear_exclusion_volume_intersections ()
void invalidate_exclusion_volume_preview ()
bool intersect_instance (int obj_id, int instance_id, BoundingBoxf3 *bounding_box=nullptr)
int add_instance (int obj_id, int instance_id, bool move_position, BoundingBoxf3 *bounding_box=nullptr)
int remove_instance (int obj_id, int instance_id)
void translate_all_instance (Vec3d position)
void duplicate_all_instance (unsigned int dup_count, bool need_skip, std::map< int, bool > &skip_objects)
void update_instance_exclude_status (int obj_id, int instance_id, BoundingBoxf3 *bounding_box=nullptr)
void update_object_index (int obj_idx_removed, int obj_idx_max)
void set_vase_mode_related_object_config (int obj_id=-1)
bool empty ()
int printable_instance_size ()
bool has_printable_instances ()
bool is_all_instances_unprintable ()
void move_instances_to (PartPlate &left_plate, PartPlate &right_plate, BoundingBoxf3 *bounding_box=nullptr)
const Pointfs & get_shape () const
bool set_shape (const Pointfs &shape, const Pointfs &exclude_areas, const std::vector< Pointfs > &extruder_areas, const std::vector< double > &extruder_heights, Vec2d position, float height_to_lid, float height_to_rod)
const std::vector< Pointfs > & get_extruder_areas () const
const std::vector< double > & get_extruder_heights () const
bool contains (const Vec3d &point) const
bool contains (const GLVolume &v) const
bool contains (const BoundingBoxf3 &bb) const
bool intersects (const BoundingBoxf3 &bb) const
bool belt_open_y () const
void open_belt_y (BoundingBoxf3 &box) const
void render (const Transform3d &view_matrix, const Transform3d &projection_matrix, bool bottom, bool only_body=false, bool force_background_color=false, HeightLimitMode mode=HEIGHT_LIMIT_NONE, int hover_id=-1, bool render_cali=false, bool show_grid=true, bool hide_chrome=false)
void set_selected ()
void set_unselected ()
void set_hover_id (int id)
const BoundingBoxf3 & get_bounding_box (bool extended=false)
const BoundingBox get_bounding_box_crd ()
BoundingBoxf3 get_plate_box ()
BoundingBoxf3 get_build_volume (bool use_share=false)
Polygon get_shared_printable_polygon () const
const std::vector< BoundingBoxf3 > & get_exclude_areas ()
void update_states ()
bool is_locked () const
void lock (bool state)
bool is_printable () const
bool can_slice () const
ImexPlacementViolation imex_placement_violation ()
bool imex_hull_violates (const Polygon &hull) const
Polygon imex_wipe_tower_hull () const
bool has_imex_multimaterial_conflict () const
std::optional< BoundingBoxf > imex_primary_zone ()
const std::vector< BoundingBoxf3 > & imex_collision_zones () const
void update_slice_ready_status (bool ready_slice)
bool is_apply_result_invalid () const
void update_apply_result_invalid (bool invalid)
bool is_slice_result_valid () const
bool is_slice_result_ready_for_print () const
bool is_slice_result_ready_for_export ()
void update_slice_result_valid_state (bool valid=false)
void update_slicing_percent (float percent)
float get_slicing_percent ()
void update_slice_context (BackgroundSlicingProcess &process)
Print * fff_print ()
GCodeProcessorResult * get_slice_result ()
std::string get_tmp_gcode_path ()
std::string get_temp_config_3mf_path ()
void set_tmp_gcode_path (std::string new_path)
int load_gcode_from_file (const std::string &filename)
int load_thumbnail_data (std::string filename, ThumbnailData &thumb_data)
int load_pattern_thumbnail_data (std::string filename)
int load_pattern_box_data (std::string filename)
std::vector< int > get_first_layer_print_sequence () const
std::vector< LayerPrintSequence > get_other_layers_print_sequence () const
void set_first_layer_print_sequence (const std::vector< int > &sorted_filaments)
void set_other_layers_print_sequence (const std::vector< LayerPrintSequence > &layer_seq_list)
void update_first_layer_print_sequence (size_t filament_nums)
void update_first_layer_print_sequence_when_delete_filament (size_t filamen_id)
void print () const
void on_extruder_count_changed (int extruder_count)
void set_filament_count (int filament_count)
void on_filament_added ()
void on_filament_deleted (int filament_count, int filament_id)
template<class Archive>
void load (Archive &ar)
template<class Archive>
void save (Archive &ar) const
ObjectID id () const
virtual Timestamp timestamp () const

Static Public Member Functions

static bool is_imex_ghost_composite_id (int object_id)
static int imex_ghost_head_from_composite_id (int object_id)
static int imex_ghost_composite_id_for_head (int physical_head)
static void update_render_colors ()
static void load_render_colors ()

Public Attributes

ThumbnailData thumbnail_data
ThumbnailData no_light_thumbnail_data
ThumbnailData obj_preview_thumbnail_data
ThumbnailData top_thumbnail_data
ThumbnailData pick_thumbnail_data
PlateBBoxData cali_bboxes_data

Static Public Attributes

static constexpr unsigned int PLATE_NAME_HOVER_ID = 6
static constexpr unsigned int PLATE_FILAMENT_MAP_ID = 8
static constexpr unsigned int PLATE_IMEX_MODE_ID = 9
static constexpr unsigned int GRABBER_COUNT = 10
static constexpr int IMEX_GHOST_COMPOSITE_ID_BASE = -100000
static constexpr int IMEX_GHOST_MAX_HEADS = 256
static ColorRGBA SELECT_COLOR = { 0.2666f, 0.2784f, 0.2784f, 1.0f }
static ColorRGBA UNSELECT_COLOR = { 0.82f, 0.82f, 0.82f, 1.0f }
static ColorRGBA UNSELECT_DARK_COLOR = { 0.384f, 0.384f, 0.412f, 1.0f }
static ColorRGBA DEFAULT_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f }
static ColorRGBA LINE_BOTTOM_COLOR = { 0.8f, 0.8f, 0.8f, 0.4f }
static ColorRGBA LINE_TOP_COLOR = { 0.89f, 0.89f, 0.89f, 1.0f }
static ColorRGBA LINE_TOP_DARK_COLOR = { 0.431f, 0.431f, 0.463f, 1.0f }
static ColorRGBA LINE_TOP_SEL_COLOR = { 0.5294f, 0.5451, 0.5333f, 1.0f}
static ColorRGBA LINE_TOP_SEL_DARK_COLOR = { 0.298f, 0.298f, 0.3333f, 1.0f}
static ColorRGBA HEIGHT_LIMIT_BOTTOM_COLOR = { 0.4f, 0.4f, 1.0f, 1.0f }
static ColorRGBA HEIGHT_LIMIT_TOP_COLOR = { 0.6f, 0.6f, 1.0f, 1.0f }
static const int plate_thumbnail_width = 512
static const int plate_thumbnail_height = 512

Protected Member Functions

void set_new_unique_id ()
void set_invalid_id ()
void copy_id (const ObjectBase &rhs)
virtual void assign_new_unique_ids_recursive ()

Private Member Functions

void init ()
bool valid_instance (int obj_id, int instance_id) const
void generate_print_polygon (ExPolygon &print_polygon)
void generate_exclude_polygon (ExPolygon &exclude_polygon)
void generate_logo_polygon (ExPolygon &logo_polygon)
void calc_bounding_boxes () const
void calc_triangles (const ExPolygon &poly)
void calc_exclude_triangles (const ExPolygon &poly)
void calc_triangles_from_polygon (const ExPolygon &poly, GLModel &render_model)
void calc_gridlines (const ExPolygon &poly, const BoundingBox &pp_bbox)
void calc_height_limit ()
void calc_imex_zones ()
void ensure_imex_zones ()
std::string build_imex_cache_key () const
void calc_imex_ghosts ()
void ensure_imex_ghosts ()
std::string build_imex_ghost_cache_key () const
bool resolve_active_mode_tools (std::string &out_tools_str, int &out_primary_phys) const
void render_imex_zones (bool force_default_color)
void refresh_imex_icon ()
float icon_scale_factor () const
void calc_vertex_for_number (int index, bool one_number, GLModel &buffer)
void calc_vertex_for_plate_name_edit_icon (GLTexture *texture, int index, PickingModel &model)
void calc_vertex_for_icons (int index, PickingModel &model)
void calc_vertex_for_imex_warn_badge (int imex_icon_index, GLModel &model)
void render_background (bool force_default_color=false)
void render_logo (bool bottom, bool render_cali=true)
void render_logo_texture (GLTexture &logo_texture, GLModel &logo_buffer, bool bottom)
void render_exclude_area (bool force_default_color)
void render_exclusion_volume_previews (bool force_default_color)
void render_exclusion_volume_intersections ()
void update_exclusion_volume_preview_models ()
std::string exclusion_volume_preview_cache_key (const std::vector< BedExcludeRegion > &regions) const
double max_broad_phase_intersecting_object_height (const Polygons &regions) const
void render_grid (bool bottom)
void render_wrapping_detection_area (bool force_default_color)
void render_height_limit (PartPlate::HeightLimitMode mode=HEIGHT_LIMIT_BOTH)
void render_icon_texture (GLModel &buffer, GLTexture &texture)
void set_hover_tooltip (const std::string &tooltip)
void render_icons (bool bottom, bool only_name=false, int hover_id=-1)
void render_only_numbers (bool bottom)
void render_plate_name_texture ()
void invalidate_plate_name_texture ()
void register_raycasters_for_picking (GLCanvas3D &canvas)
int picking_id_component (int idx) const
void on_filament_map_mode_change ()
Polygons wipe_tower_obstacles (const DynamicPrintConfig &config) const
template<class Archive>
void serialize (Archive &ar)

Static Private Member Functions

static ObjectID generate_new_id ()
template<class Archive>
static void load_and_construct (Archive &ar, cereal::construct< ObjectBase > &construct)

Private Attributes

PartPlateList * m_partplate_list {nullptr }
Plater * m_plater
Model * m_model
PrinterTechnology printer_technology
std::set< std::pair< int, int > > obj_to_instance_set
std::set< std::pair< int, int > > instance_outside_set
int m_plate_index
Vec3d m_origin
int m_width
int m_depth
double m_height
float m_height_to_lid
float m_height_to_rod
bool m_printable
bool m_locked
bool m_ready_for_slice
bool m_slice_result_valid
bool m_apply_invalid {false}
float m_slice_percent
Print * m_print
GCodeProcessorResult * m_gcode_result
std::vector< FilamentInfo > slice_filaments_info
int m_print_index
std::string m_tmp_gcode_path
std::string m_temp_config_3mf_path
std::string m_gcode_path_from_3mf
Pointfs m_shape
Pointfs m_exclude_area
std::vector< Pointfs > m_extruder_areas
std::vector< double > m_extruder_heights
BoundingBoxf3 m_bounding_box
BoundingBoxf3 m_extended_bounding_box
std::vector< BoundingBoxf3 > m_exclude_bounding_box
BoundingBoxf3 m_grabber_box
Transform3d m_grabber_trans_matrix
Slic3r::Geometry::Transformation position
std::vector< Vec3f > positions
ExPolygon m_print_polygon
PickingModel m_triangles
GLModel m_exclude_triangles
GLModel m_wrapping_detection_triangles
GLModel m_exclusion_volume_floor_triangles
GLModel m_exclusion_volume_border_triangles
std::vector< std::pair< std::unique_ptr< GLModel >, ColorRGBA > > m_extruder_exclusion_volume_borders
GLModel m_active_exclusion_volume_prisms
GLModel m_exclusion_volume_intersection_triangles
std::string m_exclusion_volume_preview_cache_key
bool m_exclusion_volume_preview_dirty { true }
bool m_exclusion_volume_intersections_cleared { false }
GLModel m_logo_triangles
GLModel m_gridlines
GLModel m_gridlines_bolder
std::vector< GLModel > m_imex_copy_zones
std::vector< GLModel > m_imex_mirror_zones
std::vector< BoundingBoxf3 > m_imex_secondary_zone_boxes
std::vector< BoundingBoxf3 > m_imex_collision_zones
std::vector< GLModel > m_imex_collision_overlay
std::vector< GLModel > m_imex_margin_overlay
std::optional< BoundingBoxf > m_imex_primary_zone_box
std::map< int, Vec2d > m_imex_head_zone_centers
int m_imex_primary_head { -1 }
std::string m_imex_zones_mode_cache { "\x01" }
std::vector< std::unique_ptr< GLVolume > > m_imex_ghost_volumes
std::string m_imex_ghost_cache_key { "\x01" }
GLModel m_height_limit_common
GLModel m_height_limit_bottom
GLModel m_height_limit_top
PickingModel m_del_icon
PickingModel m_arrange_icon
PickingModel m_orient_icon
PickingModel m_lock_icon
PickingModel m_plate_settings_icon
PickingModel m_plate_filament_map_icon
PickingModel m_plate_name_edit_icon
PickingModel m_move_front_icon
PickingModel m_imex_mode_icon
GLModel m_imex_warn_icon
GLModel m_plate_idx_icon
GLTexture m_texture
float m_scale_factor { 1.0f }
GLUquadricObject * m_quadric
int m_hover_id
bool m_selected
int m_timelapse_warning_code = 0
DynamicPrintConfig m_config
std::string m_name
GLModel m_plate_name_icon
GLTexture m_name_texture
wxCoord m_name_texture_width
wxCoord m_name_texture_height
ObjectID m_id

Static Private Attributes

static size_t s_last_id = 0

Friends

class PartPlateList
class cereal::access
class UndoRedo::StackImpl

Detailed Description

Member Typedef Documentation

◆ Timestamp

using Slic3r::ObjectBase::Timestamp = uint64_t
inherited

Member Enumeration Documentation

◆ HeightLimitMode

Enumerator
HEIGHT_LIMIT_NONE 
HEIGHT_LIMIT_BOTTOM 
HEIGHT_LIMIT_TOP 
HEIGHT_LIMIT_BOTH 
110 {
115 };
@ HEIGHT_LIMIT_TOP
Definition PartPlate.hpp:113
@ HEIGHT_LIMIT_BOTH
Definition PartPlate.hpp:114
@ HEIGHT_LIMIT_BOTTOM
Definition PartPlate.hpp:112
@ HEIGHT_LIMIT_NONE
Definition PartPlate.hpp:111

◆ ImexPlacementViolation

Enumerator
None 
Object 
PrimeTower 
625{ None, Object, PrimeTower };
@ None
Definition SketchEngine.hpp:180

Constructor & Destructor Documentation

◆ PartPlate() [1/2]

Slic3r::GUI::PartPlate::PartPlate ( )
227 : ObjectBase(-1), m_plater(nullptr), m_model(nullptr), m_quadric(nullptr)
228{
229 assert(this->id().invalid());
230 init();
231}
GLUquadricObject * m_quadric
Definition PartPlate.hpp:205
Plater * m_plater
Definition PartPlate.hpp:119
void init()
Definition PartPlate.cpp:248
Model * m_model
Definition PartPlate.hpp:120
ObjectBase()
Definition ObjectID.hpp:79

References Slic3r::ObjectBase::ObjectBase(), init(), m_model, m_plater, and m_quadric.

Referenced by move_instances_to(), and operator<().

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

◆ PartPlate() [2/2]

Slic3r::GUI::PartPlate::PartPlate ( PartPlateList * partplate_list,
Vec3d origin,
int width,
int depth,
double height,
Plater * platerObj,
Model * modelObj,
bool printable = true,
PrinterTechnology tech = ptFFF )
234 :m_partplate_list(partplate_list), m_plater(platerObj), m_model(modelObj), printer_technology(tech), m_origin(origin), m_width(width), m_depth(depth), m_height(height), m_printable(printable)
235{
236 init();
237}
int m_depth
Definition PartPlate.hpp:128
PrinterTechnology printer_technology
Definition PartPlate.hpp:121
double m_height
Definition PartPlate.hpp:129
Vec3d m_origin
Definition PartPlate.hpp:126
PartPlateList * m_partplate_list
Definition PartPlate.hpp:118
bool m_printable
Definition PartPlate.hpp:132
int m_width
Definition PartPlate.hpp:127

References init(), m_depth, m_height, m_model, m_origin, m_partplate_list, m_plater, m_printable, m_width, PartPlateList, and printer_technology.

Here is the call graph for this function:

◆ ~PartPlate()

Slic3r::GUI::PartPlate::~PartPlate ( )
240{
241 clear();
242 //if (m_quadric != nullptr)
243 // ::gluDeleteQuadric(m_quadric);
244
245 //boost::nowide::remove(m_tmp_gcode_path.c_str());
246}
void clear(bool clear_sliced_result=true)
Definition PartPlate.cpp:4173

References clear().

Here is the call graph for this function:

Member Function Documentation

◆ add_instance()

int Slic3r::GUI::PartPlate::add_instance ( int obj_id,
int instance_id,
bool move_position,
BoundingBoxf3 * bounding_box = nullptr )
4647{
4648 if (!valid_instance(obj_id, instance_id))
4649 {
4650 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": plate_id %1%, invalid obj_id %2%, instance_id %3%, move_position %4%") % m_plate_index % obj_id % instance_id % move_position;
4651 return -1;
4652 }
4653
4654 ModelObject* object = m_model->objects[obj_id];
4655 ModelInstance* instance = object->instances[instance_id];
4656 std::pair<int, int> pair(obj_id, instance_id);
4657
4658 obj_to_instance_set.insert(pair);
4660
4661 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plate_id %1%, add instance obj_id %2%, instance_id %3%, move_position %4%") % m_plate_index % obj_id % instance_id % move_position;
4662
4663 if (move_position)
4664 {
4665 //move this instance into the new position
4667 center.z() = instance->get_transformation().get_offset(Z);
4668
4669 instance->set_offset(center);
4670 object->invalidate_bounding_box();
4671 }
4672
4673 //need to judge whether this instance has an outer part
4674 bool outside = check_outside(obj_id, instance_id, bounding_box);
4675 if (outside)
4676 instance_outside_set.insert(pair);
4677
4678 if (m_ready_for_slice && outside)
4679 {
4680 m_ready_for_slice = false;
4681 }
4682 else if ((obj_to_instance_set.size() == 1) && (!m_ready_for_slice) && !outside)
4683 {
4684 m_ready_for_slice = true;
4685 }
4686
4687 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% , m_ready_for_slice changes to %2%") % m_plate_index %m_ready_for_slice;
4688 if (m_plater)
4689 m_plater->mark_plate_toolbar_image_dirty();
4690 return 0;
4691}
int m_plate_index
Definition PartPlate.hpp:125
bool m_ready_for_slice
Definition PartPlate.hpp:134
bool valid_instance(int obj_id, int instance_id) const
Definition PartPlate.cpp:595
Vec3d get_center_origin()
Definition PartPlate.cpp:4266
std::set< std::pair< int, int > > obj_to_instance_set
Definition PartPlate.hpp:123
void invalidate_exclusion_volume_preview()
Definition PartPlate.cpp:2428
std::set< std::pair< int, int > > instance_outside_set
Definition PartPlate.hpp:124
bool check_outside(int obj_id, int instance_id, BoundingBoxf3 *bounding_box=nullptr)
Definition PartPlate.cpp:4497
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
BoundingBoxf3 bounding_box(const TriangleMesh &m)
Definition TriangleMesh.hpp:391
@ Z
Definition libslic3r.h:143
@ outside
Definition CutSurface.cpp:237

References Slic3r::bounding_box(), Slic3r::center(), check_outside(), get_center_origin(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::ModelInstance::get_transformation(), instance_outside_set, invalidate_exclusion_volume_preview(), m_model, m_plate_index, m_plater, m_ready_for_slice, obj_to_instance_set, Slic3r::ModelInstance::set_offset(), valid_instance(), and Slic3r::Z.

Referenced by Slic3r::GUI::PartPlateList::add_to_plate(), Slic3r::GUI::PartPlateList::construct_objects_list_for_new_plate(), move_instances_to(), Slic3r::GUI::PartPlateList::notify_instance_update(), and Slic3r::GUI::PartPlateList::reload_all_objects().

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

◆ assign_new_unique_ids_recursive()

virtual void Slic3r::ObjectBase::assign_new_unique_ids_recursive ( )
inlineprotectedvirtualinherited

Reimplemented in Slic3r::Model, Slic3r::ModelObject, and Slic3r::ModelVolume.

95{ this->set_new_unique_id(); }
void set_new_unique_id()
Definition ObjectID.hpp:89

References set_new_unique_id().

Here is the call graph for this function:

◆ belt_open_y()

bool Slic3r::GUI::PartPlate::belt_open_y ( ) const
5264{
5265 // Headless (CLI) plates have no plater and no wxApp behind wxGetApp(); the CLI's own belt
5266 // handling lives in Print::validate().
5267 if (m_plater == nullptr || wxGetApp().preset_bundle == nullptr)
5268 return false;
5269 const DynamicPrintConfig &printer = wxGetApp().preset_bundle->printers.get_edited_preset().config;
5270 const auto *belt = printer.option<ConfigOptionBool>("belt_printer");
5271 const auto *infinite_y = printer.option<ConfigOptionBool>("belt_printer_infinite_y");
5272 return belt != nullptr && belt->value && infinite_y != nullptr && infinite_y->value;
5273}

References m_plater, Slic3r::ConfigBase::option(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by open_belt_y().

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

◆ build_imex_cache_key()

std::string Slic3r::GUI::PartPlate::build_imex_cache_key ( ) const
private
758{
759 // CLI / headless slice: no GUI_App is initialized, so `wxGetApp()` returns
760 // memory that segfaults on member access. `m_plater` is set only by the GUI
761 // construction path; treat its absence as "no IMEX state to compute" and
762 // return an empty key. Same guard pattern used by calc_imex_ghosts.
763 if (!m_plater || !wxGetApp().preset_bundle)
764 return "";
765 const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
766 auto* is_imex_opt = printer_cfg.option<ConfigOptionBool>("is_imex");
767 if (!is_imex_opt || !is_imex_opt->value)
768 return "";
769 std::string active_mode = get_effective_imex_mode();
770 // Mode NAME alone is not printer identity: two presets can define the same mode
771 // name with different tool rosters/primary, and imex_firmware_managed_zones
772 // suppresses ghost generation entirely. Both shape the baked zone/ghost set, so
773 // key them directly (previously caught only incidentally, via the ghost key's
774 // since-removed pem entry).
775 std::string active_tools;
776 int primary_phys = -1;
777 resolve_active_mode_tools(active_tools, primary_phys); // empty on failure — keyed as such
778 // imex_tool_layout decides which physical corner tool 0 occupies (flip_x / flip_y inside
779 // compute_imex_zone_layout), so every zone rectangle, collision strip and ghost offset moves
780 // when it changes while every other keyed field stays put. Without it the key is identical
781 // across a layout change and the baked zones go stale; that this currently appears to work is
782 // incidental -- some other path happens to rebuild -- not something to rely on.
783 // Geometry values go through imex_cfg_* so the key is built from the same numbers
784 // compute_imex_zone_layout() lays out with; a literal here could key on a value the layout
785 // never used.
786 return active_mode
787 + "|" + std::to_string(imex_cfg_int(printer_cfg, "imex_tools_per_gantry"))
788 + "x" + std::to_string(imex_cfg_int(printer_cfg, "imex_gantry_count"))
789 + "|ly" + std::to_string((int)imex_cfg_enum<ImexToolLayout>(printer_cfg, "imex_tool_layout"))
790 + "|cw" + std::to_string((int)(imex_cfg_float(printer_cfg, "imex_nozzle_clearance_x") * 10))
791 + "|ch" + std::to_string((int)(imex_cfg_float(printer_cfg, "imex_nozzle_clearance_y") * 10))
792 + "|mg" + std::to_string((int)(imex_cfg_float(printer_cfg, "imex_carriage_margin") * 10))
793 + "|t" + active_tools
794 + "|p" + std::to_string(primary_phys)
795 + "|fw" + (imex_cfg_bool(printer_cfg, "imex_firmware_managed_zones") ? "1" : "0");
796}
std::string get_effective_imex_mode() const
Definition PartPlate.cpp:467
bool resolve_active_mode_tools(std::string &out_tools_str, int &out_primary_phys) const
Definition PartPlate.cpp:865
T imex_cfg_enum(const ConfigBase &cfg, const std::string &key)
Definition IMEXHelpers.hpp:386
bool imex_cfg_bool(const ConfigBase &cfg, const std::string &key)
Definition IMEXHelpers.cpp:282
double imex_cfg_float(const ConfigBase &cfg, const std::string &key)
Definition IMEXHelpers.cpp:295
int imex_cfg_int(const ConfigBase &cfg, const std::string &key)
Definition IMEXHelpers.cpp:269

References get_effective_imex_mode(), Slic3r::imex_cfg_bool(), Slic3r::imex_cfg_enum(), Slic3r::imex_cfg_float(), Slic3r::imex_cfg_int(), m_plater, Slic3r::ConfigBase::option(), and resolve_active_mode_tools().

Referenced by build_imex_ghost_cache_key(), and ensure_imex_zones().

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

◆ build_imex_ghost_cache_key()

std::string Slic3r::GUI::PartPlate::build_imex_ghost_cache_key ( ) const
private
842{
843 // Ghost shape depends on: mode topology (same inputs as zone key) + set of
844 // objects on plate + each primary instance's transform. Filament routing and
845 // colors are deliberately NOT keyed: ghost RGB is restamped live every frame
846 // by update_imex_ghost_colors, so color-only changes never need a mesh rebuild.
847 std::string k = build_imex_cache_key();
848 if (k.empty()) return ""; // ghost-off when zones-off
849
850 k += "|obj";
851 for (const auto& oi : obj_to_instance_set)
852 k += std::to_string(oi.first) + "." + std::to_string(oi.second) + ",";
853 return k;
854}
std::string build_imex_cache_key() const
Definition PartPlate.cpp:757

References build_imex_cache_key(), and obj_to_instance_set.

Referenced by ensure_imex_ghosts().

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

◆ calc_bounding_boxes()

void Slic3r::GUI::PartPlate::calc_bounding_boxes ( ) const
private
607 {
608 BoundingBoxf3* bounding_box = const_cast<BoundingBoxf3*>(&m_bounding_box);
609 *bounding_box = BoundingBoxf3();
610 for (const Vec2d& p : m_shape) {
611 bounding_box->merge({ p(0), p(1), 0.0 });
612 }
613
614 BoundingBoxf3* extended_bounding_box = const_cast<BoundingBoxf3*>(&m_extended_bounding_box);
615 *extended_bounding_box = m_bounding_box;
616
617 double half_x = bounding_box->size().x() * GRABBER_X_FACTOR;
618 double half_y = bounding_box->size().y() * 1.0f * GRABBER_Y_FACTOR;
619 double half_z = GRABBER_Z_VALUE;
621 m_grabber_box.min = Vec3d(center.x() - half_x, center.y() - half_y, center.z() - half_z);
622 m_grabber_box.max = Vec3d(center.x() + half_x, center.y() + half_y, center.z() + half_z);
623 m_grabber_box.defined = true;
624 extended_bounding_box->merge(m_grabber_box);
625
626 //calc exclude area bounding box
628 BoundingBoxf3 exclude_bb;
629 for (int index = 0; index < m_exclude_area.size(); index ++) {
630 const Vec2d& p = m_exclude_area[index];
631
632 if (index % 4 == 0)
633 exclude_bb = BoundingBoxf3();
634
635 exclude_bb.merge({ p(0), p(1), 0.0 });
636
637 if (index % 4 == 3)
638 {
639 exclude_bb.max(2) = m_depth;
640 exclude_bb.min(2) = GROUND_Z;
641 m_exclude_bounding_box.emplace_back(exclude_bb);
642 }
643 }
644}
static const float GROUND_Z
Definition 3DBed.cpp:49
static const float GRABBER_Y_FACTOR
Definition PartPlate.cpp:127
static const float GRABBER_Z_VALUE
Definition PartPlate.cpp:128
static const float GRABBER_X_FACTOR
Definition PartPlate.cpp:126
PointType center() const
Definition BoundingBox.cpp:237
PointType size() const
Definition BoundingBox.cpp:187
void merge(const PointType &point)
Definition BoundingBox.cpp:139
BoundingBoxf3 m_grabber_box
Definition PartPlate.hpp:157
BoundingBoxf3 m_bounding_box
Definition PartPlate.hpp:154
Pointfs m_shape
Definition PartPlate.hpp:150
Pointfs m_exclude_area
Definition PartPlate.hpp:151
std::vector< BoundingBoxf3 > m_exclude_bounding_box
Definition PartPlate.hpp:156
BoundingBoxf3 m_extended_bounding_box
Definition PartPlate.hpp:155
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67

References Slic3r::bounding_box(), Slic3r::center(), GRABBER_X_FACTOR, GRABBER_Y_FACTOR, GRABBER_Z_VALUE, GROUND_Z, m_bounding_box, m_depth, m_exclude_area, m_exclude_bounding_box, m_extended_bounding_box, m_grabber_box, m_shape, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBox3Base< PointType >::merge(), and Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min.

Referenced by set_shape().

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

◆ calc_exclude_triangles()

void Slic3r::GUI::PartPlate::calc_exclude_triangles ( const ExPolygon & poly)
private
655{
656 m_exclude_triangles.reset();
657
659 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create exclude triangles\n";
660}
GLModel m_exclude_triangles
Definition PartPlate.hpp:163
bool init_model_from_poly(GLModel &model, const ExPolygon &poly, float z)
Definition 3DBed.cpp:54

References GROUND_Z, Slic3r::GUI::init_model_from_poly(), and m_exclude_triangles.

Referenced by set_shape().

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

◆ calc_gridlines()

void Slic3r::GUI::PartPlate::calc_gridlines ( const ExPolygon & poly,
const BoundingBox & pp_bbox )
private
1631 {
1632 m_gridlines.reset();
1633 m_gridlines_bolder.reset();
1634
1635 // calculate and generate grid
1636 int step = Bed_2D::calculate_grid_step(pp_bbox, scale_(1.00));
1637 Vec2d scaled_origin = Vec2d(scale_(m_origin.x()),scale_(m_origin.y()));
1638 auto grid_lines = Bed_2D::generate_grid(poly, pp_bbox, scaled_origin, scale_(step), SCALED_EPSILON);
1639
1640 Lines lines_thin = to_lines(grid_lines[0]);
1641 Lines lines_bold = to_lines(grid_lines[1]);
1642
1643 // append bed contours
1644 Lines contour_lines = to_lines(poly);
1645 std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(lines_thin));
1646
1648 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n";
1649
1651 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create bed grid lines\n";
1652}
static const float GROUND_Z_GRIDLINE
Definition PartPlate.cpp:125
static int calculate_grid_step(const BoundingBox &bb, const double &scale)
Definition 2DBed.cpp:48
static std::vector< Polylines > generate_grid(const ExPolygon &poly, const BoundingBox &pp_bbox, const Vec2d &origin, const double &step, const double &scale)
Definition 2DBed.cpp:59
GLModel m_gridlines_bolder
Definition PartPlate.hpp:175
GLModel m_gridlines
Definition PartPlate.hpp:174
#define SCALED_EPSILON
Definition libslic3r.h:109
#define scale_(val)
Definition libslic3r.h:106
static bool init_model_from_lines(GLModel &model, const Lines &lines, float z)
Definition PartPlate.cpp:1433
std::vector< Line > Lines
Definition Line.hpp:20
Lines to_lines(const ExPolygon &src)
Definition ExPolygon.hpp:124
void step(Coord &crd, const Dir d, const long n=1)
Definition MarchingSquares.hpp:213

References Slic3r::GUI::Bed_2D::calculate_grid_step(), Slic3r::GUI::Bed_2D::generate_grid(), GROUND_Z_GRIDLINE, Slic3r::GUI::init_model_from_lines(), m_gridlines, m_gridlines_bolder, m_origin, scale_, SCALED_EPSILON, and Slic3r::to_lines().

Referenced by set_shape().

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

◆ calc_height_limit()

void Slic3r::GUI::PartPlate::calc_height_limit ( )
private
1654 {
1655 m_height_limit_common.reset();
1656 m_height_limit_bottom.reset();
1657 m_height_limit_top.reset();
1658
1659 Lines3 bottom_h_lines, top_lines, top_h_lines, common_lines;
1660 int shape_count = m_shape.size();
1661 float first_z = 0.02f;
1662 for (int i = 0; i < shape_count; i++) {
1663 auto &cur_p = m_shape[i];
1664 Vec3crd p1(scale_(cur_p.x()), scale_(cur_p.y()), scale_(first_z));
1665 Vec3crd p2(scale_(cur_p.x()), scale_(cur_p.y()), scale_(m_height_to_rod));
1666 Vec3crd p3(scale_(cur_p.x()), scale_(cur_p.y()), scale_(m_height_to_lid));
1667
1668 common_lines.emplace_back(p1, p2);
1669 top_lines.emplace_back(p2, p3);
1670
1671 Vec2d next_p;
1672 if (i < (shape_count - 1)) {
1673 next_p = m_shape[i+1];
1674
1675 }
1676 else {
1677 next_p = m_shape[0];
1678 }
1679 Vec3crd p4(scale_(cur_p.x()), scale_(cur_p.y()), scale_(m_height_to_rod));
1680 Vec3crd p5(scale_(next_p.x()), scale_(next_p.y()), scale_(m_height_to_rod));
1681 bottom_h_lines.emplace_back(p4, p5);
1682
1683 Vec3crd p6(scale_(cur_p.x()), scale_(cur_p.y()), scale_(m_height_to_lid));
1684 Vec3crd p7(scale_(next_p.x()), scale_(next_p.y()), scale_(m_height_to_lid));
1685 top_h_lines.emplace_back(p6, p7);
1686 }
1687 //std::copy(bottom_lines.begin(), bottom_lines.end(), std::back_inserter(bottom_h_lines));
1688 std::copy(top_lines.begin(), top_lines.end(), std::back_inserter(top_h_lines));
1689
1690 if (!init_model_from_lines(m_height_limit_common, common_lines))
1691 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create height limit bottom lines\n";
1692
1693 if (!init_model_from_lines(m_height_limit_bottom, bottom_h_lines))
1694 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create height limit bottom lines\n";
1695
1696 if (!init_model_from_lines(m_height_limit_top, top_h_lines))
1697 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to create height limit top lines\n";
1698}
GLModel m_height_limit_bottom
Definition PartPlate.hpp:189
float m_height_to_rod
Definition PartPlate.hpp:131
GLModel m_height_limit_common
Definition PartPlate.hpp:188
float m_height_to_lid
Definition PartPlate.hpp:130
GLModel m_height_limit_top
Definition PartPlate.hpp:190
Eigen::Matrix< coord_t, 3, 1, Eigen::DontAlign > Vec3crd
Definition Point.hpp:53
std::vector< Line3 > Lines3
Definition Line.hpp:21

References Slic3r::GUI::init_model_from_lines(), m_height_limit_bottom, m_height_limit_common, m_height_limit_top, m_height_to_lid, m_height_to_rod, m_shape, and scale_.

Referenced by set_shape().

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

◆ calc_imex_ghosts()

void Slic3r::GUI::PartPlate::calc_imex_ghosts ( )
private
894{
895 m_imex_ghost_volumes.clear();
896 if (!m_plater || !m_model) return;
897 if (obj_to_instance_set.empty()) return;
898
899 std::string active_tools_str;
900 int primary_phys = -1;
901 if (!resolve_active_mode_tools(active_tools_str, primary_phys)) return;
902
903 // IMEX firmware-managed zones: the slicer emits a centered single-half slice and the
904 // firmware fans copies/mirrors out from there — placement is not slicer-authoritative.
905 // Rendering secondary-tool ghosts via imex_head_transform (which assumes slicer-managed
906 // placement at primary_zone_center + gantry_offset) would draw them at positions the
907 // firmware doesn't honor (e.g. off-bed once the centered slice is in play). Suppress
908 // ghost generation entirely so we don't lie about something the slicer doesn't own.
909 if (imex_cfg_bool(wxGetApp().preset_bundle->printers.get_edited_preset().config,
910 "imex_firmware_managed_zones"))
911 return;
912
913 // Zone centers are the basis for ghost placement; make sure they exist before
914 // we read them. render_imex_zones already ensures this, but ghost rebuild can
915 // also be driven from mode/preset invalidation paths that don't touch zones.
917
918 const auto heads = parse_imex_active_tools(active_tools_str);
919
920 // When primary's gantry has a Span tool, paired-gantry aggregation means each
921 // non-primary gantry is represented by a single ghost — its column-paired rep —
922 // so non-rep tools on aggregated gantries are skipped. This single source of
923 // pairing truth keeps ghost emission and zone aggregation in lockstep.
924 // Grouping must divide the grid the same way compute_imex_zone_layout() does, so the key is
925 // read through the same accessor rather than against a literal repeated here.
926 const int tpg = std::max(1, imex_cfg_int(
927 wxGetApp().preset_bundle->printers.get_edited_preset().config, "imex_tools_per_gantry"));
928 const ImexGantryGrouping grouping =
929 group_imex_active_tools_by_gantry(active_tools_str, tpg);
930 auto is_aggregated = [&](int phys) -> bool {
931 const int g = phys / tpg;
932 for (const auto& grp : grouping.groups)
933 if (grp.gantry_index == g) return grp.aggregate;
934 return false;
935 };
936 auto skip_for_aggregation = [&](int phys) -> bool {
937 const int g = phys / tpg;
938 for (const auto& grp : grouping.groups) {
939 if (grp.gantry_index != g) continue;
940 return grp.aggregate && phys != grp.representative_phys;
941 }
942 return false;
943 };
944
945 auto mirror_axis_for = [&](int phys) {
946 return imex_mirror_axis_for(primary_phys, phys, tpg);
947 };
948
949 // Zone centers are the source of truth for ghost placement: they come from the
950 // same grid math that paints the colored secondary zones, so a ghost always lands
951 // in its own tool's zone. extruder_offset is physical-nozzle data and is left at
952 // zero on most IMEX presets — sourcing offsets from it stacks every ghost on top
953 // of the primary, which is what motivated this switch.
954 auto center_for = [&](int phys) -> Vec2d {
955 auto it = m_imex_head_zone_centers.find(phys);
956 return (it == m_imex_head_zone_centers.end()) ? Vec2d::Zero() : it->second;
957 };
958 const Vec2d primary_off = center_for(primary_phys);
959
960 // An aggregated gantry's zone is a full-X row strip, so it has no column of its own to
961 // align to. Putting BOTH the primary and target X frames on the bed centerline makes
962 // gantry_offset.x zero, which is what we want: a cross-gantry tool tracks primary's X
963 // (it reflects in Y, not X — see imex_mirror_axis_for) and only translates along Y.
964 // NB: the X frame is NOT a reflection plane. Do not "simplify" the bed_x_center
965 // substitution away on the grounds that the mirror no longer reflects in X — dropping it
966 // reintroduces a nonzero gantry_offset.x and shoves aggregated ghosts a column off their
967 // strip.
968 auto bed_ext = get_extents(m_shape);
969 const double bed_x_center = 0.5 * (bed_ext.min(0) + bed_ext.max(0));
970 auto resolve_centers = [&](int phys) -> std::pair<Vec2d, Vec2d> {
971 const Vec2d target_off = center_for(phys);
972 if (!is_aggregated(phys)) {
973 // Per-tool: target stays at its column-aligned zone center.
974 return {primary_off, target_off - primary_off};
975 }
976 const Vec2d aggregated_primary{bed_x_center, primary_off.y()};
977 const Vec2d aggregated_target {bed_x_center, target_off.y()};
978 return {aggregated_primary, aggregated_target - aggregated_primary};
979 };
980
981 // Mesh is object-local and identical across all instances and heads of a given object.
982 // Build the merged TriangleMesh once per obj_idx and reuse across the inner head loop.
983 // (Per-ghost GLModel::init_from still runs once each, since GLVolume owns its GLModel by value;
984 // sharing a GLModel across GLVolumes would require API changes outside this task's scope.)
985 std::map<int, TriangleMesh> mesh_by_obj;
986 auto get_combined_mesh = [&](int obj_idx, const ModelObject* mo) -> const TriangleMesh& {
987 auto it = mesh_by_obj.find(obj_idx);
988 if (it != mesh_by_obj.end()) return it->second;
989 TriangleMesh combined;
990 for (const ModelVolume* mv : mo->volumes) {
991 if (!mv->is_model_part()) continue;
992 TriangleMesh tm = mv->mesh();
993 tm.transform(mv->get_matrix());
994 combined.merge(tm);
995 }
996 return mesh_by_obj.emplace(obj_idx, std::move(combined)).first->second;
997 };
998
999 for (const auto& oi : obj_to_instance_set) {
1000 const int obj_idx = oi.first;
1001 const int inst_idx = oi.second;
1002 if (obj_idx < 0 || obj_idx >= (int)m_model->objects.size()) continue;
1003 ModelObject* mo = m_model->objects[obj_idx];
1004 if (!mo || inst_idx < 0 || inst_idx >= (int)mo->instances.size()) continue;
1005 ModelInstance* mi = mo->instances[inst_idx];
1006
1007 const Transform3d inst_world = mi->get_matrix();
1008 const TriangleMesh& combined = get_combined_mesh(obj_idx, mo);
1009
1010 for (const auto& [phys, role] : heads) {
1011 if (phys == primary_phys) continue;
1012 if (phys >= IMEX_GHOST_MAX_HEADS) continue;
1013 if (role == ImexRole::Span) continue; // within-gantry partner; primary's zone covers it
1014 if (skip_for_aggregation(phys)) continue; // non-rep on an aggregated gantry
1015
1016 const auto [pri_center, gantry] = resolve_centers(phys);
1017 // A mirror on the primary's own gantry sits beside it in X, so it reflects across
1018 // the vertical boundary between their zones. A mirror on another gantry sits in
1019 // front of / behind it, so it reflects across the horizontal boundary between the
1020 // row strips — the Y axis. Copy translates by `gantry`; aggregated tools resolve
1021 // gantry.x to 0, so a cross-gantry mirror tracks primary's X and reflects only Y.
1022 const Transform3d head_xf = imex_head_transform(
1023 primary_phys, phys, role, gantry, pri_center, mirror_axis_for(phys));
1024 const Transform3d ghost_xf = head_xf * inst_world;
1025
1026 // No color at bake time: update_imex_ghost_colors is the sole author of
1027 // ghost color, restamping RGB + alpha from the live palette every frame.
1028 auto ghost = std::make_unique<GLVolume>();
1029 ghost->set_instance_transformation(ghost_xf);
1030 ghost->force_transparent = 1;
1031 ghost->force_native_color = 1;
1032 ghost->disabled = 1; // skip selection path
1033 // is_active defaults to true in GLVolume's ctor — leave it alone.
1034 ghost->zoom_to_volumes = 0;
1035 // Ghosts live in secondary zones that are by definition outside the primary
1036 // printable area; suppress the red "outside bed" overlay for them.
1037 ghost->shader_outside_printer_detection_enabled = 0;
1038 ghost->picking = 1;
1039 // object_id = sentinel-encoded physical head; volume_id = source obj_idx (for live-drag);
1040 // instance_id = source inst_idx.
1041 ghost->composite_id = GLVolume::CompositeID(
1042 imex_ghost_composite_id_for_head(phys), obj_idx, inst_idx);
1043 ghost->model.init_from(combined);
1044 m_imex_ghost_volumes.push_back(std::move(ghost));
1045 }
1046 }
1047}
static int imex_ghost_composite_id_for_head(int physical_head)
Definition PartPlate.hpp:303
void ensure_imex_zones()
Definition PartPlate.cpp:828
static constexpr int IMEX_GHOST_MAX_HEADS
Definition PartPlate.hpp:294
std::map< int, Vec2d > m_imex_head_zone_centers
Definition PartPlate.hpp:183
std::vector< std::unique_ptr< GLVolume > > m_imex_ghost_volumes
Definition PartPlate.hpp:186
@ Span
Definition IMEXHelpers.hpp:345
Transform3d imex_head_transform(int, int, ImexRole role, const Vec2d &gantry_offset, const Vec2d &primary_zone_center, ImexMirrorAxis mirror_axis)
Definition IMEXHelpers.cpp:584
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
ImexGantryGrouping group_imex_active_tools_by_gantry(const std::string &active_tools_for_mode, int tools_per_gantry)
Definition IMEXHelpers.cpp:365
ImexMirrorAxis imex_mirror_axis_for(int primary_phys, int target_phys, int tools_per_gantry)
Definition IMEXHelpers.cpp:578
std::vector< std::pair< int, ImexRole > > parse_imex_active_tools(const std::string &active_tools_for_mode)
Definition IMEXHelpers.cpp:327

References ensure_imex_zones(), Slic3r::get_extents(), Slic3r::ModelInstance::get_matrix(), Slic3r::ModelVolume::get_matrix(), Slic3r::group_imex_active_tools_by_gantry(), Slic3r::ImexGantryGrouping::groups, Slic3r::imex_cfg_bool(), Slic3r::imex_cfg_int(), imex_ghost_composite_id_for_head(), IMEX_GHOST_MAX_HEADS, Slic3r::imex_head_transform(), Slic3r::imex_mirror_axis_for(), Slic3r::ModelObject::instances, Slic3r::ModelVolume::is_model_part(), m_imex_ghost_volumes, m_imex_head_zone_centers, m_model, m_plater, m_shape, Slic3r::TriangleMesh::merge(), Slic3r::ModelVolume::mesh(), obj_to_instance_set, Slic3r::parse_imex_active_tools(), resolve_active_mode_tools(), Slic3r::Span, and Slic3r::TriangleMesh::transform().

Referenced by ensure_imex_ghosts().

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

◆ calc_imex_zones()

void Slic3r::GUI::PartPlate::calc_imex_zones ( )
private
671{
672 m_imex_copy_zones.clear();
673 m_imex_mirror_zones.clear();
674 // Clear blocking vectors at the top so early returns don't leave stale data.
678 m_imex_margin_overlay.clear();
679 m_imex_primary_zone_box = std::nullopt;
682
683 if (!wxGetApp().preset_bundle)
684 return;
685
686 PresetBundle& bundle = *wxGetApp().preset_bundle;
687 const DynamicPrintConfig& printer_cfg = bundle.printers.get_edited_preset().config;
688
689 // Process-preset mode is the fallback the library applies when the plate is still on
690 // the reserved Primary mode; it ignores this string otherwise.
691 std::string process_mode;
692 if (auto* mode_opt = bundle.prints.get_edited_preset().config.option<ConfigOptionString>("imex_parallel_mode"))
693 process_mode = mode_opt->value;
694
695 const ImexZoneLayout layout = compute_imex_zone_layout(printer_cfg, get_imex_mode(),
696 process_mode, get_extents(m_shape));
697
698 m_imex_primary_head = layout.primary_head;
699 m_imex_head_zone_centers = layout.head_zone_centers;
700 m_imex_primary_zone_box = layout.primary_zone_box;
701 m_imex_secondary_zone_boxes = layout.secondary_zone_boxes;
702 m_imex_collision_zones = layout.collision_zones;
703
704 // No primary zone means the layout is empty (IMEX off, Primary mode, single-tool grid,
705 // or a mode with no tools) -- exactly the cases that returned before touching geometry.
706 if (!m_imex_primary_zone_box.has_value())
707 return;
708
709 ExPolygon bed_poly;
710 generate_print_polygon(bed_poly);
711
712 // Build a clipped filled GLModel for one zone rect and push it into a vector.
713 // A rect falling entirely outside the bed outline contributes no model.
714 auto push_zone_fill = [&](std::vector<GLModel>& vec, double cx0, double cx1, double cy0, double cy1) {
715 ExPolygon cell;
716 cell.contour.append({ scale_(cx0), scale_(cy0) });
717 cell.contour.append({ scale_(cx1), scale_(cy0) });
718 cell.contour.append({ scale_(cx1), scale_(cy1) });
719 cell.contour.append({ scale_(cx0), scale_(cy1) });
720 ExPolygons clipped = intersection_ex({ cell }, { bed_poly });
721 if (!clipped.empty()) {
722 GLModel m;
723 if (init_model_from_poly(m, clipped.front(), GROUND_Z))
724 vec.push_back(std::move(m));
725 }
726 };
727
728 for (const BoundingBoxf& b : layout.copy_zones)
729 push_zone_fill(m_imex_copy_zones, b.min.x(), b.max.x(), b.min.y(), b.max.y());
730 for (const BoundingBoxf& b : layout.mirror_zones)
731 push_zone_fill(m_imex_mirror_zones, b.min.x(), b.max.x(), b.min.y(), b.max.y());
732 // Red-orange fill for each carriage danger strip, and the amber advisory band just
733 // inside it. Both are visual only -- blocking is driven by m_imex_collision_zones.
734 for (const BoundingBoxf3& b : layout.collision_zones)
735 push_zone_fill(m_imex_collision_overlay, b.min.x(), b.max.x(), b.min.y(), b.max.y());
736 for (const BoundingBoxf& b : layout.margin_bands)
737 push_zone_fill(m_imex_margin_overlay, b.min.x(), b.max.x(), b.min.y(), b.max.y());
738}
std::vector< BoundingBoxf3 > m_imex_collision_zones
Definition PartPlate.hpp:179
std::optional< BoundingBoxf > m_imex_primary_zone_box
Definition PartPlate.hpp:182
std::vector< GLModel > m_imex_copy_zones
Definition PartPlate.hpp:176
std::string get_imex_mode() const
Definition PartPlate.cpp:457
std::vector< GLModel > m_imex_collision_overlay
Definition PartPlate.hpp:180
std::vector< GLModel > m_imex_margin_overlay
Definition PartPlate.hpp:181
int m_imex_primary_head
Definition PartPlate.hpp:184
std::vector< GLModel > m_imex_mirror_zones
Definition PartPlate.hpp:177
std::vector< BoundingBoxf3 > m_imex_secondary_zone_boxes
Definition PartPlate.hpp:178
void generate_print_polygon(ExPolygon &print_polygon)
Definition PartPlate.cpp:5037
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
Slic3r::ExPolygons intersection_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:878
zaa_minimize_perimeter_height ConfigOptionString
Definition PrintConfig.hpp:1702
ImexZoneLayout compute_imex_zone_layout(const DynamicPrintConfig &printer_cfg, const std::string &plate_mode, const std::string &process_mode, const BoundingBoxf &bed_extents)
Definition IMEXZones.cpp:17

References Slic3r::MultiPoint::append(), Slic3r::ImexZoneLayout::collision_zones, Slic3r::compute_imex_zone_layout(), Slic3r::Preset::config, Slic3r::ExPolygon::contour, Slic3r::ImexZoneLayout::copy_zones, generate_print_polygon(), Slic3r::PresetCollection::get_edited_preset(), Slic3r::get_extents(), get_imex_mode(), GROUND_Z, Slic3r::ImexZoneLayout::head_zone_centers, Slic3r::GUI::init_model_from_poly(), Slic3r::intersection_ex(), m_imex_collision_overlay, m_imex_collision_zones, m_imex_copy_zones, m_imex_head_zone_centers, m_imex_margin_overlay, m_imex_mirror_zones, m_imex_primary_head, m_imex_primary_zone_box, m_imex_secondary_zone_boxes, m_shape, Slic3r::ImexZoneLayout::margin_bands, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::ImexZoneLayout::mirror_zones, Slic3r::ConfigBase::option(), Slic3r::ImexZoneLayout::primary_head, Slic3r::ImexZoneLayout::primary_zone_box, Slic3r::PresetBundle::printers, Slic3r::PresetBundle::prints, scale_, and Slic3r::ImexZoneLayout::secondary_zone_boxes.

Referenced by ensure_imex_zones(), and set_shape().

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

◆ calc_triangles()

void Slic3r::GUI::PartPlate::calc_triangles ( const ExPolygon & poly)
private
647{
648 m_triangles.reset();
649
650 if (!init_model_from_poly(m_triangles.model, poly, GROUND_Z))
651 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n";
652}
PickingModel m_triangles
Definition PartPlate.hpp:162

References GROUND_Z, Slic3r::GUI::init_model_from_poly(), and m_triangles.

Referenced by set_shape().

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

◆ calc_triangles_from_polygon()

void Slic3r::GUI::PartPlate::calc_triangles_from_polygon ( const ExPolygon & poly,
GLModel & render_model )
private
1422 {
1423 if (poly.empty()) {
1424 render_model.reset();
1425 return;
1426 }
1427 render_model.reset();
1428 if (!init_model_from_poly(render_model, poly, GROUND_Z)) {
1429 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "calc_triangles_from_polygon fail";
1430 }
1431}
void poly(std::vector< std::pair< Vec2d, Vec2d > > &out, std::initializer_list< Vec2d > p)
Definition DesignSketchTool.cpp:7751

References GROUND_Z, Slic3r::GUI::init_model_from_poly(), and Slic3r::GUI::GLModel::reset().

Referenced by render().

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

◆ calc_vertex_for_icons()

void Slic3r::GUI::PartPlate::calc_vertex_for_icons ( int index,
PickingModel & model )
private
1776{
1777 model.reset();
1778
1779 ExPolygon poly;
1780 auto bed_ext = get_extents(m_shape);
1781 Vec2d p = bed_ext[2];
1782 float factor = icon_scale_factor();
1783 float size = PARTPLATE_ICON_SIZE * factor;
1784 float gap_left = PARTPLATE_ICON_GAP_LEFT * factor;
1785 float gap_y = PARTPLATE_ICON_GAP_Y * factor;
1786 float gap_top = PARTPLATE_ICON_GAP_TOP * factor;
1787 p += Vec2d(gap_left,-1 * (index * (size + gap_y) + gap_top));
1788
1789 if (m_plater && m_plater->get_build_volume_type() == BuildVolume_Type::Circle)
1790 p[1] -= std::max(0.0, (bed_ext.size()(1) - (size + gap_y) * 6 /* bed_icon_count */) / 2);
1791
1792 poly.contour.append({ scale_(p(0)) , scale_(p(1) - size) });
1793 poly.contour.append({ scale_(p(0) + size), scale_(p(1) - size) });
1794 poly.contour.append({ scale_(p(0) + size), scale_(p(1)) });
1795 poly.contour.append({ scale_(p(0)) , scale_(p(1)) });
1796
1797 if (!init_model_from_poly(model.model, poly, GROUND_Z))
1798 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n";
1799
1801}
static const int PARTPLATE_ICON_GAP_LEFT
Definition PartPlate.cpp:135
static const int PARTPLATE_ICON_GAP_Y
Definition PartPlate.cpp:136
static const int PARTPLATE_ICON_GAP_TOP
Definition PartPlate.cpp:134
static const int PARTPLATE_ICON_SIZE
Definition PartPlate.cpp:132
float icon_scale_factor() const
Definition PartPlate.cpp:1703
static void init_raycaster_from_model(PickingModel &model)
Definition PartPlate.cpp:1611
@ Circle
Definition BuildVolume.hpp:25

References Slic3r::Circle, Slic3r::get_extents(), GROUND_Z, icon_scale_factor(), Slic3r::GUI::init_model_from_poly(), Slic3r::GUI::init_raycaster_from_model(), m_plater, m_shape, Slic3r::GUI::PickingModel::model, PARTPLATE_ICON_GAP_LEFT, PARTPLATE_ICON_GAP_TOP, PARTPLATE_ICON_GAP_Y, PARTPLATE_ICON_SIZE, Slic3r::GUI::PickingModel::reset(), and scale_.

Referenced by refresh_imex_icon(), and set_shape().

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

◆ calc_vertex_for_imex_warn_badge()

void Slic3r::GUI::PartPlate::calc_vertex_for_imex_warn_badge ( int imex_icon_index,
GLModel & model )
private
1806{
1807 model.reset();
1808
1809 auto bed_ext = get_extents(m_shape);
1810 Vec2d p = bed_ext[2];
1811 auto factor = bed_ext.size()(1) / 200.0;
1812 float size = PARTPLATE_ICON_SIZE * factor;
1813 float gap_left = PARTPLATE_ICON_GAP_LEFT * factor;
1814 float gap_y = PARTPLATE_ICON_GAP_Y * factor;
1815 float gap_top = PARTPLATE_ICON_GAP_TOP * factor;
1816
1817 // Centre of the IMEX mode icon (top-left corner = p after offset)
1818 p += Vec2d(gap_left, -1 * (imex_icon_index * (size + gap_y) + gap_top));
1819
1820 // Badge is half the icon size, anchored to the bottom-right corner of the icon slot
1821 float badge = size * 0.55f;
1822 Vec2d bp(p(0) + size - badge, p(1) - size);
1823
1824 ExPolygon poly;
1825 poly.contour.append({ scale_(bp(0)) , scale_(bp(1)) });
1826 poly.contour.append({ scale_(bp(0) + badge), scale_(bp(1)) });
1827 poly.contour.append({ scale_(bp(0) + badge), scale_(bp(1) + badge)});
1828 poly.contour.append({ scale_(bp(0)) , scale_(bp(1) + badge)});
1829
1830 if (!init_model_from_poly(model, poly, GROUND_Z + 0.01f))
1831 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry for IMEX warn badge\n";
1832}

References Slic3r::get_extents(), GROUND_Z, Slic3r::GUI::init_model_from_poly(), m_shape, PARTPLATE_ICON_GAP_LEFT, PARTPLATE_ICON_GAP_TOP, PARTPLATE_ICON_GAP_Y, PARTPLATE_ICON_SIZE, Slic3r::GUI::GLModel::reset(), and scale_.

Referenced by refresh_imex_icon(), and set_shape().

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

◆ calc_vertex_for_number()

void Slic3r::GUI::PartPlate::calc_vertex_for_number ( int index,
bool one_number,
GLModel & buffer )
private
1712{
1713 buffer.reset();
1714
1715 ExPolygon poly;
1716#if 0 //in the up area
1717 Vec2d& p = m_shape[2];
1718 float offset_x = one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2;
1719
1720 poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP) - PARTPLATE_ICON_GAP - PARTPLATE_ICON_SIZE + PARTPLATE_TEXT_OFFSET_Y) });
1721 poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_ICON_SIZE + PARTPLATE_TEXT_OFFSET_Y) });
1722 poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + PARTPLATE_ICON_SIZE - offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y)});
1723 poly.contour.append({ scale_(p(0) + PARTPLATE_ICON_GAP + offset_x), scale_(p(1) - index * (PARTPLATE_ICON_SIZE + PARTPLATE_ICON_GAP)- PARTPLATE_ICON_GAP - PARTPLATE_TEXT_OFFSET_Y) });
1724#else //in the bottom
1725 auto bed_ext = get_extents(m_shape);
1726 Vec2d p = bed_ext[1];
1727 float factor = icon_scale_factor();
1728 float size = PARTPLATE_ICON_SIZE * factor;
1729 float offset_y = PARTPLATE_TEXT_OFFSET_Y * factor;
1730 float offset_x = (one_number?PARTPLATE_TEXT_OFFSET_X1: PARTPLATE_TEXT_OFFSET_X2) * factor;
1731 float gap_left = PARTPLATE_ICON_GAP_LEFT * factor;
1732 p += Vec2d(gap_left,0);
1733
1734 poly.contour.append({ scale_(p(0) + offset_x) , scale_(p(1) + offset_y) });
1735 poly.contour.append({ scale_(p(0) + size - offset_x), scale_(p(1) + offset_y) });
1736 poly.contour.append({ scale_(p(0) + size - offset_x), scale_(p(1) + size - offset_y) });
1737 poly.contour.append({ scale_(p(0) + offset_x) , scale_(p(1) + size - offset_y) });
1738#endif
1739 if (!init_model_from_poly(buffer, poly, GROUND_Z))
1740 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n";
1741}
static const int PARTPLATE_TEXT_OFFSET_X1
Definition PartPlate.cpp:137
static const int PARTPLATE_TEXT_OFFSET_Y
Definition PartPlate.cpp:139
static const int PARTPLATE_TEXT_OFFSET_X2
Definition PartPlate.cpp:138

References Slic3r::get_extents(), GROUND_Z, icon_scale_factor(), Slic3r::GUI::init_model_from_poly(), m_shape, PARTPLATE_ICON_GAP_LEFT, PARTPLATE_ICON_SIZE, PARTPLATE_TEXT_OFFSET_X1, PARTPLATE_TEXT_OFFSET_X2, PARTPLATE_TEXT_OFFSET_Y, Slic3r::GUI::GLModel::reset(), and scale_.

Referenced by set_shape().

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

◆ calc_vertex_for_plate_name_edit_icon()

void Slic3r::GUI::PartPlate::calc_vertex_for_plate_name_edit_icon ( GLTexture * texture,
int index,
PickingModel & model )
private
1743 {
1744 model.reset();
1745
1746 ExPolygon poly;
1747 auto bed_ext = get_extents(m_shape);
1748 Vec2d p = bed_ext[3];
1749 float factor = icon_scale_factor();
1750 float icon_sz = factor * PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE;
1751 float width = icon_sz;
1752 float height = icon_sz;
1753 float offset_y = factor * PARTPLATE_TEXT_OFFSET_Y;
1754
1755 float name_width = 0.0;
1756 if (texture && texture->get_width() > 0 && texture->get_height())
1757 // original width give correct ratio in here since rendering width can be much higher because of next_highest_power_of_2 for rendering
1758 name_width = icon_sz * texture->m_original_width / texture->get_height();
1759
1760 //if (m_plater && m_plater->get_build_volume_type() == BuildVolume_Type::Circle)
1761 // px = scale_(bed_ext.center()(0)) + m_name_texture_width * 0.50 - height * 0.50;
1762 p += Vec2d(name_width, offset_y);
1763
1764 poly.contour.append({ scale_(p(0) ), scale_(p(1) ) });
1765 poly.contour.append({ scale_(p(0) + width), scale_(p(1) ) });
1766 poly.contour.append({ scale_(p(0) + width), scale_(p(1) + height) });
1767 poly.contour.append({ scale_(p(0) ), scale_(p(1) + height) });
1768
1769 if (!init_model_from_poly(model.model, poly, GROUND_Z))
1770 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n";
1771
1773}
static const int PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE
Definition PartPlate.cpp:133
coord_t width(const BoundingBox &box)
Definition Arrange.cpp:1184
coord_t height(const BoundingBox &box)
Definition Arrange.cpp:1185

References Slic3r::get_extents(), Slic3r::GUI::GLTexture::get_height(), Slic3r::GUI::GLTexture::get_width(), GROUND_Z, icon_scale_factor(), Slic3r::GUI::init_model_from_poly(), Slic3r::GUI::init_raycaster_from_model(), Slic3r::GUI::GLTexture::m_original_width, m_shape, Slic3r::GUI::PickingModel::model, PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE, PARTPLATE_TEXT_OFFSET_Y, Slic3r::GUI::PickingModel::reset(), and scale_.

Referenced by generate_plate_name_texture().

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

◆ can_slice()

bool Slic3r::GUI::PartPlate::can_slice ( ) const
inline
619 {
621 }
bool m_apply_invalid
Definition PartPlate.hpp:136

References m_apply_invalid, and m_ready_for_slice.

Referenced by Slic3r::GUI::GLCanvas3D::_render_imgui_select_plate_toolbar(), Slic3r::GUI::MainFrame::get_enable_slice_status(), and Slic3r::GUI::Plater::priv::update_background_process().

Here is the caller graph for this function:

◆ check_compatible_of_nozzle_and_filament()

bool Slic3r::GUI::PartPlate::check_compatible_of_nozzle_and_filament ( const DynamicPrintConfig & config,
const std::vector< std::string > & filament_presets,
std::string & error_msg )
3864{
3865 float nozzle_diameter = config.option<ConfigOptionFloats>("nozzle_diameter")->values[0];
3866 auto volume_type_opt = config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type");
3867
3868 auto get_filament_alias = [](std::string preset_name) -> std::string {
3869 size_t at_pos = preset_name.find('@');
3870 std::string alias = preset_name.substr(0, at_pos);
3871 size_t first = alias.find_first_not_of(' ');
3872 if (first == std::string::npos) return "";
3873 size_t last = alias.find_last_not_of(' ');
3874 return alias.substr(first, last - first + 1);
3875 };
3876
3877 bool with_same_volume_type = std::all_of(volume_type_opt->values.begin(), volume_type_opt->values.end(),
3878 [first_value = volume_type_opt->values[0]](int value) { return value == first_value; });
3879
3880 std::set<std::string> selected_filament_alias;
3881 for (auto &filament_preset : filament_presets) { selected_filament_alias.insert(get_filament_alias(filament_preset)); }
3882
3883 auto get_incompatible_selected = [&](const NozzleVolumeType volume_type) -> std::set<std::string> {
3884 std::vector<std::string> incompatible_filaments = Print::get_incompatible_filaments_by_nozzle(nozzle_diameter, volume_type);
3885 std::set<std::string> ret;
3886 for (auto &filament : selected_filament_alias) {
3887 if (std::find(incompatible_filaments.begin(), incompatible_filaments.end(), filament) != incompatible_filaments.end()) ret.insert(filament);
3888 }
3889 return ret;
3890 };
3891
3892 auto get_nozzle_msg = [](const float nozzle_diameter, const NozzleVolumeType volume_type) -> std::string {
3893 std::ostringstream oss;
3894 oss << std::fixed << std::setprecision(1) << nozzle_diameter;
3895 // TRN %1% is the nozzle diameter, %2% the nozzle volume type, for example "Standard" or "High Flow".
3896 return Slic3r::format(_u8L("%1%mm %2% nozzle"), oss.str(), _u8L(get_nozzle_volume_type_string(volume_type)));
3897 };
3898
3899 auto get_incompatible_filament_msg = [](const std::set<std::string> &incompatible_selected_filaments) -> std::string {
3900 std::string filament_str;
3901 size_t idx = 0;
3902 for (const auto &filament : incompatible_selected_filaments) {
3903 if (idx > 0) filament_str += ',';
3904 filament_str += filament;
3905 ++idx;
3906 }
3907 return filament_str;
3908 };
3909
3910 error_msg.clear();
3911
3912 std::set<int> nozzle_volumes(volume_type_opt->values.begin(), volume_type_opt->values.end());
3913 std::map<NozzleVolumeType, std::set<std::string>> incompatible_selected_map;
3914
3915 for (auto volume_type_value : nozzle_volumes) {
3916 NozzleVolumeType volume_type = static_cast<NozzleVolumeType>(volume_type_value);
3917 auto incompatible_selected = get_incompatible_selected(volume_type);
3918 if (!incompatible_selected.empty()) incompatible_selected_map[volume_type] = incompatible_selected;
3919 }
3920
3921 if (incompatible_selected_map.empty()) return true;
3922
3923 if (incompatible_selected_map.size() == 1) {
3924 auto elem = incompatible_selected_map.begin();
3925 NozzleVolumeType volume_type = elem->first;
3926 auto incompatible_selected = elem->second;
3927 error_msg = GUI::format(_L_PLURAL("It is not recommended to print the following filament with %1%: %2%\n",
3928 "It is not recommended to print the following filaments with %1%: %2%\n", incompatible_selected.size()),
3929 get_nozzle_msg(nozzle_diameter, volume_type),
3930 get_incompatible_filament_msg(incompatible_selected));
3931 } else {
3932 std::string warning_msg = _u8L("It is not recommended to use the following nozzle and filament combinations:\n");
3933 for (auto &elem : incompatible_selected_map) {
3934 NozzleVolumeType volume_type = elem.first;
3935 auto incompatible_selected = elem.second;
3936 warning_msg += GUI::format(_L("%1% with %2%\n"),get_nozzle_msg(nozzle_diameter, volume_type), get_incompatible_filament_msg(incompatible_selected));
3937 }
3938 error_msg = warning_msg;
3939 }
3940 return false;
3941}
#define _L(s)
Definition OBJ.cpp:34
DynamicPrintConfig * config()
Definition PartPlate.hpp:337
static std::vector< std::string > get_incompatible_filaments_by_nozzle(const float nozzle_diameter, const std::optional< NozzleVolumeType > nozzle_volume_type=std::nullopt)
Definition Print.cpp:4603
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
zaa_minimize_perimeter_height nozzle_diameter((ConfigOptionBool, reduce_infill_retraction))((ConfigOptionBool
NozzleVolumeType
Definition PrintConfig.hpp:618
ConfigOptionEnumsGenericTempl< false > ConfigOptionEnumsGeneric
Definition Config.hpp:2311
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:45
std::string get_nozzle_volume_type_string(NozzleVolumeType nozzle_volume_type)
Definition PrintConfig.cpp:860
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:1015
#define _u8L(s)
Definition I18N.hpp:11
#define _L_PLURAL(s, plural, n)
Definition I18N.hpp:96

References _L, _L_PLURAL, _u8L, config(), Slic3r::format(), Slic3r::GUI::format(), Slic3r::Print::get_incompatible_filaments_by_nozzle(), Slic3r::get_nozzle_volume_type_string(), Slic3r::nozzle_diameter(), and Slic3r::ConfigOptionVector< double >::values.

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene().

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

◆ check_filament_printable()

bool Slic3r::GUI::PartPlate::check_filament_printable ( const DynamicPrintConfig & config,
wxString & error_message )
3676{
3677 error_message.clear();
3679 // only check printablity if we have explicit map result
3680 if (mode != fmmManual)
3681 return true;
3682
3683 std::vector<int> used_filaments = get_extruders(true); // 1 base
3684 if (!used_filaments.empty()) {
3685 const std::vector<std::string>& filament_types = config.option<ConfigOptionStrings>("filament_type")->values;
3686 const std::vector<int>& filament_printables = config.option<ConfigOptionInts>("filament_printable")->values;
3687 const std::vector<int>& filament_map = get_real_filament_maps(config);
3688 // This runs synchronously mid printer-switch (load_current_preset -> reload_scene), before the
3689 // filament-count reconciliation clears stale per-object assignments, so the plate objects can
3690 // still reference filament indices beyond the freshly selected printer config. Skip those to
3691 // avoid an out-of-range access. Matches BambuStudio's guards in the same function.
3692 const int filament_count = std::min({(int) filament_types.size(), (int) filament_printables.size(), (int) filament_map.size()});
3693 for (auto filament_idx : used_filaments) {
3694 int filament_id = filament_idx - 1;
3695 if (filament_id < 0 || filament_id >= filament_count)
3696 continue;
3697 std::string filament_type = filament_types[filament_id];
3698 int filament_printable_status = filament_printables[filament_id];
3699 int extruder_idx = filament_map[filament_id] - 1;
3700 if (!(filament_printable_status >> extruder_idx & 1)) {
3701 error_message = wxString::Format(extruder_idx == 0 ? _L("The left nozzle cannot print %s.") : _L("The right nozzle cannot print %s."),
3703 return false;
3704 }
3705 }
3706 }
3707 return true;
3708}
FilamentMapMode get_real_filament_map_mode(const DynamicConfig &g_config, bool *use_global_param=nullptr) const
Definition PartPlate.cpp:408
std::vector< int > get_real_filament_maps(const DynamicConfig &g_config, bool *use_global_param=nullptr) const
Definition PartPlate.cpp:384
std::vector< int > get_extruders(bool conside_custom_gcode=false, bool expand_mixed_slots=true) const
Definition PartPlate.cpp:3063
static const std::vector< std::string > filament_types
Definition CreatePresetsDialog.cpp:123
zaa_minimize_perimeter_height filament_type((ConfigOptionBools, filament_soluble))((ConfigOptionStrings
zaa_minimize_perimeter_height filament_map((ConfigOptionInts, filament_volume_map))((ConfigOptionInts
ConfigOptionIntsTempl< false > ConfigOptionInts
Definition Config.hpp:1154
FilamentMapMode
Definition PrintConfig.hpp:632
@ fmmManual
Definition PrintConfig.hpp:635

References _L, config(), Slic3r::filament_map(), Slic3r::filament_type(), Slic3r::GUI::filament_types, Slic3r::fmmManual, get_extruders(), get_real_filament_map_mode(), and get_real_filament_maps().

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene(), and Slic3r::GUI::Plater::validate_current_plate().

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

◆ check_mixture_filament_compatible()

bool Slic3r::GUI::PartPlate::check_mixture_filament_compatible ( const DynamicPrintConfig & config,
std::string & error_msg )
3821{
3822 static std::unordered_map<std::string, std::unordered_set<std::string>> incompatible_filament_pairs;
3823
3824 auto add_incompatibility = [&](std::string filament_type1, std::string filament_type2) {
3825 incompatible_filament_pairs[filament_type1].insert(filament_type2);
3826 incompatible_filament_pairs[filament_type2].insert(filament_type1);
3827 };
3828
3829 if (incompatible_filament_pairs.empty()) { add_incompatibility("PVA", "PETG"); }
3830
3831 std::vector<int> used_filaments = get_extruders(true); // 1 based idx
3832 std::vector<std::string> filament_types;
3833 auto filament_type_opt = config.option<ConfigOptionStrings>("filament_type");
3834 for (auto filament : used_filaments) {
3835 int filament_idx = filament - 1;
3836 if (filament_idx >= filament_type_opt->values.size()) filament_idx = 0;
3837 filament_types.push_back(filament_type_opt->values[filament_idx]);
3838 };
3839
3840 {
3841 std::unordered_set<std::string> seen;
3842 filament_types.erase(std::remove_if(filament_types.begin(), filament_types.end(), [&](const std::string &s) { return !seen.insert(s).second; }), filament_types.end());
3843 }
3844
3845 std::vector<std::pair<std::string, std::string>> conflicts;
3846
3847 for (size_t i = 0; i < filament_types.size(); i++) {
3848 auto it = incompatible_filament_pairs.find(filament_types[i]);
3849 if (it == incompatible_filament_pairs.end()) continue;
3850 for (size_t j = i + 1; j < filament_types.size(); ++j) {
3851 if (it->second.count(filament_types[j])) { conflicts.emplace_back(filament_types[i], filament_types[j]); }
3852 }
3853 }
3854
3855 if (!conflicts.empty()) {
3856 // TODO: add the full text if has multi conflict
3857 auto conflict = conflicts.front();
3858 error_msg = GUI::format(_L("Mixing %1% with %2% in printing is not recommended.\n"), conflict.first, conflict.second);
3859 }
3860 return conflicts.empty();
3861}

References _L, config(), Slic3r::GUI::filament_types, Slic3r::GUI::format(), and get_extruders().

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene().

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

◆ check_mixture_of_pla_and_petg()

bool Slic3r::GUI::PartPlate::check_mixture_of_pla_and_petg ( const DynamicPrintConfig & config)
3761{
3762 bool has_pla = false;
3763 bool has_petg = false;
3764
3765 // On a toolchanger (machine_tool_change_time > 0) each filament slot maps to a
3766 // separate physical nozzle: only one nozzle is ever mounted or heated at a time, so
3767 // there is no cross-nozzle contamination between PLA and PETG. Track which physical
3768 // nozzle each material is on; warn only when PLA and PETG would pass through the
3769 // *same* nozzle.
3770 //
3771 // NOTE: if MMU-on-toolchanger support is added (#10586), the nozzle-mapping logic
3772 // will need to be revisited because multiple filaments may then share one tool slot.
3773 bool is_toolchanger = false;
3774 auto *tool_change_time = config.option<ConfigOptionFloat>("machine_tool_change_time");
3775 if (tool_change_time && tool_change_time->value > 0)
3776 is_toolchanger = true;
3777
3778 // nozzle index → whether it carries PLA / PETG
3779 std::map<int, bool> nozzle_has_pla;
3780 std::map<int, bool> nozzle_has_petg;
3781
3782 std::vector<int> used_filaments = get_extruders(true); // 1-based
3783 if (!used_filaments.empty()) {
3784 const auto *filament_types = config.option<ConfigOptionStrings>("filament_type");
3785 for (auto filament_idx : used_filaments) {
3786 int filament_id = filament_idx - 1;
3787 if (filament_id < (int)filament_types->values.size()) {
3788 const std::string &filament_type = filament_types->values[filament_id];
3789 if (filament_type == "PLA") {
3790 has_pla = true;
3791 nozzle_has_pla[filament_id] = true;
3792 }
3793 if (filament_type == "PETG") {
3794 has_petg = true;
3795 nozzle_has_petg[filament_id] = true;
3796 }
3797 } else {
3798 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " check error:array bound";
3799 }
3800 }
3801 }
3802
3803 if (!has_pla || !has_petg)
3804 return true; // no mixture — no warning
3805
3806 if (is_toolchanger) {
3807 // Warn only if any single nozzle slot carries both PLA and PETG (e.g. future MMU
3808 // on toolchanger). On a pure toolchanger each slot is independent, so this loop
3809 // will never fire and the warning is correctly suppressed. (#12073)
3810 for (const auto &kv : nozzle_has_pla) {
3811 if (nozzle_has_petg.count(kv.first))
3812 return false; // same nozzle → warn
3813 }
3814 return true; // different nozzles → safe, no warning
3815 }
3816
3817 return false; // non-toolchanger with both PLA and PETG → warn
3818}
zaa_minimize_perimeter_height ConfigOptionFloat
Definition PrintConfig.hpp:1954

References config(), Slic3r::filament_type(), Slic3r::GUI::filament_types, and get_extruders().

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene().

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

◆ check_objects_empty_and_gcode3mf()

bool Slic3r::GUI::PartPlate::check_objects_empty_and_gcode3mf ( std::vector< int > & result) const
3431{
3432 if (m_model->objects.empty()) {//objects is empty
3433 if (wxGetApp().plater()->is_gcode_3mf()) { // if gcode.3mf file
3434 for (int i = 0; i < slice_filaments_info.size(); i++) {
3435 result.push_back(slice_filaments_info[i].id + 1);
3436 }
3437 }
3438 return true;
3439 }
3440 return false;
3441}
std::vector< FilamentInfo > slice_filaments_info
Definition PartPlate.hpp:141
static Plater * plater()
Definition GUI_Factories.cpp:400

References m_model, Slic3r::GUI::plater(), and slice_filaments_info.

Referenced by get_extruders(), get_extruders_without_support(), and get_used_filaments().

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

◆ check_outside()

bool Slic3r::GUI::PartPlate::check_outside ( int obj_id,
int instance_id,
BoundingBoxf3 * bounding_box = nullptr )
4498{
4499 // Ensure IDEX/IQEX zone geometry is current before any placement check.
4501
4502 bool outside = true;
4503
4504 ModelObject* object = m_model->objects[obj_id];
4505 ModelInstance* instance = object->instances[instance_id];
4506
4507 BoundingBoxf3 instance_box = bounding_box? *bounding_box: object->instance_convex_hull_bounding_box(instance_id);
4508 // Reuse the hull across exclusion and IMEX checks, but do not build it for
4509 // instances rejected by the plate bounds or printers with no relevant zones.
4510 std::optional<Polygon> instance_hull;
4511 const auto get_instance_hull = [&]() -> const Polygon & {
4512 if (!instance_hull)
4513 instance_hull = instance->convex_hull_2d();
4514 return *instance_hull;
4515 };
4516 BoundingBoxf3 plate_box = get_plate_box();
4517 this->open_belt_y(plate_box);
4518 if (instance_box.max.z() > plate_box.min.z())
4519 plate_box.min.z() += instance_box.min.z(); // not considering outsize if sinking
4520
4521 if (instance_box.min.z() < SINKING_Z_THRESHOLD) {
4522 // Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered
4523 // m_height mirrors the printer's printable height and is set in CLI mode too, unlike m_plater.
4524 if (plate_box.intersects(instance_box)) {
4525 // TODO: FIXME: this does not take exclusion area into account
4526 const BuildVolume build_volume(get_shape(), m_height, m_extruder_areas, m_extruder_heights);
4527 const auto state = instance->calc_print_volume_state(build_volume);
4529 }
4530 }
4531 else
4532 if (plate_box.contains(instance_box))
4533 {
4534 outside = false;
4535 const DynamicPrintConfig *config = m_plater != nullptr ? m_plater->config() : nullptr;
4536 bool checked_config_regions = false;
4537 if (config != nullptr) {
4538 const std::vector<std::vector<BedExcludeRegion>> regions_by_extruder =
4541 // The legacy outside flag has no filament/nozzle context. Always
4542 // check the shared legacy area here, but let the newer per-extruder
4543 // pipeline handle nozzle-specific collision volumes.
4544 const Point plate_offset(scale_(m_origin.x()), scale_(m_origin.y()));
4545 const Polygon &hull = get_instance_hull();
4546
4547 const size_t groups_to_check = regions_by_extruder.empty() ? 0 : 1;
4548 for (size_t group_id = 0; group_id < groups_to_check; ++group_id) {
4549 const std::vector<BedExcludeRegion> &extruder_regions = regions_by_extruder[group_id];
4550 for (const BedExcludeRegion &region_src : extruder_regions) {
4551 if (mode != BedExcludeVolumeMode::Shared && region_src.is_collision_volume())
4552 continue;
4553 checked_config_regions = true;
4554 Polygon region = region_src.polygon;
4555 region.translate(plate_offset);
4556 region.make_counter_clockwise();
4557
4558 if (intersection(Polygons{ region }, Polygons{ hull }).empty())
4559 continue;
4560
4561 if (instance_box.max.z() < region_src.z_min || instance_box.min.z() > region_src.z_max)
4562 continue;
4563
4564 BedExcludeRegion translated_region = region_src;
4565 translated_region.polygon = std::move(region);
4566 if (instance->intersects_bed_exclude_region(translated_region)) {
4567 outside = true;
4568 break;
4569 }
4570 }
4571 if (outside)
4572 break;
4573 }
4574 }
4575
4576 if (!checked_config_regions && m_exclude_bounding_box.size() > 0) {
4577 const Polygon &hull = get_instance_hull();
4578 for (const BoundingBoxf3 &exclude_box : m_exclude_bounding_box) {
4579 Polygon p = exclude_box.polygon(true); // instance convex hull is scaled, so we need to scale here
4580 if (!intersection({ p }, { hull }).empty()) {
4581 outside = true;
4582 break;
4583 }
4584 }
4585 }
4586 }
4587
4588 // IDEX/IQEX placement check (prepare-mode bounding-box test).
4589 // Block objects that overlap secondary (copy/mirror) zones or the carriage
4590 // danger strip at the primary zone boundary. Reuses the existing
4591 // outside=true → instance_outside_set → update_states() → blocks slicing path.
4592 if (!outside && (!m_imex_secondary_zone_boxes.empty() || !m_imex_collision_zones.empty()) &&
4593 imex_hull_violates(get_instance_hull()))
4594 outside = true;
4595
4596 return outside;
4597}
std::vector< Pointfs > m_extruder_areas
Definition PartPlate.hpp:152
std::vector< double > m_extruder_heights
Definition PartPlate.hpp:153
const Pointfs & get_shape() const
Definition PartPlate.hpp:577
bool imex_hull_violates(const Polygon &hull) const
Definition PartPlate.cpp:1174
BoundingBoxf3 get_plate_box()
Definition PartPlate.hpp:597
void open_belt_y(BoundingBoxf3 &box) const
Definition PartPlate.hpp:588
void translate(double x, double y)
Definition MultiPoint.hpp:38
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
uint32_t group_id(std::vector< Bridge > &bridges, uint32_t src_id)
Definition LayerRegion.cpp:214
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:769
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
std::vector< std::vector< BedExcludeRegion > > get_bed_excluded_regions_by_extruder(const DynamicPrintConfig &cfg)
Definition PrintConfig.cpp:14211
BedExcludeVolumeMode active_bed_exclude_volume_mode(const DynamicPrintConfig &cfg)
Definition PrintConfig.cpp:14364
@ ModelInstancePVS_Partly_Outside
Definition Model.hpp:1413
static const float SINKING_Z_THRESHOLD
Definition Model.hpp:1967
BedExcludeVolumeMode
Definition PrintConfig.hpp:642
@ Shared
Definition PrintConfig.hpp:643
Slic3r::Polygon Polygon
Definition Emboss.cpp:101

References Slic3r::active_bed_exclude_volume_mode(), Slic3r::bounding_box(), Slic3r::ModelInstance::calc_print_volume_state(), config(), Slic3r::BoundingBox3Base< PointType >::contains(), Slic3r::ModelInstance::convex_hull_2d(), ensure_imex_zones(), Slic3r::get_bed_excluded_regions_by_extruder(), get_plate_box(), get_shape(), Slic3r::group_id(), imex_hull_violates(), Slic3r::intersection(), Slic3r::BoundingBox3Base< PointType >::intersects(), Slic3r::ModelInstance::intersects_bed_exclude_region(), m_exclude_bounding_box, m_extruder_areas, m_extruder_heights, m_height, m_imex_collision_zones, m_imex_secondary_zone_boxes, m_model, m_origin, m_plater, Slic3r::Polygon::make_counter_clockwise(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::ModelInstancePVS_Partly_Outside, open_belt_y(), Slic3r::BedExcludeRegion::polygon, scale_, Slic3r::Shared, Slic3r::SINKING_Z_THRESHOLD, and Slic3r::MultiPoint::translate().

Referenced by add_instance(), and update_instance_exclude_status().

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

◆ check_single_extruder_mixed_filament_risk()

bool Slic3r::GUI::PartPlate::check_single_extruder_mixed_filament_risk ( const DynamicPrintConfig & config,
std::string & warning_text ) const
3720{
3721 warning_text.clear();
3722
3723 auto *nozzle_diameter_opt = config.option<ConfigOptionFloatsNullable>("nozzle_diameter");
3724 if (!nozzle_diameter_opt || nozzle_diameter_opt->values.size() > 1)
3725 return false;
3726
3727 auto *is_mixed_opt = wxGetApp().preset_bundle->project_config.option<ConfigOptionBools>("filament_is_mixed");
3728 if (!is_mixed_opt || !has_any_mixed_filament(is_mixed_opt->values))
3729 return false;
3730
3731 auto is_mixed_slot = [&](int extruder_1based) {
3732 size_t idx = (size_t)(extruder_1based - 1);
3733 return idx < is_mixed_opt->values.size() && is_mixed_opt->values[idx];
3734 };
3735
3736 const std::string mixed_warn_msg = _u8L("Printing mixed-color filament on a single-extruder printer requires frequent filament changes and flushing, "
3737 "which may significantly increase waste and the risk of nozzle / waste-chute clogging.");
3738
3739 for (int obj_idx = 0; obj_idx < (int)m_model->objects.size(); ++obj_idx) {
3740 if (!contain_any_instance_totally(obj_idx))
3741 continue;
3742 ModelObject *mo = m_model->objects[obj_idx];
3743 int obj_ext = mo->config.has("extruder") ? mo->config.extruder() : 1;
3744 if (is_mixed_slot(obj_ext)) {
3745 warning_text = mixed_warn_msg;
3746 return true;
3747 }
3748 for (ModelVolume *mv : mo->volumes) {
3749 int vol_ext = mv->config.has("extruder") ? mv->config.extruder() : obj_ext;
3750 if (is_mixed_slot(vol_ext)) {
3751 warning_text = mixed_warn_msg;
3752 return true;
3753 }
3754 }
3755 }
3756
3757 return false;
3758}
bool contain_any_instance_totally(int obj_id) const
Definition PartPlate.cpp:4483
static const std::string warning_text
Definition GLGizmoMeshBoolean.cpp:44
bool has_any_mixed_filament(const std::vector< unsigned char > &is_mixed)
Definition FilamentMixer.cpp:486
ConfigOptionFloatsTempl< true > ConfigOptionFloatsNullable
Definition Config.hpp:1016
ConfigOptionBoolsTempl< false > ConfigOptionBools
Definition Config.hpp:2066

References _u8L, config(), Slic3r::ModelObject::config, Slic3r::ModelVolume::config, contain_any_instance_totally(), Slic3r::ModelConfig::extruder(), Slic3r::ModelConfig::has(), Slic3r::has_any_mixed_filament(), m_model, Slic3r::ModelObject::volumes, and Slic3r::GUI::warning_text.

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene().

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

◆ check_tpu_printable_status()

bool Slic3r::GUI::PartPlate::check_tpu_printable_status ( const DynamicPrintConfig & config,
const std::vector< int > & tpu_filaments )
3711{
3712 // do not limit the num of tpu filament in slicing
3713 return true;
3714}

References config().

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::CLI::run(), and Slic3r::GUI::Plater::validate_current_plate().

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

◆ clear()

void Slic3r::GUI::PartPlate::clear ( bool clear_sliced_result = true)
4174{
4175 obj_to_instance_set.clear();
4176 instance_outside_set.clear();
4178 if (clear_sliced_result) {
4179 m_ready_for_slice = true;
4181 }
4183 return;
4184}
void invalidate_plate_name_texture()
Definition PartPlate.cpp:4327
void update_slice_result_valid_state(bool valid=false)
Definition PartPlate.cpp:5423

References instance_outside_set, invalidate_exclusion_volume_preview(), invalidate_plate_name_texture(), m_ready_for_slice, obj_to_instance_set, and update_slice_result_valid_state().

Referenced by ~PartPlate(), Slic3r::GUI::PartPlateList::clear(), estimate_wipe_tower_polygon(), and set_pos_and_size().

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

◆ clear_exclusion_volume_intersections()

void Slic3r::GUI::PartPlate::clear_exclusion_volume_intersections ( )
2423{
2426}
bool m_exclusion_volume_intersections_cleared
Definition PartPlate.hpp:172
GLModel m_exclusion_volume_intersection_triangles
Definition PartPlate.hpp:169

References m_exclusion_volume_intersection_triangles, and m_exclusion_volume_intersections_cleared.

◆ clear_filament_map()

void Slic3r::GUI::PartPlate::clear_filament_map ( )
5807{
5808 if (m_config.has("filament_map"))
5809 m_config.erase("filament_map");
5811}
DynamicPrintConfig m_config
Definition PartPlate.hpp:211

References invalidate_exclusion_volume_preview(), and m_config.

Referenced by on_extruder_count_changed(), and set_filament_map_mode().

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

◆ clear_filament_map_mode()

void Slic3r::GUI::PartPlate::clear_filament_map_mode ( )
5848{
5849 if (m_config.has("filament_map_mode"))
5850 m_config.erase("filament_map_mode");
5851}

References m_config.

Referenced by set_filament_map_mode().

Here is the caller graph for this function:

◆ clear_filament_volume_map()

void Slic3r::GUI::PartPlate::clear_filament_volume_map ( )
5828{
5829 if (m_config.has("filament_volume_map"))
5830 m_config.erase("filament_volume_map");
5831}

References m_config.

◆ config()

◆ contain_any_instance_totally()

bool Slic3r::GUI::PartPlate::contain_any_instance_totally ( int obj_id) const
4484{
4485 if (obj_id < 0 || obj_id >= int(m_model->objects.size()))
4486 return false;
4487
4488 const ModelObject *object = m_model->objects[obj_id];
4489 for (int instance_id = 0; instance_id < int(object->instances.size()); ++instance_id)
4490 if (contain_instance_totally(obj_id, instance_id))
4491 return true;
4492
4493 return false;
4494}
bool contain_instance_totally(ModelObject *object, int instance_id) const
Definition PartPlate.cpp:4446

References contain_instance_totally(), Slic3r::ModelObject::instances, and m_model.

Referenced by check_single_extruder_mixed_filament_risk(), estimate_wipe_tower_footprint(), get_extruders(), and get_extruders_without_support().

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

◆ contain_instance()

bool Slic3r::GUI::PartPlate::contain_instance ( int obj_id,
int instance_id )
4433{
4434 bool result = false;
4435 std::set<std::pair<int, int>>::iterator it;
4436
4437 it = obj_to_instance_set.find(std::pair(obj_id, instance_id));
4438 if (it != obj_to_instance_set.end()) {
4439 result = true;
4440 }
4441
4442 return result;
4443}

References obj_to_instance_set.

Referenced by Slic3r::GUI::PartPlateList::construct_objects_list_for_new_plate(), Slic3r::GUI::PartPlateList::find_instance(), get_instance(), Slic3r::GUI::Selection::get_volume_idxs_from_plate(), Slic3r::GUI::Plater::priv::on_select_preset(), Slic3r::GUI::ArrangeJob::prepare_partplate(), Slic3r::GUI::OrientJob::prepare_partplate(), Slic3r::GUI::GLCanvas3D::Labels::render(), and Slic3r::CLI::run().

Here is the caller graph for this function:

◆ contain_instance_totally() [1/2]

bool Slic3r::GUI::PartPlate::contain_instance_totally ( int obj_id,
int instance_id ) const
4468{
4469 bool result = false;
4470 std::set<std::pair<int, int>>::iterator it;
4471
4472 it = obj_to_instance_set.find(std::pair(obj_id, instance_id));
4473 if (it != obj_to_instance_set.end()) {
4474 it = instance_outside_set.find(std::pair(obj_id, instance_id));
4475 if (it == instance_outside_set.end())
4476 result = true;
4477 }
4478
4479 return result;
4480}

References instance_outside_set, and obj_to_instance_set.

◆ contain_instance_totally() [2/2]

bool Slic3r::GUI::PartPlate::contain_instance_totally ( ModelObject * object,
int instance_id ) const
4447{
4448 bool result = false;
4449 int obj_id = -1;
4450
4451 for (int index = 0; index < m_model->objects.size(); index ++)
4452 {
4453 if (m_model->objects[index] == object)
4454 {
4455 obj_id = index;
4456 break;
4457 }
4458 }
4459
4460 if ((obj_id >= 0 ) && (obj_id < m_model->objects.size()))
4461 result = contain_instance_totally(obj_id, instance_id);
4462
4463 return result;
4464}

References contain_instance_totally(), and m_model.

Referenced by Slic3r::GUI::ObjectDataViewModel::AddPlate(), contain_any_instance_totally(), contain_instance_totally(), Slic3r::GUI::ensure_belt_purge_tower(), estimate_wipe_tower_footprint(), Slic3r::GUI::PartPlateList::find_instance_belongs(), Slic3r::GUI::Sidebar::has_broken_mixed_filament(), and Slic3r::GUI::Plater::priv::replace_all_with_stl().

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

◆ contains() [1/3]

bool Slic3r::GUI::PartPlate::contains ( const BoundingBoxf3 & bb) const
5286{
5287 // Allow the objects to protrude below the print bed
5288 BoundingBoxf3 print_volume(Vec3d(m_bounding_box.min(0), m_bounding_box.min(1), 0.0), Vec3d(m_bounding_box.max(0), m_bounding_box.max(1), 1e3));
5289 print_volume.min(2) = -1e10;
5290 print_volume.min(0) -= Slic3r::BuildVolume::BedEpsilon;
5291 print_volume.min(1) -= Slic3r::BuildVolume::BedEpsilon;
5292 print_volume.max(0) += Slic3r::BuildVolume::BedEpsilon;
5293 print_volume.max(1) += Slic3r::BuildVolume::BedEpsilon;
5294 this->open_belt_y(print_volume);
5295 return print_volume.contains(bb);
5296}
static constexpr const double BedEpsilon
Definition BuildVolume.hpp:121

References Slic3r::BuildVolume::BedEpsilon, Slic3r::BoundingBox3Base< PointType >::contains(), m_bounding_box, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, and open_belt_y().

Here is the call graph for this function:

◆ contains() [2/3]

bool Slic3r::GUI::PartPlate::contains ( const GLVolume & v) const
5281{
5282 return m_bounding_box.contains(v.bounding_box());
5283}

References Slic3r::GLVolume::bounding_box(), and m_bounding_box.

Here is the call graph for this function:

◆ contains() [3/3]

bool Slic3r::GUI::PartPlate::contains ( const Vec3d & point) const
5276{
5277 return m_bounding_box.contains(point);
5278}

References m_bounding_box.

◆ copy_id()

void Slic3r::ObjectBase::copy_id ( const ObjectBase & rhs)
inlineprotectedinherited
92{ m_id = rhs.id(); }
ObjectID m_id
Definition ObjectID.hpp:98

References ObjectBase(), id(), and m_id.

Referenced by Slic3r::CutObjectBase::copy().

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

◆ duplicate_all_instance()

void Slic3r::GUI::PartPlate::duplicate_all_instance ( unsigned int dup_count,
bool need_skip,
std::map< int, bool > & skip_objects )
4767{
4768 std::set<std::pair<int, int>> old_obj_list = obj_to_instance_set;
4769 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plate_id %1%, dup_count %2%") % m_plate_index % dup_count;
4770 for (std::set<std::pair<int, int>>::iterator it = old_obj_list.begin(); it != old_obj_list.end(); ++it)
4771 {
4772 int obj_id = it->first;
4773 int instance_id = it->second;
4774
4775 if (valid_instance(obj_id, instance_id))
4776 {
4777 ModelObject* object = m_model->objects[obj_id];
4778 ModelInstance* instance = object->instances[instance_id];
4779
4780 if (need_skip)
4781 {
4782 if (skip_objects.find(instance->loaded_id) != skip_objects.end())
4783 {
4784 instance->printable = false;
4785 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": skipped object, loaded_id %1%, name %2%, set to unprintable, no need to duplicate") % instance->loaded_id % object->name;
4786 continue;
4787 }
4788 }
4789 for (size_t index = 0; index < dup_count; index ++)
4790 {
4791 ModelObject* newObj = m_model->add_object(*object);
4792 newObj->name = object->name +"_"+ std::to_string(index+1);
4793 int new_obj_id = m_model->objects.size() - 1;
4794 for ( size_t new_instance_id = 0; new_instance_id < newObj->instances.size(); new_instance_id++ )
4795 {
4796 obj_to_instance_set.emplace(std::pair(new_obj_id, new_instance_id));
4798 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": duplicate object into plate: index_pair [%1%,%2%], obj_id %3%") % new_obj_id % new_instance_id % newObj->id().id;
4799 }
4800 }
4801 }
4802 }
4803
4804 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
4805 {
4806 int obj_id = it->first;
4807 int instance_id = it->second;
4808
4809 if (valid_instance(obj_id, instance_id))
4810 {
4811 ModelObject* object = m_model->objects[obj_id];
4812 ModelInstance* instance = object->instances[instance_id];
4813
4814 if (instance->printable)
4815 {
4816 instance->loaded_id = instance->id().id;
4817 if (need_skip) {
4818 while (skip_objects.find(instance->loaded_id) != skip_objects.end())
4819 {
4820 instance->loaded_id ++;
4821 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": duplicated id %1% with skip, try new one %2%") %instance->id().id % instance->loaded_id;
4822 }
4823 }
4824 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": set obj %1% instance %2%'s loaded_id to its id %3%, name %4%") % obj_id %instance_id %instance->loaded_id % object->name;
4825 }
4826 }
4827 }
4828
4829 return;
4830}

References Slic3r::ObjectBase::id(), Slic3r::ObjectID::id, Slic3r::ModelObject::instances, invalidate_exclusion_volume_preview(), Slic3r::ModelInstance::loaded_id, m_model, m_plate_index, Slic3r::ModelObject::name, obj_to_instance_set, Slic3r::ModelInstance::printable, and valid_instance().

Referenced by Slic3r::CLI::run().

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

◆ empty()

bool Slic3r::GUI::PartPlate::empty ( )
inline
565{ return obj_to_instance_set.empty(); }

References obj_to_instance_set.

Referenced by Slic3r::GUI::GLCanvas3D::_render_imgui_select_plate_toolbar(), Slic3r::GUI::GLCanvas3D::_render_plate_switcher(), is_valid_gcode_file(), Slic3r::GUI::ArrangeJob::prepare_partplate(), Slic3r::GUI::OrientJob::prepare_partplate(), and update_exclusion_volume_preview_models().

Here is the caller graph for this function:

◆ ensure_imex_ghosts()

void Slic3r::GUI::PartPlate::ensure_imex_ghosts ( )
private
857{
858 std::string key = build_imex_ghost_cache_key();
859 if (key != m_imex_ghost_cache_key) {
862 }
863}
std::string build_imex_ghost_cache_key() const
Definition PartPlate.cpp:841
void calc_imex_ghosts()
Definition PartPlate.cpp:893
std::string m_imex_ghost_cache_key
Definition PartPlate.hpp:187

References build_imex_ghost_cache_key(), calc_imex_ghosts(), and m_imex_ghost_cache_key.

Referenced by render_imex_zones().

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

◆ ensure_imex_zones()

void Slic3r::GUI::PartPlate::ensure_imex_zones ( )
private
829{
830 // CLI / headless slice: no GUI_App, no plater, no IMEX state to track. Bail out
831 // before touching `wxGetApp()` (which segfaults without a GUI_App) — placement
832 // checks reach this from the headless 3MF-load path through `check_outside`.
833 if (!m_plater) return;
834 std::string cache_key = build_imex_cache_key();
835 if (cache_key != m_imex_zones_mode_cache) {
836 m_imex_zones_mode_cache = cache_key;
838 }
839}
std::string m_imex_zones_mode_cache
Definition PartPlate.hpp:185
void calc_imex_zones()
Definition PartPlate.cpp:670

References build_imex_cache_key(), calc_imex_zones(), m_imex_zones_mode_cache, and m_plater.

Referenced by calc_imex_ghosts(), check_outside(), imex_placement_violation(), imex_primary_zone(), render_imex_zones(), and update_imex_ghost_transforms().

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

◆ estimate_wipe_tower_footprint()

WipeTowerFootprint Slic3r::GUI::PartPlate::estimate_wipe_tower_footprint ( const DynamicPrintConfig & config,
int plate_extruder_size = 0,
bool use_global_objects = false ) const
3983{
3984 // The CLI calls this too, so the plate's filaments are derived from the passed config:
3985 // get_extruders(bool) reads the same keys off wxGetApp()'s presets, which the CLI has none of.
3986 // An explicit count is a floor: init-time and arrange estimates size an empty plate for that
3987 // many generic filaments, the lowest ids not already on the plate.
3988 std::vector<int> plate_extruders = get_extruders(true, config, config);
3989 for (int id = 1; int(plate_extruders.size()) < plate_extruder_size; ++id)
3990 if (std::find(plate_extruders.begin(), plate_extruders.end(), id) == plate_extruders.end())
3991 plate_extruders.push_back(id);
3992 // The wipe tower filament joins the tool ordering even when unused (Print::extruders), so
3993 // validation counts it - but only where there is a tower to join, which is the
3994 // has_wipe_tower() half of that guard.
3995 const ConfigOption *wipe_tower_filament_opt = config.option("wipe_tower_filament");
3996 const ConfigOption *enable_prime_tower_opt = config.option("enable_prime_tower");
3997 const int wipe_tower_filament = wipe_tower_filament_opt != nullptr ? wipe_tower_filament_opt->getInt() : 0;
3998 if (enable_prime_tower_opt != nullptr && enable_prime_tower_opt->getBool() && plate_extruders.size() > 1 && wipe_tower_filament > 0 &&
3999 std::find(plate_extruders.begin(), plate_extruders.end(), wipe_tower_filament) == plate_extruders.end())
4000 plate_extruders.push_back(wipe_tower_filament);
4001 if (plate_extruders.empty())
4002 return WipeTowerFootprint();
4003
4004 // Tallest object on this plate and the thinnest layer it is sliced at, resolved per object
4005 // as PrintObject resolves them (override, else preset) and over this plate's objects only -
4006 // seeding from the global value, or folding in an off-plate override, diverges from Print.
4007 const ConfigOption *layer_height_opt = config.option("layer_height");
4008 const double global_layer_height = layer_height_opt != nullptr ? layer_height_opt->getFloat() : 0.08;
4009 double max_height = 0.;
4010 double layer_height = std::numeric_limits<double>::max();
4011 for (int obj_idx = 0; obj_idx < int(m_model->objects.size()); ++obj_idx) {
4012 const ModelObject *object = m_model->objects[obj_idx];
4013 if (!use_global_objects && !contain_any_instance_totally(obj_idx))
4014 continue;
4015 // Per instance, to match PrintObject::size(); the union over instances differs once
4016 // they are rotated apart. The cached convex hull has the mesh's z extent and is cheap
4017 // enough for every scene reload.
4018 for (int inst_idx = 0; inst_idx < int(object->instances.size()); ++inst_idx) {
4019 if (!use_global_objects && !contain_instance_totally(obj_idx, inst_idx))
4020 continue;
4021 max_height = std::max(max_height, object->instance_convex_hull_bounding_box(inst_idx, true).size().z());
4022 }
4023 const ConfigOption *object_layer_height = object->config.option("layer_height");
4024 layer_height = std::min(layer_height, object_layer_height != nullptr ? object_layer_height->getFloat() : global_layer_height);
4025 }
4026 if (layer_height == std::numeric_limits<double>::max())
4027 layer_height = global_layer_height;
4028
4029 std::vector<unsigned int> filament_ids;
4030 for (int id : plate_extruders)
4031 if (id > 0)
4032 filament_ids.push_back(static_cast<unsigned int>(id - 1));
4034}
ObjectID id() const
Definition ObjectID.hpp:69
static std::string layer_height
Definition Tab.cpp:4294
WipeTowerFootprint estimate_wipe_tower_footprint(const ConfigBase &config, WipeTowerType tower_type, const std::vector< unsigned int > &filament_slots, double layer_height, double max_object_height)
Definition WipeTowerEstimate.cpp:86
zaa_minimize_perimeter_height filament_ids((ConfigOptionStrings, filament_colour))((ConfigOptionStrings
WipeTowerType resolve_wipe_tower_type(const ConfigBase &config)
Definition WipeTowerEstimate.cpp:62

References config(), contain_any_instance_totally(), contain_instance_totally(), Slic3r::estimate_wipe_tower_footprint(), Slic3r::filament_ids(), get_extruders(), Slic3r::ConfigOption::getBool(), Slic3r::ConfigOption::getFloat(), Slic3r::ConfigOption::getInt(), Slic3r::ObjectBase::id(), Slic3r::ModelObject::instance_convex_hull_bounding_box(), Slic3r::ModelObject::instances, Slic3r::GUI::layer_height, m_model, Slic3r::resolve_wipe_tower_type(), and Slic3r::BoundingBox3Base< PointType >::size().

Referenced by estimate_wipe_tower_polygon(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::CLI::run(), and Slic3r::GUI::PartPlateList::set_default_wipe_tower_pos_for_plate().

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

◆ estimate_wipe_tower_polygon()

arrangement::ArrangePolygon Slic3r::GUI::PartPlate::estimate_wipe_tower_polygon ( const DynamicPrintConfig & config,
int plate_index,
Vec3d & wt_pos,
Vec3d & wt_size,
int plate_extruder_size = 0,
bool use_global_objects = false,
WipeTowerRelocation * relocation = nullptr ) const
4067{
4068 float x = dynamic_cast<const ConfigOptionFloats*>(config.option("wipe_tower_x"))->get_at(plate_index);
4069 float y = dynamic_cast<const ConfigOptionFloats*>(config.option("wipe_tower_y"))->get_at(plate_index);
4070 //float a = dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value;
4071 const WipeTowerFootprint footprint = estimate_wipe_tower_footprint(config, plate_extruder_size, use_global_objects);
4072 wt_size = Vec3d(footprint.width, footprint.depth, footprint.height);
4073 int plate_width=m_width, plate_depth=m_depth;
4074 float w = wt_size(0); // effective width; differs from prime_tower_width when the rib wall squares the tower
4075 float depth = wt_size(1);
4076 // Resolved brim, not the raw option: "Auto" (-1) would yield a margin of 0 and let the
4077 // clamp put the brim off the bed. Matches set_default_wipe_tower_pos_for_plate.
4078 float wp_brim_width = float(footprint.brim_width);
4079 // A Type2 stabilization cone bulges past the body box like a brim does - fold its worst-axis
4080 // bulge into the same margin.
4081 const BoundingBox outline = get_extents(estimate_wipe_tower_first_layer_outline(config, resolve_wipe_tower_type(config), w, depth, wt_size.z()));
4082 wp_brim_width += float(std::max({0., unscaled(outline.max.x()) - w, unscaled(outline.max.y()) - depth, -unscaled(outline.min.x()), -unscaled(outline.min.y())}));
4083 // A position valid by WIPE_TOWER_MARGIN is the user's choice and stays untouched; an
4084 // invalid one is re-placed with the comfort margin (falling back to the validity bounds
4085 // on cramped plates). std::clamp is UB if lo > hi, so keep every hi >= lo.
4086 const float margin = WIPE_TOWER_MARGIN + wp_brim_width;
4087 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange wipe_tower: wp_brim_width %1%") % wp_brim_width;
4088 const float x_hi = std::max(margin, (float) plate_width - w - margin);
4089 const float y_hi = std::max(margin, (float) plate_depth - depth - margin);
4090 const float margin_c = (float) WIPE_TOWER_AUTO_MARGIN + wp_brim_width;
4091 float x_lo_c = margin_c, x_hi_c = (float) plate_width - w - margin_c;
4092 if (x_lo_c > x_hi_c) { x_lo_c = margin; x_hi_c = x_hi; }
4093 float y_lo_c = margin_c, y_hi_c = (float) plate_depth - depth - margin_c;
4094 if (y_lo_c > y_hi_c) { y_lo_c = margin; y_hi_c = y_hi; }
4095 // Drag clamps reach this limit through the volume's bounding box (post-slice: the real
4096 // mesh, a couple of mm inside this reserved estimate), so a drop can land slightly out
4097 // of bounds — snap it onto the bound; only far-out positions get the comfort re-place.
4098 const float tol = 5.f;
4099 const float saved_x = x, saved_y = y;
4100 const bool replace_x = x < margin - tol || x > x_hi + tol;
4101 const bool replace_y = y < margin - tol || y > y_hi + tol;
4102 x = replace_x ? std::clamp(x, x_lo_c, x_hi_c) : std::clamp(x, margin, x_hi);
4103 y = replace_y ? std::clamp(y, y_lo_c, y_hi_c) : std::clamp(y, margin, y_hi);
4104 if (relocation != nullptr && (replace_x || replace_y)) {
4105 relocation->moved = true;
4106 // The footprint keeps clear of every object and its brim, and turns about its anchor
4107 // as the tower does.
4108 Polygon tower({ {scaled(-wp_brim_width), scaled(-wp_brim_width)},
4109 {scaled(w + wp_brim_width), scaled(-wp_brim_width)},
4110 {scaled(w + wp_brim_width), scaled(depth + wp_brim_width)},
4111 {scaled(-wp_brim_width), scaled(depth + wp_brim_width)} });
4112 if (const auto *rotation = config.option<ConfigOptionFloat>("wipe_tower_rotation_angle"); rotation != nullptr && rotation->value != 0.)
4113 tower.rotate(Geometry::deg2rad(rotation->value));
4114 const Polygons objects = wipe_tower_obstacles(config);
4115 const Point placed(scaled(x), scaled(y));
4116 // The re-placed spot stands when it is clear. Otherwise take the clear spot nearest the
4117 // saved position, keeping the comfort margin where the plate leaves room for it.
4118 if (!nearest_clear_wipe_tower_anchor(BoundingBox(placed, placed), tower, objects, placed)) {
4119 const Point saved(scaled(saved_x), scaled(saved_y));
4120 std::optional<Point> clear = nearest_clear_wipe_tower_anchor(
4121 BoundingBox(Point(scaled(x_lo_c), scaled(y_lo_c)), Point(scaled(x_hi_c), scaled(y_hi_c))), tower, objects, saved);
4122 if (!clear)
4123 clear = nearest_clear_wipe_tower_anchor(BoundingBox(Point(scaled(margin), scaled(margin)), Point(scaled(x_hi), scaled(y_hi))),
4124 tower, objects, saved);
4125 if (clear) {
4126 x = static_cast<float>(unscaled(clear->x()));
4127 y = static_cast<float>(unscaled(clear->y()));
4128 } else {
4129 relocation->overlaps_objects = true;
4130 }
4131 }
4132 }
4133 wt_pos(0) = x;
4134 wt_pos(1) = y;
4135 wt_pos(2) = 0.f;
4136
4137 arrangement::ArrangePolygon wipe_tower_ap;
4138 Polygon ap({
4139 {scaled(x - wp_brim_width), scaled(y - wp_brim_width)},
4140 {scaled(x + w + wp_brim_width), scaled(y - wp_brim_width)},
4141 {scaled(x + w + wp_brim_width), scaled(y + depth + wp_brim_width)},
4142 {scaled(x - wp_brim_width), scaled(y + depth + wp_brim_width)}
4143 });
4144 wipe_tower_ap.bed_idx = plate_index;
4145 wipe_tower_ap.setter = NULL; // do not move wipe tower
4146
4147 wipe_tower_ap.poly.contour = std::move(ap);
4148 wipe_tower_ap.translation = { scaled(0.f), scaled(0.f) };
4149 //wipe_tower_ap.rotation = a;
4150 wipe_tower_ap.name = "WipeTower";
4151 wipe_tower_ap.is_virt_object = true;
4152 wipe_tower_ap.is_wipe_tower = true;
4153
4154 return wipe_tower_ap;
4155}
const double & get_at(size_t i) const
Definition Config.hpp:676
WipeTowerFootprint estimate_wipe_tower_footprint(const DynamicPrintConfig &config, int plate_extruder_size=0, bool use_global_objects=false) const
Definition PartPlate.cpp:3982
Polygons wipe_tower_obstacles(const DynamicPrintConfig &config) const
Definition PartPlate.cpp:4036
void rotate(double angle)
Definition MultiPoint.hpp:40
static constexpr double WIPE_TOWER_MARGIN
Definition libslic3r.h:100
static constexpr double WIPE_TOWER_AUTO_MARGIN
Definition libslic3r.h:103
T clamp(T a, T lower, T upper)
Definition Bicubic.hpp:186
constexpr T deg2rad(const T angle)
Definition Geometry.hpp:312
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81
std::optional< Point > nearest_clear_wipe_tower_anchor(const BoundingBox &anchor_bounds, const Polygon &footprint, const Polygons &obstacles, const Point &target)
Definition WipeTowerEstimate.cpp:247
Polygon estimate_wipe_tower_first_layer_outline(const ConfigBase &config, WipeTowerType tower_type, double width, double depth, double height)
Definition WipeTowerEstimate.cpp:75

References Slic3r::arrangement::ArrangePolygon::bed_idx, Slic3r::WipeTowerFootprint::brim_width, clear(), config(), Slic3r::ExPolygon::contour, Slic3r::Geometry::deg2rad(), Slic3r::WipeTowerFootprint::depth, Slic3r::estimate_wipe_tower_first_layer_outline(), estimate_wipe_tower_footprint(), Slic3r::get_extents(), Slic3r::WipeTowerFootprint::height, Slic3r::arrangement::ArrangePolygon::is_virt_object, Slic3r::arrangement::ArrangePolygon::is_wipe_tower, m_depth, m_width, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::GUI::WipeTowerRelocation::moved, Slic3r::arrangement::ArrangePolygon::name, Slic3r::nearest_clear_wipe_tower_anchor(), Slic3r::GUI::WipeTowerRelocation::overlaps_objects, Slic3r::arrangement::ArrangePolygon::poly, Slic3r::resolve_wipe_tower_type(), Slic3r::MultiPoint::rotate(), Slic3r::scaled(), Slic3r::arrangement::ArrangePolygon::setter, Slic3r::arrangement::ArrangePolygon::translation, Slic3r::unscaled(), Slic3r::ConfigOptionSingle< T >::value, Slic3r::WipeTowerFootprint::width, WIPE_TOWER_AUTO_MARGIN, WIPE_TOWER_MARGIN, and wipe_tower_obstacles().

Referenced by Slic3r::GUI::estimate_wipe_tower_info(), imex_wipe_tower_hull(), Slic3r::GUI::GLCanvas3D::reload_scene(), and Slic3r::CLI::run().

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

◆ exclusion_volume_preview_cache_key()

std::string Slic3r::GUI::PartPlate::exclusion_volume_preview_cache_key ( const std::vector< BedExcludeRegion > & regions) const
private
2071{
2072 std::ostringstream key;
2073 key << std::setprecision(17);
2074 key << "plate:" << m_origin.x() << ',' << m_origin.y() << ',' << m_height << ';';
2075
2076 key << "regions:" << regions.size() << ';';
2077 for (const BedExcludeRegion &region : regions) {
2078 key << region.z_min << ".." << region.z_max << ':'
2079 << int(region.purpose) << ':' << region.has_z_range << ':'
2080 << region.polygon.points.size();
2081 for (const Point &point : region.polygon.points)
2082 key << ',' << point.x() << 'x' << point.y();
2083 key << ';';
2084 }
2085
2086 key << "instances:" << obj_to_instance_set.size() << ';';
2087 if (m_model != nullptr) {
2088 for (const std::pair<int, int> &object_instance : obj_to_instance_set) {
2089 const int obj_id = object_instance.first;
2090 const int instance_id = object_instance.second;
2091 key << obj_id << ':' << instance_id << ':';
2092 if (obj_id < 0 || obj_id >= int(m_model->objects.size())) {
2093 key << "invalid;";
2094 continue;
2095 }
2096
2097 const ModelObject *object = m_model->objects[obj_id];
2098 if (instance_id < 0 || instance_id >= int(object->instances.size())) {
2099 key << "invalid;";
2100 continue;
2101 }
2102
2103 const ModelInstance *instance = object->instances[instance_id];
2104 key << static_cast<const void*>(object) << ':' << static_cast<const void*>(instance) << ':'
2105 << object->volumes.size() << ':' << instance->printable << ':';
2106
2107 const Transform3d instance_matrix = instance->get_matrix();
2108 for (int r = 0; r < int(instance_matrix.matrix().rows()); ++r)
2109 for (int c = 0; c < int(instance_matrix.matrix().cols()); ++c)
2110 key << instance_matrix.matrix()(r, c) << ',';
2111
2112 for (const ModelVolume *volume : object->volumes) {
2113 key << static_cast<const void*>(volume) << ':';
2114 for (const int filament_id : volume->get_extruders())
2115 key << 'f' << filament_id << ',';
2116 const Transform3d volume_matrix = volume->get_matrix();
2117 for (int r = 0; r < int(volume_matrix.matrix().rows()); ++r)
2118 for (int c = 0; c < int(volume_matrix.matrix().cols()); ++c)
2119 key << volume_matrix.matrix()(r, c) << ',';
2120 }
2121 key << ';';
2122 }
2123 }
2124
2125 return key.str();
2126}

References Slic3r::ModelVolume::get_extruders(), Slic3r::ModelInstance::get_matrix(), Slic3r::ModelVolume::get_matrix(), Slic3r::ModelObject::instances, m_height, m_model, m_origin, obj_to_instance_set, Slic3r::ModelInstance::printable, and Slic3r::ModelObject::volumes.

Referenced by update_exclusion_volume_preview_models().

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

◆ fff_print()

Print * Slic3r::GUI::PartPlate::fff_print ( )
inline
696{ return m_print; }
Print * m_print
Definition PartPlate.hpp:139

References m_print.

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene(), and Slic3r::GUI::SelectMachineDialog::start_timelapse_storage_check().

Here is the caller graph for this function:

◆ generate_exclude_polygon()

void Slic3r::GUI::PartPlate::generate_exclude_polygon ( ExPolygon & exclude_polygon)
private
5058{
5059 auto compute_exclude_points = [&exclude_polygon](Vec2d& center, double radius, double start_angle, double stop_angle, int count)
5060 {
5061 double angle_steps;
5062 angle_steps = (stop_angle - start_angle) / (count - 1);
5063 for(int j = 0; j < count; j++ )
5064 {
5065 double angle = start_angle + j * angle_steps;
5066 double x = center(0) + ::cos(angle) * radius;
5067 double y = center(1) + ::sin(angle) * radius;
5068 exclude_polygon.contour.append({ scale_(x), scale_(y) });
5069 }
5070 };
5071
5072 int points_count = 8;
5073 if (m_exclude_area.size() == 4)
5074 {
5075 //rectangle case
5076 for (int i = 0; i < 4; i++)
5077 {
5078 const Vec2d& p = m_exclude_area[i];
5079 Vec2d center;
5080 double start_angle, stop_angle, radius;
5081 radius = 1.f; // ORCA use equal rounding for all corners
5082 switch (i) {
5083 case 0: // Left-Bottom
5084 center(0) = p(0) + radius;
5085 center(1) = p(1) + radius;
5086 start_angle = 1.0 * PI; //180
5087 stop_angle = 1.5 * PI; //270
5088 compute_exclude_points(center, radius, start_angle, stop_angle, points_count);
5089 break;
5090 case 1: // Right-Bottom
5091 center(0) = p(0) - radius;
5092 center(1) = p(1) + radius;
5093 start_angle = 1.5 * PI; //270
5094 stop_angle = 2.0 * PI; //360
5095 compute_exclude_points(center, radius, start_angle, stop_angle, points_count);
5096 break;
5097 case 2: // Right-Top
5098 center(0) = p(0) - radius;
5099 center(1) = p(1) - radius;
5100 start_angle = 0.0 * PI; //0
5101 stop_angle = 0.5 * PI; //90
5102 compute_exclude_points(center, radius, start_angle, stop_angle, points_count);
5103 break;
5104 case 3: // Left-Top
5105 center(0) = p(0) + radius;
5106 center(1) = p(1) - radius;
5107 start_angle = 0.5 * PI; //90
5108 stop_angle = 1.0 * PI; //180
5109 compute_exclude_points(center, radius, start_angle, stop_angle, points_count);
5110 break;
5111 }
5112 }
5113 }
5114 else {
5115 for (const Vec2d& p : m_exclude_area) {
5116 exclude_polygon.contour.append({ scale_(p(0)), scale_(p(1)) });
5117 }
5118 }
5119
5120 exclude_polygon.contour.make_counter_clockwise();
5121}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
static constexpr double PI
Definition libslic3r.h:81
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138

References Slic3r::angle(), Slic3r::MultiPoint::append(), Slic3r::center(), Slic3r::ExPolygon::contour, count, m_exclude_area, Slic3r::Polygon::make_counter_clockwise(), PI, and scale_.

Referenced by set_shape().

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

◆ generate_logo_polygon()

void Slic3r::GUI::PartPlate::generate_logo_polygon ( ExPolygon & logo_polygon)
private
5008{
5009 if (m_shape.size() == 4)
5010 {
5011 bool is_bbl_vendor = false;
5012
5013 if (m_plater) {
5014 if (auto preset_bundle = wxGetApp().preset_bundle; preset_bundle)
5015 is_bbl_vendor = preset_bundle->is_bbl_vendor();
5016 }
5017
5018 //rectangle case
5019 for (int i = 0; i < 4; i++)
5020 {
5021 const Vec2d& p = m_shape[i];
5022 if ((i == 0) || (i == 1)) {
5023 logo_polygon.contour.append({scale_(p(0)), scale_(is_bbl_vendor ? p(1) - 12.f : p(1))});
5024 }
5025 else {
5026 logo_polygon.contour.append({ scale_(p(0)), scale_(p(1)) });
5027 }
5028 }
5029 }
5030 else {
5031 for (const Vec2d& p : m_shape) {
5032 logo_polygon.contour.append({ scale_(p(0)), scale_(p(1)) });
5033 }
5034 }
5035}

References Slic3r::MultiPoint::append(), Slic3r::ExPolygon::contour, m_plater, m_shape, and scale_.

Referenced by set_shape().

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

◆ generate_new_id()

ObjectID Slic3r::ObjectBase::generate_new_id ( )
inlinestaticprivateinherited
100{ return ObjectID(++ s_last_id); }
static size_t s_last_id
Definition ObjectID.hpp:101

References s_last_id.

Referenced by ObjectBase(), and set_new_unique_id().

Here is the caller graph for this function:

◆ generate_plate_name_texture()

void Slic3r::GUI::PartPlate::generate_plate_name_texture ( )
4278{
4279 auto canvas = this->m_partplate_list->m_plater->get_view3D_canvas3D();
4280 if (canvas == nullptr)
4281 return;
4282
4283 m_plate_name_icon.reset();
4284
4285 // generate m_name_texture texture from m_name with generate_from_text_string
4286 m_name_texture.reset();
4287 auto text = m_name.empty()? _L("Untitled") : from_u8(m_name);
4288
4289 // ORCA also scale font size to prevent low res texture
4290 int size = wxGetApp().em_unit() * PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE;
4291 auto l = Label::sysFont(size, true);
4292 wxFont* font = &l;
4293
4294 wxColour foreground(0xf2, 0x75, 0x4e, 0xff);
4295 if (!m_name_texture.generate_from_text_string(text.ToUTF8().data(), *font, *wxBLACK, foreground)) {
4296 BOOST_LOG_TRIVIAL(error) << "PartPlate::generate_plate_name_texture(): generate_from_text_string() failed";
4297 return;
4298 }
4299
4300 ExPolygon poly;
4301 auto bed_ext = get_extents(m_shape);
4302 Vec2d p = bed_ext[3];
4303 float factor = icon_scale_factor();
4304 float icon_sz = factor * PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE;
4305 float width = icon_sz * m_name_texture.get_width() / m_name_texture.get_height(); // icon size * text_bb_ratio
4306 float height = icon_sz; // scale with icon size to preserve ratio while system scaling
4307 float offset_y = factor * PARTPLATE_TEXT_OFFSET_Y;
4308
4309 //if (m_plater && m_plater->get_build_volume_type() == BuildVolume_Type::Circle)
4310 // px = scale_(bed_ext.center()(0)) - (width + height) / 2.00;
4311
4312 p += Vec2d(0, offset_y);
4313
4314 poly.contour.append({ scale_(p(0) ), scale_(p(1) ) });
4315 poly.contour.append({ scale_(p(0) + width), scale_(p(1) ) });
4316 poly.contour.append({ scale_(p(0) + width), scale_(p(1) + height) });
4317 poly.contour.append({ scale_(p(0) ), scale_(p(1) + height) });
4318
4320 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << "Unable to generate geometry buffers for icons\n";
4321
4322 canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
4325}
static wxFont sysFont(int size, bool bold=false)
Definition Label.cpp:28
void calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, PickingModel &model)
Definition PartPlate.cpp:1743
GLTexture m_name_texture
Definition PartPlate.hpp:217
PickingModel m_plate_name_edit_icon
Definition PartPlate.hpp:197
int picking_id_component(int idx) const
Definition PartPlate.cpp:3058
std::string m_name
Definition PartPlate.hpp:215
GLModel m_plate_name_icon
Definition PartPlate.hpp:216
@ Bed
Definition SceneRaycaster.hpp:49
static void register_model_for_picking(GLCanvas3D &canvas, PickingModel &model, int id)
Definition PartPlate.cpp:3019
wxString from_u8(const std::string &str)
Definition GUI.cpp:544

References _L, Slic3r::GUI::SceneRaycaster::Bed, calc_vertex_for_plate_name_edit_icon(), Slic3r::GUI::from_u8(), Slic3r::get_extents(), GROUND_Z, icon_scale_factor(), Slic3r::GUI::init_model_from_poly(), m_name, m_name_texture, m_partplate_list, m_plate_name_edit_icon, m_plate_name_icon, m_shape, PARTPLATE_EDIT_PLATE_NAME_ICON_SIZE, PARTPLATE_TEXT_OFFSET_Y, picking_id_component(), Slic3r::GUI::register_model_for_picking(), scale_, and Label::sysFont().

Referenced by render_plate_name_texture().

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

◆ generate_print_polygon()

void Slic3r::GUI::PartPlate::generate_print_polygon ( ExPolygon & print_polygon)
private
5038{
5039 auto compute_points = [&print_polygon](Vec2d& center, double radius, double start_angle, double stop_angle, int count)
5040 {
5041 double angle_steps;
5042 angle_steps = (stop_angle - start_angle) / (count - 1);
5043 for(int j = 0; j < count; j++ )
5044 {
5045 double angle = start_angle + j * angle_steps;
5046 double x = center(0) + ::cos(angle) * radius;
5047 double y = center(1) + ::sin(angle) * radius;
5048 print_polygon.contour.append({ scale_(x), scale_(y) });
5049 }
5050 };
5051
5052 for (const Vec2d& p : m_shape) {
5053 print_polygon.contour.append({scale_(p(0)), scale_(p(1))});
5054 }
5055}

References Slic3r::angle(), Slic3r::MultiPoint::append(), Slic3r::center(), Slic3r::ExPolygon::contour, count, m_shape, and scale_.

Referenced by calc_imex_zones(), and set_shape().

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

◆ get_bed_type()

BedType Slic3r::GUI::PartPlate::get_bed_type ( bool load_from_project = false) const
267{
268 std::string bed_type_key = "curr_bed_type";
269
270 if (m_config.has(bed_type_key)) {
271 BedType bed_type = m_config.opt_enum<BedType>(bed_type_key);
272 return bed_type;
273 }
274
275 if (!load_from_project || !m_plater || !wxGetApp().preset_bundle)
276 return btDefault;
277
278 DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
279 if (proj_cfg.has(bed_type_key))
280 return proj_cfg.opt_enum<BedType>(bed_type_key);
281 return btDefault;
282}
BedType
Definition PrintConfig.hpp:507
@ btDefault
Definition PrintConfig.hpp:508

References Slic3r::btDefault, Slic3r::ConfigOptionResolver::has(), m_config, m_plater, and Slic3r::DynamicConfig::opt_enum().

Referenced by Slic3r::GUI::Plater::open_platesettings_dialog(), Slic3r::GUI::PrintJob::process(), render_icons(), render_logo(), Slic3r::GUI::SendMultiMachinePage::request_params(), Slic3r::CLI::run(), and set_bed_type().

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

◆ get_bounding_box()

const BoundingBoxf3 & Slic3r::GUI::PartPlate::get_bounding_box ( bool extended = false)
inline

◆ get_bounding_box_crd()

const BoundingBox Slic3r::GUI::PartPlate::get_bounding_box_crd ( )
5230{
5231 const auto plate_shape = Slic3r::Polygon::new_scale(m_shape);
5232
5233 return plate_shape.bounding_box();
5234}
static Polygon new_scale(const std::vector< Vec2d > &points)
Definition Polygon.hpp:38

References m_shape, and Slic3r::Polygon::new_scale().

Referenced by Slic3r::GUI::FillBedJob::prepare(), Slic3r::GUI::GLCanvas3D::update_compacted_wipe_tower_clearance(), and Slic3r::GUI::GLCanvas3D::update_sequential_clearance().

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

◆ get_build_volume()

BoundingBoxf3 Slic3r::GUI::PartPlate::get_build_volume ( bool use_share = false)
5237{
5239 Vec3d up_point;
5240 Vec3d low_point;
5241 if (use_share && !m_extruder_areas.empty()) {
5243 BoundingBox bbox = bed_poly.bounding_box();
5244
5245 up_point = Vec3d(unscale_(bbox.max.x()) + eps, unscale_(bbox.max.y()) + eps, m_origin.z() + m_height + eps);
5246 low_point = Vec3d(unscale_(bbox.min.x()) - eps, unscale_(bbox.min.y()) - eps, m_origin.z() - eps);
5247 }
5248 else {
5249 // Orca: support non-rectangular bed
5250 up_point = m_bounding_box.max + Vec3d(eps, eps, m_origin.z() + m_height + eps);
5251 low_point = m_bounding_box.min + Vec3d(-eps, -eps, m_origin.z() - eps);
5252 }
5253 BoundingBoxf3 plate_box(low_point, up_point);
5254 return plate_box;
5255}
static constexpr const double SceneEpsilon
Definition BuildVolume.hpp:110
#define unscale_(val)
Definition libslic3r.h:107
Polygon get_shared_poly(const std::vector< Pointfs > &extruder_polys)
Definition PrintConfig.cpp:13820

References Slic3r::MultiPoint::bounding_box(), Slic3r::get_shared_poly(), m_bounding_box, m_extruder_areas, m_height, m_origin, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::BuildVolume::SceneEpsilon, and unscale_.

Referenced by Slic3r::GUI::GLCanvas3D::get_empty_cells(), Slic3r::GUI::Plater::get_empty_cells(), get_plate_box(), Slic3r::GUI::Selection::paste_objects_from_clipboard(), Slic3r::GUI::GLCanvas3D::render_thumbnail_internal(), and 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:

◆ get_center_origin()

Vec3d Slic3r::GUI::PartPlate::get_center_origin ( )
4267{
4268 Vec3d origin;
4269
4270 origin(0) = (m_bounding_box.min(0) + m_bounding_box.max(0)) / 2;//m_origin.x() + m_width / 2;
4271 origin(1) = (m_bounding_box.min(1) + m_bounding_box.max(1)) / 2; //m_origin.y() + m_depth / 2;
4272 origin(2) = m_origin.z();
4273
4274 return origin;
4275}

References m_bounding_box, and m_origin.

Referenced by add_instance(), Slic3r::GUI::MenuFactory::append_menu_item_center(), Slic3r::GUI::Selection::center(), Slic3r::GUI::Selection::center_plate(), Slic3r::GUI::Plater::priv::on_select_preset(), and Slic3r::GUI::Plater::priv::scale_selection_to_fit_print_volume().

Here is the caller graph for this function:

◆ get_effective_exclusion_filament_maps()

std::vector< int > Slic3r::GUI::PartPlate::get_effective_exclusion_filament_maps ( const DynamicConfig & g_config,
size_t filament_count,
size_t extruder_count ) const
3542{
3543 std::vector<int> result(filament_count, 0);
3544 if (extruder_count == 0)
3545 return result;
3546
3547 const std::vector<int> configured_map = get_real_filament_maps(g_config);
3548 const FilamentMapMode map_mode = get_real_filament_map_mode(g_config);
3549 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
3550 const bool is_bambu = preset_bundle != nullptr && preset_bundle->is_bbl_vendor();
3551 const bool automatic = is_auto_filament_map_mode(map_mode);
3552 const bool automatic_map_resolved = !automatic || !get_filament_maps().empty();
3553 for (size_t filament_id = 0; filament_id < filament_count; ++filament_id) {
3554 const int extruder_id = bed_exclusion_extruder_for_filament(
3555 filament_id, configured_map, map_mode, is_bambu, automatic_map_resolved, extruder_count);
3556 if (extruder_id >= 0)
3557 result[filament_id] = extruder_id + 1;
3558 }
3559 return result;
3560}
std::vector< int > get_filament_maps() const
Definition PartPlate.cpp:5791
int bed_exclusion_extruder_for_filament(const size_t filament_id, const std::vector< int > &configured_map, const FilamentMapMode map_mode, const bool is_bambu, const bool automatic_map_resolved, const size_t extruder_count)
Definition PrintConfig.cpp:14187
bool is_auto_filament_map_mode(FilamentMapMode mode)
Definition PrintConfig.hpp:649

References Slic3r::bed_exclusion_extruder_for_filament(), get_filament_maps(), get_real_filament_map_mode(), get_real_filament_maps(), Slic3r::is_auto_filament_map_mode(), and Slic3r::PresetBundle::is_bbl_vendor().

Referenced by get_object_filament_extruders(), and update_exclusion_volume_preview_models().

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

◆ get_effective_imex_mode()

std::string Slic3r::GUI::PartPlate::get_effective_imex_mode ( ) const
468{
469 // Per-plate mode takes priority over the process preset; set_imex_mode() erases the
470 // key on Primary, which is what lets the preset's value survive the config merge and
471 // reach the slicer. Resolve it the same way here.
472 std::string mode = get_imex_mode();
473 if (mode != kImexPrimaryMode)
474 return mode;
475 // wxGetApp() is not available headless -- see build_imex_cache_key, which guards on the
476 // same thing. Nothing calls this from the CLI today; this keeps that from being fatal.
477 if (!m_plater)
478 return mode;
479 if (auto* bundle = wxGetApp().preset_bundle) {
480 if (auto* opt = bundle->prints.get_edited_preset().config.option<ConfigOptionString>("imex_parallel_mode"))
481 if (!opt->value.empty())
482 return opt->value;
483 }
484 return kImexPrimaryMode;
485}
constexpr const char * kImexPrimaryMode
Definition IMEXHelpers.hpp:27

References get_imex_mode(), Slic3r::kImexPrimaryMode, and m_plater.

Referenced by build_imex_cache_key(), Slic3r::GUI::collect_imex_warnings(), has_imex_multimaterial_conflict(), render_icons(), Slic3r::GUI::GCodeViewer::render_markers(), and resolve_active_mode_tools().

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

◆ get_exclude_areas()

const std::vector< BoundingBoxf3 > & Slic3r::GUI::PartPlate::get_exclude_areas ( )
inline
603{ return m_exclude_bounding_box; }

References m_exclude_bounding_box.

Referenced by Slic3r::GLVolumeCollection::check_outside_state(), Slic3r::GUI::Plater::get_empty_cells(), Slic3r::GUI::GLCanvas3D::load_gcode_preview(), and Slic3r::GUI::Plater::priv::scale_selection_to_fit_print_volume().

Here is the caller graph for this function:

◆ get_extruder_areas()

const std::vector< Pointfs > & Slic3r::GUI::PartPlate::get_extruder_areas ( ) const
inline
579{ return m_extruder_areas; }

References m_extruder_areas.

Referenced by Slic3r::CLI::run(), and Slic3r::GUI::PartPlateList::set_default_wipe_tower_pos_for_plate().

Here is the caller graph for this function:

◆ get_extruder_heights()

const std::vector< double > & Slic3r::GUI::PartPlate::get_extruder_heights ( ) const
inline
580{ return m_extruder_heights; }

References m_extruder_heights.

◆ get_extruders() [1/2]

std::vector< int > Slic3r::GUI::PartPlate::get_extruders ( bool conside_custom_gcode,
const DynamicPrintConfig & glb_config,
const DynamicPrintConfig & project_config,
bool expand_mixed_slots = true ) const
3076{
3077 std::vector<int> plate_extruders;
3078 // A plate from a sliced .gcode.3mf holds no objects, so report the filaments the G-code
3079 // used. check_objects_empty_and_gcode3mf does this for get_extruders(bool), but reaches
3080 // the plater, which the CLI has none of; slice_filaments_info is only filled for such a plate.
3081 if (m_model->objects.empty()) {
3082 for (const FilamentInfo &info : slice_filaments_info)
3083 plate_extruders.push_back(info.id + 1);
3084 return plate_extruders;
3085 }
3086 int glb_support_intf_extr = glb_config.opt_int("support_interface_filament");
3087 int glb_support_extr = glb_config.opt_int("support_filament");
3088 int glb_outer_wall_extr = glb_config.opt_int("outer_wall_filament_id");
3089 int glb_inner_wall_extr = glb_config.opt_int("inner_wall_filament_id");
3090 if (glb_outer_wall_extr == 0) glb_outer_wall_extr = glb_inner_wall_extr;
3091 if (glb_inner_wall_extr == 0) glb_inner_wall_extr = glb_outer_wall_extr;
3092 int glb_sparse_infill_extr = glb_config.opt_int("sparse_infill_filament_id");
3093 int glb_internal_solid_extr = glb_config.opt_int("internal_solid_filament_id");
3094 int glb_top_surface_extr = glb_config.opt_int("top_surface_filament_id");
3095 int glb_bottom_surface_extr = glb_config.opt_int("bottom_surface_filament_id");
3096 if (glb_top_surface_extr == 0) glb_top_surface_extr = glb_internal_solid_extr;
3097 if (glb_bottom_surface_extr == 0) glb_bottom_surface_extr = glb_internal_solid_extr;
3098 bool glb_support = glb_config.opt_bool("enable_support");
3099 glb_support |= glb_config.opt_int("raft_layers") > 0;
3100
3101 for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
3102 // Any instance on the plate counts, as PrintApply does: after an arrange, instance 0
3103 // can sit on a different plate.
3104 if (!contain_any_instance_totally(obj_idx))
3105 continue;
3106
3107 ModelObject* mo = m_model->objects[obj_idx];
3108 for (ModelVolume* mv : mo->volumes) {
3109 std::vector<int> volume_extruders = mv->get_extruders();
3110 plate_extruders.insert(plate_extruders.end(), volume_extruders.begin(), volume_extruders.end());
3111 }
3112
3113 // layer range
3114 for (auto layer_range : mo->layer_config_ranges) {
3115 if (layer_range.second.has("extruder")) {
3116 if (auto id = layer_range.second.option("extruder")->getInt(); id > 0)
3117 plate_extruders.push_back(id);
3118 }
3119 }
3120
3121 bool obj_support = false;
3122 const ConfigOption* obj_support_opt = mo->config.option("enable_support");
3123 const ConfigOption *obj_raft_opt = mo->config.option("raft_layers");
3124 if (obj_support_opt != nullptr || obj_raft_opt != nullptr) {
3125 if (obj_support_opt != nullptr)
3126 obj_support = obj_support_opt->getBool();
3127 if (obj_raft_opt != nullptr)
3128 obj_support |= obj_raft_opt->getInt() > 0;
3129 }
3130 else
3131 obj_support = glb_support;
3132
3133 if (obj_support) {
3134 int obj_support_intf_extr = 0;
3135 const ConfigOption* support_intf_extr_opt = mo->config.option("support_interface_filament");
3136 if (support_intf_extr_opt != nullptr)
3137 obj_support_intf_extr = support_intf_extr_opt->getInt();
3138 if (obj_support_intf_extr != 0)
3139 plate_extruders.push_back(obj_support_intf_extr);
3140 else if (glb_support_intf_extr != 0)
3141 plate_extruders.push_back(glb_support_intf_extr);
3142
3143 int obj_support_extr = 0;
3144 const ConfigOption* support_extr_opt = mo->config.option("support_filament");
3145 if (support_extr_opt != nullptr)
3146 obj_support_extr = support_extr_opt->getInt();
3147 if (obj_support_extr != 0)
3148 plate_extruders.push_back(obj_support_extr);
3149 else if (glb_support_extr != 0)
3150 plate_extruders.push_back(glb_support_extr);
3151 }
3152
3153 int obj_outer_wall_extr = 0;
3154 if (const ConfigOption* wall_opt = mo->config.option("outer_wall_filament_id"); wall_opt != nullptr)
3155 obj_outer_wall_extr = wall_opt->getInt();
3156 if (obj_outer_wall_extr == 0)
3157 if (const ConfigOption* wall_opt = mo->config.option("inner_wall_filament_id"); wall_opt != nullptr)
3158 obj_outer_wall_extr = wall_opt->getInt();
3159 if (obj_outer_wall_extr != 0)
3160 plate_extruders.push_back(obj_outer_wall_extr);
3161 else if (glb_outer_wall_extr != 0)
3162 plate_extruders.push_back(glb_outer_wall_extr);
3163
3164 int obj_inner_wall_extr = 0;
3165 if (const ConfigOption* wall_opt = mo->config.option("inner_wall_filament_id"); wall_opt != nullptr)
3166 obj_inner_wall_extr = wall_opt->getInt();
3167 if (obj_inner_wall_extr == 0)
3168 if (const ConfigOption* wall_opt = mo->config.option("outer_wall_filament_id"); wall_opt != nullptr)
3169 obj_inner_wall_extr = wall_opt->getInt();
3170 if (obj_inner_wall_extr != 0)
3171 plate_extruders.push_back(obj_inner_wall_extr);
3172 else if (glb_inner_wall_extr != 0)
3173 plate_extruders.push_back(glb_inner_wall_extr);
3174
3175 int obj_sparse_infill_extr = 0;
3176 const ConfigOption* sparse_infill_opt = mo->config.option("sparse_infill_filament_id");
3177 if (sparse_infill_opt != nullptr)
3178 obj_sparse_infill_extr = sparse_infill_opt->getInt();
3179 if (obj_sparse_infill_extr != 0)
3180 plate_extruders.push_back(obj_sparse_infill_extr);
3181 else if (glb_sparse_infill_extr != 0)
3182 plate_extruders.push_back(glb_sparse_infill_extr);
3183
3184 int obj_internal_solid_extr = 0;
3185 if (const ConfigOption* solid_opt = mo->config.option("internal_solid_filament_id"); solid_opt != nullptr)
3186 obj_internal_solid_extr = solid_opt->getInt();
3187 if (obj_internal_solid_extr != 0)
3188 plate_extruders.push_back(obj_internal_solid_extr);
3189 else if (glb_internal_solid_extr != 0)
3190 plate_extruders.push_back(glb_internal_solid_extr);
3191
3192 int obj_top_surface_extr = 0;
3193 if (const ConfigOption* top_opt = mo->config.option("top_surface_filament_id"); top_opt != nullptr)
3194 obj_top_surface_extr = top_opt->getInt();
3195 if (obj_top_surface_extr == 0)
3196 obj_top_surface_extr = obj_internal_solid_extr;
3197 if (obj_top_surface_extr != 0)
3198 plate_extruders.push_back(obj_top_surface_extr);
3199 else if (glb_top_surface_extr != 0)
3200 plate_extruders.push_back(glb_top_surface_extr);
3201
3202 int obj_bottom_surface_extr = 0;
3203 if (const ConfigOption* bottom_opt = mo->config.option("bottom_surface_filament_id"); bottom_opt != nullptr)
3204 obj_bottom_surface_extr = bottom_opt->getInt();
3205 if (obj_bottom_surface_extr == 0)
3206 obj_bottom_surface_extr = obj_internal_solid_extr;
3207 if (obj_bottom_surface_extr != 0)
3208 plate_extruders.push_back(obj_bottom_surface_extr);
3209 else if (glb_bottom_surface_extr != 0)
3210 plate_extruders.push_back(glb_bottom_surface_extr);
3211
3212 }
3213
3214 if (conside_custom_gcode) {
3215 //BBS
3216 int nums_extruders = 0;
3217 if (const ConfigOptionStrings *color_option = dynamic_cast<const ConfigOptionStrings *>(project_config.option("filament_colour"))) {
3218 nums_extruders = color_option->values.size();
3219 if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
3220 for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
3221 if (item.type == CustomGCode::Type::ToolChange && item.extruder <= nums_extruders)
3222 plate_extruders.push_back(item.extruder);
3223 }
3224 }
3225 }
3226 }
3227
3228 std::sort(plate_extruders.begin(), plate_extruders.end());
3229 auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end());
3230 plate_extruders.resize(std::distance(plate_extruders.begin(), it_end));
3231
3232 // Expand mixed filament slots to their physical components. A mixed slot is virtual and
3233 // is never loaded into a tray, so callers (AMS mapping, filament checks) must see the
3234 // physical filaments it resolves to instead.
3235 {
3236 const auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
3237 const auto* comp_strs_opt = project_config.option<ConfigOptionStrings>("filament_mixed_components");
3238 if (expand_mixed_slots && is_mixed_opt && comp_strs_opt && has_any_mixed_filament(is_mixed_opt->values)) {
3239 std::vector<unsigned int> ext_0based;
3240 for (int e : plate_extruders)
3241 if (e >= 1) ext_0based.push_back((unsigned int)(e - 1));
3242 auto expanded = expand_mixed_filaments(ext_0based, is_mixed_opt->values, comp_strs_opt->values);
3243 plate_extruders.clear();
3244 for (unsigned int e : expanded)
3245 plate_extruders.push_back((int)(e + 1));
3246 }
3247 }
3248
3249 return plate_extruders;
3250}
@ ToolChange
Definition CustomGCode.hpp:21
std::vector< unsigned int > expand_mixed_filaments(const std::vector< unsigned int > &extruders_0based, const std::vector< unsigned char > &is_mixed, const std::vector< std::string > &comp_strs)
Definition FilamentMixer.cpp:520

References Slic3r::ModelObject::config, contain_any_instance_totally(), Slic3r::expand_mixed_filaments(), Slic3r::ModelVolume::get_extruders(), Slic3r::ConfigOption::getBool(), Slic3r::ConfigOption::getInt(), Slic3r::has_any_mixed_filament(), Slic3r::ModelObject::layer_config_ranges, m_model, m_plate_index, Slic3r::DynamicConfig::opt_bool(), Slic3r::DynamicConfig::opt_int(), Slic3r::ConfigBase::option(), Slic3r::ModelConfig::option(), slice_filaments_info, Slic3r::CustomGCode::ToolChange, Slic3r::ConfigOptionVector< unsigned char >::values, and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ get_extruders() [2/2]

std::vector< int > Slic3r::GUI::PartPlate::get_extruders ( bool conside_custom_gcode = false,
bool expand_mixed_slots = true ) const
3064{
3065 std::vector<int> plate_extruders;
3066 if (check_objects_empty_and_gcode3mf(plate_extruders)) {
3067 return plate_extruders;
3068 }
3069 return get_extruders(conside_custom_gcode, wxGetApp().preset_bundle->prints.get_edited_preset().config, wxGetApp().preset_bundle->project_config, expand_mixed_slots);
3070}
bool check_objects_empty_and_gcode3mf(std::vector< int > &result) const
Definition PartPlate.cpp:3430

References check_objects_empty_and_gcode3mf(), and get_extruders().

Referenced by check_filament_printable(), check_mixture_filament_compatible(), check_mixture_of_pla_and_petg(), Slic3r::GUI::collect_imex_warnings(), estimate_wipe_tower_footprint(), get_extruders(), has_imex_multimaterial_conflict(), imex_wipe_tower_hull(), Slic3r::GLVolumeCollection::load_real_wipe_tower_preview(), Slic3r::GLVolumeCollection::load_wipe_tower_preview(), Slic3r::GUI::Plater::open_filament_map_setting_dialog(), Slic3r::GUI::ArrangeJob::prepare_wipe_tower(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::GUI::try_pop_up_before_slice(), and Slic3r::GUI::Plater::validate_current_plate().

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

◆ get_extruders_under_cli()

std::vector< int > Slic3r::GUI::PartPlate::get_extruders_under_cli ( bool conside_custom_gcode,
DynamicPrintConfig & full_config,
bool expand_mixed_slots = true ) const
3253{
3254 std::vector<int> plate_extruders;
3255
3256 // if 3mf file
3257 int glb_support_intf_extr = full_config.opt_int("support_interface_filament");
3258 int glb_support_extr = full_config.opt_int("support_filament");
3259 int glb_outer_wall_extr = full_config.opt_int("outer_wall_filament_id");
3260 int glb_inner_wall_extr = full_config.opt_int("inner_wall_filament_id");
3261 if (glb_outer_wall_extr == 0) glb_outer_wall_extr = glb_inner_wall_extr;
3262 if (glb_inner_wall_extr == 0) glb_inner_wall_extr = glb_outer_wall_extr;
3263 int glb_sparse_infill_extr = full_config.opt_int("sparse_infill_filament_id");
3264 int glb_internal_solid_extr = full_config.opt_int("internal_solid_filament_id");
3265 int glb_top_surface_extr = full_config.opt_int("top_surface_filament_id");
3266 int glb_bottom_surface_extr = full_config.opt_int("bottom_surface_filament_id");
3267 if (glb_top_surface_extr == 0) glb_top_surface_extr = glb_internal_solid_extr;
3268 if (glb_bottom_surface_extr == 0) glb_bottom_surface_extr = glb_internal_solid_extr;
3269
3270 bool glb_support = full_config.opt_bool("enable_support");
3271 glb_support |= full_config.opt_int("raft_layers") > 0;
3272
3273 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
3274 {
3275 int obj_id = it->first;
3276 int instance_id = it->second;
3277
3278 if (valid_instance(obj_id, instance_id))
3279 {
3280 ModelObject* object = m_model->objects[obj_id];
3281 ModelInstance* instance = object->instances[instance_id];
3282
3283 if (!instance->printable)
3284 continue;
3285
3286 for (ModelVolume* mv : object->volumes) {
3287 std::vector<int> volume_extruders = mv->get_extruders();
3288 plate_extruders.insert(plate_extruders.end(), volume_extruders.begin(), volume_extruders.end());
3289 }
3290
3291 // layer range
3292 for (auto layer_range : object->layer_config_ranges) {
3293 if (layer_range.second.has("extruder")) {
3294 if (auto id = layer_range.second.option("extruder")->getInt(); id > 0)
3295 plate_extruders.push_back(id);
3296 }
3297 }
3298
3299 bool obj_support = false;
3300 const ConfigOption* obj_support_opt = object->config.option("enable_support");
3301 const ConfigOption *obj_raft_opt = object->config.option("raft_layers");
3302 if (obj_support_opt != nullptr || obj_raft_opt != nullptr) {
3303 if (obj_support_opt != nullptr)
3304 obj_support = obj_support_opt->getBool();
3305 if (obj_raft_opt != nullptr)
3306 obj_support |= obj_raft_opt->getInt() > 0;
3307 }
3308 else
3309 obj_support = glb_support;
3310
3311 if (obj_support) {
3312 int obj_support_intf_extr = 0;
3313 const ConfigOption* support_intf_extr_opt = object->config.option("support_interface_filament");
3314 if (support_intf_extr_opt != nullptr)
3315 obj_support_intf_extr = support_intf_extr_opt->getInt();
3316 if (obj_support_intf_extr != 0)
3317 plate_extruders.push_back(obj_support_intf_extr);
3318 else if (glb_support_intf_extr != 0)
3319 plate_extruders.push_back(glb_support_intf_extr);
3320
3321 int obj_support_extr = 0;
3322 const ConfigOption* support_extr_opt = object->config.option("support_filament");
3323 if (support_extr_opt != nullptr)
3324 obj_support_extr = support_extr_opt->getInt();
3325 if (obj_support_extr != 0)
3326 plate_extruders.push_back(obj_support_extr);
3327 else if (glb_support_extr != 0)
3328 plate_extruders.push_back(glb_support_extr);
3329 }
3330
3331 int obj_outer_wall_extr = 0;
3332 if (const ConfigOption* wall_opt = object->config.option("outer_wall_filament_id"); wall_opt != nullptr)
3333 obj_outer_wall_extr = wall_opt->getInt();
3334 if (obj_outer_wall_extr == 0)
3335 if (const ConfigOption* wall_opt = object->config.option("inner_wall_filament_id"); wall_opt != nullptr)
3336 obj_outer_wall_extr = wall_opt->getInt();
3337 if (obj_outer_wall_extr != 0)
3338 plate_extruders.push_back(obj_outer_wall_extr);
3339 else if (glb_outer_wall_extr != 0)
3340 plate_extruders.push_back(glb_outer_wall_extr);
3341
3342 int obj_inner_wall_extr = 0;
3343 if (const ConfigOption* wall_opt = object->config.option("inner_wall_filament_id"); wall_opt != nullptr)
3344 obj_inner_wall_extr = wall_opt->getInt();
3345 if (obj_inner_wall_extr == 0)
3346 if (const ConfigOption* wall_opt = object->config.option("outer_wall_filament_id"); wall_opt != nullptr)
3347 obj_inner_wall_extr = wall_opt->getInt();
3348 if (obj_inner_wall_extr != 0)
3349 plate_extruders.push_back(obj_inner_wall_extr);
3350 else if (glb_inner_wall_extr != 0)
3351 plate_extruders.push_back(glb_inner_wall_extr);
3352
3353 int obj_sparse_infill_extr = 0;
3354 const ConfigOption* sparse_infill_opt = object->config.option("sparse_infill_filament_id");
3355 if (sparse_infill_opt != nullptr)
3356 obj_sparse_infill_extr = sparse_infill_opt->getInt();
3357 if (obj_sparse_infill_extr != 0)
3358 plate_extruders.push_back(obj_sparse_infill_extr);
3359 else if (glb_sparse_infill_extr != 0)
3360 plate_extruders.push_back(glb_sparse_infill_extr);
3361
3362 int obj_internal_solid_extr = 0;
3363 if (const ConfigOption* solid_opt = object->config.option("internal_solid_filament_id"); solid_opt != nullptr)
3364 obj_internal_solid_extr = solid_opt->getInt();
3365 if (obj_internal_solid_extr != 0)
3366 plate_extruders.push_back(obj_internal_solid_extr);
3367 else if (glb_internal_solid_extr != 0)
3368 plate_extruders.push_back(glb_internal_solid_extr);
3369
3370 int obj_top_surface_extr = 0;
3371 if (const ConfigOption* top_opt = object->config.option("top_surface_filament_id"); top_opt != nullptr)
3372 obj_top_surface_extr = top_opt->getInt();
3373 if (obj_top_surface_extr == 0)
3374 obj_top_surface_extr = obj_internal_solid_extr;
3375 if (obj_top_surface_extr != 0)
3376 plate_extruders.push_back(obj_top_surface_extr);
3377 else if (glb_top_surface_extr != 0)
3378 plate_extruders.push_back(glb_top_surface_extr);
3379
3380 int obj_bottom_surface_extr = 0;
3381 if (const ConfigOption* bottom_opt = object->config.option("bottom_surface_filament_id"); bottom_opt != nullptr)
3382 obj_bottom_surface_extr = bottom_opt->getInt();
3383 if (obj_bottom_surface_extr == 0)
3384 obj_bottom_surface_extr = obj_internal_solid_extr;
3385 if (obj_bottom_surface_extr != 0)
3386 plate_extruders.push_back(obj_bottom_surface_extr);
3387 else if (glb_bottom_surface_extr != 0)
3388 plate_extruders.push_back(glb_bottom_surface_extr);
3389 }
3390 }
3391
3392 if (conside_custom_gcode) {
3393 //BBS
3394 int nums_extruders = 0;
3395 if (const ConfigOptionStrings *color_option = dynamic_cast<const ConfigOptionStrings *>(full_config.option("filament_colour"))) {
3396 nums_extruders = color_option->values.size();
3397 if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
3398 for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
3399 if (item.type == CustomGCode::Type::ToolChange && item.extruder <= nums_extruders)
3400 plate_extruders.push_back(item.extruder);
3401 }
3402 }
3403 }
3404 }
3405
3406 std::sort(plate_extruders.begin(), plate_extruders.end());
3407 auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end());
3408 plate_extruders.resize(std::distance(plate_extruders.begin(), it_end));
3409
3410 // Expand mixed filament slots to their physical components. A mixed slot is virtual and
3411 // is never loaded into a tray, so callers (AMS mapping, filament checks) must see the
3412 // physical filaments it resolves to instead.
3413 if (expand_mixed_slots) {
3414 auto* is_mixed_opt = full_config.option<ConfigOptionBools>("filament_is_mixed");
3415 auto* comp_strs_opt = full_config.option<ConfigOptionStrings>("filament_mixed_components");
3416 if (is_mixed_opt && comp_strs_opt && has_any_mixed_filament(is_mixed_opt->values)) {
3417 std::vector<unsigned int> ext_0based;
3418 for (int e : plate_extruders)
3419 if (e >= 1) ext_0based.push_back((unsigned int)(e - 1));
3420 auto expanded = expand_mixed_filaments(ext_0based, is_mixed_opt->values, comp_strs_opt->values);
3421 plate_extruders.clear();
3422 for (unsigned int e : expanded)
3423 plate_extruders.push_back((int)(e + 1));
3424 }
3425 }
3426
3427 return plate_extruders;
3428}

References Slic3r::ModelObject::config, Slic3r::expand_mixed_filaments(), Slic3r::ModelVolume::get_extruders(), Slic3r::ConfigOption::getBool(), Slic3r::ConfigOption::getInt(), Slic3r::has_any_mixed_filament(), Slic3r::ModelObject::layer_config_ranges, m_model, m_plate_index, obj_to_instance_set, Slic3r::DynamicConfig::opt_bool(), Slic3r::DynamicConfig::opt_int(), Slic3r::ConfigBase::option(), Slic3r::ModelConfig::option(), Slic3r::ModelInstance::printable, Slic3r::CustomGCode::ToolChange, valid_instance(), Slic3r::ConfigOptionVector< unsigned char >::values, and Slic3r::ModelObject::volumes.

Referenced by Slic3r::CLI::run().

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

◆ get_extruders_without_support()

std::vector< int > Slic3r::GUI::PartPlate::get_extruders_without_support ( bool conside_custom_gcode = false) const
3444{
3445 std::vector<int> plate_extruders;
3446 if (check_objects_empty_and_gcode3mf(plate_extruders)) {
3447 return plate_extruders;
3448 }
3449 // if 3mf file
3450 const DynamicPrintConfig& glb_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
3451
3452 for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
3453 if (!contain_any_instance_totally(obj_idx))
3454 continue;
3455
3456 ModelObject* mo = m_model->objects[obj_idx];
3457 for (ModelVolume* mv : mo->volumes) {
3458 std::vector<int> volume_extruders = mv->get_extruders();
3459 plate_extruders.insert(plate_extruders.end(), volume_extruders.begin(), volume_extruders.end());
3460 }
3461 }
3462
3463 if (conside_custom_gcode) {
3464 //BBS
3465 int nums_extruders = 0;
3466 if (const ConfigOptionStrings* color_option = dynamic_cast<const ConfigOptionStrings*>(wxGetApp().preset_bundle->project_config.option("filament_colour"))) {
3467 nums_extruders = color_option->values.size();
3468 if (m_model->plates_custom_gcodes.find(m_plate_index) != m_model->plates_custom_gcodes.end()) {
3469 for (auto item : m_model->plates_custom_gcodes.at(m_plate_index).gcodes) {
3470 if (item.type == CustomGCode::Type::ToolChange && item.extruder <= nums_extruders)
3471 plate_extruders.push_back(item.extruder);
3472 }
3473 }
3474 }
3475 }
3476
3477 std::sort(plate_extruders.begin(), plate_extruders.end());
3478 auto it_end = std::unique(plate_extruders.begin(), plate_extruders.end());
3479 plate_extruders.resize(std::distance(plate_extruders.begin(), it_end));
3480
3481 // Expand mixed filament slots to their physical components. A mixed slot is virtual and
3482 // is never loaded into a tray, so callers (AMS mapping, filament checks) must see the
3483 // physical filaments it resolves to instead.
3484 {
3485 auto& project_config = wxGetApp().preset_bundle->project_config;
3486 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
3487 auto* comp_strs_opt = project_config.option<ConfigOptionStrings>("filament_mixed_components");
3488 if (is_mixed_opt && comp_strs_opt && has_any_mixed_filament(is_mixed_opt->values)) {
3489 std::vector<unsigned int> ext_0based;
3490 for (int e : plate_extruders)
3491 if (e >= 1) ext_0based.push_back((unsigned int)(e - 1));
3492 auto expanded = expand_mixed_filaments(ext_0based, is_mixed_opt->values, comp_strs_opt->values);
3493 plate_extruders.clear();
3494 for (unsigned int e : expanded)
3495 plate_extruders.push_back((int)(e + 1));
3496 }
3497 }
3498
3499 return plate_extruders;
3500}

References check_objects_empty_and_gcode3mf(), contain_any_instance_totally(), Slic3r::expand_mixed_filaments(), Slic3r::ModelVolume::get_extruders(), Slic3r::has_any_mixed_filament(), m_model, m_plate_index, Slic3r::CustomGCode::ToolChange, Slic3r::ConfigOptionVector< unsigned char >::values, and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ get_filament_map_mode()

FilamentMapMode Slic3r::GUI::PartPlate::get_filament_map_mode ( ) const
5767{
5768 std::string key = "filament_map_mode";
5769 if(m_config.has(key))
5770 return m_config.option<ConfigOptionEnum<FilamentMapMode>>(key)->value;
5772}
@ fmmDefault
Definition PrintConfig.hpp:637

References Slic3r::fmmDefault, and m_config.

Referenced by get_real_filament_map_mode(), Slic3r::GUI::Plater::open_filament_map_setting_dialog(), and set_filament_map_mode().

Here is the caller graph for this function:

◆ get_filament_maps()

std::vector< int > Slic3r::GUI::PartPlate::get_filament_maps ( ) const
5792{
5793 std::string key = "filament_map";
5794 if (m_config.has(key))
5795 return m_config.option<ConfigOptionInts>(key)->values;
5796
5797 return {};
5798}

References m_config.

Referenced by Slic3r::GUI::SelectMachineDialog::get_ams_mapping_result(), Slic3r::GUI::SendMultiMachinePage::get_ams_mapping_result(), Slic3r::GUI::SyncAmsInfoDialog::get_ams_mapping_result(), get_effective_exclusion_filament_maps(), get_real_filament_maps(), and load_gcode_from_file().

Here is the caller graph for this function:

◆ get_filament_nozzle_maps()

std::vector< int > Slic3r::GUI::PartPlate::get_filament_nozzle_maps ( ) const
5834{
5835 std::string key = "filament_nozzle_map";
5836 if (m_config.has(key))
5837 return m_config.option<ConfigOptionInts>(key)->values;
5838
5839 return {};
5840}

References m_config.

◆ get_filament_volume_maps()

std::vector< int > Slic3r::GUI::PartPlate::get_filament_volume_maps ( ) const
5814{
5815 std::string key = "filament_volume_map";
5816 if (m_config.has(key))
5817 return m_config.option<ConfigOptionInts>(key)->values;
5818
5819 return {};
5820}

References m_config.

Referenced by Slic3r::GUI::Plater::apply_background_progress(), get_real_filament_volume_maps(), load_gcode_from_file(), Slic3r::GUI::Plater::select_plate(), Slic3r::GUI::Plater::select_plate_by_hover_id(), Slic3r::GUI::PartPlateList::set_default_wipe_tower_pos_for_plate(), and Slic3r::GUI::Plater::priv::update_background_process().

Here is the caller graph for this function:

◆ get_first_layer_print_sequence()

std::vector< int > Slic3r::GUI::PartPlate::get_first_layer_print_sequence ( ) const
5603{
5604 const ConfigOptionInts *op_print_sequence_1st = m_config.option<ConfigOptionInts>("first_layer_print_sequence");
5605 if (op_print_sequence_1st)
5606 return op_print_sequence_1st->values;
5607 else
5608 return std::vector<int>();
5609}
std::vector< int > values
Definition Config.hpp:418

References m_config, and Slic3r::ConfigOptionVector< int >::values.

Referenced by Slic3r::GUI::Plater::open_platesettings_dialog(), and render_icons().

Here is the caller graph for this function:

◆ get_gcode_filename()

std::string Slic3r::GUI::PartPlate::get_gcode_filename ( )
4393{
4395 return m_gcode_result->filename;
4396 }
4397 return "";
4398}
GCodeProcessorResult * m_gcode_result
Definition PartPlate.hpp:140
GCodeProcessorResult * get_slice_result()
Definition PartPlate.hpp:698
bool is_slice_result_valid() const
Definition PartPlate.hpp:660

References get_slice_result(), is_slice_result_valid(), and m_gcode_result.

Referenced by is_valid_gcode_file().

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

◆ get_imex_ghost_volumes()

const std::vector< std::unique_ptr< GLVolume > > & Slic3r::GUI::PartPlate::get_imex_ghost_volumes ( ) const
inline
403 {
405 }

References m_imex_ghost_volumes.

Referenced by Slic3r::GUI::GLCanvas3D::_picking_pass_imex_ghosts(), Slic3r::GUI::GLCanvas3D::_render_imex_ghost_tooltip(), and Slic3r::GUI::GLCanvas3D::_render_imex_ghosts().

Here is the caller graph for this function:

◆ get_imex_head_filament_color() [1/2]

ColorRGBA Slic3r::GUI::PartPlate::get_imex_head_filament_color ( int physical_head) const
542{
543 auto* pb = wxGetApp().preset_bundle;
544 if (!pb)
546
547 return get_imex_head_filament_color(physical_head,
550}
static ColorRGBA UNPRINTABLE_COLOR
Definition 3DScene.hpp:98
ColorRGBA get_imex_head_filament_color(int physical_head) const
Definition PartPlate.cpp:541
std::map< int, int > get_imex_head_filament_map() const
Definition PartPlate.cpp:507
ConfigOptionInts effective_physical_extruder_map(const ConfigOptionInts *explicit_pem, int nozzle_count)
Definition IMEXHelpers.cpp:52

References Slic3r::effective_physical_extruder_map(), get_imex_head_filament_color(), get_imex_head_filament_map(), and Slic3r::GLVolume::UNPRINTABLE_COLOR.

Referenced by Slic3r::GUI::Plater::format_imex_ghost_tooltip(), get_imex_head_filament_color(), Slic3r::GUI::GCodeViewer::render_markers(), and update_imex_ghost_colors().

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

◆ get_imex_head_filament_color() [2/2]

ColorRGBA Slic3r::GUI::PartPlate::get_imex_head_filament_color ( int physical_head,
const ConfigOptionInts & pem,
const std::map< int, int > & plate_map ) const
555{
556 auto* pb = wxGetApp().preset_bundle;
557 if (!pb)
559
560 const int logical = resolve_filament_for_head(plate_map, pem, physical_head);
561 if (logical < 0)
563
564 auto* colours = pb->project_config.option<ConfigOptionStrings>("filament_colour");
565 if (!colours || logical >= (int)colours->values.size())
567
568 ColorRGBA rgba;
569 if (!decode_color(colours->values[logical], rgba))
571 return rgba;
572}
static wxColour decode_color(const std::string &color)
Definition SliceInfoPanel.cpp:51
int resolve_filament_for_head(const std::map< int, int > &plate_map, const ConfigOptionInts &pem, int physical)
Definition IMEXHelpers.cpp:556

References Slic3r::GUI::decode_color(), Slic3r::resolve_filament_for_head(), and Slic3r::GLVolume::UNPRINTABLE_COLOR.

Here is the call graph for this function:

◆ get_imex_head_filament_map()

std::map< int, int > Slic3r::GUI::PartPlate::get_imex_head_filament_map ( ) const
508{
509 if (!m_config.has("imex_head_filament_map"))
510 return {};
511 auto* opt = m_config.option<ConfigOptionString>("imex_head_filament_map");
512 if (!opt) return {};
513 return parse_imex_head_filament_map(opt->value);
514}
std::map< int, int > parse_imex_head_filament_map(const std::string &s)
Definition IMEXHelpers.cpp:457

References m_config, and Slic3r::parse_imex_head_filament_map().

Referenced by Slic3r::GUI::Plater::format_imex_ghost_tooltip(), get_imex_head_filament_color(), Slic3r::GUI::GCodeViewer::render_markers(), and update_imex_ghost_colors().

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

◆ get_imex_mode()

std::string Slic3r::GUI::PartPlate::get_imex_mode ( ) const
458{
459 if (m_config.has("imex_parallel_mode")) {
460 auto* opt = m_config.option<ConfigOptionString>("imex_parallel_mode");
461 if (opt && !opt->value.empty())
462 return opt->value;
463 }
464 return kImexPrimaryMode;
465}

References Slic3r::kImexPrimaryMode, and m_config.

Referenced by Slic3r::GUI::TabPrinter::build_unregular_pages(), calc_imex_zones(), get_effective_imex_mode(), render_icons(), and Slic3r::GUI::Plater::select_plate_by_hover_id().

Here is the caller graph for this function:

◆ get_index()

int Slic3r::GUI::PartPlate::get_index ( )
inline

◆ get_instance()

ModelInstance * Slic3r::GUI::PartPlate::get_instance ( int obj_id,
int instance_id )
4423{
4424 if (!contain_instance(obj_id, instance_id))
4425 return nullptr;
4426 else
4427 return m_model->objects[obj_id]->instances[instance_id];
4428}
bool contain_instance(int obj_id, int instance_id)
Definition PartPlate.cpp:4432

References contain_instance(), and m_model.

Here is the call graph for this function:

◆ get_logical_extruder_by_filament_id()

int Slic3r::GUI::PartPlate::get_logical_extruder_by_filament_id ( const DynamicConfig & g_config,
int idx ) const
3530{
3531 const std::vector<int>& filament_map = get_real_filament_maps(g_config);
3532 if (idx <= 0 || idx > (int)filament_map.size())
3533 {
3534 return -1;
3535 }
3536
3537 return filament_map[idx - 1] - 1;
3538}

References Slic3r::filament_map(), and get_real_filament_maps().

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

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

◆ get_object_filament_extruders()

std::map< int, size_t > Slic3r::GUI::PartPlate::get_object_filament_extruders ( const ModelObject & object,
const DynamicConfig & g_config,
size_t extruder_count ) const
3564{
3565 std::set<int> filament_ids;
3566 const DynamicPrintConfig &process_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
3567 const auto effective_option = [&object, &process_config](const char *key) -> const ConfigOption * {
3568 if (const ConfigOption *option = object.config.option(key); option != nullptr)
3569 return option;
3570 return process_config.option(key);
3571 };
3572 const auto effective_int = [&effective_option](const char *key) {
3573 const ConfigOption *option = effective_option(key);
3574 return option != nullptr ? option->getInt() : 0;
3575 };
3576 const auto effective_float = [&effective_option](const char *key) {
3577 const ConfigOption *option = effective_option(key);
3578 return option != nullptr ? option->getFloat() : 0.0;
3579 };
3580 const auto effective_bool = [&effective_option](const char *key) {
3581 const ConfigOption *option = effective_option(key);
3582 return option != nullptr && option->getBool();
3583 };
3584
3585 const bool has_brim = effective_int("brim_type") != int(BrimType::btNoBrim) && effective_float("brim_width") > 0.0;
3586 const int wall_loops = effective_int("wall_loops");
3587 const double sparse_infill_density = effective_float("sparse_infill_density");
3588 const int top_shell_layers = effective_int("top_shell_layers");
3589 const int bottom_shell_layers = effective_int("bottom_shell_layers");
3590 const std::array<std::pair<const char *, bool>, 6> feature_filament_keys = {
3591 std::pair{ "outer_wall_filament_id", wall_loops > 0 || has_brim },
3592 std::pair{ "inner_wall_filament_id", wall_loops > 1 },
3593 std::pair{ "sparse_infill_filament_id", sparse_infill_density > 0.0 },
3594 std::pair{ "internal_solid_filament_id", sparse_infill_density > 0.0 || top_shell_layers > 0 || bottom_shell_layers > 0 },
3595 std::pair{ "top_surface_filament_id", top_shell_layers > 0 },
3596 std::pair{ "bottom_surface_filament_id", bottom_shell_layers > 0 }
3597 };
3598 auto collect_config_filaments = [&filament_ids, &feature_filament_keys](const DynamicConfig &config) {
3599 for (const auto &[key, active] : feature_filament_keys) {
3600 if (active) {
3601 if (const ConfigOption *option = config.option(key); option != nullptr && option->getInt() > 0)
3602 filament_ids.emplace(option->getInt());
3603 }
3604 }
3605 if (const ConfigOption *option = config.option("extruder"); option != nullptr && option->getInt() > 0)
3606 filament_ids.emplace(option->getInt());
3607 };
3608
3609 for (const ModelVolume *volume : object.volumes) {
3610 const std::vector<int> volume_filaments = volume->get_extruders();
3611 filament_ids.insert(volume_filaments.begin(), volume_filaments.end());
3612 collect_config_filaments(volume->config.get());
3613 }
3614 collect_config_filaments(object.config.get());
3615 for (const auto &layer_range : object.layer_config_ranges)
3616 collect_config_filaments(layer_range.second.get());
3617
3618 // Process-level feature assignments also apply when the object has no
3619 // override. This mirrors the relevant parts of PrintObject::printing_extruders()
3620 // closely enough for an unsliced placement preview.
3621 for (const auto &[key, active] : feature_filament_keys) {
3622 if (active && !object.config.has(key) && process_config.has(key) && process_config.opt_int(key) > 0)
3623 filament_ids.emplace(process_config.opt_int(key));
3624 }
3625
3626 const bool has_support = effective_bool("enable_support") || effective_int("raft_layers") > 0;
3627 if (has_support) {
3628 const int support_filament = effective_int("support_filament");
3629 const int interface_filament = effective_int("support_interface_filament");
3630 if (support_filament > 0)
3631 filament_ids.emplace(support_filament);
3632 if (interface_filament > 0)
3633 filament_ids.emplace(interface_filament);
3634 }
3635
3636 // Match Orca's normal fallback for an unassigned object.
3637 if (filament_ids.empty())
3638 filament_ids.emplace(1);
3639
3640 const size_t required_filament_count = filament_ids.empty() ? 0 : size_t(*filament_ids.rbegin());
3641 const std::vector<int> filament_map = get_effective_exclusion_filament_maps(
3642 g_config, required_filament_count, extruder_count);
3643 std::map<int, size_t> result;
3644 for (const int filament_id : filament_ids) {
3645 if (filament_id <= 0)
3646 continue;
3647
3648 const int mapped_extruder = size_t(filament_id) <= filament_map.size() && filament_map[filament_id - 1] > 0 ?
3649 filament_map[filament_id - 1] - 1 : -1;
3650 if (mapped_extruder >= 0 && size_t(mapped_extruder) < extruder_count)
3651 result.emplace(filament_id, size_t(mapped_extruder));
3652 }
3653 return result;
3654}
std::vector< int > get_effective_exclusion_filament_maps(const DynamicConfig &g_config, size_t filament_count, size_t extruder_count) const
Definition PartPlate.cpp:3540
@ btNoBrim
Definition PrintConfig.hpp:461
sparse_infill_density((ConfigOptionEnum< InfillPattern >, sparse_infill_pattern))((ConfigOptionPercent
bottom_shell_layers((ConfigOptionFloat, bottom_shell_thickness))((ConfigOptionInt

References Slic3r::bottom_shell_layers(), Slic3r::btNoBrim, config(), Slic3r::filament_ids(), Slic3r::filament_map(), get_effective_exclusion_filament_maps(), Slic3r::ConfigOption::getBool(), Slic3r::ConfigOption::getFloat(), Slic3r::ConfigOption::getInt(), Slic3r::ConfigOptionResolver::has(), Slic3r::DynamicConfig::opt_int(), Slic3r::ConfigBase::option(), and Slic3r::sparse_infill_density().

Referenced by Slic3r::GUI::set_arrange_polygon_bed_exclusion_extruders(), and update_exclusion_volume_preview_models().

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

◆ get_objects()

ModelObjectPtrs Slic3r::GUI::PartPlate::get_objects ( )
inline
474{ return m_model->objects; }

References m_model.

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

Here is the caller graph for this function:

◆ get_objects_bounding_box()

BoundingBoxf3 Slic3r::GUI::PartPlate::get_objects_bounding_box ( )
4723{
4724 BoundingBoxf3 bbox;
4725 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
4726 {
4727 int obj_id = it->first;
4728 int instance_id = it->second;
4729
4730 if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
4731 {
4732 ModelObject* object = m_model->objects[obj_id];
4733 if ((instance_id >= 0) && (instance_id < object->instances.size()))
4734 {
4735 BoundingBoxf3 instance_bbox = object->instance_bounding_box(instance_id);
4736 bbox.merge(instance_bbox);
4737 }
4738 }
4739 }
4740 return bbox;
4741}

References m_model, Slic3r::BoundingBox3Base< PointType >::merge(), and obj_to_instance_set.

Referenced by Slic3r::CLI::run().

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

◆ get_objects_on_this_plate()

ModelObjectPtrs Slic3r::GUI::PartPlate::get_objects_on_this_plate ( )
4412 {
4413 ModelObjectPtrs objects_ptr;
4414 int obj_id;
4415 for (auto it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); it++) {
4416 obj_id = it->first;
4417 objects_ptr.push_back(m_model->objects[obj_id]);
4418 }
4419 return objects_ptr;
4420}
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13

References m_model, and obj_to_instance_set.

Referenced by Slic3r::GUI::PartPlateList::duplicate_plate(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::GUI::SelectMachineDialog::set_default(), Slic3r::GUI::SendMultiMachinePage::set_default(), Slic3r::GUI::SyncAmsInfoDialog::set_default(), and set_vase_mode_related_object_config().

Here is the caller graph for this function:

◆ get_origin()

◆ get_other_layers_print_sequence()

std::vector< LayerPrintSequence > Slic3r::GUI::PartPlate::get_other_layers_print_sequence ( ) const
5612{
5613 const ConfigOptionInts* other_layers_print_sequence_op = m_config.option<ConfigOptionInts>("other_layers_print_sequence");
5614 const ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option<ConfigOptionInt>("other_layers_print_sequence_nums");
5615 if (other_layers_print_sequence_op && other_layers_print_sequence_nums_op) {
5616 const std::vector<int>& print_sequence = other_layers_print_sequence_op->values;
5617 int sequence_nums = other_layers_print_sequence_nums_op->value;
5618 auto other_layers_seqs = Slic3r::get_other_layers_print_sequence(sequence_nums, print_sequence);
5619 return other_layers_seqs;
5620 }
5621 else
5622 return {};
5623}
zaa_minimize_perimeter_height print_sequence((ConfigOptionEnum< PrintOrder >, print_order))((ConfigOptionInts
std::vector< LayerPrintSequence > get_other_layers_print_sequence(int sequence_nums, const std::vector< int > &sequence)
Definition ParameterUtils.cpp:11

References Slic3r::get_other_layers_print_sequence(), m_config, Slic3r::print_sequence(), and Slic3r::ConfigOptionVector< int >::values.

Referenced by Slic3r::GUI::Plater::open_platesettings_dialog(), render_icons(), update_first_layer_print_sequence(), and update_first_layer_print_sequence_when_delete_filament().

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

◆ get_physical_extruder_by_filament_id()

int Slic3r::GUI::PartPlate::get_physical_extruder_by_filament_id ( const DynamicConfig & g_config,
int idx ) const
3512{
3513 const std::vector<int>& filament_map = get_real_filament_maps(g_config);
3514 if (filament_map.size() < idx)
3515 {
3516 return -1;
3517 }
3518
3519 const auto the_map = g_config.option<ConfigOptionInts>("physical_extruder_map");
3520 if (!the_map)
3521 {
3522 return -1;
3523 }
3524
3525 int zero_base_logical_idx = filament_map[idx - 1] - 1;
3526 return the_map->values[zero_base_logical_idx];
3527}

References Slic3r::filament_map(), get_real_filament_maps(), and Slic3r::ConfigBase::option().

Referenced by Slic3r::GUI::_get_used_nozzle_idxes(), and Slic3r::GUI::s_get_slicing_extuder_nozzles().

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

◆ get_plate_box()

BoundingBoxf3 Slic3r::GUI::PartPlate::get_plate_box ( )
inline
597{return get_build_volume();}
BoundingBoxf3 get_build_volume(bool use_share=false)
Definition PartPlate.cpp:5236

References get_build_volume().

Referenced by check_outside(), Slic3r::GUI::GLGizmoAlignment::get_parent_box(), and intersect_instance().

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

◆ get_plate_name()

◆ get_plate_wrapping_detection_area()

std::vector< Vec2d > Slic3r::GUI::PartPlate::get_plate_wrapping_detection_area ( ) const
443{
444 DynamicPrintConfig gconfig = wxGetApp().preset_bundle->printers.get_edited_preset().config;
445 ConfigOptionPoints *wrapping_exclude_area_opt = gconfig.option<ConfigOptionPoints>("wrapping_exclude_area");
446 if (wrapping_exclude_area_opt) {
447 std::vector<Vec2d> wrapping_area = wrapping_exclude_area_opt->values;
448 for (Vec2d& pt : wrapping_area) {
449 pt += Vec2d(m_origin.x(), m_origin.y());
450 }
451 return wrapping_area;
452 }
453
454 return std::vector<Vec2d>();
455}

References m_origin, Slic3r::ConfigBase::option(), and Slic3r::ConfigOptionVector< T >::values.

Referenced by render().

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

◆ get_print()

void Slic3r::GUI::PartPlate::get_print ( PrintBase ** print,
GCodeResult ** result,
int * index )
4362{
4364 *print = m_print;
4365
4366 if (result)
4367 *result = m_gcode_result;
4368
4369 if (index)
4370 *index = m_print_index;
4371
4372 return;
4373}
int m_print_index
Definition PartPlate.hpp:142
void print() const
Definition PartPlate.cpp:5741
@ ptFFF
Definition Config.hpp:231

References m_gcode_result, m_print, m_print_index, print(), printer_technology, and Slic3r::ptFFF.

Referenced by Slic3r::GUI::PartPlateList::delete_plate(), Slic3r::GUI::Plater::export_3mf(), Slic3r::GUI::PartPlateList::get_current_fff_print(), Slic3r::GUI::CalibUtils::process_and_store_3mf(), Slic3r::CLI::run(), Slic3r::GUI::Plater::select_plate(), and Slic3r::GUI::Plater::select_plate_by_hover_id().

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

◆ get_print_seq()

PrintSequence Slic3r::GUI::PartPlate::get_print_seq ( ) const
359{
360 std::string print_seq_key = "print_sequence";
361
362 if (m_config.has(print_seq_key)) {
363 PrintSequence print_seq = m_config.opt_enum<PrintSequence>(print_seq_key);
364 return print_seq;
365 }
366
368}
PrintSequence
Definition PrintConfig.hpp:310
@ ByDefault
Definition PrintConfig.hpp:313

References Slic3r::ByDefault, and m_config.

Referenced by get_real_print_seq(), Slic3r::GUI::Plater::open_platesettings_dialog(), Slic3r::GUI::GLCanvas3D::reload_scene(), render_icons(), Slic3r::CLI::run(), and set_print_seq().

Here is the caller graph for this function:

◆ get_real_filament_map_mode()

FilamentMapMode Slic3r::GUI::PartPlate::get_real_filament_map_mode ( const DynamicConfig & g_config,
bool * use_global_param = nullptr ) const
409{
410 auto mode = get_filament_map_mode();
411 if (FilamentMapMode::fmmDefault != mode) {
412 if (use_global_param) { *use_global_param = false; };
413 return mode;
414 }
415
416 auto g_mode = g_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode")->value;
417 if (use_global_param) { *use_global_param = true; }
418 return g_mode;
419}
FilamentMapMode get_filament_map_mode() const
Definition PartPlate.cpp:5766

References Slic3r::fmmDefault, get_filament_map_mode(), and Slic3r::ConfigBase::option().

Referenced by check_filament_printable(), Slic3r::GLVolumeCollection::check_outside_state(), Slic3r::GUI::get_applied_map_mode(), get_effective_exclusion_filament_maps(), Slic3r::CLI::run(), and Slic3r::GUI::set_arrange_polygon_bed_exclusion_extruders().

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

◆ get_real_filament_maps()

std::vector< int > Slic3r::GUI::PartPlate::get_real_filament_maps ( const DynamicConfig & g_config,
bool * use_global_param = nullptr ) const
385{
386 auto maps = get_filament_maps();
387 if (!maps.empty()) {
388 if (use_global_param) { *use_global_param = false; }
389 return maps;
390 }
391 auto g_maps = g_config.option<ConfigOptionInts>("filament_map")->values;
392 if (use_global_param) { *use_global_param = true; }
393 return g_maps;
394}

References get_filament_maps(), and Slic3r::ConfigBase::option().

Referenced by Slic3r::GUI::Plater::apply_background_progress(), check_filament_printable(), Slic3r::GLVolumeCollection::check_outside_state(), Slic3r::GUI::get_applied_map(), get_effective_exclusion_filament_maps(), get_logical_extruder_by_filament_id(), get_physical_extruder_by_filament_id(), Slic3r::GUI::Plater::open_filament_map_setting_dialog(), Slic3r::CLI::run(), Slic3r::GUI::Plater::select_plate(), Slic3r::GUI::Plater::select_plate_by_hover_id(), Slic3r::GUI::PartPlateList::set_default_wipe_tower_pos_for_plate(), and Slic3r::GUI::Plater::priv::update_background_process().

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

◆ get_real_filament_volume_maps()

std::vector< int > Slic3r::GUI::PartPlate::get_real_filament_volume_maps ( const DynamicConfig & g_config,
bool * use_global_param = nullptr ) const
397{
398 auto maps = get_filament_volume_maps();
399 if (!maps.empty()) {
400 if (use_global_param) { *use_global_param = false; }
401 return maps;
402 }
403 auto g_maps = g_config.option<ConfigOptionInts>("filament_volume_map")->values;
404 if (use_global_param) { *use_global_param = true; }
405 return g_maps;
406}
std::vector< int > get_filament_volume_maps() const
Definition PartPlate.cpp:5813

References get_filament_volume_maps(), and Slic3r::ConfigBase::option().

Referenced by Slic3r::GUI::get_applied_volume_map(), and Slic3r::GUI::Plater::open_filament_map_setting_dialog().

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

◆ get_real_print_seq()

PrintSequence Slic3r::GUI::PartPlate::get_real_print_seq ( bool * plate_same_as_global = nullptr) const
371{
372 PrintSequence global_print_seq = wxGetApp().global_print_sequence();
373 PrintSequence curr_plate_seq = get_print_seq();
374 if (curr_plate_seq == PrintSequence::ByDefault) {
375 curr_plate_seq = global_print_seq;
376 }
377
378 if(plate_same_as_global)
379 *plate_same_as_global = (curr_plate_seq == global_print_seq);
380
381 return curr_plate_seq;
382}
PrintSequence get_print_seq() const
Definition PartPlate.cpp:358

References Slic3r::ByDefault, and get_print_seq().

Referenced by Slic3r::GUI::Plater::priv::generate_first_layer_bbox(), Slic3r::GUI::init_arrange_params(), and Slic3r::GUI::ArrangeJob::prepare_all().

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

◆ get_shape()

const Pointfs & Slic3r::GUI::PartPlate::get_shape ( ) const
inline
577{ return m_shape; }

References m_shape.

Referenced by check_outside(), Slic3r::GLVolumeCollection::check_outside_state(), Slic3r::GUI::GCodeViewer::render_markers(), Slic3r::CLI::run(), and Slic3r::GUI::Plater::priv::update_print_volume_state().

Here is the caller graph for this function:

◆ get_shared_printable_polygon()

Polygon Slic3r::GUI::PartPlate::get_shared_printable_polygon ( ) const

References Slic3r::get_shared_poly(), m_extruder_areas, m_shape, and Slic3r::Polygon::new_scale().

Referenced by Slic3r::GUI::PartPlateList::set_default_wipe_tower_pos_for_plate().

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

◆ get_size()

Vec2d Slic3r::GUI::PartPlate::get_size ( ) const
inline
473{ return Vec2d(m_width, m_depth); }

References m_depth, and m_width.

Referenced by Slic3r::GUI::GLCanvas3D::get_wipe_tower_info().

Here is the caller graph for this function:

◆ get_slice_filaments_info()

const std::vector< FilamentInfo > & Slic3r::GUI::PartPlate::get_slice_filaments_info ( ) const
inline
501{ return slice_filaments_info; }

References slice_filaments_info.

◆ get_slice_result()

◆ get_slicing_percent()

float Slic3r::GUI::PartPlate::get_slicing_percent ( )
inline
690{ return m_slice_percent; }
float m_slice_percent
Definition PartPlate.hpp:137

References m_slice_percent.

Referenced by Slic3r::GUI::GLCanvas3D::_render_imgui_select_plate_toolbar(), and Slic3r::GUI::Plater::priv::on_slicing_update().

Here is the caller graph for this function:

◆ get_spiral_vase_mode()

bool Slic3r::GUI::PartPlate::get_spiral_vase_mode ( ) const
429{
430 std::string key = "spiral_mode";
431 if (m_config.has(key)) {
432 return m_config.opt_bool(key);
433 }
434 else {
435 DynamicPrintConfig* global_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
436 if (global_config->has(key))
437 return global_config->opt_bool(key);
438 }
439 return false;
440}

References Slic3r::ConfigOptionResolver::has(), m_config, and Slic3r::DynamicConfig::opt_bool().

Referenced by Slic3r::GUI::Plater::open_platesettings_dialog(), and set_spiral_vase_mode().

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

◆ get_temp_config_3mf_path()

std::string Slic3r::GUI::PartPlate::get_temp_config_3mf_path ( )
5477{
5478 if (m_temp_config_3mf_path.empty()) {
5479 boost::filesystem::path temp_path(m_model->get_backup_path("Metadata"));
5480 temp_path /= (boost::format(".%1%.%2%_config.3mf") % get_current_pid() %
5481 GLOBAL_PLATE_INDEX++).str();
5482 m_temp_config_3mf_path = temp_path.string();
5483
5484 }
5486}
static unsigned int GLOBAL_PLATE_INDEX
Definition PartPlate.cpp:129
std::string m_temp_config_3mf_path
Definition PartPlate.hpp:145
unsigned get_current_pid()
Definition utils.cpp:1480

References Slic3r::get_current_pid(), GLOBAL_PLATE_INDEX, m_model, and m_temp_config_3mf_path.

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

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

◆ get_tmp_gcode_path()

std::string Slic3r::GUI::PartPlate::get_tmp_gcode_path ( )
5466{
5467 if (m_tmp_gcode_path.empty()) {
5468 boost::filesystem::path temp_path(m_model->get_backup_path("Metadata"));
5469 temp_path /= (boost::format(".%1%.%2%.gcode") % get_current_pid() %
5470 GLOBAL_PLATE_INDEX++).str();
5471 m_tmp_gcode_path = temp_path.string();
5472 }
5473 return m_tmp_gcode_path;
5474}
std::string m_tmp_gcode_path
Definition PartPlate.hpp:144

References Slic3r::get_current_pid(), GLOBAL_PLATE_INDEX, m_model, and m_tmp_gcode_path.

Referenced by Slic3r::BackgroundSlicingProcess::process_fff(), Slic3r::CLI::run(), and Slic3r::GUI::Plater::send_gcode().

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

◆ get_used_filaments()

std::vector< int > Slic3r::GUI::PartPlate::get_used_filaments ( )
3657{
3658 std::vector<int> used_filaments;
3659 if (check_objects_empty_and_gcode3mf(used_filaments)) {
3660 return used_filaments;
3661 }
3662
3663 GCodeProcessorResult* result = get_slice_result();
3664 if (!result)
3665 return used_filaments;
3666
3667 std::set<int> used_extruders_set;
3668 PrintEstimatedStatistics& ps = result->print_statistics;
3669 for (const auto& item : ps.total_volumes_per_extruder)
3670 used_extruders_set.emplace(item.first + 1);
3671
3672 return std::vector(used_extruders_set.begin(), used_extruders_set.end());
3673}

References check_objects_empty_and_gcode3mf(), get_slice_result(), Slic3r::GCodeProcessorResult::print_statistics, and Slic3r::PrintEstimatedStatistics::total_volumes_per_extruder.

Referenced by Slic3r::GUI::_get_used_nozzle_idxes(), and Slic3r::GUI::s_get_slicing_extuder_nozzles().

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

◆ has_imex_multimaterial_conflict()

bool Slic3r::GUI::PartPlate::has_imex_multimaterial_conflict ( ) const
1270{
1271 // Mirror the logic Print::validate uses so the plater badge fires exactly when
1272 // slicing would be blocked — no false positives where the badge warns but the
1273 // slice goes through anyway. Delegates to imex_multicolor_block_reason() so
1274 // both paths share one source of truth.
1275 auto* pb = wxGetApp().preset_bundle;
1276 if (!pb) return false;
1277 const DynamicPrintConfig& printer_cfg = pb->printers.get_edited_preset().config;
1278 auto* is_imex_opt = printer_cfg.option<ConfigOptionBool>("is_imex");
1279 if (!is_imex_opt || !is_imex_opt->value) return false;
1280
1281 // Resolved, not the raw plate value: a plate left on Primary still slices in the
1282 // process preset's mode, and this badge has to fire wherever validate() would block.
1283 const std::string mode = get_effective_imex_mode();
1284 if (mode == kImexPrimaryMode) return false;
1285
1286 // Bails rather than defaulting through imex_cfg_int(), deliberately: this reports a routing
1287 // CONFLICT, so it must run on the printer's real configuration or not at all. With a defaulted
1288 // grid the conflict would be computed against a shape the printer does not have. A false
1289 // conflict warning is worse than staying quiet, so an absent key means "no answer" here --
1290 // unlike the geometry paths, where a defaulted value still describes a drawable bed.
1291 auto* tpg_opt = printer_cfg.option<ConfigOptionInt>("imex_tools_per_gantry");
1292 if (!tpg_opt) return false;
1293 // The map Print::apply() hands validate(): a printer that authors none gets the identity,
1294 // which the raw key's single default entry does not describe.
1296
1297 // Resolve the active mode's tools string from the printer config. Print::validate()
1298 // resolves the same name the same way and keeps going on an empty result -- the mixed
1299 // filament rule below does not depend on the roster -- so this must too, or the badge
1300 // goes quiet on exactly the plates the slicer refuses.
1301 const std::string active_tools_str = find_imex_mode(printer_cfg, mode).active_tools;
1302
1303 // Convert PartPlate's 1-based extruder list to the 0-based form the helper expects.
1304 //
1305 // get_extruders(true) expands a mixed slot into its physical components, which is right for
1306 // AMS mapping but wrong here: Print::validate counts the slot itself, so an expanded list
1307 // makes the badge disagree with the thing it is previewing. A plate holding one 2-component
1308 // blend reads as 2 filaments to the badge and 1 to validate -- the badge stays silent and
1309 // the slice is then refused, or it warns about "multi-material objects" on a plate the user
1310 // sees as single-colour. Undo the expansion so both sides count the same way.
1311 const std::vector<int> used_1b = get_extruders(true, /*expand_mixed_slots=*/false);
1312 std::vector<int> used_0b;
1313 used_0b.reserve(used_1b.size());
1314 for (int e : used_1b) if (e > 0) used_0b.push_back(e - 1);
1315
1316 // validate()'s first rule: a mixed filament is unsupported in a parallel mode outright,
1317 // ahead of any multi-color reasoning. The badge has to agree or it under-reports.
1318 if (auto* is_mixed_opt = wxGetApp().preset_bundle->project_config.option<ConfigOptionBools>("filament_is_mixed")) {
1319 const auto& is_mixed = is_mixed_opt->values;
1320 if (std::any_of(used_0b.begin(), used_0b.end(),
1321 [&](int slot) { return slot >= 0 && slot < (int) is_mixed.size() && is_mixed[slot]; }))
1322 return true;
1323 }
1324
1325 return !imex_multicolor_block_reason(mode, active_tools_str, tpg_opt->value, used_0b, pem).empty();
1326}
std::string imex_multicolor_block_reason(const std::string &parallel_mode, const std::string &active_tools_str, int tools_per_gantry, const std::vector< int > &used_filaments_0b, const ConfigOptionInts &pem)
Definition IMEXHelpers.cpp:104
ImexMode find_imex_mode(const ConfigBase &cfg, const std::string &name)
Definition IMEXHelpers.cpp:665
std::string active_tools
Definition IMEXHelpers.hpp:70

References Slic3r::ImexMode::active_tools, Slic3r::effective_physical_extruder_map(), Slic3r::find_imex_mode(), get_effective_imex_mode(), get_extruders(), Slic3r::imex_multicolor_block_reason(), Slic3r::kImexPrimaryMode, and Slic3r::ConfigBase::option().

Referenced by render_icons().

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

◆ has_printable_instances()

bool Slic3r::GUI::PartPlate::has_printable_instances ( )
4943{
4944 bool result = false;
4945
4946 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
4947 {
4948 int obj_id = it->first;
4949 int instance_id = it->second;
4950
4951 if (!valid_instance(obj_id, instance_id))
4952 continue;
4953
4954 ModelObject* object = m_model->objects[obj_id];
4955 ModelInstance* instance = object->instances[instance_id];
4956
4957 if ((instance->printable)&&(instance_outside_set.find(std::pair(obj_id, instance_id)) == instance_outside_set.end()))
4958 {
4959 result = true;
4960 break;
4961 }
4962 }
4963
4964 return result;
4965}

References instance_outside_set, m_model, obj_to_instance_set, Slic3r::ModelInstance::printable, and valid_instance().

Referenced by Slic3r::GUI::GLCanvas3D::_render_imgui_select_plate_toolbar(), is_slice_result_ready_for_export(), Slic3r::GUI::GCodeViewer::load_as_gcode(), Slic3r::GUI::Plater::priv::object_list_changed(), Slic3r::GUI::Plater::reslice(), Slic3r::GUI::Plater::priv::schedule_auto_reslice_if_needed(), Slic3r::GUI::Plater::select_plate(), Slic3r::GUI::Plater::select_plate_by_hover_id(), Slic3r::GUI::Plater::priv::set_current_panel(), and Slic3r::GUI::Plater::priv::trigger_auto_reslice_now().

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

◆ has_spiral_mode_config()

bool Slic3r::GUI::PartPlate::has_spiral_mode_config ( ) const
423{
424 std::string key = "spiral_mode";
425 return m_config.has(key);
426}

References m_config.

Referenced by Slic3r::GUI::Plater::open_platesettings_dialog(), and render_icons().

Here is the caller graph for this function:

◆ icon_scale_factor()

float Slic3r::GUI::PartPlate::icon_scale_factor ( ) const
private
1704{
1705 const BoundingBoxf bed_ext = get_extents(m_shape);
1706 const double by_depth = bed_ext.size().y() / 200.;
1707 const double by_gap = bed_ext.size().x() * LOGICAL_PART_PLATE_GAP / (PARTPLATE_ICON_SIZE + 2 * PARTPLATE_ICON_GAP_LEFT);
1708 return float(std::min(by_depth, by_gap));
1709}
static const double LOGICAL_PART_PLATE_GAP
Definition PartPlate.cpp:131

References Slic3r::get_extents(), LOGICAL_PART_PLATE_GAP, m_shape, PARTPLATE_ICON_GAP_LEFT, PARTPLATE_ICON_SIZE, and Slic3r::BoundingBoxBase< PointType, APointsType >::size().

Referenced by calc_vertex_for_icons(), calc_vertex_for_number(), calc_vertex_for_plate_name_edit_icon(), and generate_plate_name_texture().

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

◆ id()

ObjectID Slic3r::ObjectBase::id ( ) const
inlineinherited
69{ return m_id; }

References m_id.

Referenced by Slic3r::CutObjectBase::CutObjectBase(), Slic3r::Model::Model(), Slic3r::ModelInstance::ModelInstance(), Slic3r::ModelMaterial::ModelMaterial(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelObject::ModelObject(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), Slic3r::ModelVolume::ModelVolume(), ObjectBase(), Slic3r::PrintBase::SlicingStatus::SlicingStatus(), Slic3r::PrintBase::SlicingStatus::SlicingStatus(), Slic3r::_BBS_3MF_Exporter::_add_cut_information_file_to_archive(), Slic3r::_BBS_3MF_Exporter::_add_model_config_file_to_archive(), Slic3r::_BBS_3MF_Exporter::_add_slice_info_config_file_to_archive(), Slic3r::GUI::Plater::priv::actualize_slicing_warnings(), Slic3r::ModelObjectStatusDB::add(), Slic3r::ModelObjectStatusDB::add_if_new(), Slic3r::Model::add_object(), Slic3r::append_and_translate(), Slic3r::SLAPrint::apply(), Slic3r::GUI::calc_distance(), Slic3r::GUI::calc_surface_offset(), Slic3r::check_model_ids_equal(), Slic3r::check_model_ids_validity(), Slic3r::GUI::GLGizmoTextureDisplacement::close_image_adjust(), Slic3r::Model::collect_reusable_objects(), Slic3r::ModelObject::convert_units(), copy_id(), Slic3r::PrintObjectStatusDB::count(), anonymous_namespace{RaycastManager.cpp}::create_key(), Slic3r::GUI::create_meshes(), anonymous_namespace{EmbossJob.cpp}::create_volume(), Slic3r::GUI::Emboss::create_volume_sources(), Slic3r::GUI::GLGizmoPainterBase::data_changed(), Slic3r::GCode::do_export(), Slic3r::GUI::PartPlate::duplicate_all_instance(), Slic3r::GUI::PartPlateList::duplicate_plate(), Slic3r::GUI::PartPlate::estimate_wipe_tower_footprint(), Slic3r::Print::export_cached_data(), Slic3r::GUI::Plater::export_stl(), Slic3r::find_volume_extents(), Slic3r::PreciseSeam::detail::fragment_location(), Slic3r::GUI::Plater::priv::generate_first_layer_bbox(), Slic3r::ModelObjectStatusDB::get(), Slic3r::Model::get_backup_path(), Slic3r::GUI::GLCanvas3D::get_empty_cells(), Slic3r::ModelInstance::get_labeled_id(), Slic3r::GUI::get_model_volume(), Slic3r::PrintObjectStatusDB::get_range(), Slic3r::GUI::get_selected_volume(), Slic3r::GUI::get_volume(), Slic3r::CutObjectBase::has_same_id(), Slic3r::UndoRedo::StackImpl::immutable_object_id_impl(), Slic3r::GUI::GLGizmoFdmSupports::init_print_instance(), Slic3r::CutObjectBase::is_equal(), Slic3r::GUI::GLGizmoSVG::is_svg_object(), Slic3r::ModelVolume::is_the_only_one_part(), Slic3r::GUI::IMSlider::IsNewPrint(), Slic3r::ModelObject::load(), load_and_construct(), Slic3r::Print::load_cached_data(), Slic3r::GLVolumeCollection::load_object_auxiliary(), Slic3r::GLVolumeCollection::load_object_volume(), Slic3r::GUI::GCodeViewer::load_shells(), Slic3r::UndoRedo::StackImpl::load_snapshot(), Slic3r::GUI::GLCanvas3D::CenterOfMass::model_markers(), Slic3r::model_property_changed(), Slic3r::model_volume_list_changed(), Slic3r::model_volume_list_copy_configs(), Slic3r::ModelConfigObject::object_id_and_timestamp_match(), Slic3r::ObjectWithTimestamp::object_id_and_timestamp_match(), Slic3r::GUI::GLGizmoEmboss::on_mouse_change_selection(), Slic3r::GUI::GLGizmoSimplify::on_render_input_window(), Slic3r::GUI::GLGizmoTextureDisplacement::open_image_adjust(), Slic3r::CutObjectBase::operator<(), Slic3r::Model::operator=(), Slic3r::ModelObject::operator=(), Slic3r::ModelObject::operator=(), Slic3r::CutObjectBase::operator==(), Slic3r::outer_inner_brim_area(), Slic3r::GUI::GLGizmoTextureDisplacement::painted_area_mm2(), Slic3r::GUI::GLGizmoCut3D::perform_cut(), anonymous_namespace{GLGizmoEmboss.cpp}::prepare_volumes_to_slice(), Slic3r::GUI::GLGizmoTextureDisplacement::preview_part(), Slic3r::GCode::process_layer(), Slic3r::GUI::NotificationManager::push_slicing_warning_notification(), Slic3r::GUI::GLGizmoTextureDisplacement::queue_preview_job(), Slic3r::GUI::queue_texture_displacement_debug(), Slic3r::GUI::GLGizmoEmboss::re_emboss(), Slic3r::GUI::GLGizmoTextureDisplacement::rebuild_other_paint_overlay(), Slic3r::GUI::GLGizmoTextureDisplacement::rebuild_painted_colors(), Slic3r::GUI::GLCanvas3D::reload_scene(), Slic3r::_BBS_Backup_Manager::remove_backup(), Slic3r::Model::remove_backup_path_if_exist(), Slic3r::GUI::GLGizmoTextureDisplacement::render_image_adjust_window(), Slic3r::CLI::run(), Slic3r::GUI::GLCanvas3D::LayersEditing::select_object(), Slic3r::ModelMaterial::serialize(), Slic3r::Model::set_backup_path(), Slic3r::GUI::GLGizmoBrimEars::set_brim_data(), Slic3r::GUI::PartPlate::set_hover_id(), Slic3r::GUI::GLGizmoEmboss::set_volume_by_selection(), Slic3r::GUI::GLGizmoSVG::set_volume_by_selection(), Slic3r::sla_instances(), Slic3r::slices_to_regions(), Slic3r::ModelObject::split(), anonymous_namespace{EmbossJob.cpp}::start_create_volume_on_surface_job(), anonymous_namespace{SurfaceDrag.cpp}::start_dragging(), Slic3r::GUI::Emboss::start_update_volume(), Slic3r::UndoRedo::StackImpl::take_snapshot(), Slic3r::GUI::texture_displacement_bake_volume(), Slic3r::GUI::GLGizmoPainterBase::update_contours(), anonymous_namespace{EmbossJob.cpp}::update_name_in_list(), Slic3r::GUI::ObjectList::update_name_in_model(), Slic3r::GUI::update_object_cut_id(), Slic3r::GUI::GLGizmoTextureDisplacement::v2_recommendation(), Slic3r::verify_update_print_object_regions(), wipe_tower_instance_id, and wipe_tower_object_id.

◆ imex_collision_zones()

const std::vector< BoundingBoxf3 > & Slic3r::GUI::PartPlate::imex_collision_zones ( ) const
inline
643{ return m_imex_collision_zones; }

References m_imex_collision_zones.

◆ imex_ghost_composite_id_for_head()

int Slic3r::GUI::PartPlate::imex_ghost_composite_id_for_head ( int physical_head)
inlinestatic
303 {
304 return IMEX_GHOST_COMPOSITE_ID_BASE - physical_head;
305 }
static constexpr int IMEX_GHOST_COMPOSITE_ID_BASE
Definition PartPlate.hpp:293

References IMEX_GHOST_COMPOSITE_ID_BASE.

Referenced by calc_imex_ghosts().

Here is the caller graph for this function:

◆ imex_ghost_head_from_composite_id()

int Slic3r::GUI::PartPlate::imex_ghost_head_from_composite_id ( int object_id)
inlinestatic
300 {
301 return IMEX_GHOST_COMPOSITE_ID_BASE - object_id;
302 }

References IMEX_GHOST_COMPOSITE_ID_BASE.

Referenced by Slic3r::GUI::GLCanvas3D::_picking_pass_imex_ghosts(), update_imex_ghost_colors(), and update_imex_ghost_transforms().

Here is the caller graph for this function:

◆ imex_hull_violates()

bool Slic3r::GUI::PartPlate::imex_hull_violates ( const Polygon & hull) const
1175{
1178}
bool imex_hull_violates_zones(const std::vector< BoundingBoxf3 > &zones, const Polygon &hull)
Definition IMEXHelpers.cpp:703

References Slic3r::imex_hull_violates_zones(), m_imex_collision_zones, and m_imex_secondary_zone_boxes.

Referenced by check_outside(), and imex_placement_violation().

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

◆ imex_placement_violation()

PartPlate::ImexPlacementViolation Slic3r::GUI::PartPlate::imex_placement_violation ( )
1251{
1255 for (const auto& pr : obj_to_instance_set) {
1256 int obj_id = pr.first;
1257 int instance_id = pr.second;
1258 if (!valid_instance(obj_id, instance_id))
1259 continue;
1260 ModelInstance* instance = m_model->objects[obj_id]->instances[instance_id];
1261 if (imex_hull_violates(instance->convex_hull_2d()))
1263 }
1267}
Polygon imex_wipe_tower_hull() const
Definition PartPlate.cpp:1182
@ PrimeTower
Definition PartPlate.hpp:625
@ Object
Definition PartPlate.hpp:625

References Slic3r::ModelInstance::convex_hull_2d(), ensure_imex_zones(), imex_hull_violates(), imex_wipe_tower_hull(), m_imex_collision_zones, m_imex_secondary_zone_boxes, m_model, None, obj_to_instance_set, Object, PrimeTower, and valid_instance().

Referenced by Slic3r::GUI::anonymous_namespace{Plater.cpp}::imex_placement_error().

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

◆ imex_primary_zone()

std::optional< BoundingBoxf > Slic3r::GUI::PartPlate::imex_primary_zone ( )
inline

References ensure_imex_zones(), and m_imex_primary_zone_box.

Here is the call graph for this function:

◆ imex_wipe_tower_hull()

Polygon Slic3r::GUI::PartPlate::imex_wipe_tower_hull ( ) const
1183{
1184 // The estimate walks m_model->objects, and this runs even on an empty plate. The
1185 // m_print arm is dead since the estimate stopped reading it; dropping it would newly
1186 // validate plates this currently skips.
1187 if (!m_plater || !m_print || !m_model)
1188 return Polygon();
1189 PresetBundle* preset_bundle = wxGetApp().preset_bundle;
1190 if (!preset_bundle)
1191 return Polygon();
1192
1193 const DynamicPrintConfig& print_cfg = preset_bundle->prints.get_edited_preset().config;
1194
1195 // Whether a tower is PRINTED is normalize_fdm_2's rule, shared with the slicer through
1196 // prime_tower_is_printed() rather than re-derived here - re-deriving it is what let this
1197 // validate a tower the slicer had already cancelled. Do not substitute the footprint
1198 // estimate: it never reads enable_prime_tower or print_sequence, so it still sizes a tower
1199 // for a plate that switched the tower off or prints by object, which would hard-block a
1200 // plate with nothing drawn on screen to move.
1201 //
1202 // Counts are the ones normalize_fdm_2 is handed: filament slots as authored, so a mixed
1203 // slot counts once, and distinct objects rather than instances. filament_is_mixed is a
1204 // project option, hence read separately.
1205 const auto* mixed_opt = preset_bundle->project_config.option<ConfigOptionBools>("filament_is_mixed");
1206 const bool has_mixed = mixed_opt != nullptr && has_any_mixed_filament(mixed_opt->values);
1207 std::set<int> plate_objects;
1208 for (const auto& pr : obj_to_instance_set)
1209 plate_objects.insert(pr.first);
1210 if (!prime_tower_is_printed(print_cfg, (int) get_extruders(true, /*expand_mixed_slots=*/false).size(),
1211 (int) plate_objects.size(), has_mixed))
1212 return Polygon();
1213
1214 // The estimate's floor counts what is purged, so a mixed slot counts as its components here.
1215 const int plate_extruder_size = (int) get_extruders(true).size();
1216
1217 Vec3d wt_pos, wt_size;
1218 // full_config(), not the print preset: wipe_tower_x/y are project options the estimate
1219 // dereferences unchecked. apply_extruder=false, so the per-filament arrays arrive as the
1220 // concatenation of each preset's declared variants rather than one entry per filament.
1221 // That matters now: filament_minimal_purge_on_wipe_tower became variant-keyed upstream and
1222 // WipeTower2::extract_wipe_volumes indexes it by raw filament slot, so a multi-variant
1223 // filament preset on a single-extruder-multi-material machine would estimate the tower
1224 // from the wrong column. No shipped preset pairs the two today.
1225 // plate_extruder_size is a floor, not an override; the scene passes 0, and both counts
1226 // come from the same object walk.
1227 arrangement::ArrangePolygon ap = estimate_wipe_tower_polygon(preset_bundle->full_config(false), m_plate_index, wt_pos, wt_size, plate_extruder_size);
1228 if (wt_size(0) <= 0. || wt_size(1) <= 0. || ap.poly.contour.points.empty())
1229 return Polygon();
1230
1231 // Only the estimated box and brim are validated. The depth is approximate, so a sliced
1232 // tower can exceed it (the true footprint is Print::first_layer_wipe_tower_corners(),
1233 // post-slice only). A Type2 cone's bulge is already in the margin the hull is built
1234 // from - do not add a second allowance. Object brim, skirt and supports are unvalidated
1235 // here too.
1236 Polygon hull = ap.poly.contour;
1237
1238 // The estimate is an axis-aligned box, but the real tower is rotated about its anchor
1239 // corner before placement, so without this a rotated footprint escapes the hull.
1240 if (const auto* rot = print_cfg.option<ConfigOptionFloat>("wipe_tower_rotation_angle");
1241 rot && rot->value != 0.)
1242 hull.rotate(Geometry::deg2rad(rot->value),
1243 Point(scaled(wt_pos.x()), scaled(wt_pos.y())));
1244
1245 // Plate-local mm to plate-list coordinates, which the zones and instance hulls use.
1246 hull.translate(Point(scaled(m_origin.x()), scaled(m_origin.y())));
1247 return hull;
1248}
arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig &config, int plate_index, Vec3d &wt_pos, Vec3d &wt_size, int plate_extruder_size=0, bool use_global_objects=false, WipeTowerRelocation *relocation=nullptr) const
Definition PartPlate.cpp:4065
bool prime_tower_is_printed(const ConfigBase &config, int used_filaments, int num_objects, bool has_mixed_filament)
Definition WipeTowerEstimate.cpp:40

References Slic3r::Preset::config, Slic3r::ExPolygon::contour, Slic3r::Geometry::deg2rad(), estimate_wipe_tower_polygon(), Slic3r::PresetBundle::full_config(), Slic3r::PresetCollection::get_edited_preset(), get_extruders(), Slic3r::has_any_mixed_filament(), m_model, m_origin, m_plate_index, m_plater, m_print, obj_to_instance_set, Slic3r::ConfigBase::option(), Slic3r::MultiPoint::points, Slic3r::arrangement::ArrangePolygon::poly, Slic3r::prime_tower_is_printed(), Slic3r::PresetBundle::prints, Slic3r::PresetBundle::project_config, Slic3r::MultiPoint::rotate(), Slic3r::scaled(), Slic3r::MultiPoint::translate(), and Slic3r::ConfigOptionSingle< T >::value.

Referenced by imex_placement_violation().

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

◆ init()

void Slic3r::GUI::PartPlate::init ( )
private
249{
250 m_locked = false;
251 m_ready_for_slice = true;
252 m_slice_result_valid = false;
253 m_slice_percent = -1.0f; // ORCA create new plates with negative values or it will take "slicing" role on toolbar
254 // condition for sliced / slicing -- if (plate_list.get_plate(i)->get_slicing_percent() < 0.0f)
255 m_hover_id = -1;
256 m_selected = false;
257 //m_quadric = ::gluNewQuadric();
258 //if (m_quadric != nullptr)
259 // ::gluQuadricDrawStyle(m_quadric, GLU_FILL);
260
261 m_print_index = -1;
262 m_print = nullptr;
263 m_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode", true)->value = FilamentMapMode::fmmAutoForFlush;
264}
bool m_selected
Definition PartPlate.hpp:207
int m_hover_id
Definition PartPlate.hpp:206
bool m_slice_result_valid
Definition PartPlate.hpp:135
bool m_locked
Definition PartPlate.hpp:133
@ fmmAutoForFlush
Definition PrintConfig.hpp:633

References Slic3r::fmmAutoForFlush, m_config, m_hover_id, m_locked, m_print, m_print_index, m_ready_for_slice, m_selected, m_slice_percent, and m_slice_result_valid.

Referenced by PartPlate(), and PartPlate().

Here is the caller graph for this function:

◆ intersect_instance()

bool Slic3r::GUI::PartPlate::intersect_instance ( int obj_id,
int instance_id,
BoundingBoxf3 * bounding_box = nullptr )
4601{
4602 bool result = false;
4603
4604 if (!valid_instance(obj_id, instance_id))
4605 {
4606 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": plate_id %1%, invalid obj_id %2%, instance_id %3%") % m_plate_index % obj_id % instance_id;
4607 return false;
4608 }
4609
4610 if (m_printable)
4611 {
4612 ModelObject* object = m_model->objects[obj_id];
4613 ModelInstance* instance = object->instances[instance_id];
4614 BoundingBoxf3 instance_box = bounding_box? *bounding_box: object->instance_convex_hull_bounding_box(instance_id);
4615 result = get_plate_box().intersects(instance_box);
4616 }
4617 else
4618 {
4619 result = is_left_top_of(obj_id, instance_id);
4620 }
4621
4622 return result;
4623}
bool intersects(const BoundingBox3Base< PointType > &other) const
Definition BoundingBox.hpp:170
bool is_left_top_of(int obj_id, int instance_id)
Definition PartPlate.cpp:4626

References Slic3r::bounding_box(), get_plate_box(), Slic3r::BoundingBox3Base< PointType >::intersects(), is_left_top_of(), m_model, m_plate_index, m_printable, and valid_instance().

Referenced by Slic3r::GUI::PartPlateList::construct_objects_list_for_new_plate(), Slic3r::GUI::Selection::get_volume_idxs_from_plate(), move_instances_to(), Slic3r::GUI::PartPlateList::notify_instance_update(), Slic3r::GUI::ArrangeJob::prepare_partplate(), Slic3r::GUI::PartPlateList::reload_all_objects(), and Slic3r::CLI::run().

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

◆ intersects()

bool Slic3r::GUI::PartPlate::intersects ( const BoundingBoxf3 & bb) const
5299{
5300 // Allow the objects to protrude below the print bed
5301 BoundingBoxf3 print_volume(Vec3d(m_bounding_box.min(0), m_bounding_box.min(1), 0.0), Vec3d(m_bounding_box.max(0), m_bounding_box.max(1), 1e3));
5302 print_volume.min(2) = -1e10;
5303 print_volume.min(0) -= Slic3r::BuildVolume::BedEpsilon;
5304 print_volume.min(1) -= Slic3r::BuildVolume::BedEpsilon;
5305 print_volume.max(0) += Slic3r::BuildVolume::BedEpsilon;
5306 print_volume.max(1) += Slic3r::BuildVolume::BedEpsilon;
5307 this->open_belt_y(print_volume);
5308 return print_volume.intersects(bb);
5309}

References Slic3r::BuildVolume::BedEpsilon, Slic3r::BoundingBox3Base< PointType >::intersects(), m_bounding_box, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, and open_belt_y().

Referenced by Slic3r::GUI::PartPlateList::find_instance(), and Slic3r::GUI::Selection::paste_objects_from_clipboard().

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

◆ invalidate_exclusion_volume_preview()

void Slic3r::GUI::PartPlate::invalidate_exclusion_volume_preview ( )
2429{
2431}
bool m_exclusion_volume_preview_dirty
Definition PartPlate.hpp:171

References m_exclusion_volume_preview_dirty.

Referenced by add_instance(), clear(), clear_filament_map(), duplicate_all_instance(), Slic3r::GUI::PartPlateList::duplicate_plate(), load(), remove_instance(), set_filament_map_mode(), set_filament_maps(), set_pos_and_size(), set_print(), set_shape(), translate_all_instance(), update_instance_exclude_status(), and update_object_index().

Here is the caller graph for this function:

◆ invalidate_imex_ghosts()

void Slic3r::GUI::PartPlate::invalidate_imex_ghosts ( )
inline
419{ m_imex_ghost_cache_key = "\x01"; }

References m_imex_ghost_cache_key.

◆ invalidate_plate_name_texture()

void Slic3r::GUI::PartPlate::invalidate_plate_name_texture ( )
private
4328{
4329 m_plate_name_edit_icon.mesh_raycaster.reset();
4330
4331 auto canvas = (m_plater != nullptr) ? m_plater->get_view3D_canvas3D() : nullptr;
4332 if (canvas != nullptr) {
4333 canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
4334 canvas->set_as_dirty();
4335 }
4336}

References Slic3r::GUI::SceneRaycaster::Bed, m_plate_name_edit_icon, m_plater, and picking_id_component().

Referenced by clear(), set_plate_name(), and set_shape().

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

◆ is_all_instances_unprintable()

bool Slic3r::GUI::PartPlate::is_all_instances_unprintable ( )
4968{
4969 bool result = true;
4970
4971 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
4972 int obj_id = it->first;
4973 int instance_id = it->second;
4974
4975 if (!valid_instance(obj_id, instance_id))
4976 continue;
4977
4978 ModelObject * object = m_model->objects[obj_id];
4979 ModelInstance *instance = object->instances[instance_id];
4980
4981 if ((instance->printable)) {
4982 result = false;
4983 break;
4984 }
4985 }
4986
4987 return result;
4988}

References m_model, obj_to_instance_set, Slic3r::ModelInstance::printable, and valid_instance().

Here is the call graph for this function:

◆ is_apply_result_invalid()

bool Slic3r::GUI::PartPlate::is_apply_result_invalid ( ) const
inline
651 {
652 return m_apply_invalid;
653 }

References m_apply_invalid.

◆ is_imex_ghost_composite_id()

bool Slic3r::GUI::PartPlate::is_imex_ghost_composite_id ( int object_id)
inlinestatic

◆ is_left_top_of()

bool Slic3r::GUI::PartPlate::is_left_top_of ( int obj_id,
int instance_id )
4627{
4628 bool result = false;
4629
4630 if (!valid_instance(obj_id, instance_id))
4631 {
4632 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(": plate_id %1%, invalid obj_id %2%, instance_id %3%") % m_plate_index % obj_id % instance_id;
4633 return false;
4634 }
4635
4636 ModelObject* object = m_model->objects[obj_id];
4637 ModelInstance* instance = object->instances[instance_id];
4638 std::pair<int, int> pair(obj_id, instance_id);
4639 BoundingBoxf3 instance_box = object->instance_convex_hull_bounding_box(instance_id);
4640
4641 result = (m_origin.x() <= instance_box.min.x()) && (m_origin.y() >= instance_box.min.y());
4642 return result;
4643}

References m_model, m_origin, m_plate_index, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, and valid_instance().

Referenced by intersect_instance().

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

◆ is_locked()

bool Slic3r::GUI::PartPlate::is_locked ( ) const
inline
611{ return m_locked; }

References m_locked.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_locked(), Slic3r::GUI::PartPlateList::clear(), Slic3r::GUI::ArrangeJob::prepare_all(), Slic3r::GUI::ArrangeJob::prepare_imex_zones(), Slic3r::GUI::ArrangeJob::prepare_partplate(), Slic3r::GUI::OrientJob::prepare_partplate(), and render_icons().

Here is the caller graph for this function:

◆ is_printable()

bool Slic3r::GUI::PartPlate::is_printable ( ) const
inline
615{ return m_printable; }

References m_printable.

◆ is_slice_result_ready_for_export()

bool Slic3r::GUI::PartPlate::is_slice_result_ready_for_export ( )
inline
678 {
680 }
bool has_printable_instances()
Definition PartPlate.cpp:4942
bool is_slice_result_ready_for_print() const
Definition PartPlate.hpp:666

References has_printable_instances(), and is_slice_result_ready_for_print().

Referenced by Slic3r::GUI::MainFrame::get_enable_print_status().

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

◆ is_slice_result_ready_for_print()

bool Slic3r::GUI::PartPlate::is_slice_result_ready_for_print ( ) const
inline
667 {
668 bool result = m_slice_result_valid;
669 if (result)
670 result = m_gcode_result ?
671 (!m_gcode_result->toolpath_outside && m_gcode_result->gcode_check_result.error_code == 0 && !m_gcode_result->filament_printable_reuslt.has_value()) :
672 false;// && !m_gcode_result->conflict_result.has_value() gcode conflict can also print
673 return result;
674 }

References m_gcode_result, and m_slice_result_valid.

Referenced by Slic3r::GUI::GLCanvas3D::_render_imgui_select_plate_toolbar(), Slic3r::GUI::MainFrame::can_export_gcode(), Slic3r::GUI::MainFrame::get_enable_print_status(), and is_slice_result_ready_for_export().

Here is the caller graph for this function:

◆ is_slice_result_valid()

◆ is_valid_gcode_file()

bool Slic3r::GUI::PartPlate::is_valid_gcode_file ( )
4401{
4402 if (get_gcode_filename().empty())
4403 return false;
4404 boost::filesystem::path gcode_file(m_gcode_result->filename);
4405 if (!boost::filesystem::exists(gcode_file)) {
4406 BOOST_LOG_TRIVIAL(info) << "invalid gcode file, file is missing, file = " << m_gcode_result->filename;
4407 return false;
4408 }
4409 return true;
4410}
bool empty()
Definition PartPlate.hpp:565
std::string get_gcode_filename()
Definition PartPlate.cpp:4392

References empty(), get_gcode_filename(), and m_gcode_result.

Referenced by Slic3r::GUI::PrintJob::process(), Slic3r::GUI::SendJob::process(), and Slic3r::GUI::SelectMachineDialog::update_show_status().

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

◆ load()

template<class Archive>
void Slic3r::GUI::PartPlate::load ( Archive & ar)
inline
733 {
734 std::vector<std::pair<int, int>> objects_and_instances;
735 std::vector<std::pair<int, int>> instances_outside;
736
738
739 for (std::vector<std::pair<int, int>>::iterator it = objects_and_instances.begin(); it != objects_and_instances.end(); ++it)
740 obj_to_instance_set.insert(std::pair(it->first, it->second));
741
742 for (std::vector<std::pair<int, int>>::iterator it = instances_outside.begin(); it != instances_outside.end(); ++it)
743 instance_outside_set.insert(std::pair(it->first, it->second));
744
746 }

References instance_outside_set, invalidate_exclusion_volume_preview(), m_apply_invalid, m_config, m_depth, m_height, m_locked, m_name, m_origin, m_plate_index, m_print_index, m_printable, m_ready_for_slice, m_selected, m_slice_result_valid, m_tmp_gcode_path, m_width, and obj_to_instance_set.

Here is the call graph for this function:

◆ load_and_construct()

template<class Archive>
void Slic3r::ObjectBase::load_and_construct ( Archive & ar,
cereal::construct< ObjectBase > & construct )
inlinestaticprivateinherited
109{ ObjectID id; ar(id); construct(id); }

References id().

Here is the call graph for this function:

◆ load_gcode_from_file()

int Slic3r::GUI::PartPlate::load_gcode_from_file ( const std::string & filename)
5490{
5491 int ret = 0;
5492
5493 // process gcode
5494 auto& preset_bundle = wxGetApp().preset_bundle;
5495 std::vector<int> filament_maps = this->get_filament_maps();
5496 // Inject the plate's volume map (or the per-extruder defaults) exactly like the apply-time
5497 // composition, so the config applied over the loaded slice result matches the next
5498 // background-process apply and does not invalidate the embedded g-code.
5499 std::vector<int> f_volume_maps = this->get_filament_volume_maps();
5500 if (f_volume_maps.empty()) {
5501 f_volume_maps = preset_bundle->get_default_nozzle_volume_types_for_filaments(filament_maps);
5502 }
5503 DynamicPrintConfig full_config = preset_bundle->full_config(false, filament_maps, f_volume_maps);
5504 full_config.apply(m_config, true);
5505 m_print->apply(*m_model, full_config, false);
5506 //BBS: need to apply two times, for after the first apply, the m_print got its object,
5507 //which will affect the config when new_full_config.normalize_fdm(used_filaments);
5508 m_print->apply(*m_model, full_config, false);
5509
5510 // BBS: use backup path to save temp gcode
5511 // auto path = get_tmp_gcode_path();
5512 // if (boost::filesystem::exists(boost::filesystem::path(path))) {
5513 // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": file %1% exists, delete it firstly") % filename.c_str();
5514 // boost::nowide::remove(path.c_str());
5515 //}
5516
5517 // std::error_code error = rename_file(filename, path);
5518 // if (error) {
5519 // BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("Failed to rename the output G-code file from %1% to %2%, error code %3%") % filename.c_str() % path.c_str() %
5520 //error.message(); return -1;
5521 //}
5522 if (boost::filesystem::exists(filename)) {
5523 assert(m_tmp_gcode_path.empty());
5524 m_tmp_gcode_path = filename;
5525 m_gcode_result->filename = filename;
5526 m_print->set_gcode_file_ready();
5527
5529
5530 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": found valid gcode file %1%") % filename.c_str();
5531 }
5532 else {
5533 BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": can not find gcode file %1%") % filename.c_str();
5534 ret = -1;
5535 }
5536
5537 m_ready_for_slice = true;
5538 return ret;
5539}

References Slic3r::ConfigBase::apply(), get_filament_maps(), get_filament_volume_maps(), m_config, m_gcode_result, m_model, m_print, m_ready_for_slice, m_tmp_gcode_path, and update_slice_result_valid_state().

Here is the call graph for this function:

◆ load_pattern_box_data()

int Slic3r::GUI::PartPlate::load_pattern_box_data ( std::string filename)
5585{
5586 try {
5587 nlohmann::json j;
5588 boost::nowide::ifstream ifs(filename);
5589 ifs >> j;
5590
5591 PlateBBoxData bbox_data;
5592 bbox_data.from_json(j);
5593 cali_bboxes_data = bbox_data;
5594 return 0;
5595 }
5596 catch(std::exception &ex) {
5597 BOOST_LOG_TRIVIAL(trace) << boost::format("catch an exception %1%")%ex.what();
5598 return -1;
5599 }
5600}
PlateBBoxData cali_bboxes_data
Definition PartPlate.hpp:435
void trace(unsigned int level, const char *message)
Definition utils.cpp:247

References cali_bboxes_data, Slic3r::PlateBBoxData::from_json(), and Slic3r::trace().

Here is the call graph for this function:

◆ load_pattern_thumbnail_data()

int Slic3r::GUI::PartPlate::load_pattern_thumbnail_data ( std::string filename)
5564{
5565 /*bool result = true;
5566 wxImage img;
5567 result = load_image(filename, img);
5568 if (result) {
5569 cali_thumbnail_data.set(img.GetWidth(), img.GetHeight());
5570 for (int i = 0; i < img.GetWidth() * img.GetHeight(); i++) {
5571 memcpy(&cali_thumbnail_data.pixels[4 * i], (unsigned char*)(img.GetData() + 3 * i), 3);
5572 if (img.HasAlpha()) {
5573 cali_thumbnail_data.pixels[4 * i + 3] = *(unsigned char*)(img.GetAlpha() + i);
5574 }
5575 }
5576 }
5577 else {
5578 return -1;
5579 }*/
5580 return 0;
5581}

◆ load_render_colors()

void Slic3r::GUI::PartPlate::load_render_colors ( )
static
217{
223}
@ RenderCol_Plate_Line_Bottom
Definition GUI_Colors.hpp:14
@ RenderCol_Plate_Selected
Definition GUI_Colors.hpp:11
@ RenderCol_Plate_Default
Definition GUI_Colors.hpp:12
@ RenderCol_Plate_Unselected
Definition GUI_Colors.hpp:10
@ RenderCol_Plate_Line_Top
Definition GUI_Colors.hpp:13
static ImVec4 to_ImVec4(const ColorRGB &color)
Definition ImGuiWrapper.cpp:1053
static ColorRGBA UNSELECT_COLOR
Definition PartPlate.hpp:308
static ColorRGBA LINE_TOP_COLOR
Definition PartPlate.hpp:312
static ColorRGBA DEFAULT_COLOR
Definition PartPlate.hpp:310
static ColorRGBA SELECT_COLOR
Definition PartPlate.hpp:307
static ColorRGBA LINE_BOTTOM_COLOR
Definition PartPlate.hpp:311
static ImVec4 colors[RenderCol_Count]
Definition GUI_Colors.hpp:40

References Slic3r::RenderColor::colors, DEFAULT_COLOR, LINE_BOTTOM_COLOR, LINE_TOP_COLOR, RenderCol_Plate_Default, RenderCol_Plate_Line_Bottom, RenderCol_Plate_Line_Top, RenderCol_Plate_Selected, RenderCol_Plate_Unselected, SELECT_COLOR, Slic3r::GUI::ImGuiWrapper::to_ImVec4(), and UNSELECT_COLOR.

Referenced by Slic3r::GUI::GLCanvas3D::init().

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

◆ load_thumbnail_data()

int Slic3r::GUI::PartPlate::load_thumbnail_data ( std::string filename,
ThumbnailData & thumb_data )
5542{
5543 bool result = true;
5544 wxImage img;
5545 if (boost::algorithm::iends_with(filename, ".png")) {
5546 result = img.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_PNG);
5547 img = img.Mirror(false);
5548 }
5549 if (result) {
5550 thumb_data.set(img.GetWidth(), img.GetHeight());
5551 for (int i = 0; i < img.GetWidth() * img.GetHeight(); i++) {
5552 memcpy(&thumb_data.pixels[4 * i], (unsigned char*)(img.GetData() + 3 * i), 3);
5553 if (img.HasAlpha()) {
5554 thumb_data.pixels[4 * i + 3] = *(unsigned char*)(img.GetAlpha() + i);
5555 }
5556 }
5557 } else {
5558 return -1;
5559 }
5560 return 0;
5561}

References Slic3r::ThumbnailData::pixels, and Slic3r::ThumbnailData::set().

Here is the call graph for this function:

◆ lock()

void Slic3r::GUI::PartPlate::lock ( bool state)
inline
612{ m_locked = state; }

References m_locked.

Referenced by Slic3r::GUI::MenuFactory::append_menu_item_locked(), Slic3r::GUI::ArrangeJob::finalize(), Slic3r::GUI::PartPlateList::lock_plate(), Slic3r::GUI::ArrangeJob::prepare_all(), and Slic3r::CLI::run().

Here is the caller graph for this function:

◆ max_broad_phase_intersecting_object_height()

double Slic3r::GUI::PartPlate::max_broad_phase_intersecting_object_height ( const Polygons & regions) const
private
2031{
2032 if (m_model == nullptr)
2033 return 0.0;
2034
2035 double max_height = 0.0;
2036
2037 for (const std::pair<int, int> &object_instance : obj_to_instance_set) {
2038 const int obj_id = object_instance.first;
2039 const int instance_id = object_instance.second;
2040 if (obj_id < 0 || obj_id >= int(m_model->objects.size()))
2041 continue;
2042
2043 ModelObject *object = m_model->objects[obj_id];
2044 if (instance_id < 0 || instance_id >= int(object->instances.size()))
2045 continue;
2046
2047 ModelInstance *instance = object->instances[instance_id];
2048 if (!instance->printable)
2049 continue;
2050
2051 Polygon hull = instance->convex_hull_2d();
2052 bool intersects_region = false;
2053 for (const Polygon &region : regions) {
2054 if (!intersection(Polygons{ region }, Polygons{ hull }).empty()) {
2055 intersects_region = true;
2056 break;
2057 }
2058 }
2059
2060 if (!intersects_region)
2061 continue;
2062
2063 const BoundingBoxf3 instance_box = object->instance_convex_hull_bounding_box(instance_id);
2064 max_height = std::max(max_height, instance_box.max.z());
2065 }
2066
2067 return max_height;
2068}

References Slic3r::ModelInstance::convex_hull_2d(), Slic3r::ModelObject::instances, Slic3r::intersection(), m_model, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, obj_to_instance_set, and Slic3r::ModelInstance::printable.

Referenced by update_exclusion_volume_preview_models().

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

◆ move_instances_to()

void Slic3r::GUI::PartPlate::move_instances_to ( PartPlate & left_plate,
PartPlate & right_plate,
BoundingBoxf3 * bounding_box = nullptr )
4992{
4993 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
4994 {
4995 int obj_id = it->first;
4996 int instance_id = it->second;
4997
4998 if (left_plate.intersect_instance(obj_id, instance_id, bounding_box))
4999 left_plate.add_instance(obj_id, instance_id, false, bounding_box);
5000 else
5001 right_plate.add_instance(obj_id, instance_id, false, bounding_box);
5002 }
5003
5004 return;
5005}

References PartPlate(), add_instance(), Slic3r::bounding_box(), intersect_instance(), and obj_to_instance_set.

Referenced by Slic3r::GUI::PartPlateList::delete_plate().

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

◆ on_extruder_count_changed()

void Slic3r::GUI::PartPlate::on_extruder_count_changed ( int extruder_count)
5854{
5855 if (extruder_count < 2) {
5856 std::vector<int> f_map = wxGetApp().plater()->get_global_filament_map();
5857 std::fill(f_map.begin(), f_map.end(), 1);
5858 wxGetApp().plater()->set_global_filament_map(f_map);
5859 // clear filament map and mode in single extruder mode
5861 //clear_filament_map_mode();
5862 // do not clear mode now, reset to default mode
5863 m_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode", true)->value = FilamentMapMode::fmmAutoForFlush;
5864 }
5865}
void clear_filament_map()
Definition PartPlate.cpp:5806

References clear_filament_map(), Slic3r::fmmAutoForFlush, and m_config.

Here is the call graph for this function:

◆ on_filament_added()

void Slic3r::GUI::PartPlate::on_filament_added ( )
5886{
5887 if (m_config.has("filament_map")) {
5888 std::vector<int>& filament_maps = m_config.option<ConfigOptionInts>("filament_map")->values;
5889 filament_maps.push_back(1);
5890 }
5891
5892 if (m_config.has("filament_nozzle_map")) {
5893 std::vector<int>& filament_nozzle_map = m_config.option<ConfigOptionInts>("filament_nozzle_map")->values;
5894 filament_nozzle_map.push_back(0);
5895 }
5896
5897 if (m_config.has("filament_volume_map")) {
5898 std::vector<int>& filament_volume_map = m_config.option<ConfigOptionInts>("filament_volume_map")->values;
5899 // A new filament defaults onto the first extruder, so seed its volume value from
5900 // that extruder's flow type.
5901 int volume_type = static_cast<int>(NozzleVolumeType::nvtStandard);
5902 auto nozzle_volumes = wxGetApp().preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type");
5903 if (nozzle_volumes && !nozzle_volumes->values.empty())
5904 volume_type = nozzle_volumes->values[0];
5905 // Orca: never store the Hybrid marker as a per-filament value; on a Hybrid extruder
5906 // each filament still prints with a concrete flow, defaulting to Standard.
5907 if (volume_type == static_cast<int>(NozzleVolumeType::nvtHybrid))
5908 volume_type = static_cast<int>(NozzleVolumeType::nvtStandard);
5909
5910 filament_volume_map.push_back(volume_type);
5911 }
5912}
@ nvtHybrid
Definition PrintConfig.hpp:621
@ nvtStandard
Definition PrintConfig.hpp:619
zaa_minimize_perimeter_height filament_nozzle_map((ConfigOptionInts, filament_map_2))((ConfigOptionStrings

References Slic3r::filament_nozzle_map(), m_config, Slic3r::nvtHybrid, and Slic3r::nvtStandard.

Here is the call graph for this function:

◆ on_filament_deleted()

void Slic3r::GUI::PartPlate::on_filament_deleted ( int filament_count,
int filament_id )
5915{
5916 if (m_config.has("filament_map")) {
5917 std::vector<int>& filament_maps = m_config.option<ConfigOptionInts>("filament_map")->values;
5918 // Guard against an out-of-range index: the per-plate filament_map can be out of sync
5919 // with the global filament count, and erasing at/past end() triggers an out-of-bounds
5920 // memmove (crash on macOS, see PartPlate::on_filament_deleted in crash reports).
5921 if (filament_id >= 0 && filament_id < (int) filament_maps.size())
5922 filament_maps.erase(filament_maps.begin() + filament_id);
5923 }
5924
5925 if (m_config.has("filament_nozzle_map")) {
5926 std::vector<int>& filament_nozzle_map = m_config.option<ConfigOptionInts>("filament_nozzle_map")->values;
5927 if (filament_id >= 0 && filament_id < (int) filament_nozzle_map.size())
5928 filament_nozzle_map.erase(filament_nozzle_map.begin() + filament_id);
5929 }
5930
5931 if (m_config.has("filament_volume_map")) {
5932 std::vector<int>& filament_volume_map = m_config.option<ConfigOptionInts>("filament_volume_map")->values;
5933 if (filament_id >= 0 && filament_id < (int) filament_volume_map.size())
5934 filament_volume_map.erase(filament_volume_map.begin() + filament_id);
5935 }
5936
5938}
void update_first_layer_print_sequence_when_delete_filament(size_t filamen_id)
Definition PartPlate.cpp:5710

References Slic3r::filament_nozzle_map(), m_config, and update_first_layer_print_sequence_when_delete_filament().

Here is the call graph for this function:

◆ on_filament_map_mode_change()

void Slic3r::GUI::PartPlate::on_filament_map_mode_change ( )
private

References config().

Here is the call graph for this function:

◆ open_belt_y()

void Slic3r::GUI::PartPlate::open_belt_y ( BoundingBoxf3 & box) const
inline
588{ if (this->belt_open_y()) { box.min.y() = -1e5; box.max.y() = 1e5; } }
bool belt_open_y() const
Definition PartPlate.cpp:5263

References belt_open_y(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, and Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min.

Referenced by check_outside(), contains(), and intersects().

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

◆ operator<()

bool Slic3r::GUI::PartPlate::operator< ( PartPlate & plate) const
4158{
4159 int index = plate.get_index();
4160 return (this->m_plate_index < index);
4161}

References PartPlate(), get_index(), and m_plate_index.

Here is the call graph for this function:

◆ picking_id_component()

int Slic3r::GUI::PartPlate::picking_id_component ( int idx) const
private
3059{
3060 return this->m_plate_index * GRABBER_COUNT + idx;
3061}
static constexpr unsigned int GRABBER_COUNT
Definition PartPlate.hpp:288

References GRABBER_COUNT, and m_plate_index.

Referenced by generate_plate_name_texture(), invalidate_plate_name_texture(), refresh_imex_icon(), and register_raycasters_for_picking().

Here is the caller graph for this function:

◆ print()

void Slic3r::GUI::PartPlate::print ( ) const
5742{
5743 unsigned int count=0;
5744
5745 BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << boost::format(": plate index %1%, pointer %2%, print_index %3% print pointer %4%") % m_plate_index % this % m_print_index % m_print;
5746 BOOST_LOG_TRIVIAL(trace) << boost::format("\t origin {%1%,%2%,%3%}, width %4%, depth %5%, height %6%") % m_origin.x() % m_origin.y() % m_origin.z() % m_width % m_depth % m_height;
5747 BOOST_LOG_TRIVIAL(trace) << boost::format("\t m_printable %1%, m_locked %2%, m_ready_for_slice %3%, m_slice_result_valid %4%, m_tmp_gcode_path %5%, set size %6%")\
5749 /*for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
5750 int obj_id = it->first;
5751 int instance_id = it->second;
5752
5753 BOOST_LOG_TRIVIAL(trace) << boost::format("\t the %1%th instance, obj_id %2%, instance id %3%") % count++ % obj_id % instance_id;
5754 }*/
5755 BOOST_LOG_TRIVIAL(trace) << boost::format("excluded instance set size %1%")%instance_outside_set.size();
5756 /*for (std::set<std::pair<int, int>>::iterator it = instance_outside_set.begin(); it != instance_outside_set.end(); ++it) {
5757 int obj_id = it->first;
5758 int instance_id = it->second;
5759
5760 BOOST_LOG_TRIVIAL(trace) << boost::format("\t obj_id %1%, instance id %2%") % obj_id % instance_id;
5761 }*/
5762
5763 return;
5764}

References count, instance_outside_set, m_depth, m_height, m_locked, m_origin, m_plate_index, m_print, m_print_index, m_printable, m_ready_for_slice, m_slice_result_valid, m_tmp_gcode_path, m_width, obj_to_instance_set, and Slic3r::trace().

Referenced by get_print(), and set_print().

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

◆ printable_instance_size()

int Slic3r::GUI::PartPlate::printable_instance_size ( )
4922{
4923 int size = 0;
4924 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
4925 int obj_id = it->first;
4926 int instance_id = it->second;
4927
4928 if (!valid_instance(obj_id, instance_id))
4929 continue;
4930
4931 ModelObject * object = m_model->objects[obj_id];
4932 ModelInstance *instance = object->instances[instance_id];
4933
4934 if ((instance->printable) && (instance_outside_set.find(std::pair(obj_id, instance_id)) == instance_outside_set.end())) {
4935 size++;
4936 }
4937 }
4938 return size;
4939}

References instance_outside_set, m_model, obj_to_instance_set, Slic3r::ModelInstance::printable, and valid_instance().

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene(), and Slic3r::CLI::run().

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

◆ refresh_imex_icon()

void Slic3r::GUI::PartPlate::refresh_imex_icon ( )
private
804{
805 if (!m_plater) return;
806 PresetBundle* preset = wxGetApp().preset_bundle;
807 if (!preset) return;
808 bool dual_bbl = preset->is_bbl_vendor() && preset->get_printer_extruder_count() == 2;
809 auto* is_imex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex");
810 if (is_imex_opt && is_imex_opt->value) {
811 int imex_slot = dual_bbl ? 7 : 6;
814
815 // calc_vertex_for_icons() destroyed the MeshRaycaster that SceneRaycaster still
816 // holds by raw pointer; swap the registration as calc_vertex_for_plate_name() does.
817 // Only the mode icon is picked -- the warn badge is a plain GLModel.
818 if (GLCanvas3D *canvas = m_plater->get_view3D_canvas3D()) {
819 canvas->remove_raycasters_for_picking(SceneRaycaster::EType::Bed,
822 }
823 }
824}
static constexpr unsigned int PLATE_IMEX_MODE_ID
Definition PartPlate.hpp:287
void calc_vertex_for_icons(int index, PickingModel &model)
Definition PartPlate.cpp:1775
void calc_vertex_for_imex_warn_badge(int imex_icon_index, GLModel &model)
Definition PartPlate.cpp:1805
GLModel m_imex_warn_icon
Definition PartPlate.hpp:200
PickingModel m_imex_mode_icon
Definition PartPlate.hpp:199

References Slic3r::GUI::SceneRaycaster::Bed, calc_vertex_for_icons(), calc_vertex_for_imex_warn_badge(), Slic3r::Preset::config, Slic3r::PresetCollection::get_edited_preset(), Slic3r::PresetBundle::get_printer_extruder_count(), Slic3r::PresetBundle::is_bbl_vendor(), m_imex_mode_icon, m_imex_warn_icon, m_plater, Slic3r::ConfigBase::option(), picking_id_component(), PLATE_IMEX_MODE_ID, Slic3r::PresetBundle::printers, and Slic3r::GUI::register_model_for_picking().

Here is the call graph for this function:

◆ register_raycasters_for_picking()

void Slic3r::GUI::PartPlate::register_raycasters_for_picking ( GLCanvas3D & canvas)
private
3028{
3034 if (m_partplate_list->render_plate_settings)
3036
3037 canvas.remove_raycasters_for_picking(SceneRaycaster::EType::Bed, picking_id_component(6));
3038 // Plate-name edit picking is built lazily together with the plate-name texture.
3039 // During reset / reload_scene the icon may not have a raycaster yet, which is valid.
3040 if (m_plate_name_edit_icon.mesh_raycaster != nullptr)
3043
3044 // Only register filament map button for H2D (dual-extruder Bambu Lab) printers
3045 PresetBundle* preset = wxGetApp().preset_bundle;
3046 bool dual_bbl = (preset && preset->is_bbl_vendor() && preset->get_printer_extruder_count() == 2);
3047 if (dual_bbl)
3049
3050 // Register IDEX/IQEX mode icon only when IDEX/IQEX is active and geometry is initialized.
3051 if (preset) {
3052 auto* is_imex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex");
3053 if (is_imex_opt && is_imex_opt->value && m_imex_mode_icon.mesh_raycaster)
3055 }
3056}
PickingModel m_lock_icon
Definition PartPlate.hpp:194
PickingModel m_orient_icon
Definition PartPlate.hpp:193
PickingModel m_plate_filament_map_icon
Definition PartPlate.hpp:196
PickingModel m_del_icon
Definition PartPlate.hpp:191
PickingModel m_move_front_icon
Definition PartPlate.hpp:198
PickingModel m_arrange_icon
Definition PartPlate.hpp:192
PickingModel m_plate_settings_icon
Definition PartPlate.hpp:195
static constexpr unsigned int PLATE_FILAMENT_MAP_ID
Definition PartPlate.hpp:286

References Slic3r::GUI::SceneRaycaster::Bed, Slic3r::Preset::config, Slic3r::PresetCollection::get_edited_preset(), Slic3r::PresetBundle::get_printer_extruder_count(), Slic3r::PresetBundle::is_bbl_vendor(), m_arrange_icon, m_del_icon, m_imex_mode_icon, m_lock_icon, m_move_front_icon, m_orient_icon, m_partplate_list, m_plate_filament_map_icon, m_plate_name_edit_icon, m_plate_settings_icon, m_triangles, Slic3r::ConfigBase::option(), picking_id_component(), PLATE_FILAMENT_MAP_ID, PLATE_IMEX_MODE_ID, Slic3r::PresetBundle::printers, Slic3r::GUI::register_model_for_picking(), and Slic3r::GUI::GLCanvas3D::remove_raycasters_for_picking().

Here is the call graph for this function:

◆ remove_instance()

int Slic3r::GUI::PartPlate::remove_instance ( int obj_id,
int instance_id )
4695{
4696 bool result;
4697 std::set<std::pair<int, int>>::iterator it;
4698
4699 it = obj_to_instance_set.find(std::pair(obj_id, instance_id));
4700 if (it != obj_to_instance_set.end()) {
4701 obj_to_instance_set.erase(it);
4703 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":plate_id %1%, found obj_id %2%, instance_id %3%") % m_plate_index % obj_id % instance_id;
4704 result = 0;
4705 }
4706 else {
4707 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plate_id %1%, can not find obj_id %2%, instance_id %3%") % m_plate_index % obj_id % instance_id;
4708 result = -1;
4709 return result;
4710 }
4711
4712 it = instance_outside_set.find(std::pair(obj_id, instance_id));
4713 if (it != instance_outside_set.end()) {
4714 instance_outside_set.erase(it);
4715 }
4716 if (!m_ready_for_slice)
4717 update_states();
4718
4719 return result;
4720}
void update_states()
Definition PartPlate.cpp:5395

References instance_outside_set, invalidate_exclusion_volume_preview(), m_plate_index, m_ready_for_slice, obj_to_instance_set, and update_states().

Referenced by Slic3r::GUI::PartPlateList::add_to_plate(), Slic3r::GUI::PartPlateList::notify_instance_removed(), and Slic3r::GUI::PartPlateList::notify_instance_update().

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

◆ render()

void Slic3r::GUI::PartPlate::render ( const Transform3d & view_matrix,
const Transform3d & projection_matrix,
bool bottom,
bool only_body = false,
bool force_background_color = false,
HeightLimitMode mode = HEIGHT_LIMIT_NONE,
int hover_id = -1,
bool render_cali = false,
bool show_grid = true,
bool hide_chrome = false )
5312{
5314
5315 GLShaderProgram *shader = wxGetApp().get_shader("flat");
5316 if (shader != nullptr) {
5317 shader->start_using();
5320
5321 shader->set_uniform("view_model_matrix", view_matrix);
5322 shader->set_uniform("projection_matrix", projection_matrix);
5323
5324 if (!bottom) {
5325 // draw background
5326 render_background(force_background_color);
5327
5328 render_exclude_area(force_background_color);
5329 render_imex_zones(force_background_color);
5330 if(m_selected && wxGetApp().plater()->get_enable_wrapping_detection()){
5331 if(!m_wrapping_detection_triangles.is_initialized()){
5332 auto points = get_plate_wrapping_detection_area();
5333 if (points.size() > 0) {//wrapping_detection_area
5334 ExPolygon temp_poly;
5335 for (const Vec2d &p : points) {
5336 temp_poly.contour.append({scale_(p(0)), scale_(p(1))});
5337 }
5338 auto result = intersection(m_print_polygon, temp_poly);
5339 if (result.size() > 0) {
5340 ExPolygon wrapp_poly(result[0]);
5342 }
5343 }
5344 }
5345 render_wrapping_detection_area(force_background_color);
5346 }
5347 render_exclusion_volume_previews(force_background_color);
5348 }
5349
5350 render_height_limit(mode);
5351
5353
5354 // if (with_label) {
5355 // render_label(canvas);
5356 // }
5357
5358 shader->stop_using();
5359 }
5360
5361 if (wxGetApp().show_plate_gridlines() && show_grid) {
5362 glsafe(::glDepthMask(bottom ? GL_TRUE : GL_FALSE));
5363 render_grid(bottom);
5365 }
5366
5367 if (!hide_chrome && !bottom && m_selected && !force_background_color) {
5368 if (m_partplate_list)
5369 render_logo(bottom, m_partplate_list->render_cali_logo && render_cali);
5370 else
5371 render_logo(bottom);
5372 }
5373
5374 if (!hide_chrome) {
5375 render_icons(bottom, only_body, hover_id);
5376 if (!force_background_color) {
5377 render_only_numbers(bottom);
5378 }
5379 }
5380
5382}
#define glsafe(cmd)
Definition OpenGLUtils.hpp:25
std::vector< Vec2d > get_plate_wrapping_detection_area() const
Definition PartPlate.cpp:442
void render_wrapping_detection_area(bool force_default_color)
Definition PartPlate.cpp:2005
void render_height_limit(PartPlate::HeightLimitMode mode=HEIGHT_LIMIT_BOTH)
Definition PartPlate.cpp:2519
void render_only_numbers(bool bottom)
Definition PartPlate.cpp:2768
void render_grid(bool bottom)
Definition PartPlate.cpp:2446
void render_imex_zones(bool force_default_color)
Definition PartPlate.cpp:1328
GLModel m_wrapping_detection_triangles
Definition PartPlate.hpp:164
ExPolygon m_print_polygon
Definition PartPlate.hpp:161
void render_background(bool force_default_color=false)
Definition PartPlate.cpp:1853
void render_exclude_area(bool force_default_color)
Definition PartPlate.cpp:2014
void render_exclusion_volume_previews(bool force_default_color)
Definition PartPlate.cpp:2375
void render_logo(bool bottom, bool render_cali=true)
Definition PartPlate.cpp:1924
void calc_triangles_from_polygon(const ExPolygon &poly, GLModel &render_model)
Definition PartPlate.cpp:1422
void render_icons(bool bottom, bool only_name=false, int hover_id=-1)
Definition PartPlate.cpp:2588
#define GL_TRUE
Definition gl.h:1892
#define glEnable
Definition gl.h:3667
#define GL_DEPTH_TEST
Definition gl.h:574
#define GL_SRC_ALPHA
Definition gl.h:1621
#define glDepthMask
Definition gl.h:3595
#define GL_BLEND
Definition gl.h:275
#define GL_ONE_MINUS_SRC_ALPHA
Definition gl.h:1239
#define GL_FALSE
Definition gl.h:648
#define glDisable
Definition gl.h:3607
#define glBlendFunc
Definition gl.h:3325

References Slic3r::MultiPoint::append(), calc_triangles_from_polygon(), Slic3r::ExPolygon::contour, get_plate_wrapping_detection_area(), GL_BLEND, GL_DEPTH_TEST, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TRUE, glBlendFunc, glDepthMask, glDisable, glEnable, glsafe, Slic3r::intersection(), m_partplate_list, m_print_polygon, m_selected, m_wrapping_detection_triangles, Slic3r::GUI::plater(), render_background(), render_exclude_area(), render_exclusion_volume_previews(), render_grid(), render_height_limit(), render_icons(), render_imex_zones(), render_logo(), render_only_numbers(), render_wrapping_detection_area(), scale_, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Here is the call graph for this function:

◆ render_background()

void Slic3r::GUI::PartPlate::render_background ( bool force_default_color = false)
private
1854{
1855 //return directly for current plate
1856 if (m_selected && !force_default_color) return;
1857
1858 // draw background
1860
1861 ColorRGBA color;
1862 if (!force_default_color) {
1863 if (m_selected) {
1865 }
1866 else {
1868 }
1869 }
1870 else {
1872 }
1873 m_triangles.model.set_color(color);
1874 m_triangles.model.render();
1876}
static ColorRGBA UNSELECT_DARK_COLOR
Definition PartPlate.hpp:309

References DEFAULT_COLOR, GL_FALSE, GL_TRUE, glDepthMask, glsafe, m_partplate_list, m_selected, m_triangles, SELECT_COLOR, UNSELECT_COLOR, and UNSELECT_DARK_COLOR.

Referenced by render().

Here is the caller graph for this function:

◆ render_exclude_area()

void Slic3r::GUI::PartPlate::render_exclude_area ( bool force_default_color)
private
2014 {
2015 if (force_default_color) //for thumbnail case
2016 return;
2017
2018 ColorRGBA select_color{ .9f, .86f, .82f, .7f }; // ORCA
2019 ColorRGBA unselect_color{ .6f, .6f, .6f, .3f }; // ORCA
2020 //ColorRGBA default_color{ 0.9f, 0.9f, 0.9f, 1.0f };
2021
2022 // draw exclude area
2024
2025 m_exclude_triangles.set_color(m_selected ? select_color : unselect_color);
2026 m_exclude_triangles.render();
2028}

References GL_FALSE, GL_TRUE, glDepthMask, glsafe, m_exclude_triangles, and m_selected.

Referenced by render().

Here is the caller graph for this function:

◆ render_exclusion_volume_intersections()

void Slic3r::GUI::PartPlate::render_exclusion_volume_intersections ( )
private
2407{
2408 if (!m_exclusion_volume_intersection_triangles.is_initialized())
2409 return;
2410
2411 const ColorRGBA intersection_color{ .68f, .02f, .02f, .58f };
2412
2414 glsafe(::glPolygonOffset(-1.0f, -1.0f));
2415
2416 m_exclusion_volume_intersection_triangles.set_color(intersection_color);
2418
2420}
#define GL_POLYGON_OFFSET_FILL
Definition gl.h:1318
#define glPolygonOffset
Definition gl.h:4471

References GL_POLYGON_OFFSET_FILL, glDisable, glEnable, glPolygonOffset, glsafe, and m_exclusion_volume_intersection_triangles.

◆ render_exclusion_volume_previews()

void Slic3r::GUI::PartPlate::render_exclusion_volume_previews ( bool force_default_color)
private
2376{
2377 if (force_default_color)
2378 return;
2379
2381
2382 const ColorRGBA floor_color = m_selected ? ColorRGBA{ .86f, .86f, .86f, .70f } : ColorRGBA{ .60f, .60f, .60f, .30f };
2383 const ColorRGBA ribbon_color{ .60f, .60f, .60f, .70f };
2384 const ColorRGBA prism_color{ .52f, .52f, .52f, .38f };
2385
2387
2388 m_exclusion_volume_floor_triangles.set_color(floor_color);
2390
2391 m_exclusion_volume_border_triangles.set_color(ribbon_color);
2393
2394 for (auto &colored_border : m_extruder_exclusion_volume_borders) {
2395 colored_border.first->set_color(colored_border.second);
2396 colored_border.first->render();
2397 }
2398
2399 m_active_exclusion_volume_prisms.set_color(prism_color);
2401
2404}
float m_scale_factor
Definition PartPlate.hpp:204
GLModel m_active_exclusion_volume_prisms
Definition PartPlate.hpp:168
std::vector< std::pair< std::unique_ptr< GLModel >, ColorRGBA > > m_extruder_exclusion_volume_borders
Definition PartPlate.hpp:167
GLModel m_exclusion_volume_border_triangles
Definition PartPlate.hpp:166
void update_exclusion_volume_preview_models()
Definition PartPlate.cpp:2128
GLModel m_exclusion_volume_floor_triangles
Definition PartPlate.hpp:165
#define glLineWidth
Definition gl.h:4215

References GL_FALSE, GL_TRUE, glDepthMask, glLineWidth, glsafe, m_active_exclusion_volume_prisms, m_exclusion_volume_border_triangles, m_exclusion_volume_floor_triangles, m_extruder_exclusion_volume_borders, m_scale_factor, m_selected, and update_exclusion_volume_preview_models().

Referenced by render().

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

◆ render_grid()

void Slic3r::GUI::PartPlate::render_grid ( bool bottom)
private
2446 {
2447 //glsafe(::glEnable(GL_MULTISAMPLE));
2448 // draw grid
2449
2450 // ORCA: OpenGL Core Profile support
2451 // FIXME: ideally, we'd use the same shader for both the thin and thick lines, but for some reason setting the uniforms has no effect
2452 GLShaderProgram* shader = wxGetApp().get_shader("flat");
2453 if (shader == nullptr) {
2454 return;
2455 }
2456
2457 shader->start_using();
2460
2461 const Camera& camera = wxGetApp().plater()->get_camera();
2462 const std::array<int, 4>& viewport = camera.get_viewport();
2463 const Transform3d& view_matrix = camera.get_view_matrix();
2464 const Transform3d& projection_matrix = camera.get_projection_matrix();
2465
2466 shader->set_uniform("view_model_matrix", view_matrix);
2467 shader->set_uniform("projection_matrix", projection_matrix);
2468
2469#if !SLIC3R_OPENGL_ES
2470 if (!OpenGLManager::get_gl_info().is_core_profile())
2472#endif // !SLIC3R_OPENGL_ES
2473
2474 ColorRGBA color;
2475 if (bottom)
2476 color = LINE_BOTTOM_COLOR;
2477 else {
2478 if (m_selected)
2480 else
2482 }
2483 m_gridlines.set_color(color);
2484 m_gridlines.render();
2485
2486 shader->stop_using();
2487
2488 // ORCA: OpenGL Core Profile support
2489#if SLIC3R_OPENGL_ES
2490 shader = wxGetApp().get_shader("dashed_lines");
2491#else
2492 shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
2493#endif // SLIC3R_OPENGL_ES
2494 if (shader == nullptr) {
2495 return;
2496 }
2497 shader->start_using();
2498
2499 shader->set_uniform("view_model_matrix", view_matrix);
2500 shader->set_uniform("projection_matrix", projection_matrix);
2501
2502#if !SLIC3R_OPENGL_ES
2503 if (OpenGLManager::get_gl_info().is_core_profile()) {
2504#endif // !SLIC3R_OPENGL_ES
2505 shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3])));
2506 shader->set_uniform("width", 0.25f);
2507#if !SLIC3R_OPENGL_ES
2508 } else {
2510 }
2511#endif // !SLIC3R_OPENGL_ES
2512
2513 m_gridlines_bolder.set_color(color);
2514 m_gridlines_bolder.render();
2515
2516 shader->stop_using();
2517}
bool is_core_profile() const
Definition OpenGLManager.hpp:53
static const GLInfo & get_gl_info()
Definition OpenGLManager.hpp:106
static ColorRGBA LINE_TOP_DARK_COLOR
Definition PartPlate.hpp:313
static ColorRGBA LINE_TOP_SEL_COLOR
Definition PartPlate.hpp:314
static ColorRGBA LINE_TOP_SEL_DARK_COLOR
Definition PartPlate.hpp:315
@ Camera
Definition Shortcuts.hpp:72

References Slic3r::GUI::OpenGLManager::get_gl_info(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), Slic3r::GUI::Camera::get_viewport(), GL_BLEND, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glEnable, glLineWidth, glsafe, Slic3r::GUI::OpenGLManager::GLInfo::is_core_profile(), LINE_BOTTOM_COLOR, LINE_TOP_COLOR, LINE_TOP_DARK_COLOR, LINE_TOP_SEL_COLOR, LINE_TOP_SEL_DARK_COLOR, m_gridlines, m_gridlines_bolder, m_partplate_list, m_scale_factor, m_selected, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by render().

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

◆ render_height_limit()

void Slic3r::GUI::PartPlate::render_height_limit ( PartPlate::HeightLimitMode mode = HEIGHT_LIMIT_BOTH)
private
2520{
2521 // Orca: a prime tower compacted by "No sparse layers" drags the nozzle back down to the plate on
2522 // every toolchange, so the rod and the lid limit how tall a neighbouring object may be exactly as
2523 // they do in sequential printing. The reference lines are just as useful there.
2524 const bool relevant_for_print_mode = m_print && (m_print->config().print_sequence == PrintSequence::ByObject ||
2525 (m_print->config().print_sequence == PrintSequence::ByLayer &&
2526 wipe_tower_sparse_layers_skipped(m_print->config()) && m_print->has_wipe_tower()));
2527 if (relevant_for_print_mode && mode != HEIGHT_LIMIT_NONE)
2528 {
2529 // draw lower limit
2530 // ORCA: OpenGL Core Profile
2531#if !SLIC3R_OPENGL_ES
2532 if (!OpenGLManager::get_gl_info().is_core_profile())
2534#endif // !SLIC3R_OPENGL_ES
2536 m_height_limit_common.render();
2537
2538 if ((mode == HEIGHT_LIMIT_BOTTOM) || (mode == HEIGHT_LIMIT_BOTH)) {
2539 // ORCA: OpenGL Core Profile
2540#if !SLIC3R_OPENGL_ES
2541 if (!OpenGLManager::get_gl_info().is_core_profile())
2543#endif // !SLIC3R_OPENGL_ES
2545 m_height_limit_bottom.render();
2546 }
2547
2548 // draw upper limit
2549 if ((mode == HEIGHT_LIMIT_TOP) || (mode == HEIGHT_LIMIT_BOTH)){
2550 // ORCA: OpenGL Core Profile
2551#if !SLIC3R_OPENGL_ES
2552 if (!OpenGLManager::get_gl_info().is_core_profile())
2554#endif // !SLIC3R_OPENGL_ES
2556 m_height_limit_top.render();
2557 }
2558 }
2559}
static ColorRGBA HEIGHT_LIMIT_BOTTOM_COLOR
Definition PartPlate.hpp:316
static ColorRGBA HEIGHT_LIMIT_TOP_COLOR
Definition PartPlate.hpp:317
@ ByObject
Definition PrintConfig.hpp:312
@ ByLayer
Definition PrintConfig.hpp:311
bool wipe_tower_sparse_layers_skipped(const PrintConfig &config)
Definition WipeTower.cpp:53

References Slic3r::ByLayer, Slic3r::ByObject, Slic3r::GUI::OpenGLManager::get_gl_info(), glLineWidth, glsafe, HEIGHT_LIMIT_BOTH, HEIGHT_LIMIT_BOTTOM, HEIGHT_LIMIT_BOTTOM_COLOR, HEIGHT_LIMIT_NONE, HEIGHT_LIMIT_TOP, HEIGHT_LIMIT_TOP_COLOR, m_height_limit_bottom, m_height_limit_common, m_height_limit_top, m_print, m_scale_factor, Slic3r::print_sequence(), and Slic3r::wipe_tower_sparse_layers_skipped().

Referenced by render().

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

◆ render_icon_texture()

void Slic3r::GUI::PartPlate::render_icon_texture ( GLModel & buffer,
GLTexture & texture )
private
2562{
2563 GLuint tex_id = (GLuint)texture.get_id();
2565 buffer.render();
2567}
#define glBindTexture
Definition gl.h:3299
unsigned int GLuint
Definition gl.h:2063
#define GL_TEXTURE_2D
Definition gl.h:1739

References Slic3r::GUI::GLTexture::get_id(), GL_TEXTURE_2D, glBindTexture, glsafe, and Slic3r::GUI::GLModel::render().

Referenced by render_icons(), and render_only_numbers().

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

◆ render_icons()

void Slic3r::GUI::PartPlate::render_icons ( bool bottom,
bool only_name = false,
int hover_id = -1 )
private
2589{
2590 GLShaderProgram* shader = wxGetApp().get_shader("printbed");
2591 if (shader != nullptr) {
2592 shader->start_using();
2593 const Camera &camera = wxGetApp().plater()->get_camera();
2594 shader->set_uniform("view_model_matrix", camera.get_view_matrix());
2595 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
2596 shader->set_uniform("transparent_background", bottom);
2597 //shader->set_uniform("svg_source", boost::algorithm::iends_with(m_partplate_list->m_del_texture.get_source(), ".svg"));
2598 shader->set_uniform("svg_source", 0);
2599
2600 //if (bottom)
2601 // glsafe(::glFrontFace(GL_CW));
2603
2606
2607 if (!only_name) {
2608 if (hover_id == 1) {
2609 render_icon_texture(m_del_icon.model, m_partplate_list->m_del_hovered_texture);
2610 set_hover_tooltip(_u8L("Remove current plate (if not last one)"));
2611 }
2612 else
2613 render_icon_texture(m_del_icon.model, m_partplate_list->m_del_texture);
2614
2615 if (hover_id == 2) {
2616 render_icon_texture(m_orient_icon.model, m_partplate_list->m_orient_hovered_texture);
2617 set_hover_tooltip(_u8L("Auto orient objects on current plate"));
2618 }
2619 else
2620 render_icon_texture(m_orient_icon.model, m_partplate_list->m_orient_texture);
2621
2622 if (hover_id == 3) {
2623 render_icon_texture(m_arrange_icon.model, m_partplate_list->m_arrange_hovered_texture);
2624 set_hover_tooltip(_u8L("Arrange objects on current plate"));
2625 }
2626 else
2627 render_icon_texture(m_arrange_icon.model, m_partplate_list->m_arrange_texture);
2628
2629 if (hover_id == 4) {
2630 if (this->is_locked()) {
2632 m_partplate_list->m_locked_hovered_texture);
2633 set_hover_tooltip(_u8L("Unlock current plate"));
2634 }
2635 else {
2637 m_partplate_list->m_lockopen_hovered_texture);
2638 set_hover_tooltip(_u8L("Lock current plate"));
2639 }
2640 } else {
2641 if (this->is_locked())
2642 render_icon_texture(m_lock_icon.model, m_partplate_list->m_locked_texture);
2643 else
2644 render_icon_texture(m_lock_icon.model, m_partplate_list->m_lockopen_texture);
2645 }
2646
2647 PresetBundle* preset = wxGetApp().preset_bundle;
2648 bool dual_bbl = (preset->is_bbl_vendor() && preset->get_printer_extruder_count() == 2);
2649 if (dual_bbl) {
2650 if (hover_id == PLATE_FILAMENT_MAP_ID){
2651 render_icon_texture(m_plate_filament_map_icon.model, m_partplate_list->m_plate_set_filament_map_hovered_texture);
2652 set_hover_tooltip(_u8L("Filament grouping"));
2653 } else
2654 render_icon_texture(m_plate_filament_map_icon.model, m_partplate_list->m_plate_set_filament_map_texture);
2655 }
2656
2657 if (hover_id == 6) {
2658 render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_hovered_texture);
2659 set_hover_tooltip(_u8L("Edit current plate name"));
2660 }
2661 else
2662 render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_texture);
2663
2664 if (hover_id == 7) {
2665 render_icon_texture(m_move_front_icon.model, m_partplate_list->m_move_front_hovered_texture);
2666 set_hover_tooltip(_u8L("Move plate to the front"));
2667 } else
2668 render_icon_texture(m_move_front_icon.model, m_partplate_list->m_move_front_texture);
2669
2670 // IDEX/IQEX mode icon — only when is_imex is active
2671 {
2672 PresetBundle* pb = wxGetApp().preset_bundle;
2673 auto* is_imex_opt = pb ? pb->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex") : nullptr;
2674 if (is_imex_opt && is_imex_opt->value) {
2675 // The icon shows the mode the plate slices as, the one its ghosts follow.
2676 std::string active_tools;
2677 int primary_phys = -1;
2678 const size_t kind = size_t(resolve_active_mode_tools(active_tools, primary_phys) ?
2679 imex_mode_kind(active_tools) :
2681 // Both the mode name and the conflict warning describe the same hovered icon,
2682 // and set_hover_tooltip records one string per frame, so they are composed here.
2683 std::string hover_tip;
2684 if (hover_id == (int)PLATE_IMEX_MODE_ID) {
2685 render_icon_texture(m_imex_mode_icon.model, m_partplate_list->m_imex_mode_hovered_textures[kind]);
2686 // The stored value, not the resolved one: this line carries the click
2687 // affordances, and the menu checkmark and the left-click cycle both act
2688 // on what the plate stores. Reporting the inherited mode here would leave
2689 // one control saying three different things. Where they differ -- a plate
2690 // on Primary under a process preset that names a mode, which is what
2691 // actually slices -- the inherited mode is named after it, so the tooltip
2692 // still tells the user what this plate will print as.
2693 std::string cur = get_imex_mode();
2694 const std::string effective = get_effective_imex_mode();
2695 if (cur == kImexPrimaryMode) cur = _u8L("Primary");
2696 // One format string, not two catalog fragments concatenated around a
2697 // runtime value: translators need to move the mode name within the
2698 // sentence, and the space-padded fragments were untranslatable alone.
2699 //
2700 // Guarded because this runs on the paint path: boost::format throws if a
2701 // TRANSLATED string drops or malforms %1%, and an exception escaping here
2702 // would take down the frame rather than show a wrong tooltip. The English
2703 // literal is the fallback and cannot itself throw.
2704 if (effective != get_imex_mode()) {
2705 try {
2706 // TRN Plate icon tooltip. %1% is the plate's IDEX/IQEX mode, %2% the mode its process preset sets.
2707 hover_tip = (boost::format(_u8L("IDEX/IQEX mode: %1% (process preset: %2%) (left-click to cycle, right-click for menu)")) % cur % effective).str();
2708 } catch (const std::exception&) {
2709 hover_tip = (boost::format("IDEX/IQEX mode: %1% (process preset: %2%) (left-click to cycle, right-click for menu)") % cur % effective).str();
2710 }
2711 } else {
2712 try {
2713 hover_tip = (boost::format(_u8L("IDEX/IQEX mode: %1% (left-click to cycle, right-click for menu)")) % cur).str();
2714 } catch (const std::exception&) {
2715 hover_tip = (boost::format("IDEX/IQEX mode: %1% (left-click to cycle, right-click for menu)") % cur).str();
2716 }
2717 }
2718 } else {
2719 render_icon_texture(m_imex_mode_icon.model, m_partplate_list->m_imex_mode_textures[kind]);
2720 }
2721 // Warning badge: IMEX parallel mode active alongside multi-material objects
2724 // The warning joins the mode line rather than replacing it: one hover
2725 // records one string, and the mode name carries the click affordances.
2726 if (hover_id == (int)PLATE_IMEX_MODE_ID)
2727 hover_tip += (hover_tip.empty() ? "" : "\n\n") +
2728 _u8L("Warning: this plate uses a parallel IDEX/IQEX mode with multi-material objects. Proceed with caution — verify your G-code handles this combination correctly.");
2729 }
2730 if (!hover_tip.empty())
2731 set_hover_tooltip(hover_tip);
2732 }
2733 }
2734
2735 if (m_partplate_list->render_plate_settings) {
2737 if (hover_id == 5) {
2738 if (!has_plate_settings)
2739 render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_hovered_texture);
2740 else
2741 render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_changed_hovered_texture);
2742
2743 set_hover_tooltip(_u8L("Customize current plate"));
2744 } else {
2745 if (!has_plate_settings)
2746 render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_texture);
2747 else
2748 render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_changed_texture);
2749 }
2750 }
2751
2754 }
2755 }
2757
2759
2760 //if (bottom)
2761 // glsafe(::glFrontFace(GL_CCW));
2762
2764 shader->stop_using();
2765 }
2766}
#define MAX_PLATE_COUNT
Definition PartPlate.hpp:59
bool is_locked() const
Definition PartPlate.hpp:611
void render_plate_name_texture()
Definition PartPlate.cpp:2569
std::vector< int > get_first_layer_print_sequence() const
Definition PartPlate.cpp:5602
BedType get_bed_type(bool load_from_project=false) const
Definition PartPlate.cpp:266
std::vector< LayerPrintSequence > get_other_layers_print_sequence() const
Definition PartPlate.cpp:5611
bool has_imex_multimaterial_conflict() const
Definition PartPlate.cpp:1269
void set_hover_tooltip(const std::string &tooltip)
Definition PartPlate.cpp:2583
void render_icon_texture(GLModel &buffer, GLTexture &texture)
Definition PartPlate.cpp:2561
GLModel m_plate_idx_icon
Definition PartPlate.hpp:201
bool has_spiral_mode_config() const
Definition PartPlate.cpp:422
@ Primary
Definition IMEXHelpers.hpp:456
ImexModeKind imex_mode_kind(const std::string &active_tools_for_mode)
Definition IMEXHelpers.cpp:351

References _u8L, Slic3r::btDefault, Slic3r::ByDefault, Slic3r::Preset::config, get_bed_type(), Slic3r::PresetCollection::get_edited_preset(), get_effective_imex_mode(), get_first_layer_print_sequence(), get_imex_mode(), get_other_layers_print_sequence(), get_print_seq(), Slic3r::PresetBundle::get_printer_extruder_count(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), GL_BLEND, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TRUE, glBlendFunc, glDepthMask, glDisable, glEnable, glsafe, has_imex_multimaterial_conflict(), has_spiral_mode_config(), Slic3r::imex_mode_kind(), Slic3r::PresetBundle::is_bbl_vendor(), is_locked(), Slic3r::kImexPrimaryMode, m_arrange_icon, m_del_icon, m_imex_mode_icon, m_imex_warn_icon, m_lock_icon, m_move_front_icon, m_orient_icon, m_partplate_list, m_plate_filament_map_icon, m_plate_idx_icon, m_plate_index, m_plate_name_edit_icon, m_plate_settings_icon, MAX_PLATE_COUNT, Slic3r::ConfigBase::option(), PLATE_FILAMENT_MAP_ID, PLATE_IMEX_MODE_ID, Slic3r::Primary, Slic3r::PresetBundle::printers, render_icon_texture(), render_plate_name_texture(), resolve_active_mode_tools(), set_hover_tooltip(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by render().

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

◆ render_imex_zones()

void Slic3r::GUI::PartPlate::render_imex_zones ( bool force_default_color)
private
1329{
1330 if (force_default_color)
1331 return;
1332
1335
1336 // Read visualization theme from printer config.
1337 struct IMEXTheme {
1338 ColorRGBA copy; // secondary copy zone fill
1339 ColorRGBA mirror; // secondary mirror zone fill
1340 ColorRGBA danger; // blocking collision strip
1341 ColorRGBA margin; // advisory safety margin
1342 };
1343
1344 // Standard (Okabe-Ito orange + sky blue)
1345 // Alphas are deliberately low: these fills cover whole quadrants of the bed and sit under
1346 // the model for the entire session, so at the saturation that reads well on a swatch they
1347 // dominate the scene. The zone a tool owns only has to be legible, not loud.
1348 // The three themes below keep their original alphas -- they are chosen for discriminability
1349 // (and k_high_contrast explicitly for low vision), which is the opposite trade.
1350 static const IMEXTheme k_standard = {
1351 { 0.337f, 0.706f, 0.914f, 0.22f }, // copy — sky blue #56B4E9
1352 { 0.902f, 0.624f, 0.000f, 0.22f }, // mirror — orange #E69F00
1353 // Dimmed less than the fills: this strip marks where a head collides, so it stays the
1354 // most prominent thing on the bed even after the surrounding zones recede.
1355 { 0.850f, 0.100f, 0.100f, 0.40f }, // danger — red
1356 { 0.300f, 0.900f, 0.200f, 0.20f }, // margin — lime green
1357 };
1358 // Deuteranopia / Protanopia: avoids red-green confusion.
1359 // Danger strip uses strong blue-violet (red invisible to protanopes).
1360 static const IMEXTheme k_deuteranopia = {
1361 { 0.000f, 0.447f, 0.698f, 0.50f }, // copy — blue #0072B2
1362 { 0.941f, 0.894f, 0.259f, 0.50f }, // mirror — yellow #F0E442
1363 { 0.200f, 0.100f, 0.800f, 0.65f }, // danger — blue-violet (red not visible)
1364 { 0.800f, 0.475f, 0.655f, 0.45f }, // margin — reddish purple #CC79A7
1365 };
1366 // Tritanopia: avoids blue-yellow confusion.
1367 // Copy uses vermilion, mirror uses reddish-purple, margin uses teal.
1368 static const IMEXTheme k_tritanopia = {
1369 { 0.835f, 0.369f, 0.000f, 0.50f }, // copy — vermilion #D55E00
1370 { 0.800f, 0.475f, 0.655f, 0.50f }, // mirror — reddish purple #CC79A7
1371 { 0.850f, 0.100f, 0.100f, 0.55f }, // danger — red (visible to tritanopes)
1372 { 0.000f, 0.700f, 0.600f, 0.45f }, // margin — teal
1373 };
1374 // High contrast: saturated, higher alpha for low-vision users.
1375 static const IMEXTheme k_high_contrast = {
1376 { 0.000f, 0.600f, 1.000f, 0.65f }, // copy — vivid blue
1377 { 1.000f, 0.600f, 0.000f, 0.65f }, // mirror — vivid orange
1378 { 1.000f, 0.000f, 0.000f, 0.75f }, // danger — full red
1379 { 0.000f, 1.000f, 0.200f, 0.60f }, // margin — bright green
1380 };
1381
1382 const IMEXTheme* theme = &k_standard;
1383 if (wxGetApp().preset_bundle) {
1384 const DynamicPrintConfig& pcfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
1385 switch (imex_cfg_enum<ImexVizTheme>(pcfg, "imex_viz_theme")) {
1386 case ImexVizTheme::Deuteranopia: theme = &k_deuteranopia; break;
1387 case ImexVizTheme::Tritanopia: theme = &k_tritanopia; break;
1388 case ImexVizTheme::HighContrast: theme = &k_high_contrast; break;
1389 default: break; // Standard
1390 }
1391 }
1392
1393 // Both fills and border lines use the flat shader already active from render().
1395
1396 if (!m_imex_copy_zones.empty())
1397 for (GLModel& z : m_imex_copy_zones)
1398 if (z.is_initialized()) { z.set_color(theme->copy); z.render(); }
1399
1400 if (!m_imex_mirror_zones.empty())
1401 for (GLModel& z : m_imex_mirror_zones)
1402 if (z.is_initialized()) { z.set_color(theme->mirror); z.render(); }
1403
1405
1406
1407 if (!m_imex_collision_overlay.empty()) {
1409 for (GLModel& s : m_imex_collision_overlay)
1410 if (s.is_initialized()) { s.set_color(theme->danger); s.render(); }
1412 }
1413
1414 if (!m_imex_margin_overlay.empty()) {
1416 for (GLModel& b : m_imex_margin_overlay)
1417 if (b.is_initialized()) { b.set_color(theme->margin); b.render(); }
1419 }
1420}
void ensure_imex_ghosts()
Definition PartPlate.cpp:856
@ Tritanopia
Definition PrintConfig.hpp:275
@ Deuteranopia
Definition PrintConfig.hpp:274
@ HighContrast
Definition PrintConfig.hpp:276

References Slic3r::Deuteranopia, ensure_imex_ghosts(), ensure_imex_zones(), GL_FALSE, GL_TRUE, glDepthMask, glsafe, Slic3r::HighContrast, Slic3r::imex_cfg_enum(), m_imex_collision_overlay, m_imex_copy_zones, m_imex_margin_overlay, m_imex_mirror_zones, and Slic3r::Tritanopia.

Referenced by render().

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

◆ render_logo()

void Slic3r::GUI::PartPlate::render_logo ( bool bottom,
bool render_cali = true )
private
1925{
1926 if (!m_partplate_list->render_bedtype_logo) {
1927 // render third-party printer texture logo
1928 if (!m_partplate_list->load_logo_texture())
1929 return;
1930
1931 if (m_logo_triangles.is_initialized())
1932 render_logo_texture(m_partplate_list->m_logo_texture, m_logo_triangles, bottom);
1933 return;
1934 }
1935
1936 m_partplate_list->load_bedtype_textures();
1937 m_partplate_list->load_cali_textures();
1938 m_partplate_list->load_extruder_only_area_textures();
1939 // btDefault should be skipped
1940 auto curr_bed_type = get_bed_type();
1941 if (curr_bed_type == btDefault) {
1942 DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
1943 if (proj_cfg.has(std::string("curr_bed_type")))
1944 curr_bed_type = proj_cfg.opt_enum<BedType>(std::string("curr_bed_type"));
1945 }
1946 int bed_type_idx = (int)curr_bed_type;
1947 auto is_single_extruder = wxGetApp().preset_bundle->get_printer_extruder_count() == 1;
1948 if (!is_single_extruder) {
1949 if (m_partplate_list->m_allow_bed_type_in_double_nozzle.find(bed_type_idx) == m_partplate_list->m_allow_bed_type_in_double_nozzle.end()) {
1950 bed_type_idx = 0;
1951 }
1952 }
1953 // render bed textures
1954 for (auto &part : m_partplate_list->bed_texture_info[bed_type_idx].parts) {
1955 if (part.texture) {
1956 if (part.buffer && part.buffer->is_initialized()
1957 //&& part.vbo_id != 0
1958 ) {
1959 if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) {
1960 part.offset = Vec2d(m_origin.x(), m_origin.y());
1961 part.update_buffer();
1962 }
1963 render_logo_texture(*(part.texture),
1964 *(part.buffer),
1965 bottom);
1966 }
1967 }
1968 }
1969
1970 // render cali texture
1971 if (render_cali) {
1972 for (auto& part : m_partplate_list->cali_texture_info.parts) {
1973 if (part.texture) {
1974 if (part.buffer && part.buffer->is_initialized()) {
1975 if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) {
1976 part.offset = Vec2d(m_origin.x(), m_origin.y());
1977 part.update_buffer();
1978 }
1979 render_logo_texture(*(part.texture),
1980 *(part.buffer),
1981 bottom);
1982 }
1983 }
1984 }
1985 }
1986
1987 //render extruder_only_area_info
1988 bool is_zh = wxGetApp().app_config->get("language") == "zh_CN";
1989 int language_idx = (int) (is_zh ? ExtruderOnlyAreaType::Chinese:ExtruderOnlyAreaType::Engilish);
1990 if (!is_single_extruder) {
1991 for (auto &part : m_partplate_list->extruder_only_area_info[language_idx].parts) {
1992 if (part.texture) {
1993 if (part.buffer && part.buffer->is_initialized()) {
1994 if (part.offset.x() != m_origin.x() || part.offset.y() != m_origin.y()) {
1995 part.offset = Vec2d(m_origin.x(), m_origin.y());
1996 part.update_buffer();
1997 }
1998 render_logo_texture(*(part.texture), *(part.buffer), bottom);
1999 }
2000 }
2001 }
2002 }
2003}
GLModel m_logo_triangles
Definition PartPlate.hpp:173
void render_logo_texture(GLTexture &logo_texture, GLModel &logo_buffer, bool bottom)
Definition PartPlate.cpp:1878
@ Chinese
Definition PrintConfig.hpp:521
@ Engilish
Definition PrintConfig.hpp:520
zaa_minimize_perimeter_height curr_bed_type((ConfigOptionInts, cool_plate_temp))((ConfigOptionInts

References Slic3r::btDefault, Slic3r::Chinese, Slic3r::curr_bed_type(), Slic3r::Engilish, get_bed_type(), Slic3r::ConfigOptionResolver::has(), m_logo_triangles, m_origin, m_partplate_list, Slic3r::DynamicConfig::opt_enum(), and render_logo_texture().

Referenced by render().

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

◆ render_logo_texture()

void Slic3r::GUI::PartPlate::render_logo_texture ( GLTexture & logo_texture,
GLModel & logo_buffer,
bool bottom )
private
1879{
1880 //check valid
1881 if (logo_texture.unsent_compressed_data_available()) {
1882 // sends to gpu the already available compressed levels of the main texture
1883 logo_texture.send_compressed_data_to_gpu();
1884 }
1885
1886 if (logo_buffer.is_initialized()) {
1887 GLShaderProgram* shader = wxGetApp().get_shader("printbed");
1888 if (shader != nullptr) {
1889 shader->start_using();
1890 const Camera &camera = wxGetApp().plater()->get_camera();
1891 shader->set_uniform("view_model_matrix", camera.get_view_matrix());
1892 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
1893 shader->set_uniform("transparent_background", 0);
1894 shader->set_uniform("svg_source", 0);
1895
1896 //glsafe(::glEnable(GL_DEPTH_TEST));
1898
1901
1902 if (bottom)
1904
1905 // show the temporary texture while no compressed data is available
1906 GLuint tex_id = (GLuint)logo_texture.get_id();
1907
1909 logo_buffer.render();
1911
1912 if (bottom)
1914
1916
1918
1919 shader->stop_using();
1920 }
1921 }
1922}
#define GL_CW
Definition gl.h:520
#define GL_CCW
Definition gl.h:317
#define glFrontFace
Definition gl.h:3765

References Slic3r::GUI::GLTexture::get_id(), Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), GL_BLEND, GL_CCW, GL_CW, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TEXTURE_2D, GL_TRUE, glBindTexture, glBlendFunc, glDepthMask, glDisable, glEnable, glFrontFace, glsafe, Slic3r::GUI::GLModel::is_initialized(), Slic3r::GUI::GLModel::render(), Slic3r::GUI::GLTexture::send_compressed_data_to_gpu(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), and Slic3r::GUI::GLTexture::unsent_compressed_data_available().

Referenced by render_logo().

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

◆ render_only_numbers()

void Slic3r::GUI::PartPlate::render_only_numbers ( bool bottom)
private
2769{
2770 GLShaderProgram* shader = wxGetApp().get_shader("printbed");
2771 if (shader != nullptr) {
2772 shader->start_using();
2773 const Camera &camera = wxGetApp().plater()->get_camera();
2774 shader->set_uniform("view_model_matrix", camera.get_view_matrix());
2775 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
2776 shader->set_uniform("transparent_background", bottom);
2777 //shader->set_uniform("svg_source", boost::algorithm::iends_with(m_partplate_list->m_del_texture.get_source(), ".svg"));
2778 shader->set_uniform("svg_source", 0);
2779
2780 //if (bottom)
2781 // glsafe(::glFrontFace(GL_CW));
2783
2786
2789 }
2790
2792
2793 //if (bottom)
2794 // glsafe(::glFrontFace(GL_CCW));
2795
2797 shader->stop_using();
2798 }
2799}

References Slic3r::GUI::Camera::get_projection_matrix(), Slic3r::GUI::Camera::get_view_matrix(), GL_BLEND, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TRUE, glBlendFunc, glDepthMask, glDisable, glEnable, glsafe, m_partplate_list, m_plate_idx_icon, m_plate_index, MAX_PLATE_COUNT, render_icon_texture(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by render().

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

◆ render_plate_name_texture()

void Slic3r::GUI::PartPlate::render_plate_name_texture ( )
private
2570{
2571 if (m_plate_name_edit_icon.mesh_raycaster == nullptr)
2573
2574 if (m_name_texture.get_id() == 0)
2575 return;
2576
2577 GLuint tex_id = (GLuint)m_name_texture.get_id();
2579 m_plate_name_icon.render();
2581}
void generate_plate_name_texture()
Definition PartPlate.cpp:4277

References generate_plate_name_texture(), GL_TEXTURE_2D, glBindTexture, glsafe, m_name_texture, m_plate_name_edit_icon, and m_plate_name_icon.

Referenced by render_icons().

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

◆ render_wrapping_detection_area()

void Slic3r::GUI::PartPlate::render_wrapping_detection_area ( bool force_default_color)
private
2006{
2007 if (force_default_color || !m_wrapping_detection_triangles.is_initialized())
2008 return;
2009 ColorRGBA select_color{0.765f, 0.7686f, 0.7686f, 1.0f};
2010 m_wrapping_detection_triangles.set_color(select_color);
2012}

References m_wrapping_detection_triangles.

Referenced by render().

Here is the caller graph for this function:

◆ reset_bed_type()

void Slic3r::GUI::PartPlate::reset_bed_type ( )
315{
316 m_config.erase("curr_bed_type");
317}

References m_config.

Referenced by Slic3r::GUI::TabPrintPlate::on_value_change(), and Slic3r::GUI::TabPrintPlate::reset_model_config().

Here is the caller graph for this function:

◆ reset_imex_head_filament_map()

void Slic3r::GUI::PartPlate::reset_imex_head_filament_map ( )
536{
537 m_config.erase("imex_head_filament_map");
539}

References m_config, and update_slice_result_valid_state().

Here is the call graph for this function:

◆ reset_imex_mode()

void Slic3r::GUI::PartPlate::reset_imex_mode ( )
500{
501 m_config.erase("imex_parallel_mode");
504 m_imex_ghost_cache_key = "\x01";
505}

References m_config, m_imex_ghost_cache_key, m_imex_zones_mode_cache, and update_slice_result_valid_state().

Here is the call graph for this function:

◆ reset_skirt_start_angle()

void Slic3r::GUI::PartPlate::reset_skirt_start_angle ( )
320{
321 m_config.erase("skirt_start_angle");
322}

References m_config.

◆ resolve_active_mode_tools()

bool Slic3r::GUI::PartPlate::resolve_active_mode_tools ( std::string & out_tools_str,
int & out_primary_phys ) const
private
866{
867 if (!wxGetApp().preset_bundle) return false;
868 const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
869 auto* is_imex_opt = printer_cfg.option<ConfigOptionBool>("is_imex");
870 if (!is_imex_opt || !is_imex_opt->value) return false;
871
872 const std::string active_mode = get_effective_imex_mode();
873 if (active_mode == kImexPrimaryMode) return false;
874
875 const ImexMode mode = find_imex_mode(printer_cfg, active_mode);
876 if (!mode.found()) return false;
877
878 // Also the ragged case: a tools array too short to reach this row hands back an empty
879 // string, which has no declared primary, which is the same "no zones here" answer the
880 // explicit bounds check used to give.
881 const int primary_phys = imex_primary_tool_for_mode(mode.active_tools);
882 if (primary_phys < 0) return false;
883
884 out_tools_str = mode.active_tools;
885 out_primary_phys = primary_phys;
886 return true;
887}
int imex_primary_tool_for_mode(const std::string &active_tools_for_mode)
Definition IMEXHelpers.cpp:422

References Slic3r::ImexMode::active_tools, Slic3r::find_imex_mode(), Slic3r::ImexMode::found(), get_effective_imex_mode(), Slic3r::imex_primary_tool_for_mode(), Slic3r::kImexPrimaryMode, and Slic3r::ConfigBase::option().

Referenced by build_imex_cache_key(), calc_imex_ghosts(), render_icons(), and update_imex_ghost_transforms().

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

◆ save()

template<class Archive>
void Slic3r::GUI::PartPlate::save ( Archive & ar) const
inline
747 {
748 std::vector<std::pair<int, int>> objects_and_instances;
749 std::vector<std::pair<int, int>> instances_outside;
750
751 for (std::set<std::pair<int, int>>::iterator it = instance_outside_set.begin(); it != instance_outside_set.end(); ++it)
752 instances_outside.emplace_back(it->first, it->second);
753
754 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
755 objects_and_instances.emplace_back(it->first, it->second);
756
758 }

References instance_outside_set, m_apply_invalid, m_config, m_depth, m_height, m_locked, m_name, m_origin, m_plate_index, m_print_index, m_printable, m_ready_for_slice, m_selected, m_slice_result_valid, m_tmp_gcode_path, m_width, and obj_to_instance_set.

◆ serialize()

template<class Archive>
void Slic3r::ObjectBase::serialize ( Archive & ar)
inlineprivateinherited
108{ ar(m_id); }

References m_id.

◆ set_bed_type()

void Slic3r::GUI::PartPlate::set_bed_type ( BedType bed_type)
285{
286 std::string bed_type_key = "curr_bed_type";
287
288 // should be called in GUI context
289 assert(m_plater != nullptr);
290
291 // update slice state
292 BedType old_real_bed_type = get_bed_type();
293 if (old_real_bed_type == btDefault) {
294 DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
295 if (proj_cfg.has(bed_type_key))
296 old_real_bed_type = proj_cfg.opt_enum<BedType>(bed_type_key);
297 }
298 BedType new_real_bed_type = bed_type;
299 if (bed_type == BedType::btDefault) {
300 DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
301 if (proj_cfg.has(bed_type_key))
302 new_real_bed_type = proj_cfg.opt_enum<BedType>(bed_type_key);
303 }
304 if (old_real_bed_type != new_real_bed_type) {
306 }
307
308 if (bed_type == BedType::btDefault)
309 m_config.erase(bed_type_key);
310 else
311 m_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(bed_type));
312}

References Slic3r::btDefault, get_bed_type(), Slic3r::ConfigOptionResolver::has(), m_config, m_plater, Slic3r::DynamicConfig::opt_enum(), and update_slice_result_valid_state().

Referenced by Slic3r::GUI::PartPlateList::check_all_plate_local_bed_type(), and Slic3r::GUI::Plater::open_platesettings_dialog().

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

◆ set_filament_count()

void Slic3r::GUI::PartPlate::set_filament_count ( int filament_count)
5868{
5869 if (m_config.has("filament_map")) {
5870 std::vector<int>& filament_maps = m_config.option<ConfigOptionInts>("filament_map")->values;
5871 filament_maps.resize(filament_count, 1);
5872 }
5873
5874 if (m_config.has("filament_nozzle_map")) {
5875 std::vector<int>& filament_nozzle_map = m_config.option<ConfigOptionInts>("filament_nozzle_map")->values;
5876 filament_nozzle_map.resize(filament_count, 0);
5877 }
5878
5879 if (m_config.has("filament_volume_map")) {
5880 std::vector<int>& filament_volume_map = m_config.option<ConfigOptionInts>("filament_volume_map")->values;
5881 filament_volume_map.resize(filament_count, static_cast<int>(NozzleVolumeType::nvtStandard));
5882 }
5883}
void resize(size_t n, const ConfigOption *opt_default=nullptr) override
Definition Config.hpp:687

References Slic3r::filament_nozzle_map(), m_config, and Slic3r::nvtStandard.

Referenced by Slic3r::GUI::PartPlateList::create_plate().

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

◆ set_filament_map_mode()

void Slic3r::GUI::PartPlate::set_filament_map_mode ( const FilamentMapMode & mode)
5775{
5776 const auto& proj_config = wxGetApp().preset_bundle->project_config;
5777 FilamentMapMode global_mode = proj_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode")->value;
5779 FilamentMapMode old_real_mode = old_mode == fmmDefault ? global_mode : old_mode;
5780 FilamentMapMode new_real_mode = mode == fmmDefault ? global_mode : mode;
5781
5782 if (old_real_mode != new_real_mode)
5784 if (mode == fmmDefault)
5786 else
5787 m_config.option<ConfigOptionEnum<FilamentMapMode>>("filament_map_mode", true)->value = mode;
5789}
void clear_filament_map_mode()
Definition PartPlate.cpp:5847

References clear_filament_map(), clear_filament_map_mode(), Slic3r::fmmDefault, get_filament_map_mode(), invalidate_exclusion_volume_preview(), and m_config.

Referenced by Slic3r::GUI::Plater::open_filament_map_setting_dialog(), Slic3r::GUI::GCodeViewer::render_legend_color_arr_recommen(), and Slic3r::GUI::try_pop_up_before_slice().

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

◆ set_filament_maps()

void Slic3r::GUI::PartPlate::set_filament_maps ( const std::vector< int > & f_maps)
5801{
5802 m_config.option<ConfigOptionInts>("filament_map", true)->values = f_maps;
5804}

References invalidate_exclusion_volume_preview(), and m_config.

Referenced by Slic3r::GUI::Plater::open_filament_map_setting_dialog(), Slic3r::CLI::run(), and Slic3r::GUI::try_pop_up_before_slice().

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

◆ set_filament_nozzle_maps()

void Slic3r::GUI::PartPlate::set_filament_nozzle_maps ( const std::vector< int > & f_maps)
5843{
5844 m_config.option<ConfigOptionInts>("filament_nozzle_map", true)->values = f_maps;
5845}

References m_config.

Referenced by Slic3r::CLI::run().

Here is the caller graph for this function:

◆ set_filament_volume_maps()

void Slic3r::GUI::PartPlate::set_filament_volume_maps ( const std::vector< int > & f_maps)
5823{
5824 m_config.option<ConfigOptionInts>("filament_volume_map", true)->values = f_maps;
5825}

References m_config.

Referenced by Slic3r::GUI::Plater::open_filament_map_setting_dialog(), Slic3r::CLI::run(), and Slic3r::GUI::try_pop_up_before_slice().

Here is the caller graph for this function:

◆ set_first_layer_print_sequence()

void Slic3r::GUI::PartPlate::set_first_layer_print_sequence ( const std::vector< int > & sorted_filaments)
5626{
5627 if (sorted_filaments.size() > 0) {
5628 if (sorted_filaments.size() == 1 && sorted_filaments[0] == 0) {
5629 m_config.erase("first_layer_print_sequence");
5630 }
5631 else {
5632 ConfigOptionInts *op_print_sequence_1st = m_config.option<ConfigOptionInts>("first_layer_print_sequence");
5633 if (op_print_sequence_1st)
5634 op_print_sequence_1st->values = sorted_filaments;
5635 else
5636 m_config.set_key_value("first_layer_print_sequence", new ConfigOptionInts(sorted_filaments));
5637 }
5638 }
5639 else {
5640 m_config.erase("first_layer_print_sequence");
5641 }
5642}

References m_config, and Slic3r::ConfigOptionVector< int >::values.

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

Here is the caller graph for this function:

◆ set_hover_id()

void Slic3r::GUI::PartPlate::set_hover_id ( int id)
inline
594{ m_hover_id = id; }

References Slic3r::ObjectBase::id(), and m_hover_id.

Here is the call graph for this function:

◆ set_hover_tooltip()

void Slic3r::GUI::PartPlate::set_hover_tooltip ( const std::string & tooltip)
private
2584{
2585 m_partplate_list->m_hover_tooltip = tooltip;
2586}

References m_partplate_list.

Referenced by render_icons().

Here is the caller graph for this function:

◆ set_imex_head_filament_map()

void Slic3r::GUI::PartPlate::set_imex_head_filament_map ( const std::map< int, int > & m)
517{
518 if (m.empty()) {
519 m_config.erase("imex_head_filament_map");
520 } else {
521 std::ostringstream os;
522 bool first = true;
523 for (const auto& [phys, slot] : m) {
524 if (!first) os << ',';
525 os << phys << ':' << slot;
526 first = false;
527 }
528 m_config.set_key_value("imex_head_filament_map", new ConfigOptionString(os.str()));
529 }
531 // No ghost rebuild: routing only affects color, which update_imex_ghost_colors
532 // restamps live every frame.
533}

References Slic3r::ConfigOptionString, m_config, and update_slice_result_valid_state().

Here is the call graph for this function:

◆ set_imex_mode()

void Slic3r::GUI::PartPlate::set_imex_mode ( const std::string & mode)
488{
489 if (mode.empty() || mode == kImexPrimaryMode) {
490 m_config.erase("imex_parallel_mode");
491 } else {
492 m_config.set_key_value("imex_parallel_mode", new ConfigOptionString(mode));
493 }
495 m_imex_zones_mode_cache = "\x01"; // force zone rebuild
496 m_imex_ghost_cache_key = "\x01"; // force ghost rebuild
497}

References Slic3r::ConfigOptionString, Slic3r::kImexPrimaryMode, m_config, m_imex_ghost_cache_key, m_imex_zones_mode_cache, and update_slice_result_valid_state().

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

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

◆ set_index()

void Slic3r::GUI::PartPlate::set_index ( int index)
4165{
4166 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": plate_id update from %1% to %2%") % m_plate_index % index;
4167
4168 m_plate_index = index;
4169 if (m_print != nullptr)
4170 m_print->set_plate_index(index);
4171}

References m_plate_index, and m_print.

Referenced by Slic3r::GUI::PartPlateList::create_plate(), Slic3r::GUI::PartPlateList::delete_plate(), Slic3r::GUI::PartPlateList::init(), and Slic3r::GUI::PartPlateList::move_plate_to_index().

Here is the caller graph for this function:

◆ set_invalid_id()

void Slic3r::ObjectBase::set_invalid_id ( )
inlineprotectedinherited
90{ m_id = 0; }

References m_id.

Referenced by Slic3r::CutObjectBase::invalidate().

Here is the caller graph for this function:

◆ set_new_unique_id()

void Slic3r::ObjectBase::set_new_unique_id ( )
inlineprotectedinherited
89{ m_id = generate_new_id(); }
static ObjectID generate_new_id()
Definition ObjectID.hpp:100

References generate_new_id(), and m_id.

Referenced by Slic3r::ModelVolume::ModelVolume(), Slic3r::Model::assign_new_unique_ids_recursive(), Slic3r::ModelVolume::assign_new_unique_ids_recursive(), assign_new_unique_ids_recursive(), Slic3r::CutObjectBase::init(), Slic3r::ModelMaterial::set_new_unique_id(), Slic3r::ModelObject::set_new_unique_id(), and Slic3r::ModelVolume::set_new_unique_id().

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

◆ set_other_layers_print_sequence()

void Slic3r::GUI::PartPlate::set_other_layers_print_sequence ( const std::vector< LayerPrintSequence > & layer_seq_list)
5645{
5646 if (layer_seq_list.empty()) {
5647 m_config.erase("other_layers_print_sequence");
5648 m_config.erase("other_layers_print_sequence_nums");
5649 return;
5650 }
5651
5652 int sequence_nums;
5653 std::vector<int> other_layers_seqs;
5654 Slic3r::get_other_layers_print_sequence(layer_seq_list, sequence_nums, other_layers_seqs);
5655 ConfigOptionInts* other_layers_print_sequence_op = m_config.option<ConfigOptionInts>("other_layers_print_sequence");
5656 ConfigOptionInt* other_layers_print_sequence_nums_op = m_config.option<ConfigOptionInt>("other_layers_print_sequence_nums");
5657 if (other_layers_print_sequence_op)
5658 other_layers_print_sequence_op->values = other_layers_seqs;
5659 else
5660 m_config.set_key_value("other_layers_print_sequence", new ConfigOptionInts(other_layers_seqs));
5661 if (other_layers_print_sequence_nums_op)
5662 other_layers_print_sequence_nums_op->value = sequence_nums;
5663 else
5664 m_config.set_key_value("other_layers_print_sequence_nums", new ConfigOptionInt(sequence_nums));
5665}

References Slic3r::get_other_layers_print_sequence(), m_config, and Slic3r::ConfigOptionVector< int >::values.

Referenced by Slic3r::GUI::Plater::open_platesettings_dialog(), update_first_layer_print_sequence(), and update_first_layer_print_sequence_when_delete_filament().

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

◆ set_plate_name()

void Slic3r::GUI::PartPlate::set_plate_name ( const std::string & name)
4339{
4340 // compare if name equal to m_name, case sensitive
4341 if (boost::equals(m_name, name))
4342 return;
4343
4344 const std::string previous_name = m_name;
4345 m_name = name;
4346 if (m_print != nullptr)
4347 m_print->set_plate_name(name);
4348
4350
4351 if (m_plater != nullptr && !m_plater->is_loading_project()) {
4352 LifecycleEventContext ctx;
4353 ctx.name = name;
4354 ctx.previous_name = previous_name;
4355 ctx.index = m_plate_index;
4357 }
4358}
@ PlateRenamed
Definition LifecycleEvents.hpp:44
void fire_lifecycle_event(LifecycleEvent event, const LifecycleEventContext &ctx)
Definition LifecycleEvents.hpp:234

References Slic3r::fire_lifecycle_event(), Slic3r::LifecycleEventContext::index, invalidate_plate_name_texture(), m_name, m_plate_index, m_plater, m_print, Slic3r::LifecycleEventContext::name, Slic3r::PlateRenamed, and Slic3r::LifecycleEventContext::previous_name.

Referenced by Slic3r::GUI::anonymous_namespace{NativeCommands.cpp}::build_command_catalog(), Slic3r::GUI::Plater::open_platesettings_dialog(), and Slic3r::GUI::Plater::select_plate_by_hover_id().

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

◆ set_pos_and_size()

void Slic3r::GUI::PartPlate::set_pos_and_size ( Vec3d & origin,
int width,
int depth,
double height,
bool with_instance_move,
bool do_clear = true )
4189{
4190 bool size_changed = false; //size changed means the machine changed
4191 bool pos_changed = false;
4192
4193 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate_id %1%, before, origin {%2%,%3%,%4%}, plate_width %5%, plate_depth %6%, plate_height %7%")\
4195 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": with_instance_move %1%, after, origin {%2%,%3%,%4%}, plate_width %5%, plate_depth %6%, plate_height %7%")\
4196 % with_instance_move % origin.x() % origin.y() % origin.z() % width % depth % height;
4197 size_changed = ((width != m_width) || (depth != m_depth) || (height != m_height));
4198 pos_changed = (m_origin != origin);
4199
4200 if ((!size_changed) && (!pos_changed))
4201 {
4202 //size and position the same with before, just return
4203 return;
4204 }
4205
4206 if (with_instance_move && m_model)
4207 {
4208 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
4209 int obj_id = it->first;
4210 int instance_id = it->second;
4211 if (!valid_instance(obj_id, instance_id))
4212 continue;
4213
4214 ModelObject* object = m_model->objects[obj_id];
4215 ModelInstance* instance = object->instances[instance_id];
4216
4217 //move this instance into the new plate's same position
4218 Vec3d offset = instance->get_transformation().get_offset();
4219 int off_x, off_y;
4220
4221 if (size_changed)
4222 {
4223 //change position due to the bed size changes
4224 //off_x = (width - m_width) * m_plate_index + (width - m_width) / 2;
4225 //off_y = (depth - m_depth) * m_plate_index + (depth - m_depth) / 2;
4226 off_x = origin.x() - m_origin.x() + (width - m_width) / 2;
4227 off_y = origin.y() - m_origin.y() + (depth - m_depth) / 2;
4228 }
4229 else
4230 {
4231 //change position due to the plate moves
4232 off_x = origin.x() - m_origin.x();
4233 off_y = origin.y() - m_origin.y();
4234 }
4235 offset.x() = offset.x() + off_x;
4236 offset.y() = offset.y() + off_y;
4237
4238 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": object %1%, instance %2%, moved {%3%,%4%} to {%5%, %6%}")\
4239 % obj_id % instance_id % off_x % off_y % offset.x() % offset.y();
4240
4241 instance->set_offset(offset);
4242 object->invalidate_bounding_box();
4243 }
4244 }
4245 else if (do_clear)
4246 {
4247 clear();
4248 }
4249
4250 if (m_print)
4251 m_print->set_plate_origin(origin);
4252
4253 m_origin = origin;
4254 m_width = width;
4255 m_depth = depth;
4256 m_height = height;
4258
4259 if (with_instance_move && m_plater)
4260 m_plater->mark_plate_toolbar_image_dirty();
4261
4262 return;
4263}
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582

References clear(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::ModelInstance::get_transformation(), invalidate_exclusion_volume_preview(), m_depth, m_height, m_model, m_origin, m_plate_index, m_plater, m_print, m_width, obj_to_instance_set, Slic3r::offset(), Slic3r::ModelInstance::set_offset(), and valid_instance().

Referenced by Slic3r::GUI::PartPlateList::delete_plate(), Slic3r::GUI::PartPlateList::move_plate_to_index(), and Slic3r::GUI::PartPlateList::update_all_plates_pos_and_size().

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

◆ set_print()

void Slic3r::GUI::PartPlate::set_print ( PrintBase * print,
GCodeResult * result = nullptr,
int index = -1 )
4377{
4379 m_print = static_cast<Print*>(print);
4380 //todo, for other printers
4381
4382 m_gcode_result = result;
4383 if (index >= 0)
4384 m_print_index = index;
4385
4386 m_print->set_plate_origin(m_origin);
4388
4389 return;
4390}

References invalidate_exclusion_volume_preview(), m_gcode_result, m_origin, m_print, m_print_index, print(), printer_technology, and Slic3r::ptFFF.

Referenced by Slic3r::GUI::PartPlateList::create_plate(), and Slic3r::GUI::PartPlateList::init().

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

◆ set_print_seq()

void Slic3r::GUI::PartPlate::set_print_seq ( PrintSequence print_seq = PrintSequence::ByDefault)
325{
326 std::string print_seq_key = "print_sequence";
327
328 // should be called in GUI context
329 assert(m_plater != nullptr);
330
331 // update slice state
332 PrintSequence old_real_print_seq = get_print_seq();
333 if (old_real_print_seq == PrintSequence::ByDefault) {
334 auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
335 if (curr_preset_config.has(print_seq_key))
336 old_real_print_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>(print_seq_key)->value;
337 }
338
339 PrintSequence new_real_print_seq = print_seq;
340
341 if (print_seq == PrintSequence::ByDefault) {
342 auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
343 if (curr_preset_config.has(print_seq_key))
344 new_real_print_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>(print_seq_key)->value;
345 }
346
347 if (old_real_print_seq != new_real_print_seq) {
349 }
350
351 //print_seq_same_global = same_global;
352 if (print_seq == PrintSequence::ByDefault)
353 m_config.erase(print_seq_key);
354 else
355 m_config.set_key_value(print_seq_key, new ConfigOptionEnum<PrintSequence>(print_seq));
356}

References Slic3r::ByDefault, get_print_seq(), m_config, m_plater, and update_slice_result_valid_state().

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

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

◆ set_selected()

void Slic3r::GUI::PartPlate::set_selected ( )
5384 {
5385 m_selected = true;
5386}

References m_selected.

◆ set_shape()

bool Slic3r::GUI::PartPlate::set_shape ( const Pointfs & shape,
const Pointfs & exclude_areas,
const std::vector< Pointfs > & extruder_areas,
const std::vector< double > & extruder_heights,
Vec2d position,
float height_to_lid,
float height_to_rod )
5124{
5126
5127 Pointfs new_shape, new_exclude_areas;
5128 m_extruder_heights = extruder_heights;
5129 for (const Vec2d& p : shape) {
5130 new_shape.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
5131 }
5132
5133 for (const Vec2d& p : exclude_areas) {
5134 new_exclude_areas.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
5135 }
5136
5137 std::vector<Pointfs> new_extruder_areas;
5138 for (const Pointfs& shape : extruder_areas) {
5139 Pointfs new_extruder_area;
5140 for (const Vec2d& p : shape) {
5141 Vec2d point(p(0) + position.x(), p(1) + position.y());
5142 new_extruder_area.push_back(point);
5143 }
5144 new_extruder_areas.push_back(new_extruder_area);
5145 }
5146 m_extruder_areas = std::move(new_extruder_areas);
5147
5148 if ((m_shape == new_shape)&&(m_exclude_area == new_exclude_areas)
5149 &&(m_height_to_lid == height_to_lid)&&(m_height_to_rod == height_to_rod)) {
5150 BOOST_LOG_TRIVIAL(info) << "PartPlate same shape, skip directly";
5151 return false;
5152 }
5153
5154 m_height_to_lid = height_to_lid;
5155 m_height_to_rod = height_to_rod;
5156
5157 if ((m_shape != new_shape) || (m_exclude_area != new_exclude_areas))
5158 {
5159 /*m_shape.clear();
5160 for (const Vec2d& p : shape) {
5161 m_shape.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
5162 }
5163
5164 m_exclude_area.clear();
5165 for (const Vec2d& p : exclude_areas) {
5166 m_exclude_area.push_back(Vec2d(p.x() + position.x(), p.y() + position.y()));
5167 }*/
5168 m_shape = std::move(new_shape);
5169 m_exclude_area = std::move(new_exclude_areas);
5170
5172
5173 if (m_plater != nullptr) { // render data, skip in CLI mode where m_plater is null
5174 ExPolygon logo_poly;
5175 generate_logo_polygon(logo_poly);
5176 m_logo_triangles.reset();
5177 if (!init_model_from_poly(m_logo_triangles, logo_poly, GROUND_Z + 0.02f))
5178 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create logo triangles\n";
5179
5180 ExPolygon poly;
5182 calc_triangles(poly);
5183
5184 // reset m_wrapping_detection_triangles when change printer
5188
5189 ExPolygon exclude_poly;
5190 generate_exclude_polygon(exclude_poly);
5191 calc_exclude_triangles(exclude_poly);
5192
5193 const BoundingBox& pp_bbox = poly.contour.bounding_box();
5194 calc_gridlines(poly, pp_bbox);
5195 m_imex_zones_mode_cache = "\x01"; // force rebuild on next render
5197
5203 // ORCA also change bed_icon_count number in calc_vertex_for_icons() after adding or removing icons for circular shaped beds that uses vertical alingment for icons
5204 bool dual_bbl = false;
5205 PresetBundle* preset = wxGetApp().preset_bundle;
5206 dual_bbl = (preset->is_bbl_vendor() && preset->get_printer_extruder_count() == 2);
5208 calc_vertex_for_icons(dual_bbl ? 6 : 5, m_move_front_icon);
5209 {
5210 auto* is_imex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex");
5211 if (is_imex_opt && is_imex_opt->value) {
5212 int imex_slot = dual_bbl ? 7 : 6;
5215 }
5216 }
5217
5219 // calc vertex for plate name
5221 }
5222 }
5223
5225
5226 return true;
5227}
void calc_triangles(const ExPolygon &poly)
Definition PartPlate.cpp:646
Slic3r::Geometry::Transformation position
Definition PartPlate.hpp:159
void calc_bounding_boxes() const
Definition PartPlate.cpp:607
void calc_exclude_triangles(const ExPolygon &poly)
Definition PartPlate.cpp:654
void calc_height_limit()
Definition PartPlate.cpp:1654
void generate_logo_polygon(ExPolygon &logo_polygon)
Definition PartPlate.cpp:5007
void calc_vertex_for_number(int index, bool one_number, GLModel &buffer)
Definition PartPlate.cpp:1711
void generate_exclude_polygon(ExPolygon &exclude_polygon)
Definition PartPlate.cpp:5057
void calc_gridlines(const ExPolygon &poly, const BoundingBox &pp_bbox)
Definition PartPlate.cpp:1631
std::vector< Vec2d > Pointfs
Definition Point.hpp:77

References calc_bounding_boxes(), calc_exclude_triangles(), calc_gridlines(), calc_height_limit(), calc_imex_zones(), calc_triangles(), calc_vertex_for_icons(), calc_vertex_for_imex_warn_badge(), calc_vertex_for_number(), Slic3r::Preset::config, generate_exclude_polygon(), generate_logo_polygon(), generate_print_polygon(), Slic3r::PresetCollection::get_edited_preset(), Slic3r::PresetBundle::get_printer_extruder_count(), GROUND_Z, Slic3r::GUI::init_model_from_poly(), Slic3r::GUI::init_raycaster_from_model(), invalidate_exclusion_volume_preview(), invalidate_plate_name_texture(), Slic3r::PresetBundle::is_bbl_vendor(), m_arrange_icon, m_del_icon, m_exclude_area, m_extruder_areas, m_extruder_heights, m_height_to_lid, m_height_to_rod, m_imex_mode_icon, m_imex_warn_icon, m_imex_zones_mode_cache, m_lock_icon, m_logo_triangles, m_move_front_icon, m_orient_icon, m_plate_filament_map_icon, m_plate_idx_icon, m_plate_settings_icon, m_plater, m_print_polygon, m_shape, m_triangles, m_wrapping_detection_triangles, Slic3r::ConfigBase::option(), position, and Slic3r::PresetBundle::printers.

Referenced by Slic3r::GUI::PartPlateList::create_plate(), Slic3r::GUI::PartPlateList::delete_plate(), and Slic3r::GUI::PartPlateList::set_shapes().

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

◆ set_spiral_vase_mode()

void Slic3r::GUI::PartPlate::set_spiral_vase_mode ( bool spiral_mode,
bool as_global )
575{
576 std::string key = "spiral_mode";
577 if (as_global)
578 m_config.erase(key);
579 else {
580 if (spiral_mode) {
582 return;
583 // Secondary confirmation
584 auto answer = static_cast<TabPrintPlate*>(wxGetApp().plate_tab)->show_spiral_mode_settings_dialog(false);
585 if (answer == wxID_YES) {
586 m_config.set_key_value(key, new ConfigOptionBool(true));
588 }
589 }
590 else
591 m_config.set_key_value(key, new ConfigOptionBool(false));
592 }
593}
bool get_spiral_vase_mode() const
Definition PartPlate.cpp:428
void set_vase_mode_related_object_config(int obj_id=-1)
Definition PartPlate.cpp:4885

References get_spiral_vase_mode(), m_config, and set_vase_mode_related_object_config().

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

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

◆ set_timelapse_warning_code()

void Slic3r::GUI::PartPlate::set_timelapse_warning_code ( int code)
inline
452{ m_timelapse_warning_code = code; }
int m_timelapse_warning_code
Definition PartPlate.hpp:208

References m_timelapse_warning_code.

◆ set_tmp_gcode_path()

void Slic3r::GUI::PartPlate::set_tmp_gcode_path ( std::string new_path)
inline
704 {
705 m_tmp_gcode_path = new_path;
706 }

References m_tmp_gcode_path.

Referenced by Slic3r::CLI::run().

Here is the caller graph for this function:

◆ set_unselected()

void Slic3r::GUI::PartPlate::set_unselected ( )
5388 {
5389 m_selected = false;
5390}

References m_selected.

◆ set_vase_mode_related_object_config()

void Slic3r::GUI::PartPlate::set_vase_mode_related_object_config ( int obj_id = -1)
4885 {
4886 ModelObjectPtrs obj_ptrs;
4887 if (obj_id != -1) {
4888 ModelObject* object = m_model->objects[obj_id];
4889 obj_ptrs.push_back(object);
4890 }
4891 else
4892 obj_ptrs = get_objects_on_this_plate();
4893
4894 DynamicPrintConfig* global_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
4895 DynamicPrintConfig new_conf;
4896 new_conf.set_key_value("wall_loops", new ConfigOptionInt(1));
4897 new_conf.set_key_value("top_shell_layers", new ConfigOptionInt(0));
4898 new_conf.set_key_value("sparse_infill_density", new ConfigOptionPercent(0));
4899 new_conf.set_key_value("enable_support", new ConfigOptionBool(false));
4900 new_conf.set_key_value("enforce_support_layers", new ConfigOptionInt(0));
4901 new_conf.set_key_value("detect_thin_wall", new ConfigOptionBool(false));
4902 new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
4903 new_conf.set_key_value("overhang_reverse", new ConfigOptionBool(false));
4904 const auto applying_keys = global_config->diff(new_conf);
4905
4906 for (ModelObject* object : obj_ptrs) {
4907 ModelConfigObject& config = object->config;
4908
4909 for (auto opt_key : applying_keys) {
4910 config.set_key_value(opt_key, new_conf.option(opt_key)->clone());
4911 }
4912
4913 const auto object_keys = config.get().diff(new_conf);
4914 for (auto opt_key : object_keys) {
4915 config.set_key_value(opt_key, new_conf.option(opt_key)->clone());
4916 }
4917 }
4918 //wxGetApp().obj_list()->update_selections();
4919}
ModelObjectPtrs get_objects_on_this_plate()
Definition PartPlate.cpp:4412
@ tlTraditional
Definition PrintConfig.hpp:469

References Slic3r::ConfigOption::clone(), config(), Slic3r::DynamicConfig::diff(), get_objects_on_this_plate(), m_model, Slic3r::ConfigBase::option(), Slic3r::DynamicConfig::set_key_value(), and Slic3r::tlTraditional.

Referenced by Slic3r::GUI::PartPlateList::notify_instance_update(), and set_spiral_vase_mode().

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

◆ timelapse_warning_code()

int Slic3r::GUI::PartPlate::timelapse_warning_code ( )
inline

◆ timestamp()

virtual Timestamp Slic3r::ObjectBase::timestamp ( ) const
inlinevirtualinherited

Reimplemented in Slic3r::ModelConfigObject, and Slic3r::ObjectWithTimestamp.

74{ return 0; }

◆ translate_all_instance()

void Slic3r::GUI::PartPlate::translate_all_instance ( Vec3d position)
4745{
4746 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
4747 {
4748 int obj_id = it->first;
4749 int instance_id = it->second;
4750
4751 if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
4752 {
4753 ModelObject* object = m_model->objects[obj_id];
4754 if ((instance_id >= 0) && (instance_id < object->instances.size()))
4755 {
4756 ModelInstance* instance = object->instances[instance_id];
4757 const Vec3d& offset = instance->get_offset();
4758 instance->set_offset(offset + position);
4759 }
4760 }
4761 }
4763 return;
4764}

References Slic3r::ModelInstance::get_offset(), invalidate_exclusion_volume_preview(), m_model, obj_to_instance_set, Slic3r::offset(), position, and Slic3r::ModelInstance::set_offset().

Referenced by Slic3r::GUI::PartPlateList::duplicate_plate(), and Slic3r::CLI::run().

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

◆ update_apply_result_invalid()

void Slic3r::GUI::PartPlate::update_apply_result_invalid ( bool invalid)
inline
655 {
656 m_apply_invalid = invalid;
657 }

References m_apply_invalid.

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

Here is the caller graph for this function:

◆ update_exclusion_volume_preview_models()

void Slic3r::GUI::PartPlate::update_exclusion_volume_preview_models ( )
private
2129{
2131 return;
2133
2134 const DynamicPrintConfig *config = m_plater != nullptr ? m_plater->config() : nullptr;
2135 if (config == nullptr) {
2143 return;
2144 }
2145
2146 const std::vector<std::vector<BedExcludeRegion>> regions_by_extruder = get_bed_excluded_regions_by_extruder(*config);
2147 std::vector<BedExcludeRegion> regions;
2149 for (size_t extruder_id = 0; extruder_id < regions_by_extruder.size(); ++extruder_id) {
2150 if (mode == BedExcludeVolumeMode::Shared && extruder_id > 0)
2151 break;
2152 for (const BedExcludeRegion &region : regions_by_extruder[extruder_id]) {
2153 if (!region.is_collision_volume() && extruder_id > 0)
2154 continue;
2155 regions.emplace_back(region);
2156 }
2157 }
2158 // A coloured border communicates which physical nozzle owns a footprint.
2159 // With only one nozzle the exclusion applies to every filament, so using
2160 // the first filament colour would incorrectly imply material ownership.
2161 const bool show_nozzle_ownership =
2162 regions_by_extruder.size() > 1 && mode != BedExcludeVolumeMode::Shared;
2163 std::ostringstream grouped_key;
2164 const bool show_all_volumes = m_plater->are_collision_volumes_shown();
2165 grouped_key << exclusion_volume_preview_cache_key(regions) << "mode:" << int(mode)
2166 << ";show_all:" << show_all_volumes << ";groups:";
2167 for (const std::vector<BedExcludeRegion> &group : regions_by_extruder)
2168 grouped_key << group.size() << ',';
2169 const std::vector<std::string> filament_colors = m_plater->get_extruder_colors_from_plater_config();
2170 std::vector<std::string> preview_colors(regions_by_extruder.size());
2171
2172 // Use the same effective filament-to-nozzle policy as collision checks so
2173 // the coloured border never implies a mapping the validator does not use.
2174 const DynamicPrintConfig &project_config = wxGetApp().preset_bundle->project_config;
2175 const std::vector<int> filament_map = get_effective_exclusion_filament_maps(
2176 project_config, filament_colors.size(), regions_by_extruder.size());
2177 grouped_key << "map:";
2178 for (const int extruder_id : filament_map)
2179 grouped_key << extruder_id << ',';
2180 grouped_key << ';';
2181 grouped_key << "object_maps:";
2182 if (m_model != nullptr) {
2183 for (const std::pair<int, int> &object_instance : obj_to_instance_set) {
2184 const int object_id = object_instance.first;
2185 if (object_id < 0 || object_id >= int(m_model->objects.size()))
2186 continue;
2187 grouped_key << object_id << ':';
2188 for (const auto &[filament_id, extruder_id] : get_object_filament_extruders(
2189 *m_model->objects[object_id], project_config, regions_by_extruder.size()))
2190 grouped_key << filament_id << '>' << extruder_id << ',';
2191 grouped_key << ';';
2192 }
2193 }
2194 for (size_t filament_id = 0; filament_id < filament_colors.size(); ++filament_id) {
2195 const int mapped_extruder = filament_id < filament_map.size() ? filament_map[filament_id] - 1 : int(filament_id);
2196 if (mapped_extruder >= 0 && size_t(mapped_extruder) < preview_colors.size() && preview_colors[mapped_extruder].empty())
2197 preview_colors[mapped_extruder] = filament_colors[filament_id];
2198 }
2199
2200 if (const ConfigOptionStrings *extruder_colors = config->opt<ConfigOptionStrings>("extruder_colour");
2201 extruder_colors != nullptr) {
2202 for (size_t extruder_id = 0; extruder_id < preview_colors.size() && extruder_id < extruder_colors->size(); ++extruder_id)
2203 if (preview_colors[extruder_id].empty())
2204 preview_colors[extruder_id] = extruder_colors->values[extruder_id];
2205 }
2206 for (const std::string &color : preview_colors)
2207 grouped_key << color << ',';
2208 const std::string cache_key = grouped_key.str();
2210 return;
2213
2219
2220 const Point plate_offset(scale_(m_origin.x()), scale_(m_origin.y()));
2221 Polygons floor_regions;
2222 ExPolygons border_regions;
2223 const coord_t ribbon_width = scale_(1.6);
2224 struct PreviewRegion {
2225 BedExcludeRegion region;
2226 Polygon footprint;
2227 size_t extruder_id;
2228 };
2229 std::vector<PreviewRegion> preview_regions;
2230 Polygons preview_footprints;
2231 std::vector<ExclusionVolumePrismPreview> active_prisms;
2232
2233 if (show_nozzle_ownership) {
2234 static const std::array<ColorRGBA, 6> fallback_colors = {
2235 ColorRGBA{ .18f, .52f, .95f, .92f }, ColorRGBA{ .95f, .35f, .22f, .92f },
2236 ColorRGBA{ .25f, .72f, .38f, .92f }, ColorRGBA{ .72f, .34f, .88f, .92f },
2237 ColorRGBA{ .95f, .68f, .16f, .92f }, ColorRGBA{ .18f, .76f, .78f, .92f }
2238 };
2239 const coord_t tool_border_width = scale_(0.55);
2240 for (size_t extruder_id = 0; extruder_id < regions_by_extruder.size(); ++extruder_id) {
2241 ColorRGBA color = fallback_colors[extruder_id % fallback_colors.size()];
2242 if (extruder_id < preview_colors.size()) {
2243 ColorRGBA decoded;
2244 if (decode_color(preview_colors[extruder_id], decoded)) {
2245 color = decoded;
2246 color.a(0.92f);
2247 }
2248 }
2249
2250 for (const BedExcludeRegion &region_src : regions_by_extruder[extruder_id]) {
2251 if (!region_src.is_collision_volume())
2252 continue;
2253 Polygon footprint = region_src.polygon;
2254 footprint.translate(plate_offset);
2255 footprint.make_counter_clockwise();
2256 const Polygons inner = offset(Polygons{ footprint }, -tool_border_width, jtMiter, 2.0);
2257 const ExPolygons border = inner.empty() ? ExPolygons{ expolygon_from_polygon(footprint) } : diff_ex(Polygons{ footprint }, inner);
2258 auto model = std::make_unique<GLModel>();
2259 // Nozzle colours identify the bed footprint, not the volume's
2260 // vertical position, so keep this border with the grey preview.
2261 const float border_z = GROUND_Z + 0.026f;
2262 if (init_model_from_expolygons(*model, border, border_z) && model->is_initialized())
2263 m_extruder_exclusion_volume_borders.emplace_back(std::move(model), color);
2264 }
2265 }
2266 }
2267
2268 for (size_t extruder_id = 0; extruder_id < regions_by_extruder.size(); ++extruder_id) {
2269 // Shared regions are identical for every nozzle. Keeping one copy
2270 // avoids duplicate floor, prism and intersection geometry.
2271 if (mode == BedExcludeVolumeMode::Shared && extruder_id > 0)
2272 break;
2273
2274 for (const BedExcludeRegion &region_src : regions_by_extruder[extruder_id]) {
2275 // The legacy area is shared and bed-fixed, even when nozzle-specific
2276 // collision volumes are active. Keep only one preview copy.
2277 if (!region_src.is_collision_volume() && extruder_id > 0)
2278 continue;
2279 Polygon region = region_src.polygon;
2280 region.translate(plate_offset);
2281 region.make_counter_clockwise();
2282 BedExcludeRegion translated_region = region_src;
2283 translated_region.polygon = region;
2284 preview_regions.push_back({ std::move(translated_region), region, extruder_id });
2285 preview_footprints.emplace_back(region);
2286
2287 // Legacy polygons continue to use Orca's existing grey bed preview;
2288 // the additional floor/ribbon belongs only to collision volumes.
2289 if (region_src.is_collision_volume()) {
2290 if (!region_src.has_z_range || region_src.z_min <= EPSILON) {
2291 floor_regions.emplace_back(region);
2292 } else {
2293 const Polygons inner = offset(Polygons{ region }, -ribbon_width, jtMiter, 2.0);
2294 ExPolygons border = inner.empty() ? ExPolygons{ expolygon_from_polygon(region) } : diff_ex(Polygons{ region }, inner);
2295 border_regions.insert(border_regions.end(), border.begin(), border.end());
2296 }
2297 }
2298 }
2299 }
2300
2301 // Automatic previews stay limited to nearby objects. The View toggle lets
2302 // profile authors inspect the complete configured height on an empty bed.
2303 const double preview_height = show_all_volumes ? 0.0 :
2305 if (show_all_volumes || preview_height > EPSILON) {
2306 for (const PreviewRegion &preview_region : preview_regions) {
2307 const BedExcludeRegion &region_src = preview_region.region;
2308 if (!region_src.is_collision_volume())
2309 continue;
2310 const double z_min = region_src.has_z_range ? region_src.z_min : 0.0;
2311 const double z_max = show_all_volumes ? region_src.z_max : std::min(region_src.z_max, preview_height);
2312 if (z_max > z_min + EPSILON)
2313 active_prisms.push_back({ preview_region.footprint, z_min, z_max });
2314 }
2315 }
2316
2317 indexed_triangle_set intersection_triangles;
2318 if (m_model != nullptr && !preview_regions.empty()) {
2319 for (const std::pair<int, int> &object_instance : obj_to_instance_set) {
2320 const int obj_id = object_instance.first;
2321 const int instance_id = object_instance.second;
2322 if (obj_id < 0 || obj_id >= int(m_model->objects.size()))
2323 continue;
2324
2325 ModelObject *object = m_model->objects[obj_id];
2326 if (instance_id < 0 || instance_id >= int(object->instances.size()))
2327 continue;
2328
2329 ModelInstance *instance = object->instances[instance_id];
2330 if (!instance->printable)
2331 continue;
2332
2333 std::set<size_t> relevant_extruders;
2334 if (mode != BedExcludeVolumeMode::Shared) {
2335 for (const auto &mapping : get_object_filament_extruders(
2336 *object, project_config, regions_by_extruder.size()))
2337 relevant_extruders.emplace(mapping.second);
2338 }
2339
2340 Polygon hull = instance->convex_hull_2d();
2341 const BoundingBoxf3 instance_box = object->instance_convex_hull_bounding_box(instance_id);
2342 for (const PreviewRegion &preview_region : preview_regions) {
2343 if (preview_region.region.is_collision_volume() && mode != BedExcludeVolumeMode::Shared &&
2344 relevant_extruders.find(preview_region.extruder_id) == relevant_extruders.end())
2345 continue;
2346
2347 const BedExcludeRegion &region = preview_region.region;
2348 if (intersection(Polygons{ preview_region.footprint }, Polygons{ hull }).empty())
2349 continue;
2350 if (instance_box.max.z() < region.z_min || instance_box.min.z() > region.z_max)
2351 continue;
2352
2353 // The preview path intentionally requests the full clipped mesh.
2354 // Boolean-only placement checks call this without an output mesh.
2355 indexed_triangle_set region_intersections;
2356 if (instance->intersects_bed_exclude_region(region, &region_intersections) && !region_intersections.empty())
2357 its_merge(intersection_triangles, region_intersections);
2358 }
2359 }
2360 }
2361
2362 if (!floor_regions.empty() && !init_model_from_polygons(m_exclusion_volume_floor_triangles, floor_regions, GROUND_Z + 0.01f))
2363 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create exclusion volume floor preview triangles\n";
2364
2365 if (!border_regions.empty() && !init_model_from_expolygons(m_exclusion_volume_border_triangles, border_regions, GROUND_Z + 0.018f))
2366 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create exclusion volume preview border\n";
2367
2368 if (!active_prisms.empty() && !init_exclusion_volume_prism_model(m_active_exclusion_volume_prisms, active_prisms))
2369 BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create active exclusion volume preview prisms\n";
2370
2371 if (!intersection_triangles.empty())
2372 m_exclusion_volume_intersection_triangles.init_from(intersection_triangles);
2373}
#define EPSILON
Definition ColorUtils.cpp:64
double max_broad_phase_intersecting_object_height(const Polygons &regions) const
Definition PartPlate.cpp:2030
std::string exclusion_volume_preview_cache_key(const std::vector< BedExcludeRegion > &regions) const
Definition PartPlate.cpp:2070
std::string m_exclusion_volume_preview_cache_key
Definition PartPlate.hpp:170
std::map< int, size_t > get_object_filament_extruders(const ModelObject &object, const DynamicConfig &g_config, size_t extruder_count) const
Definition PartPlate.cpp:3562
int64_t coord_t
Definition libslic3r.h:48
static bool init_exclusion_volume_prism_model(GLModel &model, const std::vector< ExclusionVolumePrismPreview > &prisms)
Definition PartPlate.cpp:1562
static bool init_model_from_polygons(GLModel &model, const Polygons &polygons, float z)
Definition PartPlate.cpp:1511
static bool init_model_from_expolygons(GLModel &model, const ExPolygons &expolygons, float z)
Definition PartPlate.cpp:1533
static ExPolygon expolygon_from_polygon(const Polygon &polygon)
Definition PartPlate.cpp:1473
@ jtMiter
Definition ClipperUtils.hpp:21
Slic3r::ExPolygons diff_ex(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:831
void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B)
Definition TriangleMesh.cpp:1448

References Slic3r::ColorRGBA::a(), Slic3r::active_bed_exclude_volume_mode(), config(), Slic3r::ModelInstance::convex_hull_2d(), Slic3r::GUI::decode_color(), Slic3r::diff_ex(), empty(), EPSILON, exclusion_volume_preview_cache_key(), Slic3r::GUI::expolygon_from_polygon(), Slic3r::filament_map(), Slic3r::get_bed_excluded_regions_by_extruder(), get_effective_exclusion_filament_maps(), get_object_filament_extruders(), GROUND_Z, Slic3r::BedExcludeRegion::has_z_range, Slic3r::GUI::init_exclusion_volume_prism_model(), Slic3r::GUI::init_model_from_expolygons(), Slic3r::GUI::init_model_from_polygons(), Slic3r::ModelObject::instances, Slic3r::intersection(), Slic3r::ModelInstance::intersects_bed_exclude_region(), Slic3r::BedExcludeRegion::is_collision_volume(), Slic3r::its_merge(), Slic3r::jtMiter, m_active_exclusion_volume_prisms, m_exclusion_volume_border_triangles, m_exclusion_volume_floor_triangles, m_exclusion_volume_intersection_triangles, m_exclusion_volume_intersections_cleared, m_exclusion_volume_preview_cache_key, m_exclusion_volume_preview_dirty, m_extruder_exclusion_volume_borders, m_model, m_origin, m_plater, Slic3r::Polygon::make_counter_clockwise(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, max_broad_phase_intersecting_object_height(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, obj_to_instance_set, Slic3r::offset(), Slic3r::BedExcludeRegion::polygon, Slic3r::ModelInstance::printable, scale_, Slic3r::Shared, Slic3r::MultiPoint::translate(), Slic3r::BedExcludeRegion::z_max, and Slic3r::BedExcludeRegion::z_min.

Referenced by render_exclusion_volume_previews().

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

◆ update_first_layer_print_sequence()

void Slic3r::GUI::PartPlate::update_first_layer_print_sequence ( size_t filament_nums)
5668{
5669 auto other_layers_seqs = get_other_layers_print_sequence();
5670 if (!other_layers_seqs.empty()) {
5671 bool need_update_data = false;
5672 for (auto& other_layers_seq : other_layers_seqs) {
5673 std::vector<int>& orders = other_layers_seq.second;
5674 if (orders.size() > filament_nums) {
5675 orders.erase(std::remove_if(orders.begin(), orders.end(), [filament_nums](int n) { return n > filament_nums; }), orders.end());
5676 need_update_data = true;
5677 }
5678 if (orders.size() < filament_nums) {
5679 for (size_t extruder_id = orders.size(); extruder_id < filament_nums; ++extruder_id) {
5680 orders.push_back(extruder_id + 1);
5681 need_update_data = true;
5682 }
5683 }
5684 }
5685 if (need_update_data)
5686 set_other_layers_print_sequence(other_layers_seqs);
5687 }
5688
5689
5690 ConfigOptionInts * op_print_sequence_1st = m_config.option<ConfigOptionInts>("first_layer_print_sequence");
5691 if (!op_print_sequence_1st) {
5692 return;
5693 }
5694
5695 std::vector<int> &print_sequence_1st = op_print_sequence_1st->values;
5696 if (print_sequence_1st.size() == 0 || print_sequence_1st[0] == 0)
5697 return;
5698
5699 if (print_sequence_1st.size() > filament_nums) {
5700 print_sequence_1st.erase(std::remove_if(print_sequence_1st.begin(), print_sequence_1st.end(), [filament_nums](int n) { return n > filament_nums; }),
5701 print_sequence_1st.end());
5702 }
5703 else if (print_sequence_1st.size() < filament_nums) {
5704 for (size_t extruder_id = print_sequence_1st.size(); extruder_id < filament_nums; ++extruder_id) {
5705 print_sequence_1st.push_back(extruder_id + 1);
5706 }
5707 }
5708}
void set_other_layers_print_sequence(const std::vector< LayerPrintSequence > &layer_seq_list)
Definition PartPlate.cpp:5644

References get_other_layers_print_sequence(), m_config, set_other_layers_print_sequence(), and Slic3r::ConfigOptionVector< int >::values.

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

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

◆ update_first_layer_print_sequence_when_delete_filament()

void Slic3r::GUI::PartPlate::update_first_layer_print_sequence_when_delete_filament ( size_t filamen_id)
5711{
5712 auto other_layers_seqs = get_other_layers_print_sequence();
5713 if (!other_layers_seqs.empty()) {
5714 bool need_update_data = false;
5715 for (auto &other_layers_seq : other_layers_seqs) {
5716 std::vector<int> &orders = other_layers_seq.second;
5717 orders.erase(std::remove_if(orders.begin(), orders.end(), [filament_id](int n) { return n == filament_id +1; }), orders.end());
5718 for (auto &order : orders) {
5719 order = order > filament_id ? order - 1 : order;
5720 }
5721 need_update_data = true;
5722 }
5723 if (need_update_data)
5724 set_other_layers_print_sequence(other_layers_seqs);
5725 }
5726
5727 ConfigOptionInts *op_print_sequence_1st = m_config.option<ConfigOptionInts>("first_layer_print_sequence");
5728 if (!op_print_sequence_1st)
5729 return;
5730
5731 std::vector<int> &print_sequence_1st = op_print_sequence_1st->values;
5732 if (print_sequence_1st.size() == 0 || print_sequence_1st[0] == 0)
5733 return;
5734
5735 print_sequence_1st.erase(std::remove_if(print_sequence_1st.begin(), print_sequence_1st.end(), [filament_id](int n) { return n == filament_id + 1; }), print_sequence_1st.end());
5736 for (auto &order : print_sequence_1st) {
5737 order = order > filament_id ? order - 1 : order;
5738 }
5739}

References get_other_layers_print_sequence(), m_config, set_other_layers_print_sequence(), and Slic3r::ConfigOptionVector< int >::values.

Referenced by on_filament_deleted().

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

◆ update_imex_ghost_colors()

void Slic3r::GUI::PartPlate::update_imex_ghost_colors ( )
1147{
1148 // !m_plater is the headless sentinel: without a GUI_App, calling wxGetApp()
1149 // below is unsafe — same guard pattern as ensure_imex_zones.
1150 if (m_imex_ghost_volumes.empty() || !m_plater) return;
1151 auto* pb = wxGetApp().preset_bundle;
1152 if (!pb) return;
1153
1154 // Plate-level inputs hoisted once; per-head results memoized across instances.
1156 const auto plate_map = get_imex_head_filament_map();
1157
1158 std::map<int, ColorRGBA> head_colors;
1159 for (auto& ghost : m_imex_ghost_volumes) {
1160 if (!ghost) continue;
1161 const int head = imex_ghost_head_from_composite_id(ghost->composite_id.object_id);
1162 auto hc = head_colors.find(head);
1163 if (hc == head_colors.end())
1164 hc = head_colors.emplace(head, get_imex_head_filament_color(head, pem, plate_map)).first;
1165 ColorRGBA color = hc->second;
1166 color.a(IMEX_GHOST_ALPHA);
1167 ghost->color = color;
1168 }
1169}
static int imex_ghost_head_from_composite_id(int object_id)
Definition PartPlate.hpp:300
static constexpr float IMEX_GHOST_ALPHA
Definition PartPlate.cpp:891

References Slic3r::ColorRGBA::a(), Slic3r::effective_physical_extruder_map(), get_imex_head_filament_color(), get_imex_head_filament_map(), Slic3r::GUI::IMEX_GHOST_ALPHA, imex_ghost_head_from_composite_id(), m_imex_ghost_volumes, and m_plater.

Referenced by Slic3r::GUI::GLCanvas3D::_render_imex_ghosts().

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

◆ update_imex_ghost_transforms()

void Slic3r::GUI::PartPlate::update_imex_ghost_transforms ( const std::function< std::optional< Transform3d >(int, int)> & primary_live_xf = {})
1051{
1052 if (m_imex_ghost_volumes.empty() || !m_plater || !m_model) return;
1053
1054 std::string active_tools_str;
1055 int primary_phys = -1;
1056 if (!resolve_active_mode_tools(active_tools_str, primary_phys)) return;
1057
1058 // Reuse zone-center-derived offsets (same source calc_imex_ghosts uses), so
1059 // update and rebuild paths always agree on where each ghost belongs.
1061 auto center_for = [&](int phys) -> Vec2d {
1062 auto it = m_imex_head_zone_centers.find(phys);
1063 return (it == m_imex_head_zone_centers.end()) ? Vec2d::Zero() : it->second;
1064 };
1065 const Vec2d primary_off = center_for(primary_phys);
1066
1067 // Same aggregation-aware center resolution as calc_imex_ghosts uses, so a live drag
1068 // moves the ghost exactly as a rebuild would place it. See the note there: for an
1069 // aggregated gantry both X frames sit on the bed centerline, which zeroes gantry_offset.x
1070 // so the cross-gantry mirror tracks primary's X and reflects in Y.
1071 // Same accessor, same reason as calc_imex_ghosts() above: this must group the grid the way
1072 // compute_imex_zone_layout() does. The grouping/is_aggregated preamble that follows is
1073 // duplicated from that function; the duplication predates this change and is left alone.
1074 const int tpg = std::max(1, imex_cfg_int(
1075 wxGetApp().preset_bundle->printers.get_edited_preset().config, "imex_tools_per_gantry"));
1076 const ImexGantryGrouping grouping =
1077 group_imex_active_tools_by_gantry(active_tools_str, tpg);
1078 auto is_aggregated = [&](int phys) -> bool {
1079 const int g = phys / tpg;
1080 for (const auto& grp : grouping.groups)
1081 if (grp.gantry_index == g) return grp.aggregate;
1082 return false;
1083 };
1084 auto bed_ext = get_extents(m_shape);
1085 const double bed_x_center = 0.5 * (bed_ext.min(0) + bed_ext.max(0));
1086 auto resolve_centers = [&](int phys) -> std::pair<Vec2d, Vec2d> {
1087 const Vec2d target_off = center_for(phys);
1088 if (!is_aggregated(phys))
1089 return {primary_off, target_off - primary_off};
1090 const Vec2d ap{bed_x_center, primary_off.y()};
1091 const Vec2d at{bed_x_center, target_off.y()};
1092 return {ap, at - ap};
1093 };
1094 auto mirror_axis_for = [&](int phys) {
1095 return imex_mirror_axis_for(primary_phys, phys, tpg);
1096 };
1097
1098 // Build a phys → role map once so the per-ghost loop is a lookup, not a reparse.
1099 std::map<int, ImexRole> role_by_phys;
1100 for (const auto& [phys, role] : parse_imex_active_tools(active_tools_str))
1101 role_by_phys[phys] = role;
1102 auto role_for = [&](int phys) -> ImexRole {
1103 auto it = role_by_phys.find(phys);
1104 return (it == role_by_phys.end()) ? ImexRole::Copy : it->second;
1105 };
1106
1107 for (auto& ghost : m_imex_ghost_volumes) {
1108 const int head = imex_ghost_head_from_composite_id(ghost->composite_id.object_id);
1109 const int inst_idx = ghost->composite_id.instance_id;
1110 const int obj_idx = ghost->composite_id.volume_id; // stashed by calc_imex_ghosts
1111 if (obj_idx < 0 || obj_idx >= (int)m_model->objects.size()) continue;
1112 const ModelObject* mo = m_model->objects[obj_idx];
1113 if (!mo || inst_idx < 0 || inst_idx >= (int)mo->instances.size()) continue;
1114
1115 // Live-drag path: GLVolume carries the in-progress gizmo transform, while
1116 // ModelInstance::get_matrix() only reflects the last committed state. Use
1117 // the live lookup when the caller provides it so ghosts track drags frame
1118 // by frame instead of snapping on mouse-up.
1119 Transform3d primary_xf;
1120 if (primary_live_xf) {
1121 if (auto live = primary_live_xf(obj_idx, inst_idx))
1122 primary_xf = *live;
1123 else
1124 primary_xf = mo->instances[inst_idx]->get_matrix();
1125 } else {
1126 primary_xf = mo->instances[inst_idx]->get_matrix();
1127 }
1128
1129 const ImexRole role = role_for(head);
1130 const auto [pri_center, gantry] = resolve_centers(head);
1131 // Mirror axis follows the gantry row — see calc_imex_ghosts(). A cross-gantry mirror
1132 // reflects in Y and tracks primary's X, so drag no longer pushes it off-bed and the
1133 // old bake-the-flip-into-the-mesh workaround is unnecessary.
1134 const Transform3d head_xf = imex_head_transform(
1135 primary_phys, head, role, gantry, pri_center, mirror_axis_for(head));
1136 const Transform3d ghost_xf = head_xf * primary_xf;
1137 ghost->set_instance_transformation(ghost_xf);
1138 }
1139}
ImexRole
Definition IMEXHelpers.hpp:345
@ Copy
Definition IMEXHelpers.hpp:345

References Slic3r::Copy, ensure_imex_zones(), Slic3r::get_extents(), Slic3r::group_imex_active_tools_by_gantry(), Slic3r::ImexGantryGrouping::groups, Slic3r::imex_cfg_int(), imex_ghost_head_from_composite_id(), Slic3r::imex_head_transform(), Slic3r::imex_mirror_axis_for(), Slic3r::ModelObject::instances, m_imex_ghost_volumes, m_imex_head_zone_centers, m_model, m_plater, m_shape, Slic3r::parse_imex_active_tools(), and resolve_active_mode_tools().

Referenced by Slic3r::GUI::GLCanvas3D::_render_imex_ghosts().

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

◆ update_instance_exclude_status()

void Slic3r::GUI::PartPlate::update_instance_exclude_status ( int obj_id,
int instance_id,
BoundingBoxf3 * bounding_box = nullptr )
4836{
4837 bool outside;
4838 std::set<std::pair<int, int>>::iterator it;
4839
4840 outside = check_outside(obj_id, instance_id, bounding_box);
4842
4843 it = instance_outside_set.find(std::pair(obj_id, instance_id));
4844 if (it == instance_outside_set.end()) {
4845 if (outside)
4846 instance_outside_set.insert(std::pair(obj_id, instance_id));
4847 }
4848 else {
4849 if (!outside)
4850 instance_outside_set.erase(it);
4851 }
4852}

References Slic3r::bounding_box(), check_outside(), instance_outside_set, and invalidate_exclusion_volume_preview().

Referenced by Slic3r::GUI::PartPlateList::notify_instance_update().

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

◆ update_object_index()

void Slic3r::GUI::PartPlate::update_object_index ( int obj_idx_removed,
int obj_idx_max )
4856{
4857 std::set<std::pair<int, int>> temp_set;
4858 std::set<std::pair<int, int>>::iterator it;
4859 //update the obj_to_instance_set
4860 for (it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
4861 {
4862 if (it->first >= obj_idx_removed)
4863 temp_set.insert(std::pair(it->first-1, it->second));
4864 else
4865 temp_set.insert(std::pair(it->first, it->second));
4866 }
4867 obj_to_instance_set.clear();
4868 obj_to_instance_set = temp_set;
4870
4871 //update the instance_outside_set
4872 temp_set.clear();
4873 for (it = instance_outside_set.begin(); it != instance_outside_set.end(); ++it)
4874 {
4875 if (it->first >= obj_idx_removed)
4876 temp_set.insert(std::pair(it->first - 1, it->second));
4877 else
4878 temp_set.insert(std::pair(it->first, it->second));
4879 }
4880 instance_outside_set.clear();
4881 instance_outside_set = temp_set;
4882
4883}

References instance_outside_set, invalidate_exclusion_volume_preview(), and obj_to_instance_set.

Referenced by Slic3r::GUI::PartPlateList::notify_instance_removed().

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

◆ update_render_colors()

void Slic3r::GUI::PartPlate::update_render_colors ( )
static

◆ update_slice_context()

void Slic3r::GUI::PartPlate::update_slice_context ( BackgroundSlicingProcess & process)
5443{
5444 auto statuscb = [this](const Slic3r::PrintBase::SlicingStatus& status) {
5445 Slic3r::SlicingStatusEvent *event = new Slic3r::SlicingStatusEvent(EVT_SLICING_UPDATE, 0, status);
5446 //BBS: GUI refactor: add plate info befor message
5447 if (status.message_type == Slic3r::PrintStateBase::SlicingDefaultNotification) {
5448 // TRN Slicing progress. %1% is the plate number, %2% the current slicing step.
5449 event->status.text = Slic3r::format(_u8L("Slicing plate %1%: %2%"), m_plate_index + 1, event->status.text);
5450 }
5451 wxQueueEvent(m_plater, event);
5452 };
5453
5454 process.set_fff_print(m_print);
5455 process.set_gcode_result(m_gcode_result);
5456 process.select_technology(this->printer_technology);
5457 process.set_current_plate(this);
5458 m_print->set_status_callback(statuscb);
5459 process.switch_print_preprocess();
5460
5461 return;
5462}
@ SlicingDefaultNotification
Definition PrintBase.hpp:68
bool process(std::exception_ptr &eptr)
Definition EmbossJob.cpp:1427

References _u8L, Slic3r::format(), m_gcode_result, m_plate_index, m_plater, m_print, printer_technology, and Slic3r::PrintStateBase::SlicingDefaultNotification.

Referenced by Slic3r::GUI::PartPlateList::update_slice_context_to_current_plate().

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

◆ update_slice_ready_status()

void Slic3r::GUI::PartPlate::update_slice_ready_status ( bool ready_slice)
inline
645 {
646 m_ready_for_slice = ready_slice;
647 }

References m_ready_for_slice.

Referenced by Slic3r::GUI::GLCanvas3D::reload_scene(), and Slic3r::GUI::Plater::validate_current_plate().

Here is the caller graph for this function:

◆ update_slice_result_valid_state()

void Slic3r::GUI::PartPlate::update_slice_result_valid_state ( bool valid = false)
5424{
5425 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% , update slice result from %2% to %3%") % m_plate_index %m_slice_result_valid %valid;
5426 const bool changed = (m_slice_result_valid != valid);
5427 m_slice_result_valid = valid;
5428 if (valid)
5429 m_slice_percent = 100.0f;
5430 else {
5431 m_slice_percent = -1.0f;
5432 }
5433 // This flips the plate's slice-ready / IMEX blocked-plate state without a geometry change,
5434 // so the plate-selector thumbnail/warning badge must be repainted explicitly. Upstream
5435 // replaced the old per-idle unconditional toolbar refresh with this dirty flag, so nothing
5436 // else repaints the naughty-plate icon otherwise.
5437 if (changed && m_plater)
5438 m_plater->mark_plate_toolbar_image_dirty();
5439}

References m_plate_index, m_plater, m_slice_percent, and m_slice_result_valid.

Referenced by Slic3r::GUI::Plater::apply_background_progress(), clear(), load_gcode_from_file(), Slic3r::GUI::PartPlateList::notify_instance_removed(), Slic3r::GUI::PartPlateList::notify_instance_update(), Slic3r::GUI::Plater::priv::on_process_completed(), Slic3r::GUI::Plater::open_filament_map_setting_dialog(), Slic3r::GUI::CalibUtils::process_and_store_3mf(), reset_imex_head_filament_map(), reset_imex_mode(), Slic3r::GUI::Plater::reslice(), Slic3r::CLI::run(), Slic3r::GUI::Plater::select_plate(), Slic3r::GUI::Plater::select_plate_by_hover_id(), set_bed_type(), set_imex_head_filament_map(), set_imex_mode(), set_print_seq(), and Slic3r::GUI::Plater::priv::update_background_process().

Here is the caller graph for this function:

◆ update_slicing_percent()

void Slic3r::GUI::PartPlate::update_slicing_percent ( float percent)
inline
686 {
687 m_slice_percent = percent;
688 }

References m_slice_percent.

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

Here is the caller graph for this function:

◆ update_states()

void Slic3r::GUI::PartPlate::update_states ( )
5396{
5397 //currently let judge outside partplate when plate is empty
5398 /*if (obj_to_instance_set.size() == 0)
5399 {
5400 m_ready_for_slice = false;
5401 return;
5402 }*/
5403 m_ready_for_slice = true;
5404 for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
5405 int obj_id = it->first;
5406 int instance_id = it->second;
5407
5408 //if (check_outside(obj_id, instance_id))
5409 if (instance_outside_set.find(std::pair(obj_id, instance_id)) != instance_outside_set.end())
5410 {
5411 m_ready_for_slice = false;
5412 //currently only check whether ready to slice
5413 break;
5414 }
5415 }
5416
5417 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% , m_ready_for_slice changes to %2%") % m_plate_index %m_ready_for_slice;
5418 return;
5419}

References instance_outside_set, m_plate_index, m_ready_for_slice, and obj_to_instance_set.

Referenced by Slic3r::GUI::PartPlateList::notify_instance_update(), and remove_instance().

Here is the caller graph for this function:

◆ valid_instance()

bool Slic3r::GUI::PartPlate::valid_instance ( int obj_id,
int instance_id ) const
private
596{
597 if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
598 {
599 ModelObject* object = m_model->objects[obj_id];
600 if ((instance_id >= 0) && (instance_id < object->instances.size()))
601 return true;
602 }
603
604 return false;
605}

References m_model.

Referenced by add_instance(), duplicate_all_instance(), get_extruders_under_cli(), has_printable_instances(), imex_placement_violation(), intersect_instance(), is_all_instances_unprintable(), is_left_top_of(), printable_instance_size(), set_pos_and_size(), and wipe_tower_obstacles().

Here is the caller graph for this function:

◆ wipe_tower_obstacles()

Polygons Slic3r::GUI::PartPlate::wipe_tower_obstacles ( const DynamicPrintConfig & config) const
private
4037{
4038 Polygons obstacles;
4039 for (const auto &[obj_id, instance_id] : obj_to_instance_set) {
4040 if (!valid_instance(obj_id, instance_id))
4041 continue;
4042 const ModelObject *object = m_model->objects[obj_id];
4043 const ModelInstance *instance = object->instances[instance_id];
4044 if (!instance->printable)
4045 continue;
4046 // A sinking object counts its whole outline, the part below the bed included.
4047 Polygon hull = object->convex_hull_2d(instance->get_matrix());
4048 if (hull.size() < 3)
4049 continue;
4050 hull.translate(-scaled(m_origin.x()), -scaled(m_origin.y()));
4051 // An object's own setting wins over the print preset's.
4052 auto option_of = [&object, &config](const char *key) {
4053 const ConfigOption *opt = object->config.option(key);
4054 return opt != nullptr ? opt : config.option(key);
4055 };
4056 // An auto brim is only sized while slicing, so it is taken at the brim width option too.
4057 const ConfigOption *brim_type = option_of("brim_type");
4058 const ConfigOption *brim_width = option_of("brim_width");
4059 const double brim = brim_type != nullptr && brim_width != nullptr && brim_type->getInt() != static_cast<int>(btNoBrim) ? brim_width->getFloat() : 0.;
4060 append(obstacles, offset(hull, static_cast<float>(scaled(brim + WIPE_TOWER_MARGIN))));
4061 }
4062 return obstacles;
4063}
static const ConfigOption * option_of(const ConfigBase &config, const char *key)
Definition WipeTowerEstimate.cpp:30
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157

References Slic3r::append(), Slic3r::btNoBrim, config(), Slic3r::ModelInstance::get_matrix(), Slic3r::ConfigOption::getFloat(), Slic3r::ConfigOption::getInt(), m_model, m_origin, obj_to_instance_set, Slic3r::offset(), Slic3r::option_of(), Slic3r::ModelInstance::printable, Slic3r::scaled(), Slic3r::MultiPoint::size(), Slic3r::MultiPoint::translate(), valid_instance(), and WIPE_TOWER_MARGIN.

Referenced by estimate_wipe_tower_polygon().

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

◆ cereal::access

friend class cereal::access
friend

References cereal::access.

Referenced by cereal::access.

◆ PartPlateList

friend class PartPlateList
friend

References PartPlateList.

Referenced by PartPlate(), and PartPlateList.

◆ UndoRedo::StackImpl

friend class UndoRedo::StackImpl
friend

Member Data Documentation

◆ cali_bboxes_data

PlateBBoxData Slic3r::GUI::PartPlate::cali_bboxes_data

Referenced by load_pattern_box_data().

◆ DEFAULT_COLOR

ColorRGBA Slic3r::GUI::PartPlate::DEFAULT_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f }
static

◆ GRABBER_COUNT

◆ HEIGHT_LIMIT_BOTTOM_COLOR

ColorRGBA Slic3r::GUI::PartPlate::HEIGHT_LIMIT_BOTTOM_COLOR = { 0.4f, 0.4f, 1.0f, 1.0f }
static

Referenced by render_height_limit().

◆ HEIGHT_LIMIT_TOP_COLOR

ColorRGBA Slic3r::GUI::PartPlate::HEIGHT_LIMIT_TOP_COLOR = { 0.6f, 0.6f, 1.0f, 1.0f }
static

Referenced by render_height_limit().

◆ IMEX_GHOST_COMPOSITE_ID_BASE

int Slic3r::GUI::PartPlate::IMEX_GHOST_COMPOSITE_ID_BASE = -100000
staticconstexpr

◆ IMEX_GHOST_MAX_HEADS

int Slic3r::GUI::PartPlate::IMEX_GHOST_MAX_HEADS = 256
staticconstexpr

◆ instance_outside_set

◆ LINE_BOTTOM_COLOR

ColorRGBA Slic3r::GUI::PartPlate::LINE_BOTTOM_COLOR = { 0.8f, 0.8f, 0.8f, 0.4f }
static

◆ LINE_TOP_COLOR

ColorRGBA Slic3r::GUI::PartPlate::LINE_TOP_COLOR = { 0.89f, 0.89f, 0.89f, 1.0f }
static

◆ LINE_TOP_DARK_COLOR

ColorRGBA Slic3r::GUI::PartPlate::LINE_TOP_DARK_COLOR = { 0.431f, 0.431f, 0.463f, 1.0f }
static

Referenced by render_grid().

◆ LINE_TOP_SEL_COLOR

ColorRGBA Slic3r::GUI::PartPlate::LINE_TOP_SEL_COLOR = { 0.5294f, 0.5451, 0.5333f, 1.0f}
static

◆ LINE_TOP_SEL_DARK_COLOR

ColorRGBA Slic3r::GUI::PartPlate::LINE_TOP_SEL_DARK_COLOR = { 0.298f, 0.298f, 0.3333f, 1.0f}
static

◆ m_active_exclusion_volume_prisms

GLModel Slic3r::GUI::PartPlate::m_active_exclusion_volume_prisms
private

◆ m_apply_invalid

bool Slic3r::GUI::PartPlate::m_apply_invalid {false}
private

◆ m_arrange_icon

PickingModel Slic3r::GUI::PartPlate::m_arrange_icon
private

◆ m_bounding_box

◆ m_config

◆ m_del_icon

PickingModel Slic3r::GUI::PartPlate::m_del_icon
private

◆ m_depth

int Slic3r::GUI::PartPlate::m_depth
private

◆ m_exclude_area

Pointfs Slic3r::GUI::PartPlate::m_exclude_area
private

◆ m_exclude_bounding_box

std::vector<BoundingBoxf3> Slic3r::GUI::PartPlate::m_exclude_bounding_box
mutableprivate

◆ m_exclude_triangles

GLModel Slic3r::GUI::PartPlate::m_exclude_triangles
private

◆ m_exclusion_volume_border_triangles

GLModel Slic3r::GUI::PartPlate::m_exclusion_volume_border_triangles
private

◆ m_exclusion_volume_floor_triangles

GLModel Slic3r::GUI::PartPlate::m_exclusion_volume_floor_triangles
private

◆ m_exclusion_volume_intersection_triangles

GLModel Slic3r::GUI::PartPlate::m_exclusion_volume_intersection_triangles
private

◆ m_exclusion_volume_intersections_cleared

bool Slic3r::GUI::PartPlate::m_exclusion_volume_intersections_cleared { false }
private

◆ m_exclusion_volume_preview_cache_key

std::string Slic3r::GUI::PartPlate::m_exclusion_volume_preview_cache_key
private

◆ m_exclusion_volume_preview_dirty

bool Slic3r::GUI::PartPlate::m_exclusion_volume_preview_dirty { true }
private

◆ m_extended_bounding_box

BoundingBoxf3 Slic3r::GUI::PartPlate::m_extended_bounding_box
private

◆ m_extruder_areas

std::vector<Pointfs> Slic3r::GUI::PartPlate::m_extruder_areas
private

◆ m_extruder_exclusion_volume_borders

std::vector<std::pair<std::unique_ptr<GLModel>, ColorRGBA> > Slic3r::GUI::PartPlate::m_extruder_exclusion_volume_borders
private

◆ m_extruder_heights

std::vector<double> Slic3r::GUI::PartPlate::m_extruder_heights
private

◆ m_gcode_path_from_3mf

std::string Slic3r::GUI::PartPlate::m_gcode_path_from_3mf
private

◆ m_gcode_result

◆ m_grabber_box

BoundingBoxf3 Slic3r::GUI::PartPlate::m_grabber_box
mutableprivate

Referenced by calc_bounding_boxes().

◆ m_grabber_trans_matrix

Transform3d Slic3r::GUI::PartPlate::m_grabber_trans_matrix
private

◆ m_gridlines

GLModel Slic3r::GUI::PartPlate::m_gridlines
private

Referenced by calc_gridlines(), and render_grid().

◆ m_gridlines_bolder

GLModel Slic3r::GUI::PartPlate::m_gridlines_bolder
private

Referenced by calc_gridlines(), and render_grid().

◆ m_height

double Slic3r::GUI::PartPlate::m_height
private

◆ m_height_limit_bottom

GLModel Slic3r::GUI::PartPlate::m_height_limit_bottom
private

◆ m_height_limit_common

GLModel Slic3r::GUI::PartPlate::m_height_limit_common
private

◆ m_height_limit_top

GLModel Slic3r::GUI::PartPlate::m_height_limit_top
private

◆ m_height_to_lid

float Slic3r::GUI::PartPlate::m_height_to_lid
private

Referenced by calc_height_limit(), and set_shape().

◆ m_height_to_rod

float Slic3r::GUI::PartPlate::m_height_to_rod
private

Referenced by calc_height_limit(), and set_shape().

◆ m_hover_id

int Slic3r::GUI::PartPlate::m_hover_id
private

Referenced by init(), and set_hover_id().

◆ m_id

ObjectID Slic3r::ObjectBase::m_id
privateinherited

◆ m_imex_collision_overlay

std::vector<GLModel> Slic3r::GUI::PartPlate::m_imex_collision_overlay
private

◆ m_imex_collision_zones

std::vector<BoundingBoxf3> Slic3r::GUI::PartPlate::m_imex_collision_zones
private

◆ m_imex_copy_zones

std::vector<GLModel> Slic3r::GUI::PartPlate::m_imex_copy_zones
private

◆ m_imex_ghost_cache_key

std::string Slic3r::GUI::PartPlate::m_imex_ghost_cache_key { "\x01" }
private
187{ "\x01" }; // sentinel = unbuilt

Referenced by ensure_imex_ghosts(), invalidate_imex_ghosts(), reset_imex_mode(), and set_imex_mode().

◆ m_imex_ghost_volumes

std::vector<std::unique_ptr<GLVolume> > Slic3r::GUI::PartPlate::m_imex_ghost_volumes
private

◆ m_imex_head_zone_centers

std::map<int, Vec2d> Slic3r::GUI::PartPlate::m_imex_head_zone_centers
private

◆ m_imex_margin_overlay

std::vector<GLModel> Slic3r::GUI::PartPlate::m_imex_margin_overlay
private

◆ m_imex_mirror_zones

std::vector<GLModel> Slic3r::GUI::PartPlate::m_imex_mirror_zones
private

◆ m_imex_mode_icon

PickingModel Slic3r::GUI::PartPlate::m_imex_mode_icon
private

◆ m_imex_primary_head

int Slic3r::GUI::PartPlate::m_imex_primary_head { -1 }
private
184{ -1 }; // physical-head index of the primary tool in the active mode; -1 when no mode

Referenced by calc_imex_zones().

◆ m_imex_primary_zone_box

std::optional<BoundingBoxf> Slic3r::GUI::PartPlate::m_imex_primary_zone_box
private

◆ m_imex_secondary_zone_boxes

std::vector<BoundingBoxf3> Slic3r::GUI::PartPlate::m_imex_secondary_zone_boxes
private

◆ m_imex_warn_icon

GLModel Slic3r::GUI::PartPlate::m_imex_warn_icon
private

◆ m_imex_zones_mode_cache

std::string Slic3r::GUI::PartPlate::m_imex_zones_mode_cache { "\x01" }
private
185{ "\x01" }; // cached mode+topology key; sentinel = unbuilt

Referenced by ensure_imex_zones(), reset_imex_mode(), set_imex_mode(), and set_shape().

◆ m_lock_icon

PickingModel Slic3r::GUI::PartPlate::m_lock_icon
private

◆ m_locked

bool Slic3r::GUI::PartPlate::m_locked
private

Referenced by init(), is_locked(), load(), lock(), print(), and save().

◆ m_logo_triangles

GLModel Slic3r::GUI::PartPlate::m_logo_triangles
private

Referenced by render_logo(), and set_shape().

◆ m_model

◆ m_move_front_icon

PickingModel Slic3r::GUI::PartPlate::m_move_front_icon
private

◆ m_name

std::string Slic3r::GUI::PartPlate::m_name
private

◆ m_name_texture

GLTexture Slic3r::GUI::PartPlate::m_name_texture
private

◆ m_name_texture_height

wxCoord Slic3r::GUI::PartPlate::m_name_texture_height
private

◆ m_name_texture_width

wxCoord Slic3r::GUI::PartPlate::m_name_texture_width
private

◆ m_orient_icon

PickingModel Slic3r::GUI::PartPlate::m_orient_icon
private

◆ m_origin

◆ m_partplate_list

◆ m_plate_filament_map_icon

PickingModel Slic3r::GUI::PartPlate::m_plate_filament_map_icon
private

◆ m_plate_idx_icon

GLModel Slic3r::GUI::PartPlate::m_plate_idx_icon
private

◆ m_plate_index

◆ m_plate_name_edit_icon

◆ m_plate_name_icon

GLModel Slic3r::GUI::PartPlate::m_plate_name_icon
private

◆ m_plate_settings_icon

PickingModel Slic3r::GUI::PartPlate::m_plate_settings_icon
private

◆ m_plater

◆ m_print

◆ m_print_index

int Slic3r::GUI::PartPlate::m_print_index
private

◆ m_print_polygon

ExPolygon Slic3r::GUI::PartPlate::m_print_polygon
private

Referenced by render(), and set_shape().

◆ m_printable

bool Slic3r::GUI::PartPlate::m_printable
private

◆ m_quadric

GLUquadricObject* Slic3r::GUI::PartPlate::m_quadric
private

Referenced by PartPlate().

◆ m_ready_for_slice

bool Slic3r::GUI::PartPlate::m_ready_for_slice
private

◆ m_scale_factor

float Slic3r::GUI::PartPlate::m_scale_factor { 1.0f }
private

◆ m_selected

◆ m_shape

◆ m_slice_percent

float Slic3r::GUI::PartPlate::m_slice_percent
private

◆ m_slice_result_valid

bool Slic3r::GUI::PartPlate::m_slice_result_valid
private

◆ m_temp_config_3mf_path

std::string Slic3r::GUI::PartPlate::m_temp_config_3mf_path
private

◆ m_texture

GLTexture Slic3r::GUI::PartPlate::m_texture
private

◆ m_timelapse_warning_code

int Slic3r::GUI::PartPlate::m_timelapse_warning_code = 0
private

◆ m_tmp_gcode_path

std::string Slic3r::GUI::PartPlate::m_tmp_gcode_path
private

◆ m_triangles

PickingModel Slic3r::GUI::PartPlate::m_triangles
private

◆ m_width

int Slic3r::GUI::PartPlate::m_width
private

◆ m_wrapping_detection_triangles

GLModel Slic3r::GUI::PartPlate::m_wrapping_detection_triangles
private

◆ no_light_thumbnail_data

◆ obj_preview_thumbnail_data

ThumbnailData Slic3r::GUI::PartPlate::obj_preview_thumbnail_data

◆ obj_to_instance_set

◆ pick_thumbnail_data

◆ PLATE_FILAMENT_MAP_ID

unsigned int Slic3r::GUI::PartPlate::PLATE_FILAMENT_MAP_ID = 8
staticconstexpr

◆ PLATE_IMEX_MODE_ID

unsigned int Slic3r::GUI::PartPlate::PLATE_IMEX_MODE_ID = 9
staticconstexpr

◆ PLATE_NAME_HOVER_ID

unsigned int Slic3r::GUI::PartPlate::PLATE_NAME_HOVER_ID = 6
staticconstexpr

◆ plate_thumbnail_height

const int Slic3r::GUI::PartPlate::plate_thumbnail_height = 512
static

◆ plate_thumbnail_width

const int Slic3r::GUI::PartPlate::plate_thumbnail_width = 512
static

◆ position

Slic3r::Geometry::Transformation Slic3r::GUI::PartPlate::position
private

◆ positions

std::vector<Vec3f> Slic3r::GUI::PartPlate::positions
private

◆ printer_technology

PrinterTechnology Slic3r::GUI::PartPlate::printer_technology
private

◆ s_last_id

size_t Slic3r::ObjectBase::s_last_id = 0
staticprivateinherited

Referenced by generate_new_id().

◆ SELECT_COLOR

ColorRGBA Slic3r::GUI::PartPlate::SELECT_COLOR = { 0.2666f, 0.2784f, 0.2784f, 1.0f }
static

◆ slice_filaments_info

std::vector<FilamentInfo> Slic3r::GUI::PartPlate::slice_filaments_info
private

◆ thumbnail_data

◆ top_thumbnail_data

◆ UNSELECT_COLOR

ColorRGBA Slic3r::GUI::PartPlate::UNSELECT_COLOR = { 0.82f, 0.82f, 0.82f, 1.0f }
static

◆ UNSELECT_DARK_COLOR

ColorRGBA Slic3r::GUI::PartPlate::UNSELECT_DARK_COLOR = { 0.384f, 0.384f, 0.412f, 1.0f }
static

Referenced by render_background().


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