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

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

Collaboration diagram for Slic3r::GUI::GLCanvas3D:

Classes

class  LayersEditing
struct  Mouse
struct  SlaCap
class  RenderStats
class  Labels
class  CenterOfMass
class  Tooltip
class  Slope
class  RenderTimer
class  ToolbarHighlighterTimer
class  GizmoHighlighterTimer
struct  ArrangeSettings
struct  OrientSettings
struct  SectionView
struct  KeyDown
struct  SelectionEdit
class  SequentialPrintClearance
struct  ToolbarHighlighter
struct  GizmoHighlighter
class  WipeTowerInfo

Public Types

enum  ECursorType : unsigned char { Standard , Cross }
enum  ECanvasType { CanvasView3D = 0 , CanvasPreview = 1 , CanvasAssembleView = 2 }
enum class  MouseButton { None , Left , Middle , Right }
enum class  MouseAction { None , Pan , Rotation }

Public Member Functions

int GetHoverId ()
OrientSettings & get_orient_settings ()
void load_arrange_settings ()
ArrangeSettings & get_arrange_settings ()
 GLCanvas3D (wxGLCanvas *canvas, Bed3D &bed)
 ~GLCanvas3D ()
bool is_initialized () const
void set_context (wxGLContext *context)
void set_type (ECanvasType type)
void set_studio_lighting (bool on)
ECanvasType get_canvas_type ()
wxGLCanvas * get_wxglcanvas ()
const wxGLCanvas * get_wxglcanvas () const
bool init ()
void post_event (wxEvent &&event)
std::shared_ptr< SceneRaycasterItem > add_raycaster_for_picking (SceneRaycaster::EType type, int id, const MeshRaycaster &raycaster, const Transform3d &trafo=Transform3d::Identity(), bool use_back_faces=false)
void remove_raycasters_for_picking (SceneRaycaster::EType type, int id)
void remove_raycasters_for_picking (SceneRaycaster::EType type)
std::vector< std::shared_ptr< SceneRaycasterItem > > * get_raycasters_for_picking (SceneRaycaster::EType type)
void set_raycaster_gizmos_on_top (bool value)
float get_explosion_ratio ()
void reset_explosion_ratio ()
void on_change_color_mode (bool is_dark, bool reinit=true)
const bool get_dark_mode_status ()
void set_as_dirty ()
void requires_check_outside_state ()
unsigned int get_volumes_count () const
const GLVolumeCollection & get_volumes () const
void reset_volumes ()
ModelInstanceEPrintVolumeState check_volumes_outside_state (ObjectFilamentResults *object_results=nullptr) const
void check_volumes_outside_state (GLVolumeCollection &volumes) const
bool is_all_plates_selected ()
const float get_scale () const
GCodeViewer & get_gcode_viewer ()
void init_gcode_viewer (ConfigOptionMode mode, Slic3r::PresetBundle *preset_bundle)
void reset_gcode_toolpaths ()
const GCodeViewer::SequentialView & get_gcode_sequential_view () const
void update_gcode_sequential_view_current (unsigned int first, unsigned int last)
const libvgcode::Interval & get_gcode_view_full_range () const
const libvgcode::Interval & get_gcode_view_enabled_range () const
const libvgcode::Interval & get_gcode_view_visible_range () const
const libvgcode::PathVertex & get_gcode_vertex_at (size_t id) const
void toggle_selected_volume_visibility (bool selected_visible)
void toggle_sla_auxiliaries_visibility (bool visible, const ModelObject *mo=nullptr, int instance_idx=-1)
void toggle_model_objects_visibility (bool visible, const ModelObject *mo=nullptr, int instance_idx=-1, const ModelVolume *mv=nullptr)
void update_instance_printable_state_for_object (size_t obj_idx)
void update_instance_printable_state_for_objects (const std::vector< size_t > &object_idxs)
void set_config (const DynamicPrintConfig *config)
void set_process (BackgroundSlicingProcess *process)
void set_model (Model *model)
const Model * get_model () const
const Selection & get_selection () const
Selection & get_selection ()
const GLGizmosManager & get_gizmos_manager () const
GLGizmosManager & get_gizmos_manager ()
void bed_shape_changed ()
void plates_count_changed ()
Camera & get_camera ()
void set_clipping_plane (unsigned int id, const ClippingPlane &plane)
void reset_clipping_planes_cache ()
void set_use_clipping_planes (bool use)
bool get_use_clipping_planes () const
const std::array< ClippingPlane, 2 > & get_clipping_planes () const
void set_use_color_clip_plane (bool use)
void set_color_clip_plane (const Vec3d &cp_normal, double offset)
void set_color_clip_plane_colors (const std::array< ColorRGBA, 2 > &colors)
bool is_section_view_active () const
double get_section_view_ratio () const
const Vec3d & get_section_view_normal () const
void set_section_view_ratio (double ratio)
void toggle_section_view ()
void align_section_view_to_camera ()
void share_section_view (const GLCanvas3D &owner)
void toggle_world_axes_visibility (bool force_show=false)
void refresh_camera_scene_box ()
void set_color_by (const std::string &value)
BoundingBoxf3 volumes_bounding_box (bool current_plate_only=false) const
BoundingBoxf3 scene_bounding_box () const
BoundingBoxf3 plate_scene_bounding_box (int plate_idx) const
bool is_layers_editing_enabled () const
bool is_layers_editing_allowed () const
void reset_layer_height_profile ()
void adaptive_layer_height_profile (float quality_factor)
void smooth_layer_height_profile (const HeightProfileSmoothingParams &smoothing_params)
bool is_reload_delayed () const
void enable_layers_editing (bool enable)
void enable_picking (bool enable)
void enable_moving (bool enable)
void enable_gizmos (bool enable)
void enable_selection (bool enable)
void enable_main_toolbar (bool enable)
void _update_select_plate_toolbar_stats_item (bool force_selected=false)
void reset_select_plate_toolbar_selection ()
void enable_select_plate_toolbar (bool enable)
void enable_assemble_view_toolbar (bool enable)
void enable_return_toolbar (bool enable)
void enable_separator_toolbar (bool enable)
void enable_collapse_toolbar (bool enable)
void set_collapse_toolbar (GLToolbar *toolbar, std::function< CollapseSide()> side)
void enable_plate_chrome (bool enable)
void set_design_canvas (bool b)
void set_show_bed (bool b)
bool get_show_bed () const
void enable_sinking_contours (bool enable)
void enable_dynamic_background (bool enable)
void enable_labels (bool enable)
void enable_slope (bool enable)
void allow_multisample (bool allow)
void zoom_to_bed ()
void zoom_to_volumes ()
void zoom_to_selection ()
void zoom_to_gcode ()
void zoom_to_plate (int plate_idx=-1)
void select_view (const std::string &direction)
void select_plate ()
int get_main_toolbar_offset () const
int get_main_toolbar_height () const
int get_main_toolbar_width () const
float get_assemble_view_toolbar_width () const
float get_assemble_view_toolbar_height () const
float get_assembly_paint_toolbar_width () const
float get_separator_toolbar_width () const
float get_separator_toolbar_height () const
bool is_collapse_toolbar_on_left () const
float get_collapse_toolbar_width () const
float get_collapse_toolbar_height () const
float get_canvas_toolbar_right () const
void update_volumes_colors_by_extruder ()
bool is_dragging () const
bool has_mouse_capture () const
void render (bool only_init=false)
bool is_rendering_enabled ()
void enable_render (bool enabled)
void render_thumbnail (ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
void render_thumbnail (ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
void render_thumbnail (ThumbnailData &thumbnail_data, std::vector< ColorRGBA > &extruder_colors, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
void select_curr_plate_all ()
void select_object_from_idx (std::vector< int > &object_idxs)
void remove_curr_plate_all ()
void select_all ()
void deselect_all ()
void exit_gizmo ()
void set_selected_visible (bool visible)
void delete_selected ()
void ensure_on_bed (unsigned int object_idx, bool allow_negative_z)
std::vector< double > get_gcode_layers_zs () const
std::vector< float > get_gcode_layers_times () const
const std::vector< float > & get_gcode_layers_times_cache () const
void reset_gcode_layers_times_cache ()
void set_volumes_z_range (const std::array< double, 2 > &range)
size_t get_gcode_extruders_count ()
std::vector< int > load_object (const ModelObject &model_object, int obj_idx, std::vector< int > instance_idxs)
std::vector< int > load_object (const Model &model, int obj_idx)
void mirror_selection (Axis axis)
void reload_scene (bool refresh_immediately, bool force_full_scene_refresh=false)
void set_shell_transparence (float alpha=0.2f)
void load_shells (const Print &print, bool force_previewing=false)
void reset_shells ()
void set_shells_on_previewing (bool is_preview)
void load_gcode_preview (const GCodeProcessorResult &gcode_result, const std::vector< std::string > &str_tool_colors, const std::vector< std::string > &str_color_print_colors, bool only_gcode)
void set_gcode_view_type (libvgcode::EViewType type)
libvgcode::EViewType get_gcode_view_type () const
void load_sla_preview ()
void bind_event_handlers ()
void unbind_event_handlers ()
void on_size (wxSizeEvent &evt)
void on_idle (wxIdleEvent &evt)
void on_char (wxKeyEvent &evt)
void on_key (wxKeyEvent &evt)
void release_held_modifiers ()
bool handle_shortcut (const KeyChord &chord)
void apply_selection_move (bool slow, bool camera_space)
void apply_selection_rotate (double angle_z_rad)
void finish_selection_edit ()
void update_shortcut_tooltips ()
void on_mouse_wheel (wxMouseEvent &evt)
void on_timer (wxTimerEvent &evt)
void on_render_timer (wxTimerEvent &evt)
void on_set_color_timer (wxTimerEvent &evt)
void on_fps_overlay_timer (wxTimerEvent &evt)
void on_mouse (wxMouseEvent &evt)
void on_gesture (wxGestureEvent &evt)
void on_paint (wxPaintEvent &evt)
void on_set_focus (wxFocusEvent &evt)
void force_set_focus ()
bool clicked_button_matches_action (const wxMouseEvent &evt, MouseAction action, const std::map< MouseButton, MouseAction > &mappings) const
bool is_camera_rotate (const wxMouseEvent &evt, const std::map< MouseButton, MouseAction > &mappings) const
bool is_camera_pan (const wxMouseEvent &evt, const std::map< MouseButton, MouseAction > &mappings) const
Size get_canvas_size () const
Vec2d get_local_mouse_position () const
void set_popup_menu_position (const Vec2d &position)
const std::optional< Vec2d > & get_popup_menu_position () const
void clear_popup_menu_position ()
void set_tooltip (const std::string &tooltip)
void do_move (const std::string &snapshot_type, bool force_volume_move=false)
void do_rotate (const std::string &snapshot_type)
void do_scale (const std::string &snapshot_type)
void do_center ()
void do_drop ()
void do_center_plate (const int plate_idx)
void do_mirror (const std::string &snapshot_type)
void update_gizmos_on_off_state ()
void reset_all_gizmos ()
void handle_sidebar_focus_event (const std::string &opt_key, bool focus_on)
void handle_layers_data_focus_event (const t_layer_height_range range, const EditorType type)
void update_ui_from_settings ()
int get_move_volume_id () const
int get_first_hover_volume_idx () const
int get_hover_ghost_head () const
int get_hover_ghost_plate () const
void set_selected_extruder (int extruder)
WipeTowerInfo get_wipe_tower_info (int plate_idx) const
Linef3 mouse_ray (const Point &mouse_pos)
void set_mouse_as_dragging ()
bool is_mouse_dragging () const
bool is_mouse_left_up_ignored () const
double get_size_proportional_to_max_bed_size (double factor) const
std::vector< Vec2f > get_empty_cells (const Vec2f start_point, const Vec2f step={10, 10})
Vec2f get_nearest_empty_cell (const Vec2f start_point, const Vec2f step={10, 10})
void set_cursor (ECursorType type)
void msw_rescale ()
void request_extra_frame ()
void schedule_extra_frame (int milliseconds)
void set_benchmarking (bool benchmarking)
FrameProfiler & get_frame_profiler ()
int get_main_toolbar_item_id (const std::string &name) const
void force_main_toolbar_left_action (int item_id)
void force_main_toolbar_right_action (int item_id)
bool has_toolpaths_to_export () const
void export_toolpaths_to_obj (const char *filename) const
void mouse_up_cleanup ()
bool are_labels_shown () const
void show_labels (bool show)
bool is_overhang_shown () const
void show_overhang (bool show)
bool is_using_slope () const
void use_slope (bool use)
void set_slope_normal_angle (float angle_in_deg)
void highlight_toolbar_item (const std::string &item_name)
void highlight_gizmo (const std::string &gizmo_name)
void reset_sequential_print_clearance ()
void set_sequential_print_clearance_visible (bool visible)
void set_sequential_print_clearance_render_fill (bool render_fill)
void set_sequential_print_clearance_polygons (const Polygons &polygons, const std::vector< std::pair< Polygon, float > > &height_polygons)
bool can_sequential_clearance_show_in_gizmo ()
void update_sequential_clearance ()
void update_compacted_wipe_tower_clearance ()
const Print * fff_print () const
const SLAPrint * sla_print () const
void reset_old_size ()
bool is_object_sinking (int object_idx) const
void apply_retina_scale (Vec2d &screen_coordinate) const
void _perform_layer_editing_action (wxMouseEvent *evt=nullptr)
Vec3d _mouse_to_3d (const Point &mouse_pos, float *z=nullptr)
bool make_current_for_postinit ()
void set_imgui_scaling ()

Static Public Member Functions

static bool is_frame_in_progress ()
static void render_thumbnail_internal (ThumbnailData &thumbnail_data, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
static void render_thumbnail_framebuffer (ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
static void render_thumbnail_framebuffer_ext (ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
static void render_thumbnail_legacy (ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
static int64_t timestamp_now ()

Public Attributes

SequentialPrintClearance m_sequential_print_clearance
bool m_sequential_print_clearance_first_displacement { true }
struct Slic3r::GUI::GLCanvas3D::ToolbarHighlighter m_toolbar_highlighter
struct Slic3r::GUI::GLCanvas3D::GizmoHighlighter m_gizmo_highlighter
GLModel m_background
unsigned int m_fxaa_texture_id { 0 }
std::array< unsigned int, 2 > m_fxaa_texture_size { 0, 0 }
unsigned int m_ssao_color_texture_id { 0 }
unsigned int m_ssao_depth_texture_id { 0 }
std::array< unsigned int, 2 > m_ssao_texture_size { { 0, 0 } }
SceneCache m_scene_cache
std::optional< size_t > m_presented_signature
GLModel m_plate_shadow_mask
std::string m_plate_shadow_mask_key
unsigned int m_shadow_map_fbo { 0 }
unsigned int m_shadow_map_texture_id { 0 }
unsigned int m_shadow_map_size { 0 }
Transform3d m_shadow_light_vp { Transform3d::Identity() }
bool m_shadow_map_valid { false }
size_t m_shadow_map_key { 0 }
std::array< float, 4 > m_shadow_plate_bounds { { 0.0f, 0.0f, 0.0f, 0.0f } }
std::optional< Vec2d > m_popup_menu_positon

Private Types

enum class  EWarning {
  ObjectOutside , ToolpathOutside , SlaSupportsOutside , SomethingNotShown ,
  ObjectClashed , ObjectLimited , GCodeConflict , ToolHeightOutside ,
  TPUPrintableError , FilamentPrintableError , LeftExtruderPrintableError , RightExtruderPrintableError ,
  MultiExtruderPrintableError , MultiExtruderHeightOutside , FilamentUnPrintableOnFirstLayer , MixUsePLAAndPETG ,
  PrimeTowerOutside , NozzleFilamentIncompatible , MixtureFilamentIncompatible , SingleExtruderMixedFilament ,
  FlushingVolumeZero
}
enum class  EShadowMode { Off , Static , Orbit }
enum class  ECameraNavigationType : unsigned char { Mouse , Gesture }

Private Member Functions

PrinterTechnology current_printer_technology () const
bool check_volumes_outside_state (GLVolumeCollection &volumes, ModelInstanceEPrintVolumeState *out_state, bool selection_only=true) const
bool _is_shown_on_screen () const
void _update_slice_error_status ()
void _switch_toolbars_icon_filename ()
bool _init_toolbars ()
bool _init_main_toolbar ()
bool _init_select_plate_toolbar ()
bool _update_imgui_select_plate_toolbar ()
bool _init_assemble_view_toolbar ()
bool _init_return_toolbar ()
bool _init_separator_toolbar ()
bool _init_collapse_toolbar ()
GLToolbar & collapse_toolbar () const
CollapseSide collapse_side () const
bool _set_current ()
bool _set_shown_canvas_current ()
void _resize (unsigned int w, unsigned int h)
BoundingBoxf3 _max_bounding_box (bool include_gizmos, bool include_bed_model, bool include_plates) const
void _zoom_to_box (const BoundingBoxf3 &box, double margin_factor=DefaultCameraZoomToBoxMarginFactor)
void _update_camera_zoom (double zoom)
void _refresh_if_shown_on_screen (bool scene_dirty=true)
void _picking_pass ()
void _rectangular_selection_picking_pass ()
void _picking_pass_imex_ghosts ()
bool _is_fxaa_enabled () const
bool _is_realistic_view_enabled () const
bool _is_ssao_enabled () const
int _get_effective_fps_cap () const
bool _is_fps_overlay_enabled () const
bool _is_render_timings_enabled () const
EShadowMode _shadow_mode () const
std::optional< Vec3d > _static_light_dir_eye () const
size_t _shadow_casters_signature (bool toolpath_casters) const
bool _is_scene_cache_enabled () const
bool _is_scene_cacheable () const
bool _is_frame_skipping_enabled () const
void _render_fps_overlay (int fps) const
void _render_fxaa_pass (unsigned int width, unsigned int height)
void _render_ssao_pass (unsigned int width, unsigned int height)
void _render_frame (bool scene_dirty, bool only_init=false)
void _render_scene (const Camera &camera, const Size &cnv_size)
void _set_overlay_as_dirty ()
SceneCache::Key _scene_cache_key (const Camera &camera) const
bool _can_reuse_cached_scene (const Camera &camera) const
void _capture_scene_cache (const Camera &camera)
void _render_background ()
void _render_bed (const Transform3d &view_matrix, const Transform3d &projection_matrix, bool bottom, bool show_axes)
void _render_shadows (const Transform3d &view_matrix, const Transform3d &projection_matrix)
void _render_platelist (const Transform3d &view_matrix, const Transform3d &projection_matrix, bool bottom, bool only_current, bool only_body=false, int hover_id=-1, bool render_cali=false, bool show_grid=true)
bool _hides_inactive_plates () const
bool _update_inactive_plates_visibility ()
BoundingBoxf3 _current_plate_box () const
void _render_cad_grid (const Transform3d &view_matrix, const Transform3d &projection_matrix)
void _render_objects (GLVolumeCollection::ERenderType type, bool with_outline=true)
void _render_imex_ghosts (bool xray_pass=false)
void _render_imex_ghosts_xray ()
void _render_imex_ghost_tooltip ()
void _render_section_view_caps ()
void _render_wireframe_overlay ()
bool _is_below_plate_view_active () const
void _render_below_plate_volumes ()
bool _is_xray_view_active () const
void _render_xray_volumes ()
void _render_gcode (int canvas_width, int canvas_height)
void _render_gcode_translucent (int canvas_width, int canvas_height)
bool _bind_gcode_shadow_map (bool bind) const
void _render_gcode_overlay (int canvas_width, int canvas_height)
void _render_plane () const
void _render_selection ()
void _render_sequential_clearance ()
void _check_and_update_toolbar_icon_scale ()
void _render_overlays ()
void _render_overlay_toolbars ()
size_t _overlay_signature (const ImDrawData *draw_data) const
void _render_style_editor ()
void _render_volumes_for_picking (const Camera &camera) const
void _render_current_gizmo () const
void _render_gizmos_overlay ()
void _render_main_toolbar ()
void _render_imgui_select_plate_toolbar ()
void _render_plate_switcher ()
void _render_assemble_view_toolbar () const
void _render_return_toolbar () const
void _render_canvas_toolbar ()
void _render_section_view_panel (const ImVec2 &bottom_left)
void _render_separator_toolbar_right () const
void _render_separator_toolbar_left () const
void _render_collapse_toolbar () const
void _render_paint_toolbar () const
float _render_assembly_tooltip_button (ImGuiWrapper *imgui_wrapper) const
void _render_assemble_control ()
void _render_assemble_info () const
void _render_sla_slices ()
void _render_selection_sidebar_hints ()
bool _render_orient_menu (float left, float right, float bottom, float top)
void _render_arrange_menu (float left, float right, float bottom, float top)
void _render_3d_navigator ()
void _update_volumes_hover_state ()
Vec3d _mouse_to_bed_3d (const Point &mouse_pos)
void _on_section_view_changed ()
ClippingPlane _get_section_view_plane () const
ClippingPlane _get_volumes_clipping_plane () const
ClippingPlane get_raycaster_clipping_plane () const
bool is_bed_visible () const
std::optional< Vec3d > get_camera_orbit_target (ECameraNavigationType navigation_type) const
Vec3d get_camera_pan_anchor (Camera &camera, ECameraNavigationType navigation_type, const Vec2d &screen_position) const
void _start_timer ()
void _stop_timer ()
void _load_sla_shells ()
void _update_sla_shells_outside_state ()
void _set_warning_notification_if_needed (EWarning warning)
BoundingBoxf3 _get_current_partplate_print_volume ()
void _set_warning_notification (EWarning warning, bool state)
bool is_flushing_matrix_error ()
bool _is_any_volume_outside () const
void _update_selection_from_hover ()
bool _deactivate_collapse_toolbar_items ()
bool _deactivate_arrange_menu ()
bool _deactivate_orient_menu ()
bool _deactivate_layersediting_menu ()
float get_overlay_window_width ()

Static Private Member Functions

static void update_render_colors ()
static void load_render_colors ()

Private Attributes

bool m_is_dark = false
wxGLCanvas * m_canvas
wxGLContext * m_context
SceneRaycaster m_scene_raycaster
Bed3D & m_bed
std::vector< std::pair< wxString, wxString > > m_shortcuts_assembly_view
unsigned int m_last_w
unsigned int m_last_h
bool m_in_render
wxTimer m_timer
wxTimer m_timer_set_color
wxTimer m_fps_overlay_timer
bool m_fps_overlay_tick { false }
LayersEditing m_layers_editing
Mouse m_mouse
std::optional< Vec3d > m_gesture_pan_anchor
GLGizmosManager m_gizmos
GLToolbar m_main_toolbar
GLToolbar m_separator_toolbar
IMToolbar m_sel_plate_toolbar
std::vector< std::unique_ptr< IMToolbarItem > > m_plate_switcher_items
unsigned m_plate_switcher_version { unsigned(-1) }
bool m_plate_switcher_scrollbar { false }
GLToolbar m_assemble_view_toolbar
IMReturnToolbar m_return_toolbar
Vec2i32 m_canvas_toolbar_pos = {140, 5}
float m_sc {1}
float m_paint_toolbar_width
bool m_collapse_toolbar_enabled {true}
GLToolbar * m_collapse_toolbar {nullptr}
std::function< CollapseSide()> m_collapse_side
bool m_plate_chrome_enabled {true}
bool m_design_canvas {false}
bool m_show_bed {true}
bool m_sinking_contours_enabled {true}
GLModel m_cad_grid_minor
GLModel m_cad_grid_major
BoundingBoxf m_cad_grid_bb
Vec2d m_cad_grid_center
bool m_cad_grid_valid {false}
ECanvasType m_canvas_type
bool m_studio_lighting {false}
std::array< ClippingPlane, 2 > m_clipping_planes
ClippingPlane m_camera_clipping_plane
bool m_use_clipping_planes
std::shared_ptr< SectionView > m_section_view { std::make_shared<SectionView>(this) }
std::map< const GLVolume *, MeshClipper > m_section_view_caps
bool m_alt_wheel_used { false }
std::array< SlaCap, 2 > m_sla_caps
std::string m_sidebar_field
bool m_extra_frame_requested
bool m_event_handlers_bound { false }
GLVolumeCollection m_volumes
GCodeViewer m_gcode_viewer
RenderTimer m_render_timer
Selection m_selection
const DynamicPrintConfig * m_config
Model * m_model
BackgroundSlicingProcess * m_process
bool m_requires_check_outside_state { false }
std::array< unsigned int, 2 > m_old_size { 0, 0 }
bool m_is_touchpad_navigation { false }
bool m_dirty
bool m_overlay_dirty { false }
bool m_initialized
bool m_render_preview { true }
bool m_enable_render { true }
bool m_apply_zoom_to_volumes_filter
bool m_picking_enabled
bool m_moving_enabled
bool m_dynamic_background_enabled
bool m_multisample_allowed
bool m_moving
KeyDown m_key_down
SelectionEdit m_selection_edit
bool m_camera_movement
bool m_toolpath_outside { false }
ECursorType m_cursor_type
GLSelectionRectangle m_rectangle_selection
bool m_navigator_dragging { false }
std::vector< int > m_hover_volume_idxs
std::vector< int > m_hover_plate_idxs
bool m_inactive_plates_hidden { false }
int m_hover_ghost_head { -1 }
int m_hover_ghost_plate { -1 }
float m_explosion_ratio = 1.0
Vec3d m_rotation_center { 0.0, 0.0, 0.0}
Camera camera
bool m_render_sla_auxiliaries
std::string m_color_by
bool m_reload_delayed
RenderStats m_render_stats
FrameProfiler m_frame_profiler
bool m_benchmarking { false }
std::chrono::time_point< std::chrono::steady_clock > m_last_frame_start_time { std::chrono::steady_clock::now() }
int m_imgui_undo_redo_hovered_pos { -1 }
int m_mouse_wheel { 0 }
int m_selected_extruder
Labels m_labels
CenterOfMass m_center_of_mass
Tooltip m_tooltip
bool m_tooltip_enabled { true }
Slope m_slope
OrientSettings m_orient_settings_fff
OrientSettings m_orient_settings_sla
ArrangeSettings m_arrange_settings_fff
ArrangeSettings m_arrange_settings_sla
ArrangeSettings m_arrange_settings_fff_seq_print
bool m_show_world_axes {true}
Bed3D::Axes m_axes
int auto_orient_count = 0
int auto_arrange_count = 0
int split_to_objects_count = 0
int split_to_part_count = 0
int custom_height_count = 0
int assembly_view_count = 0
std::vector< float > m_gcode_layers_times_cache

Static Private Attributes

static const double DefaultCameraZoomToBoxMarginFactor = 1.25
static const double DefaultCameraZoomToBedMarginFactor = 2.00
static const double DefaultCameraZoomToPlateMarginFactor = 1.25
static int s_frames_in_progress = 0

Detailed Description


Class Documentation

◆ Slic3r::GUI::GLCanvas3D::ArrangeSettings

struct Slic3r::GUI::GLCanvas3D::ArrangeSettings
Class Members
float accuracy = 0.65f
bool align_to_y_axis = false
bool allow_multi_materials_on_same_plate = true
bool avoid_extrusion_cali_region = true
float distance = 0.f
bool enable_rotation = false
bool is_seq_print = false

◆ Slic3r::GUI::GLCanvas3D::OrientSettings

struct Slic3r::GUI::GLCanvas3D::OrientSettings
Class Members
bool enable_rotation = false
bool min_area = true
float overhang_angle = 60.f

◆ Slic3r::GUI::GLCanvas3D::KeyDown

struct Slic3r::GUI::GLCanvas3D::KeyDown
Class Members
int code = WXK_NONE
bool repeat = false

Member Enumeration Documentation

◆ ECameraNavigationType

enum class Slic3r::GUI::GLCanvas3D::ECameraNavigationType : unsigned char
strongprivate
Enumerator
Mouse 
Gesture 
1617 {
1618 Mouse,
1619 Gesture
1620 };
@ Gesture
Definition DesignInteraction.hpp:21

◆ ECanvasType

Enumerator
CanvasView3D 
CanvasPreview 
CanvasAssembleView 
625 {
626 CanvasView3D = 0,
627 CanvasPreview = 1,
629 };
@ CanvasAssembleView
Definition GLCanvas3D.hpp:628
@ CanvasPreview
Definition GLCanvas3D.hpp:627
@ CanvasView3D
Definition GLCanvas3D.hpp:626

◆ ECursorType

Enumerator
Standard 
Cross 
598 {
599 Standard,
600 Cross
601 };
@ Standard
Definition GLCanvas3D.hpp:599
@ Cross
Definition GLCanvas3D.hpp:600

◆ EShadowMode

enum class Slic3r::GUI::GLCanvas3D::EShadowMode
strongprivate
Enumerator
Off 
Static 
Orbit 
1511{ Off, Static, Orbit };

◆ EWarning

enum class Slic3r::GUI::GLCanvas3D::EWarning
strongprivate
Enumerator
ObjectOutside 
ToolpathOutside 
SlaSupportsOutside 
SomethingNotShown 
ObjectClashed 
ObjectLimited 
GCodeConflict 
ToolHeightOutside 
TPUPrintableError 
FilamentPrintableError 
LeftExtruderPrintableError 
RightExtruderPrintableError 
MultiExtruderPrintableError 
MultiExtruderHeightOutside 
FilamentUnPrintableOnFirstLayer 
MixUsePLAAndPETG 
PrimeTowerOutside 
NozzleFilamentIncompatible 
MixtureFilamentIncompatible 
SingleExtruderMixedFilament 
FlushingVolumeZero 
417 {
418 ObjectOutside,
419 ToolpathOutside,
420 SlaSupportsOutside,
421 SomethingNotShown,
422 ObjectClashed,
423 ObjectLimited,
424 GCodeConflict,
425 ToolHeightOutside,
426 TPUPrintableError,
427 FilamentPrintableError,
428 LeftExtruderPrintableError, // before slice
429 RightExtruderPrintableError, // before slice
430 MultiExtruderPrintableError, // after slice
431 MultiExtruderHeightOutside, // after slice
432 FilamentUnPrintableOnFirstLayer,
433 MixUsePLAAndPETG,
434 PrimeTowerOutside,
435 NozzleFilamentIncompatible,
436 MixtureFilamentIncompatible,
437 SingleExtruderMixedFilament,
438 FlushingVolumeZero
439 };

◆ MouseAction

Enumerator
None 
Pan 
Rotation 
1299{ None, Pan, Rotation };
@ None
Definition SketchEngine.hpp:180

◆ MouseButton

Enumerator
None 
Left 
Middle 
Right 
1298{ None, Left, Middle, Right };
@ Right
Definition GLToolbar.hpp:462
@ Left
Definition GLToolbar.hpp:462

Constructor & Destructor Documentation

◆ GLCanvas3D()

Slic3r::GUI::GLCanvas3D::GLCanvas3D ( wxGLCanvas * canvas,
Bed3D & bed )
explicit
1595 : m_canvas(canvas)
1596 , m_context(nullptr)
1597 , m_bed(bed)
1598#if ENABLE_RETINA_GL
1599 , m_retina_helper(nullptr)
1600#endif
1601 , m_in_render(false)
1604 , m_assemble_view_toolbar(GLToolbar::Normal, "Assembly_View")
1607 , m_gizmos(*this)
1608 , m_use_clipping_planes(false)
1609 , m_sidebar_field("")
1611 , m_config(nullptr)
1612 , m_process(nullptr)
1613 , m_model(nullptr)
1614 , m_dirty(true)
1615 , m_initialized(false)
1617 , m_picking_enabled(false)
1618 , m_moving_enabled(false)
1620 , m_multisample_allowed(false)
1621 , m_moving(false)
1622 , m_camera_movement(false)
1624 , m_color_by("volume")
1625 , m_reload_delayed(false)
1627 , m_labels(*this)
1629{
1630 if (m_canvas != nullptr) {
1631 m_timer.SetOwner(m_canvas);
1632 m_render_timer.SetOwner(m_canvas);
1633#if ENABLE_RETINA_GL
1634 m_retina_helper.reset(new RetinaHelper(canvas));
1635#endif // ENABLE_RETINA_GL
1636 }
1637 m_timer_set_color.Bind(wxEVT_TIMER, &GLCanvas3D::on_set_color_timer, this);
1638 m_fps_overlay_timer.Bind(wxEVT_TIMER, &GLCanvas3D::on_fps_overlay_timer, this);
1640
1641 m_selection.set_volumes(&m_volumes.volumes);
1642
1643 const wxString alt = GUI::shortkey_alt_prefix();
1644
1646 {_L("Left mouse button"), _L("Object selection")},
1647 {alt + _L("Left mouse button"), _L("Part selection")},
1648 {_L("1~16 number keys"), _L("Number keys can quickly change the color of objects")},
1649 };
1650}
#define _L(s)
Definition OBJ.cpp:34
const DynamicPrintConfig * m_config
Definition GLCanvas3D.hpp:736
wxGLCanvas * m_canvas
Definition GLCanvas3D.hpp:635
bool m_picking_enabled
Definition GLCanvas3D.hpp:753
bool m_initialized
Definition GLCanvas3D.hpp:748
wxGLContext * m_context
Definition GLCanvas3D.hpp:636
wxTimer m_timer_set_color
Definition GLCanvas3D.hpp:649
void on_fps_overlay_timer(wxTimerEvent &evt)
Definition GLCanvas3D.cpp:4597
bool m_apply_zoom_to_volumes_filter
Definition GLCanvas3D.hpp:752
std::string m_color_by
Definition GLCanvas3D.hpp:800
ECursorType m_cursor_type
Definition GLCanvas3D.hpp:778
Model * m_model
Definition GLCanvas3D.hpp:737
Selection m_selection
Definition GLCanvas3D.hpp:735
GLToolbar m_main_toolbar
Definition GLCanvas3D.hpp:660
bool m_dynamic_background_enabled
Definition GLCanvas3D.hpp:755
bool m_dirty
Definition GLCanvas3D.hpp:745
bool m_camera_movement
Definition GLCanvas3D.hpp:775
std::vector< std::pair< wxString, wxString > > m_shortcuts_assembly_view
Definition GLCanvas3D.hpp:640
BackgroundSlicingProcess * m_process
Definition GLCanvas3D.hpp:738
GLToolbar m_assemble_view_toolbar
Definition GLCanvas3D.hpp:667
bool m_render_sla_auxiliaries
Definition GLCanvas3D.hpp:798
Bed3D & m_bed
Definition GLCanvas3D.hpp:638
Slope m_slope
Definition GLCanvas3D.hpp:817
IMReturnToolbar m_return_toolbar
Definition GLCanvas3D.hpp:668
bool m_reload_delayed
Definition GLCanvas3D.hpp:802
wxTimer m_fps_overlay_timer
Definition GLCanvas3D.hpp:651
bool m_multisample_allowed
Definition GLCanvas3D.hpp:756
void load_arrange_settings()
Definition GLCanvas3D.cpp:1526
bool m_extra_frame_requested
Definition GLCanvas3D.hpp:727
GLVolumeCollection m_volumes
Definition GLCanvas3D.hpp:730
GLToolbar m_separator_toolbar
Definition GLCanvas3D.hpp:661
Labels m_labels
Definition GLCanvas3D.hpp:813
bool m_moving_enabled
Definition GLCanvas3D.hpp:754
void on_set_color_timer(wxTimerEvent &evt)
Definition GLCanvas3D.cpp:4589
ECanvasType m_canvas_type
Definition GLCanvas3D.hpp:703
wxTimer m_timer
Definition GLCanvas3D.hpp:648
bool m_use_clipping_planes
Definition GLCanvas3D.hpp:709
bool m_in_render
Definition GLCanvas3D.hpp:645
RenderTimer m_render_timer
Definition GLCanvas3D.hpp:733
std::string m_sidebar_field
Definition GLCanvas3D.hpp:724
GLGizmosManager m_gizmos
Definition GLCanvas3D.hpp:658
bool m_moving
Definition GLCanvas3D.hpp:757
@ Normal
Definition GLToolbar.hpp:274
const std::string & shortkey_alt_prefix()
Definition GUI.cpp:127

References GLCanvas3D(), _L, CanvasView3D, ENABLE_RETINA_GL, load_arrange_settings(), m_apply_zoom_to_volumes_filter, m_assemble_view_toolbar, m_bed, m_camera_movement, m_canvas, m_canvas_type, m_color_by, m_config, m_context, m_cursor_type, m_dirty, m_dynamic_background_enabled, m_extra_frame_requested, m_fps_overlay_timer, m_gizmos, m_in_render, m_initialized, m_labels, m_main_toolbar, m_model, m_moving, m_moving_enabled, m_multisample_allowed, m_picking_enabled, m_process, m_reload_delayed, m_render_sla_auxiliaries, m_render_timer, m_return_toolbar, m_selection, m_separator_toolbar, m_shortcuts_assembly_view, m_sidebar_field, m_slope, m_timer, m_timer_set_color, m_use_clipping_planes, m_volumes, Slic3r::GUI::Normal, on_fps_overlay_timer(), on_set_color_timer(), Slic3r::GUI::shortkey_alt_prefix(), and Standard.

Referenced by GLCanvas3D(), Slic3r::GUI::GLCanvas3D::Labels::Labels(), Slic3r::GUI::GLCanvas3D::SectionView::SectionView(), _get_section_view_plane(), _render_background(), Slic3r::GUI::GLCanvas3D::LayersEditing::accept_changes(), Slic3r::GUI::GLCanvas3D::LayersEditing::adaptive_layer_height_profile(), Slic3r::GUI::GLCanvas3D::LayersEditing::bar_rect_contains(), Slic3r::GUI::GLCanvas3D::LayersEditing::get_bar_rect_screen(), Slic3r::GUI::GLCanvas3D::LayersEditing::get_cursor_z_relative(), Slic3r::GUI::GLCanvas3D::LayersEditing::get_tooltip(), Slic3r::GUI::GLCanvas3D::GizmoHighlighter::init(), Slic3r::GUI::GLCanvas3D::ToolbarHighlighter::init(), Slic3r::GUI::GLCanvas3D::CenterOfMass::model_markers(), Slic3r::GUI::GLCanvas3D::CenterOfMass::on_left_down(), Slic3r::GUI::GLCanvas3D::CenterOfMass::render(), Slic3r::GUI::GLCanvas3D::Tooltip::render(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_active_object_annotations(), Slic3r::GUI::GLCanvas3D::CenterOfMass::render_details(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_overlay(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_profile(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_volumes(), Slic3r::GUI::GLCanvas3D::LayersEditing::reset_layer_height_profile(), share_section_view(), Slic3r::GUI::GLCanvas3D::LayersEditing::smooth_layer_height_profile(), and Slic3r::GUI::GLCanvas3D::LayersEditing::thickness_bar_width().

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

◆ ~GLCanvas3D()

Slic3r::GUI::GLCanvas3D::~GLCanvas3D ( )
1653{
1654 if (_set_current()) {
1655 m_scene_cache.reset();
1656 m_frame_profiler.reset();
1657 if (m_fxaa_texture_id != 0) {
1660 }
1661 if (m_ssao_color_texture_id != 0) {
1664 }
1665 if (m_ssao_depth_texture_id != 0) {
1668 }
1669 if (m_shadow_map_texture_id != 0) {
1672 }
1673 if (m_shadow_map_fbo != 0) {
1675 m_shadow_map_fbo = 0;
1676 }
1677 m_plate_shadow_mask.reset();
1678 m_section_view_caps.clear();
1679 }
1681 if (m_section_view->owner == this)
1682 m_section_view->owner = nullptr;
1683
1684 reset_volumes();
1685
1686 m_sel_plate_toolbar.del_all_item();
1687 m_sel_plate_toolbar.del_stats_item();
1688 m_plate_switcher_items.clear();
1689}
#define glsafe(cmd)
Definition OpenGLUtils.hpp:25
void reset_volumes()
Definition GLCanvas3D.cpp:1820
std::shared_ptr< SectionView > m_section_view
Definition GLCanvas3D.hpp:719
IMToolbar m_sel_plate_toolbar
Definition GLCanvas3D.hpp:662
SceneCache m_scene_cache
Definition GLCanvas3D.hpp:928
FrameProfiler m_frame_profiler
Definition GLCanvas3D.hpp:805
std::vector< std::unique_ptr< IMToolbarItem > > m_plate_switcher_items
Definition GLCanvas3D.hpp:664
unsigned int m_fxaa_texture_id
Definition GLCanvas3D.hpp:922
unsigned int m_shadow_map_fbo
Definition GLCanvas3D.hpp:935
bool _set_current()
Definition GLCanvas3D.cpp:7844
GLModel m_plate_shadow_mask
Definition GLCanvas3D.hpp:932
unsigned int m_shadow_map_texture_id
Definition GLCanvas3D.hpp:936
unsigned int m_ssao_depth_texture_id
Definition GLCanvas3D.hpp:925
unsigned int m_ssao_color_texture_id
Definition GLCanvas3D.hpp:924
std::map< const GLVolume *, MeshClipper > m_section_view_caps
Definition GLCanvas3D.hpp:720
std::string m_plate_shadow_mask_key
Definition GLCanvas3D.hpp:933
#define glDeleteFramebuffers
Definition gl.h:3565
#define glDeleteTextures
Definition gl.h:3587

References _set_current(), glDeleteFramebuffers, glDeleteTextures, glsafe, m_frame_profiler, m_fxaa_texture_id, m_plate_shadow_mask, m_plate_shadow_mask_key, m_plate_switcher_items, m_scene_cache, m_section_view, m_section_view_caps, m_sel_plate_toolbar, m_shadow_map_fbo, m_shadow_map_texture_id, m_ssao_color_texture_id, m_ssao_depth_texture_id, and reset_volumes().

Here is the call graph for this function:

Member Function Documentation

◆ _bind_gcode_shadow_map()

bool Slic3r::GUI::GLCanvas3D::_bind_gcode_shadow_map ( bool bind) const
private
9940{
9942 return false;
9946 return true;
9947}
bool m_shadow_map_valid
Definition GLCanvas3D.hpp:939
unsigned int m_shadow_map_size
Definition GLCanvas3D.hpp:937
#define GL_TEXTURE0
Definition gl.h:1705
#define GL_TEXTURE4
Definition gl.h:1731
#define glBindTexture
Definition gl.h:3299
#define GL_TEXTURE_2D
Definition gl.h:1739
#define glActiveTexture
Definition gl.h:3245

References _bind_gcode_shadow_map(), GL_TEXTURE0, GL_TEXTURE4, GL_TEXTURE_2D, glActiveTexture, glBindTexture, glsafe, m_shadow_map_size, m_shadow_map_texture_id, and m_shadow_map_valid.

Referenced by _bind_gcode_shadow_map(), _render_gcode(), and _render_gcode_translucent().

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

◆ _can_reuse_cached_scene()

bool Slic3r::GUI::GLCanvas3D::_can_reuse_cached_scene ( const Camera & camera) const
private
8806{
8808}
bool _is_scene_cacheable() const
Definition GLCanvas3D.cpp:8581
Camera camera
Definition GLCanvas3D.hpp:794
SceneCache::Key _scene_cache_key(const Camera &camera) const
Definition GLCanvas3D.cpp:8780

References _can_reuse_cached_scene(), _is_scene_cacheable(), _scene_cache_key(), camera, and m_scene_cache.

Referenced by _can_reuse_cached_scene(), and _render_frame().

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

◆ _capture_scene_cache()

void Slic3r::GUI::GLCanvas3D::_capture_scene_cache ( const Camera & camera)
private
8811{
8812 if (!_is_scene_cache_enabled()) {
8813 m_scene_cache.reset();
8814 return;
8815 }
8816
8817 if (!_is_scene_cacheable()) {
8818 m_scene_cache.invalidate();
8819 return;
8820 }
8821
8823}
bool _is_scene_cache_enabled() const
Definition GLCanvas3D.cpp:8576

References _capture_scene_cache(), _is_scene_cache_enabled(), _is_scene_cacheable(), _scene_cache_key(), camera, and m_scene_cache.

Referenced by _capture_scene_cache(), and _render_scene().

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

◆ _check_and_update_toolbar_icon_scale()

void Slic3r::GUI::GLCanvas3D::_check_and_update_toolbar_icon_scale ( )
private
10001{
10002 // Update collapse toolbar
10003 GLToolbar& collapse_toolbar = this->collapse_toolbar();
10005
10006 // Don't update a toolbar scale, when we are on a Preview. Asked of this canvas, not of the
10007 // plater: the Design tab's canvas is on screen while the plater's current view may be Preview.
10009 IMSlider *m_layers_slider = get_gcode_viewer().get_layers_slider();
10010 IMSlider *m_moves_slider = get_gcode_viewer().get_moves_slider();
10011 float sc = get_scale();
10012#ifdef WIN32
10013 int dpi = get_dpi_for_window(wxGetApp().GetTopWindow());
10014 sc *= (float) dpi / (float) DPI_DEFAULT;
10015#endif // WIN32
10016
10017 m_layers_slider->set_scale(sc * GCODE_VIEWER_SLIDER_SCALE);
10018 m_moves_slider->set_scale(sc * GCODE_VIEWER_SLIDER_SCALE);
10019 m_gcode_viewer.set_scale(sc);
10020
10021 auto *m_notification = wxGetApp().plater()->get_notification_manager();
10022 m_notification->set_scale(sc);
10023 return;
10024 }
10025
10026 float scale = wxGetApp().toolbar_icon_scale() * get_scale();
10027 Size cnv_size = get_canvas_size();
10028
10029 //BBS: GUI refactor: GLToolbar
10030 int size_i = int(GLToolbar::Default_Icons_Size * scale);
10031 // force even size
10032 if (size_i % 2 != 0)
10033 size_i -= 1;
10034 float size = size_i;
10035
10036 // Set current size for all top toolbars. It will be used for next calculations
10037 //BBS: GUI refactor: GLToolbar
10038 m_main_toolbar.set_icons_size(size);
10039 m_assemble_view_toolbar.set_icons_size(size);
10040 m_separator_toolbar.set_icons_size(size);
10041 collapse_toolbar.set_icons_size(size / 2.0);
10042 m_gizmos.set_overlay_icon_size(size);
10043
10044 //BBS: GUI refactor: GLToolbar
10045#if BBS_TOOLBAR_ON_TOP
10046 float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : 0;
10047
10048 float top_tb_width = m_main_toolbar.get_width() + m_gizmos.get_scaled_total_width() + m_assemble_view_toolbar.get_width() + m_separator_toolbar.get_width() + collapse_toolbar_width * 2;
10049 int items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + m_assemble_view_toolbar.get_visible_items_cnt() + m_separator_toolbar.get_visible_items_cnt() + collapse_toolbar.get_visible_items_cnt();
10050 float noitems_width = top_tb_width - size * items_cnt; // width of separators and borders in top toolbars
10051
10052 // calculate scale needed for items in all top toolbars
10053 float new_h_scale = (cnv_size.get_width() - noitems_width) / (items_cnt * GLToolbar::Default_Icons_Size);
10054
10055 //for protect
10056 if (new_h_scale <= 0) {
10057 new_h_scale = 1;
10058 }
10059
10060 //use the same value as horizon
10061 float new_v_scale = new_h_scale;
10062#else
10063 float top_tb_width = = collapse_toolbar.get_width();
10064 int items_cnt = collapse_toolbar.get_visible_items_cnt();
10065 float noitems_width = top_tb_width - size * items_cnt; // width of separators and borders in top toolbars
10066
10067 // calculate scale needed for items in all top toolbars
10068 float new_h_scale = (cnv_size.get_width() - noitems_width) / (items_cnt * GLToolbar::Default_Icons_Size);
10069
10070 //items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + 3; // +3 means a place for top and view toolbars and separators in gizmos toolbar
10071
10072 // calculate scale needed for items in the gizmos toolbar
10073 items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + m_assemble_view_toolbar.get_visible_items_cnt();
10074 float new_v_scale = cnv_size.get_height() / (items_cnt * GLGizmosManager::Default_Icons_Size);
10075#endif
10076
10077 // set minimum scale as a auto scale for the toolbars
10078 float new_scale = std::min(new_h_scale, new_v_scale);
10079 new_scale /= get_scale();
10080 // Only a canvas with toolbars to fit sets the shared size: a collapse button alone (the Design
10081 // tab's canvas) always fits at the largest.
10082 if (items_cnt > collapse_toolbar.get_visible_items_cnt() && fabs(new_scale - scale) > 0.05) // scale is changed by 5% and more
10083 wxGetApp().set_auto_toolbar_icon_scale(new_scale);
10084}
int scale(const int val)
Definition WipeTowerDialog.cpp:58
IMSlider * get_layers_slider()
Definition GCodeViewer.hpp:465
IMSlider * get_moves_slider()
Definition GCodeViewer.hpp:464
Size get_canvas_size() const
Definition GLCanvas3D.cpp:5596
CollapseSide collapse_side() const
Definition GLCanvas3D.cpp:2465
GCodeViewer & get_gcode_viewer()
Definition GLCanvas3D.hpp:1007
const float get_scale() const
Definition GLCanvas3D.cpp:1811
GCodeViewer m_gcode_viewer
Definition GLCanvas3D.hpp:731
GLToolbar & collapse_toolbar() const
Definition GLCanvas3D.cpp:2460
static const float Default_Icons_Size
Definition GLGizmosManager.hpp:83
static const float Default_Icons_Size
Definition GLToolbar.hpp:270
int get_dpi_for_window(const wxWindow *window)
Definition GUI_Utils.cpp:234
@ None
Definition GLToolbar.hpp:462
@ DPI_DEFAULT
Definition GUI_Utils.hpp:92
static const float GCODE_VIEWER_SLIDER_SCALE
Definition GCodeViewer.hpp:49

References _check_and_update_toolbar_icon_scale(), CanvasPreview, collapse_side(), collapse_toolbar(), Slic3r::GUI::GLGizmosManager::Default_Icons_Size, Slic3r::GUI::GLToolbar::Default_Icons_Size, Slic3r::GUI::DPI_DEFAULT, Slic3r::GUI::GCODE_VIEWER_SLIDER_SCALE, get_canvas_size(), Slic3r::GUI::get_dpi_for_window(), get_gcode_viewer(), Slic3r::GUI::Size::get_height(), get_scale(), Slic3r::GUI::Size::get_width(), m_assemble_view_toolbar, m_canvas_type, m_gcode_viewer, m_gizmos, m_main_toolbar, m_separator_toolbar, Slic3r::GUI::None, scale(), and Slic3r::GUI::IMSlider::set_scale().

Referenced by _check_and_update_toolbar_icon_scale(), and _render_overlays().

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

◆ _current_plate_box()

BoundingBoxf3 Slic3r::GUI::GLCanvas3D::_current_plate_box ( ) const
private
9071{
9072 // Design tab: its own bed stands in for the current plate (see _render_platelist).
9073 const BuildVolume& build_volume = m_bed.build_volume();
9074 if (m_design_canvas && build_volume.valid()) {
9075 // Flat at z = 0 like the plate's own box. Merged, as PartPlate builds it: the min/max
9076 // constructor leaves a flat box undefined.
9077 const BoundingBoxf bb = build_volume.bounding_volume2d();
9078 BoundingBoxf3 box;
9079 box.merge(Vec3d(bb.min.x(), bb.min.y(), 0.));
9080 box.merge(Vec3d(bb.max.x(), bb.max.y(), 0.));
9081 return box;
9082 }
9083 PartPlate* curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
9084 return curr_plate != nullptr ? curr_plate->get_bounding_box() : BoundingBoxf3();
9085}
bool m_design_canvas
Definition GLCanvas3D.hpp:681
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68

References _current_plate_box(), Slic3r::BuildVolume::bounding_volume2d(), Slic3r::GUI::PartPlate::get_bounding_box(), m_bed, m_design_canvas, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::min, and Slic3r::BuildVolume::valid().

Referenced by _current_plate_box(), get_camera_orbit_target(), and volumes_bounding_box().

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

◆ _deactivate_arrange_menu()

bool Slic3r::GUI::GLCanvas3D::_deactivate_arrange_menu ( )
private
12757{
12758 if (m_main_toolbar.is_item_pressed("arrange")) {
12759 m_main_toolbar.force_right_action(m_main_toolbar.get_item_id("arrange"), *this);
12760 return true;
12761 }
12762
12763 return false;
12764}

References _deactivate_arrange_menu(), and m_main_toolbar.

Referenced by _deactivate_arrange_menu(), on_char(), and on_mouse().

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

◆ _deactivate_collapse_toolbar_items()

bool Slic3r::GUI::GLCanvas3D::_deactivate_collapse_toolbar_items ( )
private
12789{
12790 GLToolbar& collapse_toolbar = this->collapse_toolbar();
12791 if (collapse_toolbar.is_item_pressed("print")) {
12792 collapse_toolbar.force_left_action(collapse_toolbar.get_item_id("print"), *this);
12793 return true;
12794 }
12795
12796 return false;
12797}

References _deactivate_collapse_toolbar_items(), and collapse_toolbar().

Referenced by _deactivate_collapse_toolbar_items().

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

◆ _deactivate_layersediting_menu()

bool Slic3r::GUI::GLCanvas3D::_deactivate_layersediting_menu ( )
private
12779{
12780 if (m_main_toolbar.is_item_pressed("layersediting")) {
12781 m_main_toolbar.force_left_action(m_main_toolbar.get_item_id("layersediting"), *this);
12782 return true;
12783 }
12784
12785 return false;
12786}

References _deactivate_layersediting_menu(), and m_main_toolbar.

Referenced by _deactivate_layersediting_menu(), and on_mouse().

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

◆ _deactivate_orient_menu()

bool Slic3r::GUI::GLCanvas3D::_deactivate_orient_menu ( )
private
12768{
12769 if (m_main_toolbar.is_item_pressed("orient")) {
12770 m_main_toolbar.force_right_action(m_main_toolbar.get_item_id("orient"), *this);
12771 return true;
12772 }
12773
12774 return false;
12775}

References _deactivate_orient_menu(), and m_main_toolbar.

Referenced by _deactivate_orient_menu(), on_char(), and on_mouse().

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

◆ _get_current_partplate_print_volume()

BoundingBoxf3 Slic3r::GUI::GLCanvas3D::_get_current_partplate_print_volume ( )
private
1840{
1841 BoundingBoxf3 test_volume;
1842 if (m_process && m_config)
1843 {
1844 BoundingBoxf3 plate_bb = m_process->get_current_plate()->get_bounding_box(false);
1845 BoundingBoxf3 print_volume({ plate_bb.min(0), plate_bb.min(1), 0.0 }, { plate_bb.max(0), plate_bb.max(1), m_config->opt_float("printable_height") });
1846 // Allow the objects to protrude below the print bed
1847 print_volume.min(2) = -1e10;
1848 print_volume.min(0) -= Slic3r::BuildVolume::BedEpsilon;
1849 print_volume.min(1) -= Slic3r::BuildVolume::BedEpsilon;
1850 print_volume.max(0) += Slic3r::BuildVolume::BedEpsilon;
1851 print_volume.max(1) += Slic3r::BuildVolume::BedEpsilon;
1852 test_volume = print_volume;
1853 }
1854 else
1855 test_volume = BoundingBoxf3();
1856
1857 return test_volume;
1858}
static constexpr const double BedEpsilon
Definition BuildVolume.hpp:121

References Slic3r::BuildVolume::BedEpsilon, m_config, m_process, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, and Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min.

Referenced by _render_background().

Here is the caller graph for this function:

◆ _get_effective_fps_cap()

int Slic3r::GUI::GLCanvas3D::_get_effective_fps_cap ( ) const
private
8510{
8511 if (wxGetApp().app_config == nullptr)
8512 return 0;
8513
8514 int fps_cap = 0;
8515 try {
8516 fps_cap = std::stoi(wxGetApp().app_config->get(SETTING_OPENGL_FPS_CAP));
8517 }
8518 catch (...) {
8519 fps_cap = 0;
8520 }
8521
8522 fps_cap = std::max(0, std::min(fps_cap, 240));
8523
8524 return fps_cap;
8525}
#define SETTING_OPENGL_FPS_CAP
Definition AppConfig.hpp:36

References _get_effective_fps_cap(), and SETTING_OPENGL_FPS_CAP.

Referenced by _get_effective_fps_cap(), and on_idle().

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

◆ _get_section_view_plane()

ClippingPlane Slic3r::GUI::GLCanvas3D::_get_section_view_plane ( ) const
private
12044{
12045 const SectionView& section_view = *m_section_view;
12046 if (section_view.ratio == 0.)
12048
12049 // The owner's objects, so Preview cuts where Prepare does.
12050 const GLCanvas3D& owner = section_view.owner != nullptr ? *section_view.owner : *this;
12051 BoundingBoxf3 box = owner.volumes_bounding_box(true);
12052 if (!box.defined)
12053 box = owner.volumes_bounding_box();
12054 // G-code without objects: its toolpaths, merged by corner as a flat box is undefined.
12055 if (!box.defined && m_gcode_viewer.has_data()) {
12056 box.merge(m_gcode_viewer.get_paths_bounding_box().min);
12057 box.merge(m_gcode_viewer.get_paths_bounding_box().max);
12058 }
12059 if (!box.defined)
12061
12062 // Sweeps the bounding sphere from the camera side (0) to the far side (1), as ObjectClipper does.
12063 const double radius = box.radius();
12064 return ClippingPlane(section_view.normal, section_view.normal.dot(box.center()) + radius - 2. * radius * section_view.ratio);
12065}
static ClippingPlane ClipsNothing()
Definition MeshUtils.hpp:73
GLCanvas3D(wxGLCanvas *canvas, Bed3D &bed)
Definition GLCanvas3D.cpp:1594
Definition GLCanvas3D.hpp:711

References GLCanvas3D(), _get_section_view_plane(), Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::GUI::ClippingPlane::ClipsNothing(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::defined, m_gcode_viewer, m_section_view, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::GUI::GLCanvas3D::SectionView::normal, Slic3r::GUI::GLCanvas3D::SectionView::owner, Slic3r::BoundingBox3Base< PointType >::radius(), Slic3r::GUI::GLCanvas3D::SectionView::ratio, and volumes_bounding_box().

Referenced by _get_section_view_plane(), _get_volumes_clipping_plane(), _render_scene(), and _render_section_view_caps().

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

◆ _get_volumes_clipping_plane()

ClippingPlane Slic3r::GUI::GLCanvas3D::_get_volumes_clipping_plane ( ) const
private
12068{
12069 const std::optional<ClippingPlane> gizmo_plane = m_gizmos.get_clipping_plane();
12070 return gizmo_plane.has_value() ? *gizmo_plane : _get_section_view_plane().inverted_normal();
12071}
ClippingPlane inverted_normal() const
Definition MeshUtils.hpp:71
ClippingPlane _get_section_view_plane() const
Definition GLCanvas3D.cpp:12043

References _get_section_view_plane(), _get_volumes_clipping_plane(), and m_gizmos.

Referenced by _get_volumes_clipping_plane(), _render_objects(), and get_raycaster_clipping_plane().

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

◆ _hides_inactive_plates()

bool Slic3r::GUI::GLCanvas3D::_hides_inactive_plates ( ) const
private
8997{
8998 return m_canvas_type == ECanvasType::CanvasView3D && !m_design_canvas && wxGetApp().focus_mode();
8999}

References _hides_inactive_plates(), CanvasView3D, m_canvas_type, and m_design_canvas.

Referenced by _hides_inactive_plates(), _render_bed(), _render_plate_switcher(), _render_platelist(), _update_inactive_plates_visibility(), and zoom_to_plate().

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

◆ _init_assemble_view_toolbar()

bool Slic3r::GUI::GLCanvas3D::_init_assemble_view_toolbar ( )
private
7723{
7724 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": enter, m_assemble_view_toolbar.is_enabled=" << m_assemble_view_toolbar.is_enabled() << "\n";
7725 if (!m_assemble_view_toolbar.is_enabled())
7726 return true;
7727
7728 BackgroundTexture::Metadata background_data;
7729 background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png";
7730 background_data.left = 16;
7731 background_data.top = 16;
7732 background_data.right = 16;
7733 background_data.bottom = 16;
7734
7735 if (!m_assemble_view_toolbar.init(background_data))
7736 {
7737 // unable to init the toolbar texture, disable it
7738 m_assemble_view_toolbar.set_enabled(false);
7739 return true;
7740 }
7741
7743 //BBS: assemble toolbar is at the top and right, we don't need the rounded-corner effect at the left side and the top side
7744 m_assemble_view_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left);
7745 m_assemble_view_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top);
7746 m_assemble_view_toolbar.set_border(4.0f);
7747 m_assemble_view_toolbar.set_separator_size(10);
7748 m_assemble_view_toolbar.set_gap_size(4);
7749
7750 m_assemble_view_toolbar.del_all_item();
7751
7752 GLToolbarItem::Data item;
7753 item.name = "assembly_view";
7754 item.icon_filename = m_is_dark ? "toolbar_assemble_dark.svg" : "toolbar_assemble.svg";
7755 item.tooltip = _utf8(L("Assembly View"));
7756 item.sprite_id = 1;
7757 item.left.toggable = false;
7758 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); };
7759 item.left.render_callback = GLToolbarItem::Default_Render_Callback;
7760 item.visible = true;
7761 item.visibility_callback = []()->bool { return true; };
7762 item.enabling_callback = []()->bool {
7763 return wxGetApp().plater()->has_assmeble_view();
7764 };
7765 if (!m_assemble_view_toolbar.add_item(item))
7766 return false;
7767
7768 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": Finished Successfully\n";
7769 return true;
7770}
#define L(s)
Definition ExtrusionEntity.cpp:25
bool m_is_dark
Definition GLCanvas3D.hpp:634
static const RenderCallback Default_Render_Callback
Definition GLToolbar.hpp:171
#define _utf8(s)
Definition I18N.hpp:10
@ Horizontal
Definition GLToolbar.hpp:283
@ VO_Top
Definition GLToolbar.hpp:298
@ HO_Left
Definition GLToolbar.hpp:290

References _utf8, Slic3r::GUI::GLToolbarItem::Data::Option::action_callback, Slic3r::GUI::BackgroundTexture::Metadata::bottom, Slic3r::GUI::GLToolbarItem::Default_Render_Callback, Slic3r::GUI::GLToolbarItem::Data::enabling_callback, Slic3r::GUI::BackgroundTexture::Metadata::filename, Slic3r::GUI::GLToolbar::Layout::HO_Left, Slic3r::GUI::GLToolbar::Layout::Horizontal, Slic3r::GUI::GLToolbarItem::Data::icon_filename, L, Slic3r::GUI::BackgroundTexture::Metadata::left, Slic3r::GUI::GLToolbarItem::Data::left, m_assemble_view_toolbar, m_canvas, m_is_dark, Slic3r::GUI::GLToolbarItem::Data::name, Slic3r::GUI::GLToolbarItem::Data::Option::render_callback, Slic3r::GUI::BackgroundTexture::Metadata::right, Slic3r::GUI::GLToolbarItem::Data::sprite_id, Slic3r::GUI::GLToolbarItem::Data::Option::toggable, Slic3r::GUI::GLToolbarItem::Data::tooltip, Slic3r::GUI::BackgroundTexture::Metadata::top, Slic3r::GUI::GLToolbarItem::Data::visibility_callback, Slic3r::GUI::GLToolbarItem::Data::visible, and Slic3r::GUI::GLToolbar::Layout::VO_Top.

Referenced by _init_toolbars().

Here is the caller graph for this function:

◆ _init_collapse_toolbar()

bool Slic3r::GUI::GLCanvas3D::_init_collapse_toolbar ( )
private
7830{
7831 if (m_collapse_toolbar == nullptr)
7832 return wxGetApp().plater()->init_collapse_toolbar();
7833
7834 // Its owner laid it out; the background needs the GL context.
7835 BackgroundTexture::Metadata background_data;
7836 background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png";
7837 background_data.left = 16;
7838 background_data.top = 16;
7839 background_data.right = 16;
7840 background_data.bottom = 16;
7841 return m_collapse_toolbar->init(background_data);
7842}
GLToolbar * m_collapse_toolbar
Definition GLCanvas3D.hpp:674

References Slic3r::GUI::BackgroundTexture::Metadata::bottom, Slic3r::GUI::BackgroundTexture::Metadata::filename, Slic3r::GUI::BackgroundTexture::Metadata::left, m_collapse_toolbar, m_is_dark, Slic3r::GUI::BackgroundTexture::Metadata::right, and Slic3r::GUI::BackgroundTexture::Metadata::top.

Referenced by _init_toolbars().

Here is the caller graph for this function:

◆ _init_main_toolbar()

bool Slic3r::GUI::GLCanvas3D::_init_main_toolbar ( )
private
7484{
7485 if (!m_main_toolbar.is_enabled())
7486 return true;
7487
7488 BackgroundTexture::Metadata background_data;
7489 background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png";
7490 background_data.left = 16;
7491 background_data.top = 16;
7492 background_data.right = 16;
7493 background_data.bottom = 16;
7494
7495 if (!m_main_toolbar.init(background_data))
7496 {
7497 // unable to init the toolbar texture, disable it
7498 m_main_toolbar.set_enabled(false);
7499 return true;
7500 }
7501 // init arrow
7502 if (!m_main_toolbar.init_arrow("toolbar_arrow.svg"))
7503 BOOST_LOG_TRIVIAL(error) << "Main toolbar failed to load arrow texture.";
7504
7505 // m_gizmos is created at constructor, thus we can init arrow here.
7506 if (!m_gizmos.init_arrow("toolbar_arrow.svg"))
7507 BOOST_LOG_TRIVIAL(error) << "Gizmos manager failed to load arrow texture.";
7508
7510 //BBS: main toolbar is at the top and left, we don't need the rounded-corner effect at the right side and the top side
7511 m_main_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Right);
7512 m_main_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top);
7513 m_main_toolbar.set_border(4.0f);
7514 m_main_toolbar.set_separator_size(4);
7515 m_main_toolbar.set_gap_size(4);
7516
7517 m_main_toolbar.del_all_item();
7518
7519 GLToolbarItem::Data item;
7520
7521 item.name = "add";
7522 item.icon_filename = m_is_dark ? "toolbar_open_dark.svg" : "toolbar_open.svg";
7523 item.sprite_id = 0;
7524 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
7525 item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_model(); };
7526 if (!m_main_toolbar.add_item(item))
7527 return false;
7528
7529 item.name = "addplate";
7530 item.icon_filename = m_is_dark ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg";
7531 item.tooltip = _utf8(L("Add plate"));
7532 item.sprite_id++;
7533 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD_PLATE)); };
7534 item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_plate(); };
7535 if (!m_main_toolbar.add_item(item))
7536 return false;
7537
7538 item.name = "orient";
7539 item.icon_filename = m_is_dark ? "toolbar_orient_dark.svg" : "toolbar_orient.svg";
7540 item.sprite_id++;
7541 item.left.render_callback = nullptr;
7542 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
7543 item.left.toggable = false; // allow right mouse click
7544 //BBS: GUI refactor: adjust the main toolbar position
7545 item.left.action_callback = [this]() {
7546 if (m_canvas != nullptr)
7547 {
7548 wxGetApp().plater()->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
7549 wxGetApp().plater()->orient();
7550 //BBS do not show orient menu
7551 //_render_orient_menu(left, right, bottom, top);
7552 NetworkAgent* agent = GUI::wxGetApp().getAgent();
7553 if (agent) agent->track_update_property("auto_orient", std::to_string(++auto_orient_count));
7554 }
7555 };
7556 if (!m_main_toolbar.add_item(item))
7557 return false;
7558
7559 item.name = "arrange";
7560 item.icon_filename = m_is_dark ? "toolbar_arrange_dark.svg" : "toolbar_arrange.svg";
7561 item.sprite_id++;
7562 item.left.action_callback = []() {};
7563 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
7564 item.left.toggable = true;
7565 //BBS: GUI refactor: adjust the main toolbar position
7566 item.left.render_callback = [this](float left, float right, float bottom, float top) {
7567 if (m_canvas != nullptr)
7568 {
7569 _render_arrange_menu(left, right, bottom, top);
7570 //_render_arrange_menu(0.5f * (left + right));
7571 }
7572 };
7573 if (!m_main_toolbar.add_item(item))
7574 return false;
7575
7576 item.right.toggable = false;
7577 item.right.render_callback = GLToolbarItem::Default_Render_Callback;
7578
7579 if (!m_main_toolbar.add_separator())
7580 return false;
7581
7582 item.name = "more";
7583 item.icon_filename = m_is_dark ? "instance_add_dark.svg" : "instance_add.svg";
7584 item.sprite_id++;
7585 item.left.render_callback = nullptr;
7586 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_MORE)); };
7587 item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
7588 item.left.toggable = false;
7589 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_increase_instances(); };
7590 if (!m_main_toolbar.add_item(item))
7591 return false;
7592
7593 item.name = "fewer";
7594 item.icon_filename = m_is_dark ? "instance_remove_dark.svg" : "instance_remove.svg";
7595 item.sprite_id++;
7596 item.left.render_callback = nullptr;
7597 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_FEWER)); };
7598 item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
7599 item.left.toggable = false;
7600 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_decrease_instances(); };
7601 if (!m_main_toolbar.add_item(item))
7602 return false;
7603
7604 item.name = "splitobjects";
7605 item.icon_filename = m_is_dark ? "split_objects_dark.svg" : "split_objects.svg";
7606 item.tooltip = _utf8(L("Split to objects"));
7607 item.sprite_id++;
7608 item.left.render_callback = nullptr;
7609 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
7610 item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
7611 item.left.toggable = false;
7612 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
7613 if (!m_main_toolbar.add_item(item))
7614 return false;
7615
7616 item.name = "splitvolumes";
7617 item.icon_filename = m_is_dark ? "split_parts_dark.svg" : "split_parts.svg";
7618 item.tooltip = _utf8(L("Split to parts"));
7619 item.sprite_id++;
7620 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_VOLUMES)); };
7621 item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
7622 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_volumes(); };
7623 if (!m_main_toolbar.add_item(item))
7624 return false;
7625
7626 item.name = "layersediting";
7627 item.icon_filename = m_is_dark ? "toolbar_variable_layer_height_dark.svg" : "toolbar_variable_layer_height.svg";
7628 item.tooltip = _utf8(L("Variable layer height"));
7629 item.sprite_id++;
7630 item.left.toggable = true; // ORCA Closes popup if other toolbar icon clicked and it allows closing popup when clicked its button
7631 item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_LAYERSEDITING)); };
7632 item.visibility_callback = [this]()->bool {
7633 bool res = current_printer_technology() == ptFFF;
7634 // turns off if changing printer technology
7635 if (!res && m_main_toolbar.is_item_visible("layersediting") && m_main_toolbar.is_item_pressed("layersediting"))
7637
7638 return res;
7639 };
7640 item.enabling_callback = []()->bool { return wxGetApp().plater()->can_layers_editing(); };
7641 if (!m_main_toolbar.add_item(item))
7642 return false;
7643
7645 return true;
7646}
void update_shortcut_tooltips()
Definition GLCanvas3D.cpp:7648
void _render_arrange_menu(float left, float right, float bottom, float top)
Definition GLCanvas3D.cpp:6646
int get_main_toolbar_item_id(const std::string &name) const
Definition GLCanvas3D.hpp:1393
PrinterTechnology current_printer_technology() const
Definition GLCanvas3D.cpp:1590
int auto_orient_count
Definition GLCanvas3D.hpp:829
void force_main_toolbar_left_action(int item_id)
Definition GLCanvas3D.hpp:1394
static const VisibilityCallback Default_Visibility_Callback
Definition GLToolbar.hpp:169
@ PREPARE_STATE_DEFAULT
Definition Job.hpp:23
@ ptFFF
Definition Config.hpp:231
@ right
Definition MarchingSquares.hpp:190
@ left
Definition MarchingSquares.hpp:188
@ HO_Right
Definition GLToolbar.hpp:292

References _render_arrange_menu(), _utf8, Slic3r::GUI::GLToolbarItem::Data::Option::action_callback, auto_orient_count, Slic3r::GUI::BackgroundTexture::Metadata::bottom, current_printer_technology(), Slic3r::GUI::GLToolbarItem::Default_Render_Callback, Slic3r::GUI::GLToolbarItem::Default_Visibility_Callback, Slic3r::GUI::GLToolbarItem::Data::enabling_callback, Slic3r::GUI::BackgroundTexture::Metadata::filename, force_main_toolbar_left_action(), get_main_toolbar_item_id(), Slic3r::GUI::GLToolbar::Layout::HO_Right, Slic3r::GUI::GLToolbar::Layout::Horizontal, Slic3r::GUI::GLToolbarItem::Data::icon_filename, L, Slic3r::GUI::BackgroundTexture::Metadata::left, Slic3r::GUI::GLToolbarItem::Data::left, m_canvas, m_gizmos, m_is_dark, m_main_toolbar, Slic3r::GUI::GLToolbarItem::Data::name, Slic3r::GUI::Job::PREPARE_STATE_DEFAULT, Slic3r::ptFFF, Slic3r::GUI::GLToolbarItem::Data::Option::render_callback, Slic3r::GUI::BackgroundTexture::Metadata::right, Slic3r::GUI::GLToolbarItem::Data::right, Slic3r::GUI::GLToolbarItem::Data::sprite_id, Slic3r::GUI::GLToolbarItem::Data::Option::toggable, Slic3r::GUI::GLToolbarItem::Data::tooltip, Slic3r::GUI::BackgroundTexture::Metadata::top, Slic3r::NetworkAgent::track_update_property(), update_shortcut_tooltips(), Slic3r::GUI::GLToolbarItem::Data::visibility_callback, and Slic3r::GUI::GLToolbar::Layout::VO_Top.

Referenced by _init_toolbars().

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

◆ _init_return_toolbar()

bool Slic3r::GUI::GLCanvas3D::_init_return_toolbar ( )
private
7773{
7774 if (!m_return_toolbar.is_enabled())
7775 return true;
7776
7777 return m_return_toolbar.init();
7778}

References m_return_toolbar.

Referenced by _init_toolbars().

Here is the caller graph for this function:

◆ _init_select_plate_toolbar()

bool Slic3r::GUI::GLCanvas3D::_init_select_plate_toolbar ( )
private
7660{
7661 std::string path = resources_dir() + "/images/";
7662 IMToolbarItem* item = new IMToolbarItem();
7663 // ORCA add dark mode support and load images with 2x resolution to prevent blurry image on hi-dpi screens
7664 std::string ext = m_is_dark ? "_dark.svg" : ".svg";
7665 bool result = item->image_stats.load_from_svg_file( path + "im_all_plates_stats" + ext, false, false, false, 200);
7666 result = result && item->image_idle.load_from_svg_file( path + "im_all_plates_idle" + ext, false, false, false, 200);
7667 result = result && item->image_slicing.load_from_svg_file( path + "im_all_plates_slicing" + ext, false, false, false, 200);
7668 result = result && item->image_failed.load_from_svg_file( path + "im_all_plates_failed" + ext, false, false, false, 200);
7669 m_sel_plate_toolbar.m_all_plates_stats_item = item;
7670
7671 return result;
7672}
const std::string & resources_dir()
Definition utils.cpp:296

References Slic3r::GUI::IMToolbarItem::image_failed, Slic3r::GUI::IMToolbarItem::image_idle, Slic3r::GUI::IMToolbarItem::image_slicing, Slic3r::GUI::IMToolbarItem::image_stats, Slic3r::GUI::GLTexture::load_from_svg_file(), m_is_dark, m_sel_plate_toolbar, and Slic3r::resources_dir().

Referenced by _init_toolbars(), and on_change_color_mode().

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

◆ _init_separator_toolbar()

bool Slic3r::GUI::GLCanvas3D::_init_separator_toolbar ( )
private
7781{
7782 if (!m_separator_toolbar.is_enabled())
7783 return true;
7784
7785 BackgroundTexture::Metadata background_data;
7786 background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png";
7787 background_data.left = 0;
7788 background_data.top = 0;
7789 background_data.right = 0;
7790 background_data.bottom = 0;
7791
7792 if (!m_separator_toolbar.init(background_data))
7793 {
7794 // unable to init the toolbar texture, disable it
7795 m_separator_toolbar.set_enabled(false);
7796 return true;
7797 }
7798
7800 //BBS: assemble toolbar is at the top and right, we don't need the rounded-corner effect at the left side and the top side
7801 m_separator_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Left);
7802 m_separator_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top);
7803 m_separator_toolbar.set_border(4.0f);
7804
7805 m_separator_toolbar.del_all_item();
7806
7807 GLToolbarItem::Data sperate_item;
7808 sperate_item.name = "start_seperator";
7809 sperate_item.icon_filename = "seperator.svg";
7810 sperate_item.sprite_id = 0;
7811 sperate_item.left.action_callback = []() {};
7812 sperate_item.visibility_callback = []()->bool { return true; };
7813 sperate_item.enabling_callback = []()->bool { return false; };
7814 if (!m_separator_toolbar.add_item(sperate_item))
7815 return false;
7816
7817 return true;
7818}

References Slic3r::GUI::GLToolbarItem::Data::Option::action_callback, Slic3r::GUI::BackgroundTexture::Metadata::bottom, Slic3r::GUI::GLToolbarItem::Data::enabling_callback, Slic3r::GUI::BackgroundTexture::Metadata::filename, Slic3r::GUI::GLToolbar::Layout::HO_Left, Slic3r::GUI::GLToolbar::Layout::Horizontal, Slic3r::GUI::GLToolbarItem::Data::icon_filename, Slic3r::GUI::BackgroundTexture::Metadata::left, Slic3r::GUI::GLToolbarItem::Data::left, m_is_dark, m_separator_toolbar, Slic3r::GUI::GLToolbarItem::Data::name, Slic3r::GUI::BackgroundTexture::Metadata::right, Slic3r::GUI::GLToolbarItem::Data::sprite_id, Slic3r::GUI::BackgroundTexture::Metadata::top, Slic3r::GUI::GLToolbarItem::Data::visibility_callback, and Slic3r::GUI::GLToolbar::Layout::VO_Top.

Referenced by _init_toolbars().

Here is the caller graph for this function:

◆ _init_toolbars()

bool Slic3r::GUI::GLCanvas3D::_init_toolbars ( )
private
7454{
7455 if (!_init_main_toolbar())
7456 return false;
7457
7458 //BBS: GUI refractor
7460 return false;
7461
7462 if (!_init_return_toolbar())
7463 return false;
7464
7466 return false;
7467
7469 return false;
7470
7471#if 0
7472 if (!_init_view_toolbar())
7473 return false;
7474#endif
7475
7477 return false;
7478
7479 return true;
7480}
bool _init_separator_toolbar()
Definition GLCanvas3D.cpp:7780
bool _init_collapse_toolbar()
Definition GLCanvas3D.cpp:7829
bool _init_main_toolbar()
Definition GLCanvas3D.cpp:7483
bool _init_return_toolbar()
Definition GLCanvas3D.cpp:7772
bool _init_assemble_view_toolbar()
Definition GLCanvas3D.cpp:7722
bool _init_select_plate_toolbar()
Definition GLCanvas3D.cpp:7659

References _init_assemble_view_toolbar(), _init_collapse_toolbar(), _init_main_toolbar(), _init_return_toolbar(), _init_select_plate_toolbar(), and _init_separator_toolbar().

Referenced by init().

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

◆ _is_any_volume_outside()

bool Slic3r::GUI::GLCanvas3D::_is_any_volume_outside ( ) const
private
12663{
12664 for (const GLVolume* volume : m_volumes.volumes) {
12665 if (volume != nullptr && volume->is_outside)
12666 return true;
12667 }
12668
12669 return false;
12670}

References _is_any_volume_outside(), and m_volumes.

Referenced by _is_any_volume_outside(), _render_background(), and _set_warning_notification_if_needed().

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

◆ _is_below_plate_view_active()

bool Slic3r::GUI::GLCanvas3D::_is_below_plate_view_active ( ) const
private
8919{
8920 return dynamic_cast<const GLGizmoPainterBase*>(m_gizmos.get_current()) != nullptr && m_gizmos.is_hiding_instances();
8921}

References _is_below_plate_view_active(), and m_gizmos.

Referenced by _is_below_plate_view_active(), _render_below_plate_volumes(), _render_scene(), and is_bed_visible().

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

◆ _is_fps_overlay_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_fps_overlay_enabled ( ) const
private
8528{
8529 return !m_benchmarking && wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_SHOW_FPS_OVERLAY);
8530}
#define SETTING_OPENGL_SHOW_FPS_OVERLAY
Definition AppConfig.hpp:39
bool m_benchmarking
Definition GLCanvas3D.hpp:806

References _is_fps_overlay_enabled(), m_benchmarking, and SETTING_OPENGL_SHOW_FPS_OVERLAY.

Referenced by _is_fps_overlay_enabled(), _render_fps_overlay(), and _render_frame().

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

◆ _is_frame_skipping_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_frame_skipping_enabled ( ) const
private
8602{
8603 return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_SKIP_IDENTICAL_FRAMES);
8604}
#define SETTING_OPENGL_SKIP_IDENTICAL_FRAMES
Definition AppConfig.hpp:38

References _is_frame_skipping_enabled(), and SETTING_OPENGL_SKIP_IDENTICAL_FRAMES.

Referenced by _is_frame_skipping_enabled(), and _render_frame().

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

◆ _is_fxaa_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_fxaa_enabled ( ) const
private
8488{
8489 return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_FXAA_ENABLED);
8490}
#define SETTING_OPENGL_FXAA_ENABLED
Definition AppConfig.hpp:35

References _is_fxaa_enabled(), and SETTING_OPENGL_FXAA_ENABLED.

Referenced by _is_fxaa_enabled(), and _render_scene().

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

◆ _is_realistic_view_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_realistic_view_enabled ( ) const
private
8493{
8494 const AppConfig* cfg = wxGetApp().app_config;
8495 if (cfg == nullptr || !cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE))
8496 return false;
8497 // Prepare and Assemble follow the umbrella toggle alone; Preview needs its own opt-in.
8499}
#define SETTING_OPENGL_REALISTIC_PREVIEW
Definition AppConfig.hpp:49
#define SETTING_OPENGL_REALISTIC_MODE
Definition AppConfig.hpp:41

References _is_realistic_view_enabled(), CanvasPreview, Slic3r::AppConfig::get_bool(), m_canvas_type, SETTING_OPENGL_REALISTIC_MODE, and SETTING_OPENGL_REALISTIC_PREVIEW.

Referenced by _is_realistic_view_enabled(), _is_ssao_enabled(), _render_gcode(), _render_objects(), _render_shadows(), and _static_light_dir_eye().

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

◆ _is_render_timings_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_render_timings_enabled ( ) const
private
8572{
8573 return !m_benchmarking && wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_SHOW_RENDER_TIMINGS);
8574}
#define SETTING_OPENGL_SHOW_RENDER_TIMINGS
Definition AppConfig.hpp:40

References _is_render_timings_enabled(), m_benchmarking, and SETTING_OPENGL_SHOW_RENDER_TIMINGS.

Referenced by _is_render_timings_enabled(), _render_fps_overlay(), and _render_frame().

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

◆ _is_scene_cache_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_scene_cache_enabled ( ) const
private
8577{
8578 return wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_SCENE_CACHE);
8579}
#define SETTING_OPENGL_SCENE_CACHE
Definition AppConfig.hpp:37

References _is_scene_cache_enabled(), and SETTING_OPENGL_SCENE_CACHE.

Referenced by _capture_scene_cache(), _is_scene_cache_enabled(), and _is_scene_cacheable().

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

◆ _is_scene_cacheable()

bool Slic3r::GUI::GLCanvas3D::_is_scene_cacheable ( ) const
private
8582{
8584 return false;
8585
8586#ifdef SLIC3R_CAD
8587 // The Design tab draws its sketch overlay, ImGui included, inside the scene.
8588 if (m_design_sketch_tool != nullptr && m_design_sketch_tool->has_display())
8589 return false;
8590#endif
8591
8592 // The scene follows the cursor during a drag, under a gizmo that draws at the cursor, and while
8593 // the cursor is on the layer height bar, where the object shader draws a band at its height.
8594 const GLGizmoBase* gizmo = m_gizmos.get_current();
8595 const bool cursor_on_layers_bar = is_layers_editing_enabled() &&
8596 m_layers_editing.bar_rect_contains(*this, (float)m_mouse.position.x(), (float)m_mouse.position.y());
8597 return !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging() &&
8598 (gizmo == nullptr || !gizmo->render_follows_cursor()) && !cursor_on_layers_bar;
8599}
GLSelectionRectangle m_rectangle_selection
Definition GLCanvas3D.hpp:779
LayersEditing m_layers_editing
Definition GLCanvas3D.hpp:654
Mouse m_mouse
Definition GLCanvas3D.hpp:655
bool is_layers_editing_enabled() const
Definition GLCanvas3D.hpp:1076

References _is_scene_cache_enabled(), _is_scene_cacheable(), is_layers_editing_enabled(), m_gizmos, m_layers_editing, m_mouse, m_rectangle_selection, and Slic3r::GUI::GLGizmoBase::render_follows_cursor().

Referenced by _can_reuse_cached_scene(), _capture_scene_cache(), and _is_scene_cacheable().

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

◆ _is_shown_on_screen()

bool Slic3r::GUI::GLCanvas3D::_is_shown_on_screen ( ) const
private
6544{
6545 return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
6546}

References m_canvas.

Referenced by _refresh_if_shown_on_screen(), _render_frame(), and on_idle().

Here is the caller graph for this function:

◆ _is_ssao_enabled()

bool Slic3r::GUI::GLCanvas3D::_is_ssao_enabled ( ) const
private
8502{
8503 if (wxGetApp().app_config == nullptr)
8504 return false;
8505 return _is_realistic_view_enabled() &&
8506 wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SSAO);
8507}
#define SETTING_OPENGL_PHONG_SSAO
Definition AppConfig.hpp:47
bool _is_realistic_view_enabled() const
Definition GLCanvas3D.cpp:8492

References _is_realistic_view_enabled(), _is_ssao_enabled(), and SETTING_OPENGL_PHONG_SSAO.

Referenced by _is_ssao_enabled(), and _render_scene().

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

◆ _is_xray_view_active()

bool Slic3r::GUI::GLCanvas3D::_is_xray_view_active ( ) const
private
9791{
9792 if (m_canvas_type == ECanvasType::CanvasPreview || !wxGetApp().plater()->is_show_xray())
9793 return false;
9794
9795 // A painting gizmo and the layer height editor draw the object through their own shaders, and
9796 // would lose what they draw if X-Ray took the pass over.
9797 if (dynamic_cast<const GLGizmoPainterBase*>(m_gizmos.get_current()) != nullptr)
9798 return false;
9799 return !(m_picking_enabled && m_layers_editing.is_enabled() && m_layers_editing.last_object_id != -1 &&
9800 m_layers_editing.object_max_z() > 0.0f);
9801}
static Plater * plater()
Definition GUI_Factories.cpp:400

References _is_xray_view_active(), CanvasPreview, m_canvas_type, m_gizmos, m_layers_editing, m_picking_enabled, and Slic3r::GUI::plater().

Referenced by _is_xray_view_active(), and _render_objects().

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

◆ _load_sla_shells()

void Slic3r::GUI::GLCanvas3D::_load_sla_shells ( )
private
12203{
12204 const SLAPrint* print = this->sla_print();
12205 if (print->objects().empty())
12206 // nothing to render, return
12207 return;
12208
12209 auto add_volume = [this](const SLAPrintObject &object, int volume_id, const SLAPrintObject::Instance& instance,
12210 const TriangleMesh& mesh, const ColorRGBA& color, bool outside_printer_detection_enabled) {
12211 m_volumes.volumes.emplace_back(new GLVolume(color));
12212 GLVolume& v = *m_volumes.volumes.back();
12213 v.model.init_from(mesh);
12214 v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
12215 v.composite_id.volume_id = volume_id;
12216 v.set_instance_offset(unscale(instance.shift.x(), instance.shift.y(), 0.0));
12217 v.set_instance_rotation({ 0.0, 0.0, (double)instance.rotation });
12218 v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.);
12219 v.set_convex_hull(mesh.convex_hull_3d());
12220 };
12221
12222 // adds objects' volumes
12223 for (const SLAPrintObject* obj : print->objects())
12224 if (obj->is_step_done(slaposSliceSupports)) {
12225 unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
12226 for (const SLAPrintObject::Instance& instance : obj->instances()) {
12227 add_volume(*obj, 0, instance, obj->get_mesh_to_print(), GLVolume::MODEL_COLOR[0], true);
12228 // Set the extruder_id and volume_id to achieve the same color as in the 3D scene when
12229 // through the update_volumes_colors_by_extruder() call.
12230 m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id();
12231 if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree))
12232 add_volume(*obj, -int(slaposSupportTree), instance, obj->support_mesh(), GLVolume::SLA_SUPPORT_COLOR, true);
12233 if (obj->is_step_done(slaposPad) && obj->has_mesh(slaposPad))
12234 add_volume(*obj, -int(slaposPad), instance, obj->pad_mesh(), GLVolume::SLA_PAD_COLOR, false);
12235 }
12236 double shift_z = obj->get_current_elevation();
12237 for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
12238 // apply shift z
12239 m_volumes.volumes[i]->set_sla_shift_z(shift_z);
12240 }
12241 }
12242
12244}
static ColorRGBA SLA_PAD_COLOR
Definition 3DScene.hpp:96
static ColorRGBA SLA_SUPPORT_COLOR
Definition 3DScene.hpp:95
static std::array< ColorRGBA, 5 > MODEL_COLOR
Definition 3DScene.hpp:99
const SLAPrint * sla_print() const
Definition GLCanvas3D.cpp:12820
void update_volumes_colors_by_extruder()
Definition GLCanvas3D.cpp:2410
static bool is_left_handed(const Transform3d::ConstLinearPart &m)
Definition Selection.cpp:2998
@ slaposPad
Definition SLAPrint.hpp:48
@ slaposSupportTree
Definition SLAPrint.hpp:47
@ slaposSliceSupports
Definition SLAPrint.hpp:49
T unscale(Q v)
Definition libslic3r.h:138
@ X
Definition libslic3r.h:141

References _load_sla_shells(), Slic3r::GLVolume::composite_id, Slic3r::GUI::GLModel::init_from(), Slic3r::GUI::is_left_handed(), m_volumes, Slic3r::GLVolume::model, Slic3r::GLVolume::MODEL_COLOR, Slic3r::SLAPrint::objects(), Slic3r::GLVolume::set_convex_hull(), Slic3r::GLVolume::set_instance_mirror(), Slic3r::GLVolume::set_instance_offset(), Slic3r::GLVolume::set_instance_rotation(), Slic3r::GLVolume::SLA_PAD_COLOR, sla_print(), Slic3r::GLVolume::SLA_SUPPORT_COLOR, Slic3r::slaposPad, Slic3r::slaposSliceSupports, Slic3r::slaposSupportTree, Slic3r::unscale(), update_volumes_colors_by_extruder(), Slic3r::GLVolume::CompositeID::volume_id, and Slic3r::X.

Referenced by _load_sla_shells(), and load_sla_preview().

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

◆ _max_bounding_box()

BoundingBoxf3 Slic3r::GUI::GLCanvas3D::_max_bounding_box ( bool include_gizmos,
bool include_bed_model,
bool include_plates ) const
private
7900{
7901 BoundingBoxf3 bb = volumes_bounding_box();
7902
7903 // The following is a workaround for gizmos not being taken in account when calculating the tight camera frustrum
7904 // A better solution would ask the gizmo manager for the bounding box of the current active gizmo, if any
7905 if (include_gizmos && m_gizmos.is_running())
7906 {
7907 BoundingBoxf3 sel_bb = m_selection.get_bounding_box();
7908 Vec3d sel_bb_center = sel_bb.center();
7909 Vec3d extend_by = sel_bb.max_size() * Vec3d::Ones();
7910 bb.merge(BoundingBoxf3(sel_bb_center - extend_by, sel_bb_center + extend_by));
7911 }
7912
7913 bb.merge(include_bed_model ? m_bed.extended_bounding_box() : m_bed.build_volume().bounding_volume());
7914 if (include_plates) {
7915 bb.merge(wxGetApp().plater()->get_partplate_list().get_bounding_box());
7916 }
7917
7918 if (!m_main_toolbar.is_enabled()) {
7919 const BoundingBoxf3& toolpath_bb = m_gcode_viewer.get_max_bounding_box();
7920 if (toolpath_bb.max_size() > 0.f)
7921 bb.merge(toolpath_bb);
7922 else
7923 bb.merge(m_gcode_viewer.get_shell_bounding_box());
7924 }
7925
7927 float height_to_lid, height_to_rod;
7928 wxGetApp().plater()->get_partplate_list().get_height_limits(height_to_lid, height_to_rod);
7929 bb.max.z() = std::max(bb.max.z(), (double)height_to_lid);
7930 }
7931
7932 return bb;
7933}
BoundingBoxf3 volumes_bounding_box(bool current_plate_only=false) const
Definition GLCanvas3D.cpp:2209
const Print * fff_print() const
Definition GLCanvas3D.cpp:12815
zaa_minimize_perimeter_height print_sequence((ConfigOptionEnum< PrintOrder >, print_order))((ConfigOptionInts
@ ByObject
Definition PrintConfig.hpp:312

References Slic3r::ByObject, CanvasView3D, Slic3r::BoundingBox3Base< PointType >::center(), fff_print(), m_bed, m_canvas_type, m_gcode_viewer, m_gizmos, m_main_toolbar, m_selection, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBox3Base< PointType >::max_size(), Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::GUI::plater(), Slic3r::print_sequence(), and volumes_bounding_box().

Referenced by _render_frame().

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

◆ _mouse_to_3d()

Vec3d Slic3r::GUI::GLCanvas3D::_mouse_to_3d ( const Point & mouse_pos,
float * z = nullptr )
12021{
12022 if (m_canvas == nullptr)
12023 return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX);
12024
12025 if (z == nullptr) {
12026 const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(mouse_pos.cast<double>(), wxGetApp().plater()->get_camera(), nullptr);
12027 return hit.is_valid() ? hit.position.cast<double>() : _mouse_to_bed_3d(mouse_pos);
12028 }
12029 else {
12030 const Camera& camera = wxGetApp().plater()->get_camera();
12031 const Vec4i32 viewport(camera.get_viewport().data());
12032 Vec3d out;
12033 igl::unproject(Vec3d(mouse_pos.x(), viewport[3] - mouse_pos.y(), *z), camera.get_view_matrix().matrix(), camera.get_projection_matrix().matrix(), viewport, out);
12034 return out;
12035 }
12036}
SceneRaycaster m_scene_raycaster
Definition GLCanvas3D.hpp:637
Camera & get_camera()
Definition GLCanvas3D.cpp:2194
Vec3d _mouse_to_bed_3d(const Point &mouse_pos)
Definition GLCanvas3D.cpp:12038
@ Camera
Definition Shortcuts.hpp:72
Eigen::Matrix< int32_t, 4, 1, Eigen::DontAlign > Vec4i32
Definition Point.hpp:61

References _mouse_to_3d(), _mouse_to_bed_3d(), camera, get_camera(), Slic3r::GUI::SceneRaycaster::HitResult::is_valid(), m_canvas, m_scene_raycaster, Slic3r::GUI::plater(), and Slic3r::GUI::SceneRaycaster::HitResult::position.

Referenced by _mouse_to_3d(), mouse_ray(), on_mouse(), and on_mouse_wheel().

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

◆ _mouse_to_bed_3d()

Vec3d Slic3r::GUI::GLCanvas3D::_mouse_to_bed_3d ( const Point & mouse_pos)
private
12039{
12040 return mouse_ray(mouse_pos).intersect_plane(0.0);
12041}
Linef3 mouse_ray(const Point &mouse_pos)
Definition GLCanvas3D.cpp:6180
Vec3d intersect_plane(double z) const
Definition Line.cpp:133

References _mouse_to_bed_3d(), and mouse_ray().

Referenced by _mouse_to_3d(), and _mouse_to_bed_3d().

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

◆ _on_section_view_changed()

void Slic3r::GUI::GLCanvas3D::_on_section_view_changed ( )
private
2016{
2017 m_gizmos.update_section_view();
2018 // Set from the overlay, after this frame's scene was drawn.
2019 set_as_dirty();
2021}
void request_extra_frame()
Definition GLCanvas3D.hpp:1385
void set_as_dirty()
Definition GLCanvas3D.hpp:984

References m_gizmos, request_extra_frame(), and set_as_dirty().

Referenced by align_section_view_to_camera(), and set_section_view_ratio().

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

◆ _overlay_signature()

size_t Slic3r::GUI::GLCanvas3D::_overlay_signature ( const ImDrawData * draw_data) const
private
10160{
10161 // The recorded ImGui geometry plus the state of the toolbars and the gizmo bar, which draw
10162 // outside ImGui.
10163 size_t hash = ImGuiWrapper::draw_data_signature(draw_data);
10164 for (size_t state_hash : { m_main_toolbar.get_state_hash(), m_separator_toolbar.get_state_hash(),
10165 m_assemble_view_toolbar.get_state_hash(),
10167 m_gizmos.get_overlay_state_hash() })
10168 boost::hash_combine(hash, state_hash);
10169 return hash;
10170}
size_t get_state_hash() const
Definition GLToolbar.cpp:574
static ImGuiID draw_data_signature(const ImDrawData *draw_data)
Definition ImGuiWrapper.cpp:644

References _overlay_signature(), collapse_toolbar(), Slic3r::GUI::ImGuiWrapper::draw_data_signature(), m_assemble_view_toolbar, m_gizmos, m_main_toolbar, and m_separator_toolbar.

Referenced by _overlay_signature(), and _render_frame().

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

◆ _perform_layer_editing_action()

void Slic3r::GUI::GLCanvas3D::_perform_layer_editing_action ( wxMouseEvent * evt = nullptr)
11998{
11999 int object_idx_selected = m_layers_editing.last_object_id;
12000 if (object_idx_selected == -1)
12001 return;
12002
12003 // A volume is selected. Test, whether hovering over a layer thickness bar.
12004 if (evt != nullptr) {
12005 const Rect& rect = LayersEditing::get_bar_rect_screen(*this);
12006 float b = rect.get_bottom();
12007 m_layers_editing.last_z = m_layers_editing.object_max_z() * (b - evt->GetY() - 1.0f) / (b - rect.get_top());
12008 m_layers_editing.last_action =
12009 evt->ShiftDown() ? (evt->RightIsDown() ? LAYER_HEIGHT_EDIT_ACTION_SMOOTH : LAYER_HEIGHT_EDIT_ACTION_REDUCE) :
12011 }
12012
12013 m_layers_editing.adjust_layer_height_profile();
12015
12016 // Automatic action on mouse down with the same coordinate.
12017 _start_timer();
12018}
static Rect get_bar_rect_screen(const GLCanvas3D &canvas)
Definition GLCanvas3D.cpp:527
void _start_timer()
Definition GLCanvas3D.hpp:1634
void _refresh_if_shown_on_screen(bool scene_dirty=true)
Definition GLCanvas3D.cpp:7947
@ LAYER_HEIGHT_EDIT_ACTION_DECREASE
Definition Slicing.hpp:185
@ LAYER_HEIGHT_EDIT_ACTION_SMOOTH
Definition Slicing.hpp:187
@ LAYER_HEIGHT_EDIT_ACTION_REDUCE
Definition Slicing.hpp:186
@ LAYER_HEIGHT_EDIT_ACTION_INCREASE
Definition Slicing.hpp:184

References _perform_layer_editing_action(), _refresh_if_shown_on_screen(), _start_timer(), Slic3r::GUI::GLCanvas3D::LayersEditing::get_bar_rect_screen(), Slic3r::GUI::Rect::get_bottom(), Slic3r::GUI::Rect::get_top(), Slic3r::LAYER_HEIGHT_EDIT_ACTION_DECREASE, Slic3r::LAYER_HEIGHT_EDIT_ACTION_INCREASE, Slic3r::LAYER_HEIGHT_EDIT_ACTION_REDUCE, Slic3r::LAYER_HEIGHT_EDIT_ACTION_SMOOTH, m_layers_editing, and Slic3r::GUI::wxMouseEvent.

Referenced by _perform_layer_editing_action(), on_mouse(), and on_timer().

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

◆ _picking_pass()

void Slic3r::GUI::GLCanvas3D::_picking_pass ( )
private
7960{
7961 if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX) || m_gizmos.is_dragging()) {
7962#if ENABLE_RAYCAST_PICKING_DEBUG
7963 ImGuiWrapper& imgui = *wxGetApp().imgui();
7964 imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
7965 imgui.text("Picking disabled");
7966 imgui.end();
7967#endif // ENABLE_RAYCAST_PICKING_DEBUG
7968 return;
7969 }
7970
7971 m_hover_volume_idxs.clear();
7972 m_hover_plate_idxs.clear();
7973
7974 // Orca: Picking and camera navigation must interpret the active gizmo clipping plane identically.
7975 const ClippingPlane clipping_plane = get_raycaster_clipping_plane();
7976 const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(m_mouse.position, wxGetApp().plater()->get_camera(), &clipping_plane);
7977 if (hit.is_valid()) {
7978 switch (hit.type)
7979 {
7981 {
7982 if (0 <= hit.raycaster_id && hit.raycaster_id < (int)m_volumes.volumes.size()) {
7983 const GLVolume* volume = m_volumes.volumes[hit.raycaster_id];
7984 if (volume->is_active && !volume->disabled && (volume->composite_id.volume_id >= 0 || m_render_sla_auxiliaries)) {
7985 // do not add the volume id if CTRL is pressed while a gizmo that does not allow Ctrl+click selection is active
7986 if (m_gizmos.is_allow_multi_select_parts_or_objects() || !wxGetKeyState(WXK_CONTROL))
7987 m_hover_volume_idxs.emplace_back(hit.raycaster_id);
7988 m_gizmos.set_hover_id(-1);
7989 }
7990 }
7991 else
7992 assert(false);
7993
7994 break;
7995 }
7998 {
7999 const Size& cnv_size = get_canvas_size();
8000 const bool inside = 0 <= m_mouse.position.x() && m_mouse.position.x() < cnv_size.get_width() &&
8001 0 <= m_mouse.position.y() && m_mouse.position.y() < cnv_size.get_height();
8002 m_gizmos.set_hover_id(inside ? hit.raycaster_id : -1);
8003 break;
8004 }
8006 {
8007 // BBS: add plate picking logic
8008 int plate_hover_id = hit.raycaster_id;
8009 if (plate_hover_id >= 0 && plate_hover_id < PartPlateList::MAX_PLATES_COUNT * PartPlate::GRABBER_COUNT) {
8010 wxGetApp().plater()->get_partplate_list().set_hover_id(plate_hover_id);
8011 m_hover_plate_idxs.emplace_back(plate_hover_id);
8012 } else {
8013 wxGetApp().plater()->get_partplate_list().reset_hover_id();
8014 }
8015 m_gizmos.set_hover_id(-1);
8016 break;
8017 }
8018 default:
8019 {
8020 assert(false);
8021 break;
8022 }
8023 }
8024 }
8025 else
8026 m_gizmos.set_hover_id(-1);
8027
8029
8030 // IMEX ghost picking runs unconditionally after the normal pass: ghosts visually
8031 // occlude the main volumes, so their tooltip/click handling must fire even when a
8032 // regular volume hit also occurred underneath.
8034
8035#if ENABLE_RAYCAST_PICKING_DEBUG
8036 ImGuiWrapper& imgui = *wxGetApp().imgui();
8037 imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
8038 std::string object_type = "None";
8039 switch (hit.type)
8040 {
8041 case SceneRaycaster::EType::Bed: { object_type = "Bed"; break; }
8042 case SceneRaycaster::EType::Gizmo: { object_type = "Gizmo element"; break; }
8043 case SceneRaycaster::EType::FallbackGizmo: { object_type = "Gizmo2 element"; break; }
8045 {
8046 if (m_volumes.volumes[hit.raycaster_id]->is_wipe_tower)
8047 object_type = "Volume (Wipe tower)";
8048 else if (m_volumes.volumes[hit.raycaster_id]->volume_idx() == -int(slaposPad))
8049 object_type = "Volume (SLA pad)";
8050 else if (m_volumes.volumes[hit.raycaster_id]->volume_idx() == -int(slaposSupportTree))
8051 object_type = "Volume (SLA supports)";
8052 else if (m_volumes.volumes[hit.raycaster_id]->is_modifier)
8053 object_type = "Volume (Modifier)";
8054 else
8055 object_type = "Volume (Part)";
8056 break;
8057 }
8058 default: { break; }
8059 }
8060
8061 auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color,
8062 const std::string& col_3 = "", const ImVec4& col_3_color = ImGui::GetStyleColorVec4(ImGuiCol_Text)) {
8063 ImGui::TableNextRow();
8064 ImGui::TableSetColumnIndex(0);
8065 imgui.text_colored(col_1_color, col_1.c_str());
8066 ImGui::TableSetColumnIndex(1);
8067 imgui.text_colored(col_2_color, col_2.c_str());
8068 if (!col_3.empty()) {
8069 ImGui::TableSetColumnIndex(2);
8070 imgui.text_colored(col_3_color, col_3.c_str());
8071 }
8072 };
8073
8074 char buf[1024];
8075 if (hit.type != SceneRaycaster::EType::None) {
8076 if (ImGui::BeginTable("Hit", 2)) {
8077 add_strings_row_to_table("Object ID", ImGuiWrapper::COL_ORANGE_LIGHT, std::to_string(hit.raycaster_id), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8078 add_strings_row_to_table("Type", ImGuiWrapper::COL_ORANGE_LIGHT, object_type, ImGui::GetStyleColorVec4(ImGuiCol_Text));
8079 sprintf(buf, "%.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z());
8080 add_strings_row_to_table("Position", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8081 sprintf(buf, "%.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z());
8082 add_strings_row_to_table("Normal", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8083 ImGui::EndTable();
8084 }
8085 }
8086 else
8087 imgui.text("NO HIT");
8088
8089 ImGui::Separator();
8090 imgui.text("Registered for picking:");
8091 if (ImGui::BeginTable("Raycasters", 2)) {
8092 sprintf(buf, "%d (%d)", (int)m_scene_raycaster.beds_count(), (int)m_scene_raycaster.active_beds_count());
8093 add_strings_row_to_table("Beds", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8094 sprintf(buf, "%d (%d)", (int)m_scene_raycaster.volumes_count(), (int)m_scene_raycaster.active_volumes_count());
8095 add_strings_row_to_table("Volumes", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8096 sprintf(buf, "%d (%d)", (int)m_scene_raycaster.gizmos_count(), (int)m_scene_raycaster.active_gizmos_count());
8097 add_strings_row_to_table("Gizmo elements", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8098 sprintf(buf, "%d (%d)", (int)m_scene_raycaster.fallback_gizmos_count(), (int)m_scene_raycaster.active_fallback_gizmos_count());
8099 add_strings_row_to_table("Gizmo2 elements", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8100 ImGui::EndTable();
8101 }
8102
8103 std::vector<std::shared_ptr<SceneRaycasterItem>>* gizmo_raycasters = m_scene_raycaster.get_raycasters(SceneRaycaster::EType::Gizmo);
8104 if (gizmo_raycasters != nullptr && !gizmo_raycasters->empty()) {
8105 ImGui::Separator();
8106 imgui.text("Gizmo raycasters IDs:");
8107 if (ImGui::BeginTable("GizmoRaycasters", 3)) {
8108 for (size_t i = 0; i < gizmo_raycasters->size(); ++i) {
8110 std::to_string(SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, (*gizmo_raycasters)[i]->get_id())), ImGui::GetStyleColorVec4(ImGuiCol_Text),
8111 to_string(Geometry::Transformation((*gizmo_raycasters)[i]->get_transform()).get_offset()), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8112 }
8113 ImGui::EndTable();
8114 }
8115 }
8116
8117 std::vector<std::shared_ptr<SceneRaycasterItem>>* gizmo2_raycasters = m_scene_raycaster.get_raycasters(SceneRaycaster::EType::FallbackGizmo);
8118 if (gizmo2_raycasters != nullptr && !gizmo2_raycasters->empty()) {
8119 ImGui::Separator();
8120 imgui.text("Gizmo2 raycasters IDs:");
8121 if (ImGui::BeginTable("Gizmo2Raycasters", 3)) {
8122 for (size_t i = 0; i < gizmo2_raycasters->size(); ++i) {
8124 std::to_string(SceneRaycaster::decode_id(SceneRaycaster::EType::FallbackGizmo, (*gizmo2_raycasters)[i]->get_id())), ImGui::GetStyleColorVec4(ImGuiCol_Text),
8125 to_string(Geometry::Transformation((*gizmo2_raycasters)[i]->get_transform()).get_offset()), ImGui::GetStyleColorVec4(ImGuiCol_Text));
8126 }
8127 ImGui::EndTable();
8128 }
8129 }
8130
8131 imgui.end();
8132#endif // ENABLE_RAYCAST_PICKING_DEBUG
8133}
ClippingPlane get_raycaster_clipping_plane() const
Definition GLCanvas3D.cpp:12073
std::vector< int > m_hover_plate_idxs
Definition GLCanvas3D.hpp:784
void _update_volumes_hover_state()
Definition GLCanvas3D.cpp:11920
void _picking_pass_imex_ghosts()
Definition GLCanvas3D.cpp:8135
std::vector< int > m_hover_volume_idxs
Definition GLCanvas3D.hpp:783
static const ImVec4 COL_ORANGE_LIGHT
Definition ImGuiWrapper.hpp:387
static constexpr unsigned int MAX_PLATES_COUNT
Definition PartPlate.hpp:893
static constexpr unsigned int GRABBER_COUNT
Definition PartPlate.hpp:288
static int decode_id(EType type, int id)
Definition SceneRaycaster.cpp:344
@ FallbackGizmo
Definition SceneRaycaster.hpp:52
@ None
Definition SceneRaycaster.hpp:48
@ Gizmo
Definition SceneRaycaster.hpp:51
@ Volume
Definition SceneRaycaster.hpp:50
@ Bed
Definition SceneRaycaster.hpp:49
bool inside(const Polygons &polygons, const Point &p)
Definition TreeNode.cpp:160
static std::string to_string(libvgcode::EMoveType type)
Definition GCodeViewer.cpp:377
static void add_strings_row_to_table(ImGuiWrapper &imgui, const std::string &col_1, const ImVec4 &col_1_color, const std::string &col_2, const ImVec4 &col_2_color)
Definition GLGizmoMeasure.cpp:1790
Transform3f get_transform(const CSGPartT &part)
Definition CSGMesh.hpp:66
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67

References _picking_pass_imex_ghosts(), _update_volumes_hover_state(), Slic3r::GUI::add_strings_row_to_table(), Slic3r::GUI::SceneRaycaster::Bed, Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::COL_ORANGE_LIGHT, Slic3r::GLVolume::composite_id, Slic3r::GUI::SceneRaycaster::decode_id(), Slic3r::GUI::ImGuiWrapper::end(), Slic3r::GUI::SceneRaycaster::FallbackGizmo, get_camera(), get_canvas_size(), Slic3r::GUI::Size::get_height(), get_raycaster_clipping_plane(), Slic3r::GUI::Size::get_width(), Slic3r::GUI::SceneRaycaster::Gizmo, Slic3r::GUI::PartPlate::GRABBER_COUNT, Slic3r::GUI::SceneRaycaster::HitResult::is_valid(), m_gizmos, m_hover_plate_idxs, m_hover_volume_idxs, m_mouse, m_picking_enabled, m_render_sla_auxiliaries, m_scene_raycaster, m_volumes, Slic3r::GUI::PartPlateList::MAX_PLATES_COUNT, Slic3r::GUI::SceneRaycaster::None, Slic3r::GUI::SceneRaycaster::HitResult::normal, Slic3r::GUI::plater(), Slic3r::GUI::SceneRaycaster::HitResult::position, Slic3r::GUI::SceneRaycaster::HitResult::raycaster_id, Slic3r::slaposPad, Slic3r::slaposSupportTree, Slic3r::GUI::ImGuiWrapper::text(), Slic3r::GUI::ImGuiWrapper::text_colored(), Slic3r::GUI::to_string(), Slic3r::GUI::SceneRaycaster::HitResult::type, Slic3r::GUI::SceneRaycaster::Volume, and Slic3r::GLVolume::CompositeID::volume_id.

Referenced by _render_frame().

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

◆ _picking_pass_imex_ghosts()

void Slic3r::GUI::GLCanvas3D::_picking_pass_imex_ghosts ( )
private
8136{
8137 m_hover_ghost_head = -1;
8139
8140 if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX) || m_gizmos.is_dragging())
8141 return;
8142
8143 // Build a world-space ray from the mouse: mouse_ray(pos) returns the near/far
8144 // world-space points, so direction is b - a.
8145 const Linef3 ray = mouse_ray(Point(static_cast<coord_t>(m_mouse.position.x()),
8146 static_cast<coord_t>(m_mouse.position.y())));
8147 const Vec3d ray_origin = ray.a;
8148 const Vec3d ray_dir = ray.b - ray.a;
8149 if (ray_dir.squaredNorm() == 0.0)
8150 return;
8151
8152 // Standard slab ray-vs-AABB test. Accept a hit when the nearest plane entry is
8153 // closer than the farthest plane exit and the exit is in front of the origin.
8154 auto ray_hits_bbox = [](const Vec3d& o, const Vec3d& d, const BoundingBoxf3& bb) -> bool {
8155 double tmin = -std::numeric_limits<double>::infinity();
8156 double tmax = std::numeric_limits<double>::infinity();
8157 for (int i = 0; i < 3; ++i) {
8158 if (std::abs(d[i]) < 1e-12) {
8159 if (o[i] < bb.min[i] || o[i] > bb.max[i])
8160 return false;
8161 }
8162 else {
8163 double t1 = (bb.min[i] - o[i]) / d[i];
8164 double t2 = (bb.max[i] - o[i]) / d[i];
8165 if (t1 > t2) std::swap(t1, t2);
8166 tmin = std::max(tmin, t1);
8167 tmax = std::min(tmax, t2);
8168 if (tmin > tmax) return false;
8169 }
8170 }
8171 return tmax >= 0.0;
8172 };
8173
8174 // Match _render_imex_ghosts: only hit-test ghosts on the active plate. Picking
8175 // through ghosts on background plates would hand the user a stale plate index
8176 // for the head-filament popover and let them edit a plate they aren't looking at.
8177 PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
8178 PartPlate* active_plate = ppl.get_curr_plate();
8179 if (active_plate) {
8180 const auto& ghosts = active_plate->get_imex_ghost_volumes();
8181 for (const auto& g : ghosts) {
8182 if (!g || !g->is_active || !g->picking) continue;
8183 const BoundingBoxf3 bbox = g->transformed_bounding_box();
8184 if (ray_hits_bbox(ray_origin, ray_dir, bbox)) {
8186 m_hover_ghost_plate = ppl.get_curr_plate_index();
8187 return; // first hit wins
8188 }
8189 }
8190 }
8191}
int m_hover_ghost_plate
Definition GLCanvas3D.hpp:789
int m_hover_ghost_head
Definition GLCanvas3D.hpp:788
static int imex_ghost_head_from_composite_id(int object_id)
Definition PartPlate.hpp:300
int64_t coord_t
Definition libslic3r.h:48
Kernel::Point_3 Point
Definition MeshRepair.cpp:81

References Slic3r::Linef3::a, Slic3r::Linef3::b, Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlateList::get_curr_plate_index(), Slic3r::GUI::PartPlate::get_imex_ghost_volumes(), Slic3r::GUI::PartPlate::imex_ghost_head_from_composite_id(), m_gizmos, m_hover_ghost_head, m_hover_ghost_plate, m_mouse, m_picking_enabled, and mouse_ray().

Referenced by _picking_pass().

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

◆ _rectangular_selection_picking_pass()

void Slic3r::GUI::GLCanvas3D::_rectangular_selection_picking_pass ( )
private
8310{
8311 m_gizmos.set_hover_id(-1);
8312
8313 std::set<int> idxs;
8314
8315 if (m_picking_enabled) {
8316 const size_t width = std::max<size_t>(m_rectangle_selection.get_width(), 1);
8317 const size_t height = std::max<size_t>(m_rectangle_selection.get_height(), 1);
8318
8320 bool use_framebuffer = framebuffers_type != OpenGLManager::EFramebufferType::Unknown;
8321
8322 GLuint render_fbo = 0;
8323 GLuint render_tex = 0;
8324 GLuint render_depth = 0;
8325 if (use_framebuffer) {
8326 // setup a framebuffer which covers only the selection rectangle
8327 if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
8328 glsafe(::glGenFramebuffers(1, &render_fbo));
8330 }
8331 else {
8332 glsafe(::glGenFramebuffersEXT(1, &render_fbo));
8334 }
8335 glsafe(::glGenTextures(1, &render_tex));
8336 glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
8337 glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
8340 if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
8342 glsafe(::glGenRenderbuffers(1, &render_depth));
8346 }
8347 else {
8349 glsafe(::glGenRenderbuffersEXT(1, &render_depth));
8353 }
8354 const GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
8355 glsafe(::glDrawBuffers(1, drawBufs));
8356 if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
8358 use_framebuffer = false;
8359 }
8360 else {
8362 use_framebuffer = false;
8363 }
8364 }
8365
8367 // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer.
8369
8372
8374
8375 Camera& main_camera = wxGetApp().plater()->get_camera();
8376 Camera framebuffer_camera;
8377 Camera* camera = &main_camera;
8378 if (use_framebuffer) {
8379 // setup a camera which covers only the selection rectangle
8380 const std::array<int, 4>& viewport = camera->get_viewport();
8381 const double near_left = camera->get_near_left();
8382 const double near_bottom = camera->get_near_bottom();
8383 const double near_width = camera->get_near_width();
8384 const double near_height = camera->get_near_height();
8385
8386 const double ratio_x = near_width / double(viewport[2]);
8387 const double ratio_y = near_height / double(viewport[3]);
8388
8389 const double rect_near_left = near_left + double(m_rectangle_selection.get_left()) * ratio_x;
8390 const double rect_near_bottom = near_bottom + (double(viewport[3]) - double(m_rectangle_selection.get_bottom())) * ratio_y;
8391 double rect_near_right = near_left + double(m_rectangle_selection.get_right()) * ratio_x;
8392 double rect_near_top = near_bottom + (double(viewport[3]) - double(m_rectangle_selection.get_top())) * ratio_y;
8393
8394 if (rect_near_left == rect_near_right)
8395 rect_near_right = rect_near_left + ratio_x;
8396 if (rect_near_bottom == rect_near_top)
8397 rect_near_top = rect_near_bottom + ratio_y;
8398
8399 framebuffer_camera.look_at(camera->get_position(), camera->get_target(), camera->get_dir_up());
8400 framebuffer_camera.set_type(camera->get_type());
8401 framebuffer_camera.apply_projection(rect_near_left, rect_near_right, rect_near_bottom, rect_near_top, camera->get_near_z(), camera->get_far_z());
8402 framebuffer_camera.set_viewport(0, 0, width, height);
8403 framebuffer_camera.apply_viewport();
8404 camera = &framebuffer_camera;
8405 }
8406
8408 //BBS: remove the bed picking logic
8409 //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward());
8410
8413
8414 const size_t px_count = width * height;
8415
8416 const size_t left = use_framebuffer ? 0 : (size_t)m_rectangle_selection.get_left();
8417 const size_t top = use_framebuffer ? 0 : (size_t)get_canvas_size().get_height() - (size_t)m_rectangle_selection.get_top();
8418#define USE_PARALLEL 1
8419#if USE_PARALLEL
8420 struct Pixel
8421 {
8422 std::array<GLubyte, 4> data;
8423 // Only non-interpolated colors are valid, those have their lowest three bits zeroed.
8424 bool valid() const { return picking_checksum_alpha_channel(data[0], data[1], data[2]) == data[3]; }
8425 // we reserve color = (0,0,0) for occluders (as the printbed)
8426 // volumes' id are shifted by 1
8427 // see: _render_volumes_for_picking()
8428 //BBS: remove the bed picking logic
8429 int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); }
8430 //int id() const { return data[0] + (data[1] << 8) + (data[2] << 16) - 1; }
8431 };
8432
8433 std::vector<Pixel> frame(px_count);
8434 glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data()));
8435
8436 tbb::spin_mutex mutex;
8437 tbb::parallel_for(tbb::blocked_range<size_t>(0, frame.size(), (size_t)width),
8438 [this, &frame, &idxs, &mutex](const tbb::blocked_range<size_t>& range) {
8439 for (size_t i = range.begin(); i < range.end(); ++i)
8440 if (frame[i].valid()) {
8441 int volume_id = frame[i].id();
8442 if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) {
8443 mutex.lock();
8444 idxs.insert(volume_id);
8445 mutex.unlock();
8446 }
8447 }
8448 });
8449#else
8450 std::vector<GLubyte> frame(4 * px_count);
8451 glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data()));
8452
8453 for (int i = 0; i < px_count; ++i)
8454 {
8455 int px_id = 4 * i;
8456 int volume_id = frame[px_id] + (frame[px_id + 1] << 8) + (frame[px_id + 2] << 16);
8457 if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size())
8458 idxs.insert(volume_id);
8459 }
8460#endif // USE_PARALLEL
8461 if (camera != &main_camera)
8462 main_camera.apply_viewport();
8463
8464 if (framebuffers_type == OpenGLManager::EFramebufferType::Arb) {
8466 if (render_depth != 0)
8467 glsafe(::glDeleteRenderbuffers(1, &render_depth));
8468 if (render_fbo != 0)
8469 glsafe(::glDeleteFramebuffers(1, &render_fbo));
8470 }
8471 else if (framebuffers_type == OpenGLManager::EFramebufferType::Ext) {
8473 if (render_depth != 0)
8474 glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
8475 if (render_fbo != 0)
8476 glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
8477 }
8478
8479 if (render_tex != 0)
8480 glsafe(::glDeleteTextures(1, &render_tex));
8481 }
8482
8483 m_hover_volume_idxs.assign(idxs.begin(), idxs.end());
8485}
void _render_volumes_for_picking(const Camera &camera) const
Definition GLCanvas3D.cpp:10265
static EFramebufferType get_framebuffers_type()
Definition OpenGLManager.hpp:102
EFramebufferType
Definition OpenGLManager.hpp:21
@ Arb
Definition OpenGLManager.hpp:23
@ Ext
Definition OpenGLManager.hpp:24
@ Unknown
Definition OpenGLManager.hpp:22
int get_height() const
Definition GLCanvas3D.hpp:122
#define glDeleteFramebuffersEXT
Definition gl.h:3567
#define GL_TEXTURE_MIN_FILTER
Definition gl.h:1828
#define GL_DEPTH_ATTACHMENT_EXT
Definition gl.h:555
#define glCheckFramebufferStatus
Definition gl.h:3349
#define glCheckFramebufferStatusEXT
Definition gl.h:3351
#define GL_RGBA8
Definition gl.h:1505
#define glEnable
Definition gl.h:3667
#define glFramebufferTexture2D
Definition gl.h:3755
#define GL_DEPTH_TEST
Definition gl.h:574
#define GL_FRAMEBUFFER_COMPLETE_EXT
Definition gl.h:733
#define GL_COLOR_ATTACHMENT0
Definition gl.h:360
#define GL_COLOR_ATTACHMENT0_EXT
Definition gl.h:361
#define glBindFramebufferEXT
Definition gl.h:3283
#define glTexParameteri
Definition gl.h:4911
#define glReadPixels
Definition gl.h:4659
#define glGenFramebuffersEXT
Definition gl.h:3773
#define GL_FRAMEBUFFER_COMPLETE
Definition gl.h:732
#define glTexImage2D
Definition gl.h:4895
#define glBindFramebuffer
Definition gl.h:3281
#define GL_NEAREST
Definition gl.h:1200
unsigned int GLenum
Definition gl.h:2054
#define GL_UNSIGNED_BYTE
Definition gl.h:1937
#define glGenTextures
Definition gl.h:3787
#define GL_RENDERBUFFER
Definition gl.h:1427
#define glGenRenderbuffers
Definition gl.h:3781
#define GL_COLOR_BUFFER_BIT
Definition gl.h:408
#define glFramebufferTexture2DEXT
Definition gl.h:3757
#define GL_FRAMEBUFFER
Definition gl.h:708
#define GL_RGBA
Definition gl.h:1493
#define glBindRenderbuffer
Definition gl.h:3291
#define GL_BLEND
Definition gl.h:275
#define GL_MULTISAMPLE
Definition gl.h:1194
unsigned int GLuint
Definition gl.h:2063
#define glFramebufferRenderbuffer
Definition gl.h:3745
#define GL_DEPTH_COMPONENT
Definition gl.h:561
#define GL_RENDERBUFFER_EXT
Definition gl.h:1436
#define glRenderbufferStorageEXT
Definition gl.h:4685
#define glBindRenderbufferEXT
Definition gl.h:3293
#define GL_DEPTH_ATTACHMENT
Definition gl.h:554
#define GL_TEXTURE_MAG_FILTER
Definition gl.h:1822
#define glGenRenderbuffersEXT
Definition gl.h:3783
#define glFramebufferRenderbufferEXT
Definition gl.h:3747
#define glDeleteRenderbuffers
Definition gl.h:3577
#define glRenderbufferStorage
Definition gl.h:4683
#define glDisable
Definition gl.h:3607
#define glDrawBuffers
Definition gl.h:3631
#define GL_FRAMEBUFFER_EXT
Definition gl.h:740
#define GL_DEPTH_BUFFER_BIT
Definition gl.h:558
#define glGenFramebuffers
Definition gl.h:3771
#define glClear
Definition gl.h:3357
#define glDeleteRenderbuffersEXT
Definition gl.h:3579
coord_t width(const BoundingBox &box)
Definition Arrange.cpp:1184
coord_t height(const BoundingBox &box)
Definition Arrange.cpp:1185
unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char green, unsigned char blue)
Definition Color.cpp:422
auto range(Cont &&cont)
Definition libslic3r.h:405

References _render_volumes_for_picking(), Slic3r::GUI::Camera::apply_projection(), Slic3r::GUI::Camera::apply_viewport(), Slic3r::GUI::OpenGLManager::Arb, camera, Slic3r::GUI::OpenGLManager::Ext, get_canvas_size(), Slic3r::GUI::OpenGLManager::get_framebuffers_type(), Slic3r::GUI::Size::get_height(), GL_BLEND, GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_BUFFER_BIT, GL_DEPTH_ATTACHMENT, GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_BUFFER_BIT, GL_DEPTH_COMPONENT, GL_DEPTH_TEST, GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, GL_FRAMEBUFFER_COMPLETE_EXT, GL_FRAMEBUFFER_EXT, GL_MULTISAMPLE, GL_NEAREST, GL_RENDERBUFFER, GL_RENDERBUFFER_EXT, GL_RGBA, GL_RGBA8, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_UNSIGNED_BYTE, glBindFramebuffer, glBindFramebufferEXT, glBindRenderbuffer, glBindRenderbufferEXT, glBindTexture, glCheckFramebufferStatus, glCheckFramebufferStatusEXT, glClear, glDeleteFramebuffers, glDeleteFramebuffersEXT, glDeleteRenderbuffers, glDeleteRenderbuffersEXT, glDeleteTextures, glDisable, glDrawBuffers, glEnable, glFramebufferRenderbuffer, glFramebufferRenderbufferEXT, glFramebufferTexture2D, glFramebufferTexture2DEXT, glGenFramebuffers, glGenFramebuffersEXT, glGenRenderbuffers, glGenRenderbuffersEXT, glGenTextures, glReadPixels, glRenderbufferStorage, glRenderbufferStorageEXT, glsafe, glTexImage2D, glTexParameteri, Slic3r::GUI::Camera::look_at(), m_gizmos, m_multisample_allowed, m_picking_enabled, m_rectangle_selection, m_volumes, Slic3r::picking_checksum_alpha_channel(), Slic3r::range(), Slic3r::GUI::Camera::set_type(), Slic3r::GUI::Camera::set_viewport(), and Slic3r::GUI::OpenGLManager::Unknown.

Referenced by _render_frame().

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

◆ _refresh_if_shown_on_screen()

void Slic3r::GUI::GLCanvas3D::_refresh_if_shown_on_screen ( bool scene_dirty = true)
private
7948{
7949 if (_is_shown_on_screen()) {
7950 const Size& cnv_size = get_canvas_size();
7951 _resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
7952
7953 // Because of performance problems on macOS, where PaintEvents are not delivered
7954 // frequently enough, we render here directly when we can.
7955 _render_frame(scene_dirty);
7956 }
7957}
void _render_frame(bool scene_dirty, bool only_init=false)
Definition GLCanvas3D.cpp:2487
bool _is_shown_on_screen() const
Definition GLCanvas3D.cpp:6543
void _resize(unsigned int w, unsigned int h)
Definition GLCanvas3D.cpp:7849

References _is_shown_on_screen(), _render_frame(), _resize(), get_canvas_size(), Slic3r::GUI::Size::get_height(), and Slic3r::GUI::Size::get_width().

Referenced by _perform_layer_editing_action(), on_idle(), on_mouse(), on_paint(), on_set_focus(), and update_ui_from_settings().

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

◆ _render_3d_navigator()

void Slic3r::GUI::GLCanvas3D::_render_3d_navigator ( )
private
6775{
6776 if (!wxGetApp().show_3d_navigator()) {
6777 m_canvas_toolbar_pos[0] = 0;
6778 m_navigator_dragging = false;
6779 return;
6780 }
6781
6782 // Fix stealing capture event from other drag events
6783 const bool other_drag_active = !m_navigator_dragging && (m_moving || m_rectangle_selection.is_dragging() || m_gizmos.is_dragging() || m_layers_editing.state == LayersEditing::Editing);
6784
6785 ImGuiIO& io = ImGui::GetIO();
6786 const bool saved_mouse_down0 = io.MouseDown[0];
6787 if (other_drag_active)
6788 io.MouseDown[0] = false;
6789
6790 ImGuizmo::BeginFrame();
6791
6792 auto& style = ImGuizmo::GetStyle();
6793 style.Colors[ImGuizmo::COLOR::DIRECTION_X] = ImGuiWrapper::to_ImVec4(ColorRGBA::Y());
6794 style.Colors[ImGuizmo::COLOR::DIRECTION_Y] = ImGuiWrapper::to_ImVec4(ColorRGBA::Z());
6795 style.Colors[ImGuizmo::COLOR::DIRECTION_Z] = ImGuiWrapper::to_ImVec4(ColorRGBA::X());
6796 style.Colors[ImGuizmo::COLOR::TEXT] = m_is_dark ? ImVec4(224 / 255.f, 224 / 255.f, 224 / 255.f, 1.f) : ImVec4(.2f, .2f, .2f, 1.0f);
6797 style.Colors[ImGuizmo::COLOR::FACE] = m_is_dark ? ImVec4(0.23f, 0.23f, 0.23f, 1.f) : ImVec4(0.77f, 0.77f, 0.77f, 1);
6798 strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_X], _u8L_CONTEXT("Y", "Axis").c_str()); // ORCA use uppercase to match text on tranform widgets
6799 strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Y], _u8L_CONTEXT("Z", "Axis").c_str()); // ORCA use uppercase to match text on tranform widgets
6800 strcpy(style.AxisLabels[ImGuizmo::Axis::Axis_Z], _u8L_CONTEXT("X", "Axis").c_str()); // ORCA use uppercase to match text on tranform widgets
6801 strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_FRONT], _u8L_CONTEXT("Front", "Camera View").c_str());
6802 strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BACK], _u8L_CONTEXT("Back", "Camera View").c_str());
6803 strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_TOP], _u8L_CONTEXT("Top", "Camera View").c_str());
6804 strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_BOTTOM], _u8L_CONTEXT("Bottom", "Camera View").c_str());
6805 strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_LEFT], _u8L_CONTEXT("Left", "Camera View").c_str());
6806 strcpy(style.FaceLabels[ImGuizmo::FACES::FACE_RIGHT], _u8L_CONTEXT("Right", "Camera View").c_str());
6807
6808 float sc = get_scale();
6809#ifdef WIN32
6810 const int dpi = get_dpi_for_window(wxGetApp().GetTopWindow());
6811 sc *= (float) dpi / (float) DPI_DEFAULT;
6812#endif // WIN32
6813
6814 const float viewManipulateLeft = 0;
6815 const float viewManipulateTop = io.DisplaySize.y;
6816 const float camDistance = 8.f;
6817
6818 Camera& camera = wxGetApp().plater()->get_camera();
6819 Transform3d m = Transform3d::Identity();
6820 m.matrix().block(0, 0, 3, 3) = camera.get_view_rotation().toRotationMatrix();
6821 // Rotate along X and Z axis for 90 degrees to have Y-up
6822 const auto coord_mapping_transform = Geometry::rotation_transform(Vec3d(0.5 * PI, 0, 0.5 * PI));
6823 m = m * coord_mapping_transform;
6824 float cameraView[16];
6825 for (unsigned int c = 0; c < 4; ++c) {
6826 for (unsigned int r = 0; r < 4; ++r) {
6827 cameraView[c * 4 + r] = m(r, c);
6828 }
6829 }
6830
6831 const float size = NAVIGATOR_SIZE * sc;
6832 m_canvas_toolbar_pos[0] = size;
6833 const auto result = ImGuizmo::ViewManipulate(cameraView, cameraProjection, ImGuizmo::OPERATION::ROTATE, ImGuizmo::MODE::WORLD, nullptr,
6834 camDistance, ImVec2(viewManipulateLeft, viewManipulateTop - size), ImVec2(size, size),
6835 0x00101010);
6836
6837 // Restore the real mouse-down state
6838 if (other_drag_active)
6839 io.MouseDown[0] = saved_mouse_down0;
6840
6841 if (result.changed) {
6842 for (unsigned int c = 0; c < 4; ++c) {
6843 for (unsigned int r = 0; r < 4; ++r) {
6844 m(r, c) = cameraView[c * 4 + r];
6845 }
6846 }
6847 // Rotate back
6848 m = m * (coord_mapping_transform.inverse());
6849 camera.set_rotation(m);
6850
6851 if (result.dragging) {
6852 // Switch back to perspective view when normal dragging
6854 } else if (result.clicked_box >= 0) {
6855 switch (result.clicked_box) {
6856 case 4: // back
6857 case 10: // top
6858 case 12: // right
6859 case 14: // left
6860 case 16: // bottom
6861 case 22: // front
6862 // Automatically switch to orthographic view when click the center face of the navigator
6863 camera.auto_type(Camera::EType::Ortho); break;
6864 default:
6865 // Otherwise switch back to perspective view
6866 camera.auto_type(Camera::EType::Perspective); break;
6867 }
6868 }
6869
6871 }
6872
6873 m_navigator_dragging = result.dragging;
6874}
#define style
Definition WipeTowerDialog.cpp:101
static const ColorRGBA Y()
Definition Color.hpp:146
static const ColorRGBA X()
Definition Color.hpp:145
static const ColorRGBA Z()
Definition Color.hpp:147
@ Editing
Definition GLCanvas3D.hpp:253
Vec2i32 m_canvas_toolbar_pos
Definition GLCanvas3D.hpp:669
bool m_navigator_dragging
Definition GLCanvas3D.hpp:780
static ImVec4 to_ImVec4(const ColorRGB &color)
Definition ImGuiWrapper.cpp:1053
static constexpr double PI
Definition libslic3r.h:81
static const float cameraProjection[16]
Definition GLCanvas3D.cpp:6772
static constexpr float NAVIGATOR_SIZE
Definition GLCanvas3D.cpp:2434
void rotation_transform(Transform3d &transform, const Vec3d &rotation)
Definition Geometry.cpp:359
Eigen::Transform< double, 3, Eigen::Affine, Eigen::DontAlign > Transform3d
Definition Point.hpp:96
#define _u8L_CONTEXT(s, ctx)
Definition I18N.hpp:16
@ Ortho
Definition Camera.hpp:39
@ Perspective
Definition Camera.hpp:40

References _u8L_CONTEXT, camera, Slic3r::GUI::cameraProjection, Slic3r::GUI::DPI_DEFAULT, Slic3r::GUI::GLCanvas3D::LayersEditing::Editing, Slic3r::GUI::get_dpi_for_window(), get_scale(), m_canvas_toolbar_pos, m_gizmos, m_is_dark, m_layers_editing, m_moving, m_navigator_dragging, m_rectangle_selection, Slic3r::GUI::NAVIGATOR_SIZE, Slic3r::GUI::Camera::Ortho, Slic3r::GUI::Camera::Perspective, PI, request_extra_frame(), Slic3r::Geometry::rotation_transform(), style, Slic3r::GUI::ImGuiWrapper::to_ImVec4(), Slic3r::ColorRGBA::X(), Slic3r::ColorRGBA::Y(), and Slic3r::ColorRGBA::Z().

Referenced by _render_overlays().

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

◆ _render_arrange_menu()

void Slic3r::GUI::GLCanvas3D::_render_arrange_menu ( float left,
float right,
float bottom,
float top )
private
6647{
6648 ImGuiWrapper *imgui = wxGetApp().imgui();
6649
6650 auto canvas_w = float(get_canvas_size().get_width());
6651 auto canvas_h = float(get_canvas_size().get_height());
6652 //BBS: GUI refactor: move main toolbar to the right
6653 //original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera
6654 //now change to left_up as {0,0}, and top is 0, bottom is canvas_h
6655#if BBS_TOOLBAR_ON_TOP
6656 float left_pos = m_main_toolbar.get_item("arrange")->render_left_pos;
6657 const float x = (1 + left_pos) * canvas_w / 2;
6658 imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.0f, 0.0f);
6659
6660#else
6661 const float x = canvas_w - m_main_toolbar.get_width();
6662 const float y = 0.5f * canvas_h - top * float(wxGetApp().plater()->get_camera().get_zoom());
6663 imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f);
6664#endif
6665
6666 //BBS
6668
6669 imgui->begin(_L("Arrange options"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
6670
6671 ArrangeSettings &settings_out = get_arrange_settings();
6672 const float slider_icon_width = imgui->get_slider_icon_size().x;
6673 const float cursor_slider_left = imgui->calc_text_size(_L("Spacing")).x + imgui->scaled(1.5f);
6674 const float minimal_slider_width = imgui->scaled(4.f);
6675 float window_width = minimal_slider_width + 2 * slider_icon_width;
6676 auto &appcfg = wxGetApp().app_config;
6678
6679 std::string dist_key = "min_object_distance", rot_key = "enable_rotation";
6680 std::string multi_material_key = "allow_multi_materials_on_same_plate";
6681 std::string avoid_extrusion_key = "avoid_extrusion_cali_region";
6682 std::string postfix;
6683 //BBS:
6684 bool seq_print = false;
6685
6686 if (ptech == ptSLA) {
6687 postfix = "_sla";
6688 } else if (ptech == ptFFF) {
6689 seq_print = wxGetApp().global_print_sequence() == PrintSequence::ByObject;
6690 postfix = seq_print ? "_fff_seq_print" : "_fff";
6691 }
6692
6693 dist_key += postfix;
6694 rot_key += postfix;
6695
6696 ImGui::AlignTextToFramePadding();
6697 imgui->text(_L("Spacing"));
6698 ImGui::SameLine(1.2 * cursor_slider_left);
6699 ImGui::PushItemWidth(window_width - slider_icon_width);
6700 bool b_Spacing = imgui->bbl_slider_float_style("##Spacing", &settings_out.distance, 0.f, 100.0f, "%5.2f", 1.0f, /*clamp=*/false);
6701 ImGui::SameLine(window_width - slider_icon_width + 1.3 * cursor_slider_left);
6702 ImGui::PushItemWidth(1.5 * slider_icon_width);
6703 bool b_spacing_input = ImGui::BBLDragFloat("##spacing_input", &settings_out.distance, 0.05f, 0.0f, 0.0f, "%.2f");
6704 if (b_Spacing || b_spacing_input) {
6705 settings_out.distance = std::max(0.f, settings_out.distance);
6706 appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance));
6707 }
6708 imgui->text(_L("0 means auto spacing."));
6709
6710 ImGui::Separator();
6711 if (imgui->bbl_checkbox(_L("Auto rotate for arrangement"), settings_out.enable_rotation))
6712 appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation);
6713
6714 if (imgui->bbl_checkbox(_L("Allow multiple materials on same plate"), settings_out.allow_multi_materials_on_same_plate))
6715 appcfg->set("arrange", multi_material_key.c_str(), settings_out.allow_multi_materials_on_same_plate);
6716
6717 // only show this option if the printer has micro Lidar and can do first layer scan
6718 DynamicPrintConfig &current_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
6719 const bool has_lidar = wxGetApp().preset_bundle->is_bbl_vendor();
6720 auto op = current_config.option("scan_first_layer");
6721 if (has_lidar && op && op->getBool()) {
6722 if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings_out.avoid_extrusion_cali_region))
6723 appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region);
6724 } else {
6725 settings_out.avoid_extrusion_cali_region = false;
6726 }
6727
6728 // Align to Y axis. Only enable this option when auto rotation not enabled
6729 {
6730 if (settings_out.enable_rotation) { // do not allow align to Y axis if rotation is enabled
6731 imgui->disabled_begin(true);
6732 settings_out.align_to_y_axis = false;
6733 }
6734
6735 imgui->bbl_checkbox(_L("Align to Y axis"), settings_out.align_to_y_axis);
6736
6737 if (settings_out.enable_rotation == true) { imgui->disabled_end(); }
6738 }
6739
6740 ImGui::Separator();
6741 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(15.0f, 10.0f));
6742 if (imgui->button(_L("Arrange"))) {
6743 wxGetApp().plater()->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
6744 wxGetApp().plater()->arrange();
6745 }
6746
6747 ImGui::SameLine();
6748
6749 if (imgui->button(_L("Reset"))) {
6750 settings_out = ArrangeSettings{};
6751 //BBS: add specific arrange settings
6752 if (seq_print) settings_out.is_seq_print = true;
6753
6754 if (auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) {
6755 settings_out.align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3);
6756 }
6757 else
6758 settings_out.align_to_y_axis = false;
6759
6760 appcfg->erase("arrange", dist_key);
6761 appcfg->erase("arrange", rot_key);
6762 appcfg->erase("arrange", multi_material_key);
6763 appcfg->erase("arrange", avoid_extrusion_key);
6764 }
6765 ImGui::PopStyleVar(1);
6766 imgui->end();
6767
6768 //BBS
6770}
ArrangeSettings & get_arrange_settings()
Definition GLCanvas3D.cpp:1563
bool is_seq_print
Definition GLCanvas3D.hpp:612
Definition GLCanvas3D.hpp:604
static void push_toolbar_style(const float scale)
Definition ImGuiWrapper.cpp:2705
static void pop_toolbar_style()
Definition ImGuiWrapper.cpp:2757
PrinterTechnology
Definition Config.hpp:229
@ ptSLA
Definition Config.hpp:233
std::string float_to_string_decimal_point(double value, int precision)
Definition LocalesUtils.cpp:108
@ psI3
Definition PrintConfig.hpp:560

References _L, Slic3r::GUI::GLCanvas3D::ArrangeSettings::align_to_y_axis, Slic3r::GUI::GLCanvas3D::ArrangeSettings::allow_multi_materials_on_same_plate, Slic3r::GUI::GLCanvas3D::ArrangeSettings::avoid_extrusion_cali_region, Slic3r::GUI::ImGuiWrapper::bbl_checkbox(), Slic3r::GUI::ImGuiWrapper::bbl_slider_float_style(), Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::button(), Slic3r::ByObject, Slic3r::GUI::ImGuiWrapper::calc_text_size(), current_printer_technology(), Slic3r::GUI::ImGuiWrapper::disabled_begin(), Slic3r::GUI::ImGuiWrapper::disabled_end(), Slic3r::GUI::GLCanvas3D::ArrangeSettings::distance, Slic3r::GUI::GLCanvas3D::ArrangeSettings::enable_rotation, Slic3r::GUI::ImGuiWrapper::end(), Slic3r::float_to_string_decimal_point(), get_arrange_settings(), get_camera(), get_canvas_size(), get_scale(), Slic3r::GUI::GLCanvas3D::ArrangeSettings::is_seq_print, m_main_toolbar, Slic3r::ConfigBase::option(), Slic3r::GUI::plater(), Slic3r::GUI::ImGuiWrapper::pop_toolbar_style(), Slic3r::GUI::Job::PREPARE_STATE_DEFAULT, Slic3r::psI3, Slic3r::ptFFF, Slic3r::ptSLA, Slic3r::GUI::ImGuiWrapper::push_toolbar_style(), Slic3r::GUI::ImGuiWrapper::scaled(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), and Slic3r::GUI::ImGuiWrapper::text().

Referenced by _init_main_toolbar().

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

◆ _render_assemble_control()

void Slic3r::GUI::GLCanvas3D::_render_assemble_control ( )
private
11590{
11593 return;
11594 }
11595 if (m_gizmos.get_current_type() == GLGizmosManager::EType::MmSegmentation)
11596 return;
11597
11598 ImGuiWrapper* imgui = wxGetApp().imgui();
11599
11601
11602 auto canvas_w = float(get_canvas_size().get_width());
11603 auto canvas_h = float(get_canvas_size().get_height());
11604
11605 const float text_padding = 7.0f;
11606 const float slider_width = 60.0f;
11607 const float value_size = imgui->calc_text_size("3.00"sv).x + text_padding * 2;
11608 const float item_spacing = imgui->get_item_spacing().x;
11609 ImVec2 window_padding = ImGui::GetStyle().WindowPadding;
11610
11611 imgui->set_next_window_pos(canvas_w / 2, canvas_h - 10.0f * get_scale(), ImGuiCond_Always, 0.5f, 1.0f);
11612 imgui->begin(_L("Assembly Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
11613
11614 ImGui::AlignTextToFramePadding();
11615 float tooltip_button_width;
11616 {
11617 tooltip_button_width = _render_assembly_tooltip_button(imgui);
11618 }
11619 float same_line_width = tooltip_button_width;
11620 {
11621 auto temp_x = imgui->calc_text_size(_L("Explosion Ratio")).x;
11622 ImGui::SameLine(same_line_width);
11623 ImGui::PushItemWidth(temp_x);
11624 imgui->text(_L("Explosion Ratio"));
11625
11626 same_line_width += (temp_x + item_spacing);
11627 ImGui::SameLine(same_line_width);
11628 ImGui::PushItemWidth(slider_width);
11629 bool explosion_slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f");
11630
11631 same_line_width += (slider_width + item_spacing);
11632 ImGui::SameLine(same_line_width);
11633 ImGui::PushItemWidth(value_size);
11634 bool explosion_input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f");
11635 same_line_width += (value_size + item_spacing*2);
11636 }
11637 {
11638 ImGui::SameLine(same_line_width);
11639 // input
11640 std::vector<std::string> modes = {_u8L("Object"), _u8L("Part")};
11641 int selection_idx = m_selection.get_volume_selection_mode() == Selection::Instance ? 0 : 1;
11642 auto label = _u8L("Selection Mode") + ":" ;
11643 auto label_width = imgui->calc_text_size(label).x ;
11644 auto item_width = imgui->calc_text_size(_u8L("Object")).x * 2.5 + imgui->calc_text_size("xx"sv).x+ item_spacing;
11645 //render imgui
11646 ImGui::AlignTextToFramePadding();
11647 ImGui::PushItemWidth(label_width);
11648 imgui->text(label);
11649 same_line_width += (label_width + item_spacing);
11650 ImGui::SameLine(same_line_width);
11651 ImGui::PushItemWidth(item_width);
11652 size_t selection_out = selection_idx;
11653 const char *selected_str = (selection_idx >= 0 && selection_idx < int(modes.size())) ? modes[selection_idx].c_str() : "";
11655 if (ImGui::BBLBeginCombo(("##" + label).c_str(), selected_str, 0)) {
11656 for (size_t line_idx = 0; line_idx < modes.size(); ++line_idx) {
11657 ImGui::PushID(int(line_idx));
11658 if (ImGui::Selectable("", line_idx == selection_idx))
11659 selection_out = line_idx;
11660
11661 ImGui::SameLine();
11662 ImGui::Text("%s", modes[line_idx].c_str());
11663 ImGui::PopID();
11664 }
11665 ImGui::EndCombo();
11666 }
11668 if (selection_idx != selection_out) {//do
11669 if (selection_out == 0) { m_selection.unlock_volume_selection_mode(); }
11670 m_selection.set_volume_selection_mode(selection_out == 1 ? Selection::Volume : Selection::Instance);
11671 if (selection_out == 1) { m_selection.lock_volume_selection_mode(); }
11672 }
11673 same_line_width += (label_width + item_width);
11674 }
11675 imgui->end();
11676
11678
11679 //BBS check ratio changed
11681 for (GLVolume* volume : m_volumes.volumes) {
11682 volume->set_bounding_boxes_as_dirty();
11683 }
11685 }
11686}
static float explosion_ratio
Definition 3DScene.hpp:117
float m_explosion_ratio
Definition GLCanvas3D.hpp:791
float _render_assembly_tooltip_button(ImGuiWrapper *imgui_wrapper) const
Definition GLCanvas3D.cpp:11560
@ MmSegmentation
Definition GLGizmosManager.hpp:97
static void pop_combo_style()
Definition ImGuiWrapper.cpp:2932
static void push_combo_style(const float scale)
Definition ImGuiWrapper.cpp:2907
@ Instance
Definition Selection.hpp:54
@ Volume
Definition Selection.hpp:53
#define _u8L(s)
Definition I18N.hpp:11

References _L, _render_assemble_control(), _render_assembly_tooltip_button(), _u8L, Slic3r::GUI::ImGuiWrapper::bbl_slider_float_style(), Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::calc_text_size(), CanvasAssembleView, Slic3r::GUI::ImGuiWrapper::end(), Slic3r::GLVolume::explosion_ratio, get_canvas_size(), Slic3r::GUI::ImGuiWrapper::get_item_spacing(), get_scale(), Slic3r::GUI::Selection::Instance, m_canvas_type, m_explosion_ratio, m_gizmos, m_selection, m_volumes, Slic3r::GUI::GLGizmosManager::MmSegmentation, Slic3r::GUI::ImGuiWrapper::pop_combo_style(), Slic3r::GUI::ImGuiWrapper::pop_toolbar_style(), Slic3r::GUI::ImGuiWrapper::push_combo_style(), Slic3r::GUI::ImGuiWrapper::push_toolbar_style(), Slic3r::GLVolume::set_bounding_boxes_as_dirty(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), Slic3r::GUI::ImGuiWrapper::text(), and Slic3r::GUI::Selection::Volume.

Referenced by _render_assemble_control(), and _render_overlays().

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

◆ _render_assemble_info()

void Slic3r::GUI::GLCanvas3D::_render_assemble_info ( ) const
private
11688{
11690 return;
11691 }
11692
11693 if (m_selection.is_empty()) {
11694 return;
11695 }
11696
11697 ImGuiWrapper* imgui = wxGetApp().imgui();
11698 auto canvas_w = float(get_canvas_size().get_width());
11699 auto canvas_h = float(get_canvas_size().get_height());
11700 float space_size = imgui->get_style_scaling() * 8.0f;
11701 float caption_max = imgui->calc_text_size(_L("Total Volume:")).x + 3 * space_size;
11702
11703 ImGuiIO& io = ImGui::GetIO();
11704 ImFont* font = io.Fonts->Fonts[0];
11705 float origScale = font->Scale;
11706 font->Scale = 1.2;
11707 ImGui::PushFont(font);
11708 ImGui::PopFont();
11709 float margin = 10.0f * get_scale();
11710 imgui->set_next_window_pos(canvas_w - margin, canvas_h - margin, ImGuiCond_Always, 1.0f, 1.0f);
11711 ImGuiWrapper::push_common_window_style(get_scale()); // ORCA use window style for popups with title
11712 imgui->begin(_L("Assembly Info"), ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
11713 font->Scale = origScale;
11714 ImGui::PushFont(font);
11715 ImGui::PopFont();
11716
11717 double size0 = m_selection.get_bounding_box().size()(0);
11718 double size1 = m_selection.get_bounding_box().size()(1);
11719 double size2 = m_selection.get_bounding_box().size()(2);
11720 if (!m_selection.is_empty()) {
11721 ImGui::Text("%s", _L("Volume:").ToUTF8().data()); ImGui::SameLine(caption_max);
11722 ImGui::Text("%.2f", size0 * size1 * size2);
11723 ImGui::Text("%s", _L("Size:").ToUTF8().data()); ImGui::SameLine(caption_max);
11724 ImGui::Text("%.2f x %.2f x %.2f", size0, size1, size2);
11725 }
11726 imgui->end();
11728}
static void pop_common_window_style()
Definition ImGuiWrapper.cpp:2839
static void push_common_window_style(const float scale)
Definition ImGuiWrapper.cpp:2794

References _L, _render_assemble_info(), Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::calc_text_size(), CanvasAssembleView, Slic3r::GUI::ImGuiWrapper::end(), get_canvas_size(), get_scale(), Slic3r::GUI::ImGuiWrapper::get_style_scaling(), m_canvas_type, m_selection, Slic3r::GUI::ImGuiWrapper::pop_common_window_style(), Slic3r::GUI::ImGuiWrapper::push_common_window_style(), and Slic3r::GUI::ImGuiWrapper::set_next_window_pos().

Referenced by _render_assemble_info(), and _render_overlays().

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

◆ _render_assemble_view_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_assemble_view_toolbar ( ) const
private
10920{
10921 if (!m_assemble_view_toolbar.is_enabled())
10922 return;
10923
10924 const Size cnv_size = get_canvas_size();
10925 const float gizmo_width = m_gizmos.get_scaled_total_width();
10926 const float separator_width = m_separator_toolbar.get_width();
10927 const float top = 0.5f * (float)cnv_size.get_height();
10928 const float main_toolbar_left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset();
10929 const float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width);
10930
10931 m_assemble_view_toolbar.set_position(top, left);
10932 m_assemble_view_toolbar.render(*this);
10933}
int get_main_toolbar_offset() const
Definition GLCanvas3D.cpp:10331

References _render_assemble_view_toolbar(), get_canvas_size(), Slic3r::GUI::Size::get_height(), get_main_toolbar_offset(), Slic3r::GUI::Size::get_width(), m_assemble_view_toolbar, m_gizmos, m_main_toolbar, and m_separator_toolbar.

Referenced by _render_assemble_view_toolbar(), and _render_overlay_toolbars().

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

◆ _render_assembly_tooltip_button()

float Slic3r::GUI::GLCanvas3D::_render_assembly_tooltip_button ( ImGuiWrapper * imgui_wrapper) const
private
11561{
11562 const float text_height = imgui_wrapper->calc_text_size(_L("Part selection")).y;
11563 ImVec2 windowPos = ImGui::GetWindowPos();
11564 float x = windowPos.x;
11565 float y = windowPos.y - ImGui::GetFrameHeight() - (5 * text_height);
11566 y -= ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight(); // correct default ToolTipButton behaviour
11567
11569 ImGui::SameLine();
11570 ImGui::Dummy(ImVec2(12.f, 0.f));
11571
11572 float scale = get_scale();
11573#ifdef WIN32
11574 int dpi = get_dpi_for_window(wxGetApp().GetTopWindow());
11575 scale *= (float) dpi / (float) DPI_DEFAULT;
11576#endif // WIN32
11577 ImVec2 button_size = ImVec2(25 * scale, 25 * scale); // ORCA: Use exact resolution will prevent blur on icon
11578
11579 float same_line_width = button_size.x * 1.8; // with an space size
11580 ImGui::SameLine(same_line_width);
11581 same_line_width = imgui_wrapper->calc_text_size("|"sv).x + same_line_width + imgui_wrapper->calc_text_size(" "sv).x;
11582 imgui_wrapper->text_colored(ImGuiWrapper::COL_ACTIVE, "|");
11583 ImGui::SameLine(same_line_width);
11584
11585 return same_line_width; // return the width of the space taken by the tooltip button and the separator
11586}
static const ImVec4 COL_ACTIVE
Definition ImGuiWrapper.hpp:400
void render_tooltip_button(ImGuiWrapper *imgui_wrapper, const GLCanvas3D &canvas, const std::vector< std::pair< wxString, wxString > > &shortcuts, float x, float y)
Definition GLGizmoUtils.cpp:48

References _L, _render_assembly_tooltip_button(), Slic3r::GUI::ImGuiWrapper::calc_text_size(), Slic3r::GUI::ImGuiWrapper::COL_ACTIVE, Slic3r::GUI::DPI_DEFAULT, Slic3r::GUI::get_dpi_for_window(), get_scale(), m_shortcuts_assembly_view, Slic3r::GUI::GLGizmoUtils::render_tooltip_button(), scale(), and Slic3r::GUI::ImGuiWrapper::text_colored().

Referenced by _render_assemble_control(), and _render_assembly_tooltip_button().

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

◆ _render_background()

void Slic3r::GUI::GLCanvas3D::_render_background ( )
private
8826{
8827 bool use_error_color = false;
8828 if (wxGetApp().is_editor()) {
8829 use_error_color = m_dynamic_background_enabled &&
8830 (current_printer_technology() != ptSLA || !m_volumes.empty());
8831
8832 if (!m_volumes.empty())
8833 use_error_color &= _is_any_volume_outside();
8834 else {
8835 //BBS: use current plater's bounding box
8836 //BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
8837 BoundingBoxf3 test_volume = (const_cast<GLCanvas3D*>(this))->_get_current_partplate_print_volume();
8838 const BoundingBoxf3& path_bounding_box = m_gcode_viewer.get_paths_bounding_box();
8839 if (empty(path_bounding_box))
8840 use_error_color = false;
8841 else
8842 //BBS: use previous result
8843 use_error_color = (test_volume.radius() > 0.0) ? m_toolpath_outside : false;
8844 //use_error_color &= (test_volume.radius() > 0.0) ? !test_volume.contains(path_bounding_box) : false;
8845 }
8846 }
8847
8848 // Draws a bottom to top gradient over the complete screen.
8850
8851 ColorRGBA background_color = m_is_dark ? DEFAULT_BG_LIGHT_COLOR_DARK : DEFAULT_BG_LIGHT_COLOR;
8852 ColorRGBA error_background_color = m_is_dark ? ERROR_BG_LIGHT_COLOR_DARK : ERROR_BG_LIGHT_COLOR;
8853 const ColorRGBA bottom_color = use_error_color ? error_background_color : background_color;
8854
8855 if (!m_background.is_initialized()) {
8856 m_background.reset();
8857
8858 GLModel::Geometry init_data;
8860 init_data.reserve_vertices(4);
8861 init_data.reserve_indices(6);
8862
8863 // vertices
8864 init_data.add_vertex(Vec2f(-1.0f, -1.0f), Vec2f(0.0f, 0.0f));
8865 init_data.add_vertex(Vec2f(1.0f, -1.0f), Vec2f(1.0f, 0.0f));
8866 init_data.add_vertex(Vec2f(1.0f, 1.0f), Vec2f(1.0f, 1.0f));
8867 init_data.add_vertex(Vec2f(-1.0f, 1.0f), Vec2f(0.0f, 1.0f));
8868
8869 // indices
8870 init_data.add_triangle(0, 1, 2);
8871 init_data.add_triangle(2, 3, 0);
8872
8873 m_background.init_from(std::move(init_data));
8874 }
8875
8876 GLShaderProgram* shader = wxGetApp().get_shader("background");
8877 if (shader != nullptr) {
8878 shader->start_using();
8879 shader->set_uniform("top_color", bottom_color);
8880 shader->set_uniform("bottom_color", bottom_color);
8881 m_background.render();
8882 shader->stop_using();
8883 }
8884
8886}
static Slic3r::ColorRGBA DEFAULT_BG_LIGHT_COLOR
Definition GLCanvas3D.cpp:194
static Slic3r::ColorRGBA ERROR_BG_LIGHT_COLOR
Definition GLCanvas3D.cpp:196
static Slic3r::ColorRGBA ERROR_BG_LIGHT_COLOR_DARK
Definition GLCanvas3D.cpp:197
static Slic3r::ColorRGBA DEFAULT_BG_LIGHT_COLOR_DARK
Definition GLCanvas3D.cpp:195
bool m_toolpath_outside
Definition GLCanvas3D.hpp:777
bool _is_any_volume_outside() const
Definition GLCanvas3D.cpp:12662
BoundingBoxf3 _get_current_partplate_print_volume()
Definition GLCanvas3D.cpp:1839
GLModel m_background
Definition GLCanvas3D.hpp:921
Eigen::Matrix< float, 2, 1, Eigen::DontAlign > Vec2f
Definition Point.hpp:64
bool empty(const BoundingBoxBase< PointType, PointsType > &bb)
Definition BoundingBox.hpp:273

References GLCanvas3D(), _get_current_partplate_print_volume(), _is_any_volume_outside(), _render_background(), Slic3r::GUI::GLModel::Geometry::add_triangle(), Slic3r::GUI::GLModel::Geometry::add_vertex(), current_printer_technology(), DEFAULT_BG_LIGHT_COLOR, DEFAULT_BG_LIGHT_COLOR_DARK, Slic3r::empty(), ERROR_BG_LIGHT_COLOR, ERROR_BG_LIGHT_COLOR_DARK, Slic3r::GUI::GLModel::Geometry::format, GL_DEPTH_TEST, glDisable, glEnable, glsafe, m_background, m_dynamic_background_enabled, m_gcode_viewer, m_is_dark, m_toolpath_outside, m_volumes, Slic3r::GUI::GLModel::Geometry::P2T2, Slic3r::ptSLA, Slic3r::BoundingBox3Base< PointType >::radius(), Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), and Slic3r::GUI::GLModel::Geometry::Triangles.

Referenced by _render_background(), and _render_scene().

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

◆ _render_bed()

void Slic3r::GUI::GLCanvas3D::_render_bed ( const Transform3d & view_matrix,
const Transform3d & projection_matrix,
bool bottom,
bool show_axes )
private
8889{
8890 float scale_factor = 1.0;
8891#if ENABLE_RETINA_GL
8892 scale_factor = m_retina_helper->get_scale_factor();
8893#endif // ENABLE_RETINA_GL
8894
8895 /*
8896 bool show_texture = ! bottom ||
8897 (m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
8898 && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
8899 && m_gizmos.get_current_type() != GLGizmosManager::Hollow
8900 && m_gizmos.get_current_type() != GLGizmosManager::Seam
8901 && m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation
8902 && m_gizmos.get_current_type() != GLGizmosManager::FuzzySkin);
8903 */
8904 //bool show_texture = true;
8905 //BBS set axes mode
8906 if (m_design_canvas) {
8907 // Design tab: triad at the bed centre = modeling origin (set every frame because
8908 // set_shape/set_axes_mode otherwise reset it to the bed corner).
8909 const Vec2d bc = m_bed.build_volume().bed_center();
8910 m_bed.set_axes_origin(Vec3d(bc.x(), bc.y(), 0.0));
8911 } else {
8912 // With the other plates hidden, the axes go to the current plate as in Preview.
8913 m_bed.set_axes_mode(m_main_toolbar.is_enabled() && !_hides_inactive_plates());
8914 }
8915 m_bed.render(*this, view_matrix, projection_matrix, bottom, scale_factor, show_axes);
8916}
bool _hides_inactive_plates() const
Definition GLCanvas3D.cpp:8996

References _hides_inactive_plates(), _render_bed(), m_bed, m_design_canvas, and m_main_toolbar.

Referenced by _render_bed(), and _render_scene().

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

◆ _render_below_plate_volumes()

void Slic3r::GUI::GLCanvas3D::_render_below_plate_volumes ( )
private
8926{
8927 if (!_is_below_plate_view_active() || m_volumes.empty())
8928 return;
8929
8930 GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
8931 if (shader == nullptr)
8932 return;
8933
8934 const Camera& camera = wxGetApp().plater()->get_camera();
8935 const Transform3d& view_matrix = camera.get_view_matrix();
8936 const Transform3d& proj_matrix = camera.get_projection_matrix();
8937 const int object_idx = m_selection.get_object_idx();
8938 const int instance_idx = m_selection.get_instance_idx();
8939
8940 // Depth test stays on so whatever is already in the depth buffer hides the ghost; depth writes
8941 // are off and back faces are culled, so each pixel blends only the near surface once.
8942 const GLboolean cull_face = ::glIsEnabled(GL_CULL_FACE);
8949
8950 shader->start_using();
8951 // Keep z <= SINKING_Z_THRESHOLD, the complement of the clip the painting gizmo applies.
8952 shader->set_uniform("z_range", std::array<float, 2>{ -FLT_MAX, float(SINKING_Z_THRESHOLD) });
8953 shader->set_uniform("clipping_plane", m_volumes.get_clipping_plane());
8954 shader->set_uniform("use_color_clip_plane", false);
8955 shader->set_uniform("is_outline", false);
8956 shader->set_uniform("slope.actived", false);
8957 shader->set_uniform("print_volume.type", -1);
8958 shader->set_uniform("extruder_printable_heights", std::array<float, 3>{ 0.0f, 0.0f, 0.0f });
8959 shader->set_uniform("shadow_intensity", 0.0f);
8960
8961 // simple_render() needs these to reach the plain surface; with ban_color_volume it ignores both.
8962 ModelObjectPtrs& model_objects = wxGetApp().model().objects;
8963 std::vector<ColorRGBA> extruder_colors = wxGetApp().plater()->get_extruders_colors();
8964
8965 for (GLVolume* volume : m_volumes.volumes) {
8966 // is_active cannot gate this pass: the color painter marks the whole instance inactive and
8967 // draws it in its own gizmo pass. The instance and print-part checks below are what pick
8968 // this ghost out of the scene.
8969 if (volume->object_idx() != object_idx || volume->instance_idx() != instance_idx ||
8970 volume->is_modifier || volume->is_wipe_tower || volume->volume_idx() < 0)
8971 continue;
8972
8973 volume->set_render_color();
8974 ColorRGBA color = volume->render_color;
8975 color.a(0.5f);
8976 volume->model.set_color(color);
8977
8978 const Transform3d model_matrix = volume->world_matrix();
8979 shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
8980 shader->set_uniform("projection_matrix", proj_matrix);
8981 shader->set_uniform("volume_world_matrix", model_matrix);
8982 const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
8983 shader->set_uniform("view_normal_matrix", view_normal_matrix);
8984 // Painted facets would send render() through the MMU segmentation sub-models, which carry
8985 // their own opaque filament colours; the ghost draws the plain surface so the alpha holds.
8986 volume->simple_render(shader, model_objects, extruder_colors, false, true);
8987 }
8988 shader->stop_using();
8989
8992 if (cull_face == GL_FALSE)
8994}
bool _is_below_plate_view_active() const
Definition GLCanvas3D.cpp:8918
#define GL_TRUE
Definition gl.h:1892
#define glCullFace
Definition gl.h:3555
#define GL_SRC_ALPHA
Definition gl.h:1621
#define GL_BACK
Definition gl.h:266
#define GL_CULL_FACE
Definition gl.h:500
#define glDepthMask
Definition gl.h:3595
unsigned char GLboolean
Definition gl.h:2055
#define GL_ONE_MINUS_SRC_ALPHA
Definition gl.h:1239
#define GL_FALSE
Definition gl.h:648
#define glIsEnabled
Definition gl.h:4165
#define glBlendFunc
Definition gl.h:3325
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13
static const float SINKING_Z_THRESHOLD
Definition Model.hpp:1967
Eigen::Matrix< double, 3, 3, Eigen::DontAlign > Matrix3d
Definition Point.hpp:86

References _is_below_plate_view_active(), _render_below_plate_volumes(), Slic3r::ColorRGBA::a(), camera, GL_BACK, GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TRUE, glBlendFunc, glCullFace, glDepthMask, glDisable, glEnable, glIsEnabled, glsafe, Slic3r::GLVolume::instance_idx(), m_selection, m_volumes, Slic3r::GLVolume::model, Slic3r::GLVolume::object_idx(), Slic3r::GLVolume::render_color, Slic3r::GUI::GLModel::set_color(), Slic3r::GLVolume::set_render_color(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLVolume::simple_render(), Slic3r::SINKING_Z_THRESHOLD, Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), Slic3r::GLVolume::volume_idx(), and Slic3r::GLVolume::world_matrix().

Referenced by _render_below_plate_volumes(), and _render_scene().

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

◆ _render_cad_grid()

void Slic3r::GUI::GLCanvas3D::_render_cad_grid ( const Transform3d & view_matrix,
const Transform3d & projection_matrix )
private
9092{
9093 const BuildVolume& build_volume = m_bed.build_volume();
9094 if (!build_volume.valid())
9095 return;
9096
9097 const Vec2d center = build_volume.bed_center();
9098 const BoundingBoxf bb = build_volume.bounding_volume2d();
9101 m_cad_grid_bb = bb;
9102 m_cad_grid_valid = true;
9103
9104 // Same z as PartPlate::GROUND_Z_GRIDLINE (-0.26f): just below the bed fill (GROUND_Z =
9105 // -0.03f, which is drawn with the depth mask disabled) and above the physical bed model
9106 // (offset z = -0.41), so the grid never z-fights the bed quad. Chosen by construction,
9107 // not by magic number: it is the exact z the plate grid already uses on the shared bed.
9108 const float z = -0.26f;
9109
9110 auto build_grid = [&z, &center, &bb](double step, GLModel& model) {
9111 std::vector<std::pair<Vec2d, Vec2d>> segs;
9112 // Constant-x (vertical on screen) lines, both directions from the centre so the
9113 // centre column itself is always present. Clipped to the bed bounding box so nothing
9114 // spills past the bed quad.
9115 for (double x = center.x(); x >= bb.min.x(); x -= step)
9116 segs.emplace_back(Vec2d(x, bb.min.y()), Vec2d(x, bb.max.y()));
9117 for (double x = center.x() + step; x <= bb.max.x(); x += step)
9118 segs.emplace_back(Vec2d(x, bb.min.y()), Vec2d(x, bb.max.y()));
9119 // Constant-y (horizontal on screen) lines, same centre-first convention.
9120 for (double y = center.y(); y >= bb.min.y(); y -= step)
9121 segs.emplace_back(Vec2d(bb.min.x(), y), Vec2d(bb.max.x(), y));
9122 for (double y = center.y() + step; y <= bb.max.y(); y += step)
9123 segs.emplace_back(Vec2d(bb.min.x(), y), Vec2d(bb.max.x(), y));
9124
9125 GLModel::Geometry data;
9127 data.reserve_vertices(2 * segs.size());
9128 data.reserve_indices(2 * segs.size());
9129 for (const auto& s : segs) {
9130 data.add_vertex(Vec3f(float(s.first.x()), float(s.first.y()), z));
9131 data.add_vertex(Vec3f(float(s.second.x()), float(s.second.y()), z));
9132 const unsigned int vc = static_cast<unsigned int>(data.vertices_count());
9133 data.add_line(vc - 2, vc - 1);
9134 }
9135 model.init_from(std::move(data));
9136 };
9137
9138 m_cad_grid_minor.reset();
9139 m_cad_grid_major.reset();
9140 build_grid(10.0, m_cad_grid_minor);
9141 build_grid(50.0, m_cad_grid_major);
9142 }
9143
9144 if (!m_cad_grid_minor.is_initialized() || !m_cad_grid_major.is_initialized())
9145 return;
9146
9147 GLShaderProgram* shader = wxGetApp().get_shader("flat");
9148 if (shader == nullptr)
9149 return;
9150
9151 shader->start_using();
9154 shader->set_uniform("view_model_matrix", view_matrix);
9155 shader->set_uniform("projection_matrix", projection_matrix);
9156
9157 // White every 5 cm, grey every 1 cm — the SAME in both themes, deliberately. There is no
9158 // "white bed" to vanish against: the plate is dark grey either way, DEFAULT_MODEL_COLOR
9159 // {0.326,0.337,0.337} on light and DEFAULT_MODEL_COLOR_DARK {0.255,0.255,0.283} on dark
9160 // (3DBed.cpp:185-186), a difference of 0.07. A per-theme palette here would be a branch
9161 // that buys nothing and one more thing to keep in step.
9162 //
9163 // For contrast with what this replaces: the plate's own grid uses LINE_TOP_DARK_COLOR, a
9164 // 0.43 grey, for BOTH its thin and its bold family — which is most of why the stock grid
9165 // reads as a flat mesh with no scale to it.
9166 const ColorRGBA minor_color(0.40f, 0.40f, 0.42f, 1.0f);
9167 const ColorRGBA major_color(0.90f, 0.90f, 0.90f, 1.0f);
9168
9169 glsafe(::glLineWidth(1.0f));
9170 m_cad_grid_minor.set_color(minor_color);
9171 m_cad_grid_minor.render();
9172
9173 glsafe(::glLineWidth(2.0f));
9174 m_cad_grid_major.set_color(major_color);
9175 m_cad_grid_major.render();
9176
9178}
Vec2d m_cad_grid_center
Definition GLCanvas3D.hpp:696
bool m_cad_grid_valid
Definition GLCanvas3D.hpp:697
GLModel m_cad_grid_major
Definition GLCanvas3D.hpp:692
GLModel m_cad_grid_minor
Definition GLCanvas3D.hpp:691
BoundingBoxf m_cad_grid_bb
Definition GLCanvas3D.hpp:695
#define glLineWidth
Definition gl.h:4215
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
Eigen::Matrix< float, 3, 1, Eigen::DontAlign > Vec3f
Definition Point.hpp:65
void step(Coord &crd, const Dir d, const long n=1)
Definition MarchingSquares.hpp:213

References _render_cad_grid(), Slic3r::GUI::GLModel::Geometry::add_line(), Slic3r::GUI::GLModel::Geometry::add_vertex(), Slic3r::BuildVolume::bed_center(), Slic3r::BuildVolume::bounding_volume2d(), Slic3r::center(), Slic3r::GUI::GLModel::Geometry::format, GL_BLEND, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glDisable, glEnable, glLineWidth, glsafe, Slic3r::GUI::GLModel::Geometry::Lines, m_bed, m_cad_grid_bb, m_cad_grid_center, m_cad_grid_major, m_cad_grid_minor, m_cad_grid_valid, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::GUI::GLModel::Geometry::P3, Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), Slic3r::BuildVolume::valid(), and Slic3r::GUI::GLModel::Geometry::vertices_count().

Referenced by _render_cad_grid(), and _render_scene().

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

◆ _render_canvas_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_canvas_toolbar ( )
private
11012{
11013 ImGuiWrapper &imgui = *wxGetApp().imgui();
11014 float sc = get_scale();
11015
11016 #ifdef WIN32
11017 const int dpi = get_dpi_for_window(wxGetApp().GetTopWindow());
11018 sc *= (float) dpi / (float) DPI_DEFAULT;
11019 #endif // WIN32
11020
11021 ImVec2 btn_size = ImVec2(CANVAS_TOOLBAR_BUTTON, CANVAS_TOOLBAR_BUTTON) * sc;
11022 ImVec2 margin = ImVec2(m_canvas_toolbar_pos[0] > 0 ? 0.f : (CANVAS_TOOLBAR_MARGIN * sc), CANVAS_TOOLBAR_MARGIN * sc);
11023 ImVec2 spacing = ImVec2(CANVAS_TOOLBAR_SPACING, CANVAS_TOOLBAR_SPACING) * sc;
11024 ImVec2 padding = ImVec2(CANVAS_TOOLBAR_PADDING, CANVAS_TOOLBAR_PADDING) * sc;
11025 Vec2i32 pos = {
11026 m_canvas_toolbar_pos[0] + margin.x,
11027 get_canvas_size().get_height() - margin.y
11028 };
11029 bool zoom_btn = wxGetApp().show_canvas_zoom_button();
11030
11031 imgui.set_next_window_pos(pos[0], pos[1], ImGuiCond_Always, 0, 1); // pivot bottom-left
11032
11033 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0 );
11034 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding , {0,0});
11035 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing , {0,0});
11036 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding , padding); // without padding images clipping
11037
11038 imgui.begin(_L("Canvas Toolbar"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove |
11039 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollWithMouse);//
11040
11041 // Section view, on top so its panel opens above the toolbar.
11042 const bool section_view = is_section_view_active();
11043 ImTextureID s_normal_id = m_gizmos.get_icon_texture_id(section_view ?
11046 ImTextureID s_hover_id = m_gizmos.get_icon_texture_id(section_view ?
11049
11050 if (ImGui::ImageButton3(s_normal_id, s_hover_id, btn_size))
11051 m_section_view->panel_open = !m_section_view->panel_open;
11052 else if (ImGui::IsItemHovered()) {
11053 if (const float wheel = ImGui::GetIO().MouseWheel; wheel != 0.f)
11054 set_section_view_ratio(get_section_view_ratio() + (wheel < 0.f ? -0.01 : 0.01));
11055 if (ImGui::IsMouseClicked(ImGuiMouseButton_Right))
11057 else if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle))
11059 imgui.tooltip(_L("Section view"), ImGui::GetFontSize() * 20.0f);
11060 }
11061 const ImVec2 section_panel_pos = ImGui::GetItemRectMin() - ImVec2(0.f, spacing.y);
11062
11063 ImGui::Dummy({ 0, spacing.y});
11064
11067
11068 if (ImGui::ImageButton3(m_normal_id, m_hover_id, btn_size)) {
11069 if(!ImGui::IsPopupOpen("CanvasToolbarMenu")){
11070 ImGui::SetNextWindowPos(ImVec2(pos[0] + padding.x, pos[1] - padding.y - (zoom_btn ? (btn_size.y + spacing.y) : 0.f)), ImGuiCond_Always, ImVec2(0, 1)); // pivot bottom-left
11071 ImGui::OpenPopup("CanvasToolbarMenu");
11072 }
11073 }
11074
11075 if(zoom_btn){
11076 ImGui::Dummy({ 0, spacing.y});
11077
11080
11081 if (ImGui::ImageButton3(z_normal_id, z_hover_id, btn_size)) {
11082#ifdef SLIC3R_CAD
11083 // The Design tab selects and sketches outside the canvas's selection and volumes, so
11084 // it names what to frame. Framed along the current view, which is often square to a
11085 // sketch plane; an empty tab falls through to the bed.
11086 const BoundingBoxf3 design_box = m_design_sketch_tool != nullptr ? m_design_sketch_tool->fit_box(m_volumes) : BoundingBoxf3();
11087 if (design_box.defined)
11088 _zoom_to_box(design_box);
11089 else
11090#endif
11091 {
11092 select_view("plate");
11093 if (m_selection.is_empty()) {
11096 else
11097 zoom_to_bed();
11098 } else {
11100 }
11101 }
11102 } else if (ImGui::IsItemHovered()) {
11103 auto tooltip_str_wx = _L("Fit camera to scene or selected object.");
11104 std::string tooltip_str = tooltip_str_wx.ToUTF8().data();
11105
11106 float width = ImGui::CalcTextSize(tooltip_str.c_str()).x + imgui.scaled(2.0f);
11107 imgui.tooltip(tooltip_str, width);
11108 }
11109 }
11110
11111 ImGui::PopStyleVar(4); // Window
11112
11113 ImGui::PushStyleColor(ImGuiCol_PopupBg , m_is_dark ? ImGuiWrapper::COL_TOOLBAR_BG_DARK : ImGuiWrapper::COL_TOOLBAR_BG);
11114 ImGui::PushStyleColor(ImGuiCol_Separator , m_is_dark ? ImVec4(1, 1, 1, .20f) : ImVec4(0, 0, 0, .2f));
11115 ImGui::PushStyleColor(ImGuiCol_Text , m_is_dark ? ImVec4(1, 1, 1, .88f) : ImVec4(50 / 255.f, 58 / 255.f, 61 / 255.f, 1.f));
11116 ImGui::PushStyleColor(ImGuiCol_TextDisabled , m_is_dark ? ImVec4(1, 1, 1, .44f) : ImVec4(50 / 255.f, 58 / 255.f, 61 / 255.f, .5f));
11117 ImGui::PushStyleColor(ImGuiCol_HeaderHovered , ImVec4(0, 0, 0, 0.f)); // bg color for menu item
11118 ImGui::PushStyleColor(ImGuiCol_BorderActive , ImGuiWrapper::COL_ORCA);
11119 ImGui::PushStyleVar(ImGuiStyleVar_PopupBorderSize, 0.f );
11120 ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding , 8.f * sc);
11121 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f * sc);
11122 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding , 2.f * sc);
11123 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding , ImVec2(4.f, 10.f) * sc);
11124 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing , ImVec2(0.f, 8.f ) * sc);
11125
11126 if (ImGui::BeginPopup("CanvasToolbarMenu", ImGuiWindowFlags_NoMove)) {
11127 ImGui::PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true);
11128
11129 Plater* p = wxGetApp().plater();
11130 AppConfig* cfg = wxGetApp().app_config;
11131
11132 auto create_menu_item = [sc](
11133 const std::string& name,
11134 bool enable,
11135 bool condition,
11136 const std::function<void()>& action
11137 ) {
11138 ImGui::Dummy({2.f * sc,0});
11139 ImGui::SameLine();
11140 if (ImGui::BBLMenuItem((" " + _u8L(name)).c_str(), nullptr, false, enable, ImGui::CalcTextSize(_u8L(name).c_str()).y))
11141 action();
11142 ImGui::SameLine(12.f * sc);
11143 ImGui::TextColored(enable ? ImVec4(1,1,1,1) : ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled), "%s", into_u8(condition ? ImGui::VisibleIcon : ImGui::HiddenIcon).c_str());
11144 };
11145
11146
11147 create_menu_item( _utf8(L("3D Navigator")),
11148 m_canvas_type != ECanvasType::CanvasAssembleView, // not work on assembly
11149 wxGetApp().show_3d_navigator(),
11150 []{
11151 wxGetApp().toggle_show_3d_navigator();
11152 ImGui::CloseCurrentPopup(); // Close popup to show changes on UI
11153 }
11154 );
11155
11156 create_menu_item( _utf8(L("Zoom button")),
11157 true, // work on all
11158 wxGetApp().show_canvas_zoom_button(),
11159 []{
11160 wxGetApp().toggle_canvas_zoom_button();
11161 ImGui::CloseCurrentPopup(); // Close popup to show changes on UI
11162 }
11163 );
11164
11165 ImGui::Separator();
11166
11167 create_menu_item( _utf8(L("Overhangs")),
11168 m_canvas_type == ECanvasType::CanvasView3D, // work only on prepare
11169 p->is_view3D_overhang_shown(),
11170 [p]{p->show_view3D_overhang(!p->is_view3D_overhang_shown());}
11171 );
11172
11173 create_menu_item( _utf8(L("Outline")),
11174 m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
11175 wxGetApp().show_outline(),
11176 []{wxGetApp().toggle_show_outline();}
11177 );
11178
11179 create_menu_item( _utf8(L("Wireframe")),
11180 m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
11181 p->is_show_wireframe(),
11182 [this, p]{p->toggle_show_wireframe(); m_dirty = true;}
11183 );
11184
11185 // TRN View toggle that draws models see-through, so hidden parts show.
11186 create_menu_item( _utf8(L("X-Ray")),
11187 m_canvas_type != ECanvasType::CanvasPreview, // not work on preview
11188 p->is_show_xray(),
11189 [this, p]{p->toggle_show_xray(); m_dirty = true;}
11190 );
11191
11192 create_menu_item( _utf8(L("Realistic View")),
11193 true, // work on all
11194 cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE),
11195 [&cfg]{
11196 cfg->set_bool(SETTING_OPENGL_REALISTIC_MODE, !cfg->get_bool(SETTING_OPENGL_REALISTIC_MODE));
11197 cfg->save();
11198 }
11199 );
11200
11201 ImGui::Separator();
11202
11203 create_menu_item( _utf8(L("Perspective")),
11204 true, // work on all
11205 cfg->get_bool("use_perspective_camera"),
11206 [&cfg]{
11207 cfg->set_bool("use_perspective_camera", !(cfg->get_bool("use_perspective_camera")));
11208 wxGetApp().update_ui_from_settings();
11209 }
11210 );
11211
11212 ImGui::Separator();
11213
11214 create_menu_item( _utf8(L("Axes")),
11215 m_canvas_type != ECanvasType::CanvasAssembleView, // not work on assembly
11217 [this]{toggle_world_axes_visibility(false);}
11218 );
11219
11220 create_menu_item( _utf8(L("Gridlines")),
11221 m_canvas_type != ECanvasType::CanvasAssembleView, // not work on assembly
11222 wxGetApp().show_plate_gridlines(),
11223 []{wxGetApp().toggle_show_plate_gridlines();}
11224 );
11225
11226 create_menu_item( _utf8(L("Focus mode")),
11227 m_canvas_type == ECanvasType::CanvasView3D && !m_design_canvas, // work only on prepare
11228 wxGetApp().focus_mode(),
11229 [this]{
11230 wxGetApp().toggle_focus_mode();
11231 if (wxGetApp().focus_mode())
11233 m_dirty = true;
11234 }
11235 );
11236
11237 ImGui::Separator();
11238
11239 create_menu_item( _utf8(L("Labels")),
11240 m_canvas_type == ECanvasType::CanvasView3D, // work only on prepare
11241 p->are_view3D_labels_shown(),
11242 [p]{p->show_view3D_labels(!p->are_view3D_labels_shown());}
11243 );
11244
11245 create_menu_item( _utf8(L("Center of mass")),
11246 m_canvas_type != ECanvasType::CanvasAssembleView && !m_design_canvas, // work on prepare and preview
11247 wxGetApp().show_center_of_mass(),
11248 [this]{wxGetApp().toggle_show_center_of_mass(); m_dirty = true;}
11249 );
11250
11251 // Belt printers, G-code preview only: show the raw machine-frame G-code instead of
11252 // the designed (upright) view. This menu is the only place the toggle lives (plus
11253 // its shortcut); the reload is deferred (CallAfter) so the preview is not rebuilt
11254 // mid-render.
11255 if (m_canvas_type == ECanvasType::CanvasPreview && m_gcode_viewer.is_belt_view()) {
11256 ImGui::Separator();
11257 create_menu_item( _utf8(L("Show raw G-code (belt only)")),
11258 true,
11259 !m_gcode_viewer.is_belt_show_designed(), // eye lit = raw machine-frame G-code (designed view off)
11260 [this, p]{
11261 m_gcode_viewer.toggle_belt_show_designed();
11262 p->CallAfter([p]{ p->refresh_belt_view(); });
11263 }
11264 );
11265 }
11266
11267 ImGui::PopItemFlag();
11268 ImGui::EndPopup();
11269 }
11270
11271 ImGui::PopStyleColor(6);
11272 ImGui::PopStyleVar(6);
11273
11274 imgui.end();
11275
11276 _render_section_view_panel(section_panel_pos);
11277}
#define REQUIRES_ZOOM_TO_CUR_PLATE
Definition Camera.hpp:20
void set_section_view_ratio(double ratio)
Definition GLCanvas3D.cpp:1987
double get_section_view_ratio() const
Definition GLCanvas3D.hpp:1061
bool is_section_view_active() const
Definition GLCanvas3D.hpp:1060
void toggle_world_axes_visibility(bool force_show=false)
Definition GLCanvas3D.cpp:2023
void select_view(const std::string &direction)
Definition GLCanvas3D.cpp:2396
void zoom_to_volumes()
Definition GLCanvas3D.cpp:2353
void toggle_section_view()
Definition GLCanvas3D.cpp:2003
void zoom_to_bed()
Definition GLCanvas3D.cpp:2345
void align_section_view_to_camera()
Definition GLCanvas3D.cpp:2009
void _zoom_to_box(const BoundingBoxf3 &box, double margin_factor=DefaultCameraZoomToBoxMarginFactor)
Definition GLCanvas3D.cpp:7935
void _render_section_view_panel(const ImVec2 &bottom_left)
Definition GLCanvas3D.cpp:11279
void zoom_to_selection()
Definition GLCanvas3D.cpp:2360
void zoom_to_plate(int plate_idx=-1)
Definition GLCanvas3D.cpp:2371
bool m_show_world_axes
Definition GLCanvas3D.hpp:826
@ IC_CANVAS_SECTION_ACTIVE
Definition GLGizmosManager.hpp:200
@ IC_CANVAS_SECTION_DARK_HOVER
Definition GLGizmosManager.hpp:199
@ IC_CANVAS_MENU_DARK_HOVER
Definition GLGizmosManager.hpp:191
@ IC_CANVAS_SECTION_ACTIVE_DARK
Definition GLGizmosManager.hpp:202
@ IC_CANVAS_ZOOM_DARK
Definition GLGizmosManager.hpp:194
@ IC_CANVAS_MENU
Definition GLGizmosManager.hpp:188
@ IC_CANVAS_MENU_DARK
Definition GLGizmosManager.hpp:190
@ IC_CANVAS_SECTION_ACTIVE_HOVER
Definition GLGizmosManager.hpp:201
@ IC_CANVAS_SECTION_HOVER
Definition GLGizmosManager.hpp:197
@ IC_CANVAS_SECTION_DARK
Definition GLGizmosManager.hpp:198
@ IC_CANVAS_ZOOM_HOVER
Definition GLGizmosManager.hpp:193
@ IC_CANVAS_SECTION_ACTIVE_DARK_HOVER
Definition GLGizmosManager.hpp:203
@ IC_CANVAS_MENU_HOVER
Definition GLGizmosManager.hpp:189
@ IC_CANVAS_ZOOM
Definition GLGizmosManager.hpp:192
@ IC_CANVAS_ZOOM_DARK_HOVER
Definition GLGizmosManager.hpp:195
@ IC_CANVAS_SECTION
Definition GLGizmosManager.hpp:196
static const ImVec4 COL_ORCA
Definition ImGuiWrapper.hpp:408
static const ImVec4 COL_TOOLBAR_BG_DARK
Definition ImGuiWrapper.hpp:405
static const ImVec4 COL_TOOLBAR_BG
Definition ImGuiWrapper.hpp:404
static constexpr float CANVAS_TOOLBAR_PADDING
Definition GLCanvas3D.cpp:2436
static constexpr float CANVAS_TOOLBAR_SPACING
Definition GLCanvas3D.cpp:2438
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
@ Plater
Definition Shortcuts.hpp:21
static constexpr float CANVAS_TOOLBAR_BUTTON
Definition GLCanvas3D.cpp:2437
static constexpr float CANVAS_TOOLBAR_MARGIN
Definition GLCanvas3D.cpp:2435
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16
Eigen::Matrix< int32_t, 2, 1, Eigen::DontAlign > Vec2i32
Definition Point.hpp:57

References _L, _render_canvas_toolbar(), _u8L, _utf8, _zoom_to_box(), align_section_view_to_camera(), Slic3r::GUI::Plater::are_view3D_labels_shown(), Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::CANVAS_TOOLBAR_BUTTON, Slic3r::GUI::CANVAS_TOOLBAR_MARGIN, Slic3r::GUI::CANVAS_TOOLBAR_PADDING, Slic3r::GUI::CANVAS_TOOLBAR_SPACING, CanvasAssembleView, CanvasPreview, CanvasView3D, Slic3r::GUI::ImGuiWrapper::COL_ORCA, Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG, Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG_DARK, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::defined, Slic3r::GUI::DPI_DEFAULT, Slic3r::AppConfig::get_bool(), get_canvas_size(), Slic3r::GUI::get_dpi_for_window(), get_scale(), get_section_view_ratio(), Slic3r::GUI::GLGizmosManager::IC_CANVAS_MENU, Slic3r::GUI::GLGizmosManager::IC_CANVAS_MENU_DARK, Slic3r::GUI::GLGizmosManager::IC_CANVAS_MENU_DARK_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_MENU_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_ACTIVE, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_ACTIVE_DARK, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_ACTIVE_DARK_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_ACTIVE_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_DARK, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_DARK_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_SECTION_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_ZOOM, Slic3r::GUI::GLGizmosManager::IC_CANVAS_ZOOM_DARK, Slic3r::GUI::GLGizmosManager::IC_CANVAS_ZOOM_DARK_HOVER, Slic3r::GUI::GLGizmosManager::IC_CANVAS_ZOOM_HOVER, Slic3r::into_u8(), is_section_view_active(), Slic3r::GUI::Plater::is_show_wireframe(), Slic3r::GUI::Plater::is_show_xray(), Slic3r::GUI::Plater::is_view3D_overhang_shown(), L, m_canvas_toolbar_pos, m_canvas_type, m_design_canvas, m_dirty, m_gcode_viewer, m_gizmos, m_is_dark, m_section_view, m_selection, m_show_world_axes, m_volumes, REQUIRES_ZOOM_TO_CUR_PLATE, Slic3r::GUI::ImGuiWrapper::scaled(), select_view(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), set_section_view_ratio(), SETTING_OPENGL_REALISTIC_MODE, toggle_section_view(), toggle_world_axes_visibility(), Slic3r::GUI::ImGuiWrapper::tooltip(), zoom_to_bed(), zoom_to_plate(), zoom_to_selection(), and zoom_to_volumes().

Referenced by _render_canvas_toolbar(), and _render_overlays().

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

◆ _render_collapse_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_collapse_toolbar ( ) const
private
11378{
11380 return;
11381
11382 const CollapseSide side = collapse_side();
11383 if (side == CollapseSide::None) {
11384 return;
11385 }
11386
11387 GLToolbar& collapse_toolbar = this->collapse_toolbar();
11388
11389 const Size cnv_size = get_canvas_size();
11390 const float top = 0.5f * (float)cnv_size.get_height();
11391 const float left = side == CollapseSide::Right ? 0.5f * (float) cnv_size.get_width() - (float) collapse_toolbar.get_width() :
11392 -0.5f * (float) cnv_size.get_width();
11393
11394 collapse_toolbar.set_position(top, left);
11395 collapse_toolbar.render(*this);
11396}
bool m_collapse_toolbar_enabled
Definition GLCanvas3D.hpp:672
CollapseSide
Definition GLToolbar.hpp:462

References _render_collapse_toolbar(), collapse_side(), collapse_toolbar(), get_canvas_size(), Slic3r::GUI::Size::get_height(), Slic3r::GUI::Size::get_width(), m_collapse_toolbar_enabled, Slic3r::GUI::None, and Slic3r::GUI::Right.

Referenced by _render_collapse_toolbar(), and _render_overlay_toolbars().

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

◆ _render_current_gizmo()

void Slic3r::GUI::GLCanvas3D::_render_current_gizmo ( ) const
private
10303{
10304 //BBS update inv_zoom
10305 GLGizmoBase::INV_ZOOM = (float)wxGetApp().plater()->get_camera().get_inv_zoom();
10306 m_gizmos.render_current_gizmo();
10307}
static float INV_ZOOM
Definition GLGizmoBase.hpp:54

References _render_current_gizmo(), Slic3r::GUI::GLGizmoBase::INV_ZOOM, and m_gizmos.

Referenced by _render_current_gizmo(), and _render_scene().

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

◆ _render_fps_overlay()

void Slic3r::GUI::GLCanvas3D::_render_fps_overlay ( int fps) const
private
8607{
8608 const bool show_fps = _is_fps_overlay_enabled() && fps >= 0;
8609 const std::vector<FrameProfiler::Section>& sections = m_frame_profiler.sections();
8610 const bool show_timings = _is_render_timings_enabled() && !sections.empty();
8611 if (!show_fps && !show_timings)
8612 return;
8613
8614 ImGuiWrapper& imgui = *wxGetApp().imgui();
8615 const float margin = 10.0f * get_scale();
8616 const ImVec2 display_size = ImGui::GetIO().DisplaySize;
8617 ImVec2 pos(display_size.x - margin, margin);
8618 // Last frame's size; zero until the overlay has been shown once.
8619 const ImGuiWindow* self = ImGui::FindWindowByName("###fps_overlay");
8620 const float left = pos.x - (self != nullptr ? self->Size.x : 0.0f);
8621 // The Preview legend takes the top-right corner.
8622 if (const ImGuiWindow* legend = ImGui::FindWindowByName("Legend"); m_canvas_type == ECanvasType::CanvasPreview && legend != nullptr && legend->Active)
8623 pos = ImVec2(legend->Pos.x - margin, legend->Pos.y);
8624 // The toolbar row can reach the corner on a narrow canvas; stack the overlay below it then.
8625 else if (m_main_toolbar.is_enabled() &&
8626 get_main_toolbar_offset() + m_main_toolbar.get_width() + m_separator_toolbar.get_width() + m_gizmos.get_scaled_total_width() + m_assemble_view_toolbar.get_width() > left)
8627 pos.y = std::max(m_main_toolbar.get_height(), m_gizmos.get_scaled_total_height()) + margin;
8628 ImGui::SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(1.0f, 0.0f));
8629 ImGui::SetNextWindowBgAlpha(0.35f);
8630 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f * get_scale());
8631 imgui.begin(
8632 std::string("###fps_overlay"),
8633 ImGuiWindowFlags_AlwaysAutoResize |
8634 ImGuiWindowFlags_NoResize |
8635 ImGuiWindowFlags_NoCollapse |
8636 ImGuiWindowFlags_NoTitleBar |
8637 ImGuiWindowFlags_NoMove |
8638 ImGuiWindowFlags_NoSavedSettings |
8639 ImGuiWindowFlags_NoInputs);
8640 if (show_fps) {
8641 imgui.text(std::string("FPS: ") + std::to_string(fps));
8642 ImGui::SameLine();
8643 // The subset of those frames that redrew the scene rather than reusing the cached one.
8644 imgui.text(std::string("3D: ") + std::to_string(m_render_stats.get_scene_fps()));
8645 }
8646 if (show_timings && ImGui::BeginTable("frame_sections", 3, ImGuiTableFlags_SizingFixedFit)) {
8647 ImGui::TableSetupColumn("ms");
8648 ImGui::TableSetupColumn("CPU");
8649 ImGui::TableSetupColumn("GPU");
8650 ImGui::TableHeadersRow();
8651 double cpu_ms = 0.0;
8652 double gpu_ms = 0.0;
8653 auto row = [](const char* name, double cpu, double gpu) {
8654 ImGui::TableNextRow();
8655 ImGui::TableSetColumnIndex(0);
8656 ImGui::TextUnformatted(name);
8657 ImGui::TableSetColumnIndex(1);
8658 ImGui::Text("%.2f", cpu);
8659 ImGui::TableSetColumnIndex(2);
8660 ImGui::Text("%.2f", gpu);
8661 };
8662 for (const FrameProfiler::Section& section : sections) {
8663 row(section.name, section.cpu_ms, section.gpu_ms);
8664 cpu_ms += section.cpu_ms;
8665 gpu_ms += section.gpu_ms;
8666 }
8667 row("total", cpu_ms, gpu_ms);
8668 ImGui::EndTable();
8669 }
8670 imgui.end();
8671 ImGui::PopStyleVar();
8672}
bool _is_fps_overlay_enabled() const
Definition GLCanvas3D.cpp:8527
RenderStats m_render_stats
Definition GLCanvas3D.hpp:804
bool _is_render_timings_enabled() const
Definition GLCanvas3D.cpp:8571

References _is_fps_overlay_enabled(), _is_render_timings_enabled(), _render_fps_overlay(), Slic3r::GUI::ImGuiWrapper::begin(), CanvasPreview, Slic3r::GUI::ImGuiWrapper::end(), get_main_toolbar_offset(), get_scale(), m_assemble_view_toolbar, m_canvas_type, m_frame_profiler, m_gizmos, m_main_toolbar, m_render_stats, m_separator_toolbar, and Slic3r::GUI::ImGuiWrapper::text().

Referenced by _render_fps_overlay(), and _render_frame().

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

◆ _render_frame()

void Slic3r::GUI::GLCanvas3D::_render_frame ( bool scene_dirty,
bool only_init = false )
private
2488{
2489 if (m_in_render) {
2490 // if called recursively, return
2491 m_dirty = true;
2492 return;
2493 }
2494
2495 m_in_render = true;
2497 Slic3r::ScopeGuard in_render_guard([this]() { m_in_render = false; --s_frames_in_progress; });
2498 (void)in_render_guard;
2499
2500 if (m_canvas == nullptr)
2501 return;
2502
2503 //BBS: add enable_render
2504 if (!m_enable_render)
2505 return;
2506
2507 // ensures this canvas is current and initialized
2508 if (!_is_shown_on_screen() || !_set_current() || !wxGetApp().init_opengl())
2509 return;
2510
2511 if (!is_initialized() && !init())
2512 return;
2513
2514 // If a scene reload was postponed while the canvas was hidden, consume it on first visible render.
2515 if (m_reload_delayed) {
2516 reload_scene(true);
2517 if (m_reload_delayed)
2518 return;
2519 }
2520
2522 enable_return_toolbar(false);
2523 }
2524 if (!m_main_toolbar.is_enabled())
2525 m_gcode_viewer.init(wxGetApp().get_mode(), wxGetApp().preset_bundle);
2526
2527 if (! m_bed.build_volume().valid()) {
2528 // this happens at startup when no data is still saved under <>\AppData\Roaming\Slic3rPE
2529 post_event(SimpleEvent(EVT_GLCANVAS_UPDATE_BED_SHAPE));
2530 return;
2531 }
2532
2533 if (only_init)
2534 return;
2535
2536#if ENABLE_ENVIRONMENT_MAP
2537 if (wxGetApp().is_editor())
2538 wxGetApp().plater()->init_environment_texture();
2539#endif // ENABLE_ENVIRONMENT_MAP
2540
2541 const Size& cnv_size = get_canvas_size();
2542 // Probably due to different order of events on Linux/GTK2, when one switched from 3D scene
2543 // to preview, this was called before canvas had its final size. It reported zero width
2544 // and the viewport was set incorrectly, leading to tripping glAsserts further down
2545 // the road (in apply_projection). That's why the minimum size is forced to 10.
2546 Camera& camera = wxGetApp().plater()->get_camera();
2547 camera.set_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height()));
2548 camera.apply_viewport();
2549
2550 if (camera.requires_zoom_to_bed) {
2551 zoom_to_bed();
2552 _resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
2553 camera.requires_zoom_to_bed = false;
2554 }
2555
2556 if (camera.requires_zoom_to_plate > REQUIRES_ZOOM_TO_PLATE_IDLE) {
2557 zoom_to_plate(camera.requires_zoom_to_plate);
2558 _resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
2559 camera.requires_zoom_to_plate = REQUIRES_ZOOM_TO_PLATE_IDLE;
2560 }
2561
2562 if (camera.requires_zoom_to_volumes) {
2564 _resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
2565 camera.requires_zoom_to_volumes = false;
2566 }
2567
2568 camera.apply_projection(_max_bounding_box(true, true, true));
2569
2570 wxGetApp().imgui()->new_frame();
2571
2573 scene_dirty = true;
2574
2576 if (m_rectangle_selection.is_dragging())
2577 // picking pass using rectangle selection
2579 //BBS: enable picking when no volumes for partplate logic
2580 //else if (!m_volumes.empty())
2581 else {
2582 // regular picking pass
2583 _picking_pass();
2584
2585#if ENABLE_RAYCAST_PICKING_DEBUG
2586 ImGuiWrapper& imgui = *wxGetApp().imgui();
2587 imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
2588 imgui.text("Picking disabled");
2589 imgui.end();
2590#endif // ENABLE_RAYCAST_PICKING_DEBUG
2591 }
2592 }
2593
2594 const bool overlay_tick = m_fps_overlay_tick;
2595 m_fps_overlay_tick = false;
2596
2597 // An overlay-only frame reuses the last scene pass. The overlay is rebuilt either way, and drawn
2598 // below once it is known whether the frame differs from the one on screen.
2599 const bool reuse_scene = !scene_dirty && _can_reuse_cached_scene(camera);
2600 // Only frames that redraw the scene are profiled.
2601 if (!reuse_scene && (_is_render_timings_enabled() || m_frame_profiler.is_averaging()))
2602 m_frame_profiler.begin_frame();
2603 Slic3r::ScopeGuard profiler_guard([this]() { m_frame_profiler.end_frame(); });
2604 if (!reuse_scene) {
2605 _render_scene(camera, cnv_size);
2606 if (!overlay_tick)
2607 m_render_stats.increment_scene_fps_counter();
2608 }
2609
2611 // BBS: GUI refactor: add canvas size as parameters
2612 _render_gcode_overlay(cnv_size.get_width(), cnv_size.get_height());
2613 m_frame_profiler.mark("legend");
2614 }
2615
2616 // draw overlays
2618 m_frame_profiler.mark("ui");
2619
2620 const int current_fps = m_render_stats.get_fps_and_reset_if_needed();
2622 _render_fps_overlay(current_fps);
2624 // The timer requests an overlay-only frame a second from now. A frame it requested
2625 // re-arms it only while a count is above zero.
2626 if (!overlay_tick || current_fps > 0 || m_render_stats.get_scene_fps() > 0)
2627 m_fps_overlay_timer.StartOnce(1000);
2628 }
2629
2630 if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
2631 ImGui::ShowMetricsWindow();
2632
2633 ImGuiWrapper& imgui = *wxGetApp().imgui();
2634 imgui.begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
2635 imgui.text("FPS (SwapBuffers() calls per second):");
2636 ImGui::SameLine();
2637 imgui.text(std::to_string(current_fps));
2638 ImGui::Separator();
2639 imgui.text("Compressed textures:");
2640 ImGui::SameLine();
2641 imgui.text(OpenGLManager::are_compressed_textures_supported() ? "supported" : "not supported");
2642 imgui.text("Max texture size:");
2643 ImGui::SameLine();
2644 imgui.text(std::to_string(OpenGLManager::get_gl_info().get_max_tex_size()));
2645 imgui.end();
2646 }
2647
2648#if ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
2649 if (wxGetApp().is_editor() && wxGetApp().plater()->is_view3D_shown())
2650 wxGetApp().plater()->render_project_state_debug_window();
2651#endif // ENABLE_PROJECT_DIRTY_STATE_DEBUG_WINDOW
2652
2653#if ENABLE_CAMERA_STATISTICS
2654 camera.debug_render();
2655#endif // ENABLE_CAMERA_STATISTICS
2656
2657#if ENABLE_IMGUI_STYLE_EDITOR
2658 if (wxGetApp().get_mode() == ConfigOptionMode::comDevelop)
2660#endif
2661
2662
2663 std::string tooltip;
2664
2665 // Negative coordinate means out of the window, likely because the window was deactivated.
2666 // In that case the tooltip should be hidden.
2667 if ((m_mouse.position.x() >= 0. && m_mouse.position.y() >= 0.) || has_mouse_capture()) { // ORCA continue to capture mouse pos mid drag
2668 if (tooltip.empty())
2669 tooltip = m_layers_editing.get_tooltip(*this);
2670
2671 if (tooltip.empty())
2672 tooltip = m_gizmos.get_tooltip();
2673
2674 if (tooltip.empty())
2675 tooltip = m_main_toolbar.get_tooltip();
2676
2677 //BBS: GUI refactor: GLToolbar
2678 if (tooltip.empty())
2679 tooltip = m_assemble_view_toolbar.get_tooltip();
2680
2681 if (tooltip.empty())
2682 tooltip = collapse_toolbar().get_tooltip();
2683
2684 // BBS
2685#if 0
2686 if (tooltip.empty())
2687 tooltip = wxGetApp().plater()->get_view_toolbar().get_tooltip();
2688#endif
2689 }
2690
2691 // Suppress the regular object-name/toolbar tooltip while hovering an IMEX
2692 // ghost; the swatch overlay below stands in for it.
2693 if (m_hover_ghost_head >= 0)
2694 tooltip.clear();
2695
2696 set_tooltip(tooltip);
2697
2699 m_tooltip.render(m_mouse.position, *this);
2700
2701 // IMEX ghost hover overlay: layered on top of the normal tooltip pass.
2703
2704 wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
2705
2707 float right_margin = SLIDER_DEFAULT_RIGHT_MARGIN;
2708 float bottom_margin = SLIDER_DEFAULT_BOTTOM_MARGIN;
2709 if (m_canvas_type == ECanvasType::CanvasPreview && m_gcode_viewer.has_data()) { // ORCA only shift position of notifiations when sliders / gcode_viewer exist
2710 float scale_factor = get_scale();
2711#ifdef WIN32
2712 int dpi = get_dpi_for_window(wxGetApp().GetTopWindow());
2713 scale_factor *= (float) dpi / (float) DPI_DEFAULT;
2714#endif // WIN32
2715 right_margin = SLIDER_RIGHT_MARGIN * scale_factor * GCODE_VIEWER_SLIDER_SCALE;
2716 bottom_margin = SLIDER_BOTTOM_MARGIN * scale_factor * GCODE_VIEWER_SLIDER_SCALE;
2717 }
2718 wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin, right_margin);
2719 wxGetApp().plater()->get_dailytips()->render();
2720 }
2721 m_frame_profiler.mark("notifications");
2722
2723 ImDrawData* draw_data = wxGetApp().imgui()->end_frame();
2724
2725 std::optional<size_t> signature;
2727 signature = _overlay_signature(draw_data);
2728 m_frame_profiler.mark("imgui end");
2729
2730 if (reuse_scene) {
2731 // A reused scene under an unchanged overlay is the frame already on screen.
2732 if (signature.has_value() && signature == m_presented_signature)
2733 return;
2735 }
2736
2738 m_frame_profiler.mark("toolbars");
2739
2740 wxGetApp().imgui()->render(draw_data);
2741 m_frame_profiler.mark("imgui draw");
2742
2743 // On Wayland, eglSwapBuffers blocks when the canvas is hidden or
2744 // occluded. Skip the swap to avoid stalling the render loop.
2745 // Code run from inside this frame - a modal dialog a gizmo opened from its ImGui panel, a
2746 // synchronous paint of another canvas - may have made a different surface current. Bind this one
2747 // again before presenting, so the swap is not issued against a window the context no longer
2748 // belongs to: on Mesa/X11 that is a fatal BadMatch, not the no-op it is on other platforms. Draws
2749 // already issued before this point cannot be redirected - only this swap is protected.
2750 if (m_canvas->IsShownOnScreen() && _set_current()) {
2751 m_canvas->SwapBuffers();
2752 m_frame_profiler.mark("swap");
2753 if (!overlay_tick)
2754 m_render_stats.increment_fps_counter();
2755 m_presented_signature = signature;
2756 }
2757 else {
2758 if (m_canvas->IsShownOnScreen()) {
2759 // Logged once: if the rebind fails it does so every frame, and a warning per frame would
2760 // bury everything else.
2761 static bool rebind_failure_logged = false;
2762 if (!rebind_failure_logged) {
2763 rebind_failure_logged = true;
2764 BOOST_LOG_TRIVIAL(warning) << "GLCanvas3D: could not rebind the GL context to this canvas before "
2765 "SwapBuffers(); the frame is not presented";
2766 }
2767 }
2768 m_presented_signature.reset();
2769 }
2770}
#define REQUIRES_ZOOM_TO_PLATE_IDLE
Definition Camera.hpp:22
void set_tooltip(const std::string &tooltip)
Definition GLCanvas3D.cpp:5629
void _rectangular_selection_picking_pass()
Definition GLCanvas3D.cpp:8309
void reload_scene(bool refresh_immediately, bool force_full_scene_refresh=false)
Definition GLCanvas3D.cpp:3162
Tooltip m_tooltip
Definition GLCanvas3D.hpp:815
bool _can_reuse_cached_scene(const Camera &camera) const
Definition GLCanvas3D.cpp:8805
void _render_imex_ghost_tooltip()
Definition GLCanvas3D.cpp:8268
bool m_tooltip_enabled
Definition GLCanvas3D.hpp:816
BoundingBoxf3 _max_bounding_box(bool include_gizmos, bool include_bed_model, bool include_plates) const
Definition GLCanvas3D.cpp:7899
bool _update_inactive_plates_visibility()
Definition GLCanvas3D.cpp:9001
void _render_overlay_toolbars()
Definition GLCanvas3D.cpp:10142
void _picking_pass()
Definition GLCanvas3D.cpp:7959
void _render_scene(const Camera &camera, const Size &cnv_size)
Definition GLCanvas3D.cpp:2774
bool m_render_preview
Definition GLCanvas3D.hpp:750
bool has_mouse_capture() const
Definition GLCanvas3D.cpp:2341
void _render_gcode_overlay(int canvas_width, int canvas_height)
Definition GLCanvas3D.cpp:9949
void post_event(wxEvent &&event)
Definition GLCanvas3D.cpp:1691
bool _is_frame_skipping_enabled() const
Definition GLCanvas3D.cpp:8601
bool m_enable_render
Definition GLCanvas3D.hpp:751
void _render_style_editor()
Definition GLCanvas3D.cpp:10172
bool is_initialized() const
Definition GLCanvas3D.hpp:948
size_t _overlay_signature(const ImDrawData *draw_data) const
Definition GLCanvas3D.cpp:10159
void enable_return_toolbar(bool enable)
Definition GLCanvas3D.cpp:2315
bool init()
Definition GLCanvas3D.cpp:1697
float get_overlay_window_width()
Definition GLCanvas3D.hpp:1662
bool m_fps_overlay_tick
Definition GLCanvas3D.hpp:653
static int s_frames_in_progress
Definition GLCanvas3D.hpp:647
std::optional< size_t > m_presented_signature
Definition GLCanvas3D.hpp:931
void _render_fps_overlay(int fps) const
Definition GLCanvas3D.cpp:8606
void _render_overlays()
Definition GLCanvas3D.cpp:10087
@ Undefined
Definition GLGizmosManager.hpp:109
std::string get_tooltip() const
Definition GLToolbar.cpp:488
static bool are_compressed_textures_supported()
Definition OpenGLManager.hpp:99
static const GLInfo & get_gl_info()
Definition OpenGLManager.hpp:106
static const float SLIDER_RIGHT_MARGIN
Definition GCodeViewer.hpp:53
static const float SLIDER_DEFAULT_RIGHT_MARGIN
Definition GCodeViewer.hpp:50
static const float SLIDER_DEFAULT_BOTTOM_MARGIN
Definition GCodeViewer.hpp:51
static const float SLIDER_BOTTOM_MARGIN
Definition GCodeViewer.hpp:54
@ comDevelop
Definition Config.hpp:225

References _can_reuse_cached_scene(), _is_fps_overlay_enabled(), _is_frame_skipping_enabled(), _is_render_timings_enabled(), _is_shown_on_screen(), _max_bounding_box(), _overlay_signature(), _picking_pass(), _rectangular_selection_picking_pass(), _render_fps_overlay(), _render_gcode_overlay(), _render_imex_ghost_tooltip(), _render_overlay_toolbars(), _render_overlays(), _render_scene(), _render_style_editor(), _resize(), _set_current(), _update_inactive_plates_visibility(), Slic3r::GUI::OpenGLManager::are_compressed_textures_supported(), Slic3r::GUI::ImGuiWrapper::begin(), camera, CanvasAssembleView, CanvasPreview, CanvasView3D, collapse_toolbar(), Slic3r::comDevelop, Slic3r::GUI::DPI_DEFAULT, enable_return_toolbar(), Slic3r::GUI::ImGuiWrapper::end(), Slic3r::GUI::GCODE_VIEWER_SLIDER_SCALE, get_canvas_size(), Slic3r::GUI::get_dpi_for_window(), Slic3r::GUI::OpenGLManager::get_gl_info(), Slic3r::GUI::Size::get_height(), get_overlay_window_width(), get_scale(), Slic3r::GUI::GLToolbar::get_tooltip(), Slic3r::GUI::Size::get_width(), has_mouse_capture(), init(), is_initialized(), m_assemble_view_toolbar, m_background, m_bed, m_benchmarking, m_canvas, m_canvas_type, m_dirty, m_enable_render, m_fps_overlay_tick, m_fps_overlay_timer, m_frame_profiler, m_gcode_viewer, m_gizmos, m_hover_ghost_head, m_in_render, m_layers_editing, m_main_toolbar, m_mouse, m_picking_enabled, m_presented_signature, m_rectangle_selection, m_reload_delayed, m_render_preview, m_render_stats, m_scene_cache, m_tooltip, m_tooltip_enabled, Slic3r::GUI::plater(), post_event(), reload_scene(), REQUIRES_ZOOM_TO_PLATE_IDLE, s_frames_in_progress, set_tooltip(), Slic3r::GUI::SLIDER_BOTTOM_MARGIN, Slic3r::GUI::SLIDER_DEFAULT_BOTTOM_MARGIN, Slic3r::GUI::SLIDER_DEFAULT_RIGHT_MARGIN, Slic3r::GUI::SLIDER_RIGHT_MARGIN, Slic3r::GUI::ImGuiWrapper::text(), Slic3r::GUI::GLGizmosManager::Undefined, zoom_to_bed(), zoom_to_plate(), and zoom_to_volumes().

Referenced by _refresh_if_shown_on_screen(), on_mouse(), and render().

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

◆ _render_fxaa_pass()

void Slic3r::GUI::GLCanvas3D::_render_fxaa_pass ( unsigned int width,
unsigned int height )
private
8675{
8676 if (width == 0 || height == 0)
8677 return;
8678
8679 GLShaderProgram* shader = wxGetApp().get_shader("fxaa");
8680 if (shader == nullptr)
8681 return;
8682
8684
8688
8689 shader->start_using();
8690 shader->set_uniform("view_model_matrix", Transform3d::Identity());
8691 shader->set_uniform("projection_matrix", Transform3d::Identity());
8692 shader->set_uniform("uniform_texture", 0);
8693 shader->set_uniform("inv_tex_size", Vec2f(1.0f / static_cast<float>(width), 1.0f / static_cast<float>(height)));
8694
8697 m_background.render();
8699 shader->stop_using();
8700
8704}
std::array< unsigned int, 2 > m_fxaa_texture_size
Definition GLCanvas3D.hpp:923
static void copy_from_framebuffer(unsigned int &tex_id, std::array< unsigned int, 2 > &tex_size, unsigned int width, unsigned int height, int filter)
Definition GLTexture.cpp:756
#define GL_LINEAR
Definition gl.h:930

References _render_fxaa_pass(), Slic3r::GUI::GLTexture::copy_from_framebuffer(), GL_BLEND, GL_COLOR_BUFFER_BIT, GL_DEPTH_TEST, GL_LINEAR, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TEXTURE0, GL_TEXTURE_2D, glActiveTexture, glBindTexture, glBlendFunc, glClear, glDisable, glEnable, glsafe, m_background, m_fxaa_texture_id, m_fxaa_texture_size, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by _render_fxaa_pass(), and _render_scene().

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

◆ _render_gcode()

void Slic3r::GUI::GLCanvas3D::_render_gcode ( int canvas_width,
int canvas_height )
private
9909{
9910 // Realistic view: the toolpaths receive the same depth map they were rendered into by
9911 // _render_shadows, which is what gives them object-on-object and self shadows. Intensity 0
9912 // short-circuits the lookup in the shader, so this is inert whenever the map is missing.
9913 if (_bind_gcode_shadow_map(true))
9914 m_gcode_viewer.set_shadow_map(4, m_shadow_light_vp, 0.35f, 1.0f / static_cast<float>(m_shadow_map_size));
9915 else
9916 m_gcode_viewer.set_shadow_map(4, Transform3d::Identity(), 0.0f, 0.0f);
9917
9918 // The lighting term leaves the print dimmer and duller than the legend colours. Saturation
9919 // pays back the duller half in both modes; brightness only where something takes light off
9920 // again - realistic view with at least one lossy pass on - else the lift would just clip.
9921 const AppConfig* cfg = wxGetApp().app_config;
9922 const bool lossy_passes = cfg != nullptr && _is_realistic_view_enabled() &&
9924 m_gcode_viewer.set_tone(lossy_passes ? 1.1f : 1.0f, 1.15f);
9925 m_gcode_viewer.set_light_top_dir(_static_light_dir_eye().value_or(Vec3d(-0.4574957, 0.4574957, 0.7624929)));
9926 m_gcode_viewer.set_gloss(_is_realistic_view_enabled() && cfg != nullptr && cfg->get_bool(SETTING_OPENGL_REALISTIC_GLOSS));
9927
9928 m_gcode_viewer.render_scene(canvas_width, canvas_height);
9930}
#define SETTING_OPENGL_REALISTIC_GLOSS
Definition AppConfig.hpp:50
std::optional< Vec3d > _static_light_dir_eye() const
Definition GLCanvas3D.cpp:8535
bool _bind_gcode_shadow_map(bool bind) const
Definition GLCanvas3D.cpp:9939
EShadowMode _shadow_mode() const
Definition GLCanvas3D.cpp:8543
Transform3d m_shadow_light_vp
Definition GLCanvas3D.hpp:938
@ Off
Definition GLCanvas3D.hpp:1511

References _bind_gcode_shadow_map(), _is_realistic_view_enabled(), _render_gcode(), _shadow_mode(), _static_light_dir_eye(), Slic3r::AppConfig::get_bool(), m_gcode_viewer, m_shadow_light_vp, m_shadow_map_size, Off, SETTING_OPENGL_PHONG_SSAO, and SETTING_OPENGL_REALISTIC_GLOSS.

Referenced by _render_gcode(), and _render_scene().

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

◆ _render_gcode_overlay()

void Slic3r::GUI::GLCanvas3D::_render_gcode_overlay ( int canvas_width,
int canvas_height )
private
9950{
9951 m_gcode_viewer.render_overlay(canvas_width, canvas_height, SLIDER_RIGHT_MARGIN * GCODE_VIEWER_SLIDER_SCALE);
9952 IMSlider *layers_slider = m_gcode_viewer.get_layers_slider();
9953 IMSlider *moves_slider = m_gcode_viewer.get_moves_slider();
9954
9955 if (layers_slider->is_need_post_tick_event()) {
9956 auto evt = new wxCommandEvent(EVT_CUSTOMEVT_TICKSCHANGED, m_canvas->GetId());
9957 evt->SetInt((int)layers_slider->get_post_tick_event_type());
9958 wxPostEvent(m_canvas, *evt);
9959 layers_slider->reset_post_tick_event();
9960 }
9961
9962 if (layers_slider->is_dirty()) {
9963 set_volumes_z_range({layers_slider->GetLowerValueD(), layers_slider->GetHigherValueD()});
9964 if (m_gcode_viewer.has_data()) {
9965 m_gcode_viewer.set_layers_z_range({static_cast<unsigned int>(layers_slider->GetLowerValue()), static_cast<unsigned int>(layers_slider->GetHigherValue())});
9966 }
9967 layers_slider->set_as_dirty(false);
9968 post_event(SimpleEvent(EVT_GLCANVAS_UPDATE));
9969 }
9970
9971 if (moves_slider->is_dirty()) {
9972 moves_slider->set_as_dirty(false);
9973 m_gcode_viewer.update_sequential_view_current((moves_slider->GetLowerValueD() - 1.0), static_cast<unsigned int>(moves_slider->GetHigherValueD() - 1.0));
9974 post_event(SimpleEvent(EVT_GLCANVAS_UPDATE));
9975 }
9976}
void set_volumes_z_range(const std::array< double, 2 > &range)
Definition GLCanvas3D.hpp:1249

References _render_gcode_overlay(), Slic3r::GUI::GCODE_VIEWER_SLIDER_SCALE, Slic3r::GUI::IMSlider::get_post_tick_event_type(), Slic3r::GUI::IMSlider::GetHigherValue(), Slic3r::GUI::IMSlider::GetHigherValueD(), Slic3r::GUI::IMSlider::GetLowerValue(), Slic3r::GUI::IMSlider::GetLowerValueD(), Slic3r::GUI::IMSlider::is_dirty(), Slic3r::GUI::IMSlider::is_need_post_tick_event(), m_canvas, m_gcode_viewer, post_event(), Slic3r::GUI::IMSlider::reset_post_tick_event(), Slic3r::GUI::IMSlider::set_as_dirty(), set_volumes_z_range(), and Slic3r::GUI::SLIDER_RIGHT_MARGIN.

Referenced by _render_frame(), and _render_gcode_overlay().

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

◆ _render_gcode_translucent()

void Slic3r::GUI::GLCanvas3D::_render_gcode_translucent ( int canvas_width,
int canvas_height )
private
9933{
9935 m_gcode_viewer.render_translucent_toolpaths(canvas_width, canvas_height);
9937}

References _bind_gcode_shadow_map(), _render_gcode_translucent(), and m_gcode_viewer.

Referenced by _render_gcode_translucent(), and _render_scene().

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

◆ _render_gizmos_overlay()

void Slic3r::GUI::GLCanvas3D::_render_gizmos_overlay ( )
private
10312{
10313/*#if ENABLE_RETINA_GL
10314// m_gizmos.set_overlay_scale(m_retina_helper->get_scale_factor());
10315 const float scale = m_retina_helper->get_scale_factor()*wxGetApp().toolbar_icon_scale();
10316 m_gizmos.set_overlay_scale(scale); //! #ys_FIXME_experiment
10317#else
10318// m_gizmos.set_overlay_scale(m_canvas->GetContentScaleFactor());
10319// m_gizmos.set_overlay_scale(wxGetApp().em_unit()*0.1f);
10320 const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale());
10321 m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
10322#endif */ /* __WXMSW__ */
10323 m_gizmos.render_overlay();
10324
10325 if (m_gizmo_highlighter.m_render_arrow)
10326 {
10327 m_gizmos.render_arrow(*this, m_gizmo_highlighter.m_gizmo_type);
10328 }
10329}
struct Slic3r::GUI::GLCanvas3D::GizmoHighlighter m_gizmo_highlighter

References _render_gizmos_overlay(), m_gizmo_highlighter, and m_gizmos.

Referenced by _render_gizmos_overlay(), and _render_overlay_toolbars().

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

◆ _render_imex_ghost_tooltip()

void Slic3r::GUI::GLCanvas3D::_render_imex_ghost_tooltip ( )
private
8269{
8270 if (m_hover_ghost_head < 0)
8271 return;
8272
8273 // Hover state can outlive the ghosts that produced it: _picking_pass_imex_ghosts
8274 // only resets m_hover_ghost_head when it runs, and _picking_pass early-returns
8275 // (mouse drag, mouse off-canvas, gizmo drag) skip that reset. If the user switches
8276 // from an IMEX printer to a non-IMEX one during such a window, the plate clears its
8277 // ghost volumes but the stale head index survives — producing an orphan tooltip.
8278 // Validate against live ghosts and self-heal before rendering.
8279 const PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(m_hover_ghost_plate);
8280 if (!plate || plate->get_imex_ghost_volumes().empty()) {
8281 m_hover_ghost_head = -1;
8283 return;
8284 }
8285
8286 const auto t = wxGetApp().plater()->format_imex_ghost_tooltip(m_hover_ghost_head);
8287
8288 ImGuiWrapper& imgui = *wxGetApp().imgui();
8289 const Vec2i32 mouse = m_mouse.position.cast<int>();
8290 const float cursor_offset = imgui.scaled(1.6f); // ~16px @ 100%, scales with DPI
8291 imgui.set_next_window_pos(float(mouse.x()) + cursor_offset, float(mouse.y()) + cursor_offset,
8292 ImGuiCond_Always, 0.0f, 0.0f);
8293 imgui.begin(std::string("##imex_ghost_tooltip"),
8294 ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
8295 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove |
8296 ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoSavedSettings |
8297 ImGuiWindowFlags_NoMouseInputs);
8298 // Color swatch + label on the same row. imgui.scaled() keeps it readable on high-DPI.
8299 const ImVec4 col(t.swatch.r(), t.swatch.g(), t.swatch.b(), t.swatch.a());
8300 const float swatch_size = imgui.scaled(1.4f);
8301 ImGui::ColorButton("##swatch", col,
8302 ImGuiColorEditFlags_NoBorder | ImGuiColorEditFlags_NoTooltip,
8303 ImVec2(swatch_size, swatch_size));
8304 ImGui::SameLine();
8305 imgui.text(t.label);
8306 imgui.end();
8307}

References Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::end(), Slic3r::GUI::PartPlate::get_imex_ghost_volumes(), m_hover_ghost_head, m_hover_ghost_plate, m_mouse, Slic3r::GUI::ImGuiWrapper::scaled(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), and Slic3r::GUI::ImGuiWrapper::text().

Referenced by _render_frame().

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

◆ _render_imex_ghosts()

void Slic3r::GUI::GLCanvas3D::_render_imex_ghosts ( bool xray_pass = false)
private
8194{
8195 // Draws through whichever shader the caller bound: the shaded pass leaves gouraud current,
8196 // the X-Ray pass its own program. Both are fed per volume below; the uniforms a pass sets
8197 // once for itself are the caller's (see _render_imex_ghosts_xray for the X-Ray pass's).
8198 // GLVolume::render() only binds its mesh, so we must set the per-volume
8199 // matrices AND uniform_color that GLVolumeCollection::render would normally
8200 // set; otherwise ghosts pick up whatever the last main volume left behind.
8201 GLShaderProgram* shader = wxGetApp().get_current_shader();
8202 if (shader == nullptr)
8203 return;
8204
8205 // Primary-volume live transform lookup: during a gizmo drag the GLVolume's
8206 // instance_transformation is the source of truth (the ModelInstance matrix
8207 // only catches up on mouse-up). Returning it from here makes ghosts track
8208 // the drag every frame instead of snapping when the user releases.
8209 auto primary_live_xf = [this](int obj_idx, int inst_idx) -> std::optional<Transform3d> {
8210 for (const GLVolume* v : m_volumes.volumes) {
8211 if (!v) continue;
8212 if (v->composite_id.object_id == obj_idx &&
8213 v->composite_id.instance_id == inst_idx)
8214 return v->get_instance_transformation().get_matrix();
8215 }
8216 return std::nullopt;
8217 };
8218
8219 const Camera& camera = wxGetApp().plater()->get_camera();
8220 const Transform3d& view_matrix = camera.get_view_matrix();
8221 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
8222 // Ghosts live outside the build volume check; disable the partly-inside path.
8223 shader->set_uniform("print_volume.type", -1);
8224 shader->set_uniform("slope.actived", false);
8225
8226 // Only render ghosts for the active plate. Iterating every plate here causes
8227 // ghosts from background plates to bleed through into the active scene
8228 // (e.g. when entering paint mode), since the GL state is shared across the
8229 // whole canvas. Per-plate ghost volumes still live on each PartPlate so they
8230 // round-trip through 3MF saves; we just don't draw them when their plate
8231 // isn't the one the user is currently looking at.
8232 PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
8233 PartPlate* active_plate = ppl.get_curr_plate();
8234 if (active_plate) {
8235 // Refresh per-frame so ghost positions reflect the primary's live drag state,
8236 // and restamp ghost RGB from the live filament palette so color-only changes
8237 // (palette edits, late-loading project colors) never leave stale ghosts.
8238 active_plate->update_imex_ghost_transforms(primary_live_xf);
8239 active_plate->update_imex_ghost_colors();
8240 const auto& ghosts = active_plate->get_imex_ghost_volumes();
8241 for (const auto& g : ghosts) {
8242 if (!g || !g->is_active) continue;
8243 const Transform3d model_matrix = g->world_matrix();
8244 shader->set_uniform("volume_world_matrix", model_matrix);
8245 shader->set_uniform("slope.volume_world_normal_matrix",
8246 static_cast<Matrix3f>(model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>()));
8247 shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
8248 const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3)
8249 * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
8250 shader->set_uniform("view_normal_matrix", view_normal_matrix);
8251 g->set_render_color();
8252 // GLModel::render() pushes its own data.color into uniform_color,
8253 // so we must stamp the ghost's color onto the model before render
8254 // or it draws black. Pattern matches 3DScene.cpp:1099.
8255 // X-Ray derives its own coverage from view angle and multiplies the colour's alpha
8256 // into it, so a ghost carrying its translucency as well composites about three times
8257 // fainter than the body it mirrors. Hand that pass an opaque colour and let its
8258 // density be the only source of translucency.
8259 ColorRGBA ghost_color = g->render_color;
8260 if (xray_pass)
8261 ghost_color.a(1.0f);
8262 g->model.set_color(ghost_color);
8263 g->render();
8264 }
8265 }
8266}
Eigen::Matrix< float, 3, 3, Eigen::DontAlign > Matrix3f
Definition Point.hpp:85

References Slic3r::ColorRGBA::a(), camera, Slic3r::GLVolume::composite_id, Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::get_imex_ghost_volumes(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::CompositeID::instance_id, m_volumes, Slic3r::GLVolume::CompositeID::object_id, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GUI::PartPlate::update_imex_ghost_colors(), and Slic3r::GUI::PartPlate::update_imex_ghost_transforms().

Referenced by _render_imex_ghosts_xray(), and _render_objects().

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

◆ _render_imex_ghosts_xray()

void Slic3r::GUI::GLCanvas3D::_render_imex_ghosts_xray ( )
private
9839{
9840 GLShaderProgram* shader = wxGetApp().get_shader("xray");
9841 if (shader == nullptr)
9842 return;
9843
9844 // The blend and depth state _render_xray_volumes() uses, plus its two-sided drawing: the
9845 // shader shades back faces too, so a hollow ghost shows its far wall like a real body does.
9850
9851 shader->start_using();
9852 // _render_imex_ghosts() sets the per-volume matrices and the color, but the two uniforms
9853 // the volume collection would have set for the whole pass are this pass's to supply, and
9854 // the vertex shader discards everything outside z_range - an unset one hides every ghost.
9855 shader->set_uniform("z_range", m_volumes.get_z_range());
9856 shader->set_uniform("clipping_plane", m_volumes.get_clipping_plane());
9857 _render_imex_ghosts(/*xray_pass=*/true);
9858 shader->stop_using();
9859
9863}
void _render_imex_ghosts(bool xray_pass=false)
Definition GLCanvas3D.cpp:8193

References _render_imex_ghosts(), _render_imex_ghosts_xray(), GL_BLEND, GL_CULL_FACE, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TRUE, glBlendFunc, glDepthMask, glDisable, glEnable, glsafe, m_volumes, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by _render_imex_ghosts_xray(), and _render_objects().

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

◆ _render_imgui_select_plate_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_imgui_select_plate_toolbar ( )
private
10397{
10398 if (!m_sel_plate_toolbar.is_enabled()) {
10399 if (!m_render_preview)
10400 m_render_preview = true;
10401 return;
10402 }
10403
10405
10406 IMToolbarItem* all_plates_stats_item = m_sel_plate_toolbar.m_all_plates_stats_item;
10407
10408 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
10409 size_t sliced_plates_cnt = 0; // ORCA make it accesable for other conditions
10410
10411 for (int i = 0; i < plate_list.get_plate_count(); i++) {
10412 if (i < m_sel_plate_toolbar.m_items.size()) {
10413 if (i == plate_list.get_curr_plate_index() && !all_plates_stats_item->selected)
10414 m_sel_plate_toolbar.m_items[i]->selected = true;
10415 else
10416 m_sel_plate_toolbar.m_items[i]->selected = false;
10417
10418 m_sel_plate_toolbar.m_items[i]->percent = plate_list.get_plate(i)->get_slicing_percent();
10419
10420 bool can_slice = plate_list.get_plate(i)->can_slice();
10421 bool is_empty = plate_list.get_plate(i)->empty();
10422
10423 if (plate_list.get_plate(i)->is_slice_result_valid()) {
10424 if ((!is_empty && can_slice) && plate_list.get_plate(i)->is_slice_result_ready_for_print())
10426 else
10428 }
10429 else {
10430 // A plate using a mixed filament whose components are broken cannot be sliced,
10431 // so surface that on the plate toolbar the same way an unsliceable plate is.
10432 if ((!is_empty && !can_slice) || (plate_list.get_plate(i)->has_printable_instances() && !plate_list.get_plate(i)->can_slice())
10433 || wxGetApp().plater()->sidebar().has_broken_mixed_filament(plate_list.get_plate(i)))
10435 else {
10436 if (plate_list.get_plate(i)->get_slicing_percent() < 0.0f)
10438 else
10440 }
10441 }
10442 }
10443 }
10444 if (m_sel_plate_toolbar.show_stats_item) {
10445 all_plates_stats_item->percent = 0.0f;
10446
10447 for (auto plate : plate_list.get_nonempty_plate_list()) {
10448 if (plate->is_slice_result_valid() && plate->is_slice_result_ready_for_print())
10449 sliced_plates_cnt++;
10450 }
10451 all_plates_stats_item->percent = (float)(sliced_plates_cnt) / (float)(plate_list.get_nonempty_plate_list().size()) * 100.0f;
10452
10453 if (all_plates_stats_item->percent == 0.0f)
10454 all_plates_stats_item->slice_state = IMToolbarItem::SliceState::UNSLICED;
10455 else if (sliced_plates_cnt == plate_list.get_nonempty_plate_list().size())
10456 all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICED;
10457 else if (all_plates_stats_item->percent < 100.0f)
10458 all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICING;
10459
10460 for (auto toolbar_item : m_sel_plate_toolbar.m_items) {
10461 if(toolbar_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
10462 all_plates_stats_item->slice_state = IMToolbarItem::SliceState::SLICE_FAILED;
10463 all_plates_stats_item->selected = false;
10464 break;
10465 }
10466 }
10467
10468 // Changing parameters does not invalid all plates, need extra logic to validate
10469 bool gcode_result_valid = true;
10470 for (auto gcode_result : plate_list.get_nonempty_plates_slice_results()) {
10471 if (gcode_result->moves.size() == 0) {
10472 gcode_result_valid = false;
10473 }
10474 }
10475 if (all_plates_stats_item->selected && all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICED && gcode_result_valid) {
10476 m_gcode_viewer.render_all_plates_stats(plate_list.get_nonempty_plates_slice_results());
10477 m_render_preview = false;
10478 }
10479 else{
10480 m_gcode_viewer.render_all_plates_stats(plate_list.get_nonempty_plates_slice_results(), false);
10481 m_render_preview = true;
10482 }
10483 }else
10484 m_render_preview = true;
10485
10486 // places the toolbar on the top_left corner of the 3d scene
10487 float f_scale = get_scale();
10488 #ifdef WIN32
10489 const int dpi = get_dpi_for_window(wxGetApp().GetTopWindow());
10490 f_scale *= (float) dpi / (float) DPI_DEFAULT;
10491 #endif // WIN32
10492 Size cnv_size = get_canvas_size();
10493 auto canvas_w = float(cnv_size.get_width());
10494 auto canvas_h = float(cnv_size.get_height());
10495
10496 m_sel_plate_toolbar.set_icon_size(100.0f * f_scale, 100.0f * f_scale);
10497
10498 float button_width = m_sel_plate_toolbar.icon_width;
10499 float button_height = m_sel_plate_toolbar.icon_height;
10500
10501 float frame_padding = 1.0f * f_scale;
10502 float margin_size = 4.0f * f_scale;
10503 float button_margin = frame_padding;
10504
10505 const float y_offset = is_collapse_toolbar_on_left() ? (get_collapse_toolbar_height() + 5) : 0;
10506 // Make sure the window does not overlap the 3d navigator
10507 auto window_height_max = canvas_h - y_offset;
10508 if (wxGetApp().show_3d_navigator()) {
10509 window_height_max -= (128 * f_scale + 5);
10510 }
10511 else { // ORCA spacing for canvas menu
10512 window_height_max -= (96 * f_scale + 5);
10513 }
10514
10515 // ORCA simplify and correct window size and margin calculations and get values from style
10516 ImGuiWrapper& imgui = *wxGetApp().imgui();
10517
10518 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f, 8.0f) * f_scale);
10519 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4.0f, 4.0f) * f_scale);
10520
10521 int item_count = m_sel_plate_toolbar.m_items.size() + (m_sel_plate_toolbar.show_stats_item ? 1 : 0);
10522 float window_height_calc = (item_count * (button_height + (margin_size + button_margin) * 2.0f) + (item_count - 1) * ImGui::GetStyle().ItemSpacing.y + ImGui::GetStyle().WindowPadding.y * 2.0f);
10523 bool show_scroll = m_sel_plate_toolbar.is_display_scrollbar && (window_height_calc > window_height_max);
10524 float scrollbar_size = PLATE_TOOLBAR_SCROLLBAR * f_scale;
10525 float window_height = std::min(window_height_calc, window_height_max);
10526 float window_width = button_width + (margin_size + button_margin + ImGui::GetStyle().WindowPadding.x) * 2 + (show_scroll ? scrollbar_size : 0);
10527
10528 ImVec4 window_bg = m_is_dark ? ImVec4(.13f, .13f, .15f, .5f) : ImVec4(1.f, 1.f, 1.f, .7f);
10529 ImVec4 button_active = ImGuiWrapper::COL_ORCA; // ORCA: Use orca color for selected sliced plate border
10530 ImVec4 button_hover = plate_toolbar_hover_color(m_is_dark);
10533 ImU32 plate_bg = m_is_dark ? IM_COL32(255, 255, 255, 10) : IM_COL32(0, 0, 0, 10);
10534 ImU32 plate_dim = m_is_dark ? IM_COL32(30, 30, 30, 100) : IM_COL32(0, 0, 0, 50);
10535 float button_radius = 1.0f * f_scale;
10536 //ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.f, 0.f, 0.f, 1.0f));
10537 //use white text as the background switch to black
10538 ImGui::PushStyleColor(ImGuiCol_Text, m_is_dark ? ImVec4(.9f, .9f, .9f, 1) : ImVec4(.3f, .3f, .3f, 1)); // ORCA Plate number text > Add support for dark mode
10539 ImGui::PushStyleColor(ImGuiCol_WindowBg, window_bg);
10540 ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_active);
10541 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
10543
10544 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
10545 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, show_scroll ? (6.f * f_scale) : (button_radius + margin_size + frame_padding + ImGui::GetStyle().WindowPadding.x));
10546 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, button_radius + margin_size);
10547
10548 imgui.set_next_window_pos(canvas_w * 0 + 5.0f * f_scale, canvas_h * 0 + y_offset, ImGuiCond_Always, 0, 0); // ORCA Add slight gap on left edge so toolbar looks like floating and it creates separation with sidebar
10549 imgui.set_next_window_size(window_width, window_height, ImGuiCond_Always);
10550
10551 if (show_scroll)
10552 imgui.begin(_L("Select Plate"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);
10553 else
10554 imgui.begin(_L("Select Plate"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);
10555 ImGui::SetWindowFontScale(1.2f);
10556
10557 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f * f_scale);
10558
10559 ImVec2 size = ImVec2(button_width, button_height); // Size of the image we want to make visible
10560 ImVec4 bg_col = ImVec4(128.0f, 128.0f, 128.0f, 0.0f);
10561 ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
10562 ImVec2 margin = ImVec2(margin_size, margin_size);
10563
10564 if(m_sel_plate_toolbar.show_stats_item)
10565 {
10566 // draw image
10567 ImVec2 button_start_pos = ImGui::GetCursorScreenPos();
10568
10569 auto stats_hover_rect = button_start_pos + ImGui::GetWindowPos() - ImGui::GetCurrentWindow()->Scroll;
10570 bool is_stats_hovered = ImGui::IsMouseHoveringRect(stats_hover_rect, stats_hover_rect + size);
10571
10572 if (all_plates_stats_item->selected) {
10573 auto border_color = is_stats_hovered ? ImGuiWrapper::COL_ORCA_HOVER : ImGuiWrapper::COL_ORCA;
10574 ImGui::PushStyleColor(ImGuiCol_Button , border_color);
10575 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, border_color);
10576 ImGui::PushStyleColor(ImGuiCol_ButtonActive , border_color);
10577 }
10578 else {
10579 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(128.0f, 128.0f, 128.0f, 0.0f));
10580 if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
10581 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetStyleColorVec4(ImGuiCol_Button));
10582 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetStyleColorVec4(ImGuiCol_Button));
10583 }
10584 else {
10585 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
10586 ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_hover);
10587 }
10588 }
10589
10590 ImVec4 text_clr = m_is_dark ? ImVec4(.9f, .9f, .9f, 1) : ImVec4(.3f, .3f, .3f, 1);;
10591 ImTextureID btn_texture_id;
10592 if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::UNSLICED || all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICING){
10593 btn_texture_id = (ImTextureID)(intptr_t)(m_process->running() ? all_plates_stats_item->image_slicing.get_id() : all_plates_stats_item->image_idle.get_id());
10594 } else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
10595 btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_failed.get_id());
10596 } else {
10597 btn_texture_id = (ImTextureID)(intptr_t)(all_plates_stats_item->image_stats.get_id());
10598 }
10599
10600 if (ImGui::ImageButton2(btn_texture_id, size, {0,0}, {1,1}, frame_padding, bg_col, tint_col, margin)) {
10601 if (all_plates_stats_item->slice_state != IMToolbarItem::SliceState::SLICE_FAILED) {
10602 if (m_process && !m_process->running()) {
10603 for (int i = 0; i < m_sel_plate_toolbar.m_items.size(); i++) {
10604 m_sel_plate_toolbar.m_items[i]->selected = false;
10605 }
10606 all_plates_stats_item->selected = true;
10607 wxGetApp().plater()->update(true, true);
10608 wxCommandEvent evt = wxCommandEvent(EVT_GLTOOLBAR_SLICE_ALL);
10609 wxPostEvent(wxGetApp().plater(), evt);
10610 }
10611 }
10612 }
10613
10614 ImGui::PopStyleColor(3);
10615
10616 ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
10617
10618 // ORCA add more useful information about slicing process and use progress bar on stats button
10619 std::string text_top;
10620 std::string text_bottom;
10621 ImVec2 bar_size = ImVec2(size.x - margin.x * 2, 5.0f * f_scale);
10622 ImVec2 bar_bg_bgn = start_pos + ImVec2(margin.x, size.y - bar_size.y - margin.y);
10623 ImVec2 bar_bg_end = bar_bg_bgn + bar_size;
10624 int total_plates_cnt = plate_list.get_nonempty_plate_list().size();
10625 ImGui::GetWindowDrawList()->AddRectFilled(start_pos, start_pos + size, plate_bg, button_radius); // Button background
10626
10627 if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::UNSLICED || all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICING) {
10628 float bar_current_perc_pos = 0;
10629 float bar_total_perc_pos = all_plates_stats_item->percent * (bar_size.x / 100.0f);
10630 int current_slicing_plate = 0;
10631 if (m_process->running()) {
10632 for (int i = 0; i < total_plates_cnt; i++) {
10633 if (m_sel_plate_toolbar.m_items[i]->slice_state == IMToolbarItem::SliceState::SLICING) {
10634 current_slicing_plate = i;
10635 bar_current_perc_pos = m_sel_plate_toolbar.m_items[i]->percent * (bar_size.x / total_plates_cnt / 100.0f);
10636 }
10637 }
10638 text_top = _u8L("Slicing") + ": " + std::to_string(current_slicing_plate + 1);
10639 } else {
10640 text_top = _u8L("Slice all");
10641 }
10642 text_bottom = std::to_string(sliced_plates_cnt) + " / " + std::to_string(total_plates_cnt);
10643 ImVec2 bar_fg_end = ImVec2(bar_bg_bgn.x + bar_total_perc_pos + bar_current_perc_pos, bar_bg_end.y);
10644 ImGui::GetWindowDrawList()->AddRectFilled(bar_bg_bgn, bar_bg_end, IM_COL32(128, 128, 128, 255), bar_size.y); // BAR BACKGROUND
10645 ImGui::GetWindowDrawList()->AddRectFilled(bar_bg_bgn, bar_fg_end, IM_COL32(0, 150, 136, 255), bar_size.y); // BAR PROGRESS
10646 }
10647 else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED) {
10648 text_top = _u8L("Failed");
10649 text_bottom = std::to_string(sliced_plates_cnt) + " / " + std::to_string(total_plates_cnt);
10650 ImGui::GetWindowDrawList()->AddRectFilled(bar_bg_bgn, bar_bg_end, IM_COL32(225, 74, 74, 255), bar_size.y);
10651 }
10652 else if (all_plates_stats_item->slice_state == IMToolbarItem::SliceState::SLICED) {
10653 text_top = _u8L("All Plates");
10654 text_bottom = _u8L("Stats");
10655 }
10656
10657 // draw text
10658 GImGui->FontSize = 15.0f * f_scale;
10659 ImGui::PushStyleColor(ImGuiCol_Text, text_clr);
10660 ImVec2 text_size = ImGui::CalcTextSize(text_top.c_str());
10661 ImVec2 text_start_pos = ImVec2(start_pos.x + (button_width - text_size.x) / 2, start_pos.y + 3.0f * button_height / 5.0f);
10662 ImGui::RenderText(text_start_pos, text_top.c_str());
10663 text_size = ImGui::CalcTextSize(text_bottom.c_str());
10664 text_start_pos = ImVec2(start_pos.x + (button_width - text_size.x) / 2, text_start_pos.y + ImGui::GetTextLineHeight());
10665 ImGui::RenderText(text_start_pos, text_bottom.c_str());
10666 ImGui::PopStyleColor();
10667 ImGui::SetWindowFontScale(1.2f);
10668 }
10669
10670 for (int i = 0; i < m_sel_plate_toolbar.m_items.size(); i++) {
10671 IMToolbarItem* item = m_sel_plate_toolbar.m_items[i];
10672
10673 auto current_plate = plate_list.get_plate(i);
10674 bool can_slice = current_plate->can_slice();
10675 bool is_empty = current_plate->empty();
10676
10677 // draw image
10678 ImVec2 button_start_pos = ImGui::GetCursorScreenPos();
10679 ImGui::PushID(i);
10680 ImVec2 uv0 = ImVec2(0.0f, 1.0f); // UV coordinates for lower-left
10681 ImVec2 uv1 = ImVec2(1.0f, 0.0f); // UV coordinates in our texture
10682
10683 auto button_pos = ImGui::GetCursorPos();
10684 ImGui::SetCursorPos(button_pos + margin);
10685
10686 ImGui::Image(item->texture_id, size, uv0, uv1, tint_col);
10687
10688 ImGui::SetCursorPos(button_pos);
10689
10690 // invisible button
10691 auto button_size = size + margin + margin + ImVec2(2 * frame_padding, 2 * frame_padding);
10692 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f * f_scale);
10693 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
10694 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
10695 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
10696 // Translate window pos to abs pos, also account for the window scrolling
10697 auto hover_rect = button_pos + ImGui::GetWindowPos() - ImGui::GetCurrentWindow()->Scroll;
10698 bool is_plate_hovered = ImGui::IsMouseHoveringRect(hover_rect, hover_rect + button_size);
10699
10700 if (item->selected)
10701 ImGui::PushStyleColor(ImGuiCol_Border, is_plate_hovered ? ImGuiWrapper::COL_ORCA_HOVER : ImGuiWrapper::COL_ORCA);
10702 else
10703 ImGui::PushStyleColor(ImGuiCol_Border, is_plate_hovered ? button_hover : ImVec4(.0f, .0f, .0f, .0f));
10704
10705 if(ImGui::Button("##invisible_button", button_size)){
10706 // ORCA switch back to prepare tab when clicked failed plates
10707 if (!is_empty && item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED){
10708 if (m_canvas != nullptr && !wxGetApp().is_closing()) {
10709 m_canvas->CallAfter([this, i]() {
10710 auto& app = wxGetApp();
10711 if (!app.is_closing()){
10712 auto* plater = app.plater();
10713 if (plater){
10714 plater->select_view_3D("3D"); // ensure its in 3D view
10715 plater->select_plate(i);
10716 zoom_to_bed();
10717 auto* view3d_canvas = plater->get_view3D_canvas3D();
10718 if(view3d_canvas){
10719 view3d_canvas->get_gizmos_manager().reset_all_states(); // close all gizmos
10720 view3d_canvas->reload_scene(true);
10721 }
10722 app.mainframe->select_tab(TAB_ID_PREPARE);
10723 }
10724 }
10725 });
10726 }
10727 }
10728 else if (m_process && !m_process->running()) {
10729 all_plates_stats_item->selected = false;
10730 bool was_active = item->selected;
10731 item->selected = true;
10732 // begin to slicing plate
10733 if (item->slice_state != IMToolbarItem::SliceState::SLICED)
10734 wxGetApp().plater()->update(true, true);
10735 wxCommandEvent* evt = new wxCommandEvent(EVT_GLTOOLBAR_SELECT_SLICED_PLATE);
10736 // ORCA dont reset viewing angle if item was active and non sliced to allow making comparisons on parameter changes
10737 if(!was_active || (was_active && item->slice_state == IMToolbarItem::SliceState::SLICED))
10738 evt->SetExtraLong(1); // 1 = skip zooming plate
10739 evt->SetInt(i);
10740 wxQueueEvent(wxGetApp().plater(), evt);
10741 }
10742 }
10743 ImGui::PopStyleColor(4);
10744 ImGui::PopStyleVar();
10745
10746 ImVec2 start_pos = ImVec2(button_start_pos.x + frame_padding + margin.x, button_start_pos.y + frame_padding + margin.y);
10747 ImVec2 size = ImVec2(button_width, button_height);
10748 ImVec2 end_pos = ImVec2(start_pos.x + size.x, start_pos.y + size.y);
10749 // ORCA show additional information depends on state
10750 auto draw_info_btn = [end_pos, f_scale, margin](std::string str, ImVec4 bg_color, ImVec4 fg_color){
10751 GImGui->FontSize = 15.0f * f_scale;
10752 ImVec2 txt_slice_sz = ImGui::CalcTextSize(str.c_str());
10753 ImVec2 btn_pad = ImVec2(8.f, 1.f) * f_scale;
10754 ImVec2 txt_slice_pos = end_pos - txt_slice_sz - margin - btn_pad;
10755 ImVec2 txt_slice_end = end_pos - margin - btn_pad;
10756 ImGui::GetWindowDrawList()->AddRectFilled(txt_slice_pos - btn_pad, txt_slice_end + btn_pad, ImGui::GetColorU32(bg_color), (txt_slice_sz.y + btn_pad.y) * .5f);
10757 ImGui::PushStyleColor(ImGuiCol_Text, fg_color);
10758 ImGui::RenderText(txt_slice_pos, str.c_str());
10759 ImGui::PopStyleColor(1);
10760 ImGui::SetWindowFontScale(1.2f);
10761 };
10762
10763 if (is_empty){
10764 ImGui::GetWindowDrawList()->AddRectFilled(start_pos, end_pos, plate_dim, button_radius);
10765 } else if (can_slice && item->slice_state == IMToolbarItem::SliceState::UNSLICED) {
10766 ImGui::GetWindowDrawList()->AddRectFilled(start_pos, end_pos, plate_dim, button_radius);
10767 // ORCA add slice button to guide user
10768 bool is_processing = m_process && m_process->running() ;
10769 draw_info_btn(_u8L("Slice"),
10770 is_processing ? window_bg : (is_plate_hovered ? orca_hover : orca_active),
10771 m_is_dark ? ImVec4(.9f, .9f, .9f, 1) : (is_processing ? ImVec4(.3f, .3f, .3f, 1) : ImVec4(1, 1, 1, 1))
10772 );
10773 } else if (item->slice_state == IMToolbarItem::SliceState::SLICING) {
10774 // ORCA use bottom to top for shade animation that matches with printing / slicing orientation
10775 ImVec2 rect_size = ImVec2(button_width, button_height * item->percent / 100.0f);
10776 ImVec2 rect_start_pos = ImVec2(start_pos.x, start_pos.y);
10777 ImVec2 rect_end_pos = ImVec2(start_pos.x + button_width, start_pos.y + button_height - rect_size.y);
10778 ImGui::GetWindowDrawList()->AddRectFilled(start_pos, end_pos, plate_bg, button_radius);
10779 ImGui::GetWindowDrawList()->AddRectFilled(rect_start_pos, rect_end_pos, plate_dim, button_radius);
10780 // ORCA show percentage as text
10781 draw_info_btn(std::to_string(int(item->percent)) + "%",
10782 window_bg,
10783 m_is_dark ? ImVec4(.9f, .9f, .9f, 1) : ImVec4(.3f, .3f, .3f, 1)
10784 );
10785 } else if (!is_empty && (!can_slice || item->slice_state == IMToolbarItem::SliceState::SLICE_FAILED)) {
10786 // Draw exclamation mark that matches with icon
10787 ImVec2 center = ImVec2(start_pos.x + button_width/2, start_pos.y + button_height/2 - ImGui::GetTextLineHeight() * .5f);
10788 auto draw_list =ImGui::GetWindowDrawList();
10789 auto clr = m_is_dark ? IM_COL32(60, 44, 48, 255) : IM_COL32(202, 186, 186, 255);
10790 draw_list->AddRectFilled(start_pos, end_pos, IM_COL32(64, 1, 1, 64), button_radius);
10791 draw_list->AddCircleFilled(center, 14.f * f_scale,IM_COL32(225, 74, 74, 255));
10792 draw_list->AddRectFilled(center - ImVec2(2.f, 10.f) * f_scale, center + ImVec2(2.f, 4.f) * f_scale, clr, 2.f * f_scale);
10793 draw_list->AddCircleFilled(center + ImVec2(0, 8.f * f_scale),2.f * f_scale, clr);
10794 draw_info_btn(_u8L("Review"),
10795 ImGui::ColorConvertU32ToFloat4(is_plate_hovered ? IM_COL32(239, 88, 88, 255) : IM_COL32(225, 74, 74, 255)),
10796 m_is_dark ? ImVec4(.9f, .9f, .9f, 1) : ImVec4(1, 1, 1, 1)
10797 );
10798 } else if (item->slice_state == IMToolbarItem::SliceState::SLICED) {
10799 ImGui::GetWindowDrawList()->AddRectFilled(start_pos, end_pos, plate_bg, button_radius);
10800 }
10801
10802 // draw text
10803 GImGui->FontSize = 18.0f * f_scale; // ORCA fix font scaling
10804 ImVec2 text_start_pos = ImVec2(start_pos.x + 4.0f * f_scale, start_pos.y + 2.0f * f_scale); // ORCA move close to corner to prevent overlapping with preview
10805 ImGui::RenderText(text_start_pos, std::to_string(i + 1).c_str());
10806 ImGui::SetWindowFontScale(1.2f); // ORCA fix font scaling
10807
10808 ImGui::PopID();
10809 }
10810 ImGui::SetWindowFontScale(1.0f);
10811 ImGui::PopStyleColor(8);
10812 ImGui::PopStyleVar(7);
10813
10814 m_sel_plate_toolbar.is_display_scrollbar = plate_toolbar_keeps_scrollbar(show_scroll, scrollbar_size);
10815
10816 imgui.end();
10817}
#define TAB_ID_PREPARE
Definition MainFrame.hpp:60
bool _update_imgui_select_plate_toolbar()
Definition GLCanvas3D.cpp:7685
bool is_collapse_toolbar_on_left() const
Definition GLCanvas3D.cpp:2416
float get_collapse_toolbar_height() const
Definition GLCanvas3D.cpp:2426
@ SLICED
Definition IMToolbar.hpp:25
@ SLICING
Definition IMToolbar.hpp:24
@ SLICE_FAILED
Definition IMToolbar.hpp:26
@ UNSLICED
Definition IMToolbar.hpp:23
static const ImVec4 COL_ORCA_HOVER
Definition ImGuiWrapper.hpp:410
static const ImVec4 COL_ORCA_HOVER_DARK
Definition ImGuiWrapper.hpp:411
static const ImVec4 COL_ORCA_DARK
Definition ImGuiWrapper.hpp:409
int select_plate(int plate_index, bool need_slice=false)
Definition Plater.cpp:22612
GLCanvas3D * get_view3D_canvas3D()
Definition Plater.cpp:22082
void select_view_3D(const std::string &name, bool no_slice=true)
Definition Plater.cpp:19119
wxColour bg_color()
Definition SpeedDialDialog.cpp:69
static void push_plate_toolbar_scrollbar_style(bool is_dark, float scrollbar_size)
Definition GLCanvas3D.cpp:10369
static bool plate_toolbar_keeps_scrollbar(bool shown, float scrollbar_size)
Definition GLCanvas3D.cpp:10387
static ImVec4 plate_toolbar_hover_color(bool is_dark)
Definition GLCanvas3D.cpp:10381
static constexpr float PLATE_TOOLBAR_SCROLLBAR
Definition GLCanvas3D.cpp:10366

References _L, _render_imgui_select_plate_toolbar(), _u8L, _update_imgui_select_plate_toolbar(), Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::PartPlate::can_slice(), Slic3r::center(), Slic3r::GUI::ImGuiWrapper::COL_ORCA, Slic3r::GUI::ImGuiWrapper::COL_ORCA_DARK, Slic3r::GUI::ImGuiWrapper::COL_ORCA_HOVER, Slic3r::GUI::ImGuiWrapper::COL_ORCA_HOVER_DARK, Slic3r::GUI::DPI_DEFAULT, Slic3r::GUI::PartPlate::empty(), Slic3r::GUI::ImGuiWrapper::end(), get_canvas_size(), get_collapse_toolbar_height(), Slic3r::GUI::PartPlateList::get_curr_plate_index(), Slic3r::GUI::get_dpi_for_window(), Slic3r::GUI::Size::get_height(), Slic3r::GUI::GLTexture::get_id(), Slic3r::GUI::PartPlateList::get_nonempty_plate_list(), Slic3r::GUI::PartPlateList::get_nonempty_plates_slice_results(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), get_scale(), Slic3r::GUI::PartPlate::get_slicing_percent(), Slic3r::GUI::Size::get_width(), Slic3r::GUI::PartPlate::has_printable_instances(), Slic3r::GUI::IMToolbarItem::image_failed, Slic3r::GUI::IMToolbarItem::image_idle, Slic3r::GUI::IMToolbarItem::image_slicing, Slic3r::GUI::IMToolbarItem::image_stats, is_collapse_toolbar_on_left(), Slic3r::GUI::PartPlate::is_slice_result_ready_for_print(), Slic3r::GUI::PartPlate::is_slice_result_valid(), m_canvas, m_gcode_viewer, m_is_dark, m_process, m_render_preview, m_sel_plate_toolbar, Slic3r::GUI::IMToolbarItem::percent, Slic3r::GUI::plate_toolbar_hover_color(), Slic3r::GUI::plate_toolbar_keeps_scrollbar(), Slic3r::GUI::PLATE_TOOLBAR_SCROLLBAR, Slic3r::GUI::plater(), Slic3r::GUI::push_plate_toolbar_scrollbar_style(), Slic3r::GUI::IMToolbarItem::selected, Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), Slic3r::GUI::ImGuiWrapper::set_next_window_size(), Slic3r::GUI::IMToolbarItem::SLICE_FAILED, Slic3r::GUI::IMToolbarItem::slice_state, Slic3r::GUI::IMToolbarItem::SLICED, Slic3r::GUI::IMToolbarItem::SLICING, TAB_ID_PREPARE, Slic3r::GUI::IMToolbarItem::texture_id, Slic3r::GUI::IMToolbarItem::UNSLICED, and zoom_to_bed().

Referenced by _render_imgui_select_plate_toolbar(), and _render_overlays().

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

◆ _render_main_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_main_toolbar ( )
private
10351{
10352 if (!m_main_toolbar.is_enabled())
10353 return;
10354
10355 const Size cnv_size = get_canvas_size();
10356 const float top = 0.5f * (float)cnv_size.get_height();
10357
10358 const float left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset();
10359 m_main_toolbar.set_position(top, left);
10360 m_main_toolbar.render(*this);
10361 if (m_toolbar_highlighter.m_render_arrow)
10362 m_main_toolbar.render_arrow(*this, m_toolbar_highlighter.m_toolbar_item);
10363}
struct Slic3r::GUI::GLCanvas3D::ToolbarHighlighter m_toolbar_highlighter

References _render_main_toolbar(), get_canvas_size(), Slic3r::GUI::Size::get_height(), get_main_toolbar_offset(), Slic3r::GUI::Size::get_width(), m_main_toolbar, and m_toolbar_highlighter.

Referenced by _render_main_toolbar(), and _render_overlay_toolbars().

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

◆ _render_objects()

void Slic3r::GUI::GLCanvas3D::_render_objects ( GLVolumeCollection::ERenderType type,
bool with_outline = true )
private
9535{
9536 if (m_volumes.empty())
9537 return;
9538
9540
9542
9544 // Update the layer editing selection to the first object selected, update the current object maximum Z.
9545 m_layers_editing.select_object(*m_model, this->is_layers_editing_enabled() ? m_selection.get_object_idx() : -1);
9546
9547 if (const BuildVolume &build_volume = m_bed.build_volume(); build_volume.valid()) {
9548 switch (build_volume.type()) {
9550 const BoundingBox3Base<Vec3d> bed_bb = build_volume.bounding_volume().inflated(BuildVolume::SceneEpsilon);
9551 m_volumes.set_print_volume({ 0, // Rectangle
9552 { float(bed_bb.min.x()), float(bed_bb.min.y()), float(bed_bb.max.x()), float(bed_bb.max.y()) },
9553 { 0.0f, float(build_volume.printable_height()) } });
9554 break;
9555 }
9557 m_volumes.set_print_volume({ 1, // Circle
9558 { unscaled<float>(build_volume.circle().center.x()), unscaled<float>(build_volume.circle().center.y()), unscaled<float>(build_volume.circle().radius + BuildVolume::SceneEpsilon), 0.0f },
9559 { 0.0f, float(build_volume.printable_height() + BuildVolume::SceneEpsilon) } });
9560 break;
9561 }
9562 default:
9565 m_volumes.set_print_volume({ static_cast<int>(type),
9566 { -FLT_MAX, -FLT_MAX, FLT_MAX, FLT_MAX },
9567 { -FLT_MAX, FLT_MAX } }
9568 );
9569 }
9570 }
9572 m_volumes.check_outside_state(build_volume, nullptr, nullptr);
9574 }
9575 }
9576
9578 m_volumes.set_z_range(-m_clipping_planes[0].get_data()[3], m_clipping_planes[1].get_data()[3]);
9579 else
9580 m_volumes.set_z_range(-FLT_MAX, FLT_MAX);
9581
9582 GLGizmosManager& gm = get_gizmos_manager();
9583 GLGizmoBase* current_gizmo = gm.get_current();
9584 if (current_gizmo && !current_gizmo->apply_clipping_plane()) {
9585 m_volumes.set_clipping_plane(ClippingPlane::ClipsNothing().get_data());
9586 }
9587 else {
9588 m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data());
9589 }
9591 m_volumes.set_show_sinking_contours(false);
9592 else
9593 m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances());
9594
9595 // Orca: X-Ray replaces both shaded passes with a single one, driven from the opaque call, and
9596 // reuses the volume state (print volume, z range, clipping plane) set up above.
9597 if (_is_xray_view_active()) {
9600 else
9603 return;
9604 }
9605
9606 const bool realistic_mode = _is_realistic_view_enabled();
9607 const bool realistic_phong = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_REALISTIC_PHONG);
9608 const std::string shader_name = (m_studio_lighting || (realistic_mode && realistic_phong)) ? "phong" : "gouraud";
9609 GLShaderProgram* shader = wxGetApp().get_shader(shader_name);
9610 if (shader == nullptr && shader_name != "gouraud")
9611 shader = wxGetApp().get_shader("gouraud");
9612 const bool studio = m_studio_lighting && shader != nullptr && shader->get_name() == "phong";
9613 ECanvasType canvas_type = this->m_canvas_type;
9614 bool partly_inside_enable = canvas_type == ECanvasType::CanvasAssembleView ? false : true;
9615 // The edited printer's per-extruder printable heights feed the object shader's
9616 // extruder_printable_heights uniform. Empty for single-extruder printers, so the shader flag stays
9617 // 0.0 and rendering is pixel-identical there (see GLVolumeCollection::render).
9618 auto printable_height_option = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloatsNullable>("extruder_printable_height");
9619 std::vector<double>* printable_heights = printable_height_option ? &printable_height_option->values : nullptr;
9620 if (shader != nullptr) {
9621 shader->start_using();
9622
9623 const bool phong_ssao = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SSAO);
9624 shader->set_uniform("enable_ssao", phong_ssao);
9625 // Set on every use: the program is shared, so a canvas that leaves it unset would inherit
9626 // the last canvas's choice.
9627 shader->set_uniform("lighting_model", studio ? 1 : 0);
9628 shader->set_uniform("translucent_gloss", realistic_mode);
9629 if (studio) {
9630 const Transform3d& view = wxGetApp().plater()->get_camera().get_view_matrix();
9631 shader->set_uniform("world_up_eye", Vec3f((view.matrix().block<3, 3>(0, 0) * Vec3d::UnitZ()).cast<float>()));
9632 }
9633
9634 // Object-on-object and self shadows: sample the depth map built in _render_shadow_map_pass().
9635 // shadow_intensity == 0 disables the effect entirely (unchanged behavior when off / unsupported).
9640 shader->set_uniform("shadow_map", 4);
9641 shader->set_uniform("shadow_light_vp", m_shadow_light_vp);
9642 shader->set_uniform("shadow_map_texel", 1.0f / static_cast<float>(m_shadow_map_size));
9643 shader->set_uniform("shadow_intensity", 0.35f);
9644 }
9645 else
9646 shader->set_uniform("shadow_intensity", 0.0f);
9647 const std::optional<Vec3d> static_light = _static_light_dir_eye();
9648 shader->set_uniform("use_static_light", static_light.has_value());
9649 if (static_light.has_value())
9650 shader->set_uniform("static_light_dir", *static_light);
9651
9652 const Size& cvn_size = get_canvas_size();
9653 {
9654 const Camera& camera = wxGetApp().plater()->get_camera();
9655 shader->set_uniform("z_far", camera.get_far_z());
9656 shader->set_uniform("z_near", camera.get_near_z());
9657 }
9658 switch (type)
9659 {
9660 default:
9662 {
9663 GLGizmosManager& gm = get_gizmos_manager();
9664 if (dynamic_cast<GLGizmoPainterBase*>(gm.get_current()) == nullptr)
9665 {
9666 if (m_picking_enabled && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) {
9667 int object_id = m_layers_editing.last_object_id;
9668 const Camera& camera = wxGetApp().plater()->get_camera();
9669 m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [object_id](const GLVolume& volume) {
9670 // Which volume to paint without the layer height profile shader?
9671 return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id);
9672 });
9673 m_layers_editing.render_volumes(*this, m_volumes);
9674 }
9675 else {
9676 /*if (wxGetApp().plater()->is_wireframe_enabled()) {
9677 if (wxGetApp().plater()->is_show_wireframe())
9678 shader->set_uniform("show_wireframe", true);
9679 else
9680 shader->set_uniform("show_wireframe", false);
9681 }*/
9682 //BBS:add assemble view related logic
9683 // do not cull backfaces to show broken geometry, if any
9684 const Camera& camera = wxGetApp().plater()->get_camera();
9685 m_volumes.render(type, m_picking_enabled, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [this, canvas_type](const GLVolume& volume) {
9686 if (canvas_type == ECanvasType::CanvasAssembleView) {
9687 return !volume.is_modifier && !volume.is_wipe_tower;
9688 }
9689 else {
9690 return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
9691 }
9692 },
9693 partly_inside_enable, printable_heights);
9694 }
9695 }
9696 else {
9697 // In case a painting gizmo is open, it should render the painted triangles
9698 // before transparent objects are rendered. Otherwise they would not be
9699 // visible when inside modifier meshes etc.
9700// GLGizmosManager::EType type = gm.get_current_type();
9701 if (dynamic_cast<GLGizmoPainterBase*>(gm.get_current())) {
9702 shader->stop_using();
9703 gm.render_painter_gizmo();
9704 shader->start_using();
9705 }
9706 }
9707
9709 break;
9710 }
9712 {
9713 /*if (wxGetApp().plater()->is_wireframe_enabled()) {
9714 if (wxGetApp().plater()->is_show_wireframe())
9715 shader->set_uniform("show_wireframe", true);
9716 else
9717 shader->set_uniform("show_wireframe", false);
9718 }*/
9719 const Camera& camera = wxGetApp().plater()->get_camera();
9720 //BBS:add assemble view related logic
9721 m_volumes.render(type, false, camera.get_view_matrix(), camera.get_projection_matrix(), cvn_size, [canvas_type](const GLVolume& volume) {
9722 if (canvas_type == ECanvasType::CanvasAssembleView) {
9723 return !volume.is_modifier;
9724 }
9725 else {
9726 return true;
9727 }
9728 },
9729 partly_inside_enable, printable_heights);
9730 // IMEX ghosts are transparent and share the same shader/camera state;
9731 // render them right after the main transparent pass while the shader is still bound.
9733 break;
9734 }
9735 }
9736
9737 /*if (wxGetApp().plater()->is_wireframe_enabled()) {
9738 shader->set_uniform("show_wireframe", false);
9739 }*/
9740
9745 }
9746 shader->set_uniform("use_static_light", false);
9747
9748 shader->stop_using();
9749 }
9750
9752}
#define SETTING_OPENGL_REALISTIC_PHONG
Definition AppConfig.hpp:42
static constexpr const double SceneEpsilon
Definition BuildVolume.hpp:110
std::vector< double > values
Definition Config.hpp:418
@ Transparent
Definition 3DScene.hpp:422
@ Opaque
Definition 3DScene.hpp:421
bool m_requires_check_outside_state
Definition GLCanvas3D.hpp:739
void _render_section_view_caps()
Definition GLCanvas3D.cpp:9754
bool m_sinking_contours_enabled
Definition GLCanvas3D.hpp:687
bool _is_xray_view_active() const
Definition GLCanvas3D.cpp:9790
ClippingPlane _get_volumes_clipping_plane() const
Definition GLCanvas3D.cpp:12067
void _render_xray_volumes()
Definition GLCanvas3D.cpp:9803
bool m_studio_lighting
Definition GLCanvas3D.hpp:706
std::array< ClippingPlane, 2 > m_clipping_planes
Definition GLCanvas3D.hpp:707
const GLGizmosManager & get_gizmos_manager() const
Definition GLCanvas3D.hpp:1031
void _render_imex_ghosts_xray()
Definition GLCanvas3D.cpp:9838
ClippingPlane m_camera_clipping_plane
Definition GLCanvas3D.hpp:708
ECanvasType
Definition GLCanvas3D.hpp:625
ConfigOptionFloatsTempl< true > ConfigOptionFloatsNullable
Definition Config.hpp:1016
@ Circle
Definition BuildVolume.hpp:25
@ Convex
Definition BuildVolume.hpp:27
@ Custom
Definition BuildVolume.hpp:29
@ Rectangle
Definition BuildVolume.hpp:23
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81

References _get_volumes_clipping_plane(), _is_realistic_view_enabled(), _is_xray_view_active(), _render_imex_ghosts(), _render_imex_ghosts_xray(), _render_objects(), _render_section_view_caps(), _render_xray_volumes(), _static_light_dir_eye(), Slic3r::GUI::GLGizmoBase::apply_clipping_plane(), camera, CanvasAssembleView, Slic3r::Circle, Slic3r::GUI::ClippingPlane::ClipsNothing(), Slic3r::Convex, Slic3r::Custom, get_canvas_size(), Slic3r::GUI::GLGizmosManager::get_current(), get_gizmos_manager(), Slic3r::GLShaderProgram::get_name(), GL_DEPTH_TEST, GL_TEXTURE0, GL_TEXTURE4, GL_TEXTURE_2D, glActiveTexture, glBindTexture, glEnable, glsafe, Slic3r::BoundingBox3Base< PointType >::inflated(), is_layers_editing_enabled(), m_bed, m_camera_clipping_plane, m_canvas_type, m_clipping_planes, m_gizmos, m_layers_editing, m_model, m_picking_enabled, m_requires_check_outside_state, m_selection, m_shadow_light_vp, m_shadow_map_size, m_shadow_map_texture_id, m_shadow_map_valid, m_sinking_contours_enabled, m_studio_lighting, m_use_clipping_planes, m_volumes, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::GLVolumeCollection::Opaque, Slic3r::Rectangle, Slic3r::GUI::GLGizmosManager::render_painter_gizmo(), Slic3r::BuildVolume::SceneEpsilon, Slic3r::GLShaderProgram::set_uniform(), SETTING_OPENGL_PHONG_SSAO, SETTING_OPENGL_REALISTIC_PHONG, Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), Slic3r::GLVolumeCollection::Transparent, and Slic3r::unscaled().

Referenced by _render_objects(), and _render_scene().

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

◆ _render_orient_menu()

bool Slic3r::GUI::GLCanvas3D::_render_orient_menu ( float left,
float right,
float bottom,
float top )
private
6562{
6563 ImGuiWrapper* imgui = wxGetApp().imgui();
6564
6565 auto canvas_w = float(get_canvas_size().get_width());
6566 auto canvas_h = float(get_canvas_size().get_height());
6567 //BBS: GUI refactor: move main toolbar to the right
6568 //original use center as {0.0}, and top is (canvas_h/2), bottom is (-canvas_h/2), also plus inv_camera
6569 //now change to left_up as {0,0}, and top is 0, bottom is canvas_h
6570#if BBS_TOOLBAR_ON_TOP
6571 const float x = (1 + left) * canvas_w / 2;
6573 imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
6574#else
6575 const float x = canvas_w - m_main_toolbar.get_width();
6576 const float y = 0.5f * canvas_h - top * float(wxGetApp().plater()->get_camera().get_zoom());
6577 imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f);
6578#endif
6579
6580 imgui->begin(_L("Auto orientation options"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
6581
6583 OrientSettings& settings_out = get_orient_settings();
6584
6585 auto& appcfg = wxGetApp().app_config;
6587
6588 bool settings_changed = false;
6589 float angle_min = 45.f;
6590 std::string angle_key = "overhang_angle", rot_key = "enable_rotation";
6591 std::string key_min_area = "min_area";
6592 std::string postfix = "_fff";
6593
6594 if (ptech == ptSLA) {
6595 angle_min = 45.f;
6596 postfix = "_sla";
6597 }
6598
6599
6600 angle_key += postfix;
6601 rot_key += postfix;
6602
6603 //if (imgui->slider_float(_L("Overhang Angle"), &settings.overhang_angle, angle_min, 90.0f, "%5.2f") || angle_min > settings.overhang_angle) {
6604 // settings.overhang_angle = std::max(angle_min, settings.overhang_angle);
6605 // settings_out.overhang_angle = settings.overhang_angle;
6606 // appcfg->set("orient", angle_key, std::to_string(settings_out.overhang_angle));
6607 // settings_changed = true;
6608 //}
6609
6610 if (imgui->checkbox(_L("Enable rotation"), settings.enable_rotation)) {
6611 settings_out.enable_rotation = settings.enable_rotation;
6612 appcfg->set("orient", rot_key, settings_out.enable_rotation ? "1" : "0");
6613 settings_changed = true;
6614 }
6615
6616 if (imgui->checkbox(_L("Optimize support interface area"), settings.min_area)) {
6617 settings_out.min_area = settings.min_area;
6618 appcfg->set("orient", key_min_area, settings_out.min_area ? "1" : "0");
6619 settings_changed = true;
6620 }
6621
6622 ImGui::Separator();
6623
6624 if (imgui->button(_L("Orient"))) {
6625 wxGetApp().plater()->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
6626 wxGetApp().plater()->orient();
6627 }
6628
6629 ImGui::SameLine();
6630
6631 if (imgui->button(_L("Reset"))) {
6632 settings_out = OrientSettings{};
6633 settings_out.overhang_angle = 60.f;
6634 appcfg->set("orient", angle_key, std::to_string(settings_out.overhang_angle));
6635 appcfg->set("orient", rot_key, settings_out.enable_rotation ? "1" : "0");
6636 appcfg->set("orient", key_min_area, settings_out.min_area? "1" : "0");
6637 settings_changed = true;
6638 }
6639
6640 imgui->end();
6642 return settings_changed;
6643}
OrientSettings & get_orient_settings()
Definition GLCanvas3D.hpp:840
float overhang_angle
Definition GLCanvas3D.hpp:618
Definition GLCanvas3D.hpp:617

References _L, Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::button(), Slic3r::GUI::ImGuiWrapper::checkbox(), current_printer_technology(), Slic3r::GUI::GLCanvas3D::OrientSettings::enable_rotation, Slic3r::GUI::ImGuiWrapper::end(), get_camera(), get_canvas_size(), get_orient_settings(), get_scale(), m_main_toolbar, Slic3r::GUI::GLCanvas3D::OrientSettings::min_area, Slic3r::GUI::GLCanvas3D::OrientSettings::overhang_angle, Slic3r::GUI::plater(), Slic3r::GUI::ImGuiWrapper::pop_toolbar_style(), Slic3r::GUI::Job::PREPARE_STATE_DEFAULT, Slic3r::ptSLA, Slic3r::GUI::ImGuiWrapper::push_toolbar_style(), and Slic3r::GUI::ImGuiWrapper::set_next_window_pos().

Here is the call graph for this function:

◆ _render_overlay_toolbars()

void Slic3r::GUI::GLCanvas3D::_render_overlay_toolbars ( )
private
10143{
10145
10151 //BBS: GUI refactor: GLToolbar
10152 //move gizmos behind of main
10154
10155 if (m_layers_editing.last_object_id >= 0 && m_layers_editing.object_max_z() > 0.0f)
10156 m_layers_editing.render_overlay(*this);
10157}
void _render_gizmos_overlay()
Definition GLCanvas3D.cpp:10311
void _render_main_toolbar()
Definition GLCanvas3D.cpp:10350
void _render_assemble_view_toolbar() const
Definition GLCanvas3D.cpp:10919
void _render_separator_toolbar_left() const
Definition GLCanvas3D.cpp:11363
void _render_separator_toolbar_right() const
Definition GLCanvas3D.cpp:11347
void _render_collapse_toolbar() const
Definition GLCanvas3D.cpp:11377

References _render_assemble_view_toolbar(), _render_collapse_toolbar(), _render_gizmos_overlay(), _render_main_toolbar(), _render_overlay_toolbars(), _render_separator_toolbar_left(), _render_separator_toolbar_right(), GL_DEPTH_TEST, glDisable, glsafe, and m_layers_editing.

Referenced by _render_frame(), and _render_overlay_toolbars().

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

◆ _render_overlays()

void Slic3r::GUI::GLCanvas3D::_render_overlays ( )
private
10088{
10090
10093
10094 //BBS: GUI refactor: GLToolbar
10098 // BBS
10099 //_render_view_toolbar();
10101
10102 // The options window of a pressed toolbar item (arrange).
10103 m_main_toolbar.render_item_windows(*this);
10104
10105 m_gizmos.render_overlay_input_window();
10106
10107 if (m_layers_editing.last_object_id >= 0 && m_layers_editing.object_max_z() > 0.0f)
10108 m_layers_editing.render_variable_layer_height_dialog(*this);
10109
10110 auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
10111 auto curr_print_seq = curr_plate->get_real_print_seq();
10112 const Print* print = fff_print();
10113 bool sequential_print = (curr_print_seq == PrintSequence::ByObject) || print->config().print_order == PrintOrder::AsObjectList;
10114 std::vector<const ModelInstance*> sorted_instances;
10115 if (sequential_print) {
10116 if (print) {
10117 for (const PrintObject *print_object : print->objects())
10118 {
10119 for (const PrintInstance &instance : print_object->instances())
10120 {
10121 sorted_instances.emplace_back(instance.model_instance);
10122 }
10123 }
10124 }
10125 /*for (ModelObject* model_object : m_model->objects)
10126 for (ModelInstance* model_instance : model_object->instances) {
10127 sorted_instances.emplace_back(model_instance);
10128 }*/
10129 }
10130 m_labels.render(sorted_instances);
10131 m_center_of_mass.render_details(*this);
10132
10134
10136
10137 // Recorded by the scene pass, which a reused frame skips.
10138 wxGetApp().plater()->get_partplate_list().render_hover_tooltip();
10139}
void _render_canvas_toolbar()
Definition GLCanvas3D.cpp:11011
void _render_assemble_info() const
Definition GLCanvas3D.cpp:11687
void _render_imgui_select_plate_toolbar()
Definition GLCanvas3D.cpp:10396
CenterOfMass m_center_of_mass
Definition GLCanvas3D.hpp:814
void _render_paint_toolbar() const
Definition GLCanvas3D.cpp:11399
void _render_3d_navigator()
Definition GLCanvas3D.cpp:6774
void _render_return_toolbar() const
Definition GLCanvas3D.cpp:10935
void _check_and_update_toolbar_icon_scale()
Definition GLCanvas3D.cpp:10000
void _render_assemble_control()
Definition GLCanvas3D.cpp:11589
void _render_plate_switcher()
Definition GLCanvas3D.cpp:10819
@ AsObjectList
Definition PrintConfig.hpp:320

References _check_and_update_toolbar_icon_scale(), _render_3d_navigator(), _render_assemble_control(), _render_assemble_info(), _render_canvas_toolbar(), _render_imgui_select_plate_toolbar(), _render_overlays(), _render_paint_toolbar(), _render_plate_switcher(), _render_return_toolbar(), Slic3r::AsObjectList, Slic3r::ByObject, Slic3r::Print::config(), fff_print(), m_center_of_mass, m_gizmos, m_labels, m_layers_editing, m_main_toolbar, and Slic3r::Print::objects().

Referenced by _render_frame(), and _render_overlays().

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

◆ _render_paint_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_paint_toolbar ( ) const
private
11400{
11402 return;
11403#if ENABLE_RETINA_GL
11404 float f_scale = m_retina_helper->get_scale_factor();
11405#else
11406 float f_scale = 1.0f;
11407#endif
11408 int em_unit = wxGetApp().em_unit() / 10;
11409
11410 std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
11411 int extruder_num = colors.size();
11412 std::vector<std::string> filament_text_first_line;
11413 std::vector<std::string> filament_text_second_line;
11414 {
11415 auto preset_bundle = wxGetApp().preset_bundle;
11416 for (auto filament_name : preset_bundle->filament_presets) {
11417 for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); iter++) {
11418 if (filament_name.compare(iter->name) == 0) {
11419 std::string display_filament_type;
11420 iter->config.get_filament_type(display_filament_type);
11421 auto pos = display_filament_type.find(' ');
11422 if (pos != std::string::npos) {
11423 filament_text_first_line.push_back(display_filament_type.substr(0, pos));
11424 filament_text_second_line.push_back(display_filament_type.substr(pos + 1));
11425 }
11426 else {
11427 filament_text_first_line.push_back(display_filament_type);
11428 filament_text_second_line.push_back("");
11429 }
11430 }
11431 }
11432 }
11433 }
11434 // ORCA: the loop above only labels a slot whose preset was found in the preset collection,
11435 // while the render loop below iterates extruder_num. Pad the label arrays so a slot without a
11436 // matching preset cannot index past them; a garbage std::string crashes ImGui::CalcTextSize.
11437 while (int(filament_text_first_line.size()) < extruder_num) {
11438 filament_text_first_line.emplace_back();
11439 filament_text_second_line.emplace_back();
11440 }
11441
11442 ImGuiWrapper& imgui = *wxGetApp().imgui();
11443 const float canvas_w = float(get_canvas_size().get_width());
11444 const ImVec2 button_size = ImVec2(64.0f, 48.0f) * f_scale * em_unit;
11445 const float spacing = 4.0f * em_unit * f_scale;
11446 const float return_button_margin = 130.0f * em_unit * f_scale;
11447
11448 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(spacing, spacing));
11449 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
11450 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, 0));
11451 ImGui::PushStyleColor(ImGuiCol_WindowBg, m_is_dark ? ImGuiWrapper::COL_TOOLBAR_BG_DARK : ImGuiWrapper::COL_TOOLBAR_BG); // ORCA Toolbar color
11452
11453 imgui.set_next_window_pos(0.5f * canvas_w, 0, ImGuiCond_Always, 0.5f, 0.0f);
11454 float constraint_window_width = canvas_w - 2 * return_button_margin;
11455 ImGui::SetNextWindowSizeConstraints({ 0, 0 }, { constraint_window_width, FLT_MAX });
11456 imgui.begin(_L("Paint Toolbar"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
11457
11458 const float cursor_y = ImGui::GetCursorPosY();
11459 const ImVec2 arrow_button_size = ImVec2(0.375f * button_size.x, ImGui::GetWindowHeight());
11460 const ImRect left_arrow_button = ImRect(ImGui::GetCurrentWindow()->Pos, ImGui::GetCurrentWindow()->Pos + arrow_button_size);
11461 const ImRect right_arrow_button = ImRect(ImGui::GetCurrentWindow()->Pos + ImGui::GetWindowSize() - arrow_button_size, ImGui::GetCurrentWindow()->Pos + ImGui::GetWindowSize());
11462 ImU32 left_arrow_button_color = IM_COL32(0, 0, 0, 0.4f * 255);
11463 ImU32 right_arrow_button_color = IM_COL32(0, 0, 0, 0.4f * 255);
11464 ImU32 arrow_color = IM_COL32(255, 255, 255, 255);
11465 ImDrawList* draw_list = ImGui::GetWindowDrawList();
11466 ImGuiContext& context = *GImGui;
11467 bool disabled = !wxGetApp().plater()->can_fillcolor();
11468 ColorRGBA rgba;
11469
11470 // Gradient mixed filaments fade over Z, so their swatch is drawn as that fade rather than
11471 // the single blended colour in `colors`. Every other slot's ramp is empty.
11472 const auto& gradient_ramps = wxGetApp().plater()->get_filament_gradient_ramps();
11473
11474 for (int i = 0; i < extruder_num; i++) {
11475 if (i > 0)
11476 ImGui::SameLine();
11477 decode_color(colors[i], rgba);
11478 ImGui::PushStyleColor(ImGuiCol_Button, ImGuiWrapper::to_ImVec4(rgba));
11479 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGuiWrapper::to_ImVec4(rgba));
11480 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGuiWrapper::to_ImVec4(rgba));
11481 if (disabled)
11482 ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
11483 if (ImGui::Button(("##filament_button" + std::to_string(i)).c_str(), button_size)) {
11484 if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max))
11485 wxPostEvent(m_canvas, IntEvent(EVT_GLTOOLBAR_FILLCOLOR, i + 1));
11486 }
11487 if (i < (int) gradient_ramps.size() && !gradient_ramps[i].empty())
11488 ImGuiWrapper::draw_gradient_ramp(draw_list, ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), gradient_ramps[i]);
11489 if (ImGui::IsItemHovered() && i < 9) {
11490 if (!ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max) && !ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max)) {
11491 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 20.0f * f_scale, 10.0f * f_scale });
11492 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3.0f * f_scale);
11493 imgui.tooltip(wxString::Format(_L("Shortcut Key %d"), i + 1), ImGui::GetFontSize() * 20.0f);
11494 ImGui::PopStyleVar(2);
11495 }
11496 }
11497 ImGui::PopStyleColor(3);
11498 if (disabled)
11499 ImGui::PopItemFlag();
11500 }
11501
11502 const float text_offset_y = 4.0f * em_unit * f_scale;
11503 for (int i = 0; i < extruder_num; i++) {
11504 // A gradient slot's swatch shows its fade instead of the blended colour in `colors`, so the
11505 // labels take their contrast from the colour printed at the middle of the fade they sit on.
11506 if (i < (int) gradient_ramps.size() && !gradient_ramps[i].empty()) {
11507 const wxColour& c = gradient_ramps[i][gradient_ramps[i].size() / 2];
11508 rgba = ColorRGBA(c.Red(), c.Green(), c.Blue(), c.Alpha());
11509 } else
11510 decode_color(colors[i], rgba);
11511 float gray = 0.299 * rgba.r_uchar() + 0.587 * rgba.g_uchar() + 0.114 * rgba.b_uchar();
11512 ImVec4 text_color = gray < 80 ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) : ImVec4(0, 0, 0, 1.0f);
11513
11514 imgui.push_bold_font();
11515 ImVec2 number_label_size = ImGui::CalcTextSize(std::to_string(i + 1).c_str());
11516 ImGui::SetCursorPosY(cursor_y + text_offset_y);
11517 ImGui::SetCursorPosX(spacing + i * (spacing + button_size.x) + (button_size.x - number_label_size.x) / 2);
11518 ImGui::TextColored(text_color, "%s", std::to_string(i + 1).c_str());
11519 imgui.pop_bold_font();
11520
11521 ImVec2 filament_first_line_label_size = ImGui::CalcTextSize(filament_text_first_line[i].c_str());
11522 ImGui::SetCursorPosY(cursor_y + text_offset_y + number_label_size.y);
11523 ImGui::SetCursorPosX(spacing + i * (spacing + button_size.x) + (button_size.x - filament_first_line_label_size.x) / 2);
11524 ImGui::TextColored(text_color, "%s", filament_text_first_line[i].c_str());
11525
11526 ImVec2 filament_second_line_label_size = ImGui::CalcTextSize(filament_text_second_line[i].c_str());
11527 ImGui::SetCursorPosY(cursor_y + text_offset_y + number_label_size.y + filament_first_line_label_size.y);
11528 ImGui::SetCursorPosX(spacing + i * (spacing + button_size.x) + (button_size.x - filament_second_line_label_size.x) / 2);
11529 ImGui::TextColored(text_color, "%s", filament_text_second_line[i].c_str());
11530 }
11531
11532 if (ImGui::GetWindowWidth() == constraint_window_width) {
11533 if (ImGui::IsMouseHoveringRect(left_arrow_button.Min, left_arrow_button.Max)) {
11534 left_arrow_button_color = IM_COL32(0, 0, 0, 0.64f * 255);
11535 if (context.IO.MouseClicked[ImGuiMouseButton_Left]) {
11536 ImGui::SetScrollX(ImGui::GetScrollX() - button_size.x);
11537 imgui.set_requires_extra_frame();
11538 }
11539 }
11540 draw_list->AddRectFilled(left_arrow_button.Min, left_arrow_button.Max, left_arrow_button_color);
11541 ImGui::BBLRenderArrow(draw_list, left_arrow_button.GetCenter() - ImVec2(draw_list->_Data->FontSize, draw_list->_Data->FontSize) * 0.5f, arrow_color, ImGuiDir_Left, 2.0f);
11542
11543 if (ImGui::IsMouseHoveringRect(right_arrow_button.Min, right_arrow_button.Max)) {
11544 right_arrow_button_color = IM_COL32(0, 0, 0, 0.64f * 255);
11545 if (context.IO.MouseClicked[ImGuiMouseButton_Left]) {
11546 ImGui::SetScrollX(ImGui::GetScrollX() + button_size.x);
11547 imgui.set_requires_extra_frame();
11548 }
11549 }
11550 draw_list->AddRectFilled(right_arrow_button.Min, right_arrow_button.Max, right_arrow_button_color);
11551 ImGui::BBLRenderArrow(draw_list, right_arrow_button.GetCenter() - ImVec2(draw_list->_Data->FontSize, draw_list->_Data->FontSize) * 0.5f, arrow_color, ImGuiDir_Right, 2.0f);
11552 }
11553
11554 m_paint_toolbar_width = (ImGui::GetWindowWidth() + 50.0f * em_unit * f_scale);
11555 imgui.end();
11556 ImGui::PopStyleVar(3);
11557 ImGui::PopStyleColor();
11558}
struct IMGUI_API ImRect
Definition IMSlider.hpp:19
const wxColour text_color(107, 107, 107)
float m_paint_toolbar_width
Definition GLCanvas3D.hpp:671
static void draw_gradient_ramp(ImDrawList *draw_list, const ImVec2 &top_left, const ImVec2 &bottom_right, const std::vector< wxColour > &ramp)
Fill a rect with a filament gradient ramp, one band per pixel row, ramp.front() along the bottom edge...
Definition ImGuiWrapper.cpp:2568
static wxColour decode_color(const std::string &color)
Definition SliceInfoPanel.cpp:51
@ disabled
Definition GLGizmoEmboss.cpp:223
int em_unit(wxWindow *win)
Definition wxExtensions.cpp:424

References _L, _render_paint_toolbar(), Slic3r::ColorRGBA::b_uchar(), Slic3r::GUI::ImGuiWrapper::begin(), CanvasAssembleView, Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG, Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG_DARK, Slic3r::decode_color(), Slic3r::GUI::ImGuiWrapper::draw_gradient_ramp(), em_unit(), Slic3r::GUI::ImGuiWrapper::end(), Slic3r::ColorRGBA::g_uchar(), get_canvas_size(), ImRect, m_canvas, m_canvas_type, m_is_dark, m_paint_toolbar_width, Slic3r::GUI::ImGuiWrapper::pop_bold_font(), Slic3r::GUI::ImGuiWrapper::push_bold_font(), Slic3r::ColorRGBA::r_uchar(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), Slic3r::GUI::ImGuiWrapper::set_requires_extra_frame(), text_color(), Slic3r::GUI::ImGuiWrapper::to_ImVec4(), and Slic3r::GUI::ImGuiWrapper::tooltip().

Referenced by _render_overlays(), and _render_paint_toolbar().

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

◆ _render_plane()

void Slic3r::GUI::GLCanvas3D::_render_plane ( ) const
private
9529{
9530 ;//TODO render assemble plane
9531}

References _render_plane().

Referenced by _render_plane(), and _render_scene().

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

◆ _render_plate_switcher()

void Slic3r::GUI::GLCanvas3D::_render_plate_switcher ( )
private
10820{
10821 Plater* plater = wxGetApp().plater();
10822 PartPlateList& plate_list = plater->get_partplate_list();
10823 const int plate_count = plate_list.get_plate_count();
10824 if (!_hides_inactive_plates() || plate_count < 2 || m_gizmos.get_current_type() != GLGizmosManager::Undefined)
10825 return;
10826
10827 // The thumbnails are the ones of the Preview plate toolbar.
10828 const unsigned version = plater->plate_toolbar_image_version();
10829 if (m_plate_switcher_version != version || m_plate_switcher_items.size() != size_t(plate_count)) {
10830 // Only the current plate is edited here; the others are redrawn when their thumbnails go invalid.
10831 for (int i = 0; i < plate_count && !plater->is_gcode_3mf(); ++i)
10832 plater->update_plate_thumbnails(i, i == plate_list.get_curr_plate_index());
10833 m_plate_switcher_items.clear();
10834 for (int i = 0; i < plate_count; ++i) {
10835 m_plate_switcher_items.push_back(std::make_unique<IMToolbarItem>());
10836 m_plate_switcher_items.back()->set_thumbnail(plate_list.get_plate(i)->thumbnail_data);
10837 }
10838 m_plate_switcher_version = version;
10839 }
10840
10841 float sc = get_scale();
10842#ifdef WIN32
10843 sc *= (float) get_dpi_for_window(wxGetApp().GetTopWindow()) / (float) DPI_DEFAULT;
10844#endif // WIN32
10845
10846 ImGuiWrapper& imgui = *wxGetApp().imgui();
10847 const ImVec2 btn_size = ImVec2(72.f, 72.f) * sc;
10848 const ImVec2 padding = ImVec2(8.f, 8.f) * sc;
10849 const float spacing = 8.f * sc;
10850 const float rounding = 4.f * sc;
10851 const float scrollbar = PLATE_TOOLBAR_SCROLLBAR * sc;
10852 const float top = std::max(m_main_toolbar.get_height(), m_gizmos.get_scaled_total_height()) + CANVAS_TOOLBAR_MARGIN * sc;
10853 const float content_h = plate_count * (btn_size.y + spacing) - spacing + 2.f * padding.y;
10854 const float max_h = std::max(btn_size.y + 2.f * padding.y, float(get_canvas_size().get_height()) - top - (canvas_corner_height() + CANVAS_TOOLBAR_MARGIN) * sc);
10855 // As in the Preview plate toolbar, the scrollbar shows only while the mouse is over the column.
10856 const bool scroll = m_plate_switcher_scrollbar && content_h > max_h;
10857
10858 const ImVec4 text_color = m_is_dark ? ImVec4(.9f, .9f, .9f, 1.f) : ImVec4(.3f, .3f, .3f, 1.f);
10859 const ImVec4 empty_color = ImVec4(text_color.x, text_color.y, text_color.z, .45f);
10860 const ImVec4 hover = plate_toolbar_hover_color(m_is_dark);
10861 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
10862 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
10863 // Concentric with the thumbnails; tighter around the scrollbar, as in the Preview plate toolbar.
10864 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, scroll ? 6.f * sc : rounding + padding.x);
10865 ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.f);
10866 ImGui::PushStyleColor(ImGuiCol_WindowBg, m_is_dark ? ImVec4(.13f, .13f, .15f, .5f) : ImVec4(1.f, 1.f, 1.f, .7f));
10868
10869 imgui.set_next_window_pos(CANVAS_TOOLBAR_MARGIN * sc, top, ImGuiCond_Always, 0.f, 0.f);
10870 imgui.set_next_window_size(btn_size.x + 2.f * padding.x + (scroll ? scrollbar : 0.f), std::min(content_h, max_h), ImGuiCond_Always);
10871 imgui.begin(std::string("##PlateSwitcher"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
10872 ImGuiWindowFlags_NoCollapse | (scroll ? 0 : ImGuiWindowFlags_NoScrollbar));
10873
10874 const int curr_plate = plate_list.get_curr_plate_index();
10875 ImDrawList* draw_list = ImGui::GetWindowDrawList();
10876 const ImU32 plate_bg = m_is_dark ? IM_COL32(255, 255, 255, 10) : IM_COL32(0, 0, 0, 10);
10877 const ImU32 plate_dim = m_is_dark ? IM_COL32(30, 30, 30, 100) : IM_COL32(0, 0, 0, 50);
10878 for (int i = 0; i < plate_count; ++i) {
10879 PartPlate* plate = plate_list.get_plate(i);
10880 const bool current = i == curr_plate;
10881 const ImVec2 pos = ImGui::GetCursorScreenPos();
10882 ImGui::PushID(i);
10883 const bool clicked = ImGui::InvisibleButton("##plate", btn_size);
10884 ImGui::PopID();
10885 const bool hovered = ImGui::IsItemHovered();
10886
10887 draw_list->AddRectFilled(pos, pos + btn_size, plate_bg, rounding);
10888 if (ImTextureID texture = m_plate_switcher_items[i]->texture_id)
10889 draw_list->AddImageRounded(texture, pos, pos + btn_size, ImVec2(0.f, 1.f), ImVec2(1.f, 0.f), IM_COL32_WHITE, rounding);
10890 if (plate->empty())
10891 draw_list->AddRectFilled(pos, pos + btn_size, plate_dim, rounding);
10892 if (current || hovered) {
10893 const float border = 2.f * sc;
10894 draw_list->AddRect(pos - ImVec2(border, border) * .5f, pos + btn_size + ImVec2(border, border) * .5f,
10895 ImGui::GetColorU32(current ? (hovered ? ImGuiWrapper::COL_ORCA_HOVER : ImGuiWrapper::COL_ORCA) : hover),
10896 rounding + border * .5f, 0, border);
10897 }
10898 draw_list->AddText(pos + ImVec2(4.f, 2.f) * sc, ImGui::GetColorU32(plate->empty() ? empty_color : text_color), std::to_string(i + 1).c_str());
10899
10900 if (clicked && !current)
10901 plater->CallAfter([i]() {
10902 wxGetApp().plater()->select_plate(i);
10903 wxGetApp().plater()->deselect_all();
10904 });
10905 if (hovered) {
10906 const std::string name = plate->get_plate_name();
10907 imgui.tooltip(_u8L("Plate") + " " + std::to_string(i + 1) + (name.empty() ? "" : " (" + name + ")"), ImGui::GetFontSize() * 20.f);
10908 }
10909 }
10910
10912 imgui.end();
10913 ImGui::PopStyleColor(5);
10914 ImGui::PopStyleVar(5);
10915}
unsigned m_plate_switcher_version
Definition GLCanvas3D.hpp:665
bool m_plate_switcher_scrollbar
Definition GLCanvas3D.hpp:666
int get_plate_count() const
Definition PartPlate.cpp:7042
void update_plate_thumbnails(int plate_idx, bool force_update)
Definition Plater.cpp:18354
bool is_gcode_3mf()
Definition Plater.hpp:418
PartPlateList & get_partplate_list()
Definition Plater.cpp:22578
unsigned plate_toolbar_image_version() const
Definition Plater.hpp:1080
static float canvas_corner_height()
Definition GLCanvas3D.cpp:2441
@ hovered
Definition GLGizmoEmboss.cpp:223

References _hides_inactive_plates(), _render_plate_switcher(), _u8L, Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::canvas_corner_height(), Slic3r::GUI::CANVAS_TOOLBAR_MARGIN, Slic3r::GUI::ImGuiWrapper::COL_ORCA, Slic3r::GUI::ImGuiWrapper::COL_ORCA_HOVER, Slic3r::GUI::DPI_DEFAULT, Slic3r::GUI::PartPlate::empty(), Slic3r::GUI::ImGuiWrapper::end(), get_canvas_size(), Slic3r::GUI::PartPlateList::get_curr_plate_index(), Slic3r::GUI::get_dpi_for_window(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), Slic3r::GUI::PartPlate::get_plate_name(), get_scale(), m_gizmos, m_is_dark, m_main_toolbar, m_plate_switcher_items, m_plate_switcher_scrollbar, m_plate_switcher_version, Slic3r::GUI::plate_toolbar_hover_color(), Slic3r::GUI::plate_toolbar_keeps_scrollbar(), Slic3r::GUI::PLATE_TOOLBAR_SCROLLBAR, Slic3r::GUI::plater(), Slic3r::GUI::push_plate_toolbar_scrollbar_style(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), Slic3r::GUI::ImGuiWrapper::set_next_window_size(), text_color(), Slic3r::GUI::PartPlate::thumbnail_data, Slic3r::GUI::ImGuiWrapper::tooltip(), and Slic3r::GUI::GLGizmosManager::Undefined.

Referenced by _render_overlays(), and _render_plate_switcher().

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

◆ _render_platelist()

void Slic3r::GUI::GLCanvas3D::_render_platelist ( const Transform3d & view_matrix,
const Transform3d & projection_matrix,
bool bottom,
bool only_current,
bool only_body = false,
int hover_id = -1,
bool render_cali = false,
bool show_grid = true )
private
9060{
9061 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
9062 // Design tab: its bed stays at the printer bed's home whichever plate is current, so the
9063 // current plate's exclude areas are moved from that plate onto it.
9064 PartPlate* curr_plate = plate_list.get_curr_plate();
9065 const Transform3d plate_view_matrix = m_design_canvas && curr_plate != nullptr ?
9066 Transform3d(view_matrix * Geometry::translation_transform(-curr_plate->get_origin())) : view_matrix;
9067 plate_list.render(plate_view_matrix, projection_matrix, bottom, only_current, only_body, hover_id, render_cali, show_grid, !m_plate_chrome_enabled, _hides_inactive_plates());
9068}
bool m_plate_chrome_enabled
Definition GLCanvas3D.hpp:676
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:346

References _hides_inactive_plates(), _render_platelist(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::get_origin(), m_design_canvas, m_plate_chrome_enabled, Slic3r::GUI::PartPlateList::render(), and Slic3r::Geometry::translation_transform().

Referenced by _render_platelist(), and _render_scene().

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

◆ _render_return_toolbar()

void Slic3r::GUI::GLCanvas3D::_render_return_toolbar ( ) const
private
10936{
10937 if (!m_return_toolbar.is_enabled())
10938 return;
10939
10940 float font_size = ImGui::GetFontSize();
10941 ImVec2 real_size = ImVec2(font_size * 4, font_size * 1.7);
10942 ImVec2 button_icon_size = ImVec2(font_size * .55, font_size * 1.1); // ORCA
10943
10944 ImGuiWrapper& imgui = *wxGetApp().imgui();
10945 Size cnv_size = get_canvas_size();
10946 auto canvas_w = float(cnv_size.get_width());
10947 auto canvas_h = float(cnv_size.get_height());
10948 float window_width = real_size.x + button_icon_size.x + imgui.scaled(2.0f);
10949 float window_height = button_icon_size.y + imgui.scaled(2.0f);
10950 float window_pos_x = 30.0f + (is_collapse_toolbar_on_left() ? (get_collapse_toolbar_width() + 5.f) : 0);
10951 float window_pos_y = 14.0f;
10952
10953 imgui.set_next_window_pos(window_pos_x, window_pos_y, ImGuiCond_Always, 0, 0);
10954#ifdef __WINDOWS__
10955 imgui.set_next_window_size(window_width, window_height, ImGuiCond_Always);
10956#endif
10957
10958 ImVec4 fg_color = m_is_dark ? ImVec4(1.f, 1.f, 1.f, 0.88f) : ImVec4(50 / 255.f, 58 / 255.f, 61 / 255.f, 1.f);
10960 ImVec4 bg_color_hover = bg_color + (m_is_dark ? ImVec4(.03f, .03f, .03f, 0) : ImVec4(-.02f, -.02f, -.02f, 0));
10961
10962 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 18.0f);
10963 ImGui::PushStyleColor(ImGuiCol_Button, bg_color); // ORCA Toolbar color
10964 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, bg_color_hover);
10965 ImGui::PushStyleColor(ImGuiCol_ButtonActive, bg_color);
10966 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
10967 ImGui::PushStyleColor(ImGuiCol_Text, fg_color);
10968
10969 imgui.begin(_L("Assembly Return"), ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground
10970 | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse);
10971
10972 float button_width = 20;
10973 float button_height = 20;
10974 ImVec2 size = ImVec2(button_width, button_height); // Size of the image we want to make visible
10975 ImVec2 uv0 = ImVec2(0.0f, 0.0f);
10976 ImVec2 uv1 = ImVec2(1.0f, 1.0f);
10977
10978 ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
10979 ImVec4 tint_col = fg_color; // icon color
10980 ImVec2 margin = ImVec2(10.0f, 5.0f);
10981
10982 if (ImGui::ImageTextButton(real_size,_utf8(L("Return")).c_str(), m_return_toolbar.get_return_texture_id(), button_icon_size, uv0, uv1, -1, bg_col, tint_col, margin)) {
10983 const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
10984 if (m_canvas != nullptr && !wxGetApp().is_closing()) {
10985 m_canvas->CallAfter([]() {
10986 auto& app = wxGetApp();
10987 if (app.is_closing())
10988 return;
10989
10990 auto* plater = app.plater();
10991 if (plater == nullptr)
10992 return;
10993
10994 plater->select_view_3D("3D");
10995
10996 auto* view3d_canvas = plater->get_view3D_canvas3D();
10997 if (view3d_canvas == nullptr)
10998 return;
10999
11000 view3d_canvas->get_gizmos_manager().reset_all_states();
11001 view3d_canvas->reload_scene(true);
11002 });
11003 }
11004 }
11005 ImGui::PopStyleColor(5);
11006 ImGui::PopStyleVar(1);
11007
11008 imgui.end();
11009}
float get_collapse_toolbar_width() const
Definition GLCanvas3D.cpp:2421
void reset_all_states()
Definition GLGizmosManager.cpp:440

References _L, _render_return_toolbar(), _utf8, Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG, Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG_DARK, Slic3r::GUI::ImGuiWrapper::end(), get_canvas_size(), get_collapse_toolbar_width(), Slic3r::GUI::Size::get_height(), Slic3r::GUI::Size::get_width(), is_collapse_toolbar_on_left(), L, m_canvas, m_gizmos, m_is_dark, m_return_toolbar, Slic3r::GUI::plater(), Slic3r::GUI::ImGuiWrapper::scaled(), Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), and Slic3r::GUI::ImGuiWrapper::set_next_window_size().

Referenced by _render_overlays(), and _render_return_toolbar().

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

◆ _render_scene()

void Slic3r::GUI::GLCanvas3D::_render_scene ( const Camera & camera,
const Size & cnv_size )
private
2775{
2776 // Recorded by PartPlate::render_icons() below, when it runs.
2777 wxGetApp().plater()->get_partplate_list().clear_hover_tooltip();
2779 // Invalidate the shadow map each frame; the View3D and Preview paths below rebuild it. This
2780 // keeps the Assemble canvas from sampling a stale map with an outdated light matrix.
2781 m_shadow_map_valid = false;
2783
2784 //BBS add partplater rendering logic
2785 bool only_current = false, only_body = false;
2786 const bool show_bed = is_bed_visible();
2787 bool show_grid = true;
2788 GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
2789 if (!m_main_toolbar.is_enabled()) {
2790 //only_body = true;
2791 only_current = true;
2792 }
2793 else if (gizmo_type == GLGizmosManager::BrimEars && !camera.is_looking_downward())
2794 show_grid = false;
2795 if (m_design_canvas)
2796 // Design tab: the plate grid is generated from the plate's front-left corner, so it
2797 // floats mid-cell under the modeling-origin triad. Suppress it here; a CAD grid centred
2798 // on the origin is rendered in its place (see _render_cad_grid).
2799 show_grid = false;
2800
2801 /* view3D render*/
2802 int hover_id = (m_hover_plate_idxs.size() > 0)?m_hover_plate_idxs.front():-1;
2804 // m_show_bed gates the plate list too: hiding the bed but leaving its grid and outline
2805 // floating would read as a rendering fault rather than a deliberate view option.
2806 if (show_bed) {
2807 bool show_axes = m_show_world_axes;
2808#ifdef SLIC3R_CAD
2809 // Design tab: while its reference planes are up they draw their own axes from the modeling
2810 // origin, where the bed's triad would otherwise sit on top of them.
2811 show_axes = show_axes && !(m_design_sketch_tool != nullptr && m_design_sketch_tool->draws_reference_axes());
2812#endif
2813 _render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
2814 }
2815 m_frame_profiler.mark("bed");
2816 // Exception: the painting gizmos hide the bed mesh on purpose and draw the plate instead,
2817 // so there the plate list is the only bed reference in the scene.
2818 if (show_bed || _is_below_plate_view_active()) //BBS: add outline logic
2819 _render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid);
2820 if (m_design_canvas && show_bed)
2821 // Design tab: replace the plate's corner-origin grid with the origin-centred CAD grid.
2822 _render_cad_grid(camera.get_view_matrix(), camera.get_projection_matrix());
2823 m_frame_profiler.mark("plates");
2824 //BBS: add outline logic
2825 // Depth pass for object-on-object and self shadows; consumed by the gouraud shader below.
2826 _render_shadows(camera.get_view_matrix(), camera.get_projection_matrix());
2827 m_frame_profiler.mark("shadows");
2830 m_frame_profiler.mark("objects");
2831 // Collision previews follow the same visibility rule as the bed.
2832 const bool show_exclusion_intersections = m_show_bed &&
2833 (!m_main_toolbar.is_enabled() ||
2834 (gizmo_type != GLGizmosManager::FdmSupports && gizmo_type != GLGizmosManager::Seam &&
2835 gizmo_type != GLGizmosManager::MmSegmentation && gizmo_type != GLGizmosManager::FuzzySkin));
2836 if (show_exclusion_intersections)
2837 wxGetApp().plater()->get_partplate_list().render_exclusion_volume_intersections(
2838 camera.get_view_matrix(), camera.get_projection_matrix());
2843 m_frame_profiler.mark("transparent");
2844 }
2845 /* preview render */
2847 // Before the shadow pass, so the cut away part casts no shadow.
2848 m_gcode_viewer.set_clipping_plane(_get_section_view_plane());
2852 m_frame_profiler.mark("objects");
2853 _render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), m_show_world_axes);
2854 m_frame_profiler.mark("bed");
2855 _render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, true, hover_id);
2856 m_frame_profiler.mark("plates");
2857 // Realistic view: the print casts a shadow onto the plate here as it does in View3D.
2858 _render_shadows(camera.get_view_matrix(), camera.get_projection_matrix());
2859 m_frame_profiler.mark("shadows");
2860 // BBS: GUI refactor: add canvas size as parameters
2861 _render_gcode(cnv_size.get_width(), cnv_size.get_height());
2862 m_frame_profiler.mark("gcode");
2863 }
2864 /* assemble render*/
2866 //BBS: add outline logic
2867 //if (m_show_world_axes) {
2868 // m_axes.render();
2869 //}
2872 //_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), show_axes);
2873 _render_plane();
2874 //BBS: add outline logic insteadof selection under assemble view
2875 //_render_selection();
2876 // BBS: add outline logic
2879 m_frame_profiler.mark("objects");
2880 }
2881
2883#if ENABLE_RENDER_SELECTION_CENTER
2884 _render_selection_center();
2885#endif // ENABLE_RENDER_SELECTION_CENTER
2886 // sidebar hints need to be rendered before the gizmos because the depth buffer
2887 // could be invalidated by the following gizmo render methods
2890
2891#if ENABLE_RAYCAST_PICKING_DEBUG
2892 if (m_picking_enabled && !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging())
2893 m_scene_raycaster.render_hit(camera);
2894#endif // ENABLE_RAYCAST_PICKING_DEBUG
2895
2896#if ENABLE_SHOW_CAMERA_TARGET
2897 _render_camera_target();
2898#endif // ENABLE_SHOW_CAMERA_TARGET
2899
2900 if (m_picking_enabled && m_rectangle_selection.is_dragging())
2901 m_rectangle_selection.render(*this);
2902 m_frame_profiler.mark("gizmos");
2903
2904 if (_is_ssao_enabled()) {
2905 _render_ssao_pass(static_cast<unsigned int>(cnv_size.get_width()), static_cast<unsigned int>(cnv_size.get_height()));
2906 m_frame_profiler.mark("ssao");
2907 }
2908
2910 _render_gcode_translucent(cnv_size.get_width(), cnv_size.get_height());
2911 m_frame_profiler.mark("gcode translucent");
2912 }
2913
2914 // After the occlusion pass, which would shade it as the surface behind it.
2915 m_center_of_mass.render(*this);
2916
2917 if (_is_fxaa_enabled()) {
2918 _render_fxaa_pass(static_cast<unsigned int>(cnv_size.get_width()), static_cast<unsigned int>(cnv_size.get_height()));
2919 m_frame_profiler.mark("fxaa");
2920 }
2921
2922 // Design tab: interactive 2D sketch overlay, drawn over the scene but
2923 // beneath the UI overlays (toolbars, labels).
2924#ifdef SLIC3R_CAD
2925 if (m_design_sketch_tool != nullptr && m_design_sketch_tool->has_display())
2926 m_design_sketch_tool->render(*this);
2927#endif
2928
2930 m_frame_profiler.mark("cache");
2931}
void _render_plane() const
Definition GLCanvas3D.cpp:9528
void _render_background()
Definition GLCanvas3D.cpp:8825
void _render_below_plate_volumes()
Definition GLCanvas3D.cpp:8925
void _render_cad_grid(const Transform3d &view_matrix, const Transform3d &projection_matrix)
Definition GLCanvas3D.cpp:9091
void _render_platelist(const Transform3d &view_matrix, const Transform3d &projection_matrix, bool bottom, bool only_current, bool only_body=false, int hover_id=-1, bool render_cali=false, bool show_grid=true)
Definition GLCanvas3D.cpp:9059
bool m_show_bed
Definition GLCanvas3D.hpp:684
void _render_bed(const Transform3d &view_matrix, const Transform3d &projection_matrix, bool bottom, bool show_axes)
Definition GLCanvas3D.cpp:8888
void _render_wireframe_overlay()
Definition GLCanvas3D.cpp:9865
void _render_current_gizmo() const
Definition GLCanvas3D.cpp:10302
void _render_objects(GLVolumeCollection::ERenderType type, bool with_outline=true)
Definition GLCanvas3D.cpp:9534
void _render_gcode(int canvas_width, int canvas_height)
Definition GLCanvas3D.cpp:9908
void _render_sequential_clearance()
Definition GLCanvas3D.cpp:9989
void _render_sla_slices()
Definition GLCanvas3D.cpp:11789
bool is_bed_visible() const
Definition GLCanvas3D.cpp:12126
void _render_selection_sidebar_hints()
Definition GLCanvas3D.hpp:1604
bool _is_ssao_enabled() const
Definition GLCanvas3D.cpp:8501
void _capture_scene_cache(const Camera &camera)
Definition GLCanvas3D.cpp:8810
void _render_fxaa_pass(unsigned int width, unsigned int height)
Definition GLCanvas3D.cpp:8674
void _render_ssao_pass(unsigned int width, unsigned int height)
Definition GLCanvas3D.cpp:8706
void _render_shadows(const Transform3d &view_matrix, const Transform3d &projection_matrix)
Definition GLCanvas3D.cpp:9180
void _render_selection()
Definition GLCanvas3D.cpp:9978
bool _is_fxaa_enabled() const
Definition GLCanvas3D.cpp:8487
void _render_gcode_translucent(int canvas_width, int canvas_height)
Definition GLCanvas3D.cpp:9932
EType
Definition GLGizmosManager.hpp:86
@ BrimEars
Definition GLGizmosManager.hpp:104
@ FuzzySkin
Definition GLGizmosManager.hpp:96
@ Seam
Definition GLGizmosManager.hpp:95
@ FdmSupports
Definition GLGizmosManager.hpp:94

References _capture_scene_cache(), _get_section_view_plane(), _is_below_plate_view_active(), _is_fxaa_enabled(), _is_ssao_enabled(), _render_background(), _render_bed(), _render_below_plate_volumes(), _render_cad_grid(), _render_current_gizmo(), _render_fxaa_pass(), _render_gcode(), _render_gcode_translucent(), _render_objects(), _render_plane(), _render_platelist(), _render_selection(), _render_selection_sidebar_hints(), _render_sequential_clearance(), _render_shadows(), _render_sla_slices(), _render_ssao_pass(), _render_wireframe_overlay(), Slic3r::GUI::GLGizmosManager::BrimEars, camera, CanvasAssembleView, CanvasPreview, CanvasView3D, Slic3r::GUI::GLGizmosManager::FdmSupports, Slic3r::GUI::GLGizmosManager::FuzzySkin, Slic3r::GUI::Size::get_height(), Slic3r::GUI::Size::get_width(), GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, glClear, glsafe, is_bed_visible(), m_canvas_type, m_center_of_mass, m_design_canvas, m_frame_profiler, m_gcode_viewer, m_gizmos, m_hover_plate_idxs, m_main_toolbar, m_mouse, m_picking_enabled, m_rectangle_selection, m_render_preview, m_scene_raycaster, m_shadow_map_valid, m_show_bed, m_show_world_axes, Slic3r::GUI::GLGizmosManager::MmSegmentation, Slic3r::GLVolumeCollection::Opaque, Slic3r::GUI::GLGizmosManager::Seam, and Slic3r::GLVolumeCollection::Transparent.

Referenced by _render_frame().

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

◆ _render_section_view_caps()

void Slic3r::GUI::GLCanvas3D::_render_section_view_caps ( )
private
9755{
9756 // A gizmo with its own clipper draws its own cut faces.
9757 const ClippingPlane plane = m_gizmos.get_clipping_plane().has_value() ? ClippingPlane::ClipsNothing() : _get_section_view_plane();
9758 if (!plane.is_active() || m_model == nullptr) {
9759 m_section_view_caps.clear();
9760 return;
9761 }
9762
9763 // Last frame's clippers are reused, so unchanged cuts are not recomputed.
9764 std::map<const GLVolume*, MeshClipper> caps;
9765 for (const GLVolume* volume : m_volumes.volumes) {
9766 if (!volume->is_active || volume->is_modifier || volume->is_wipe_tower || volume->volume_idx() < 0 ||
9767 volume->object_idx() >= int(m_model->objects.size()))
9768 continue;
9769 const ModelObject* object = m_model->objects[volume->object_idx()];
9770 if (volume->volume_idx() >= int(object->volumes.size()))
9771 continue;
9772 // Skip volumes the plane misses.
9773 const BoundingBoxf3& box = volume->transformed_bounding_box();
9774 if (std::abs(plane.distance(box.center())) > 0.5 * box.size().dot(plane.get_normal().cwiseAbs()))
9775 continue;
9776
9777 auto node = m_section_view_caps.extract(volume);
9778 MeshClipper& clipper = node ? caps.insert(std::move(node)).position->second : caps[volume];
9779 clipper.set_mesh(object->volumes[volume->volume_idx()]->mesh().its);
9780 clipper.set_plane(plane);
9781 clipper.set_transformation(Geometry::Transformation(volume->world_matrix()));
9782 // No cut face below the plate.
9783 if (m_canvas_type != CanvasAssembleView)
9784 clipper.set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
9785 clipper.render_cut({ 0.25f, 0.25f, 0.25f, 1.0f });
9786 }
9787 m_section_view_caps = std::move(caps);
9788}

References _get_section_view_plane(), _render_section_view_caps(), CanvasAssembleView, Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::GUI::ClippingPlane::ClipsNothing(), Slic3r::GUI::ClippingPlane::distance(), Slic3r::GUI::ClippingPlane::get_normal(), Slic3r::GUI::ClippingPlane::is_active(), m_canvas_type, m_gizmos, m_model, m_section_view_caps, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::GUI::MeshClipper::render_cut(), Slic3r::GUI::MeshClipper::set_limiting_plane(), Slic3r::GUI::MeshClipper::set_mesh(), Slic3r::GUI::MeshClipper::set_plane(), Slic3r::GUI::MeshClipper::set_transformation(), Slic3r::SINKING_Z_THRESHOLD, Slic3r::BoundingBox3Base< PointType >::size(), Slic3r::GLVolume::transformed_bounding_box(), Slic3r::GLVolume::volume_idx(), Slic3r::ModelObject::volumes, and Slic3r::GLVolume::world_matrix().

Referenced by _render_objects(), and _render_section_view_caps().

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

◆ _render_section_view_panel()

void Slic3r::GUI::GLCanvas3D::_render_section_view_panel ( const ImVec2 & bottom_left)
private
11280{
11281 if (!m_section_view->panel_open)
11282 return;
11283
11284 ImGuiWrapper& imgui = *wxGetApp().imgui();
11285 const float sc = get_scale();
11286
11288 ImGui::PushStyleColor(ImGuiCol_WindowBg, m_is_dark ? ImGuiWrapper::COL_TOOLBAR_BG_DARK : ImGuiWrapper::COL_TOOLBAR_BG);
11289 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.f * sc);
11290 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.f, 8.f) * sc);
11291 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.f, 4.f) * sc);
11292
11293 ImGui::SetNextWindowPos(bottom_left, ImGuiCond_Always, ImVec2(0.f, 1.f));
11294 imgui.begin(std::string("##CanvasSectionView"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove |
11295 ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar);
11296
11297 const wxString alt = GUI::shortkey_alt_prefix();
11298 const std::vector<std::pair<wxString, wxString>> tips = {
11299 { alt + _L("Mouse wheel"), _L("Move section plane") },
11300 { _L("Mouse wheel on icon"), _L("Move section plane") },
11301 { _L("Right click on icon"), _L("Toggle section view") },
11302 { _L("Middle click on icon"), _L("Set viewing angle") },
11303 };
11304 // render_tooltip_button() puts the tips below y plus the panel height; they go above the panel.
11305 const ImGuiStyle& style = ImGui::GetStyle();
11306 const float tips_h = tips.size() * (ImGui::GetTextLineHeight() + style.ItemSpacing.y) - style.ItemSpacing.y + 2.f * style.WindowPadding.y;
11307 GLGizmoUtils::render_tooltip_button(&imgui, *this, tips, ImGui::GetWindowPos().x,
11308 ImGui::GetWindowPos().y - style.ItemSpacing.y - tips_h - ImGui::GetContentRegionMax().y - ImGui::GetFrameHeight());
11309
11310 ImGui::SameLine();
11311 ImGui::AlignTextToFramePadding();
11312 imgui.text(_L("Section view"));
11313
11314 float ratio = float(get_section_view_ratio());
11315 ImGui::SameLine();
11316 ImGui::SetNextItemWidth(imgui.scaled(7.f));
11317 bool changed = imgui.bbl_slider_float_style("##section_view", &ratio, 0.f, 1.f, "%.2f", 1.0f, true);
11318 ImGui::SameLine();
11319 ImGui::SetNextItemWidth(1.5f * imgui.get_slider_icon_size().x);
11320 changed |= ImGui::BBLDragFloat("##section_view_input", &ratio, 0.05f, 0.0f, 0.0f, "%.2f");
11321 if (changed)
11323
11324 ImGui::SameLine();
11325 if (imgui.button(_L("Set viewing angle")))
11327
11328 imgui.disabled_begin(!is_section_view_active());
11329 ImGui::SameLine();
11330 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.f, 0.f, 0.f, 0.f));
11331 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.f, 0.f, 0.f, 0.f));
11332 ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.f, 0.f, 0.f, 0.f));
11333 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.f);
11334 if (imgui.button(wxString(ImGui::RevertBtn) + "##section_view_reset", _L("Reset")))
11336 ImGui::PopStyleVar();
11337 ImGui::PopStyleColor(3);
11338 imgui.disabled_end();
11339
11340 imgui.end();
11341
11342 ImGui::PopStyleVar(3);
11343 ImGui::PopStyleColor();
11345}

References _L, _render_section_view_panel(), align_section_view_to_camera(), Slic3r::GUI::ImGuiWrapper::bbl_slider_float_style(), Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::button(), Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG, Slic3r::GUI::ImGuiWrapper::COL_TOOLBAR_BG_DARK, Slic3r::GUI::ImGuiWrapper::disabled_begin(), Slic3r::GUI::ImGuiWrapper::disabled_end(), Slic3r::GUI::ImGuiWrapper::end(), get_scale(), get_section_view_ratio(), is_section_view_active(), m_is_dark, m_section_view, Slic3r::GUI::ImGuiWrapper::pop_toolbar_style(), Slic3r::GUI::ImGuiWrapper::push_toolbar_style(), Slic3r::GUI::GLGizmoUtils::render_tooltip_button(), Slic3r::GUI::ImGuiWrapper::scaled(), set_section_view_ratio(), Slic3r::GUI::shortkey_alt_prefix(), style, and Slic3r::GUI::ImGuiWrapper::text().

Referenced by _render_section_view_panel().

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

◆ _render_selection()

void Slic3r::GUI::GLCanvas3D::_render_selection ( )
private
9979{
9980 float scale_factor = 1.0;
9981#if ENABLE_RETINA_GL
9982 scale_factor = m_retina_helper->get_scale_factor();
9983#endif // ENABLE_RETINA_GL
9984
9985 if (!m_gizmos.is_running())
9986 m_selection.render(scale_factor);
9987}

References _render_selection(), m_gizmos, and m_selection.

Referenced by _render_scene(), and _render_selection().

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

◆ _render_selection_sidebar_hints()

void Slic3r::GUI::GLCanvas3D::_render_selection_sidebar_hints ( )
inlineprivate
1604{ m_selection.render_sidebar_hints(m_sidebar_field, m_gizmos.get_uniform_scaling()); }

References m_gizmos, m_selection, and m_sidebar_field.

Referenced by _render_scene().

Here is the caller graph for this function:

◆ _render_separator_toolbar_left()

void Slic3r::GUI::GLCanvas3D::_render_separator_toolbar_left ( ) const
private
11364{
11365 if (!m_separator_toolbar.is_enabled())
11366 return;
11367
11368 const Size cnv_size = get_canvas_size();
11369 const float top = 0.5f * (float)cnv_size.get_height();
11370 const float main_toolbar_left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset();
11371 const float left = main_toolbar_left + (m_main_toolbar.get_width());
11372
11373 m_separator_toolbar.set_position(top, left);
11375}
@ SeparatorLine
Definition GLToolbar.hpp:80

References _render_separator_toolbar_left(), get_canvas_size(), Slic3r::GUI::Size::get_height(), get_main_toolbar_offset(), Slic3r::GUI::Size::get_width(), m_main_toolbar, m_separator_toolbar, and Slic3r::GUI::GLToolbarItem::SeparatorLine.

Referenced by _render_overlay_toolbars(), and _render_separator_toolbar_left().

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

◆ _render_separator_toolbar_right()

void Slic3r::GUI::GLCanvas3D::_render_separator_toolbar_right ( ) const
private
11348{
11349 if (!m_separator_toolbar.is_enabled())
11350 return;
11351
11352 const Size cnv_size = get_canvas_size();
11353 const float gizmo_width = m_gizmos.get_scaled_total_width();
11354 const float separator_width = m_separator_toolbar.get_width();
11355 const float top = 0.5f * (float)cnv_size.get_height();
11356 const float main_toolbar_left = -0.5f * cnv_size.get_width() + get_main_toolbar_offset();
11357 const float left = main_toolbar_left + (m_main_toolbar.get_width() + gizmo_width + separator_width / 2);
11358
11359 m_separator_toolbar.set_position(top, left);
11361}

References _render_separator_toolbar_right(), get_canvas_size(), Slic3r::GUI::Size::get_height(), get_main_toolbar_offset(), Slic3r::GUI::Size::get_width(), m_gizmos, m_main_toolbar, m_separator_toolbar, and Slic3r::GUI::GLToolbarItem::SeparatorLine.

Referenced by _render_overlay_toolbars(), and _render_separator_toolbar_right().

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

◆ _render_sequential_clearance()

void Slic3r::GUI::GLCanvas3D::_render_sequential_clearance ( )
private
9990{
9991 if (m_gizmos.is_dragging())
9992 return;
9993 auto type = m_gizmos.get_current_type();
9997 }
9998}
bool can_sequential_clearance_show_in_gizmo()
Definition GLCanvas3D.cpp:6297
SequentialPrintClearance m_sequential_print_clearance
Definition GLCanvas3D.hpp:877

References _render_sequential_clearance(), can_sequential_clearance_show_in_gizmo(), m_gizmos, m_sequential_print_clearance, and Slic3r::GUI::GLGizmosManager::Undefined.

Referenced by _render_scene(), and _render_sequential_clearance().

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

◆ _render_shadows()

void Slic3r::GUI::GLCanvas3D::_render_shadows ( const Transform3d & view_matrix,
const Transform3d & projection_matrix )
private
9181{
9182 if (wxGetApp().app_config == nullptr)
9183 return;
9185 return;
9186 const EShadowMode mode = _shadow_mode();
9187 if (mode == EShadowMode::Off)
9188 return;
9189
9190 // The preview canvas holds no volumes of its own for FFF. Once slicing has run its printed
9191 // geometry is the G-code toolpaths, which both cast into the map here and sample it back in
9192 // _render_gcode; before slicing there are only shells, and nothing casts at all. View3D and
9193 // SLA preview use m_volumes. The shells are deliberately never casters: they are a
9194 // translucent ghost of the whole object, so they would drop the solid shadow of a print that
9195 // has not been sliced, and at any layer below the last, one that is not there yet.
9196 const bool toolpath_casters = m_canvas_type == ECanvasType::CanvasPreview && m_gcode_viewer.has_data();
9197 if (!toolpath_casters && m_volumes.empty())
9198 return;
9199
9201
9202 // Orbit: the light used for shading, fixed to the camera. Static: a world light, also used for shading.
9203 const Vec3d light_dir_eye = Vec3d(-0.4574957, 0.4574957, 0.7624929).normalized();
9204 const Matrix3d view_rot = view_matrix.matrix().block<3, 3>(0, 0);
9205 const Vec3d dir_to_light = mode == EShadowMode::Static ? STATIC_LIGHT_DIR :
9206 Vec3d((view_rot.transpose() * light_dir_eye).normalized());
9207
9208 // Bounding box of the printable objects (the shadow casters).
9209 BoundingBoxf3 obj_bb;
9210 if (toolpath_casters) {
9211 // Merged corner by corner: BoundingBoxf3(min, max) marks itself undefined at zero
9212 // Z extent, which a single layer print gives, and the check below would then drop
9213 // every shadow in the frame.
9214 const BoundingBoxf3& paths_bb = m_gcode_viewer.get_paths_bounding_box();
9215 if ((paths_bb.min.array() <= paths_bb.max.array()).all()) {
9216 obj_bb.merge(paths_bb.min);
9217 obj_bb.merge(paths_bb.max);
9218 }
9219 // Only the enabled layers are drawn, so fitting the map to the whole print wastes
9220 // its depth range and makes contact shadows shift as the slider moves. The z = 0
9221 // shadow is enclosed separately below, so the plate shadow is unaffected.
9222 const std::vector<double> layer_zs = m_gcode_viewer.get_layers_zs();
9223 if (!layer_zs.empty()) {
9224 const size_t top = std::min<size_t>(m_gcode_viewer.get_layers_z_range()[1], layer_zs.size() - 1);
9225 obj_bb.max.z() = std::max(obj_bb.min.z(), std::min(obj_bb.max.z(), layer_zs[top]));
9226 }
9227 }
9228 else {
9229 for (const GLVolume* volume : m_volumes.volumes) {
9230 if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower)
9231 continue;
9232 obj_bb.merge(volume->transformed_bounding_box());
9233 }
9234 }
9235 if (!obj_bb.defined)
9236 return; // no objects to cast shadows
9237
9238 // Orthographic light-space basis (z points toward the light).
9239 const Vec3d up = (std::abs(dir_to_light.z()) > 0.99) ? Vec3d::UnitY() : Vec3d::UnitZ();
9240 const Vec3d z_axis = dir_to_light;
9241 const Vec3d x_axis = up.cross(z_axis).normalized();
9242 const Vec3d y_axis = z_axis.cross(x_axis).normalized();
9243
9244 // Fit the frustum to the object AABB *and* the object's shadow projected onto the plate
9245 // (clamped to the plate footprint). This keeps the map tight/high-res for short shadows
9246 // while still covering long shadows at grazing light angles, which previously fell outside
9247 // the map and were clipped.
9248 const Vec3d ray_dir = -dir_to_light; // direction the shadow travels
9249 const BoundingBoxf3 plate_bb = m_bed.build_volume().valid() ? m_bed.build_volume().bounding_volume() : obj_bb;
9250
9251 Vec3d lmin(DBL_MAX, DBL_MAX, DBL_MAX);
9252 Vec3d lmax(-DBL_MAX, -DBL_MAX, -DBL_MAX);
9253 auto enclose = [&](const Vec3d& p) {
9254 const Vec3d lp(x_axis.dot(p), y_axis.dot(p), z_axis.dot(p));
9255 lmin = lmin.cwiseMin(lp);
9256 lmax = lmax.cwiseMax(lp);
9257 };
9258 // The plate area a shadow can reach: the casters' footprint and where their corners land on z = 0.
9259 Vec2d reach_min(DBL_MAX, DBL_MAX);
9260 Vec2d reach_max(-DBL_MAX, -DBL_MAX);
9261 auto reach = [&](const Vec3d& p) {
9262 reach_min = reach_min.cwiseMin(Vec2d(p.x(), p.y()));
9263 reach_max = reach_max.cwiseMax(Vec2d(p.x(), p.y()));
9264 };
9265 for (int i = 0; i < 8; ++i) {
9266 const Vec3d corner((i & 1) ? obj_bb.max.x() : obj_bb.min.x(),
9267 (i & 2) ? obj_bb.max.y() : obj_bb.min.y(),
9268 (i & 4) ? obj_bb.max.z() : obj_bb.min.z());
9269 enclose(corner);
9270 reach(corner);
9271 // Where this corner's shadow lands on z = 0, clamped to the plate so a grazing angle
9272 // (t -> infinity) stays bounded.
9273 if (ray_dir.z() < -1e-6) {
9274 const double t = -corner.z() / ray_dir.z();
9275 Vec3d s = corner + t * ray_dir;
9276 s.x() = std::min(std::max(s.x(), plate_bb.min.x()), plate_bb.max.x());
9277 s.y() = std::min(std::max(s.y(), plate_bb.min.y()), plate_bb.max.y());
9278 s.z() = 0.0;
9279 enclose(s);
9280 reach(s);
9281 }
9282 }
9283
9284 // Light "camera" placed just past the nearest enclosed point, looking toward the scene.
9285 const double range = lmax.z() - lmin.z();
9286 const double margin = std::max(1.0, 0.05 * range);
9287 const double cx = 0.5 * (lmin.x() + lmax.x());
9288 const double cy = 0.5 * (lmin.y() + lmax.y());
9289 const Vec3d eye = x_axis * cx + y_axis * cy + z_axis * (lmax.z() + margin);
9290
9291 Matrix4d light_view = Matrix4d::Identity();
9292 light_view.block<1, 3>(0, 0) = x_axis.transpose();
9293 light_view.block<1, 3>(1, 0) = y_axis.transpose();
9294 light_view.block<1, 3>(2, 0) = z_axis.transpose();
9295 light_view(0, 3) = -x_axis.dot(eye);
9296 light_view(1, 3) = -y_axis.dot(eye);
9297 light_view(2, 3) = -z_axis.dot(eye);
9298
9299 // Ortho fit to the light-space extent (symmetric in X/Y around cx,cy; +2% edge padding).
9300 const double halfx = std::max(0.5 * (lmax.x() - lmin.x()), 1.0) * 1.02;
9301 const double halfy = std::max(0.5 * (lmax.y() - lmin.y()), 1.0) * 1.02;
9302 const double near_z = margin * 0.5;
9303 const double far_z = range + margin * 1.5;
9304 Matrix4d light_proj = Matrix4d::Identity();
9305 light_proj(0, 0) = 1.0 / halfx;
9306 light_proj(1, 1) = 1.0 / halfy;
9307 light_proj(2, 2) = -2.0 / (far_z - near_z);
9308 light_proj(2, 3) = -(far_z + near_z) / (far_z - near_z);
9309
9310 m_shadow_light_vp = Transform3d(light_proj * light_view);
9311
9312 // Create / resize the depth texture and FBO
9313 const unsigned int size = 2048;
9314
9315 // Padded by the filter's 2 texel reach, stretched where the light grazes the plate.
9316 const double reach_margin = 3.0 * 2.0 * std::max(halfx, halfy) / size / std::max(0.1, std::abs(dir_to_light.z()));
9317 m_shadow_plate_bounds = { float(reach_min.x() - reach_margin), float(reach_min.y() - reach_margin),
9318 float(reach_max.x() + reach_margin), float(reach_max.y() + reach_margin) };
9319 if (m_shadow_map_texture_id == 0) {
9326 const float border[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
9329 }
9330 if (m_shadow_map_size != size) {
9333 m_shadow_map_size = size;
9334 }
9335 if (m_shadow_map_fbo == 0)
9337
9338 // A static light keeps the map until its frustum or the casters change.
9339 size_t cache_key = 0;
9340 if (mode == EShadowMode::Static) {
9341 cache_key = _shadow_casters_signature(toolpath_casters);
9342 for (int i = 0; i < 16; ++i)
9343 boost::hash_combine(cache_key, m_shadow_light_vp.matrix().data()[i]);
9344 }
9345 if (cache_key != 0 && cache_key == m_shadow_map_key)
9346 m_shadow_map_valid = true;
9347 else {
9348 m_shadow_map_key = 0;
9349 // Save OpenGL state that we will modify
9350 GLint prev_viewport[4] = { 0, 0, 0, 0 };
9351 glsafe(::glGetIntegerv(GL_VIEWPORT, prev_viewport));
9352 GLint prev_fbo = 0;
9354 GLboolean prev_color_mask[4] = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };
9355 glsafe(::glGetBooleanv(GL_COLOR_WRITEMASK, prev_color_mask));
9356 const GLboolean prev_cull = ::glIsEnabled(GL_CULL_FACE);
9357 GLint prev_depth_func = GL_LESS;
9358 glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func));
9359 GLboolean prev_depth_mask = GL_TRUE;
9360 glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask));
9365
9367 glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(prev_fbo)));
9368 m_shadow_map_valid = false;
9369 } else {
9370 glsafe(::glViewport(0, 0, size, size));
9377 glsafe(::glPolygonOffset(4.0f, 4.0f));
9379
9380 if (toolpath_casters)
9381 m_gcode_viewer.render_shadow_casters(Transform3d(light_view), Transform3d(light_proj), eye);
9382 // Only this branch draws through "flat"; the toolpaths bring their own program.
9383 else if (GLShaderProgram* shader = wxGetApp().get_shader("flat"); shader != nullptr) {
9384 shader->start_using();
9385 shader->set_uniform("projection_matrix", Transform3d(light_proj));
9386 for (GLVolume* volume : m_volumes.volumes) {
9387 if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower)
9388 continue;
9389 const Transform3d view_model = Transform3d(light_view) * volume->world_matrix();
9390 shader->set_uniform("view_model_matrix", view_model);
9391 volume->model.render(shader);
9392 }
9393 shader->stop_using();
9394 }
9395
9396 // Restore state
9398 glsafe(::glColorMask(prev_color_mask[0], prev_color_mask[1], prev_color_mask[2], prev_color_mask[3]));
9399 if (prev_cull)
9401 else
9403 glsafe(::glDepthFunc(prev_depth_func));
9404 glsafe(::glDepthMask(prev_depth_mask));
9405 glsafe(::glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(prev_fbo)));
9406 glsafe(::glViewport(prev_viewport[0], prev_viewport[1], prev_viewport[2], prev_viewport[3]));
9407
9408 m_shadow_map_valid = true;
9409 }
9411 m_shadow_map_key = cache_key;
9412 }
9413 } else {
9414 m_shadow_map_valid = false;
9415 }
9416
9417 // ----------------------------------------------------------------------------------
9418 // Unified plate shadow: draw the build-plate footprint and darken it wherever the same
9419 // depth shadow map (built above) says the light is occluded. This replaces the old planar
9420 // stencil projection so plate, object and self shadows all come from one technique.
9421 // ----------------------------------------------------------------------------------
9422 if (!m_shadow_map_valid)
9423 return;
9424
9425 GLShaderProgram* plate_shader = wxGetApp().get_shader("printbed_shadow");
9426 if (plate_shader == nullptr)
9427 return;
9428
9429 if (const BuildVolume& build_volume = m_bed.build_volume(); build_volume.valid()) {
9430 const std::string mask_key = build_volume.type() == BuildVolume_Type::Rectangle
9431 ? (boost::format("rect|%1$.5f|%2$.5f|%3$.5f|%4$.5f")
9432 % build_volume.bounding_volume().min.x()
9433 % build_volume.bounding_volume().min.y()
9434 % build_volume.bounding_volume().max.x()
9435 % build_volume.bounding_volume().max.y()).str()
9436 : (build_volume.type() == BuildVolume_Type::Circle
9437 ? (boost::format("circle|%1$.5f|%2$.5f|%3$.5f")
9438 % unscaled<double>(build_volume.circle().center.x())
9439 % unscaled<double>(build_volume.circle().center.y())
9440 % unscaled<double>(build_volume.circle().radius)).str()
9441 : std::string("invalid"));
9442
9443 if (mask_key != m_plate_shadow_mask_key) {
9444 m_plate_shadow_mask.reset();
9445 m_plate_shadow_mask_key = mask_key;
9446
9447 GLModel::Geometry mask;
9449
9450 if (build_volume.type() == BuildVolume_Type::Rectangle) {
9451 const BoundingBox3Base<Vec3d> bb = build_volume.bounding_volume();
9452 mask.reserve_vertices(4);
9453 mask.reserve_indices(6);
9454 mask.add_vertex(Vec3f((float)bb.min.x(), (float)bb.min.y(), 0.0f));
9455 mask.add_vertex(Vec3f((float)bb.max.x(), (float)bb.min.y(), 0.0f));
9456 mask.add_vertex(Vec3f((float)bb.max.x(), (float)bb.max.y(), 0.0f));
9457 mask.add_vertex(Vec3f((float)bb.min.x(), (float)bb.max.y(), 0.0f));
9458 mask.add_triangle(0, 1, 2);
9459 mask.add_triangle(0, 2, 3);
9460 }
9461 else if (build_volume.type() == BuildVolume_Type::Circle) {
9462 const Vec2f c = Vec2f(unscaled<float>(build_volume.circle().center.x()), unscaled<float>(build_volume.circle().center.y()));
9463 const float r = unscaled<float>(build_volume.circle().radius);
9464 const int segments = 64;
9465 mask.reserve_vertices(segments + 1);
9466 mask.reserve_indices(segments * 3);
9467 mask.add_vertex(Vec3f(c.x(), c.y(), 0.0f));
9468 for (int i = 0; i < segments; ++i) {
9469 const float a = (2.0f * float(PI) * float(i)) / float(segments);
9470 mask.add_vertex(Vec3f(c.x() + r * std::cos(a), c.y() + r * std::sin(a), 0.0f));
9471 }
9472 for (int i = 0; i < segments; ++i) {
9473 const unsigned int i1 = 1 + i;
9474 const unsigned int i2 = 1 + ((i + 1) % segments);
9475 mask.add_triangle(0, i1, i2);
9476 }
9477 }
9478
9479 if (mask.vertices_count() > 0 && mask.indices_count() > 0)
9480 m_plate_shadow_mask.init_from(std::move(mask));
9481 }
9482
9483 if (m_plate_shadow_mask.is_initialized()) {
9484 // Blend the shadow over the already-drawn plate. Depth test keeps it behind anything
9485 // already in front; depth writes are off, and a small negative polygon offset lifts it
9486 // just above the bed to avoid z-fighting.
9487 GLboolean prev_depth_mask = GL_TRUE;
9488 glsafe(::glGetBooleanv(GL_DEPTH_WRITEMASK, &prev_depth_mask));
9489 GLint prev_depth_func = GL_LESS;
9490 glsafe(::glGetIntegerv(GL_DEPTH_FUNC, &prev_depth_func));
9491
9492 glsafe(::glEnable(GL_DEPTH_TEST));
9493 glsafe(::glDepthMask(GL_FALSE));
9494 glsafe(::glDepthFunc(GL_LEQUAL));
9495 glsafe(::glEnable(GL_BLEND));
9496 glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
9497 glsafe(::glEnable(GL_POLYGON_OFFSET_FILL));
9498 glsafe(::glPolygonOffset(-1.0f, -1.0f));
9499
9500 glsafe(::glActiveTexture(GL_TEXTURE4));
9501 glsafe(::glBindTexture(GL_TEXTURE_2D, m_shadow_map_texture_id));
9502 glsafe(::glActiveTexture(GL_TEXTURE0));
9503
9504 plate_shader->start_using();
9505 plate_shader->set_uniform("view_model_matrix", view_matrix);
9506 plate_shader->set_uniform("projection_matrix", projection_matrix);
9507 plate_shader->set_uniform("shadow_map", 4);
9508 plate_shader->set_uniform("shadow_light_vp", m_shadow_light_vp);
9509 plate_shader->set_uniform("shadow_intensity", 0.35f);
9510 plate_shader->set_uniform("shadow_map_texel", 1.0f / static_cast<float>(m_shadow_map_size));
9511 plate_shader->set_uniform("shadow_bounds", m_shadow_plate_bounds);
9512 m_plate_shadow_mask.render(plate_shader);
9513 plate_shader->stop_using();
9514
9515 glsafe(::glActiveTexture(GL_TEXTURE4));
9516 glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
9517 glsafe(::glActiveTexture(GL_TEXTURE0));
9518
9519 glsafe(::glDisable(GL_POLYGON_OFFSET_FILL));
9520 glsafe(::glDisable(GL_BLEND));
9521 glsafe(::glDepthFunc(prev_depth_func));
9522 glsafe(::glDepthMask(prev_depth_mask));
9523 }
9524 }
9525}
std::array< float, 4 > m_shadow_plate_bounds
Definition GLCanvas3D.hpp:943
size_t m_shadow_map_key
Definition GLCanvas3D.hpp:941
EShadowMode
Definition GLCanvas3D.hpp:1511
@ Static
Definition GLCanvas3D.hpp:1511
size_t _shadow_casters_signature(bool toolpath_casters) const
Definition GLCanvas3D.cpp:8549
#define GL_NONE
Definition gl.h:1206
#define GL_LESS
Definition gl.h:914
#define GL_TEXTURE_BORDER_COLOR
Definition gl.h:1762
#define GL_TEXTURE_WRAP_S
Definition gl.h:1854
#define GL_DEPTH_FUNC
Definition gl.h:567
#define glDrawBuffer
Definition gl.h:3629
#define GL_POLYGON_OFFSET_FILL
Definition gl.h:1318
#define glPolygonOffset
Definition gl.h:4471
#define glDepthFunc
Definition gl.h:3593
#define glReadBuffer
Definition gl.h:4657
int GLint
Definition gl.h:2062
#define GL_FLOAT
Definition gl.h:660
#define glGetIntegerv
Definition gl.h:3873
#define glTexParameterfv
Definition gl.h:4909
#define GL_COLOR_WRITEMASK
Definition gl.h:421
#define glColorMask
Definition gl.h:3471
#define GL_VIEWPORT
Definition gl.h:2021
#define GL_DEPTH_WRITEMASK
Definition gl.h:576
#define GL_CLAMP_TO_BORDER
Definition gl.h:321
#define GL_FRAMEBUFFER_BINDING
Definition gl.h:729
#define glViewport
Definition gl.h:5333
#define glGetBooleanv
Definition gl.h:3825
#define GL_TEXTURE_WRAP_T
Definition gl.h:1855
#define GL_DEPTH_COMPONENT24
Definition gl.h:563
static const Vec3d STATIC_LIGHT_DIR
Definition GLCanvas3D.cpp:8533
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
Eigen::Matrix< double, 4, 4, Eigen::DontAlign > Matrix4d
Definition Point.hpp:88
BuildVolume_Type
Definition BuildVolume.hpp:19
@ up
Definition MarchingSquares.hpp:192

References _is_realistic_view_enabled(), _render_shadows(), _shadow_casters_signature(), _shadow_mode(), Slic3r::GUI::GLModel::Geometry::add_triangle(), Slic3r::GUI::GLModel::Geometry::add_vertex(), Slic3r::GUI::OpenGLManager::Arb, CanvasPreview, Slic3r::Circle, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::defined, Slic3r::GUI::GLModel::Geometry::format, Slic3r::GUI::OpenGLManager::get_framebuffers_type(), GL_BLEND, GL_CLAMP_TO_BORDER, GL_COLOR_WRITEMASK, GL_CULL_FACE, GL_DEPTH_ATTACHMENT, GL_DEPTH_BUFFER_BIT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_DEPTH_FUNC, GL_DEPTH_TEST, GL_DEPTH_WRITEMASK, GL_FALSE, GL_FLOAT, GL_FRAMEBUFFER, GL_FRAMEBUFFER_BINDING, GL_FRAMEBUFFER_COMPLETE, GL_LEQUAL, GL_LESS, GL_NEAREST, GL_NONE, GL_ONE_MINUS_SRC_ALPHA, GL_POLYGON_OFFSET_FILL, GL_SRC_ALPHA, GL_TEXTURE0, GL_TEXTURE4, GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TRUE, GL_VIEWPORT, glActiveTexture, glBindFramebuffer, glBindTexture, glBlendFunc, glCheckFramebufferStatus, glClear, glColorMask, glDepthFunc, glDepthMask, glDisable, glDrawBuffer, glEnable, glFramebufferTexture2D, glGenFramebuffers, glGenTextures, glGetBooleanv, glGetIntegerv, glIsEnabled, glPolygonOffset, glReadBuffer, glsafe, glTexImage2D, glTexParameterfv, glTexParameteri, glViewport, Slic3r::GUI::GLModel::Geometry::indices_count(), m_bed, m_canvas_type, m_gcode_viewer, m_plate_shadow_mask, m_plate_shadow_mask_key, m_shadow_light_vp, m_shadow_map_fbo, m_shadow_map_key, m_shadow_map_size, m_shadow_map_texture_id, m_shadow_map_valid, m_shadow_plate_bounds, m_volumes, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GLVolume::model, Off, Slic3r::GUI::GLModel::Geometry::P3, PI, Slic3r::range(), Slic3r::Rectangle, Slic3r::GUI::GLModel::render(), Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), Static, Slic3r::GUI::STATIC_LIGHT_DIR, Slic3r::GLShaderProgram::stop_using(), Slic3r::GLVolume::transformed_bounding_box(), Slic3r::GUI::GLModel::Geometry::Triangles, Slic3r::unscaled(), Slic3r::GUI::GLModel::Geometry::vertices_count(), and Slic3r::GLVolume::world_matrix().

Referenced by _render_scene(), and _render_shadows().

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

◆ _render_sla_slices()

void Slic3r::GUI::GLCanvas3D::_render_sla_slices ( )
private
11790{
11792 return;
11793
11794 const SLAPrint* print = this->sla_print();
11795 const PrintObjects& print_objects = print->objects();
11796 if (print_objects.empty())
11797 // nothing to render, return
11798 return;
11799
11800 double clip_min_z = -m_clipping_planes[0].get_data()[3];
11801 double clip_max_z = m_clipping_planes[1].get_data()[3];
11802 for (unsigned int i = 0; i < (unsigned int)print_objects.size(); ++i) {
11803 const SLAPrintObject* obj = print_objects[i];
11804
11805 if (!obj->is_step_done(slaposSliceSupports))
11806 continue;
11807
11808 SlaCap::ObjectIdToModelsMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
11809 SlaCap::ObjectIdToModelsMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i);
11810 {
11811 if (it_caps_bottom == m_sla_caps[0].triangles.end())
11812 it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first;
11813 if (!m_sla_caps[0].matches(clip_min_z)) {
11814 m_sla_caps[0].z = clip_min_z;
11815 it_caps_bottom->second.object.reset();
11816 it_caps_bottom->second.supports.reset();
11817 }
11818 if (it_caps_top == m_sla_caps[1].triangles.end())
11819 it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first;
11820 if (!m_sla_caps[1].matches(clip_max_z)) {
11821 m_sla_caps[1].z = clip_max_z;
11822 it_caps_top->second.object.reset();
11823 it_caps_top->second.supports.reset();
11824 }
11825 }
11826 GLModel& bottom_obj_triangles = it_caps_bottom->second.object;
11827 GLModel& bottom_sup_triangles = it_caps_bottom->second.supports;
11828 GLModel& top_obj_triangles = it_caps_top->second.object;
11829 GLModel& top_sup_triangles = it_caps_top->second.supports;
11830
11831 auto init_model = [](GLModel& model, const Pointf3s& triangles, const ColorRGBA& color) {
11832 GLModel::Geometry init_data;
11834 init_data.reserve_vertices(triangles.size());
11835 init_data.reserve_indices(triangles.size() / 3);
11836 init_data.color = color;
11837
11838 unsigned int vertices_count = 0;
11839 for (const Vec3d& v : triangles) {
11840 init_data.add_vertex((Vec3f)v.cast<float>());
11841 ++vertices_count;
11842 if (vertices_count % 3 == 0) {
11843 init_data.add_triangle(vertices_count - 3, vertices_count - 2, vertices_count - 1);
11844 }
11845 }
11846
11847 if (!init_data.is_empty())
11848 model.init_from(std::move(init_data));
11849 };
11850
11851 if ((!bottom_obj_triangles.is_initialized() || !bottom_sup_triangles.is_initialized() ||
11852 !top_obj_triangles.is_initialized() || !top_sup_triangles.is_initialized()) && !obj->get_slice_index().empty()) {
11853 double layer_height = print->default_object_config().layer_height.value;
11854 double initial_layer_height = print->material_config().initial_layer_height.value;
11855 bool left_handed = obj->is_left_handed();
11856
11857 coord_t key_zero = obj->get_slice_index().front().print_level();
11858 // Slice at the center of the slab starting at clip_min_z will be rendered for the lower plane.
11859 coord_t key_low = coord_t((clip_min_z - initial_layer_height + layer_height) / SCALING_FACTOR) + key_zero;
11860 // Slice at the center of the slab ending at clip_max_z will be rendered for the upper plane.
11861 coord_t key_high = coord_t((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
11862
11863 const SliceRecord& slice_low = obj->closest_slice_to_print_level(key_low, coord_t(SCALED_EPSILON));
11864 const SliceRecord& slice_high = obj->closest_slice_to_print_level(key_high, coord_t(SCALED_EPSILON));
11865
11866 // Offset to avoid OpenGL Z fighting between the object's horizontal surfaces and the triangluated surfaces of the cuts.
11867 double plane_shift_z = 0.002;
11868
11869 if (slice_low.is_valid()) {
11870 const ExPolygons& obj_bottom = slice_low.get_slice(soModel);
11871 const ExPolygons& sup_bottom = slice_low.get_slice(soSupport);
11872 // calculate model bottom cap
11873 // calculate model bottom cap
11874 if (!bottom_obj_triangles.is_initialized() && !obj_bottom.empty())
11875 init_model(bottom_obj_triangles, triangulate_expolygons_3d(obj_bottom, clip_min_z - plane_shift_z, !left_handed), { 1.0f, 0.37f, 0.0f, 1.0f });
11876 // calculate support bottom cap
11877 if (!bottom_sup_triangles.is_initialized() && !sup_bottom.empty())
11878 init_model(bottom_sup_triangles, triangulate_expolygons_3d(sup_bottom, clip_min_z - plane_shift_z, !left_handed), { 1.0f, 0.0f, 0.37f, 1.0f });
11879 }
11880
11881 if (slice_high.is_valid()) {
11882 const ExPolygons& obj_top = slice_high.get_slice(soModel);
11883 const ExPolygons& sup_top = slice_high.get_slice(soSupport);
11884 // calculate model top cap
11885 // calculate model top cap
11886 if (!top_obj_triangles.is_initialized() && !obj_top.empty())
11887 init_model(top_obj_triangles, triangulate_expolygons_3d(obj_top, clip_max_z + plane_shift_z, left_handed), { 1.0f, 0.37f, 0.0f, 1.0f });
11888 // calculate support top cap
11889 if (!top_sup_triangles.is_initialized() && !sup_top.empty())
11890 init_model(top_sup_triangles, triangulate_expolygons_3d(sup_top, clip_max_z + plane_shift_z, left_handed), { 1.0f, 0.0f, 0.37f, 1.0f });
11891 }
11892 }
11893
11894 GLShaderProgram* shader = wxGetApp().get_shader("flat");
11895 if (shader != nullptr) {
11896 shader->start_using();
11897
11898 for (const SLAPrintObject::Instance& inst : obj->instances()) {
11899 const Camera& camera = wxGetApp().plater()->get_camera();
11900 const Transform3d view_model_matrix = camera.get_view_matrix() *
11901 Geometry::assemble_transform(Vec3d(unscale<double>(inst.shift.x()), unscale<double>(inst.shift.y()), 0.0),
11902 inst.rotation * Vec3d::UnitZ(), Vec3d::Ones(),
11903 obj->is_left_handed() ? Vec3d(-1.0f, 1.0f, 1.0f) : Vec3d::Ones());
11904
11905 shader->set_uniform("view_model_matrix", view_model_matrix);
11906 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
11907
11908 bottom_obj_triangles.render();
11909 top_obj_triangles.render();
11910 bottom_sup_triangles.render();
11911 top_sup_triangles.render();
11912
11913 }
11914
11915 shader->stop_using();
11916 }
11917 }
11918}
std::array< SlaCap, 2 > m_sla_caps
Definition GLCanvas3D.hpp:723
double SCALING_FACTOR
Definition libslic3r.cpp:3
#define SCALED_EPSILON
Definition libslic3r.h:109
static std::string layer_height
Definition Tab.cpp:4294
void assemble_transform(Transform3d &transform, const Vec3d &translation, const Vec3d &rotation, const Vec3d &scale, const Vec3d &mirror)
Definition Geometry.cpp:319
std::vector< ExPolygon > ExPolygons
Definition ExPolygon.hpp:20
std::vector< Vec3d > Pointf3s
Definition Point.hpp:79
std::vector< SLAPrintObject * > PrintObjects
Definition SLAPrint.hpp:374
std::vector< Vec3d > triangulate_expolygons_3d(const ExPolygons &polys, coordf_t z, bool flip)
Definition Tesselate.cpp:210
SLAPrintObject::SliceRecord SliceRecord
Definition SLAPrint.hpp:376
@ soModel
Definition SLAPrint.hpp:63
@ soSupport
Definition SLAPrint.hpp:63
Definition GLCanvas3D.hpp:404

References _render_sla_slices(), Slic3r::GUI::GLModel::Geometry::add_triangle(), Slic3r::GUI::GLModel::Geometry::add_vertex(), Slic3r::Geometry::assemble_transform(), camera, Slic3r::SLAPrintObject::closest_slice_to_print_level(), Slic3r::GUI::GLModel::Geometry::color, current_printer_technology(), Slic3r::SLAPrint::default_object_config(), Slic3r::GUI::GLModel::Geometry::format, Slic3r::SLAPrintObject::SliceRecord::get_slice(), Slic3r::SLAPrintObject::get_slice_index(), Slic3r::GUI::GLModel::init_from(), Slic3r::SLAPrintObject::instances(), Slic3r::GUI::GLModel::Geometry::is_empty(), Slic3r::GUI::GLModel::is_initialized(), Slic3r::SLAPrintObject::is_left_handed(), Slic3r::PrintObjectBaseWithState< PrintType, PrintObjectStepEnum, COUNT >::is_step_done(), Slic3r::SLAPrintObject::SliceRecord::is_valid(), Slic3r::GUI::layer_height, m_clipping_planes, m_sla_caps, m_use_clipping_planes, Slic3r::SLAPrint::material_config(), Slic3r::SLAPrint::objects(), Slic3r::GUI::GLModel::Geometry::P3, Slic3r::ptSLA, Slic3r::GUI::GLModel::render(), Slic3r::GUI::GLModel::Geometry::reserve_indices(), Slic3r::GUI::GLModel::Geometry::reserve_vertices(), SCALED_EPSILON, SCALING_FACTOR, Slic3r::GLShaderProgram::set_uniform(), sla_print(), Slic3r::slaposSliceSupports, Slic3r::soModel, Slic3r::soSupport, Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), Slic3r::GUI::GLModel::Geometry::Triangles, Slic3r::triangulate_expolygons_3d(), and Slic3r::unscale().

Referenced by _render_scene(), and _render_sla_slices().

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

◆ _render_ssao_pass()

void Slic3r::GUI::GLCanvas3D::_render_ssao_pass ( unsigned int width,
unsigned int height )
private
8707{
8708 if (width == 0 || height == 0)
8709 return;
8710
8711 GLShaderProgram* shader = wxGetApp().get_shader("ssao");
8712 if (shader == nullptr)
8713 return;
8714
8715 if (m_ssao_color_texture_id == 0) {
8722 }
8723 if (m_ssao_depth_texture_id == 0) {
8730 }
8731
8732 if (m_ssao_texture_size[0] != width || m_ssao_texture_size[1] != height) {
8734 glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
8737 m_ssao_texture_size = { { width, height } };
8738 }
8739
8741 glsafe(::glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height));
8743 glsafe(::glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height));
8744
8745 const Camera& camera = wxGetApp().plater()->get_camera();
8746
8749
8750 shader->start_using();
8751 shader->set_uniform("view_model_matrix", Transform3d::Identity());
8752 shader->set_uniform("projection_matrix", Transform3d::Identity());
8753 shader->set_uniform("color_texture", 0);
8754 shader->set_uniform("depth_texture", 1);
8755 shader->set_uniform("inv_tex_size", Vec2f(1.0f / static_cast<float>(width), 1.0f / static_cast<float>(height)));
8756 shader->set_uniform("z_far", camera.get_far_z());
8757 // The shader reconstructs the surface normal from the depth buffer, there being no normal
8758 // target to read: it unprojects a pixel back into view space, then measures the result
8759 // against world +Z expressed in view space to tell a top surface from a wall.
8760 const Matrix4d inv_projection_matrix = camera.get_projection_matrix().matrix().inverse();
8761 shader->set_uniform("inv_projection_matrix", inv_projection_matrix);
8762 const Vec3d up_view = (camera.get_view_matrix().matrix().block<3, 3>(0, 0) * Vec3d::UnitZ()).normalized();
8763 shader->set_uniform("up_view", up_view);
8764
8769 m_background.render();
8773 shader->stop_using();
8774
8778}
std::array< unsigned int, 2 > m_ssao_texture_size
Definition GLCanvas3D.hpp:926
#define GL_TEXTURE1
Definition gl.h:1706
#define GL_UNSIGNED_INT
Definition gl.h:1940
#define glCopyTexSubImage2D
Definition gl.h:3521
#define GL_CLAMP_TO_EDGE
Definition gl.h:322

References _render_ssao_pass(), camera, GL_BLEND, GL_CLAMP_TO_EDGE, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_DEPTH_TEST, GL_LINEAR, GL_NEAREST, GL_ONE_MINUS_SRC_ALPHA, GL_RGBA, GL_SRC_ALPHA, GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, glActiveTexture, glBindTexture, glBlendFunc, glCopyTexSubImage2D, glDisable, glEnable, glGenTextures, glsafe, glTexImage2D, glTexParameteri, m_background, m_ssao_color_texture_id, m_ssao_depth_texture_id, m_ssao_texture_size, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by _render_scene(), and _render_ssao_pass().

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

◆ _render_style_editor()

void Slic3r::GUI::GLCanvas3D::_render_style_editor ( )
private
10173{
10174 bool show_style_editor = true;
10175 ImGui::Begin("ImGui Style Editor", &show_style_editor);
10176 // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
10177 // (without a reference style pointer, we will use one compared locally as a reference)
10178
10179 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
10180 ImGui::ShowFontSelector("Fonts##Selector");
10181 ImGui::Separator();
10182
10183 if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
10184 {
10185 if (ImGui::BeginTabItem("Colors"))
10186 {
10187 static int output_dest = 0;
10188 static bool output_only_modified = false;
10189 if (ImGui::Button("Export"))
10190 {
10191 if (output_dest == 0)
10192 ImGui::LogToClipboard();
10193 else
10194 ImGui::LogToTTY();
10195
10196 ImGui::LogText("RenderColors:" IM_NEWLINE);
10197 for (int i = 0; i < RenderCol_Count; i++)
10198 {
10199 const ImVec4& col = RenderColor::colors[i];
10200 const char* name = GetRenderColName(i);
10201 if (!output_only_modified || memcmp(&col, &RenderColor::colors[i], sizeof(ImVec4)) != 0)
10202 ImGui::LogText("RenderColor::colors[%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
10203 name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
10204 }
10205 ImGui::LogFinish();
10206 }
10207 ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
10208 ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
10209
10210 static ImGuiTextFilter filter;
10211 filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
10212
10213 static ImGuiColorEditFlags alpha_flags = 0;
10214 if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None)) { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
10215 if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview)) { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
10216 if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
10217 ImGui::TextDisabled("(?)");
10218 if (ImGui::IsItemHovered())
10219 {
10220 ImGui::BeginTooltip();
10221 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
10222 ImGui::TextUnformatted("In the color list:\n"
10223 "Left-click on color square to open color picker,\n"
10224 "Right-click to open edit options menu.");
10225 ImGui::PopTextWrapPos();
10226 ImGui::EndTooltip();
10227 }
10228 ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
10229 ImGui::PushItemWidth(-160);
10230 for (int i = 0; i < RenderCol_Count; i++)
10231 {
10232 const char* name = GetRenderColName(i);
10233 if (!filter.PassFilter(name))
10234 continue;
10235 ImGui::PushID(i);
10236 ImGui::ColorEdit4("##color", (float*)&RenderColor::colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
10237 // Tips: in a real user application, you may want to merge and use an icon font into the main font,
10238 // so instead of "Save"/"Revert" you'd use icons!
10239 // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
10240 ImGui::SameLine(0.0f, 3.0f);
10241 if (ImGui::Button("Set")) {
10247 }
10248 ImGui::SameLine(0.0f, 3.0f);
10249 ImGui::TextUnformatted(name);
10250 ImGui::PopID();
10251 }
10252 ImGui::PopItemWidth();
10253 ImGui::EndChild();
10254
10255 ImGui::EndTabItem();
10256 }
10257
10258 ImGui::EndTabBar();
10259 }
10260
10261 ImGui::PopItemWidth();
10262 ImGui::End();
10263}
@ RenderCol_Count
Definition GUI_Colors.hpp:31
static void update_render_colors()
Definition 3DScene.cpp:217
static void update_render_colors()
Definition 3DBed.cpp:213
static void update_render_colors()
Definition GLCanvas3D.cpp:199
static void update_render_colors()
Definition GLGizmoBase.cpp:80
static void update_render_colors()
Definition PartPlate.cpp:207
static ImVec4 colors[RenderCol_Count]
Definition GUI_Colors.hpp:40
const char * GetRenderColName(RenderCol idx)
Definition GUI_Colors.cpp:9

References _render_style_editor(), Slic3r::RenderColor::colors, Slic3r::GetRenderColName(), RenderCol_Count, Slic3r::GLVolume::update_render_colors(), Slic3r::GUI::Bed3D::update_render_colors(), update_render_colors(), Slic3r::GUI::GLGizmoBase::update_render_colors(), and Slic3r::GUI::PartPlate::update_render_colors().

Referenced by _render_frame(), and _render_style_editor().

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

◆ _render_volumes_for_picking()

void Slic3r::GUI::GLCanvas3D::_render_volumes_for_picking ( const Camera & camera) const
private
10266{
10267 GLShaderProgram* shader = wxGetApp().get_shader("flat_clip");
10268 if (shader == nullptr)
10269 return;
10270
10271 // do not cull backfaces to show broken geometry, if any
10273
10274 const Transform3d& view_matrix = camera.get_view_matrix();
10275 for (size_t type = 0; type < 2; ++ type) {
10277 for (const GLVolumeWithIdAndZ& volume : to_render)
10278 if (!volume.first->disabled && (volume.first->composite_id.volume_id >= 0 || m_render_sla_auxiliaries)) {
10279 // Object picking mode. Render the object with a color encoding the object index.
10280 // we reserve color = (0,0,0) for occluders (as the printbed)
10281 // so we shift volumes' id by 1 to get the proper color
10282 //BBS: remove the bed picking logic
10283 const unsigned int id = volume.second.first;
10284 //const unsigned int id = 1 + volume.second.first;
10285 volume.first->model.set_color(picking_decode(id));
10286 shader->start_using();
10287 shader->set_uniform("view_model_matrix", view_matrix * volume.first->world_matrix());
10288 shader->set_uniform("projection_matrix", camera.get_projection_matrix());
10289 shader->set_uniform("volume_world_matrix", volume.first->world_matrix());
10290 shader->set_uniform("z_range", m_volumes.get_z_range());
10291 shader->set_uniform("clipping_plane", m_volumes.get_clipping_plane());
10292 volume.first->picking = true;
10293 volume.first->render();
10294 volume.first->picking = false;
10295 shader->stop_using();
10296 }
10297 }
10298
10300}
ColorRGBA picking_decode(unsigned int id)
Definition Color.cpp:410
std::pair< GLVolume *, std::pair< unsigned int, double > > GLVolumeWithIdAndZ
Definition 3DScene.hpp:413
GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs &volumes, GLVolumeCollection::ERenderType type, const Transform3d &view_matrix, std::function< bool(const GLVolume &)> filter_func)
Definition 3DScene.cpp:1110
std::vector< GLVolumeWithIdAndZ > GLVolumeWithIdAndZList
Definition 3DScene.hpp:414

References _render_volumes_for_picking(), camera, GL_CULL_FACE, glDisable, glEnable, glsafe, m_render_sla_auxiliaries, m_volumes, Slic3r::GLVolumeCollection::Opaque, Slic3r::picking_decode(), Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), Slic3r::GLVolumeCollection::Transparent, and Slic3r::volumes_to_render().

Referenced by _rectangular_selection_picking_pass(), and _render_volumes_for_picking().

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

◆ _render_wireframe_overlay()

void Slic3r::GUI::GLCanvas3D::_render_wireframe_overlay ( )
private
9866{
9867 if (!wxGetApp().plater()->is_show_wireframe())
9868 return;
9869 if (m_volumes.empty())
9870 return;
9871
9872#if SLIC3R_OPENGL_ES
9873 GLShaderProgram* shader = wxGetApp().get_shader("wireframe");
9874#else
9875 GLShaderProgram* shader = wxGetApp().get_shader("mm_contour");
9876#endif
9877 if (shader == nullptr)
9878 return;
9879
9880 const Camera& camera = wxGetApp().plater()->get_camera();
9881 const Transform3d& view_matrix = camera.get_view_matrix();
9882 const Transform3d& proj_matrix = camera.get_projection_matrix();
9883 const Size sz = get_canvas_size();
9884
9885 shader->start_using();
9886 shader->set_uniform("offset", OpenGLManager::get_gl_info().is_mesa() ? 0.0005 : 0.00001);
9887 shader->set_uniform("view_model_matrix", view_matrix);
9888 shader->set_uniform("projection_matrix", proj_matrix);
9889
9891#if !SLIC3R_OPENGL_ES
9892 if (!OpenGLManager::get_gl_info().is_core_profile())
9893 glsafe(::glLineWidth(1.0f));
9895#endif
9896
9897 m_volumes.render(GLVolumeCollection::ERenderType::All, false, view_matrix, proj_matrix, sz, [](const GLVolume& volume) {
9898 return !volume.render_color.is_transparent() || (volume.visible && !volume.is_modifier && volume.color.is_transparent());
9899 });
9900
9901#if !SLIC3R_OPENGL_ES
9903#endif
9904 shader->stop_using();
9905}
@ All
Definition 3DScene.hpp:423
#define GL_FRONT_AND_BACK
Definition gl.h:761
#define GL_FILL
Definition gl.h:654
#define GL_LINE
Definition gl.h:929
#define glPolygonMode
Definition gl.h:4469

References _render_wireframe_overlay(), Slic3r::GLVolumeCollection::All, camera, Slic3r::GLVolume::color, get_canvas_size(), Slic3r::GUI::OpenGLManager::get_gl_info(), GL_DEPTH_TEST, GL_FILL, GL_FRONT_AND_BACK, GL_LINE, glEnable, glLineWidth, glPolygonMode, glsafe, Slic3r::ColorRGBA::is_transparent(), m_volumes, Slic3r::GUI::plater(), Slic3r::GLVolume::render_color, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), and Slic3r::GLShaderProgram::stop_using().

Referenced by _render_scene(), and _render_wireframe_overlay().

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

◆ _render_xray_volumes()

void Slic3r::GUI::GLCanvas3D::_render_xray_volumes ( )
private
9804{
9805 if (m_volumes.empty())
9806 return;
9807
9808 GLShaderProgram* shader = wxGetApp().get_shader("xray");
9809 if (shader == nullptr)
9810 return;
9811
9812 const Camera& camera = wxGetApp().plater()->get_camera();
9813 const ECanvasType canvas_type = m_canvas_type;
9814
9815 // Depth writes off so every surface along a view ray composites, not just the nearest one, and
9816 // back faces kept for the far wall of a hollow part. The low, near-uniform coverage the shader
9817 // emits saturates towards the volume color whatever the order, so the volumes are not sorted.
9821
9822 shader->start_using();
9823 m_volumes.render(GLVolumeCollection::ERenderType::All, true, camera.get_view_matrix(), camera.get_projection_matrix(),
9824 get_canvas_size(), [this, canvas_type](const GLVolume& volume) {
9825 if (canvas_type == ECanvasType::CanvasAssembleView)
9826 return !volume.is_modifier && !volume.is_wipe_tower;
9827 return m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0;
9828 });
9829 shader->stop_using();
9830
9833}

References _render_xray_volumes(), Slic3r::GLVolumeCollection::All, camera, CanvasAssembleView, Slic3r::GLVolume::composite_id, get_canvas_size(), GL_BLEND, GL_FALSE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_TRUE, glBlendFunc, glDepthMask, glDisable, glEnable, glsafe, m_canvas_type, m_render_sla_auxiliaries, m_volumes, Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), and Slic3r::GLVolume::CompositeID::volume_id.

Referenced by _render_objects(), and _render_xray_volumes().

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

◆ _resize()

void Slic3r::GUI::GLCanvas3D::_resize ( unsigned int w,
unsigned int h )
private
7850{
7851 if (m_canvas == nullptr && m_context == nullptr)
7852 return;
7853
7854 const std::array<unsigned int, 2> new_size = { w, h };
7855 if (m_old_size == new_size)
7856 return;
7857
7858 m_old_size = new_size;
7859
7860 auto* imgui = wxGetApp().imgui();
7861 imgui->set_display_size(static_cast<float>(w), static_cast<float>(h));
7862
7863 //BBS reduce render
7864 if (m_last_w == w && m_last_h == h) {
7865 return;
7866 }
7867
7868 m_last_w = w;
7869 m_last_h = h;
7870
7872
7873 this->request_extra_frame();
7874
7875 // ensures that this canvas is current
7876 _set_current();
7877}
unsigned int m_last_h
Definition GLCanvas3D.hpp:644
std::array< unsigned int, 2 > m_old_size
Definition GLCanvas3D.hpp:741
void set_imgui_scaling()
Definition GLCanvas3D.cpp:7879
unsigned int m_last_w
Definition GLCanvas3D.hpp:644

References _set_current(), m_canvas, m_context, m_last_h, m_last_w, m_old_size, request_extra_frame(), and set_imgui_scaling().

Referenced by _refresh_if_shown_on_screen(), and _render_frame().

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

◆ _scene_cache_key()

SceneCache::Key Slic3r::GUI::GLCanvas3D::_scene_cache_key ( const Camera & camera) const
private
8781{
8782 SceneCache::Key key;
8783 const std::array<int, 4>& viewport = camera.get_viewport();
8784 key.size = { { (unsigned int)viewport[2], (unsigned int)viewport[3] } };
8785 key.view_matrix = camera.get_view_matrix();
8786 key.projection_matrix = camera.get_projection_matrix();
8787 // Hover reaches the scene only through the sinking contour a hovered volume draws over
8788 // itself (GLVolumeCollection::render()), the plate icons (PartPlate::render_icons()) and the
8789 // open gizmo's grabbers.
8790 for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
8791 const GLVolume& volume = *m_volumes.volumes[i];
8792 if (volume.hover != GLVolume::HS_None && volume.is_sinking() && !volume.is_below_printbed())
8793 key.sinking_hover_volume_idxs.emplace_back((int)i);
8794 }
8795 for (int id : m_hover_plate_idxs) {
8796 if (id % PartPlate::GRABBER_COUNT != 0)
8797 key.hover_plate_icon_idxs.emplace_back(id);
8798 }
8799 const GLGizmoBase* gizmo = m_gizmos.get_current();
8800 key.gizmo_hover_id = gizmo != nullptr ? gizmo->get_hover_id() : -1;
8801 key.render_preview = m_render_preview;
8802 return key;
8803}
@ HS_None
Definition 3DScene.hpp:122

References _scene_cache_key(), camera, Slic3r::GUI::GLGizmoBase::get_hover_id(), Slic3r::GUI::SceneCache::Key::gizmo_hover_id, Slic3r::GUI::PartPlate::GRABBER_COUNT, Slic3r::GLVolume::hover, Slic3r::GUI::SceneCache::Key::hover_plate_icon_idxs, Slic3r::GLVolume::HS_None, Slic3r::GLVolume::is_below_printbed(), Slic3r::GLVolume::is_sinking(), m_gizmos, m_hover_plate_idxs, m_render_preview, m_volumes, Slic3r::GUI::SceneCache::Key::projection_matrix, Slic3r::GUI::SceneCache::Key::render_preview, Slic3r::GUI::SceneCache::Key::sinking_hover_volume_idxs, Slic3r::GUI::SceneCache::Key::size, and Slic3r::GUI::SceneCache::Key::view_matrix.

Referenced by _can_reuse_cached_scene(), _capture_scene_cache(), and _scene_cache_key().

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

◆ _set_current()

bool Slic3r::GUI::GLCanvas3D::_set_current ( )
private
7845{
7846 return m_context != nullptr && m_canvas->SetCurrent(*m_context);
7847}

References m_canvas, and m_context.

Referenced by ~GLCanvas3D(), _render_frame(), _resize(), _set_warning_notification_if_needed(), load_sla_preview(), make_current_for_postinit(), on_gesture(), on_mouse(), reload_scene(), and reset_volumes().

Here is the caller graph for this function:

◆ _set_overlay_as_dirty()

void Slic3r::GUI::GLCanvas3D::_set_overlay_as_dirty ( )
inlineprivate
1526{ m_overlay_dirty = true; }
bool m_overlay_dirty
Definition GLCanvas3D.hpp:747

References m_overlay_dirty.

Referenced by on_fps_overlay_timer(), on_key(), Slic3r::GUI::GLCanvas3D::CenterOfMass::on_left_down(), on_mouse(), and Slic3r::GUI::GLCanvas3D::CenterOfMass::render_details().

Here is the caller graph for this function:

◆ _set_shown_canvas_current()

bool Slic3r::GUI::GLCanvas3D::_set_shown_canvas_current ( )
private
2947{
2948 // Called before GL work outside render(), where another library's GL context (e.g. WebKitGTK's) can be current.
2949 // Inside render(), the shown canvas is the one already bound.
2950 return wxGetApp().plater()->get_current_canvas3D()->_set_current();
2951}

Referenced by load_gcode_preview(), load_shells(), render_thumbnail(), render_thumbnail(), and reset_gcode_toolpaths().

Here is the caller graph for this function:

◆ _set_warning_notification()

void Slic3r::GUI::GLCanvas3D::_set_warning_notification ( EWarning warning,
bool state )
private
12283{
12284 // Skip on shutdown: Plater's pImpl is already freed, so get_notification_manager() would use-after-free.
12285 if (wxGetApp().is_closing())
12286 return;
12287 using NotificationLevel = NotificationManager::NotificationLevel;
12288 enum ErrorType{
12289 PLATER_WARNING,
12290 PLATER_ERROR,
12291 SLICING_SERIOUS_WARNING,
12292 SLICING_ERROR,
12293 SLICING_LIMIT_ERROR,
12294 SLICING_HEIGHT_OUTSIDE
12295 };
12296 const static std::vector<std::string> extruder_name_list= {_u8L("left nozzle"), _u8L("right nozzle")}; // in ui, we treat extruder as nozzle
12297 std::string text;
12298 ErrorType error = ErrorType::PLATER_WARNING;
12299 const ModelObject* conflictObj=nullptr;
12300 const ModelInstance* conflictInst=nullptr;
12301 switch (warning) {
12303 static std::string prevConflictText;
12304 text = prevConflictText;
12305 error = ErrorType::SLICING_SERIOUS_WARNING;
12306 if (!m_gcode_viewer.m_conflict_result) { break; }
12307 std::string objName1 = m_gcode_viewer.m_conflict_result.value()._objName1;
12308 std::string objName2 = m_gcode_viewer.m_conflict_result.value()._objName2;
12309 double height = m_gcode_viewer.m_conflict_result.value()._height;
12310 int layer = m_gcode_viewer.m_conflict_result.value().layer;
12311 const PrintInstance *inst2 = reinterpret_cast<const PrintInstance *>(m_gcode_viewer.m_conflict_result.value()._obj2);
12312
12313 text = (boost::format(_u8L("Conflicts of G-code paths have been found at layer %d, Z = %.2lfmm. Please separate the conflicted objects farther (%s <-> %s).")) % layer %
12314 height % objName1 % objName2)
12315 .str();
12316 prevConflictText = text;
12317
12318 if (inst2) {
12319 if (inst2->model_instance) conflictInst = inst2->model_instance;
12320 else if (inst2->print_object) conflictObj = inst2->print_object->model_object();
12321 }
12322 break;
12323 }
12324 case EWarning::ObjectOutside: text = _u8L("An object is laid over the plate boundaries."); break;
12325 case EWarning::ToolHeightOutside: text = _u8L("A G-code path goes beyond the max print height."); error = ErrorType::SLICING_ERROR; break;
12326 case EWarning::ToolpathOutside: text = _u8L("A G-code path goes beyond plate boundaries."); error = ErrorType::SLICING_ERROR; break;
12328 text = _u8L("Not support printing 2 or more TPU filaments.");
12329 error = ErrorType::SLICING_ERROR;
12330 break;
12331 }
12333 text = filament_printable_error_msg.ToUTF8();
12334 error = ErrorType::SLICING_ERROR;
12335 break;
12336 }
12339 error = ErrorType::PLATER_ERROR;
12340 break;
12341 }
12343 for (auto error_iter = m_gcode_viewer.m_gcode_check_result.print_area_error_infos.begin(); error_iter != m_gcode_viewer.m_gcode_check_result.print_area_error_infos.end(); ++error_iter) {
12344 if (error_iter != m_gcode_viewer.m_gcode_check_result.print_area_error_infos.begin()) {
12345 text += "\n";
12346 }
12347 int extruder_id = error_iter->first + 1; // change extruder id to 1 based
12348 std::string filaments;
12349 std::vector<int> slice_error_object_idxs;
12350 for (size_t i = 0; i < error_iter->second.size(); ++i) {
12351 if (i > 0) {
12352 filaments += ", ";
12353 }
12354 int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based
12355 int object_label_id = error_iter->second[i].second;
12356
12357 filaments += std::to_string(filament_id);
12358 for (int object_idx = 0; object_idx < (int) m_model->objects.size(); ++object_idx) {
12359 const ModelObject *model_object = m_model->objects[object_idx];
12360 for (int instance_idx = 0; instance_idx < (int) model_object->instances.size(); ++instance_idx) {
12361 const ModelInstance *model_instance = model_object->instances[instance_idx];
12362 auto expect_id = model_instance->get_labeled_id();
12363 if (object_label_id == expect_id) {
12364 slice_error_object_idxs.emplace_back(object_idx);
12365 }
12366 }
12367 }
12368 }
12369 for (GLVolume *volume : m_gcode_viewer.m_shells.volumes.volumes) {
12370 for (auto obj_idx : slice_error_object_idxs) {
12371 if (volume->object_idx() == obj_idx) {
12372 volume->slice_error = true;
12373 volume->selected = true;
12374 }
12375 }
12376 }
12377 std::string extruder_name;
12378 if(wxGetApp().preset_bundle->is_bbl_vendor()){
12379 extruder_name = extruder_name_list[extruder_id-1];
12380 }
12381 else{
12382 extruder_name += (boost::format(_u8L("Tool %d"))%extruder_id).str();
12383 }
12384
12385 text += format(_L_PLURAL("Filament %1% is placed in the %2%, but the generated G-code path exceeds the printable range of the %2%.",
12386 "Filaments %1% are placed in the %2%, but the generated G-code path exceeds the printable range of the %2%.",
12387 error_iter->second.size()),
12388 filaments, extruder_name);
12389 }
12390 error = ErrorType::SLICING_LIMIT_ERROR;
12391 break;
12392 }
12394 for (auto error_iter = m_gcode_viewer.m_gcode_check_result.print_height_error_infos.begin(); error_iter != m_gcode_viewer.m_gcode_check_result.print_height_error_infos.end(); ++error_iter) {
12395 if (error_iter != m_gcode_viewer.m_gcode_check_result.print_height_error_infos.begin()) {
12396 text += "\n";
12397 }
12398 int extruder_id = error_iter->first + 1; // change extruder id to 1 based
12399 std::set<int> filament_ids;
12400 std::vector<int> slice_error_object_idxs;
12401 for (size_t i = 0; i < error_iter->second.size(); ++i) {
12402 int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based
12403 int object_label_id = error_iter->second[i].second;
12404 filament_ids.insert(filament_id);
12405 for (int object_idx = 0; object_idx < (int) m_model->objects.size(); ++object_idx) {
12406 const ModelObject *model_object = m_model->objects[object_idx];
12407 for (int instance_idx = 0; instance_idx < (int) model_object->instances.size(); ++instance_idx) {
12408 const ModelInstance *model_instance = model_object->instances[instance_idx];
12409 auto expect_id = model_instance->get_labeled_id();
12410 if (object_label_id == expect_id) {
12411 slice_error_object_idxs.emplace_back(object_idx);
12412 }
12413 }
12414 }
12415 }
12416
12417 std::string filaments;
12418 int index = 0;
12419 for (auto filament_id : filament_ids) {
12420 if (index > 0) {
12421 filaments += ", ";
12422 }
12423 filaments += std::to_string(filament_id);
12424 ++index;
12425 }
12426
12427 for (GLVolume *volume : m_gcode_viewer.m_shells.volumes.volumes) {
12428 for (auto obj_idx : slice_error_object_idxs) {
12429 if (volume->object_idx() == obj_idx) {
12430 volume->slice_error = true;
12431 volume->selected = true;
12432 }
12433 }
12434 }
12435 std::string extruder_name = extruder_name_list[extruder_id-1];
12436 text += format(_L_PLURAL("Filament %1% is placed in the %2%, but the generated G-code path exceeds the printable height of the %2%.",
12437 "Filaments %1% are placed in the %2%, but the generated G-code path exceeds the printable height of the %2%.",
12438 filament_ids.size()),
12439 filaments, extruder_name);
12440 }
12441 if (!text.empty()) {
12442 text += "\n";
12443 text += _u8L("Open wiki for more information.");
12444 }
12445 error = ErrorType::SLICING_HEIGHT_OUTSIDE;
12446 break;
12447 }
12448
12449 // BBS: remove _u8L() for SLA
12450 case EWarning::SlaSupportsOutside: text = ("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break;
12451 case EWarning::SomethingNotShown: text = _u8L("Only the object being edited is visible."); break;
12453 error = ErrorType::PLATER_ERROR;
12454 break;
12456 text = get_object_limited_text();
12457 break;
12459 std::string warning;
12460 const std::vector<int> &conflict_filament = m_gcode_viewer.filament_printable_reuslt.conflict_filament;
12461 auto iter = conflict_filament.begin();
12462 for (int filament : conflict_filament) {
12463 warning += std::to_string(filament + 1);
12464 warning += " ";
12465 }
12466 text = (boost::format(into_u8(_L_PLURAL("Filament %s cannot be printed directly on the surface of this plate.",
12467 "Filaments %s cannot be printed directly on the surface of this plate.", conflict_filament.size()))) % warning).str();
12468 error = ErrorType::SLICING_ERROR;
12469 break;
12470 }
12472 text = _u8L("PLA and PETG filaments detected in the mixture. Adjust parameters according to the Wiki to ensure print quality.");
12473 break;
12476 break;
12478 text = _u8L("The prime tower extends beyond the plate boundary.");
12479 break;
12482 break;
12483 }
12486 break;
12487 }
12489 text = _u8L("Partial flushing volume set to 0. Multi-color printing may cause color mixing in models. Please readjust flushing settings.");
12490 error = ErrorType::SLICING_ERROR;
12491 break;
12492 }
12493 //BBS: this may happened when exit the app, plater is null
12494 if (!wxGetApp().plater())
12495 return;
12496 auto& notification_manager = *wxGetApp().plater()->get_notification_manager();
12497
12498 switch (error)
12499 {
12500 case PLATER_WARNING:
12501 if (warning == EWarning::MixUsePLAAndPETG) {
12502 if (state) {
12503 notification_manager.push_slicing_customize_error_notification(NotificationType::BBLMixUsePLAAndPETG, NotificationLevel::WarningNotificationLevel, text, _u8L("Click Wiki for help."),
12504 [](wxEvtHandler*) {
12505 std::string language = wxGetApp().app_config->get("language");
12506 wxString region = L"en";
12507 if (language.find("zh") == 0)
12508 region = L"zh";
12509 // Although this link looks like it's only for the H2D, its guidance is generic.
12510 wxGetApp().open_browser_with_warning_dialog(wxString::Format(L"https://wiki.bambulab.com/%s/filament-acc/filament/h2d-pla-and-petg-mutual-support", region));
12511 return false;
12512 });
12513 }
12514 else
12515 notification_manager.close_slicing_customize_error_notification(NotificationType::BBLMixUsePLAAndPETG, NotificationLevel::WarningNotificationLevel);
12516 }
12517 else if (warning == EWarning::NozzleFilamentIncompatible){
12518 if(state){
12519 notification_manager.push_slicing_customize_error_notification(NotificationType::BBLNozzleFilamentIncompatible, NotificationLevel::WarningNotificationLevel, text);
12520 }
12521 else{
12522 notification_manager.close_slicing_customize_error_notification(NotificationType::BBLNozzleFilamentIncompatible, NotificationLevel::WarningNotificationLevel);
12523 }
12524 }
12525 else if (warning == EWarning::SingleExtruderMixedFilament) {
12526 // Close by type: check_single_extruder_mixed_filament_risk() clears the shared text
12527 // buffer on every call, so a close-by-text would miss once the risk is gone.
12528 if (state)
12529 notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSingleExtruderMixedFilamentRisk, NotificationLevel::WarningNotificationLevel, text);
12530 else
12531 notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSingleExtruderMixedFilamentRisk, NotificationLevel::WarningNotificationLevel);
12532 }
12533 else {
12534 if (state)
12535 notification_manager.push_plater_warning_notification(text);
12536 else
12537 notification_manager.close_plater_warning_notification(text);
12538 }
12539 break;
12540 case PLATER_ERROR:
12541 if (warning == EWarning::LeftExtruderPrintableError) {
12542 if (state) {
12543 if (auto left_str = get_left_extruder_unprintable_text(); !left_str.empty())
12544 notification_manager.bbl_show_filament_map_invalid_notification_before_slice(NotificationType::LeftExtruderUnprintableError, left_str);
12545 }
12546 else {
12547 notification_manager.bbl_close_filament_map_invalid_notification_before_slice(NotificationType::LeftExtruderUnprintableError);
12548 }
12549 }
12550 else if (warning == EWarning::RightExtruderPrintableError) {
12551 if (state) {
12552 if (auto right_str = get_right_extruder_unprintable_text(); !right_str.empty())
12553 notification_manager.bbl_show_filament_map_invalid_notification_before_slice(NotificationType::RightExtruderUnprintableError, right_str);
12554 }
12555 else {
12556 notification_manager.bbl_close_filament_map_invalid_notification_before_slice(NotificationType::RightExtruderUnprintableError);
12557 }
12558 }
12559 else if (warning == EWarning::ObjectClashed) {
12560 auto str = get_object_clashed_text();
12561 if(state){
12562 if (!str.empty())
12563 notification_manager.push_plater_error_notification(str);
12564 }
12565 else{
12566 notification_manager.close_plater_error_notification(str);
12567 }
12568 }
12569 else {
12570 if (state)
12571 notification_manager.push_plater_error_notification(text);
12572 else
12573 notification_manager.close_plater_error_notification(text);
12574 }
12575 break;
12576 case SLICING_SERIOUS_WARNING:
12577 if (state) {
12578 if (conflictInst) {
12579 notification_manager.push_slicing_serious_warning_notification(text, std::vector<ModelInstance const*>{conflictInst});
12580 } else {
12581 notification_manager.push_slicing_serious_warning_notification(text, conflictObj ? std::vector<ModelObject const*>{conflictObj} : std::vector<ModelObject const*>{});
12582 }
12583 }
12584 else
12585 notification_manager.close_slicing_serious_warning_notification(text);
12586 break;
12587 case SLICING_ERROR:
12589 if (state) {
12590 notification_manager.bbl_show_bed_filament_incompatible_notification(text);
12591 }
12592 else {
12593 notification_manager.bbl_close_bed_filament_incompatible_notification();
12594 }
12595 }
12596 if (warning == EWarning::FilamentPrintableError) {
12597 if (state){
12598 auto callback = [](wxEvtHandler*) {
12599 auto plater = wxGetApp().plater();
12600 auto partplate = plater->get_partplate_list().get_curr_plate();
12601 try_pop_up_before_slice(false, plater, partplate, true); // ignore the return value
12602 return false;
12603 };
12604 notification_manager.push_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationLevel::ErrorNotificationLevel, text, _u8L("Click here to regroup"), callback);
12605 }
12606 else
12607 notification_manager.close_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationLevel::ErrorNotificationLevel);
12608 }
12609 else if (warning == EWarning::FlushingVolumeZero) {
12610 if (state) {
12611 auto callback = [](wxEvtHandler *) {
12612 auto plater = wxGetApp().plater();
12613 const wxEventTypeTag<SimpleEvent> EVT_SCHEDULE_BACKGROUND_PROCESS(wxNewEventType());
12614 open_flushing_dialog(plater, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, plater));
12616 return false;
12617 };
12618 notification_manager.push_flushing_volume_error_notification(NotificationType::BBLFlushingVolumeZero, NotificationLevel::WarningNotificationLevel, text, _u8L("Flushing Volume"), callback);
12619 } else
12620 notification_manager.close_flushing_volume_error_notification(NotificationType::BBLFlushingVolumeZero, NotificationLevel::WarningNotificationLevel);
12621 }
12622 else {
12623 if (state)
12624 notification_manager.push_slicing_error_notification(text, conflictObj ? std::vector<ModelObject const*>{conflictObj} : std::vector<ModelObject const*>{});
12625 else
12626 notification_manager.close_slicing_error_notification(text);
12627 }
12628 break;
12629 case SLICING_LIMIT_ERROR:
12630 if (state)
12631 notification_manager.bbl_show_filament_map_invalid_notification_after_slice(NotificationType::BBLSliceLimitError, text);
12632 else
12633 notification_manager.bbl_close_filament_map_invalid_notification_after_slice(NotificationType::BBLSliceLimitError);
12634 break;
12635 case SLICING_HEIGHT_OUTSIDE:
12636 if (state)
12637 notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationLevel::ErrorNotificationLevel, text);
12638 else
12639 notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationLevel::ErrorNotificationLevel);
12640 break;
12641 default:
12642 break;
12643 }
12644}
void open_flushing_dialog(wxEvtHandler *parent, const wxEvent &event)
Definition WipeTowerDialog.cpp:273
@ ObjectOutside
Definition GLCanvas3D.hpp:418
@ SomethingNotShown
Definition GLCanvas3D.hpp:421
@ ToolpathOutside
Definition GLCanvas3D.hpp:419
@ LeftExtruderPrintableError
Definition GLCanvas3D.hpp:428
@ MixtureFilamentIncompatible
Definition GLCanvas3D.hpp:436
@ FilamentPrintableError
Definition GLCanvas3D.hpp:427
@ RightExtruderPrintableError
Definition GLCanvas3D.hpp:429
@ ToolHeightOutside
Definition GLCanvas3D.hpp:425
@ TPUPrintableError
Definition GLCanvas3D.hpp:426
@ NozzleFilamentIncompatible
Definition GLCanvas3D.hpp:435
@ MultiExtruderHeightOutside
Definition GLCanvas3D.hpp:431
@ SingleExtruderMixedFilament
Definition GLCanvas3D.hpp:437
@ FlushingVolumeZero
Definition GLCanvas3D.hpp:438
@ SlaSupportsOutside
Definition GLCanvas3D.hpp:420
@ ObjectClashed
Definition GLCanvas3D.hpp:422
@ PrimeTowerOutside
Definition GLCanvas3D.hpp:434
@ ObjectLimited
Definition GLCanvas3D.hpp:423
@ MixUsePLAAndPETG
Definition GLCanvas3D.hpp:433
@ MultiExtruderPrintableError
Definition GLCanvas3D.hpp:430
@ FilamentUnPrintableOnFirstLayer
Definition GLCanvas3D.hpp:432
@ GCodeConflict
Definition GLCanvas3D.hpp:424
NotificationLevel
Definition NotificationManager.hpp:208
PartPlate * get_curr_plate()
Definition PartPlate.hpp:962
std::string & get_left_extruder_unprintable_text()
Definition GLCanvas3D.cpp:269
std::string & get_object_clashed_text()
Definition GLCanvas3D.cpp:263
wxString filament_printable_error_msg
Definition GLCanvas3D.cpp:302
std::string & get_object_limited_text()
Definition GLCanvas3D.cpp:257
bool try_pop_up_before_slice(bool is_slice_all, Plater *plater_ref, PartPlate *partplate_ref, bool force_pop_up)
Try to pop up the filament map dialog before slicing.
Definition FilamentMapDialog.cpp:127
@ BBLSingleExtruderMixedFilamentRisk
Definition NotificationManager.hpp:186
@ RightExtruderUnprintableError
Definition NotificationManager.hpp:108
@ BBLFlushingVolumeZero
Definition NotificationManager.hpp:172
@ LeftExtruderUnprintableError
Definition NotificationManager.hpp:107
@ BBLSliceLimitError
Definition NotificationManager.hpp:180
@ BBLMixUsePLAAndPETG
Definition NotificationManager.hpp:183
@ BBLFilamentPrintableError
Definition NotificationManager.hpp:179
@ BBLNozzleFilamentIncompatible
Definition NotificationManager.hpp:184
@ BBLSliceMultiExtruderHeightOutside
Definition NotificationManager.hpp:181
std::string & get_filament_mixture_warning_text()
Definition GLCanvas3D.cpp:284
std::string & get_single_extruder_mixed_filament_warning_text()
Definition GLCanvas3D.cpp:289
std::string & get_right_extruder_unprintable_text()
Definition GLCanvas3D.cpp:274
std::string & get_nozzle_filament_incompatible_text()
Definition GLCanvas3D.cpp:279
zaa_minimize_perimeter_height filament_ids((ConfigOptionStrings, filament_colour))((ConfigOptionStrings
#define _L_PLURAL(s, plural, n)
Definition I18N.hpp:96

References _L_PLURAL, _set_warning_notification(), _u8L, Slic3r::GUI::BBLFilamentPrintableError, Slic3r::GUI::BBLFlushingVolumeZero, Slic3r::GUI::BBLMixUsePLAAndPETG, Slic3r::GUI::BBLNozzleFilamentIncompatible, Slic3r::GUI::BBLSingleExtruderMixedFilamentRisk, Slic3r::GUI::BBLSliceLimitError, Slic3r::GUI::BBLSliceMultiExtruderHeightOutside, Slic3r::filament_ids(), Slic3r::GUI::filament_printable_error_msg, FilamentPrintableError, FilamentUnPrintableOnFirstLayer, FlushingVolumeZero, Slic3r::format(), GCodeConflict, Slic3r::GUI::get_filament_mixture_warning_text(), Slic3r::ModelInstance::get_labeled_id(), Slic3r::GUI::get_left_extruder_unprintable_text(), Slic3r::GUI::get_nozzle_filament_incompatible_text(), Slic3r::GUI::get_object_clashed_text(), Slic3r::GUI::get_object_limited_text(), Slic3r::GUI::get_right_extruder_unprintable_text(), Slic3r::GUI::get_single_extruder_mixed_filament_warning_text(), Slic3r::ModelObject::instances, Slic3r::into_u8(), L, LeftExtruderPrintableError, Slic3r::GUI::LeftExtruderUnprintableError, m_gcode_viewer, m_model, MixtureFilamentIncompatible, MixUsePLAAndPETG, Slic3r::PrintInstance::model_instance, Slic3r::PrintObjectBase::model_object(), MultiExtruderHeightOutside, MultiExtruderPrintableError, NozzleFilamentIncompatible, Slic3r::GLVolume::object_idx(), ObjectClashed, ObjectLimited, ObjectOutside, open_flushing_dialog(), Slic3r::GUI::plater(), PrimeTowerOutside, Slic3r::PrintInstance::print_object, RightExtruderPrintableError, Slic3r::GUI::RightExtruderUnprintableError, SingleExtruderMixedFilament, SlaSupportsOutside, SomethingNotShown, ToolHeightOutside, ToolpathOutside, TPUPrintableError, and Slic3r::GUI::try_pop_up_before_slice().

Referenced by _set_warning_notification(), _set_warning_notification_if_needed(), reload_scene(), reset_volumes(), and toggle_model_objects_visibility().

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

◆ _set_warning_notification_if_needed()

void Slic3r::GUI::GLCanvas3D::_set_warning_notification_if_needed ( EWarning warning)
private
12247{
12248 _set_current();
12249 bool show = false;
12250 if (!m_volumes.empty()) {
12251 show = _is_any_volume_outside();
12252 show &= m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value();
12253 } else {
12254 if (wxGetApp().is_editor()) {
12256 unsigned int max_z_layer = m_gcode_viewer.get_layers_z_range().back();
12257 if (warning == EWarning::ToolHeightOutside) // check if max z_layer height exceed max print height
12258 // Belt printer with active post-gcode machine-frame transform: layer Z values
12259 // live in the machine frame, not the build-volume frame, so the comparison
12260 // against printable_height is meaningless. Suppress the warning entirely.
12261 show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_machine_frame_transform_active()
12262 && (m_gcode_viewer.get_layers_zs()[max_z_layer] - m_gcode_viewer.get_max_print_height() >= 1e-6);
12263 else if (warning == EWarning::ToolpathOutside) { // check if max x,y coords exceed bed area
12264 show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed() &&
12265 (m_gcode_viewer.get_max_print_height() -m_gcode_viewer.get_layers_zs()[max_z_layer] >= 1e-6);
12266 }
12267 else if (warning == EWarning::GCodeConflict)
12268 show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value();
12269 else if (warning == EWarning::MultiExtruderPrintableError)
12270 show = m_gcode_viewer.has_data() && (m_gcode_viewer.m_gcode_check_result.error_code & 1);
12271 else if (warning == EWarning::MultiExtruderHeightOutside)
12272 show = m_gcode_viewer.has_data() && (m_gcode_viewer.m_gcode_check_result.error_code & (1 << 1));
12274 show = m_gcode_viewer.has_data() && m_gcode_viewer.filament_printable_reuslt.has_value();
12275 }
12276 }
12277 }
12278
12279 _set_warning_notification(warning, show);
12280}
void _set_warning_notification(EWarning warning, bool state)
Definition GLCanvas3D.cpp:12282

References _is_any_volume_outside(), _set_current(), _set_warning_notification(), _set_warning_notification_if_needed(), current_printer_technology(), FilamentUnPrintableOnFirstLayer, GCodeConflict, m_gcode_viewer, m_volumes, MultiExtruderHeightOutside, MultiExtruderPrintableError, Slic3r::ptSLA, ToolHeightOutside, and ToolpathOutside.

Referenced by _set_warning_notification_if_needed(), _update_slice_error_status(), and load_sla_preview().

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

◆ _shadow_casters_signature()

size_t Slic3r::GUI::GLCanvas3D::_shadow_casters_signature ( bool toolpath_casters) const
private
8550{
8551 if (toolpath_casters)
8552 return m_gcode_viewer.shadow_casters_signature();
8553
8554 size_t hash = 1;
8555 for (const GLVolume* volume : m_volumes.volumes) {
8556 if (volume == nullptr || !volume->is_active || !volume->printable || volume->is_modifier || volume->is_wipe_tower)
8557 continue;
8558 boost::hash_combine(hash, volume);
8559 boost::hash_combine(hash, volume->model.vertices_count());
8560 boost::hash_combine(hash, volume->model.indices_count());
8561 const BoundingBoxf3& bb = volume->model.get_bounding_box();
8562 for (double value : { bb.min.x(), bb.min.y(), bb.min.z(), bb.max.x(), bb.max.y(), bb.max.z() })
8563 boost::hash_combine(hash, value);
8564 const Transform3d world = volume->world_matrix();
8565 for (int i = 0; i < 16; ++i)
8566 boost::hash_combine(hash, world.matrix().data()[i]);
8567 }
8568 return hash;
8569}

References _shadow_casters_signature(), Slic3r::GUI::GLModel::get_bounding_box(), Slic3r::GUI::GLModel::indices_count(), m_gcode_viewer, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GLVolume::model, Slic3r::GUI::GLModel::vertices_count(), and Slic3r::GLVolume::world_matrix().

Referenced by _render_shadows(), and _shadow_casters_signature().

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

◆ _shadow_mode()

GLCanvas3D::EShadowMode Slic3r::GUI::GLCanvas3D::_shadow_mode ( ) const
private
8544{
8545 const std::string mode = wxGetApp().app_config != nullptr ? wxGetApp().app_config->get(SETTING_OPENGL_REALISTIC_SHADOWS) : std::string();
8546 return mode == "static" ? EShadowMode::Static : mode == "orbit" ? EShadowMode::Orbit : EShadowMode::Off;
8547}
#define SETTING_OPENGL_REALISTIC_SHADOWS
Definition AppConfig.hpp:46
@ Orbit
Definition GLCanvas3D.hpp:1511

References _shadow_mode(), Off, Orbit, SETTING_OPENGL_REALISTIC_SHADOWS, and Static.

Referenced by _render_gcode(), _render_shadows(), _shadow_mode(), and _static_light_dir_eye().

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

◆ _start_timer()

void Slic3r::GUI::GLCanvas3D::_start_timer ( )
inlineprivate
1634{ m_timer.Start(100, wxTIMER_CONTINUOUS); }

References m_timer.

Referenced by _perform_layer_editing_action().

Here is the caller graph for this function:

◆ _static_light_dir_eye()

std::optional< Vec3d > Slic3r::GUI::GLCanvas3D::_static_light_dir_eye ( ) const
private
8536{
8538 return std::nullopt;
8539 const Matrix3d view_rot = wxGetApp().plater()->get_camera().get_view_matrix().matrix().block<3, 3>(0, 0);
8540 return Vec3d((view_rot * STATIC_LIGHT_DIR).normalized());
8541}

References _is_realistic_view_enabled(), _shadow_mode(), _static_light_dir_eye(), Static, and Slic3r::GUI::STATIC_LIGHT_DIR.

Referenced by _render_gcode(), _render_objects(), and _static_light_dir_eye().

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

◆ _stop_timer()

void Slic3r::GUI::GLCanvas3D::_stop_timer ( )
inlineprivate
1635{ m_timer.Stop(); }

References m_timer.

Referenced by on_mouse().

Here is the caller graph for this function:

◆ _switch_toolbars_icon_filename()

void Slic3r::GUI::GLCanvas3D::_switch_toolbars_icon_filename ( )
private
7400{
7401 BackgroundTexture::Metadata background_data;
7402 background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png";
7403 background_data.left = 16;
7404 background_data.top = 16;
7405 background_data.right = 16;
7406 background_data.bottom = 16;
7407 m_main_toolbar.init(background_data);
7408 m_assemble_view_toolbar.init(background_data);
7409 m_separator_toolbar.init(background_data);
7410 collapse_toolbar().init(background_data);
7411
7412 // main toolbar
7413 {
7414 GLToolbarItem* item;
7415 item = m_main_toolbar.get_item("add");
7416 item->set_icon_filename(m_is_dark ? "toolbar_open_dark.svg" : "toolbar_open.svg");
7417
7418 item = m_main_toolbar.get_item("addplate");
7419 item->set_icon_filename(m_is_dark ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg");
7420
7421 item = m_main_toolbar.get_item("orient");
7422 item->set_icon_filename(m_is_dark ? "toolbar_orient_dark.svg" : "toolbar_orient.svg");
7423
7424 item = m_main_toolbar.get_item("addplate");
7425 item->set_icon_filename(m_is_dark ? "toolbar_add_plate_dark.svg" : "toolbar_add_plate.svg");
7426
7427 item = m_main_toolbar.get_item("arrange");
7428 item->set_icon_filename(m_is_dark ? "toolbar_arrange_dark.svg" : "toolbar_arrange.svg");
7429
7430 item = m_main_toolbar.get_item("more");
7431 item->set_icon_filename(m_is_dark ? "instance_add_dark.svg" : "instance_add.svg");
7432
7433 item = m_main_toolbar.get_item("fewer");
7434 item->set_icon_filename(m_is_dark ? "instance_remove_dark.svg" : "instance_remove.svg");
7435
7436 item = m_main_toolbar.get_item("splitobjects");
7437 item->set_icon_filename(m_is_dark ? "split_objects_dark.svg" : "split_objects.svg");
7438
7439 item = m_main_toolbar.get_item("splitvolumes");
7440 item->set_icon_filename(m_is_dark ? "split_parts_dark.svg" : "split_parts.svg");
7441
7442 item = m_main_toolbar.get_item("layersediting");
7443 item->set_icon_filename(m_is_dark ? "toolbar_variable_layer_height_dark.svg" : "toolbar_variable_layer_height.svg");
7444 }
7445
7446 // assemble view toolbar
7447 {
7448 GLToolbarItem* item;
7449 item = m_assemble_view_toolbar.get_item("assembly_view");
7450 item->set_icon_filename(m_is_dark ? "toolbar_assemble_dark.svg" : "toolbar_assemble.svg");
7451 }
7452}
bool init(const BackgroundTexture::Metadata &background_texture)
Definition GLToolbar.cpp:281

References Slic3r::GUI::BackgroundTexture::Metadata::bottom, collapse_toolbar(), Slic3r::GUI::BackgroundTexture::Metadata::filename, Slic3r::GUI::GLToolbar::init(), Slic3r::GUI::BackgroundTexture::Metadata::left, m_assemble_view_toolbar, m_is_dark, m_main_toolbar, m_separator_toolbar, Slic3r::GUI::BackgroundTexture::Metadata::right, Slic3r::GUI::GLToolbarItem::set_icon_filename(), and Slic3r::GUI::BackgroundTexture::Metadata::top.

Referenced by on_change_color_mode().

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

◆ _update_camera_zoom()

void Slic3r::GUI::GLCanvas3D::_update_camera_zoom ( double zoom)
private
7942{
7943 wxGetApp().plater()->get_camera().update_zoom(zoom);
7944 m_dirty = true;
7945}

References m_dirty.

Referenced by handle_shortcut(), and on_mouse_wheel().

Here is the caller graph for this function:

◆ _update_imgui_select_plate_toolbar()

bool Slic3r::GUI::GLCanvas3D::_update_imgui_select_plate_toolbar ( )
private
7686{
7687 if (!m_sel_plate_toolbar.is_enabled()) {
7688 return false;
7689 }
7690
7691 const auto& p_plater = wxGetApp().plater();
7692 if (!p_plater) {
7693 return false;
7694 }
7695
7696 if (!p_plater->is_plate_toolbar_image_dirty()) {
7697 return false;
7698 }
7699
7700 if (!p_plater->is_gcode_3mf()) {
7701 p_plater->update_all_plate_thumbnails(true);
7702 }
7703
7705
7706 m_sel_plate_toolbar.del_all_item();
7707
7708 PartPlateList& plate_list = p_plater->get_partplate_list();
7709 for (int i = 0; i < plate_list.get_plate_count(); i++) {
7710 IMToolbarItem* item = new IMToolbarItem();
7711 if (PartPlate* plate = plate_list.get_plate(i))
7712 item->set_thumbnail(plate->thumbnail_data);
7713 m_sel_plate_toolbar.m_items.push_back(item);
7714 }
7715 p_plater->clear_plate_toolbar_image_dirty();
7716 m_sel_plate_toolbar.is_display_scrollbar = false;
7717 return true;
7718}
void _update_select_plate_toolbar_stats_item(bool force_selected=false)
Definition GLCanvas3D.cpp:7674

References _update_select_plate_toolbar_stats_item(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), m_sel_plate_toolbar, and Slic3r::GUI::IMToolbarItem::set_thumbnail().

Referenced by _render_imgui_select_plate_toolbar().

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

◆ _update_inactive_plates_visibility()

bool Slic3r::GUI::GLCanvas3D::_update_inactive_plates_visibility ( )
private
9002{
9003 const bool hide = _hides_inactive_plates();
9004 if (!hide && !m_inactive_plates_hidden)
9005 return false;
9006
9007 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
9008 PartPlate* plate = hide ? plate_list.get_curr_plate() : nullptr;
9009
9010 struct Instance
9011 {
9012 BoundingBoxf3 box;
9013 bool selected{ false };
9014 };
9015 std::map<std::pair<int, int>, Instance> instances;
9016 if (plate != nullptr)
9017 for (const GLVolume* volume : m_volumes.volumes) {
9018 Instance& instance = instances[{ volume->object_idx(), volume->instance_idx() }];
9019 instance.box.merge(volume->transformed_convex_hull_bounding_box());
9020 instance.selected |= volume->selected;
9021 }
9022
9023 // A gizmo that hides the other objects shows them all again when it closes.
9024 const bool keep_hidden = m_gizmos.is_hiding_instances();
9025 bool changed = false;
9026 bool any_hidden = false;
9027 std::vector<bool> shown_again(m_volumes.volumes.size(), false);
9028 for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
9029 GLVolume* volume = m_volumes.volumes[i];
9030 const Instance* instance = plate != nullptr ? &instances[{ volume->object_idx(), volume->instance_idx() }] : nullptr;
9031 if (instance != nullptr && !instance->selected && instance->box.defined && !plate->get_bounding_box().overlap(instance->box)) {
9032 changed |= volume->is_active;
9033 volume->is_active = false;
9034 volume->on_hidden_plate = true;
9035 } else if (volume->on_hidden_plate && !keep_hidden) {
9036 volume->is_active = true;
9037 volume->on_hidden_plate = false;
9038 shown_again[i] = true;
9039 changed = true;
9040 }
9041 any_hidden |= volume->on_hidden_plate;
9042 }
9043
9045 for (const std::shared_ptr<SceneRaycasterItem>& item : *raycasters) {
9046 const int i = SceneRaycaster::decode_id(SceneRaycaster::EType::Volume, item->get_id());
9047 if (0 <= i && i < int(m_volumes.volumes.size()) && (m_volumes.volumes[i]->on_hidden_plate || shown_again[i]))
9048 item->set_active(shown_again[i]);
9049 }
9051 for (const std::shared_ptr<SceneRaycasterItem>& item : *raycasters)
9052 item->set_active(!hide || SceneRaycaster::decode_id(SceneRaycaster::EType::Bed, item->get_id()) / PartPlate::GRABBER_COUNT ==
9053 plate_list.get_curr_plate_index());
9054
9055 m_inactive_plates_hidden = hide || any_hidden;
9056 return changed;
9057}
bool m_inactive_plates_hidden
Definition GLCanvas3D.hpp:786
std::vector< std::shared_ptr< SceneRaycasterItem > > * get_raycasters_for_picking(SceneRaycaster::EType type)
Definition GLCanvas3D.hpp:972
@ Instance
Definition GUI_Geometry.hpp:10

References _hides_inactive_plates(), _update_inactive_plates_visibility(), Slic3r::GUI::SceneRaycaster::Bed, Slic3r::GUI::SceneRaycaster::decode_id(), Slic3r::GUI::PartPlate::get_bounding_box(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlateList::get_curr_plate_index(), get_raycasters_for_picking(), Slic3r::GUI::PartPlate::GRABBER_COUNT, Slic3r::GUI::Instance, Slic3r::GLVolume::instance_idx(), m_gizmos, m_inactive_plates_hidden, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::overlap(), Slic3r::GLVolume::transformed_convex_hull_bounding_box(), and Slic3r::GUI::SceneRaycaster::Volume.

Referenced by _render_frame(), and _update_inactive_plates_visibility().

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

◆ _update_select_plate_toolbar_stats_item()

void Slic3r::GUI::GLCanvas3D::_update_select_plate_toolbar_stats_item ( bool force_selected = false)
7674 {
7675 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
7676 if (plate_list.get_nonempty_plate_list().size() > 1)
7677 m_sel_plate_toolbar.show_stats_item = true;
7678 else
7679 m_sel_plate_toolbar.show_stats_item = false;
7680
7681 if (force_selected && m_sel_plate_toolbar.show_stats_item && m_sel_plate_toolbar.m_all_plates_stats_item)
7682 m_sel_plate_toolbar.m_all_plates_stats_item->selected = true;
7683}

References Slic3r::GUI::PartPlateList::get_nonempty_plate_list(), and m_sel_plate_toolbar.

Referenced by _update_imgui_select_plate_toolbar().

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

◆ _update_selection_from_hover()

void Slic3r::GUI::GLCanvas3D::_update_selection_from_hover ( )
private
12673{
12674 bool ctrl_pressed = wxGetKeyState(WXK_CONTROL);
12675
12676 if (m_hover_volume_idxs.empty()) {
12677 if (!ctrl_pressed && (m_rectangle_selection.get_state() == GLSelectionRectangle::Select))
12678 m_selection.remove_all();
12679
12680 return;
12681 }
12682
12684
12685 bool hover_modifiers_only = true;
12686 for (int i : m_hover_volume_idxs) {
12687 if (!m_volumes.volumes[i]->is_modifier) {
12688 hover_modifiers_only = false;
12689 break;
12690 }
12691 }
12692
12693 bool selection_changed = false;
12694 if (state == GLSelectionRectangle::Select) {
12695 bool contains_all = true;
12696 for (int i : m_hover_volume_idxs) {
12697 if (!m_selection.contains_volume((unsigned int)i)) {
12698 contains_all = false;
12699 break;
12700 }
12701 }
12702
12703 // the selection is going to be modified (Add)
12704 if (!contains_all) {
12705 wxGetApp().plater()->take_snapshot(std::string("Select by rectangle"), UndoRedo::SnapshotType::Selection);
12706 selection_changed = true;
12707 }
12708 }
12709 else {
12710 bool contains_any = false;
12711 for (int i : m_hover_volume_idxs) {
12712 if (m_selection.contains_volume((unsigned int)i)) {
12713 contains_any = true;
12714 break;
12715 }
12716 }
12717
12718 // the selection is going to be modified (Remove)
12719 if (contains_any) {
12720 wxGetApp().plater()->take_snapshot(std::string("Unselect by rectangle"), UndoRedo::SnapshotType::Selection);
12721 selection_changed = true;
12722 }
12723 }
12724
12725 if (!selection_changed)
12726 return;
12727
12728 Plater::SuppressSnapshots suppress(wxGetApp().plater());
12729
12730 if ((state == GLSelectionRectangle::Select) && !ctrl_pressed)
12731 m_selection.clear();
12732
12733 for (int i : m_hover_volume_idxs) {
12734 if (state == GLSelectionRectangle::Select) {
12735 if (hover_modifiers_only) {
12736 const GLVolume& v = *m_volumes.volumes[i];
12737 m_selection.add_volume(v.object_idx(), v.volume_idx(), v.instance_idx(), false);
12738 }
12739 else
12740 m_selection.add(i, false);
12741 }
12742 else
12743 m_selection.remove(i);
12744 }
12745
12746 if (m_selection.is_empty())
12747 m_gizmos.reset_all_states();
12748 else
12749 m_gizmos.refresh_on_off_state();
12750
12751 m_gizmos.update_data();
12752 post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
12753 m_dirty = true;
12754}
EState
Definition GLSelectionRectangle.hpp:18
@ Select
Definition GLSelectionRectangle.hpp:20
@ Selection
Definition UndoRedo.hpp:38

References _update_selection_from_hover(), Slic3r::GLVolume::instance_idx(), m_dirty, m_gizmos, m_hover_volume_idxs, m_rectangle_selection, m_selection, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::GUI::plater(), post_event(), Slic3r::GUI::GLSelectionRectangle::Select, Slic3r::UndoRedo::Selection, and Slic3r::GLVolume::volume_idx().

Referenced by _update_selection_from_hover(), on_key(), and on_mouse().

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

◆ _update_sla_shells_outside_state()

void Slic3r::GUI::GLCanvas3D::_update_sla_shells_outside_state ( )
inlineprivate
ModelInstanceEPrintVolumeState check_volumes_outside_state(ObjectFilamentResults *object_results=nullptr) const
Definition GLCanvas3D.cpp:1971

References check_volumes_outside_state().

Referenced by load_sla_preview().

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

◆ _update_slice_error_status()

void Slic3r::GUI::GLCanvas3D::_update_slice_error_status ( )
private

References _set_warning_notification_if_needed(), FilamentUnPrintableOnFirstLayer, GCodeConflict, MultiExtruderHeightOutside, MultiExtruderPrintableError, ToolHeightOutside, and ToolpathOutside.

Referenced by load_gcode_preview(), and reload_scene().

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

◆ _update_volumes_hover_state()

void Slic3r::GUI::GLCanvas3D::_update_volumes_hover_state ( )
private
11921{
11922 for (GLVolume* v : m_volumes.volumes) {
11923 v->hover = GLVolume::HS_None;
11924 }
11925
11926 if (m_hover_volume_idxs.empty())
11927 return;
11928
11929 bool ctrl_pressed = wxGetKeyState(WXK_CONTROL); // additive select/deselect
11930 bool shift_pressed = wxGetKeyState(WXK_SHIFT); // select by rectangle
11931 bool alt_pressed = wxGetKeyState(WXK_ALT); // deselect by rectangle
11932
11933 if (alt_pressed && (shift_pressed || ctrl_pressed)) {
11934 // illegal combinations of keys
11935 m_hover_volume_idxs.clear();
11936 return;
11937 }
11938
11939 bool selection_modifiers_only = m_selection.is_empty() || m_selection.is_any_modifier();
11940
11941 bool hover_modifiers_only = true;
11942 for (int i : m_hover_volume_idxs) {
11943 if (!m_volumes.volumes[i]->is_modifier) {
11944 hover_modifiers_only = false;
11945 break;
11946 }
11947 }
11948
11949 std::set<std::pair<int, int>> hover_instances;
11950 for (int i : m_hover_volume_idxs) {
11951 const GLVolume& v = *m_volumes.volumes[i];
11952 hover_instances.insert(std::make_pair(v.object_idx(), v.instance_idx()));
11953 }
11954
11955 bool hover_from_single_instance = hover_instances.size() == 1;
11956
11957 if (hover_modifiers_only && !hover_from_single_instance) {
11958 // do not allow to select volumes from different instances
11959 m_hover_volume_idxs.clear();
11960 return;
11961 }
11962
11963 for (int i : m_hover_volume_idxs) {
11964 GLVolume& volume = *m_volumes.volumes[i];
11965 if (volume.hover != GLVolume::HS_None)
11966 continue;
11967
11968 bool deselect = volume.selected && ((ctrl_pressed && !shift_pressed) || alt_pressed);
11969 // (volume->is_modifier && !selection_modifiers_only && !is_ctrl_pressed) -> allows hovering on selected modifiers belonging to selection of type Instance
11970 bool select = (!volume.selected || (volume.is_modifier && !selection_modifiers_only && !ctrl_pressed)) && !alt_pressed;
11971
11972 if (select || deselect) {
11973 bool as_volume =
11974 volume.is_modifier && hover_from_single_instance && !ctrl_pressed &&
11975 (
11976 (!deselect) ||
11977 (deselect && !m_selection.is_single_full_instance() && (volume.object_idx() == m_selection.get_object_idx()) && (volume.instance_idx() == m_selection.get_instance_idx()))
11978 );
11979
11980 if (as_volume)
11981 volume.hover = deselect ? GLVolume::HS_Deselect : GLVolume::HS_Select;
11982 else {
11983 int object_idx = volume.object_idx();
11984 int instance_idx = volume.instance_idx();
11985
11986 for (GLVolume* v : m_volumes.volumes) {
11987 if (v->object_idx() == object_idx && v->instance_idx() == instance_idx)
11988 v->hover = deselect ? GLVolume::HS_Deselect : GLVolume::HS_Select;
11989 }
11990 }
11991 }
11992 else if (volume.selected)
11993 volume.hover = GLVolume::HS_Hover;
11994 }
11995}
@ HS_Select
Definition 3DScene.hpp:124
@ HS_Hover
Definition 3DScene.hpp:123
@ HS_Deselect
Definition 3DScene.hpp:125

References _update_volumes_hover_state(), Slic3r::GLVolume::hover, Slic3r::GLVolume::HS_Deselect, Slic3r::GLVolume::HS_Hover, Slic3r::GLVolume::HS_None, Slic3r::GLVolume::HS_Select, Slic3r::GLVolume::instance_idx(), m_hover_volume_idxs, m_selection, m_volumes, and Slic3r::GLVolume::object_idx().

Referenced by _picking_pass(), and _update_volumes_hover_state().

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

◆ _zoom_to_box()

void Slic3r::GUI::GLCanvas3D::_zoom_to_box ( const BoundingBoxf3 & box,
double margin_factor = DefaultCameraZoomToBoxMarginFactor )
private
7936{
7937 wxGetApp().plater()->get_camera().zoom_to_box(box, margin_factor);
7938 m_dirty = true;
7939}

References m_dirty.

Referenced by _render_canvas_toolbar(), zoom_to_bed(), zoom_to_gcode(), zoom_to_plate(), zoom_to_selection(), and zoom_to_volumes().

Here is the caller graph for this function:

◆ adaptive_layer_height_profile()

void Slic3r::GUI::GLCanvas3D::adaptive_layer_height_profile ( float quality_factor)
2277{
2278 wxGetApp().plater()->take_snapshot("Variable layer height - Adaptive");
2279 m_layers_editing.adaptive_layer_height_profile(*this, quality_factor);
2281 m_dirty = true;
2282}
@ Completed
Definition GLCanvas3D.hpp:254

References Slic3r::GUI::GLCanvas3D::LayersEditing::Completed, m_dirty, and m_layers_editing.

◆ add_raycaster_for_picking()

std::shared_ptr< SceneRaycasterItem > Slic3r::GUI::GLCanvas3D::add_raycaster_for_picking ( SceneRaycaster::EType type,
int id,
const MeshRaycaster & raycaster,
const Transform3d & trafo = Transform3d::Identity(),
bool use_back_faces = false )
inline
962 {
963 return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo, use_back_faces);
964 }

References m_scene_raycaster.

Referenced by Slic3r::GUI::register_model_for_picking(), reload_scene(), and Slic3r::GUI::GLGizmoBase::Grabber::render().

Here is the caller graph for this function:

◆ align_section_view_to_camera()

void Slic3r::GUI::GLCanvas3D::align_section_view_to_camera ( )
2010{
2011 m_section_view->normal = -wxGetApp().plater()->get_camera().get_dir_forward();
2013}
void _on_section_view_changed()
Definition GLCanvas3D.cpp:2015

References _on_section_view_changed(), and m_section_view.

Referenced by _render_canvas_toolbar(), _render_section_view_panel(), and set_section_view_ratio().

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

◆ allow_multisample()

void Slic3r::GUI::GLCanvas3D::allow_multisample ( bool allow)
inline
1124{ m_multisample_allowed = allow; }

References m_multisample_allowed.

◆ apply_retina_scale()

void Slic3r::GUI::GLCanvas3D::apply_retina_scale ( Vec2d & screen_coordinate) const
6536{
6537#if ENABLE_RETINA_GL
6538 double scale = static_cast<double>(m_retina_helper->get_scale_factor());
6539 screen_coordinate *= scale;
6540#endif // ENABLE_RETINA_GL
6541}

References scale().

Referenced by on_gesture(), Slic3r::GUI::PlaterDropTarget::OnDropFiles(), and Slic3r::GUI::Plater::priv::show_right_click_menu().

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

◆ apply_selection_move()

void Slic3r::GUI::GLCanvas3D::apply_selection_move ( bool slow,
bool camera_space )
4302{
4303 m_selection.setup_cache();
4304 const double multiplier = slow ? 1.0 : 10.0;
4305
4306 Vec3d displacement;
4307 if (camera_space) {
4308 Eigen::Matrix<double, 3, 3, Eigen::DontAlign> inv_view_3x3 = wxGetApp().plater()->get_camera().get_view_matrix().inverse().matrix().block(0, 0, 3, 3);
4309 displacement = multiplier * (inv_view_3x3 * m_selection_edit.direction);
4310 displacement.z() = 0.0;
4311 }
4312 else
4313 displacement = multiplier * m_selection_edit.direction;
4314
4315 TransformationType trafo_type;
4316 trafo_type.set_relative();
4317 m_selection.translate(displacement, trafo_type);
4318 m_dirty = true;
4319}
SelectionEdit m_selection_edit
Definition GLCanvas3D.hpp:774

References m_dirty, m_selection, m_selection_edit, and Slic3r::GUI::TransformationType::set_relative().

Referenced by handle_shortcut(), and on_key().

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

◆ apply_selection_rotate()

void Slic3r::GUI::GLCanvas3D::apply_selection_rotate ( double angle_z_rad)
4322{
4323 m_selection.setup_cache();
4324 m_selection.rotate(angle_z_rad * m_selection_edit.direction, TransformationType(TransformationType::World_Relative_Joint));
4325 m_dirty = true;
4326}
@ World_Relative_Joint
Definition GUI_Geometry.hpp:33

References m_dirty, m_selection, m_selection_edit, and Slic3r::GUI::TransformationType::World_Relative_Joint.

Referenced by handle_shortcut().

Here is the caller graph for this function:

◆ are_labels_shown()

bool Slic3r::GUI::GLCanvas3D::are_labels_shown ( ) const
inline
1402{ return m_labels.is_shown(); }

References m_labels.

◆ bed_shape_changed()

void Slic3r::GUI::GLCanvas3D::bed_shape_changed ( )
2182{
2184 wxGetApp().plater()->get_camera().requires_zoom_to_bed = true;
2185 m_dirty = true;
2186}
void refresh_camera_scene_box()
Definition GLCanvas3D.cpp:2204

References m_dirty, and refresh_camera_scene_box().

Here is the call graph for this function:

◆ bind_event_handlers()

void Slic3r::GUI::GLCanvas3D::bind_event_handlers ( )
3879{
3880 if (m_canvas != nullptr) {
3881 m_canvas->Bind(wxEVT_SIZE, &GLCanvas3D::on_size, this);
3882 m_canvas->Bind(wxEVT_IDLE, &GLCanvas3D::on_idle, this);
3883 m_canvas->Bind(wxEVT_CHAR, &GLCanvas3D::on_char, this);
3884 m_canvas->Bind(wxEVT_KEY_DOWN, &GLCanvas3D::on_key, this);
3885 m_canvas->Bind(wxEVT_KEY_UP, &GLCanvas3D::on_key, this);
3886 m_canvas->Bind(wxEVT_MOUSEWHEEL, &GLCanvas3D::on_mouse_wheel, this);
3887 m_canvas->Bind(wxEVT_TIMER, &GLCanvas3D::on_timer, this);
3888 m_canvas->Bind(EVT_GLCANVAS_RENDER_TIMER, &GLCanvas3D::on_render_timer, this);
3889 m_toolbar_highlighter.set_timer_owner(m_canvas, 0);
3890 m_canvas->Bind(EVT_GLCANVAS_TOOLBAR_HIGHLIGHTER_TIMER, [this](wxTimerEvent&) { m_toolbar_highlighter.blink(); });
3891 m_gizmo_highlighter.set_timer_owner(m_canvas, 0);
3892 m_canvas->Bind(EVT_GLCANVAS_GIZMO_HIGHLIGHTER_TIMER, [this](wxTimerEvent&) { m_gizmo_highlighter.blink(); });
3893 m_canvas->Bind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this);
3894 m_canvas->Bind(wxEVT_LEFT_UP, &GLCanvas3D::on_mouse, this);
3895 m_canvas->Bind(wxEVT_MIDDLE_DOWN, &GLCanvas3D::on_mouse, this);
3896 m_canvas->Bind(wxEVT_MIDDLE_UP, &GLCanvas3D::on_mouse, this);
3897 m_canvas->Bind(wxEVT_RIGHT_DOWN, &GLCanvas3D::on_mouse, this);
3898 m_canvas->Bind(wxEVT_RIGHT_UP, &GLCanvas3D::on_mouse, this);
3899 m_canvas->Bind(wxEVT_MOTION, &GLCanvas3D::on_mouse, this);
3900 m_canvas->Bind(wxEVT_ENTER_WINDOW, &GLCanvas3D::on_mouse, this);
3901 m_canvas->Bind(wxEVT_LEAVE_WINDOW, &GLCanvas3D::on_mouse, this);
3902 m_canvas->Bind(wxEVT_LEFT_DCLICK, &GLCanvas3D::on_mouse, this);
3903 m_canvas->Bind(wxEVT_MIDDLE_DCLICK, &GLCanvas3D::on_mouse, this);
3904 m_canvas->Bind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
3905 m_canvas->Bind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
3906 m_canvas->Bind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
3907 m_canvas->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& evt) {
3908 // The key-up that would commit a keyboard edit goes to whatever took the focus.
3912 wxGetApp().imgui()->forget_key_claims();
3913#ifdef __APPLE__
3914 // ImGuiWrapper stops updating the view once it is no longer the IME target.
3915 if (ImGui::GetIO().ImeWindowHandle == m_canvas->GetHandle()) {
3916 mac_ime_set_active(m_canvas->GetHandle(), false);
3917 ImGui::GetIO().ImeWindowHandle = nullptr;
3918 }
3919#endif
3920 ImGui::SetWindowFocus(nullptr);
3921 render();
3922 evt.Skip();
3923 });
3924 // ORCA If the mouse capture is lost while a button is held (Alt+Tab, dialog, lock screen), the button-up
3925 // never arrives and ImGui keeps the widget active. Cancel the interaction: clear the active widget
3926 // before releasing the buttons so the release is not taken as a click.
3927 m_canvas->Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) {
3928 if (GImGui != nullptr) {
3929 ImGui::ClearActiveID();
3930 ImGuiIO& io = ImGui::GetIO();
3931 for (bool& down : io.MouseDown)
3932 down = false;
3933 }
3934 m_navigator_dragging = false;
3935 render();
3936 });
3938
3939 m_canvas->Bind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
3940 m_canvas->Bind(wxEVT_GESTURE_ZOOM, &GLCanvas3D::on_gesture, this);
3941 m_canvas->Bind(wxEVT_GESTURE_ROTATE, &GLCanvas3D::on_gesture, this);
3942 m_canvas->EnableTouchEvents(wxTOUCH_ZOOM_GESTURE | wxTOUCH_ROTATE_GESTURE);
3943#if __WXOSX__
3944 initGestures(m_canvas->GetHandle(), m_canvas); // for UIPanGestureRecognizer allowedScrollTypesMask
3945#endif
3946 }
3947}
void on_mouse(wxMouseEvent &evt)
Definition GLCanvas3D.cpp:4731
void on_idle(wxIdleEvent &evt)
Definition GLCanvas3D.cpp:3985
void on_paint(wxPaintEvent &evt)
Definition GLCanvas3D.cpp:5523
void on_timer(wxTimerEvent &evt)
Definition GLCanvas3D.cpp:4575
void release_held_modifiers()
Definition GLCanvas3D.cpp:4358
void on_mouse_wheel(wxMouseEvent &evt)
Definition GLCanvas3D.cpp:4473
void on_char(wxKeyEvent &evt)
Definition GLCanvas3D.cpp:4058
bool m_event_handlers_bound
Definition GLCanvas3D.hpp:728
void on_key(wxKeyEvent &evt)
Definition GLCanvas3D.cpp:4369
void render(bool only_init=false)
Definition GLCanvas3D.cpp:2481
void on_set_focus(wxFocusEvent &evt)
Definition GLCanvas3D.cpp:5545
void on_render_timer(wxTimerEvent &evt)
Definition GLCanvas3D.cpp:4581
void on_size(wxSizeEvent &evt)
Definition GLCanvas3D.hpp:1274
void on_gesture(wxGestureEvent &evt)
Definition GLCanvas3D.cpp:4685
void finish_selection_edit()
Definition GLCanvas3D.cpp:4328
void mac_ime_set_active(void *ns_view, bool active)
Definition MacIME.mm:154
void initGestures(void *view, wxEvtHandler *handler)
Definition MacDarkMode.mm:468
@ down
Definition MarchingSquares.hpp:189
@ None
Definition GLCanvas3D.hpp:769

References finish_selection_edit(), Slic3r::GUI::initGestures(), m_canvas, m_event_handlers_bound, m_gizmo_highlighter, m_navigator_dragging, m_selection_edit, m_toolbar_highlighter, Slic3r::GUI::mac_ime_set_active(), Slic3r::GUI::GLCanvas3D::SelectionEdit::None, on_char(), on_gesture(), on_idle(), on_key(), on_mouse(), on_mouse_wheel(), on_paint(), on_render_timer(), on_set_focus(), on_size(), on_timer(), release_held_modifiers(), and render().

Here is the call graph for this function:

◆ can_sequential_clearance_show_in_gizmo()

bool Slic3r::GUI::GLCanvas3D::can_sequential_clearance_show_in_gizmo ( )
6297 {
6298 switch (m_gizmos.get_current_type()) {
6302 return true;
6303 }
6304 }
6305 return false;
6306}
@ Move
Definition GLGizmosManager.hpp:88
@ Scale
Definition GLGizmosManager.hpp:90
@ Rotate
Definition GLGizmosManager.hpp:89

References m_gizmos, Slic3r::GUI::GLGizmosManager::Move, Slic3r::GUI::GLGizmosManager::Rotate, and Slic3r::GUI::GLGizmosManager::Scale.

Referenced by _render_sequential_clearance(), and on_mouse().

Here is the caller graph for this function:

◆ check_volumes_outside_state() [1/3]

void Slic3r::GUI::GLCanvas3D::check_volumes_outside_state ( GLVolumeCollection & volumes) const
inline
996{ check_volumes_outside_state(volumes, nullptr, false); }

References check_volumes_outside_state().

Referenced by check_volumes_outside_state().

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

◆ check_volumes_outside_state() [2/3]

bool Slic3r::GUI::GLCanvas3D::check_volumes_outside_state ( GLVolumeCollection & volumes,
ModelInstanceEPrintVolumeState * out_state,
bool selection_only = true ) const
private

◆ check_volumes_outside_state() [3/3]

ModelInstanceEPrintVolumeState Slic3r::GUI::GLCanvas3D::check_volumes_outside_state ( ObjectFilamentResults * object_results = nullptr) const
1972{
1973 //BBS: if not initialized, return inside directly insteadof assert
1974 if (!m_initialized) {
1976 }
1977 //assert(m_initialized);
1978
1980 m_volumes.check_outside_state(m_bed.build_volume(), &state, object_results);
1981
1984 return state;
1985}
static std::pair< bool, bool > construct_extruder_unprintable_error(ObjectFilamentResults &object_result, std::string &left_extruder_unprintable_text, std::string &right_extruder_unprintable_text)
Definition GLCanvas3D.cpp:1876
static bool construct_error_string(ObjectFilamentResults &object_result, std::string &error_string)
Definition GLCanvas3D.cpp:1860
ModelInstanceEPrintVolumeState
Definition Model.hpp:1410
@ ModelInstancePVS_Inside
Definition Model.hpp:1411

References Slic3r::GUI::construct_error_string(), Slic3r::GUI::construct_extruder_unprintable_error(), Slic3r::GUI::get_left_extruder_unprintable_text(), Slic3r::GUI::get_object_clashed_text(), Slic3r::GUI::get_right_extruder_unprintable_text(), m_bed, m_initialized, m_volumes, and Slic3r::ModelInstancePVS_Inside.

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

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

◆ clear_popup_menu_position()

void Slic3r::GUI::GLCanvas3D::clear_popup_menu_position ( )
inline
1311{ m_popup_menu_positon.reset(); }
std::optional< Vec2d > m_popup_menu_positon
Definition GLCanvas3D.hpp:1308

References m_popup_menu_positon.

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

Here is the caller graph for this function:

◆ clicked_button_matches_action()

bool Slic3r::GUI::GLCanvas3D::clicked_button_matches_action ( const wxMouseEvent & evt,
MouseAction action,
const std::map< MouseButton, MouseAction > & mappings ) const
5558{
5560 if (evt.LeftIsDown()) {
5561 clicked = MouseButton::Left;
5562 }
5563 if (evt.MiddleIsDown()) {
5564 clicked = MouseButton::Middle;
5565 }
5566 if (evt.RightIsDown()) {
5567 clicked = MouseButton::Right;
5568 }
5569
5570 auto it = mappings.find(clicked);
5571 if (it == mappings.end()) {
5572 return false;
5573 }
5574 return it->second == action;
5575}
MouseButton
Definition GLCanvas3D.hpp:1298
@ None
Definition GLCanvas3D.hpp:1298
@ Right
Definition GLCanvas3D.hpp:1298
@ Left
Definition GLCanvas3D.hpp:1298
@ Middle
Definition GLCanvas3D.hpp:1298

References Left, Middle, None, Right, and Slic3r::GUI::wxMouseEvent.

Referenced by is_camera_pan(), and is_camera_rotate().

Here is the caller graph for this function:

◆ collapse_side()

CollapseSide Slic3r::GUI::GLCanvas3D::collapse_side ( ) const
private
2466{
2467 if (m_collapse_side)
2468 return m_collapse_side();
2469 switch (wxGetApp().plater()->get_sidebar_docking_state()) {
2470 case Sidebar::Left: return CollapseSide::Left;
2472 default: return CollapseSide::None;
2473 }
2474}
std::function< CollapseSide()> m_collapse_side
Definition GLCanvas3D.hpp:675
@ Right
Definition Plater.hpp:175
@ Left
Definition Plater.hpp:175

References Slic3r::GUI::Left, Slic3r::GUI::Sidebar::Left, m_collapse_side, Slic3r::GUI::None, Slic3r::GUI::plater(), Slic3r::GUI::Right, and Slic3r::GUI::Sidebar::Right.

Referenced by _check_and_update_toolbar_icon_scale(), _render_collapse_toolbar(), get_collapse_toolbar_height(), get_collapse_toolbar_width(), and is_collapse_toolbar_on_left().

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

◆ collapse_toolbar()

GLToolbar & Slic3r::GUI::GLCanvas3D::collapse_toolbar ( ) const
private
2461{
2462 return m_collapse_toolbar != nullptr ? *m_collapse_toolbar : wxGetApp().plater()->get_collapse_toolbar();
2463}

References m_collapse_toolbar.

Referenced by _check_and_update_toolbar_icon_scale(), _deactivate_collapse_toolbar_items(), _overlay_signature(), _render_collapse_toolbar(), _render_frame(), _switch_toolbars_icon_filename(), get_collapse_toolbar_height(), get_collapse_toolbar_width(), on_change_color_mode(), on_idle(), and on_mouse().

Here is the caller graph for this function:

◆ current_printer_technology()

PrinterTechnology Slic3r::GUI::GLCanvas3D::current_printer_technology ( ) const
private
1590 {
1591 return m_process->current_printer_technology();
1592}

References current_printer_technology(), and m_process.

Referenced by _init_main_toolbar(), _render_arrange_menu(), _render_background(), _render_orient_menu(), _render_sla_slices(), _set_warning_notification_if_needed(), current_printer_technology(), do_move(), get_arrange_settings(), get_orient_settings(), on_gesture(), on_mouse(), reload_scene(), toggle_sla_auxiliaries_visibility(), update_compacted_wipe_tower_clearance(), and update_sequential_clearance().

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

◆ delete_selected()

void Slic3r::GUI::GLCanvas3D::delete_selected ( )
inline
1242{ m_selection.erase(); }

References m_selection.

◆ deselect_all()

void Slic3r::GUI::GLCanvas3D::deselect_all ( )
3056{
3057 m_selection.remove_all();
3058 // BBS
3059 //wxGetApp().obj_manipul()->set_dirty();
3060 m_gizmos.reset_all_states();
3061 m_gizmos.update_data();
3062 post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
3063}

References m_gizmos, m_selection, and post_event().

Referenced by on_char(), and on_mouse().

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

◆ do_center()

void Slic3r::GUI::GLCanvas3D::do_center ( )
5980{
5981 if (m_model == nullptr)
5982 return;
5983
5984 m_selection.center();
5985}

References m_model, and m_selection.

◆ do_center_plate()

void Slic3r::GUI::GLCanvas3D::do_center_plate ( const int plate_idx)
5995 {
5996 if (m_model == nullptr)
5997 return;
5998
5999 m_selection.center_plate(plate_idx);
6000}

References m_model, and m_selection.

◆ do_drop()

void Slic3r::GUI::GLCanvas3D::do_drop ( )
5988{
5989 if (m_model == nullptr)
5990 return;
5991
5992 m_selection.drop();
5993}

References m_model, and m_selection.

◆ do_mirror()

void Slic3r::GUI::GLCanvas3D::do_mirror ( const std::string & snapshot_type)
6003{
6004 if (m_model == nullptr)
6005 return;
6006
6007 if (!snapshot_type.empty())
6008 wxGetApp().plater()->take_snapshot(snapshot_type);
6009
6010 // stores current min_z of instances
6011 std::map<std::pair<int, int>, double> min_zs;
6012 if (!snapshot_type.empty()) {
6013 for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
6014 const ModelObject* obj = m_model->objects[i];
6015 for (int j = 0; j < static_cast<int>(obj->instances.size()); ++j) {
6016 min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z();
6017 }
6018 }
6019 }
6020
6021 std::set<std::pair<int, int>> done; // keeps track of modified instances
6022
6023 Selection::EMode selection_mode = m_selection.get_mode();
6024
6025 for (const GLVolume* v : m_volumes.volumes) {
6026 int object_idx = v->object_idx();
6027 if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
6028 continue;
6029
6030 int instance_idx = v->instance_idx();
6031 int volume_idx = v->volume_idx();
6032
6033 done.insert(std::pair<int, int>(object_idx, instance_idx));
6034
6035 // Mirror instances/volumes
6036 ModelObject* model_object = m_model->objects[object_idx];
6037 if (model_object == nullptr)
6038 continue;
6039
6040 if (selection_mode == Selection::Instance)
6041 model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
6042 else if (selection_mode == Selection::Volume) {
6043 if (model_object->volumes[volume_idx]->get_transformation() != v->get_volume_transformation()) {
6044 model_object->volumes[volume_idx]->set_transformation(v->get_volume_transformation());
6045 // BBS: backup
6046 Slic3r::save_object_mesh(*model_object);
6047 }
6048 }
6049
6050 model_object->invalidate_bounding_box();
6051 }
6052
6053 //BBS: notify instance updates to part plater list
6054 m_selection.notify_instance_update(-1, -1);
6055
6056 // Fixes sinking/flying instances (snaps object to buildplate)
6057 for (const std::pair<int, int>& i : done) {
6058 ModelObject* mo = m_model->objects[i.first];
6059
6060 //BBS: don't call translate if the z is zero
6061 double shift_z = mo->get_instance_min_z(i.second);
6062 // leave sinking instances as sinking
6063 if (mo->auto_drop && (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
6064 Vec3d shift(0.0, 0.0, -shift_z);
6065 m_selection.translate(i.first, i.second, shift);
6066 mo->translate_instance(i.second, shift);
6067 //BBS: notify instance updates to part plater list
6068 m_selection.notify_instance_update(i.first, i.second);
6069 }
6070 wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
6071
6072 //BBS: notify instance updates to part plater list
6073 PartPlateList &plate_list = wxGetApp().plater()->get_partplate_list();
6074 plate_list.notify_instance_update(i.first, i.second);
6075 }
6076
6077 //BBS: nofity object list to update
6078 wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
6079
6080 post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
6081
6082 // IMEX: mirror changes per-instance transforms without touching the ghost cache key.
6083 wxGetApp().plater()->get_partplate_list().invalidate_all_imex_ghosts();
6084
6085 m_dirty = true;
6086}
EMode
Definition Selection.hpp:52
void save_object_mesh(ModelObject &object)
Definition bbs_3mf.cpp:9754

References Slic3r::ModelObject::auto_drop, Slic3r::ModelObject::get_instance_min_z(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::GLVolume::get_volume_transformation(), Slic3r::GUI::Selection::Instance, Slic3r::ModelObject::instance_bounding_box(), Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::ModelObject::invalidate_bounding_box(), m_dirty, m_model, m_selection, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GUI::PartPlateList::notify_instance_update(), Slic3r::GLVolume::object_idx(), post_event(), Slic3r::save_object_mesh(), Slic3r::SINKING_Z_THRESHOLD, Slic3r::ModelObject::translate_instance(), Slic3r::GUI::Selection::Volume, Slic3r::GLVolume::volume_idx(), and Slic3r::ModelObject::volumes.

Referenced by mirror_selection().

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

◆ do_move()

void Slic3r::GUI::GLCanvas3D::do_move ( const std::string & snapshot_type,
bool force_volume_move = false )
5636{
5637 if (m_model == nullptr)
5638 return;
5639
5640 if (!snapshot_type.empty())
5641 wxGetApp().plater()->take_snapshot(snapshot_type);
5642
5643 std::set<std::pair<int, int>> done; // keeps track of modified instances
5644 bool object_moved = false;
5645
5646 // BBS: support wipe-tower for multi-plates
5647 int n_plates = wxGetApp().plater()->get_partplate_list().get_plate_count();
5648 std::vector<Vec3d> wipe_tower_origins(n_plates, Vec3d::Zero());
5649
5650 Selection::EMode selection_mode = m_selection.get_mode();
5651
5652 for (const GLVolume* v : m_volumes.volumes) {
5653 int object_idx = v->object_idx();
5654 int instance_idx = v->instance_idx();
5655 int volume_idx = v->volume_idx();
5656
5657 if (volume_idx < 0)
5658 continue;
5659
5660 std::pair<int, int> done_id(object_idx, instance_idx);
5661
5662 if (0 <= object_idx && object_idx < (int)m_model->objects.size()) {
5663 done.insert(done_id);
5664
5665 // Move instances/volumes
5666 ModelObject* model_object = m_model->objects[object_idx];
5667 if (model_object == nullptr)
5668 continue;
5669
5670 if (force_volume_move || selection_mode == Selection::Volume) {
5671 auto cur_mv = model_object->volumes[volume_idx];
5672 if (cur_mv->get_transformation() != v->get_volume_transformation()) {
5673 cur_mv->set_transformation(v->get_volume_transformation());
5674 // BBS: backup
5675 Slic3r::save_object_mesh(*model_object);
5676 }
5677 }
5678 else if (selection_mode == Selection::Instance) {
5680 if ((model_object->instances[instance_idx]->get_assemble_offset() - v->get_instance_offset()).norm() > 1e-2) {
5681 model_object->instances[instance_idx]->set_assemble_transformation(v->get_instance_transformation());
5682 }
5683 } else {
5684 model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
5685 }
5686 }
5687
5688 object_moved = true;
5689 model_object->invalidate_bounding_box();
5690
5691 }
5692 else if (object_idx >= 1000 && object_idx < 1000 + n_plates) {
5693 // Move a wipe tower proxy.
5694 wipe_tower_origins[object_idx - 1000] = v->get_volume_offset();
5695 }
5696 }
5697
5698 //BBS: notify instance updates to part plater list
5699 // Only what moved: the selected instances, or every instance of an object one of whose
5700 // parts moved. Notifying a plate about an instance that stayed put invalidates its slice
5701 // result, and notifying instance 0 alone left a moved copy unregistered on its new plate.
5702 {
5703 const bool parts_moved = force_volume_move || selection_mode == Selection::Volume;
5704 std::set<std::pair<int, int>> notified;
5705 for (unsigned int i : m_selection.get_volume_idxs()) {
5706 const GLVolume* v = m_volumes.volumes[i];
5707 const int object_idx = v->object_idx();
5708 if (object_idx < 0 || object_idx >= static_cast<int>(m_model->objects.size()))
5709 continue;
5710 const std::pair<int, int> key(object_idx, parts_moved ? -1 : v->instance_idx());
5711 if (notified.insert(key).second)
5712 m_selection.notify_instance_update(key.first, key.second);
5713 }
5714 }
5715
5716 // Fixes sinking/flying instances (snaps object to buildplate)
5717 for (const std::pair<int, int>& i : done) {
5718 ModelObject* mo = m_model->objects[i.first];
5719
5720 const double shift_z = mo->get_instance_min_z(i.second);
5721 //BBS: don't call translate if the z is zero
5722 if (mo->auto_drop && (current_printer_technology() == ptSLA || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
5723 const Vec3d shift(0.0, 0.0, -shift_z);
5724 m_selection.translate(i.first, i.second, shift);
5725 mo->translate_instance(i.second, shift);
5726 //BBS: notify instance updates to part plater list
5727 m_selection.notify_instance_update(i.first, i.second);
5728 }
5729 wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
5730 }
5731
5732 //BBS: nofity object list to update
5733 wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
5734
5735 if (object_moved) {
5736 Slic3r::LifecycleEventContext ctx;
5738 ctx.msg = "moved";
5739 if (done.size() == 1)
5740 ctx.name = m_model->objects[done.begin()->first]->name;
5742
5743 post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_MOVED));
5744 }
5745
5746 // BBS: support wipe-tower for multi-plates
5747 for (int plate_id = 0; plate_id < wipe_tower_origins.size(); plate_id++) {
5748 Vec3d& wipe_tower_origin = wipe_tower_origins[plate_id];
5749 if (wipe_tower_origin == Vec3d::Zero())
5750 continue;
5751
5752 PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
5753 DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
5754 Vec3d plate_origin = ppl.get_plate(plate_id)->get_origin();
5755 ConfigOptionFloat wipe_tower_x(wipe_tower_origin(0) - plate_origin(0));
5756 ConfigOptionFloat wipe_tower_y(wipe_tower_origin(1) - plate_origin(1));
5757
5758 ConfigOptionFloats* wipe_tower_x_opt = proj_cfg.option<ConfigOptionFloats>("wipe_tower_x", true);
5759 ConfigOptionFloats* wipe_tower_y_opt = proj_cfg.option<ConfigOptionFloats>("wipe_tower_y", true);
5760 wipe_tower_x_opt->set_at(&wipe_tower_x, plate_id, 0);
5761 wipe_tower_y_opt->set_at(&wipe_tower_y, plate_id, 0);
5762 }
5763
5765
5766 // IMEX: selection commit may have moved/added/removed objects — ghost cache key
5767 // doesn't encode per-instance transforms, so force a full rebuild on next render.
5768 wxGetApp().plater()->get_partplate_list().invalidate_all_imex_ghosts();
5769
5770 m_dirty = true;
5771}
void set_at(const ConfigOption *rhs, size_t i, size_t j) override
Definition Config.hpp:451
void reset_sequential_print_clearance()
Definition GLCanvas3D.hpp:1426
zaa_minimize_perimeter_height ConfigOptionFloat
Definition PrintConfig.hpp:1954
std::string name
Definition LifecycleEvents.hpp:75
std::string msg
Definition LifecycleEvents.hpp:83
@ ObjectTransformed
Definition LifecycleEvents.hpp:38
@ Ok
Definition LifecycleEvents.hpp:68
LifecycleEvtCode code
Definition LifecycleEvents.hpp:79
zaa_minimize_perimeter_height wipe_tower_y((ConfigOptionFloat, prime_tower_width))((ConfigOptionFloat
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:1015
void fire_lifecycle_event(LifecycleEvent event, const LifecycleEventContext &ctx)
Definition LifecycleEvents.hpp:234

References Slic3r::ModelObject::auto_drop, CanvasAssembleView, Slic3r::LifecycleEventContext::code, current_printer_technology(), Slic3r::fire_lifecycle_event(), Slic3r::ModelObject::get_instance_min_z(), Slic3r::GLVolume::get_instance_offset(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::GUI::PartPlate::get_origin(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GLVolume::get_volume_offset(), Slic3r::GLVolume::get_volume_transformation(), Slic3r::GUI::Selection::Instance, Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::ModelObject::invalidate_bounding_box(), m_canvas_type, m_dirty, m_model, m_selection, m_volumes, Slic3r::LifecycleEventContext::msg, Slic3r::LifecycleEventContext::name, Slic3r::GLVolume::object_idx(), Slic3r::ObjectTransformed, Slic3r::Ok, Slic3r::ConfigBase::option(), post_event(), Slic3r::ptSLA, reset_sequential_print_clearance(), Slic3r::save_object_mesh(), Slic3r::ConfigOptionVector< double >::set_at(), Slic3r::SINKING_Z_THRESHOLD, Slic3r::ModelObject::translate_instance(), Slic3r::GUI::Selection::Volume, Slic3r::GLVolume::volume_idx(), Slic3r::ModelObject::volumes, and Slic3r::wipe_tower_y().

Referenced by finish_selection_edit(), anonymous_namespace{GLGizmoEmboss.cpp}::fix_transformation(), on_mouse(), and Slic3r::GUI::on_mouse_surface_drag().

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

◆ do_rotate()

void Slic3r::GUI::GLCanvas3D::do_rotate ( const std::string & snapshot_type)
5774{
5775 if (m_model == nullptr)
5776 return;
5777
5778 if (!snapshot_type.empty())
5779 wxGetApp().plater()->take_snapshot(snapshot_type);
5780
5781 // stores current min_z of instances
5782 std::map<std::pair<int, int>, double> min_zs;
5783 for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
5784 const ModelObject* obj = m_model->objects[i];
5785 for (int j = 0; j < static_cast<int>(obj->instances.size()); ++j) {
5786 if (snapshot_type == L("Gizmo-Place on Face") && m_selection.get_object_idx() == i) {
5787 // This means we are flattening this object. In that case pretend
5788 // that it is not sinking (even if it is), so it is placed on bed
5789 // later on (whatever is sinking will be left sinking).
5790 min_zs[{ i, j }] = SINKING_Z_THRESHOLD;
5791 }
5792 else
5793 min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z();
5794
5795 }
5796 }
5797
5798 std::set<std::pair<int, int>> done; // keeps track of modified instances
5799
5800 Selection::EMode selection_mode = m_selection.get_mode();
5801
5802 for (const GLVolume* v : m_volumes.volumes) {
5803 const int object_idx = v->object_idx();
5804 if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
5805 continue;
5806
5807 const int instance_idx = v->instance_idx();
5808 const int volume_idx = v->volume_idx();
5809
5810 if (volume_idx < 0)
5811 continue;
5812
5813 done.insert(std::pair<int, int>(object_idx, instance_idx));
5814
5815 // Rotate instances/volumes.
5816 ModelObject* model_object = m_model->objects[object_idx];
5817 if (model_object == nullptr)
5818 continue;
5819
5820 if (selection_mode == Selection::Instance) {
5822 model_object->instances[instance_idx]->set_assemble_from_transform(v->get_instance_transformation().get_matrix());
5823 } else {
5824 model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
5825 }
5826 }
5827 else if (selection_mode == Selection::Volume) {
5828 auto cur_mv = model_object->volumes[volume_idx];
5829 if (cur_mv->get_transformation() != v->get_volume_transformation()) {
5830 cur_mv->set_transformation(v->get_volume_transformation());
5831 // BBS: backup
5832 Slic3r::save_object_mesh(*model_object);
5833 }
5834 }
5835 model_object->invalidate_bounding_box();
5836 }
5837
5838 //BBS: notify instance updates to part plater list
5839 m_selection.notify_instance_update(-1, -1);
5840
5842 // Fixes sinking/flying instances (snaps object to buildplate)
5843 for (const std::pair<int, int> &i : done) {
5844 ModelObject *mo = m_model->objects[i.first];
5845
5846 // BBS: don't call translate if the z is zero
5847 const double shift_z = mo->get_instance_min_z(i.second);
5848 // leave sinking instances as sinking
5849 if (mo->auto_drop && (min_zs.find({i.first, i.second})->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
5850 const Vec3d shift(0.0, 0.0, -shift_z);
5851 m_selection.translate(i.first, i.second, shift);
5852 mo->translate_instance(i.second, shift);
5853 // BBS: notify instance updates to part plater list
5854 m_selection.notify_instance_update(i.first, i.second);
5855 }
5856
5857 wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
5858 }
5859 }
5860
5861 //BBS: nofity object list to update
5862 wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
5863
5864 if (!done.empty()) {
5865 Slic3r::LifecycleEventContext ctx;
5867 ctx.msg = "rotated";
5868 if (done.size() == 1)
5869 ctx.name = m_model->objects[done.begin()->first]->name;
5871
5872 post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
5873 }
5874
5875 // IMEX: rotate changes per-instance transforms without touching the ghost cache key.
5876 wxGetApp().plater()->get_partplate_list().invalidate_all_imex_ghosts();
5877
5878 m_dirty = true;
5879}

References Slic3r::ModelObject::auto_drop, CanvasAssembleView, Slic3r::LifecycleEventContext::code, Slic3r::fire_lifecycle_event(), Slic3r::ModelObject::get_instance_min_z(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::GLVolume::get_volume_transformation(), Slic3r::GUI::Selection::Instance, Slic3r::ModelObject::instance_bounding_box(), Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::ModelObject::invalidate_bounding_box(), L, m_canvas_type, m_dirty, m_model, m_selection, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::LifecycleEventContext::msg, Slic3r::LifecycleEventContext::name, Slic3r::GLVolume::object_idx(), Slic3r::ObjectTransformed, Slic3r::Ok, post_event(), Slic3r::save_object_mesh(), Slic3r::SINKING_Z_THRESHOLD, Slic3r::ModelObject::translate_instance(), Slic3r::GUI::Selection::Volume, Slic3r::GLVolume::volume_idx(), and Slic3r::ModelObject::volumes.

Referenced by Slic3r::GUI::face_selected_volume_to_camera(), finish_selection_edit(), and anonymous_namespace{GLGizmoEmboss.cpp}::fix_transformation().

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

◆ do_scale()

void Slic3r::GUI::GLCanvas3D::do_scale ( const std::string & snapshot_type)
5882{
5883 if (m_model == nullptr)
5884 return;
5885
5886 if (!snapshot_type.empty())
5887 wxGetApp().plater()->take_snapshot(snapshot_type);
5888
5889 // stores current min_z of instances
5890 std::map<std::pair<int, int>, double> min_zs;
5891 if (!snapshot_type.empty()) {
5892 for (int i = 0; i < static_cast<int>(m_model->objects.size()); ++i) {
5893 const ModelObject* obj = m_model->objects[i];
5894 for (int j = 0; j < static_cast<int>(obj->instances.size()); ++j) {
5895 min_zs[{ i, j }] = obj->instance_bounding_box(j).min.z();
5896 }
5897 }
5898 }
5899
5900 std::set<std::pair<int, int>> done; // keeps track of modified instances
5901
5902 Selection::EMode selection_mode = m_selection.get_mode();
5903
5904 for (const GLVolume* v : m_volumes.volumes) {
5905 const int object_idx = v->object_idx();
5906 if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
5907 continue;
5908
5909 const int instance_idx = v->instance_idx();
5910 const int volume_idx = v->volume_idx();
5911
5912 if (volume_idx < 0)
5913 continue;
5914
5915 done.insert(std::pair<int, int>(object_idx, instance_idx));
5916
5917 // Rotate instances/volumes
5918 ModelObject* model_object = m_model->objects[object_idx];
5919 if (model_object == nullptr)
5920 continue;
5921
5922 if (selection_mode == Selection::Instance) {
5923 model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
5924 }
5925 else if (selection_mode == Selection::Volume) {
5926 auto cur_mv = model_object->volumes[volume_idx];
5927 if (cur_mv->get_transformation() != v->get_volume_transformation()) {
5928 model_object->instances[instance_idx]->set_transformation(v->get_instance_transformation());
5929 cur_mv->set_transformation(v->get_volume_transformation());
5930 // BBS: backup
5931 Slic3r::save_object_mesh(*model_object);
5932 }
5933 }
5934 model_object->invalidate_bounding_box();
5935 }
5936
5937 //BBS: notify instance updates to part plater list
5938 m_selection.notify_instance_update(-1, -1);
5939
5940 // Fixes sinking/flying instances (snaps object to buildplate)
5941 for (const std::pair<int, int>& i : done) {
5942 ModelObject* mo = m_model->objects[i.first];
5943
5944 //BBS: don't call translate if the z is zero
5945 double shift_z = mo->get_instance_min_z(i.second);
5946 // leave sinking instances as sinking
5947 if (mo->auto_drop && (min_zs.empty() || min_zs.find({ i.first, i.second })->second >= SINKING_Z_THRESHOLD || shift_z > SINKING_Z_THRESHOLD) && (shift_z != 0.0f)) {
5948 Vec3d shift(0.0, 0.0, -shift_z);
5949 m_selection.translate(i.first, i.second, shift);
5950 mo->translate_instance(i.second, shift);
5951 //BBS: notify instance updates to part plater list
5952 m_selection.notify_instance_update(i.first, i.second);
5953 }
5954 wxGetApp().obj_list()->update_info_items(static_cast<size_t>(i.first));
5955 }
5956
5957 //BBS: nofity object list to update
5958 wxGetApp().plater()->sidebar().obj_list()->update_plate_values_for_items();
5959 //BBS: notify object info update
5960 wxGetApp().plater()->show_object_info();
5961
5962 if (!done.empty()) {
5963 Slic3r::LifecycleEventContext ctx;
5965 ctx.msg = "scaled";
5966 if (done.size() == 1)
5967 ctx.name = m_model->objects[done.begin()->first]->name;
5969
5970 post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_SCALED));
5971 }
5972
5973 // IMEX: scale changes per-instance transforms without touching the ghost cache key.
5974 wxGetApp().plater()->get_partplate_list().invalidate_all_imex_ghosts();
5975
5976 m_dirty = true;
5977}

References Slic3r::ModelObject::auto_drop, Slic3r::LifecycleEventContext::code, Slic3r::fire_lifecycle_event(), Slic3r::ModelObject::get_instance_min_z(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::GLVolume::get_volume_transformation(), Slic3r::GUI::Selection::Instance, Slic3r::ModelObject::instance_bounding_box(), Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::ModelObject::invalidate_bounding_box(), m_dirty, m_model, m_selection, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::LifecycleEventContext::msg, Slic3r::LifecycleEventContext::name, Slic3r::GLVolume::object_idx(), Slic3r::ObjectTransformed, Slic3r::Ok, post_event(), Slic3r::save_object_mesh(), Slic3r::SINKING_Z_THRESHOLD, Slic3r::ModelObject::translate_instance(), Slic3r::GUI::Selection::Volume, Slic3r::GLVolume::volume_idx(), and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ enable_assemble_view_toolbar()

void Slic3r::GUI::GLCanvas3D::enable_assemble_view_toolbar ( bool enable)
2311{
2312 m_assemble_view_toolbar.set_enabled(enable);
2313}

References m_assemble_view_toolbar.

◆ enable_collapse_toolbar()

void Slic3r::GUI::GLCanvas3D::enable_collapse_toolbar ( bool enable)
2326{
2328}

References m_collapse_toolbar_enabled.

◆ enable_dynamic_background()

void Slic3r::GUI::GLCanvas3D::enable_dynamic_background ( bool enable)
inline

◆ enable_gizmos()

void Slic3r::GUI::GLCanvas3D::enable_gizmos ( bool enable)
inline
1095{ m_gizmos.set_enabled(enable); }

References m_gizmos.

◆ enable_labels()

void Slic3r::GUI::GLCanvas3D::enable_labels ( bool enable)
inline
1122{ m_labels.enable(enable); }

References m_labels.

◆ enable_layers_editing()

void Slic3r::GUI::GLCanvas3D::enable_layers_editing ( bool enable)
2293{
2294 m_layers_editing.set_enabled(enable);
2295 set_as_dirty();
2296}

References m_layers_editing, and set_as_dirty().

Here is the call graph for this function:

◆ enable_main_toolbar()

void Slic3r::GUI::GLCanvas3D::enable_main_toolbar ( bool enable)
inline
1097{ m_main_toolbar.set_enabled(enable); }

References m_main_toolbar.

◆ enable_moving()

void Slic3r::GUI::GLCanvas3D::enable_moving ( bool enable)
inline
1094{ m_moving_enabled = enable; }

References m_moving_enabled.

Referenced by Slic3r::GUI::on_mouse_surface_drag(), and anonymous_namespace{SurfaceDrag.cpp}::start_dragging().

Here is the caller graph for this function:

◆ enable_picking()

void Slic3r::GUI::GLCanvas3D::enable_picking ( bool enable)
inline
1087 {
1088 m_picking_enabled = enable;
1089 // Orca: invalidate hover state when dragging is toggled, otherwise if we turned off dragging
1090 // while hovering above a volume, the hovering state won't update even if mouse has moved away.
1091 // Fixes https://github.com/OrcaSlicer/OrcaSlicer/pull/9979#issuecomment-3065575889
1092 m_hover_volume_idxs.clear();
1093 }

References m_hover_volume_idxs, and m_picking_enabled.

Referenced by Slic3r::GUI::on_mouse_surface_drag(), and anonymous_namespace{SurfaceDrag.cpp}::start_dragging().

Here is the caller graph for this function:

◆ enable_plate_chrome()

void Slic3r::GUI::GLCanvas3D::enable_plate_chrome ( bool enable)
2337{
2338 m_plate_chrome_enabled = enable;
2339}

References m_plate_chrome_enabled.

◆ enable_render()

void Slic3r::GUI::GLCanvas3D::enable_render ( bool enabled)
inline
1162 {
1163 m_enable_render = enabled;
1164 }

References m_enable_render.

◆ enable_return_toolbar()

void Slic3r::GUI::GLCanvas3D::enable_return_toolbar ( bool enable)
2316{
2317 m_return_toolbar.set_enabled(enable);
2318}

References m_return_toolbar.

Referenced by _render_frame().

Here is the caller graph for this function:

◆ enable_select_plate_toolbar()

void Slic3r::GUI::GLCanvas3D::enable_select_plate_toolbar ( bool enable)
2306{
2307 m_sel_plate_toolbar.set_enabled(enable);
2308}

References m_sel_plate_toolbar.

◆ enable_selection()

void Slic3r::GUI::GLCanvas3D::enable_selection ( bool enable)
inline
1096{ m_selection.set_enabled(enable); }

References m_selection.

◆ enable_separator_toolbar()

void Slic3r::GUI::GLCanvas3D::enable_separator_toolbar ( bool enable)
2321{
2322 m_separator_toolbar.set_enabled(enable);
2323}

References m_separator_toolbar.

◆ enable_sinking_contours()

void Slic3r::GUI::GLCanvas3D::enable_sinking_contours ( bool enable)
inline

◆ enable_slope()

void Slic3r::GUI::GLCanvas3D::enable_slope ( bool enable)
inline
1123{ m_slope.enable(enable); }

References m_slope.

◆ ensure_on_bed()

void Slic3r::GUI::GLCanvas3D::ensure_on_bed ( unsigned int object_idx,
bool allow_negative_z )
3084{
3085 //BBS if asseble view canvas
3087 return;
3088 }
3089
3090 if (allow_negative_z)
3091 return;
3092
3093 typedef std::map<std::pair<int, int>, double> InstancesToZMap;
3094 InstancesToZMap instances_min_z;
3095
3096 for (GLVolume* volume : m_volumes.volumes) {
3097 ModelObject* mo = m_model->objects[volume->object_idx()];
3098
3099 if (!mo->auto_drop) {
3100 continue;
3101 }
3102
3103 if (volume->object_idx() == (int)object_idx && !volume->is_modifier) {
3104 double min_z = volume->transformed_convex_hull_bounding_box().min.z();
3105 std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
3106 InstancesToZMap::iterator it = instances_min_z.find(instance);
3107 if (it == instances_min_z.end())
3108 it = instances_min_z.insert(InstancesToZMap::value_type(instance, DBL_MAX)).first;
3109
3110 it->second = std::min(it->second, min_z);
3111 }
3112 }
3113
3114 for (GLVolume* volume : m_volumes.volumes) {
3115 std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
3116 InstancesToZMap::iterator it = instances_min_z.find(instance);
3117 if (it != instances_min_z.end())
3118 volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second);
3119 }
3120}
@ Z
Definition libslic3r.h:143

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

Here is the call graph for this function:

◆ exit_gizmo()

void Slic3r::GUI::GLCanvas3D::exit_gizmo ( )
3065 {
3066 if (m_gizmos.get_current_type() != GLGizmosManager::Undefined) {
3067 m_gizmos.reset_all_states();
3068 m_gizmos.update_data();
3069 }
3070}

References m_gizmos, and Slic3r::GUI::GLGizmosManager::Undefined.

◆ export_toolpaths_to_obj()

void Slic3r::GUI::GLCanvas3D::export_toolpaths_to_obj ( const char * filename) const
inline
1398{ m_gcode_viewer.export_toolpaths_to_obj(filename); }

References m_gcode_viewer.

◆ fff_print()

const Print * Slic3r::GUI::GLCanvas3D::fff_print ( ) const
12816{
12817 return (m_process == nullptr) ? nullptr : m_process->fff_print();
12818}

References fff_print(), and m_process.

Referenced by _max_bounding_box(), _render_overlays(), fff_print(), load_gcode_preview(), on_mouse(), set_config(), update_compacted_wipe_tower_clearance(), and update_sequential_clearance().

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

◆ finish_selection_edit()

void Slic3r::GUI::GLCanvas3D::finish_selection_edit ( )
4329{
4330 const SelectionEdit::Kind kind = m_selection_edit.kind;
4332 if (kind == SelectionEdit::Move)
4333 do_move(L("Tool move"));
4334 else
4335 do_rotate(L("Tool Rotate"));
4336 m_gizmos.update_data();
4337 // Let the plater know that the dragging finished, so a delayed refresh
4338 // of the scene with the background processing data should be performed.
4339 post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
4340 // updates camera target constraints
4342 m_dirty = true;
4343}
void do_move(const std::string &snapshot_type, bool force_volume_move=false)
Definition GLCanvas3D.cpp:5635
void do_rotate(const std::string &snapshot_type)
Definition GLCanvas3D.cpp:5773
Kind
Definition GLCanvas3D.hpp:769
@ Move
Definition GLCanvas3D.hpp:769

References do_move(), do_rotate(), L, m_dirty, m_gizmos, m_selection_edit, Slic3r::GUI::GLCanvas3D::SelectionEdit::Move, Slic3r::GUI::GLCanvas3D::SelectionEdit::None, post_event(), and refresh_camera_scene_box().

Referenced by bind_event_handlers(), and on_key().

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

◆ force_main_toolbar_left_action()

void Slic3r::GUI::GLCanvas3D::force_main_toolbar_left_action ( int item_id)
inline
1394{ m_main_toolbar.force_left_action(item_id, *this); }

References m_main_toolbar.

Referenced by _init_main_toolbar().

Here is the caller graph for this function:

◆ force_main_toolbar_right_action()

void Slic3r::GUI::GLCanvas3D::force_main_toolbar_right_action ( int item_id)
inline
1395{ m_main_toolbar.force_right_action(item_id, *this); }

References m_main_toolbar.

◆ force_set_focus()

void Slic3r::GUI::GLCanvas3D::force_set_focus ( )
5541 {
5542 m_canvas->SetFocus();
5543};

References m_canvas.

Referenced by Slic3r::GUI::MainFrame::handle_global_shortcut(), and Slic3r::GUI::MainFrame::init_menubar_as_editor().

Here is the caller graph for this function:

◆ get_arrange_settings()

GLCanvas3D::ArrangeSettings & Slic3r::GUI::GLCanvas3D::get_arrange_settings ( )
1564{
1566
1567 auto* ptr = &m_arrange_settings_fff;
1568
1569 if (ptech == ptSLA) {
1571 }
1572 else if (ptech == ptFFF) {
1573 if (wxGetApp().global_print_sequence() == PrintSequence::ByObject)
1575 else
1577 }
1578
1579 return *ptr;
1580}
ArrangeSettings m_arrange_settings_sla
Definition GLCanvas3D.hpp:821
ArrangeSettings m_arrange_settings_fff_seq_print
Definition GLCanvas3D.hpp:822
ArrangeSettings m_arrange_settings_fff
Definition GLCanvas3D.hpp:821

References Slic3r::ByObject, current_printer_technology(), get_arrange_settings(), m_arrange_settings_fff, m_arrange_settings_fff_seq_print, m_arrange_settings_sla, Slic3r::ptFFF, and Slic3r::ptSLA.

Referenced by _render_arrange_menu(), get_arrange_settings(), and Slic3r::GUI::init_arrange_params().

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

◆ get_assemble_view_toolbar_height()

float Slic3r::GUI::GLCanvas3D::get_assemble_view_toolbar_height ( ) const
inline
1140{ return m_assemble_view_toolbar.get_height(); }

References m_assemble_view_toolbar.

◆ get_assemble_view_toolbar_width()

float Slic3r::GUI::GLCanvas3D::get_assemble_view_toolbar_width ( ) const
inline
1139{ return m_assemble_view_toolbar.get_width(); }

References m_assemble_view_toolbar.

◆ get_assembly_paint_toolbar_width()

float Slic3r::GUI::GLCanvas3D::get_assembly_paint_toolbar_width ( ) const
inline
1141{ return m_paint_toolbar_width; }

References m_paint_toolbar_width.

◆ get_camera()

Camera & Slic3r::GUI::GLCanvas3D::get_camera ( )
2195{
2196 return camera;
2197}

References camera.

Referenced by _mouse_to_3d(), _picking_pass(), _render_arrange_menu(), _render_orient_menu(), on_idle(), and Slic3r::GUI::GLCanvas3D::CenterOfMass::render_details().

Here is the caller graph for this function:

◆ get_camera_orbit_target()

std::optional< Vec3d > Slic3r::GUI::GLCanvas3D::get_camera_orbit_target ( ECameraNavigationType navigation_type) const
private
12084{
12085 // Orca: Centralize the pre-existing pivot rules so orbiting and pan fallback cannot
12086 // choose different reference depths for the same canvas and active tool.
12087 const BoundingBoxf3 plate_box = _current_plate_box();
12088 if (navigation_type == ECameraNavigationType::Gesture)
12089 return plate_box.defined ? std::make_optional(plate_box.center()) : std::nullopt;
12090
12091 const GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
12092 const bool use_scene_target = m_canvas_type == ECanvasType::CanvasAssembleView ||
12093 gizmo_type == GLGizmosManager::FdmSupports || gizmo_type == GLGizmosManager::Seam ||
12094 gizmo_type == GLGizmosManager::MmSegmentation || gizmo_type == GLGizmosManager::FuzzySkin;
12095 if (use_scene_target) {
12096 if (!m_selection.is_empty())
12097 return m_selection.get_bounding_box().center();
12098
12099 // Orca: Preserve the world-origin fallback used by orbit in an empty scene.
12100 return volumes_bounding_box().center();
12101 }
12102
12103 // Orca: Free-camera rotation uses Camera::m_target rather than a plate or selection pivot.
12104 if (wxGetApp().app_config->get_bool("use_free_camera"))
12105 return std::nullopt;
12106
12107 Vec3d target = Vec3d::Zero();
12109 if (plate_box.defined)
12110 target = plate_box.center();
12111 } else if (!m_selection.is_empty()) {
12112 target = m_selection.get_bounding_box().center();
12113 } else {
12114 // Orca: Match regular mouse orbit: objects on the active plate, then the plate itself.
12115 BoundingBoxf3 bbox = volumes_bounding_box(true);
12116 if (!bbox.defined)
12117 bbox = plate_box;
12118 if (bbox.defined)
12119 target = bbox.center();
12120 }
12121
12122 // Orca: Preserve the existing zero sentinel used by regular mouse orbit.
12123 return target.isZero() ? std::nullopt : std::make_optional(target);
12124}
PointType center() const
Definition BoundingBox.cpp:237
BoundingBoxf3 _current_plate_box() const
Definition GLCanvas3D.cpp:9070
@ Gesture
Definition GLCanvas3D.hpp:1619

References _current_plate_box(), CanvasAssembleView, CanvasPreview, Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::defined, Slic3r::GUI::GLGizmosManager::FdmSupports, Slic3r::GUI::GLGizmosManager::FuzzySkin, Gesture, get_camera_orbit_target(), m_canvas_type, m_gizmos, m_selection, Slic3r::GUI::GLGizmosManager::MmSegmentation, Slic3r::GUI::GLGizmosManager::Seam, and volumes_bounding_box().

Referenced by get_camera_orbit_target(), get_camera_pan_anchor(), on_gesture(), and on_mouse().

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

◆ get_camera_pan_anchor()

Vec3d Slic3r::GUI::GLCanvas3D::get_camera_pan_anchor ( Camera & camera,
ECameraNavigationType navigation_type,
const Vec2d & screen_position ) const
private
12143{
12144 // Orthographic panning has the same scale at every depth, so no raycast is needed.
12145 if (camera.get_type() != Camera::EType::Perspective)
12146 return camera.get_target();
12147
12148 // Orca: Reject non-finite anchors and points behind the camera before their depth is
12149 // allowed to scale a perspective pan.
12150 const Vec3d camera_position = camera.get_position();
12151 const Vec3d camera_forward = camera.get_dir_forward();
12152 const auto is_valid_anchor = [&camera_position, &camera_forward](const Vec3d& anchor) {
12153 return anchor.allFinite() && (anchor - camera_position).dot(camera_forward) > EPSILON;
12154 };
12155
12156 // Orca: Prefer the nearest visible bed or volume surface and exclude gizmos and
12157 // selected-volume picking priority from navigation depth selection.
12158 const ClippingPlane clipping_plane = get_raycaster_clipping_plane();
12159 const bool bed_visible = is_bed_visible();
12160 const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(screen_position, camera, &clipping_plane,
12162 if (hit.is_valid()) {
12163 const Vec3d hit_position = hit.position.cast<double>();
12164 if (is_valid_anchor(hit_position))
12165 return hit_position;
12166 }
12167
12168 // Orca: When the cursor is just outside the visible plate, use the point under it on the active
12169 // plate plane. Using the plate center here would give it a different perspective depth.
12170 PartPlate* current_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
12171 // Orca: An almost edge-on perspective makes intersection depth extremely sensitive to
12172 // the cursor's vertical position. Use the stable orbit depth around horizontal views.
12173 static constexpr double min_plate_plane_forward_z = 0.05;
12174 if (bed_visible && std::abs(camera_forward.z()) >= min_plate_plane_forward_z &&
12175 current_plate != nullptr && current_plate->get_bounding_box().defined) {
12176 Vec3d ray_origin;
12177 Vec3d ray_direction;
12178 CameraUtils::ray_from_screen_pos(camera, screen_position, ray_origin, ray_direction);
12179 const double z_direction = ray_direction.z();
12180 if (ray_origin.allFinite() && ray_direction.allFinite() && std::abs(z_direction) > EPSILON) {
12181 const double plate_z = current_plate->get_bounding_box().center().z();
12182 const double distance = (plate_z - ray_origin.z()) / z_direction;
12183 const Vec3d plate_position = ray_origin + distance * ray_direction;
12184 const double eye_depth = (plate_position - camera_position).dot(camera_forward);
12185 if (distance >= 0.0 && is_valid_anchor(plate_position) &&
12186 eye_depth >= camera.get_near_z() && eye_depth <= camera.get_far_z())
12187 return plate_position;
12188 }
12189 }
12190
12191 // Orca: Near-horizontal rays and points outside the scene depth use the orbit reference point.
12192 const std::optional<Vec3d> orbit_target = get_camera_orbit_target(navigation_type);
12193 return orbit_target.has_value() && is_valid_anchor(*orbit_target) ? *orbit_target : camera.get_target();
12194}
#define EPSILON
Definition ColorUtils.cpp:64
static void ray_from_screen_pos(const Camera &camera, const Vec2d &position, Vec3d &point, Vec3d &direction)
Create ray(point and direction) for screen coordinate.
Definition CameraUtils.cpp:95
std::optional< Vec3d > get_camera_orbit_target(ECameraNavigationType navigation_type) const
Definition GLCanvas3D.cpp:12083
@ SceneOnly
Definition SceneRaycaster.hpp:68
@ VolumesOnly
Definition SceneRaycaster.hpp:69
float distance(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:19
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154

References camera, Slic3r::BoundingBox3Base< PointType >::center(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::defined, Slic3r::dot(), EPSILON, Slic3r::GUI::PartPlate::get_bounding_box(), get_camera_orbit_target(), get_camera_pan_anchor(), get_raycaster_clipping_plane(), is_bed_visible(), Slic3r::GUI::SceneRaycaster::HitResult::is_valid(), m_scene_raycaster, Slic3r::GUI::Camera::Perspective, Slic3r::GUI::SceneRaycaster::HitResult::position, Slic3r::GUI::CameraUtils::ray_from_screen_pos(), Slic3r::GUI::SceneRaycaster::SceneOnly, and Slic3r::GUI::SceneRaycaster::VolumesOnly.

Referenced by get_camera_pan_anchor(), on_gesture(), and on_mouse().

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

◆ get_canvas_size()

Size Slic3r::GUI::GLCanvas3D::get_canvas_size ( ) const
5597{
5598 int w = 0;
5599 int h = 0;
5600
5601 if (m_canvas != nullptr)
5602 m_canvas->GetSize(&w, &h);
5603
5604#if ENABLE_RETINA_GL
5605 const float factor = m_retina_helper->get_scale_factor();
5606 w *= factor;
5607 h *= factor;
5608#else
5609 const float factor = 1.0f;
5610#endif
5611
5612 return Size(w, h, factor);
5613}

References m_canvas.

Referenced by _check_and_update_toolbar_icon_scale(), _picking_pass(), _rectangular_selection_picking_pass(), _refresh_if_shown_on_screen(), _render_arrange_menu(), _render_assemble_control(), _render_assemble_info(), _render_assemble_view_toolbar(), _render_canvas_toolbar(), _render_collapse_toolbar(), _render_frame(), _render_imgui_select_plate_toolbar(), _render_main_toolbar(), _render_objects(), _render_orient_menu(), _render_paint_toolbar(), _render_plate_switcher(), _render_return_toolbar(), _render_separator_toolbar_left(), _render_separator_toolbar_right(), _render_wireframe_overlay(), _render_xray_volumes(), Slic3r::GUI::NotificationManager::PopNotification::bbl_render_block_notification(), Slic3r::GUI::MainFrame::GLResourcesPrebuild::build_step(), Slic3r::GUI::GLToolbar::contains_mouse_horizontal(), Slic3r::GUI::GLToolbar::contains_mouse_vertical(), Slic3r::GUI::GLCanvas3D::LayersEditing::get_bar_rect_screen(), get_main_toolbar_offset(), on_mouse(), on_mouse_wheel(), Slic3r::GUI::anonymous_namespace{SceneBenchmark.cpp}::SceneBenchmarkDialog::on_timer(), Slic3r::GUI::GLCanvas3D::Tooltip::render(), Slic3r::GUI::GLSelectionRectangle::render(), Slic3r::GUI::NotificationManager::PopNotification::render(), Slic3r::GUI::NotificationManager::SlicingProgressNotification::render(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_active_object_annotations(), Slic3r::GUI::GLToolbar::render_horizontal(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_profile(), Slic3r::GUI::Mouse3DController::render_settings_dialog(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(), Slic3r::GUI::GLToolbar::render_vertical(), Slic3r::GUI::Emboss::start_create_volume_without_position(), Slic3r::GUI::GLCanvas3D::LayersEditing::thickness_bar_width(), Slic3r::GUI::GLToolbar::update_hover_state_horizontal(), and Slic3r::GUI::GLToolbar::update_hover_state_vertical().

Here is the caller graph for this function:

◆ get_canvas_toolbar_right()

float Slic3r::GUI::GLCanvas3D::get_canvas_toolbar_right ( ) const
2450{
2451 // The toolbar scale, which on Windows follows the monitor's DPI where the ImGui style does not.
2452 float sc = get_scale();
2453#ifdef WIN32
2454 sc *= (float) get_dpi_for_window(wxGetApp().GetTopWindow()) / (float) DPI_DEFAULT;
2455#endif // WIN32
2456 const float left = wxGetApp().show_3d_navigator() ? NAVIGATOR_SIZE : CANVAS_TOOLBAR_MARGIN;
2457 return (left + 2.f * CANVAS_TOOLBAR_PADDING + CANVAS_TOOLBAR_BUTTON) * sc;
2458}

References Slic3r::GUI::CANVAS_TOOLBAR_BUTTON, Slic3r::GUI::CANVAS_TOOLBAR_MARGIN, Slic3r::GUI::CANVAS_TOOLBAR_PADDING, Slic3r::GUI::DPI_DEFAULT, Slic3r::GUI::get_dpi_for_window(), get_scale(), and Slic3r::GUI::NAVIGATOR_SIZE.

Here is the call graph for this function:

◆ get_canvas_type()

ECanvasType Slic3r::GUI::GLCanvas3D::get_canvas_type ( )
inline

◆ get_clipping_planes()

const std::array< ClippingPlane, 2 > & Slic3r::GUI::GLCanvas3D::get_clipping_planes ( ) const
inline
1054{ return m_clipping_planes; };

References m_clipping_planes.

◆ get_collapse_toolbar_height()

float Slic3r::GUI::GLCanvas3D::get_collapse_toolbar_height ( ) const
2427{
2429}
float get_height()
Definition GLToolbar.cpp:410

References collapse_side(), collapse_toolbar(), Slic3r::GUI::GLToolbar::get_height(), and Slic3r::GUI::None.

Referenced by _render_imgui_select_plate_toolbar().

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

◆ get_collapse_toolbar_width()

float Slic3r::GUI::GLCanvas3D::get_collapse_toolbar_width ( ) const
2422{
2424}
float get_width()
Definition GLToolbar.cpp:402

References collapse_side(), collapse_toolbar(), Slic3r::GUI::GLToolbar::get_width(), and Slic3r::GUI::None.

Referenced by _render_return_toolbar(), and get_main_toolbar_offset().

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

◆ get_dark_mode_status()

const bool Slic3r::GUI::GLCanvas3D::get_dark_mode_status ( )
inline
983{ return m_is_dark; }

References m_is_dark.

◆ get_empty_cells()

std::vector< Vec2f > Slic3r::GUI::GLCanvas3D::get_empty_cells ( const Vec2f start_point,
const Vec2f step = {10, 10} )
6195{
6196 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
6197 BoundingBoxf3 build_volume = plate->get_build_volume();
6198 Vec2d vmin(build_volume.min.x(), build_volume.min.y()), vmax(build_volume.max.x(), build_volume.max.y());
6199 BoundingBoxf bbox(vmin, vmax);
6200 std::vector<Vec2f> cells;
6201 std::vector<Vec2f> cells_ret;
6202 auto min_x = start_point.x() - step(0) * int((start_point.x() - bbox.min.x()) / step(0));
6203 auto min_y = start_point.y() - step(1) * int((start_point.y() - bbox.min.y()) / step(1));
6204 cells.reserve(((bbox.max.x() - min_x) / step(0)) * ((bbox.max.y() - min_y) / step(1)));
6205 cells_ret.reserve(cells.size());
6206 for (float x = min_x; x < bbox.max.x() - step(0) / 2; x += step(0))
6207 for (float y = min_y; y < bbox.max.y() - step(1) / 2; y += step(1))
6208 {
6209 cells.emplace_back(x, y);
6210 }
6211 for (size_t i = 0; i < m_model->objects.size(); ++i) {
6212 ModelObject* model_object = m_model->objects[i];
6213 auto id = model_object->id().id;
6214 ModelInstance* model_instance0 = model_object->instances.front();
6215 Polygon hull_2d = model_object->convex_hull_2d(Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(),
6216 model_instance0->get_scaling_factor(), model_instance0->get_mirror()));
6217 if (hull_2d.empty())
6218 continue;
6219
6220 const auto& instances = model_object->instances;
6221 double rotation_z0 = instances.front()->get_rotation().z();
6222 for (const auto& instance : instances) {
6223 Geometry::Transformation transformation;
6224 const Vec3d& offset = instance->get_offset();
6225 transformation.set_offset({ scale_(offset.x()), scale_(offset.y()), 0.0 });
6226 transformation.set_rotation(Z, instance->get_rotation().z() - rotation_z0);
6227 const Transform3d& trafo = transformation.get_matrix();
6228 Polygon inst_hull_2d = hull_2d.transform(trafo);
6229
6230 for (auto it = cells.begin(); it != cells.end(); )
6231 {
6232 if (!inst_hull_2d.contains(Point(scale_(it->x()), scale_(it->y()))))
6233 cells_ret.push_back(*it);
6234
6235 it++;
6236 }
6237 }
6238 }
6239
6240 Vec2f start = start_point;
6241 if (start_point(0) < 0 && start_point(1) < 0) {
6242 start(0) = bbox.center()(0);
6243 start(1) = bbox.center()(1);
6244 }
6245 std::sort(cells_ret.begin(), cells_ret.end(), [start](const Vec2f& cell1, const Vec2f& cell2) {return (cell1 - start).norm() < (cell2 - start).norm(); });
6246 return cells_ret;
6247}
const Point & front() const
Definition MultiPoint.hpp:45
Polygon transform(const Transform3d &trafo) const
Definition Polygon.cpp:409
#define scale_(val)
Definition libslic3r.h:106
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
Slic3r::Polygon Polygon
Definition Emboss.cpp:101

References Slic3r::Geometry::assemble_transform(), Slic3r::BoundingBoxBase< PointType, APointsType >::center(), Slic3r::Polygon::contains(), Slic3r::ModelObject::convex_hull_2d(), Slic3r::MultiPoint::empty(), Slic3r::GUI::PartPlate::get_build_volume(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::ModelInstance::get_mirror(), Slic3r::ModelInstance::get_offset(), Slic3r::ModelInstance::get_rotation(), Slic3r::ModelInstance::get_scaling_factor(), Slic3r::ObjectBase::id(), Slic3r::ObjectID::id, Slic3r::ModelObject::instances, m_model, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::offset(), scale_, Slic3r::Geometry::Transformation::set_offset(), Slic3r::Geometry::Transformation::set_rotation(), Slic3r::Polygon::transform(), and Slic3r::Z.

Referenced by get_nearest_empty_cell().

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

◆ get_explosion_ratio()

float Slic3r::GUI::GLCanvas3D::get_explosion_ratio ( )
inline
980{ return m_explosion_ratio; }

References m_explosion_ratio.

◆ get_first_hover_volume_idx()

int Slic3r::GUI::GLCanvas3D::get_first_hover_volume_idx ( ) const
inline
1333{ return m_hover_volume_idxs.empty() ? -1 : m_hover_volume_idxs.front(); }

References m_hover_volume_idxs.

Referenced by Slic3r::GUI::get_first_hovered_gl_volume(), on_mouse(), and anonymous_namespace{SurfaceDrag.cpp}::start_dragging().

Here is the caller graph for this function:

◆ get_frame_profiler()

FrameProfiler & Slic3r::GUI::GLCanvas3D::get_frame_profiler ( )
inline
1391{ return m_frame_profiler; }

References m_frame_profiler.

◆ get_gcode_extruders_count()

size_t Slic3r::GUI::GLCanvas3D::get_gcode_extruders_count ( )
inline
1250{ return m_gcode_viewer.get_extruders_count(); }

References m_gcode_viewer.

◆ get_gcode_layers_times()

std::vector< float > Slic3r::GUI::GLCanvas3D::get_gcode_layers_times ( ) const
inline
1246{ return m_gcode_viewer.get_layers_times(); }

References m_gcode_viewer.

◆ get_gcode_layers_times_cache()

const std::vector< float > & Slic3r::GUI::GLCanvas3D::get_gcode_layers_times_cache ( ) const
inline
std::vector< float > m_gcode_layers_times_cache
Definition GLCanvas3D.hpp:837

References m_gcode_layers_times_cache.

◆ get_gcode_layers_zs()

std::vector< double > Slic3r::GUI::GLCanvas3D::get_gcode_layers_zs ( ) const
inline
1245{ return m_gcode_viewer.get_layers_zs(); }

References m_gcode_viewer.

◆ get_gcode_sequential_view()

const GCodeViewer::SequentialView & Slic3r::GUI::GLCanvas3D::get_gcode_sequential_view ( ) const
inline
1010{ return m_gcode_viewer.get_sequential_view(); }

References m_gcode_viewer.

◆ get_gcode_vertex_at()

const libvgcode::PathVertex & Slic3r::GUI::GLCanvas3D::get_gcode_vertex_at ( size_t id) const
inline
1015{ return m_gcode_viewer.get_gcode_vertex_at(id); }

References m_gcode_viewer.

◆ get_gcode_view_enabled_range()

const libvgcode::Interval & Slic3r::GUI::GLCanvas3D::get_gcode_view_enabled_range ( ) const
inline
1013{ return m_gcode_viewer.get_gcode_view_enabled_range(); }

References m_gcode_viewer.

◆ get_gcode_view_full_range()

const libvgcode::Interval & Slic3r::GUI::GLCanvas3D::get_gcode_view_full_range ( ) const
inline
1012{ return m_gcode_viewer.get_gcode_view_full_range(); }

References m_gcode_viewer.

◆ get_gcode_view_type()

libvgcode::EViewType Slic3r::GUI::GLCanvas3D::get_gcode_view_type ( ) const
inline
1268{ return m_gcode_viewer.get_view_type(); }

References m_gcode_viewer.

◆ get_gcode_view_visible_range()

const libvgcode::Interval & Slic3r::GUI::GLCanvas3D::get_gcode_view_visible_range ( ) const
inline
1014{ return m_gcode_viewer.get_gcode_view_visible_range(); }

References m_gcode_viewer.

◆ get_gcode_viewer()

◆ get_gizmos_manager() [1/2]

GLGizmosManager & Slic3r::GUI::GLCanvas3D::get_gizmos_manager ( )
inline
1032{ return m_gizmos; }

References m_gizmos.

◆ get_gizmos_manager() [2/2]

◆ get_hover_ghost_head()

int Slic3r::GUI::GLCanvas3D::get_hover_ghost_head ( ) const
inline
1334{ return m_hover_ghost_head; }

References m_hover_ghost_head.

◆ get_hover_ghost_plate()

int Slic3r::GUI::GLCanvas3D::get_hover_ghost_plate ( ) const
inline
1335{ return m_hover_ghost_plate; }

References m_hover_ghost_plate.

◆ get_local_mouse_position()

Vec2d Slic3r::GUI::GLCanvas3D::get_local_mouse_position ( ) const
5616{
5617 if (m_canvas == nullptr)
5618 return Vec2d::Zero();
5619
5620 // Use the cached mouse position from event handlers (m_mouse.position)
5621 // instead of wxGetMousePosition() + ScreenToClient(), because
5622 // wxGetMousePosition() returns (0,0) on Wayland for global coords.
5623 // m_mouse.position already stores local canvas coordinates (set from
5624 // event.GetX(), event.GetY()) and is already scaled by the retina factor
5625 // in on_mouse(), so we can return it directly.
5626 return m_mouse.position;
5627}

References m_canvas, and m_mouse.

Referenced by Slic3r::GUI::GLCanvas3D::LayersEditing::get_cursor_z_relative().

Here is the caller graph for this function:

◆ get_main_toolbar_height()

int Slic3r::GUI::GLCanvas3D::get_main_toolbar_height ( ) const
inline
1137{ return m_main_toolbar.get_height(); }

References m_main_toolbar.

◆ get_main_toolbar_item_id()

int Slic3r::GUI::GLCanvas3D::get_main_toolbar_item_id ( const std::string & name) const
inline
1393{ return m_main_toolbar.get_item_id(name); }

References m_main_toolbar.

Referenced by _init_main_toolbar().

Here is the caller graph for this function:

◆ get_main_toolbar_offset()

int Slic3r::GUI::GLCanvas3D::get_main_toolbar_offset ( ) const
10332{
10333 const float cnv_width = get_canvas_size().get_width();
10334 const float collapse_toolbar_width = get_collapse_toolbar_width() * 2;
10335 const float gizmo_width = m_gizmos.get_scaled_total_width();
10336 const float assemble_width = m_assemble_view_toolbar.get_width();
10337 const float separator_width = m_separator_toolbar.get_width();
10338 const float toolbar_total_width = m_main_toolbar.get_width() + separator_width + gizmo_width + assemble_width + collapse_toolbar_width;
10339
10340 if (cnv_width < toolbar_total_width) {
10341 return is_collapse_toolbar_on_left() ? collapse_toolbar_width : 0;
10342 } else {
10343 const float offset = (cnv_width - toolbar_total_width) / 2;
10344 return is_collapse_toolbar_on_left() ? offset + collapse_toolbar_width : offset;
10345 }
10346}
int get_width() const
Definition GLCanvas3D.hpp:119

References get_canvas_size(), get_collapse_toolbar_width(), get_main_toolbar_offset(), is_collapse_toolbar_on_left(), m_assemble_view_toolbar, m_gizmos, m_main_toolbar, m_separator_toolbar, and Slic3r::offset().

Referenced by _render_assemble_view_toolbar(), _render_fps_overlay(), _render_main_toolbar(), _render_separator_toolbar_left(), _render_separator_toolbar_right(), and get_main_toolbar_offset().

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

◆ get_main_toolbar_width()

int Slic3r::GUI::GLCanvas3D::get_main_toolbar_width ( ) const
inline
1138{ return m_main_toolbar.get_width(); }

References m_main_toolbar.

◆ get_model()

const Model * Slic3r::GUI::GLCanvas3D::get_model ( ) const
inline

◆ get_move_volume_id()

int Slic3r::GUI::GLCanvas3D::get_move_volume_id ( ) const
inline
1332{ return m_mouse.drag.move_volume_idx; }

References m_mouse.

◆ get_nearest_empty_cell()

Vec2f Slic3r::GUI::GLCanvas3D::get_nearest_empty_cell ( const Vec2f start_point,
const Vec2f step = {10, 10} )
6250{
6251 std::vector<Vec2f> empty_cells = get_empty_cells(start_point, step);
6252 if (!empty_cells.empty())
6253 return empty_cells.front();
6254 else {
6256 return { start_point(0) + offset, start_point(1) + offset };
6257 }
6258}
double get_size_proportional_to_max_bed_size(double factor) const
Definition GLCanvas3D.cpp:6187
std::vector< Vec2f > get_empty_cells(const Vec2f start_point, const Vec2f step={10, 10})
Definition GLCanvas3D.cpp:6194

References get_empty_cells(), get_size_proportional_to_max_bed_size(), and Slic3r::offset().

Here is the call graph for this function:

◆ get_orient_settings()

OrientSettings & Slic3r::GUI::GLCanvas3D::get_orient_settings ( )
inline
841 {
843
844 auto* ptr = &this->m_orient_settings_fff;
845
846 if (ptech == ptSLA) {
847 ptr = &this->m_orient_settings_sla;
848 }
849
850 return *ptr;
851 }
OrientSettings m_orient_settings_fff
Definition GLCanvas3D.hpp:819
OrientSettings m_orient_settings_sla
Definition GLCanvas3D.hpp:819

References current_printer_technology(), and Slic3r::ptSLA.

Referenced by _render_orient_menu().

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

◆ get_overlay_window_width()

float Slic3r::GUI::GLCanvas3D::get_overlay_window_width ( )
inlineprivate
1662{ return 0; /*LayersEditing::get_overlay_window_width();*/ }

Referenced by _render_frame().

Here is the caller graph for this function:

◆ get_popup_menu_position()

const std::optional< Vec2d > & Slic3r::GUI::GLCanvas3D::get_popup_menu_position ( ) const
inline
1310{ return m_popup_menu_positon; }

References m_popup_menu_positon.

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

Here is the caller graph for this function:

◆ get_raycaster_clipping_plane()

ClippingPlane Slic3r::GUI::GLCanvas3D::get_raycaster_clipping_plane ( ) const
private
12074{
12075 // Orca: Ignore the gizmo clipping plane when the active tool does not apply it, and
12076 // invert the result into the convention expected by SceneRaycaster.
12077 GLGizmoBase* current_gizmo = m_gizmos.get_current();
12078 return ((!current_gizmo || current_gizmo->apply_clipping_plane()) ? _get_volumes_clipping_plane() :
12080 .inverted_normal();
12081}

References _get_volumes_clipping_plane(), Slic3r::GUI::GLGizmoBase::apply_clipping_plane(), Slic3r::GUI::ClippingPlane::ClipsNothing(), get_raycaster_clipping_plane(), and m_gizmos.

Referenced by _picking_pass(), get_camera_pan_anchor(), and get_raycaster_clipping_plane().

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

◆ get_raycasters_for_picking()

std::vector< std::shared_ptr< SceneRaycasterItem > > * Slic3r::GUI::GLCanvas3D::get_raycasters_for_picking ( SceneRaycaster::EType type)
inline
972 {
973 return m_scene_raycaster.get_raycasters(type);
974 }

References m_scene_raycaster.

Referenced by _update_inactive_plates_visibility(), Slic3r::GUI::create_meshes(), toggle_model_objects_visibility(), and toggle_sla_auxiliaries_visibility().

Here is the caller graph for this function:

◆ get_scale()

const float Slic3r::GUI::GLCanvas3D::get_scale ( ) const

◆ get_section_view_normal()

const Vec3d & Slic3r::GUI::GLCanvas3D::get_section_view_normal ( ) const
inline
1062{ return m_section_view->normal; }

References m_section_view.

◆ get_section_view_ratio()

double Slic3r::GUI::GLCanvas3D::get_section_view_ratio ( ) const
inline
1061{ return m_section_view->ratio; }

References m_section_view.

Referenced by _render_canvas_toolbar(), _render_section_view_panel(), and on_mouse_wheel().

Here is the caller graph for this function:

◆ get_selection() [1/2]

Selection & Slic3r::GUI::GLCanvas3D::get_selection ( )
inline
1029{ return m_selection; }

References m_selection.

◆ get_selection() [2/2]

◆ get_separator_toolbar_height()

float Slic3r::GUI::GLCanvas3D::get_separator_toolbar_height ( ) const
inline
1143{ return m_separator_toolbar.get_height(); }

References m_separator_toolbar.

◆ get_separator_toolbar_width()

float Slic3r::GUI::GLCanvas3D::get_separator_toolbar_width ( ) const
inline
1142{ return m_separator_toolbar.get_width(); }

References m_separator_toolbar.

◆ get_show_bed()

bool Slic3r::GUI::GLCanvas3D::get_show_bed ( ) const
inline
1113{ return m_show_bed; }

References m_show_bed.

◆ get_size_proportional_to_max_bed_size()

double Slic3r::GUI::GLCanvas3D::get_size_proportional_to_max_bed_size ( double factor) const
6188{
6189 const BoundingBoxf& bbox = m_bed.build_volume().bounding_volume2d();
6190 return factor * std::max(bbox.size()[0], bbox.size()[1]);
6191}

References m_bed, and Slic3r::BoundingBoxBase< PointType, APointsType >::size().

Referenced by get_nearest_empty_cell(), and Slic3r::GUI::Plater::increase_instances().

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

◆ get_use_clipping_planes()

bool Slic3r::GUI::GLCanvas3D::get_use_clipping_planes ( ) const
inline
1053{ return m_use_clipping_planes; }

References m_use_clipping_planes.

◆ get_volumes()

const GLVolumeCollection & Slic3r::GUI::GLCanvas3D::get_volumes ( ) const
inline
993{ return m_volumes; }

References m_volumes.

Referenced by Slic3r::GUI::create_meshes(), anonymous_namespace{SurfaceDrag.cpp}::dragging(), Slic3r::GUI::get_first_hovered_gl_volume(), Slic3r::GUI::get_selected_gl_volume(), Slic3r::GUI::GLCanvas3D::CenterOfMass::model_markers(), and anonymous_namespace{SurfaceDrag.cpp}::start_dragging().

Here is the caller graph for this function:

◆ get_volumes_count()

unsigned int Slic3r::GUI::GLCanvas3D::get_volumes_count ( ) const
inline
992{ return (unsigned int)m_volumes.volumes.size(); }

References m_volumes.

◆ get_wipe_tower_info()

GLCanvas3D::WipeTowerInfo Slic3r::GUI::GLCanvas3D::get_wipe_tower_info ( int plate_idx) const
6142{
6143 WipeTowerInfo wti;
6144
6145 for (const GLVolume* vol : m_volumes.volumes) {
6146 if (vol->is_wipe_tower && vol->object_idx() - 1000 == plate_idx) {
6147 DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
6148 wti.m_pos = Vec2d(proj_cfg.opt<ConfigOptionFloats>("wipe_tower_x")->get_at(plate_idx),
6149 proj_cfg.opt<ConfigOptionFloats>("wipe_tower_y")->get_at(plate_idx));
6150 // BBS: don't support rotation
6151 //wti.m_rotation = (M_PI/180.) * proj_cfg->opt_float("wipe_tower_rotation_angle");
6152
6153 auto& preset = wxGetApp().preset_bundle->prints.get_edited_preset();
6154 float wt_brim_width = preset.config.opt_float("prime_tower_brim_width");
6155
6156 const BoundingBoxf3& bb = vol->bounding_box();
6157 if (wt_brim_width < 0) wt_brim_width = WipeTower::get_auto_brim_by_height((float)bb.max.z());
6158 wti.m_bb = BoundingBoxf{to_2d(bb.min), to_2d(bb.max)};
6159 wti.m_bb.offset(wt_brim_width);
6160
6161 float brim_width = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("prime_tower_brim_width");
6162 if (brim_width < 0) brim_width = WipeTower::get_auto_brim_by_height((float) bb.max.z());
6163 wti.m_bb.offset((brim_width));
6164
6165 // BBS: the wipe tower pos might be outside bed
6166 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
6167 Vec2d plate_size = plate->get_size();
6168 wti.m_pos.x() = std::clamp(wti.m_pos.x(), 0.0, plate_size(0) - wti.m_bb.size().x());
6169 wti.m_pos.y() = std::clamp(wti.m_pos.y(), 0.0, plate_size(1) - wti.m_bb.size().y());
6170
6171 // BBS: add partplate logic
6172 wti.m_plate_idx = plate_idx;
6173 break;
6174 }
6175 }
6176
6177 return wti;
6178}
const double & get_at(size_t i) const
Definition Config.hpp:676
Definition GLCanvas3D.hpp:1338
static float get_auto_brim_by_height(float max_height)
Definition WipeTower.cpp:1733
Eigen::Matrix< typename Derived::Scalar, 2, 1, Eigen::DontAlign > to_2d(const Eigen::MatrixBase< Derived > &ptN)
Definition Point.hpp:147

References Slic3r::GLVolume::bounding_box(), Slic3r::WipeTower::get_auto_brim_by_height(), Slic3r::GUI::PartPlate::get_size(), Slic3r::GUI::GLCanvas3D::WipeTowerInfo::m_bb, Slic3r::GUI::GLCanvas3D::WipeTowerInfo::m_plate_idx, Slic3r::GUI::GLCanvas3D::WipeTowerInfo::m_pos, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GLVolume::object_idx(), Slic3r::BoundingBoxBase< PointType, APointsType >::offset(), Slic3r::DynamicConfig::opt(), Slic3r::BoundingBoxBase< PointType, APointsType >::size(), and Slic3r::to_2d().

Here is the call graph for this function:

◆ get_wxglcanvas() [1/2]

wxGLCanvas * Slic3r::GUI::GLCanvas3D::get_wxglcanvas ( )
inline
955{ return m_canvas; }

References m_canvas.

Referenced by Slic3r::GUI::MainFrame::GLResourcesPrebuild::build_step(), Slic3r::GUI::anonymous_namespace{SceneBenchmark.cpp}::SceneBenchmarkDialog::on_timer(), Slic3r::GUI::GLCanvas3D::LayersEditing::render_variable_layer_height_dialog(), and Slic3r::GUI::GLCanvas3D::LayersEditing::thickness_bar_width().

Here is the caller graph for this function:

◆ get_wxglcanvas() [2/2]

const wxGLCanvas * Slic3r::GUI::GLCanvas3D::get_wxglcanvas ( ) const
inline
956{ return m_canvas; }

References m_canvas.

◆ GetHoverId()

int Slic3r::GUI::GLCanvas3D::GetHoverId ( )
1583{
1584 if (m_hover_plate_idxs.size() == 0) {
1585 return -1; }
1586 return m_hover_plate_idxs.front();
1587
1588}

References GetHoverId(), and m_hover_plate_idxs.

Referenced by GetHoverId().

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

◆ handle_layers_data_focus_event()

void Slic3r::GUI::GLCanvas3D::handle_layers_data_focus_event ( const t_layer_height_range range,
const EditorType type )
6111{
6112 std::string field = "layer_" + std::to_string(type) + "_" + std::to_string(range.first) + "_" + std::to_string(range.second);
6113 m_gizmos.reset_all_states();
6114 handle_sidebar_focus_event(field, true);
6115}
void handle_sidebar_focus_event(const std::string &opt_key, bool focus_on)
Definition GLCanvas3D.cpp:6095

References handle_sidebar_focus_event(), m_gizmos, and Slic3r::range().

Here is the call graph for this function:

◆ handle_shortcut()

bool Slic3r::GUI::GLCanvas3D::handle_shortcut ( const KeyChord & chord)
4128{
4130 const std::optional<ShortcutRegistry::Match> match = wxGetApp().shortcuts().match(context, chord);
4131 if (!match.has_value())
4132 return false;
4133 const Shortcut shortcut = match->shortcut;
4134 const int held = match->step_modifiers;
4135 if (m_key_down.repeat && !shortcut_info(shortcut).repeatable)
4136 return true;
4137
4138 const bool painting = dynamic_cast<GLGizmoPainterBase*>(m_gizmos.get_current()) != nullptr;
4139 const bool can_edit = m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView;
4140 auto edit_selection = [this](SelectionEdit::Kind kind, const Vec3d& direction) {
4141 if (!m_gizmos.is_enabled() || m_selection.is_empty() || m_canvas_type == CanvasAssembleView)
4142 return false;
4143 m_selection_edit.kind = kind;
4144 m_selection_edit.key = m_key_down.code;
4145 m_selection_edit.direction = direction;
4146 return true;
4147 };
4148 auto move_selection = [&](const Vec3d& direction) {
4149 if (edit_selection(SelectionEdit::Move, direction))
4150 apply_selection_move((held & wxMOD_SHIFT) != 0, (held & wxMOD_CONTROL) != 0);
4151 };
4152 auto rotate_selection = [&](double angle_z_rad) {
4153 if (edit_selection(SelectionEdit::Rotate, Vec3d::UnitZ()))
4154 apply_selection_rotate(angle_z_rad);
4155 };
4156 auto step_slider = [this, held](auto&& step) {
4157 IMSlider* layers = get_gcode_viewer().get_layers_slider();
4158 IMSlider* moves = get_gcode_viewer().get_moves_slider();
4159 step(layers, moves, held != 0 ? 5 : 1);
4160 if (layers->is_dirty() && layers->is_one_layer())
4161 layers->SetLowerValue(layers->GetHigherValue());
4162 m_dirty = true;
4163 };
4164
4165 switch (shortcut) {
4167 if (!painting && !m_layers_editing.is_enabled())
4168 post_event(SimpleEvent(EVT_GLCANVAS_SELECT_CURR_PLATE_ALL));
4169 break;
4171 if (!painting && !m_layers_editing.is_enabled())
4172 post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
4173 break;
4174 case Shortcut::Copy: if (!painting) post_event(SimpleEvent(EVT_GLTOOLBAR_COPY)); break;
4175 case Shortcut::Paste: if (!painting) post_event(SimpleEvent(EVT_GLTOOLBAR_PASTE)); break;
4176 case Shortcut::Cut: if (!painting) post_event(SimpleEvent(EVT_GLTOOLBAR_CUT)); break;
4177 case Shortcut::Undo: if (can_edit) post_event(SimpleEvent(EVT_GLCANVAS_UNDO)); break;
4178 case Shortcut::Redo: if (can_edit) post_event(SimpleEvent(EVT_GLCANVAS_REDO)); break;
4180 if (!m_gizmos.on_delete_key())
4181 post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
4182 break;
4183 case Shortcut::DeleteAll: post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); break;
4184 case Shortcut::CloneSelected: post_event(SimpleEvent(EVT_GLTOOLBAR_CLONE)); break;
4185 case Shortcut::AddInstance: post_event(Event<int>(EVT_GLCANVAS_INCREASE_INSTANCES, +1)); break;
4186 case Shortcut::RemoveInstance: post_event(Event<int>(EVT_GLCANVAS_INCREASE_INSTANCES, -1)); break;
4187 case Shortcut::TogglePrintable: post_event(SimpleEvent(EVT_GLCANVAS_PRINTABLE)); break;
4188 case Shortcut::Arrange:
4189 if (!m_gizmos.is_running())
4190 post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE));
4191 break;
4193 if (!m_gizmos.is_running())
4194 post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE_PARTPLATE));
4195 break;
4196 case Shortcut::Orient: post_event(SimpleEvent(EVT_GLCANVAS_ORIENT)); break;
4197 case Shortcut::OrientPlate: post_event(SimpleEvent(EVT_GLCANVAS_ORIENT_PARTPLATE)); break;
4198 case Shortcut::RotateSelectionLeft: rotate_selection(0.25 * M_PI); break;
4199 case Shortcut::RotateSelectionRight: rotate_selection(-0.25 * M_PI); break;
4200 case Shortcut::MoveSelectionLeft: move_selection(-Vec3d::UnitX()); break;
4201 case Shortcut::MoveSelectionRight: move_selection(Vec3d::UnitX()); break;
4202 case Shortcut::MoveSelectionUp: move_selection(Vec3d::UnitY()); break;
4203 case Shortcut::MoveSelectionDown: move_selection(-Vec3d::UnitY()); break;
4204 case Shortcut::ZoomIn: _update_camera_zoom(1.0); break;
4205 case Shortcut::ZoomOut: _update_camera_zoom(-1.0); break;
4206 case Shortcut::SwitchView: post_event(SimpleEvent(EVT_GLCANVAS_TAB)); break;
4208 if (!wxGetApp().is_gcode_viewer())
4209 post_event(SimpleEvent(EVT_GLCANVAS_COLLAPSE_SIDEBAR));
4210 break;
4212 wxGetApp().plater()->toggle_show_wireframe();
4213 m_dirty = true;
4214 break;
4216 Mouse3DController& controller = wxGetApp().plater()->get_mouse3d_controller();
4217 if (controller.can_show_settings_dialog()) {
4218 controller.show_settings_dialog(!controller.is_settings_dialog_shown());
4219 m_dirty = true;
4220 }
4221 break;
4222 }
4224 if (wxGetApp().mainframe->is_printer_view())
4225 wxGetApp().mainframe->load_printer_url();
4226 break;
4227 case Shortcut::KeyboardShortcuts: post_event(SimpleEvent(EVT_GLCANVAS_QUESTION_MARK)); break;
4229 wxGetApp().toggle_show_gcode_window();
4230 m_dirty = true;
4232 break;
4235 m_dirty = true;
4236 break;
4238 // Same state as the canvas view menu item. The designed-view back-transform is
4239 // baked into the toolpaths at load time, so the preview is re-converted.
4240 if (m_gcode_viewer.is_belt_view()) {
4241 m_gcode_viewer.toggle_belt_show_designed();
4242 if (Plater* plater = wxGetApp().plater())
4244 m_dirty = true;
4245 }
4246 break;
4248 if (!m_gizmos.is_enabled()) {
4250 m_dirty = true;
4251 }
4252 break;
4255 step_slider([up = shortcut == Shortcut::LayerSliderUp](IMSlider* layers, IMSlider* moves, int increment) {
4256 const int delta = up ? increment : -increment;
4257 if (layers->GetSelection() == ssHigher) {
4258 layers->SetHigherValue(layers->GetHigherValue() + delta);
4259 moves->SetHigherValue(moves->GetMaxValue());
4260 }
4261 else if (layers->GetSelection() == ssLower)
4262 layers->SetLowerValue(layers->GetLowerValue() + delta);
4263 });
4264 break;
4266 step_slider([](IMSlider* layers, IMSlider* moves, int increment) {
4267 if (moves->GetHigherValue() == moves->GetMinValue() && layers->GetHigherValue() > layers->GetMinValue()) {
4268 layers->SetHigherValue(layers->GetHigherValue() - 1);
4269 moves->SetHigherValue(moves->GetMaxValue());
4270 }
4271 else
4272 moves->SetHigherValue(moves->GetHigherValue() - increment);
4273 });
4274 break;
4276 step_slider([](IMSlider* layers, IMSlider* moves, int increment) {
4277 if (moves->GetHigherValue() == moves->GetMaxValue() && layers->GetHigherValue() < layers->GetMaxValue()) {
4278 layers->SetHigherValue(layers->GetHigherValue() + 1);
4279 moves->SetHigherValue(moves->GetMinValue());
4280 }
4281 else
4282 moves->SetHigherValue(moves->GetHigherValue() + increment);
4283 });
4284 break;
4287 step_slider([start = shortcut == Shortcut::MovesSliderStart](IMSlider*, IMSlider* moves, int) {
4288 moves->SetHigherValue(start ? moves->GetMinValue() : moves->GetMaxValue());
4289 moves->set_as_dirty();
4290 });
4291 break;
4292 default:
4293 if (!m_gizmos.open_gizmo_by_shortcut(shortcut))
4294 return false;
4295 m_dirty = true;
4296 break;
4297 }
4298 return true;
4299}
#define M_PI
Definition ExtrusionSimulator.cpp:31
void apply_selection_move(bool slow, bool camera_space)
Definition GLCanvas3D.cpp:4301
void _update_camera_zoom(double zoom)
Definition GLCanvas3D.cpp:7941
KeyDown m_key_down
Definition GLCanvas3D.hpp:764
void apply_selection_rotate(double angle_z_rad)
Definition GLCanvas3D.cpp:4321
bool switch_one_layer_mode()
Definition IMSlider.cpp:487
void show_go_to_layer(bool show)
Definition IMSlider.hpp:122
void refresh_belt_view()
Definition Plater.cpp:18337
const ShortcutInfo & shortcut_info(Shortcut shortcut)
Definition Shortcuts.cpp:237
Shortcut
Definition Shortcuts.hpp:25
@ LayerSliderUp
Definition Shortcuts.hpp:43
@ MoveSelectionLeft
Definition Shortcuts.hpp:38
@ MovesSliderLeft
Definition Shortcuts.hpp:43
@ RemoveInstance
Definition Shortcuts.hpp:35
@ MoveSelectionDown
Definition Shortcuts.hpp:38
@ LayerSliderDown
Definition Shortcuts.hpp:43
@ Undo
Definition Shortcuts.hpp:33
@ ZoomOut
Definition Shortcuts.hpp:47
@ Paste
Definition Shortcuts.hpp:33
@ SelectAllPlates
Definition Shortcuts.hpp:31
@ Mouse3DSettings
Definition Shortcuts.hpp:47
@ RotateSelectionRight
Definition Shortcuts.hpp:38
@ OrientPlate
Definition Shortcuts.hpp:37
@ CollapseSidebar
Definition Shortcuts.hpp:51
@ ZoomIn
Definition Shortcuts.hpp:47
@ Redo
Definition Shortcuts.hpp:33
@ DeleteAll
Definition Shortcuts.hpp:33
@ Copy
Definition Shortcuts.hpp:33
@ ArrangePlate
Definition Shortcuts.hpp:37
@ MoveSelectionUp
Definition Shortcuts.hpp:38
@ RotateSelectionLeft
Definition Shortcuts.hpp:38
@ ReloadDevicePage
Definition Shortcuts.hpp:51
@ SelectAll
Definition Shortcuts.hpp:31
@ TogglePrintable
Definition Shortcuts.hpp:35
@ MovesSliderEnd
Definition Shortcuts.hpp:43
@ DeleteSelected
Definition Shortcuts.hpp:33
@ ToggleOneLayerMode
Definition Shortcuts.hpp:49
@ SwitchView
Definition Shortcuts.hpp:51
@ MovesSliderStart
Definition Shortcuts.hpp:43
@ Arrange
Definition Shortcuts.hpp:37
@ MovesSliderRight
Definition Shortcuts.hpp:43
@ CloneSelected
Definition Shortcuts.hpp:33
@ GoToLayer
Definition Shortcuts.hpp:43
@ ToggleGcodeWindow
Definition Shortcuts.hpp:49
@ MoveSelectionRight
Definition Shortcuts.hpp:38
@ AddInstance
Definition Shortcuts.hpp:35
@ Cut
Definition Shortcuts.hpp:33
@ KeyboardShortcuts
Definition Shortcuts.hpp:51
@ Orient
Definition Shortcuts.hpp:37
@ ShowWireframe
Definition Shortcuts.hpp:49
@ ToggleBeltRawGcode
Definition Shortcuts.hpp:49
@ ssLower
Definition IMSlider.hpp:43
@ ssHigher
Definition IMSlider.hpp:44
ShortcutContext
Definition Shortcuts.hpp:21
@ Preview
Definition Shortcuts.hpp:21
@ Rotate
Definition GLCanvas3D.hpp:769

References _update_camera_zoom(), Slic3r::GUI::AddInstance, apply_selection_move(), apply_selection_rotate(), Slic3r::GUI::Arrange, Slic3r::GUI::ArrangePlate, Slic3r::GUI::Mouse3DController::can_show_settings_dialog(), CanvasAssembleView, CanvasPreview, CanvasView3D, Slic3r::GUI::CloneSelected, Slic3r::GUI::CollapseSidebar, Slic3r::GUI::Copy, Slic3r::GUI::Cut, Slic3r::GUI::DeleteAll, Slic3r::GUI::DeleteSelected, get_gcode_viewer(), Slic3r::GUI::GCodeViewer::get_layers_slider(), Slic3r::GUI::GCodeViewer::get_moves_slider(), Slic3r::GUI::IMSlider::GetHigherValue(), Slic3r::GUI::IMSlider::GetLowerValue(), Slic3r::GUI::IMSlider::GetMaxValue(), Slic3r::GUI::IMSlider::GetMinValue(), Slic3r::GUI::IMSlider::GetSelection(), Slic3r::GUI::GoToLayer, Slic3r::GUI::IMSlider::is_dirty(), Slic3r::GUI::IMSlider::is_one_layer(), Slic3r::GUI::Mouse3DController::is_settings_dialog_shown(), Slic3r::GUI::KeyboardShortcuts, Slic3r::GUI::LayerSliderDown, Slic3r::GUI::LayerSliderUp, m_canvas_type, m_dirty, m_gcode_viewer, m_gizmos, m_key_down, m_layers_editing, M_PI, m_selection, m_selection_edit, Slic3r::GUI::Mouse3DSettings, Slic3r::GUI::GLCanvas3D::SelectionEdit::Move, Slic3r::GUI::MoveSelectionDown, Slic3r::GUI::MoveSelectionLeft, Slic3r::GUI::MoveSelectionRight, Slic3r::GUI::MoveSelectionUp, Slic3r::GUI::MovesSliderEnd, Slic3r::GUI::MovesSliderLeft, Slic3r::GUI::MovesSliderRight, Slic3r::GUI::MovesSliderStart, Slic3r::GUI::Orient, Slic3r::GUI::OrientPlate, Slic3r::GUI::Paste, Slic3r::GUI::Plater, Slic3r::GUI::plater(), post_event(), Slic3r::GUI::Preview, Slic3r::GUI::Redo, Slic3r::GUI::ReloadDevicePage, Slic3r::GUI::RemoveInstance, request_extra_frame(), Slic3r::GUI::GLCanvas3D::SelectionEdit::Rotate, Slic3r::GUI::RotateSelectionLeft, Slic3r::GUI::RotateSelectionRight, Slic3r::GUI::SelectAll, Slic3r::GUI::SelectAllPlates, Slic3r::GUI::IMSlider::set_as_dirty(), Slic3r::GUI::IMSlider::SetHigherValue(), Slic3r::GUI::IMSlider::SetLowerValue(), Slic3r::GUI::shortcut_info(), Slic3r::GUI::IMSlider::show_go_to_layer(), Slic3r::GUI::Mouse3DController::show_settings_dialog(), Slic3r::GUI::ShowWireframe, Slic3r::GUI::ssHigher, Slic3r::GUI::ssLower, Slic3r::GUI::IMSlider::switch_one_layer_mode(), Slic3r::GUI::SwitchView, Slic3r::GUI::ToggleBeltRawGcode, Slic3r::GUI::ToggleGcodeWindow, Slic3r::GUI::ToggleOneLayerMode, Slic3r::GUI::TogglePrintable, Slic3r::GUI::Undo, Slic3r::GUI::ZoomIn, and Slic3r::GUI::ZoomOut.

Referenced by on_char(), and on_key().

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

◆ handle_sidebar_focus_event()

void Slic3r::GUI::GLCanvas3D::handle_sidebar_focus_event ( const std::string & opt_key,
bool focus_on )
6096{
6097 const std::string field = focus_on ? opt_key : "";
6098 // The gizmo panels report this on every build.
6099 if (m_sidebar_field == field)
6100 return;
6101 m_sidebar_field = field;
6102
6103 //BBS: this event was sent from gizmo now, no need to clear gizmo
6104 //if (!m_sidebar_field.empty())
6105 // m_gizmos.reset_all_states();
6106
6107 m_dirty = true;
6108}

References m_dirty, and m_sidebar_field.

Referenced by handle_layers_data_focus_event().

Here is the caller graph for this function:

◆ has_mouse_capture()

bool Slic3r::GUI::GLCanvas3D::has_mouse_capture ( ) const
2341 {
2342 return m_canvas != nullptr && m_canvas->HasCapture();
2343}

References m_canvas.

Referenced by _render_frame(), and on_mouse().

Here is the caller graph for this function:

◆ has_toolpaths_to_export()

bool Slic3r::GUI::GLCanvas3D::has_toolpaths_to_export ( ) const
inline
1397{ return m_gcode_viewer.can_export_toolpaths(); }

References m_gcode_viewer.

◆ highlight_gizmo()

void Slic3r::GUI::GLCanvas3D::highlight_gizmo ( const std::string & gizmo_name)
12808{
12809 GLGizmosManager::EType gizmo = m_gizmos.get_gizmo_from_name(gizmo_name);
12811 return;
12812 m_gizmo_highlighter.init(&m_gizmos, gizmo, this);
12813}

References highlight_gizmo(), m_gizmo_highlighter, m_gizmos, and Slic3r::GUI::GLGizmosManager::Undefined.

Referenced by highlight_gizmo().

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

◆ highlight_toolbar_item()

void Slic3r::GUI::GLCanvas3D::highlight_toolbar_item ( const std::string & item_name)
12800{
12801 GLToolbarItem* item = m_main_toolbar.get_item(item_name);
12802 if (!item || !item->is_visible())
12803 return;
12804 m_toolbar_highlighter.init(item, this);
12805}

References highlight_toolbar_item(), Slic3r::GUI::GLToolbarItem::is_visible(), m_main_toolbar, and m_toolbar_highlighter.

Referenced by highlight_toolbar_item().

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

◆ init()

bool Slic3r::GUI::GLCanvas3D::init ( )
1698{
1699 if (m_initialized)
1700 return true;
1701
1702 if (m_canvas == nullptr || m_context == nullptr)
1703 return false;
1704
1705 // init dark mode status
1706 on_change_color_mode(wxGetApp().app_config->get("dark_color_mode") == "1", false);
1707
1708 m_show_world_axes = wxGetApp().app_config->get("show_axes") == "true";
1709
1710 // Controls the display of object names directly over the object
1711 m_labels.show(wxGetApp().app_config->get_bool("show_labels"));
1712 // Controls the color coding of overhang surfaces
1713 m_slope.globalUse(wxGetApp().app_config->get_bool("show_overhang"));
1714
1715 BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< " enter";
1716 glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f));
1717 glsafe(::glClearDepth(1.0f));
1718
1720
1725
1728
1729 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": before m_layers_editing init";
1730 if (m_main_toolbar.is_enabled())
1731 m_layers_editing.init();
1732
1733 BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< ": before gizmo init";
1734 if (m_gizmos.is_enabled() && !m_gizmos.init())
1735 std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl;
1736
1737 BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< ": before _init_toolbars";
1738 if (!_init_toolbars())
1739 return false;
1740
1741 BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< ": finish _init_toolbars";
1742 if (m_selection.is_enabled() && !m_selection.init())
1743 return false;
1744
1745 BOOST_LOG_TRIVIAL(info) <<__FUNCTION__<< ": finish m_selection";
1746
1747#if ENABLE_IMGUI_STYLE_EDITOR
1748 //BBS load render color for style editor
1754#endif
1755 //if (!wxGetApp().is_gl_version_greater_or_equal_to(3, 0))
1756 // wxGetApp().plater()->enable_wireframe(false);
1757 m_initialized = true;
1758
1759 return true;
1760}
static void load_render_colors()
Definition 3DScene.cpp:229
static void load_render_colors()
Definition 3DBed.cpp:220
void on_change_color_mode(bool is_dark, bool reinit=true)
Definition GLCanvas3D.cpp:1762
bool _init_toolbars()
Definition GLCanvas3D.cpp:7453
static void load_render_colors()
Definition GLCanvas3D.cpp:204
static void load_render_colors()
Definition GLGizmoBase.cpp:92
static void load_render_colors()
Definition PartPlate.cpp:216
#define glClearColor
Definition gl.h:3373
#define glClearDepth
Definition gl.h:3375

References _init_toolbars(), GL_BLEND, GL_CULL_FACE, GL_DEPTH_TEST, GL_LESS, GL_MULTISAMPLE, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, glBlendFunc, glClearColor, glClearDepth, glDepthFunc, glEnable, glsafe, Slic3r::GLVolume::load_render_colors(), Slic3r::GUI::Bed3D::load_render_colors(), load_render_colors(), Slic3r::GUI::GLGizmoBase::load_render_colors(), Slic3r::GUI::PartPlate::load_render_colors(), m_canvas, m_context, m_gizmos, m_initialized, m_labels, m_layers_editing, m_main_toolbar, m_multisample_allowed, m_selection, m_show_world_axes, m_slope, and on_change_color_mode().

Referenced by _render_frame(), and Slic3r::GUI::MainFrame::GLResourcesPrebuild::build_step().

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

◆ init_gcode_viewer()

void Slic3r::GUI::GLCanvas3D::init_gcode_viewer ( ConfigOptionMode mode,
Slic3r::PresetBundle * preset_bundle )
inline
1008{ m_gcode_viewer.init(mode, preset_bundle); }

References m_gcode_viewer.

◆ is_all_plates_selected()

bool Slic3r::GUI::GLCanvas3D::is_all_plates_selected ( )
inline
997{ return m_sel_plate_toolbar.m_all_plates_stats_item && m_sel_plate_toolbar.m_all_plates_stats_item->selected; }

References m_sel_plate_toolbar.

◆ is_bed_visible()

bool Slic3r::GUI::GLCanvas3D::is_bed_visible ( ) const
private
12127{
12129 return m_render_preview;
12131 return false;
12132 if (!m_main_toolbar.is_enabled())
12133 return true;
12134
12135 // The painting gizmos clip the selected instance at the plate (see InstancesHider), so the bed
12136 // mesh would sit in front of the part below it. They draw the plate and its grid instead (see
12137 // _render_scene) and the below-plate part as a translucent ghost.
12139}

References _is_below_plate_view_active(), CanvasPreview, CanvasView3D, is_bed_visible(), m_canvas_type, m_main_toolbar, m_render_preview, and m_show_bed.

Referenced by _render_scene(), get_camera_pan_anchor(), and is_bed_visible().

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

◆ is_camera_pan()

bool Slic3r::GUI::GLCanvas3D::is_camera_pan ( const wxMouseEvent & evt,
const std::map< MouseButton, MouseAction > & mappings ) const
5587{
5589 return evt.Moving() && evt.ShiftDown() && !evt.AltDown();
5590 } else {
5591 return evt.Dragging() && clicked_button_matches_action(evt, MouseAction::Pan, mappings);
5592 ;
5593 }
5594}
bool clicked_button_matches_action(const wxMouseEvent &evt, MouseAction action, const std::map< MouseButton, MouseAction > &mappings) const
Definition GLCanvas3D.cpp:5557
@ Pan
Definition GLCanvas3D.hpp:1299
bool m_is_touchpad_navigation
Definition GLCanvas3D.hpp:743

References clicked_button_matches_action(), m_is_touchpad_navigation, Pan, and Slic3r::GUI::wxMouseEvent.

Referenced by on_mouse().

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

◆ is_camera_rotate()

bool Slic3r::GUI::GLCanvas3D::is_camera_rotate ( const wxMouseEvent & evt,
const std::map< MouseButton, MouseAction > & mappings ) const
5578{
5580 return evt.Moving() && evt.AltDown() && !evt.ShiftDown();
5581 } else {
5582 return evt.Dragging() && clicked_button_matches_action(evt, MouseAction::Rotation, mappings);
5583 }
5584}
@ Rotation
Definition GLCanvas3D.hpp:1299

References clicked_button_matches_action(), m_is_touchpad_navigation, Rotation, and Slic3r::GUI::wxMouseEvent.

Referenced by on_mouse().

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

◆ is_collapse_toolbar_on_left()

bool Slic3r::GUI::GLCanvas3D::is_collapse_toolbar_on_left ( ) const
2417{
2419}

References collapse_side(), and Slic3r::GUI::Left.

Referenced by _render_imgui_select_plate_toolbar(), _render_return_toolbar(), and get_main_toolbar_offset().

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

◆ is_dragging()

bool Slic3r::GUI::GLCanvas3D::is_dragging ( ) const
inline
1153{ return m_gizmos.is_dragging() || m_moving; }

References m_gizmos, and m_moving.

Referenced by Slic3r::GUI::GLCanvas3D::CenterOfMass::model_markers().

Here is the caller graph for this function:

◆ is_flushing_matrix_error()

bool Slic3r::GUI::GLCanvas3D::is_flushing_matrix_error ( )
private
12646 {
12647
12648 // Flushing volumes only apply to single-extruder multi-material (SEMM) and BBL printers
12650 return false;
12651
12652 std::vector<int> plate_extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_extruders(true);
12653 if (plate_extruders.size() < 2)
12654 return false;
12655
12656 const auto &project_config = wxGetApp().preset_bundle->project_config;
12657 const std::vector<double> &config_matrix = (project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values;
12658 const std::vector<double> &config_multiplier = (project_config.option<ConfigOptionFloats>("flush_multiplier"))->values;
12659 return has_zero_flush_volume_for_used_filaments(config_matrix, config_multiplier, plate_extruders);
12660}
static bool should_show_SEMM_buttons()
Definition Plater.cpp:6559
static bool has_zero_flush_volume_for_used_filaments(const std::vector< T > &fv_matrix, const std::vector< T > &flush_multipliers, const std::vector< int > &used_filaments)
Definition PrintConfig.hpp:2710

References Slic3r::has_zero_flush_volume_for_used_filaments(), is_flushing_matrix_error(), and Slic3r::GUI::Sidebar::should_show_SEMM_buttons().

Referenced by is_flushing_matrix_error(), and reload_scene().

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

◆ is_frame_in_progress()

bool Slic3r::GUI::GLCanvas3D::is_frame_in_progress ( )
inlinestatic
989{ return s_frames_in_progress > 0; }

References s_frames_in_progress.

Referenced by Slic3r::GUI::UVEditorCanvas::on_size(), and Slic3r::GUI::UVEditorCanvas::render().

Here is the caller graph for this function:

◆ is_initialized()

bool Slic3r::GUI::GLCanvas3D::is_initialized ( ) const
inline
948{ return m_initialized; }

References m_initialized.

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

Here is the caller graph for this function:

◆ is_layers_editing_allowed()

bool Slic3r::GUI::GLCanvas3D::is_layers_editing_allowed ( ) const
inline
1077{ return m_layers_editing.is_allowed(); }

References m_layers_editing.

◆ is_layers_editing_enabled()

bool Slic3r::GUI::GLCanvas3D::is_layers_editing_enabled ( ) const
inline
1076{ return m_layers_editing.is_enabled(); }

References m_layers_editing.

Referenced by _is_scene_cacheable(), _render_objects(), on_mouse(), and on_mouse_wheel().

Here is the caller graph for this function:

◆ is_mouse_dragging()

bool Slic3r::GUI::GLCanvas3D::is_mouse_dragging ( ) const
inline
1367{ return m_mouse.dragging; }

References m_mouse.

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

Here is the caller graph for this function:

◆ is_mouse_left_up_ignored()

bool Slic3r::GUI::GLCanvas3D::is_mouse_left_up_ignored ( ) const
inline
1371{ return m_mouse.ignore_left_up; }

References m_mouse.

◆ is_object_sinking()

bool Slic3r::GUI::GLCanvas3D::is_object_sinking ( int object_idx) const
6527{
6528 for (const GLVolume* v : m_volumes.volumes) {
6529 if (v->object_idx() == object_idx && (v->is_sinking() || (!v->is_modifier && v->is_below_printbed())))
6530 return true;
6531 }
6532 return false;
6533}

References Slic3r::GLVolume::is_below_printbed(), Slic3r::GLVolume::is_sinking(), m_volumes, and Slic3r::GLVolume::object_idx().

Here is the call graph for this function:

◆ is_overhang_shown()

bool Slic3r::GUI::GLCanvas3D::is_overhang_shown ( ) const
inline
1405{ return m_slope.is_GlobalUsed(); }

References m_slope.

◆ is_reload_delayed()

bool Slic3r::GUI::GLCanvas3D::is_reload_delayed ( ) const
inline
1083{ return m_reload_delayed; }

References m_reload_delayed.

◆ is_rendering_enabled()

bool Slic3r::GUI::GLCanvas3D::is_rendering_enabled ( )
inline
1158 {
1159 return m_enable_render;
1160 }

References m_enable_render.

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

Here is the caller graph for this function:

◆ is_section_view_active()

bool Slic3r::GUI::GLCanvas3D::is_section_view_active ( ) const
inline
1060{ return m_section_view->ratio > 0.; }

References m_section_view.

Referenced by _render_canvas_toolbar(), _render_section_view_panel(), and toggle_section_view().

Here is the caller graph for this function:

◆ is_using_slope()

bool Slic3r::GUI::GLCanvas3D::is_using_slope ( ) const
inline
1408{ return m_slope.is_used(); }

References m_slope.

◆ load_arrange_settings()

void Slic3r::GUI::GLCanvas3D::load_arrange_settings ( )
1527{
1528 // Each key must match what _render_arrange_menu writes, which appends a per-mode
1529 // postfix to the base name.
1530 auto load_float = [](const char *key, float &out) {
1531 // The menu writes these with float_to_string_decimal_point, so parse them back
1532 // the same way rather than with anything locale-dependent.
1533 std::string value = wxGetApp().app_config->get("arrange", key);
1534 size_t parsed = 0;
1535 double number = string_to_double_decimal_point(value, &parsed);
1536 if (parsed > 0)
1537 out = float(number);
1538 };
1539 auto load_bool = [](const char *key, bool &out) {
1540 std::string value = wxGetApp().app_config->get("arrange", key);
1541 if (!value.empty())
1542 out = (value == "1" || value == "true");
1543 };
1544
1545 load_float("min_object_distance_fff", m_arrange_settings_fff.distance);
1546 load_float("min_object_distance_fff_seq_print", m_arrange_settings_fff_seq_print.distance);
1547 load_float("min_object_distance_sla", m_arrange_settings_sla.distance);
1548
1549 load_bool("enable_rotation_fff", m_arrange_settings_fff.enable_rotation);
1550 load_bool("enable_rotation_fff_seq_print", m_arrange_settings_fff_seq_print.enable_rotation);
1551 load_bool("enable_rotation_sla", m_arrange_settings_sla.enable_rotation);
1552
1553 // These two keys carry no postfix, so the one stored value covers both FFF modes.
1554 load_bool("allow_multi_materials_on_same_plate", m_arrange_settings_fff.allow_multi_materials_on_same_plate);
1555 load_bool("allow_multi_materials_on_same_plate", m_arrange_settings_fff_seq_print.allow_multi_materials_on_same_plate);
1556 load_bool("avoid_extrusion_cali_region", m_arrange_settings_fff.avoid_extrusion_cali_region);
1557 load_bool("avoid_extrusion_cali_region", m_arrange_settings_fff_seq_print.avoid_extrusion_cali_region);
1558
1559 //BBS: add specific arrange settings
1560 m_arrange_settings_fff_seq_print.is_seq_print = true;
1561}
double string_to_double_decimal_point(const std::string_view str, size_t *pos)
Definition LocalesUtils.cpp:86

References load_arrange_settings(), m_arrange_settings_fff, m_arrange_settings_fff_seq_print, m_arrange_settings_sla, and Slic3r::string_to_double_decimal_point().

Referenced by GLCanvas3D(), and load_arrange_settings().

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

◆ load_gcode_preview()

void Slic3r::GUI::GLCanvas3D::load_gcode_preview ( const GCodeProcessorResult & gcode_result,
const std::vector< std::string > & str_tool_colors,
const std::vector< std::string > & str_color_print_colors,
bool only_gcode )
3837{
3838 PartPlateList& partplate_list = wxGetApp().plater()->get_partplate_list();
3839 PartPlate* plate = partplate_list.get_curr_plate();
3840 const std::vector<BoundingBoxf3>& exclude_bounding_box = plate->get_exclude_areas();
3841
3843
3844 //BBS: init is called in GLCanvas3D.render()
3845 //when load gcode directly, it is too late
3846 m_gcode_viewer.init(wxGetApp().get_mode(), wxGetApp().preset_bundle);
3847 m_gcode_viewer.enable_legend(true);
3848
3849
3850 m_gcode_viewer.load_as_gcode(gcode_result, *this->fff_print(), str_tool_colors, str_color_print_colors, wxGetApp().plater()->build_volume(), exclude_bounding_box,
3851 wxGetApp().get_mode(), only_gcode);
3852 m_gcode_layers_times_cache = m_gcode_viewer.get_layers_times();
3853
3854 m_gcode_viewer.get_moves_slider()->SetHigherValue(m_gcode_viewer.get_moves_slider()->GetMaxValue());
3855
3856 if (wxGetApp().is_editor()) {
3857 //BBS: always load shell at preview, do this in load_shells
3859 }
3860
3861 set_as_dirty();
3863}
bool _set_shown_canvas_current()
Definition GLCanvas3D.cpp:2946
void _update_slice_error_status()
Definition GLCanvas3D.cpp:7389

References _set_shown_canvas_current(), _update_slice_error_status(), fff_print(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::get_exclude_areas(), m_gcode_layers_times_cache, m_gcode_viewer, Slic3r::GUI::plater(), request_extra_frame(), and set_as_dirty().

Here is the call graph for this function:

◆ load_object() [1/2]

std::vector< int > Slic3r::GUI::GLCanvas3D::load_object ( const Model & model,
int obj_idx )
3134{
3135 if (0 <= obj_idx && obj_idx < (int)model.objects.size()) {
3136 const ModelObject* model_object = model.objects[obj_idx];
3137 if (model_object != nullptr)
3138 return load_object(*model_object, obj_idx, std::vector<int>());
3139 }
3140
3141 return std::vector<int>();
3142}
std::vector< int > load_object(const ModelObject &model_object, int obj_idx, std::vector< int > instance_idxs)
Definition GLCanvas3D.cpp:3123

References load_object(), and Slic3r::Model::objects.

Here is the call graph for this function:

◆ load_object() [2/2]

std::vector< int > Slic3r::GUI::GLCanvas3D::load_object ( const ModelObject & model_object,
int obj_idx,
std::vector< int > instance_idxs )
3124{
3125 if (instance_idxs.empty()) {
3126 for (unsigned int i = 0; i < model_object.instances.size(); ++i) {
3127 instance_idxs.emplace_back(i);
3128 }
3129 }
3130 return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_initialized);
3131}

References Slic3r::ModelObject::instances, m_color_by, m_initialized, and m_volumes.

Referenced by load_object().

Here is the caller graph for this function:

◆ load_render_colors()

void Slic3r::GUI::GLCanvas3D::load_render_colors ( )
staticprivate
205{
207}
@ RenderCol_3D_Background
Definition GUI_Colors.hpp:9

References Slic3r::RenderColor::colors, DEFAULT_BG_LIGHT_COLOR, RenderCol_3D_Background, and Slic3r::GUI::ImGuiWrapper::to_ImVec4().

Referenced by init().

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

◆ load_shells()

void Slic3r::GUI::GLCanvas3D::load_shells ( const Print & print,
bool force_previewing = false )
3822{
3823 if (m_initialized)
3824 {
3826 m_gcode_viewer.load_shells(print, m_initialized, force_previewing);
3827 m_gcode_viewer.update_shells_color_by_extruder(m_config);
3828 }
3829}

References _set_shown_canvas_current(), m_config, m_gcode_viewer, and m_initialized.

Here is the call graph for this function:

◆ load_sla_preview()

void Slic3r::GUI::GLCanvas3D::load_sla_preview ( )
3866{
3867 const SLAPrint* print = sla_print();
3868 if (m_canvas != nullptr && print != nullptr) {
3869 _set_current();
3870 // Release OpenGL data before generating new data.
3871 reset_volumes();
3875 }
3876}
void _load_sla_shells()
Definition GLCanvas3D.cpp:12202
void _update_sla_shells_outside_state()
Definition GLCanvas3D.hpp:1639

References _load_sla_shells(), _set_current(), _set_warning_notification_if_needed(), _update_sla_shells_outside_state(), m_canvas, reset_volumes(), sla_print(), and SlaSupportsOutside.

Here is the call graph for this function:

◆ make_current_for_postinit()

bool Slic3r::GUI::GLCanvas3D::make_current_for_postinit ( )
2476 {
2477 return _set_current();
2478}

References _set_current().

Referenced by Slic3r::GUI::MainFrame::GLResourcesPrebuild::build_step().

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

◆ mirror_selection()

void Slic3r::GUI::GLCanvas3D::mirror_selection ( Axis axis)
3145{
3146 TransformationType transformation_type;
3147 //transformation_type.set_world();
3148 transformation_type.set_relative();
3149 m_selection.setup_cache();
3150 m_selection.mirror(axis, transformation_type);
3151 do_mirror(L("Mirror object"));
3152 // BBS
3153 //wxGetApp().obj_manipul()->set_dirty();
3154}
void do_mirror(const std::string &snapshot_type)
Definition GLCanvas3D.cpp:6002

References do_mirror(), L, m_selection, and Slic3r::GUI::TransformationType::set_relative().

Here is the call graph for this function:

◆ mouse_ray()

Linef3 Slic3r::GUI::GLCanvas3D::mouse_ray ( const Point & mouse_pos)
6181{
6182 float z0 = 0.0f;
6183 float z1 = 1.0f;
6184 return Linef3(_mouse_to_3d(mouse_pos, &z0), _mouse_to_3d(mouse_pos, &z1));
6185}
Vec3d _mouse_to_3d(const Point &mouse_pos, float *z=nullptr)
Definition GLCanvas3D.cpp:12020

References _mouse_to_3d().

Referenced by _mouse_to_bed_3d(), _picking_pass_imex_ghosts(), Slic3r::GUI::DesignSketchTool::arc_mouse_angle(), Slic3r::GUI::DesignSketchTool::drag_datum_handle(), Slic3r::GUI::DesignSketchTool::drag_draft_arc(), Slic3r::GUI::DesignSketchTool::drag_extrude_arrow(), Slic3r::GUI::DesignSketchTool::drag_helix_handle(), Slic3r::GUI::DesignSketchTool::drag_hole_handle(), Slic3r::GUI::DesignSketchTool::drag_pattern_handle(), Slic3r::GUI::DesignSketchTool::drag_revolve_arc(), Slic3r::GUI::DesignSketchTool::drag_rib_handle(), Slic3r::GUI::DesignSketchTool::drag_thread_handle(), Slic3r::GUI::DesignSketchTool::fillet_axis_proj(), Slic3r::GUI::DesignSketchTool::hit_test_base_pick(), Slic3r::GUI::DesignSketchTool::hit_test_cut_arrow(), Slic3r::GUI::DesignSketchTool::hit_test_datum_handle(), Slic3r::GUI::DesignSketchTool::hit_test_draft_handle(), Slic3r::GUI::DesignSketchTool::hit_test_extrude_arrow(), Slic3r::GUI::DesignSketchTool::hit_test_fillet_arrow(), Slic3r::GUI::DesignSketchTool::hit_test_helix_handle(), Slic3r::GUI::DesignSketchTool::hit_test_hole_handle(), Slic3r::GUI::DesignSketchTool::hit_test_move_arc(), Slic3r::GUI::DesignSketchTool::hit_test_move_arrow(), Slic3r::GUI::DesignSketchTool::hit_test_pattern_handle(), Slic3r::GUI::DesignSketchTool::hit_test_revolve_handle(), Slic3r::GUI::DesignSketchTool::hit_test_rib_handle(), Slic3r::GUI::DesignSketchTool::hit_test_shell_arrow(), Slic3r::GUI::DesignSketchTool::hit_test_thread_handle(), Slic3r::GUI::DesignSketchTool::hole_axis_proj(), on_mouse(), Slic3r::GUI::DesignSketchTool::on_mouse_impl(), Slic3r::GUI::DesignSketchTool::resolve_solid_pick(), Slic3r::GUI::DesignSketchTool::screen_to_plane(), Slic3r::GUI::DesignSketchTool::screen_tol(), Slic3r::GUI::DesignSketchTool::select_at_screen(), Slic3r::GUI::DesignSketchTool::start_hole_drag(), and Slic3r::GUI::DesignSketchTool::start_thread_drag().

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

◆ mouse_up_cleanup()

void Slic3r::GUI::GLCanvas3D::mouse_up_cleanup ( )
6275{
6276 // Both direct dragging and gizmo manipulation clear the expensive red
6277 // exclusion-intersection mesh while moving. Gizmo drags do not always set
6278 // m_mouse.dragging, so every completed mouse operation must allow the
6279 // cached preview to restore/recompute that mesh.
6280 if (PartPlate *plate = wxGetApp().plater()->get_partplate_list().get_curr_plate())
6281 plate->invalidate_exclusion_volume_preview();
6282
6283 m_moving = false;
6284 m_camera_movement = false;
6285 m_mouse.drag.move_volume_idx = -1;
6286 m_mouse.set_start_position_3D_as_invalid();
6287 m_mouse.set_start_position_2D_as_invalid();
6288 m_mouse.dragging = false;
6289 m_mouse.ignore_left_up = false;
6290 m_mouse.ignore_right_up = false;
6291 m_dirty = true;
6292
6293 if (m_canvas->HasCapture())
6294 m_canvas->ReleaseMouse();
6295}

References m_camera_movement, m_canvas, m_dirty, m_mouse, m_moving, and Slic3r::GUI::plater().

Referenced by on_mouse(), and Slic3r::GUI::ObjectList::OnContextMenu().

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

◆ msw_rescale()

void Slic3r::GUI::GLCanvas3D::msw_rescale ( )
inline
1383{ m_gcode_viewer.invalidate_legend(); }

References m_gcode_viewer.

Referenced by Slic3r::GUI::Preview::msw_rescale().

Here is the caller graph for this function:

◆ on_change_color_mode()

void Slic3r::GUI::GLCanvas3D::on_change_color_mode ( bool is_dark,
bool reinit = true )
1762 {
1764 // Bed color
1765 m_bed.on_change_color_mode(is_dark);
1766 // GcodeViewer color
1767 m_gcode_viewer.on_change_color_mode(is_dark);
1768 // ImGui Style
1769 wxGetApp().imgui()->on_change_color_mode(is_dark);
1770 // Notification
1771 wxGetApp().plater()->get_notification_manager()->on_change_color_mode(is_dark);
1772 // DailyTips Window
1773 wxGetApp().plater()->get_dailytips()->on_change_color_mode(is_dark);
1774 // Preview Slider
1775 IMSlider* m_layers_slider = get_gcode_viewer().get_layers_slider();
1776 IMSlider* m_moves_slider = get_gcode_viewer().get_moves_slider();
1777 m_layers_slider->on_change_color_mode(is_dark);
1778 m_moves_slider->on_change_color_mode(is_dark);
1779 // Partplate
1780 wxGetApp().plater()->get_partplate_list().on_change_color_mode(is_dark);
1781 // Plates toolbar - Reload All Stats button images
1783
1784 // Toolbar
1785 if (m_canvas_type == CanvasView3D) {
1786 m_gizmos.on_change_color_mode(is_dark);
1787 if (reinit) {
1788 // reset svg
1790 m_gizmos.switch_gizmos_icon_filename();
1791 // set dirty to re-generate icon texture
1792 m_separator_toolbar.set_icon_dirty();
1793 m_main_toolbar.set_icon_dirty();
1795 m_assemble_view_toolbar.set_icon_dirty();
1796 m_gizmos.set_icon_dirty();
1797 }
1798 }
1800 m_gizmos.on_change_color_mode(is_dark);
1801 if (reinit) {
1802 // reset svg
1803 m_gizmos.switch_gizmos_icon_filename();
1804 // set dirty to re-generate icon texture
1805 m_gizmos.set_icon_dirty();
1806 }
1807 }
1808 m_dirty = true;
1809}
static bool is_dark()
Definition TextureImportDialog.cpp:85
void _switch_toolbars_icon_filename()
Definition GLCanvas3D.cpp:7399
void set_icon_dirty()
Definition GLToolbar.hpp:366
void on_change_color_mode(bool is_dark)
Definition IMSlider.cpp:1636

References _init_select_plate_toolbar(), _switch_toolbars_icon_filename(), CanvasAssembleView, CanvasView3D, collapse_toolbar(), get_gcode_viewer(), Slic3r::GUI::GCodeViewer::get_layers_slider(), Slic3r::GUI::GCodeViewer::get_moves_slider(), is_dark(), m_assemble_view_toolbar, m_bed, m_canvas_type, m_dirty, m_gcode_viewer, m_gizmos, m_is_dark, m_main_toolbar, m_separator_toolbar, Slic3r::GUI::IMSlider::on_change_color_mode(), and Slic3r::GUI::GLToolbar::set_icon_dirty().

Referenced by init().

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

◆ on_char()

void Slic3r::GUI::GLCanvas3D::on_char ( wxKeyEvent & evt)
4059{
4060 if (!m_initialized)
4061 return;
4062
4063 // see include/wx/defs.h enum wxKeyCode
4064 int keyCode = evt.GetKeyCode();
4065
4066 auto imgui = wxGetApp().imgui();
4067 const bool imgui_claimed = imgui->claim_key_event(evt);
4068 if (imgui->update_key_data(evt) || imgui_claimed)
4069 render();
4070 if (imgui_claimed)
4071 return;
4072
4073 // Design tab: Delete, Esc, Ctrl+Z/Y and F are NOT handled here. DesignPanel's CHAR_HOOK owns
4074 // them (one route per key, whatever holds focus) and only lets a key through to this canvas
4075 // when an in-canvas value field is open -- which is exactly when Backspace must edit the
4076 // number rather than delete the geometry it measures.
4077
4078 //BBS: add orient deactivate logic
4079 if (keyCode == WXK_ESCAPE
4081 return;
4082
4083 if (m_gizmos.on_char(evt))
4084 return;
4085
4086 if (const KeyChord chord = KeyChord::from_event(evt); chord.is_punctuation() && handle_shortcut(chord))
4087 return;
4088
4089 if (evt.HasModifiers()) {
4090 evt.Skip();
4091 return;
4092 }
4093
4094 auto obj_list = wxGetApp().obj_list();
4095 switch (keyCode)
4096 {
4097 case WXK_ESCAPE: { deselect_all(); break; }
4098
4099 // BBS: use keypad to change extruder
4100 case '1': {
4101 if (!m_timer_set_color.IsRunning()) {
4102 m_timer_set_color.StartOnce(500);
4103 break;
4104 }
4105 }
4106 case '0': //Color logic for material 10
4107 case '2':
4108 case '3':
4109 case '4':
4110 case '5':
4111 case '6':
4112 case '7':
4113 case '8':
4114 case '9': {
4115 if (m_timer_set_color.IsRunning()) {
4116 if (keyCode < '7') keyCode += 10;
4117 m_timer_set_color.Stop();
4118 }
4119 if (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation)
4121 break;
4122 }
4123 default: { evt.Skip(); break; }
4124 }
4125}
bool _deactivate_arrange_menu()
Definition GLCanvas3D.cpp:12756
bool handle_shortcut(const KeyChord &chord)
Definition GLCanvas3D.cpp:4127
bool _deactivate_orient_menu()
Definition GLCanvas3D.cpp:12767
void deselect_all()
Definition GLCanvas3D.cpp:3055
void set_extruder_for_selected_items(const int extruder)
Definition GUI_ObjectList.cpp:6812
static ObjectList * obj_list()
Definition GUI_Factories.cpp:405
static KeyChord from_event(const wxKeyEvent &evt)
Definition KeyChord.cpp:343
bool is_punctuation() const
Definition KeyChord.cpp:181

References _deactivate_arrange_menu(), _deactivate_orient_menu(), deselect_all(), Slic3r::GUI::KeyChord::from_event(), handle_shortcut(), m_gizmos, m_initialized, m_timer_set_color, Slic3r::GUI::GLGizmosManager::MmSegmentation, Slic3r::GUI::obj_list(), and render().

Referenced by bind_event_handlers(), Slic3r::GUI::Plater::search(), and unbind_event_handlers().

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

◆ on_fps_overlay_timer()

void Slic3r::GUI::GLCanvas3D::on_fps_overlay_timer ( wxTimerEvent & evt)
4598{
4599 m_fps_overlay_tick = true;
4601 wxWakeUpIdle();
4602}
void _set_overlay_as_dirty()
Definition GLCanvas3D.hpp:1526

References _set_overlay_as_dirty(), and m_fps_overlay_tick.

Referenced by GLCanvas3D().

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

◆ on_gesture()

void Slic3r::GUI::GLCanvas3D::on_gesture ( wxGestureEvent & evt)
4686{
4687 if (!m_initialized || !_set_current())
4688 return;
4689
4690 auto & camera = wxGetApp().plater()->get_camera();
4691 if (evt.GetEventType() == wxEVT_GESTURE_PAN) {
4692 // Orca: Gesture coordinates must use framebuffer pixels, and one stable world-space
4693 // anchor must be retained for the complete gesture to prevent perspective drift.
4694 const auto p = evt.GetPosition();
4695 auto d = static_cast<wxPanGestureEvent&>(evt).GetDelta();
4696 Vec2d screen_position(p.x, p.y);
4697 Vec2d screen_delta(d.x, d.y);
4698 apply_retina_scale(screen_position);
4699 apply_retina_scale(screen_delta);
4700 if (evt.IsGestureStart() || !m_gesture_pan_anchor.has_value())
4702 screen_position - screen_delta);
4703 pan_camera(camera, screen_delta, *m_gesture_pan_anchor);
4704 if (evt.IsGestureEnd())
4705 m_gesture_pan_anchor.reset();
4706 } else if (evt.GetEventType() == wxEVT_GESTURE_ZOOM) {
4707 static float zoom_start = 1;
4708 if (evt.IsGestureStart())
4709 zoom_start = camera.get_zoom();
4710 camera.set_zoom(zoom_start * static_cast<wxZoomGestureEvent&>(evt).GetZoomFactor());
4711 } else if (evt.GetEventType() == wxEVT_GESTURE_ROTATE) {
4712 // Orca: Rotation starts a different navigation operation, so a previous pan anchor
4713 // must not be reused; rotation and pan fallbacks share the same navigation pivot.
4714 m_gesture_pan_anchor.reset();
4715 bool rotate_limit = current_printer_technology() != ptSLA;
4716 static double last_rotate = 0;
4717 if (evt.IsGestureStart())
4718 last_rotate = 0;
4719 auto rotate = static_cast<wxRotateGestureEvent&>(evt).GetRotationAngle() - last_rotate;
4720 last_rotate += rotate;
4721 const std::optional<Vec3d> rotate_target = get_camera_orbit_target(ECameraNavigationType::Gesture);
4722 if (rotate_target.has_value())
4723 camera.rotate_on_sphere_with_target(-rotate, 0, rotate_limit, *rotate_target);
4724 else
4725 camera.rotate_on_sphere(-rotate, 0, rotate_limit);
4727 }
4728 m_dirty = true;
4729}
void apply_retina_scale(Vec2d &screen_coordinate) const
Definition GLCanvas3D.cpp:6535
Vec3d get_camera_pan_anchor(Camera &camera, ECameraNavigationType navigation_type, const Vec2d &screen_position) const
Definition GLCanvas3D.cpp:12141
std::optional< Vec3d > m_gesture_pan_anchor
Definition GLCanvas3D.hpp:657
static void pan_camera(Camera &camera, const Vec2d &screen_delta, const Vec3d &anchor)
Definition GLCanvas3D.cpp:214

References _set_current(), apply_retina_scale(), camera, current_printer_technology(), Gesture, get_camera_orbit_target(), get_camera_pan_anchor(), m_dirty, m_gesture_pan_anchor, m_initialized, Slic3r::GUI::pan_camera(), Slic3r::GUI::Camera::Perspective, and Slic3r::ptSLA.

Referenced by bind_event_handlers(), and unbind_event_handlers().

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

◆ on_idle()

void Slic3r::GUI::GLCanvas3D::on_idle ( wxIdleEvent & evt)
3986{
3988 return;
3989
3990 // Toolbar states, notifications and ImGui's own layout settling only touch the overlay.
3991 m_overlay_dirty |= m_main_toolbar.update_items_state();
3992 //BBS: GUI refactor: GLToolbar
3993 m_overlay_dirty |= m_assemble_view_toolbar.update_items_state();
3994 // BBS
3995 //m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
3997 // apply() DRAINS the 3D-mouse queue, so only the canvas actually on screen may call it: a
3998 // hidden canvas renders nothing, so the motion it swallowed moves the shared camera without
3999 // ever being drawn and the next visible frame jumps several states at once.
4000 bool mouse3d_controller_applied = _is_shown_on_screen()
4001 && wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
4002 m_dirty |= mouse3d_controller_applied;
4003 m_overlay_dirty |= wxGetApp().plater()->get_notification_manager()->update_notifications(*this);
4004 auto gizmo = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().get_current();
4005 if (gizmo != nullptr) m_dirty |= gizmo->update_items_state();
4006#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
4007 // ImGuiWrapper::m_requires_extra_frame may have been set by a render made outside of the OnIdle mechanism
4008 bool imgui_requires_extra_frame = wxGetApp().imgui()->requires_extra_frame();
4009 m_overlay_dirty |= imgui_requires_extra_frame;
4010#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
4012
4013 if (!m_dirty && !m_overlay_dirty)
4014 return;
4015
4016#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
4017 // this needs to be done here.
4018 // during the render launched by the refresh the value may be set again
4019 wxGetApp().imgui()->reset_requires_extra_frame();
4020#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
4021
4022 const int fps_cap = _get_effective_fps_cap();
4023 if (fps_cap > 0) {
4024 const auto now = std::chrono::steady_clock::now();
4025 const auto min_frame_time = std::chrono::duration<double>(1.0 / static_cast<double>(fps_cap));
4026 const auto elapsed = now - m_last_frame_start_time;
4027 if (elapsed < min_frame_time) {
4028 const int wait_ms = std::max(1, static_cast<int>(std::ceil(std::chrono::duration<double, std::milli>(min_frame_time - elapsed).count())));
4029 schedule_extra_frame(wait_ms);
4030 evt.RequestMore();
4031 return;
4032 }
4033
4034 // Pace by frame-start interval so rendering time is part of the target budget.
4036 }
4037
4038 // Read and cleared before the render; a request made during it is left for the next frame.
4039 const bool scene_dirty = m_dirty;
4040 m_dirty = false;
4041 m_overlay_dirty = false;
4042 _refresh_if_shown_on_screen(scene_dirty);
4043
4044 if (m_extra_frame_requested || mouse3d_controller_applied) {
4045 m_dirty = true;
4047 evt.RequestMore();
4048 }
4049#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
4050 else if (imgui_requires_extra_frame || wxGetApp().imgui()->requires_extra_frame()) {
4051 // ImGui settling a window or fading a tooltip.
4052 m_overlay_dirty = true;
4053 evt.RequestMore();
4054 }
4055#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
4056}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
int _get_effective_fps_cap() const
Definition GLCanvas3D.cpp:8509
void schedule_extra_frame(int milliseconds)
Definition GLCanvas3D.cpp:4604
std::chrono::time_point< std::chrono::steady_clock > m_last_frame_start_time
Definition GLCanvas3D.hpp:807
static bool has_compressed_texture_to_refresh()
Definition GLTexture.hpp:64
bool update_items_state()
Definition GLToolbar.cpp:534

References _get_effective_fps_cap(), _is_shown_on_screen(), _refresh_if_shown_on_screen(), collapse_toolbar(), count, get_camera(), Slic3r::GUI::GLTexture::Compressor::has_compressed_texture_to_refresh(), m_assemble_view_toolbar, m_benchmarking, m_dirty, m_extra_frame_requested, m_initialized, m_last_frame_start_time, m_main_toolbar, m_overlay_dirty, Slic3r::GUI::plater(), schedule_extra_frame(), and Slic3r::GUI::GLToolbar::update_items_state().

Referenced by bind_event_handlers(), and unbind_event_handlers().

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

◆ on_key()

void Slic3r::GUI::GLCanvas3D::on_key ( wxKeyEvent & evt)
4370{
4371#ifdef __APPLE__
4372 // A key the input method used for a composition must not also edit the text field: Esc would revert
4373 // it, Backspace delete a character, Enter add a line.
4374 if (evt.GetEventType() == wxEVT_KEY_DOWN && mac_ime_owns_key(m_canvas->GetHandle()))
4375 return;
4376#endif
4377
4378 auto imgui = wxGetApp().imgui();
4379 const int keyCode = evt.GetKeyCode();
4380 const bool imgui_claimed = imgui->claim_key_event(evt);
4381 if (evt.GetEventType() == wxEVT_KEY_DOWN)
4382 m_key_down = { keyCode, key_repeats(keyCode) };
4383 else if (evt.GetEventType() == wxEVT_KEY_UP)
4384 key_released(keyCode);
4385 const bool alt_wheel_released = evt.GetEventType() == wxEVT_KEY_UP && keyCode == WXK_ALT && std::exchange(m_alt_wheel_used, false);
4386
4387 // ImGui closes a popup on Esc only through keyboard navigation, which is off.
4388 if (imgui_claimed && evt.GetEventType() == wxEVT_KEY_DOWN && keyCode == WXK_ESCAPE)
4389 imgui->close_top_popup();
4390 if (imgui->update_key_data(evt) || imgui_claimed)
4391 render();
4392 if (!imgui_claimed)
4393 {
4394 // Before the gizmos and the selection, which Esc also closes.
4395 if (evt.GetEventType() == wxEVT_KEY_DOWN && keyCode == WXK_ESCAPE && std::exchange(m_section_view->panel_open, false)) {
4397 return;
4398 }
4399 if (!m_gizmos.on_key(evt)) {
4400 if (evt.GetEventType() == wxEVT_KEY_UP) {
4401 if (evt.ShiftDown() && evt.ControlDown() && keyCode == WXK_SPACE) {
4402#if !BBL_RELEASE_TO_PUBLIC
4403 wxGetApp().plater()->toggle_render_statistic_dialog();
4404 m_dirty = true;
4405#endif
4406 }
4407 else if (keyCode == WXK_SHIFT) {
4408 if (m_picking_enabled && m_rectangle_selection.is_dragging()) {
4410 m_rectangle_selection.stop_dragging();
4411 m_mouse.ignore_left_up = true;
4412 m_dirty = true;
4413 }
4414// set_cursor(Standard);
4415 }
4416 else if (keyCode == WXK_ALT) {
4417 if (m_picking_enabled && m_rectangle_selection.is_dragging()) {
4419 m_rectangle_selection.stop_dragging();
4420 m_mouse.ignore_left_up = true;
4421 m_dirty = true;
4422 }
4423// set_cursor(Standard);
4424#ifdef __WXMSW__
4426 m_camera_movement = false;
4427 m_mouse.set_start_position_3D_as_invalid();
4428 }
4429#endif
4430 }
4431 else if (keyCode == WXK_CONTROL)
4432 m_dirty = true;
4433 else if (m_selection_edit.kind != SelectionEdit::None && keyCode == m_selection_edit.key)
4435 }
4436 else if (evt.GetEventType() == wxEVT_KEY_DOWN) {
4438 return;
4439 if (keyCode == WXK_SHIFT) {
4441 apply_selection_move(true, evt.CmdDown());
4442
4443 if (m_picking_enabled /*&& (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)*/)
4444 {
4445 m_mouse.ignore_left_up = false;
4446// set_cursor(Cross);
4447 }
4448 }
4449 else if (keyCode == WXK_ALT) {
4450 if (m_picking_enabled /*&& (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports)*/)
4451 {
4452 m_mouse.ignore_left_up = false;
4453// set_cursor(Cross);
4454 }
4455 }
4456 else if (keyCode == WXK_CONTROL)
4457 m_dirty = true;
4458 }
4459 }
4460 else return;
4461 }
4462
4463 if (keyCode != WXK_TAB
4464 && keyCode != WXK_LEFT
4465 && keyCode != WXK_UP
4466 && keyCode != WXK_RIGHT
4467 && keyCode != WXK_DOWN
4468 && !alt_wheel_released) {
4469 evt.Skip(); // Needed to have EVT_CHAR generated as well
4470 }
4471}
bool m_alt_wheel_used
Definition GLCanvas3D.hpp:722
void _update_selection_from_hover()
Definition GLCanvas3D.cpp:12672
static void key_released(int key)
Definition GLCanvas3D.cpp:4356
static bool key_repeats(int key)
Definition GLCanvas3D.cpp:4349
bool mac_ime_owns_key(void *ns_view)
Definition MacIME.mm:186

References _set_overlay_as_dirty(), _update_selection_from_hover(), apply_selection_move(), finish_selection_edit(), Slic3r::GUI::KeyChord::from_event(), handle_shortcut(), Slic3r::GUI::key_released(), Slic3r::GUI::key_repeats(), m_alt_wheel_used, m_camera_movement, m_canvas, m_dirty, m_gizmos, m_is_touchpad_navigation, m_key_down, m_mouse, m_picking_enabled, m_rectangle_selection, m_section_view, m_selection_edit, Slic3r::GUI::mac_ime_owns_key(), Slic3r::GUI::GLCanvas3D::SelectionEdit::Move, Slic3r::GUI::GLCanvas3D::SelectionEdit::None, and render().

Referenced by bind_event_handlers(), release_held_modifiers(), and unbind_event_handlers().

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

◆ on_mouse()

void Slic3r::GUI::GLCanvas3D::on_mouse ( wxMouseEvent & evt)
4732{
4733 if (!m_initialized || !_set_current())
4734 return;
4735
4736 // BBS: single snapshot
4737 Plater::SingleSnapshot single(wxGetApp().plater());
4738
4739#ifdef __WXMAC__
4740 // On macOS, the mouse key state is only present for mouse btn related events such as wxEVT_LEFT_DOWN.
4741 // For other events, all buttons are reported as non-pressed, such as window leaving event. This causes
4742 // imgui stopped responding if cursor moved out of window, such as
4743 // https://github.com/OrcaSlicer/OrcaSlicer/pull/14999#issuecomment-5151344759
4744 // We solve this by correcting the state of the event from the actual mouse state querying with `wxGetMouseState()`
4745 // so it works like on other platforms.
4746 // Only fill in state the event does not carry, to preserve wx's synthetic right button for Ctrl+left.
4747 if (!evt.ButtonIsDown(wxMOUSE_BTN_ANY)) {
4748 const auto state = wxGetMouseState();
4749 evt.SetLeftDown(state.LeftIsDown());
4750 evt.SetMiddleDown(state.MiddleIsDown());
4751 evt.SetRightDown(state.RightIsDown());
4752 evt.SetAux1Down(state.Aux1IsDown());
4753 evt.SetAux2Down(state.Aux2IsDown());
4754 }
4755#endif
4756
4757#if ENABLE_RETINA_GL
4758 const float scale = m_retina_helper->get_scale_factor();
4759 evt.SetX(evt.GetX() * scale);
4760 evt.SetY(evt.GetY() * scale);
4761#endif
4762
4763 Point pos(evt.GetX(), evt.GetY());
4764
4765 ImGuiWrapper* imgui = wxGetApp().imgui();
4766 if (m_tooltip.is_in_imgui() && evt.LeftUp())
4767 // ignore left up events coming from imgui windows and not processed by them
4768 m_mouse.ignore_left_up = true;
4769 m_tooltip.set_in_imgui(false);
4770
4771 // while a non-ImGui drag is already in progress (gizmo grabber, object move, rectangle selection, layer editing),
4772 // don't let ImGui/ImGuizmo claim the event just because the cursor is hovering something like the navigator cube
4773 // that incorrectly suppresses the active drag's tooltip and can interrupt its processing. The active drag always takes priority.
4774 const bool other_drag_active = m_gizmos.is_dragging() || m_mouse.dragging || m_rectangle_selection.is_dragging() || m_layers_editing.state == LayersEditing::Editing;
4775
4776 if (imgui->update_mouse_data(evt) && !other_drag_active) {
4777 if ((evt.LeftDown() || (evt.Moving() && (evt.AltDown() || evt.ShiftDown()))) && m_canvas != nullptr)
4778 m_canvas->SetFocus();
4779 m_mouse.position = evt.Leaving() ? Vec2d(-1.0, -1.0) : pos.cast<double>();
4780 m_tooltip.set_in_imgui(true);
4781
4782 // ORCA keep tracking mouse position while drag active and cursor not in window bounds
4783 const bool imgui_dragging_active = (GImGui != nullptr && ImGui::GetIO().MouseDown[0] && GImGui->ActiveId != 0) || m_navigator_dragging;
4784 if (!has_mouse_capture() && imgui_dragging_active)
4785 m_canvas->CaptureMouse();
4786
4787 // release capture as soon as the button goes up
4788 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4790
4791 // Hovering an ImGui window only changes the overlay.
4792 const bool overlay_only = evt.Moving() && !m_mouse.dragging;
4793 // ImGui takes a press or a release only inside a frame. Motion is rendered from on_idle().
4794 if (evt.ButtonDown() || evt.ButtonUp() || evt.ButtonDClick())
4795 _render_frame(true);
4796#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
4797 printf((format_mouse_event_debug_message(evt) + " - Consumed by ImGUI\n").c_str());
4798#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
4799 if (overlay_only)
4801 else
4802 m_dirty = true;
4803 // do not return if dragging or tooltip not empty to allow for tooltip update
4804 // also, do not return if the mouse is moving and also is inside MM gizmo to allow update seed fill selection
4805 if (!m_mouse.dragging && m_tooltip.is_empty() && (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation || !evt.Moving()))
4806 return;
4807 }
4808
4809 // Design tab: the interactive sketch tool owns the mouse whenever it has
4810 // something on screen — an active session OR committed sketch overlays that the user
4811 // can click to select. It runs after ImGui (so dialogs still work) but before
4812 // camera/toolbar/gizmo handling; on_mouse returns false for events it doesn't consume
4813 // (drag/orbit/wheel) so the camera keeps working over the display-only plate.
4814#ifdef SLIC3R_CAD
4815 if (m_design_sketch_tool != nullptr && m_design_sketch_tool->has_display()) {
4816 // Except over the sidebar collapse button, which is drawn over the sketch.
4817 if (collapse_toolbar().on_mouse(evt, *this)) {
4818 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4820 m_mouse.set_start_position_3D_as_invalid();
4821 return;
4822 }
4823 if (evt.LeftDown() && m_canvas != nullptr)
4824 m_canvas->SetFocus(); // grab keyboard focus so Delete/keys reach this canvas
4825 // A Touchpad-style orbit or pan (a plain move with Alt or Shift held) is the camera's,
4826 // whatever the tool would make of the move. Only a drag consults the button mappings.
4827 const bool camera_move = evt.Moving() && (is_camera_rotate(evt, {}) || is_camera_pan(evt, {}));
4828 if (!camera_move && m_design_sketch_tool->on_mouse(evt, *this)) {
4829 m_dirty = true;
4830 render(); // force an immediate redraw so the sketch overlay updates live
4831 return;
4832 }
4833 }
4834#endif
4835
4836#ifdef __WXMSW__
4837 bool on_enter_workaround = false;
4838 if (! evt.Entering() && ! evt.Leaving() && m_mouse.position.x() == -1.0) {
4839 // Workaround for SPE-832: There seems to be a mouse event sent to the window before evt.Entering()
4840 m_mouse.position = pos.cast<double>();
4841 render();
4842#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
4843 printf((format_mouse_event_debug_message(evt) + " - OnEnter workaround\n").c_str());
4844#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
4845 on_enter_workaround = true;
4846 } else
4847#endif /* __WXMSW__ */
4848 {
4849#ifdef SLIC3R_DEBUG_MOUSE_EVENTS
4850 printf((format_mouse_event_debug_message(evt) + " - other\n").c_str());
4851#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
4852 }
4853 const int selected_object_idx = m_selection.get_object_idx();
4854 const int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
4855 const bool mouse_in_layer_editing = layer_editing_object_idx != -1 && m_layers_editing.bar_rect_contains(*this, pos(0), pos(1));
4856
4857 if (!mouse_in_layer_editing && m_main_toolbar.on_mouse(evt, *this)) {
4858 if (m_main_toolbar.is_any_item_pressed())
4859 m_gizmos.reset_all_states();
4860 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4862 m_mouse.set_start_position_3D_as_invalid();
4863 return;
4864 }
4865
4866 //BBS: GUI refactor: GLToolbar
4867 if (!mouse_in_layer_editing && m_assemble_view_toolbar.on_mouse(evt, *this)) {
4868 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4870 m_mouse.set_start_position_3D_as_invalid();
4871 return;
4872 }
4873
4874 if (!mouse_in_layer_editing && collapse_toolbar().on_mouse(evt, *this)) {
4875 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4877 m_mouse.set_start_position_3D_as_invalid();
4878 return;
4879 }
4880
4881 // BBS
4882#if 0
4883 if (wxGetApp().plater()->get_view_toolbar().on_mouse(evt, *this)) {
4884 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4886 m_mouse.set_start_position_3D_as_invalid();
4887 return;
4888 }
4889#endif
4890
4891 for (GLVolume* volume : m_volumes.volumes) {
4892 volume->force_sinking_contours = false;
4893 }
4894
4895 auto show_sinking_contours = [this]() {
4896 const Selection::IndicesList& idxs = m_selection.get_volume_idxs();
4897 for (unsigned int idx : idxs) {
4898 m_volumes.volumes[idx]->force_sinking_contours = true;
4899 }
4900 m_dirty = true;
4901 };
4902
4903 if (!mouse_in_layer_editing && m_gizmos.on_mouse(evt)) {
4904 if (m_gizmos.is_running()) {
4908 }
4909 if (wxWindow::FindFocus() != m_canvas)
4910 // Grab keyboard focus for input in gizmo dialogs.
4911 m_canvas->SetFocus();
4912
4913 if (evt.LeftDown()) {
4914 // Clear hover state in main toolbar
4915 wxMouseEvent evt2 = evt;
4916 evt2.SetEventType(wxEVT_MOTION);
4917 evt2.SetLeftDown(false);
4918 m_main_toolbar.on_mouse(evt2, *this);
4919 }
4920
4921 // ORCA keep tracking mouse position while drag active and cursor not in window bounds
4922 if (!has_mouse_capture() && evt.LeftIsDown() && m_gizmos.is_dragging())
4923 m_canvas->CaptureMouse();
4924
4925 if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
4927
4928 m_mouse.set_start_position_3D_as_invalid();
4929 m_mouse.position = pos.cast<double>();
4930
4931 // It should be detection of volume change
4932 // Not only detection of some modifiers !!!
4933 if (evt.Dragging()) {
4934 if (PartPlate *plate = wxGetApp().plater()->get_partplate_list().get_curr_plate())
4935 plate->clear_exclusion_volume_intersections();
4936 GLGizmosManager::EType c = m_gizmos.get_current_type();
4941 } else {
4942 // Orca: by-layer counterpart, for a prime tower compacted by "No sparse layers".
4948 show_sinking_contours();
4949 }
4950 }
4951 else if (evt.LeftUp() &&
4952 m_gizmos.get_current_type() == GLGizmosManager::EType::Scale &&
4953 m_gizmos.get_current()->get_state() == GLGizmoBase::EState::On) {
4954 wxGetApp().obj_list()->selection_changed();
4955 }
4956
4957 // A gizmo that acts on a click or a drag may not request a frame itself.
4958 if (!evt.Moving())
4959 m_dirty = true;
4960 return;
4961 }
4962
4963 // A click on a center of mass marker shows its details instead of selecting.
4964 if (evt.LeftDown() && !mouse_in_layer_editing && m_center_of_mass.on_left_down(*this, pos.cast<double>())) {
4965 m_mouse.ignore_left_up = true;
4966 return;
4967 }
4968
4969 bool any_gizmo_active = m_gizmos.get_current() != nullptr;
4970
4971 std::map<MouseButton, MouseAction> button_mappings;
4972 button_mappings[MouseButton::Left] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("left_mouse_drag_action").c_str()));
4973 button_mappings[MouseButton::Middle] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("middle_mouse_drag_action").c_str()));
4974 button_mappings[MouseButton::Right] = static_cast<MouseAction>(std::atoi(wxGetApp().app_config->get("right_mouse_drag_action").c_str()));
4975
4976 if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos)) {
4977 m_mouse.drag.move_requires_threshold = false;
4978 m_mouse.set_move_start_threshold_position_2D_as_invalid();
4979 }
4980
4981 if (evt.ButtonDown() && wxWindow::FindFocus() != m_canvas)
4982 // Grab keyboard focus on any mouse click event.
4983 m_canvas->SetFocus();
4984
4985 if (evt.Entering()) {
4986 // Set focus in order to remove it from sidebar fields and ensure hotkeys work
4987 if (m_canvas != nullptr) {
4988#if defined(__WXMSW__) && wxUSE_POPUPWIN
4989 // Don't steal focus when a popup window is active (e.g., search dropdown).
4990 // Stealing focus triggers MSWDismissUnfocusedPopup, closing the popup unexpectedly.
4991 if (!wxCurrentPopupWindow)
4992#endif
4993 {
4994 // Only set focus if the top level window of this canvas is active.
4995 auto p = dynamic_cast<wxWindow*>(evt.GetEventObject());
4996 while (p->GetParent())
4997 p = p->GetParent();
4998 auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
4999 //Orca: Set focus so hotkeys like 'tab' work when a notification is shown.
5000 //But don't steal focus from text input controls.
5001 wxWindow* focused = wxWindow::FindFocus();
5002 bool focus_in_text_ctrl = dynamic_cast<wxTextCtrl*>(focused) != nullptr;
5003 if (top_level_wnd != nullptr && top_level_wnd->IsActive() && !focus_in_text_ctrl)
5004 m_canvas->SetFocus();
5005 }
5006 m_mouse.position = pos.cast<double>();
5007 m_tooltip_enabled = false;
5008 // 1) forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
5009 // the context menu is shown, ensuring it to disappear if the mouse is outside any volume and to
5010 // change the volume hover state if any is under the mouse
5011 // 2) when switching between 3d view and preview the size of the canvas changes if the side panels are visible,
5012 // so forces a resize to avoid multiple renders with different sizes (seen as flickering)
5014 m_tooltip_enabled = true;
5015 }
5016 m_mouse.set_start_position_2D_as_invalid();
5017 }
5018 else if (evt.Leaving()) {
5019 // to remove hover on objects when the mouse goes out of this canvas
5020 m_mouse.position = Vec2d(-1.0, -1.0);
5021 m_dirty = true;
5022 }
5023 else if (evt.LeftDClick()) {
5024 // switch to object panel if double click on object, otherwise switch to global panel if double click on background
5025 if (selected_object_idx >= 0)
5026 post_event(SimpleEvent(EVT_GLCANVAS_SWITCH_TO_OBJECT));
5027 else
5028 post_event(SimpleEvent(EVT_GLCANVAS_SWITCH_TO_GLOBAL));
5029 }
5030 else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) {
5031 // Orca: Retain the click position even if the first motion event crosses a surface edge.
5032 m_mouse.set_start_position_2D_as_invalid();
5033 m_mouse.drag.start_position_2D = pos;
5034
5035 //BBS: add orient deactivate logic
5036 if (!m_gizmos.on_mouse(evt)) {
5038 return;
5039 }
5040
5041 // If user pressed left or right button we first check whether this happened on a volume or not.
5043 if (mouse_in_layer_editing) {
5044 // A volume is selected and the mouse is inside the layer thickness bar.
5045 // Start editing the layer height.
5048
5049 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5050 m_canvas->CaptureMouse();
5051 }
5052
5053 else {
5054 // BBS: define Alt key to enable volume selection mode
5055 m_selection.set_volume_selection_mode(evt.AltDown() ? Selection::Volume : Selection::Instance);
5056 if (evt.LeftDown() && evt.ShiftDown() && m_picking_enabled && m_layers_editing.state != LayersEditing::Editing) {
5057 if (/*m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
5058 &&*/ m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
5059 && m_gizmos.get_current_type() != GLGizmosManager::Seam
5060 && m_gizmos.get_current_type() != GLGizmosManager::Cut
5061 && m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation
5062 && m_gizmos.get_current_type() != GLGizmosManager::FuzzySkin) {
5064
5065 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5066 m_canvas->CaptureMouse();
5067
5068 m_dirty = true;
5069 }
5070 }
5071 else {
5072 // Select volume in this 3D canvas.
5073 // Don't deselect a volume if layer editing is enabled or any gizmo is active. We want the object to stay selected
5074 // during the scene manipulation.
5075
5076 if (m_picking_enabled && (m_gizmos.is_allow_multi_select_parts_or_objects() || !evt.CmdDown()) && (!m_hover_volume_idxs.empty())) {
5077 if (evt.LeftDown() && !m_hover_volume_idxs.empty()) {
5078 int volume_idx = get_first_hover_volume_idx();
5079 bool already_selected = m_selection.contains_volume(volume_idx);
5080 bool ctrl_down = evt.CmdDown();
5081 bool alt_down = evt.AltDown();
5082 Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
5083
5084 if (already_selected && ctrl_down)
5085 m_selection.remove(volume_idx);
5086 else if (alt_down && m_gizmos.is_allow_multi_select_parts_or_objects() && m_selection.get_mode() == Selection::Volume &&
5087 m_selection.get_object_idx() == m_volumes.volumes[volume_idx]->object_idx() &&
5088 m_selection.get_instance_idx() == m_volumes.volumes[volume_idx]->instance_idx()) {
5089 // Alt+click on another part of the selected parts' instance adds it, and on a selected
5090 // part removes it, unless it is the only one.
5091 if (!already_selected)
5092 m_selection.add_volumes(Selection::Volume, {(unsigned int) volume_idx}, false);
5093 else if (curr_idxs.size() > 1)
5094 m_selection.remove_volumes(Selection::Volume, {(unsigned int) volume_idx});
5095 }
5096 else if (alt_down) {
5097 // Select just the clicked part, also when an object is selected.
5099 if (already_selected) {
5100 std::vector<unsigned int> volume_idxs;
5101 for (auto idx : curr_idxs) { volume_idxs.emplace_back(idx); }
5102 m_selection.remove_volumes(mode, volume_idxs);
5103 }
5104 std::vector<unsigned int> add_volume_idxs;
5105 add_volume_idxs.emplace_back(volume_idx);
5106 m_selection.add_volumes(mode, add_volume_idxs, true);
5107 }
5108 else {
5109 m_selection.add(volume_idx, !ctrl_down, true);
5110 m_mouse.drag.move_requires_threshold = !already_selected;
5111 if (already_selected)
5112 m_mouse.set_move_start_threshold_position_2D_as_invalid();
5113 else
5114 m_mouse.drag.move_start_threshold_position_2D = pos;
5115 }
5116
5117 // propagate event through callback
5118 if (curr_idxs != m_selection.get_volume_idxs()) {
5119 if (m_selection.is_empty())
5120 m_gizmos.reset_all_states();
5121 else
5122 m_gizmos.refresh_on_off_state();
5123
5124 m_gizmos.update_data();
5125 post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
5126 m_dirty = true;
5127 }
5128 }
5129 }
5130
5131 if (!m_hover_volume_idxs.empty()) {
5132 if (evt.LeftDown() && m_moving_enabled && m_mouse.drag.move_volume_idx == -1) {
5133 // Only accept the initial position, if it is inside the volume bounding box.
5134 int volume_idx = get_first_hover_volume_idx();
5135 BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box();
5136 volume_bbox.offset(1.0);
5137 const bool is_cut_connector_selected = m_selection.is_any_connector();
5138 const Vec3d scene_position = _mouse_to_3d(pos);
5139 if ((!any_gizmo_active || !evt.CmdDown()) && volume_bbox.contains(scene_position) && !is_cut_connector_selected) {
5140 m_volumes.volumes[volume_idx]->hover = GLVolume::HS_None;
5141 // The dragging operation is initiated.
5142 m_mouse.drag.move_volume_idx = volume_idx;
5143 m_selection.setup_cache();
5144 m_mouse.drag.start_position_3D = scene_position;
5146 m_moving = true;
5147
5148 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5149 m_canvas->CaptureMouse();
5150 }
5151 }
5152 }
5153 }
5154 }
5155 }
5156 else if (evt.Dragging() && evt.LeftIsDown() && m_mouse.drag.move_volume_idx != -1 && m_layers_editing.state == LayersEditing::Unknown) {
5158
5159 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5160 m_canvas->CaptureMouse();
5161
5162 if (!m_mouse.drag.move_requires_threshold) {
5163 m_mouse.dragging = true;
5164 if (PartPlate *plate = wxGetApp().plater()->get_partplate_list().get_curr_plate())
5165 plate->clear_exclusion_volume_intersections();
5166 Vec3d cur_pos = m_mouse.drag.start_position_3D;
5167 // we do not want to translate objects if the user just clicked on an object while pressing shift to remove it from the selection and then drag
5168 if (m_selection.contains_volume(get_first_hover_volume_idx())) {
5169 const Camera& camera = wxGetApp().plater()->get_camera();
5170 if (std::abs(camera.get_dir_forward()(2)) < EPSILON) {
5171 // side view -> move selected volumes orthogonally to camera view direction
5172 Linef3 ray = mouse_ray(pos);
5173 Vec3d dir = ray.unit_vector();
5174 // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
5175 // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
5176 // in our case plane normal and ray direction are the same (orthogonal view)
5177 // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
5178 Vec3d inters = ray.a + (m_mouse.drag.start_position_3D - ray.a).dot(dir) / dir.squaredNorm() * dir;
5179 // vector from the starting position to the found intersection
5180 Vec3d inters_vec = inters - m_mouse.drag.start_position_3D;
5181
5182 Vec3d camera_right = camera.get_dir_right();
5183 Vec3d camera_up = camera.get_dir_up();
5184
5185 // finds projection of the vector along the camera axes
5186 double projection_x = inters_vec.dot(camera_right);
5187 double projection_z = inters_vec.dot(camera_up);
5188
5189 // apply offset
5190 cur_pos = m_mouse.drag.start_position_3D + projection_x * camera_right + projection_z * camera_up;
5191 }
5192 else {
5193 // Generic view
5194 // Get new position at the same Z of the initial click point.
5195 float z0 = 0.0f;
5196 float z1 = 1.0f;
5197 cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2));
5198 }
5199 }
5200
5201 TransformationType trafo_type;
5202 trafo_type.set_relative();
5203 m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type);
5204 // Ghost transforms refresh from _render_imex_ghosts via the live GLVolume
5205 // lookup, so no explicit update call is needed here.
5209 else
5211 }
5212 // BBS
5213 //wxGetApp().obj_manipul()->set_dirty();
5214 m_dirty = true;
5215 }
5216 }
5217 }
5218 else if (evt.Dragging() && evt.LeftIsDown() && m_picking_enabled && m_rectangle_selection.is_dragging()) {
5219 //BBS not in assemble view
5221
5222 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5223 m_canvas->CaptureMouse();
5224
5225 m_rectangle_selection.dragging(pos.cast<double>());
5226 m_dirty = true;
5227 }
5228 }
5229 else if (evt.Dragging() || is_camera_rotate(evt, button_mappings) || is_camera_pan(evt, button_mappings)) {
5230 m_mouse.dragging = true;
5231
5232 if (m_layers_editing.state != LayersEditing::Unknown && layer_editing_object_idx != -1) {
5234 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5235 m_canvas->CaptureMouse();
5236
5238 m_mouse.position = pos.cast<double>();
5239 }
5240 }
5241 // do not process the dragging if the left mouse was set down in another canvas
5242 else if (is_camera_rotate(evt, button_mappings)) {
5243 // Orca: Rotation and panning use different drag coordinates and cached anchors.
5244 // Clear the pan state before processing rotation or switching buttons mid-drag.
5245 m_mouse.set_start_position_2D_as_invalid();
5246
5247 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5248 m_canvas->CaptureMouse();
5249
5250 // Orca: Sphere rotation for painting view
5251 // if dragging over blank area with left button or other button mapped to rotate, then rotate
5252 bool middle_or_right_button_used_as_rotate = (evt.MiddleIsDown() && button_mappings[MouseButton::Middle] == MouseAction::Rotation) ||
5253 (evt.RightIsDown() && button_mappings[MouseButton::Right] == MouseAction::Rotation);
5254 if ((any_gizmo_active || middle_or_right_button_used_as_rotate || m_hover_volume_idxs.empty()) &&
5255 m_mouse.is_start_position_3D_defined()) {
5256 Camera& camera = wxGetApp().plater()->get_camera();
5257 auto mult_pref = wxGetApp().app_config->get("camera_orbit_mult");
5258 const double mult = mult_pref.empty() ? 1.0 : std::stod(mult_pref);
5259 const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.) * mult;
5261 m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmSegmentation ||
5262 m_gizmos.get_current_type() == GLGizmosManager::FuzzySkin) {
5263 // Orca: Reuse the centralized pivot policy for scene-oriented tools.
5264 const std::optional<Vec3d> rotate_target = get_camera_orbit_target(ECameraNavigationType::Mouse);
5265 if (rotate_target.has_value())
5266 camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, *rotate_target);
5267 else
5268 camera.rotate_on_sphere(rot.x(), rot.y(), false);
5269 }
5270 else {
5271 if (wxGetApp().app_config->get_bool("use_free_camera"))
5272 // Virtual track ball (similar to the 3DConnexion mouse).
5273 camera.rotate_local_around_target(Vec3d(rot.y(), rot.x(), 0.));
5274 else {
5275 // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
5276 // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
5277 // which checks an atomics (flushes CPU caches).
5278 // See GH issue #3816.
5279 bool rotate_limit = current_printer_technology() != ptSLA;
5280
5281 camera.recover_from_free_camera();
5282 if (evt.ControlDown() || evt.CmdDown()) {
5283 if ((m_rotation_center.x() == 0.f) && (m_rotation_center.y() == 0.f) && (m_rotation_center.z() == 0.f)) {
5284 auto canvas_w = float(get_canvas_size().get_width());
5285 auto canvas_h = float(get_canvas_size().get_height());
5286 Point screen_center(canvas_w/2, canvas_h/2);
5287 m_rotation_center = _mouse_to_3d(screen_center);
5288 m_rotation_center(2) = 0.f;
5289 }
5290 camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, m_rotation_center);
5291 } else {
5292 // Orca: Keep regular mouse orbit and perspective-pan fallback centered
5293 // on the same selection, active-plate, or scene reference.
5294 const std::optional<Vec3d> rotate_target = get_camera_orbit_target(ECameraNavigationType::Mouse);
5295 if (rotate_target.has_value())
5296 camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, *rotate_target);
5297 else
5298 camera.rotate_on_sphere(rot.x(), rot.y(), rotate_limit);
5299 }
5300 }
5301 }
5302
5304 m_dirty = true;
5305 m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
5306 }
5307
5308 m_camera_movement = true;
5309 m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
5310 }
5311 else if (is_camera_pan(evt, button_mappings)) {
5312 // Orca: Pan uses screen coordinates and must not inherit the rotation start point.
5313 m_mouse.set_start_position_3D_as_invalid();
5314
5315 if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
5316 m_canvas->CaptureMouse();
5317
5318 // if dragging with right button or if button functions swapped and dragging with left button over blank area then pan
5319 if (m_mouse.is_start_position_2D_defined()) {
5320 Camera& camera = wxGetApp().plater()->get_camera();
5322 // Orca: Use a constrained camera when navigating the 3D scene with a regular mouse, if the free camera is not selected
5323 if (!wxGetApp().app_config->get_bool("use_free_camera"))
5324 // Forces camera right vector to be parallel to XY plane in case it has been misaligned using the 3D mouse free rotation.
5325 // It is cheaper to call this function right away instead of testing wxGetApp().plater()->get_mouse3d_controller().connected(),
5326 // which checks an atomics (flushes CPU caches).
5327 // See GH issue #3816.
5328 camera.recover_from_free_camera();
5329 }
5330
5331 // Orca: Cache the surface under the initial click and apply every incremental
5332 // cursor delta at that depth, so perspective zoom and camera angle stay exact.
5333 const Vec2d screen_delta =
5334 pos.cast<double>() - m_mouse.drag.start_position_2D.cast<double>();
5335 if (!m_mouse.drag.camera_pan_anchor.has_value())
5337 m_mouse.drag.start_position_2D.cast<double>());
5338 pan_camera(camera, screen_delta, *m_mouse.drag.camera_pan_anchor);
5339 m_dirty = true;
5340 m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
5341 }
5342
5343 m_camera_movement = true;
5344 m_mouse.drag.start_position_2D = pos;
5345 }
5346 }
5347 else if ((evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) ||
5348 (m_camera_movement && !is_camera_rotate(evt, button_mappings) && !is_camera_pan(evt, button_mappings))) {
5349 m_mouse.position = pos.cast<double>();
5350
5351 // Check if the button that was released is mapped to rotation
5352 if ((evt.LeftUp() && button_mappings[MouseButton::Left] == MouseAction::Rotation) ||
5353 (evt.MiddleUp() && button_mappings[MouseButton::Middle] == MouseAction::Rotation) ||
5354 (evt.RightUp() && button_mappings[MouseButton::Right] == MouseAction::Rotation)) {
5356 }
5357
5360 _stop_timer();
5361 m_layers_editing.accept_changes(*this);
5362 }
5363 else if (m_mouse.drag.move_volume_idx != -1 && m_mouse.dragging) {
5364 do_move(L("Move object"));
5365 // BBS
5366 //wxGetApp().obj_manipul()->set_dirty();
5367 // Let the plater know that the dragging finished, so a delayed refresh
5368 // of the scene with the background processing data should be performed.
5369 post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
5370 }
5371 else if (evt.LeftUp() && m_picking_enabled && m_rectangle_selection.is_dragging() && m_layers_editing.state != LayersEditing::Editing) {
5372 //BBS: don't use alt as de-select
5373 //if (evt.ShiftDown() || evt.AltDown())
5374 if (evt.ShiftDown())
5376
5377 m_rectangle_selection.stop_dragging();
5378 }
5379 else if (evt.LeftUp() && !m_mouse.dragging && m_hover_ghost_head >= 0) {
5380 // IMEX ghost click: dispatch to Plater (filament picker). The else-if chain
5381 // already prevents deselect/plate-select from firing on the same event; we
5382 // fall through to mouse_up_cleanup() below so mouse capture and drag state
5383 // get reset like every other branch in this chain.
5384 wxGetApp().plater()->on_imex_ghost_click(m_hover_ghost_head);
5385 }
5386 else if (evt.LeftUp() && !m_mouse.ignore_left_up && !m_mouse.dragging && m_hover_volume_idxs.empty() && m_hover_plate_idxs.empty() && !is_layers_editing_enabled()) {
5387 // deselect and propagate event through callback
5388 if (!evt.ShiftDown() && (!any_gizmo_active || !evt.CmdDown()) && m_picking_enabled)
5389 deselect_all();
5390 }
5391 //BBS Select plate in this 3D canvas.
5392 // The left up may come from an ImGui window (e.g. a drag started on the gizmo floating window and released over the bed),
5393 // in which case it must not be treated as a click on the plate, otherwise the gizmo would be closed (see deselect_all below).
5394 else if (evt.LeftUp() && !m_mouse.ignore_left_up && !m_mouse.dragging && m_picking_enabled && !m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !is_layers_editing_enabled())
5395 {
5396 int hover_idx = m_hover_plate_idxs.front();
5397 wxGetApp().plater()->select_plate_by_hover_id(hover_idx);
5398 //wxGetApp().plater()->get_partplate_list().select_plate_view();
5399 //deselect all the objects
5400 if (m_gizmos.get_current_type() != GLGizmosManager::MeshBoolean && m_hover_volume_idxs.empty())
5401 deselect_all();
5402 }
5403 else if (evt.RightUp() && !is_layers_editing_enabled()) {
5404 // forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
5405 // the context menu is already shown
5406 render();
5407 if (!m_hover_volume_idxs.empty()) {
5408 // if right clicking on volume, propagate event through callback (shows context menu)
5409 int volume_idx = get_first_hover_volume_idx();
5410 if (!m_volumes.volumes[volume_idx]->is_wipe_tower // no context menu for the wipe tower
5411 /*&& m_gizmos.get_current_type() != GLGizmosManager::SlaSupports*/) // disable context menu when the gizmo is open
5412 {
5413 // forces the selection of the volume
5414 /* m_selection.add(volume_idx); // #et_FIXME_if_needed
5415 * To avoid extra "Add-Selection" snapshots,
5416 * call add() with check_for_already_contained=true
5417 * */
5418 m_selection.add(volume_idx, true, true);
5419 m_gizmos.refresh_on_off_state();
5420 post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
5421 m_gizmos.update_data();
5422 // BBS
5423 //wxGetApp().obj_manipul()->set_dirty();
5424 // forces a frame render to update the view before the context menu is shown
5425 render();
5426 }
5427 }
5428
5429 //BBS change plate selection
5430 bool plate_icon_popup_shown = false;
5431 if (!m_hover_plate_idxs.empty() && (m_canvas_type == CanvasView3D) && !m_mouse.dragging) {
5432 int hover_idx = m_hover_plate_idxs.front();
5433 plate_icon_popup_shown = (wxGetApp().plater()->select_plate_by_hover_id(hover_idx, true) == 1);
5434 if (m_hover_volume_idxs.empty())
5435 deselect_all();
5436 render();
5437 }
5438
5439 //ORCA allow right click on empty space while an object selected
5440 if (m_hover_plate_idxs.empty() && m_hover_volume_idxs.empty() && (m_canvas_type == CanvasView3D) && !m_mouse.dragging) {
5441 deselect_all();
5442 render();
5443 }
5444
5445 Vec2d logical_pos = pos.cast<double>();
5446#if ENABLE_RETINA_GL
5447 const float factor = m_retina_helper->get_scale_factor();
5448 logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor));
5449#endif // ENABLE_RETINA_GL
5450
5451 if (!m_mouse.ignore_right_up && m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined) {
5452 //BBS post right click event
5453 if (!m_hover_plate_idxs.empty() && !plate_icon_popup_shown) {
5454 post_event(RBtnPlateEvent(EVT_GLCANVAS_PLATE_RIGHT_CLICK, { logical_pos, m_hover_plate_idxs.front() }));
5455 }
5456 else if (!plate_icon_popup_shown) {
5457 // do not post the event if the user is panning the scene
5458 // or if right click was done over the wipe tower
5459 bool post_right_click_event = m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower;
5460 if (post_right_click_event)
5461 post_event(RBtnEvent(EVT_GLCANVAS_RIGHT_CLICK, { logical_pos, m_hover_volume_idxs.empty() }));
5462 }
5463 }
5464 }
5465
5467 }
5468 else if (evt.Moving()) {
5469 m_mouse.position = pos.cast<double>();
5470
5471 // updates gizmos overlay
5472 if (m_selection.is_empty())
5473 m_gizmos.reset_all_states();
5474
5476 }
5477 else
5478 evt.Skip();
5479
5480 // Detection of doubleclick on text to open emboss edit window
5481 auto type = m_gizmos.get_current_type();
5482 if (evt.LeftDClick() && !m_hover_volume_idxs.empty() &&
5488 type == GLGizmosManager::EType::Svg) ) {
5489 for (int hover_volume_id : m_hover_volume_idxs) {
5490 const GLVolume &hover_gl_volume = *m_volumes.volumes[hover_volume_id];
5491 int object_idx = hover_gl_volume.object_idx();
5492 if (object_idx < 0 || static_cast<size_t>(object_idx) >= m_model->objects.size()) continue;
5493 const ModelObject* hover_object = m_model->objects[object_idx];
5494 int hover_volume_idx = hover_gl_volume.volume_idx();
5495 if (hover_volume_idx < 0 || static_cast<size_t>(hover_volume_idx) >= hover_object->volumes.size()) continue;
5496 const ModelVolume* hover_volume = hover_object->volumes[hover_volume_idx];
5497
5498 if (hover_volume->text_configuration.has_value()) {
5499 m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
5502 wxGetApp().obj_list()->update_selections();
5503 return;
5504 } else if (hover_volume->emboss_shape.has_value()) {
5505 m_selection.add_volumes(Selection::EMode::Volume, {(unsigned) hover_volume_id});
5506 if (type != GLGizmosManager::EType::Svg)
5508 wxGetApp().obj_list()->update_selections();
5509 return;
5510 }
5511 }
5512 }
5513
5514 if (m_moving)
5515 show_sinking_contours();
5516
5517#ifdef __WXMSW__
5518 if (on_enter_workaround)
5519 m_mouse.position = Vec2d(-1., -1.);
5520#endif /* __WXMSW__ */
5521}
static constexpr const float TRACKBALLSIZE
Definition GLCanvas3D.cpp:192
@ Unknown
Definition GLCanvas3D.hpp:252
bool m_sequential_print_clearance_first_displacement
Definition GLCanvas3D.hpp:878
void _perform_layer_editing_action(wxMouseEvent *evt=nullptr)
Definition GLCanvas3D.cpp:11997
bool _deactivate_layersediting_menu()
Definition GLCanvas3D.cpp:12778
bool is_camera_pan(const wxMouseEvent &evt, const std::map< MouseButton, MouseAction > &mappings) const
Definition GLCanvas3D.cpp:5586
@ Mouse
Definition GLCanvas3D.hpp:1618
void update_sequential_clearance()
Definition GLCanvas3D.cpp:6403
void update_compacted_wipe_tower_clearance()
Definition GLCanvas3D.cpp:6315
void _stop_timer()
Definition GLCanvas3D.hpp:1635
int get_first_hover_volume_idx() const
Definition GLCanvas3D.hpp:1333
bool is_camera_rotate(const wxMouseEvent &evt, const std::map< MouseButton, MouseAction > &mappings) const
Definition GLCanvas3D.cpp:5577
MouseAction
Definition GLCanvas3D.hpp:1299
void mouse_up_cleanup()
Definition GLCanvas3D.cpp:6274
Vec3d m_rotation_center
Definition GLCanvas3D.hpp:792
@ On
Definition GLGizmoBase.hpp:128
@ MeshBoolean
Definition GLGizmosManager.hpp:93
@ Emboss
Definition GLGizmosManager.hpp:99
@ Svg
Definition GLGizmosManager.hpp:100
@ Cut
Definition GLGizmosManager.hpp:92
@ Deselect
Definition GLSelectionRectangle.hpp:21
std::set< unsigned int > IndicesList
Definition Selection.hpp:49
wxMouseEvent
Definition CameraPopup.cpp:47
Event< std::pair< Vec2d, int > > RBtnPlateEvent
Definition GLCanvas3D.hpp:192
Event< std::pair< Vec2d, bool > > RBtnEvent
Definition GLCanvas3D.hpp:191
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References _deactivate_arrange_menu(), _deactivate_layersediting_menu(), _deactivate_orient_menu(), _mouse_to_3d(), _perform_layer_editing_action(), _refresh_if_shown_on_screen(), _render_frame(), _set_current(), _set_overlay_as_dirty(), _stop_timer(), _update_selection_from_hover(), Slic3r::Linef3::a, Slic3r::ByObject, camera, can_sequential_clearance_show_in_gizmo(), CanvasAssembleView, CanvasView3D, collapse_toolbar(), Slic3r::BoundingBox3Base< PointType >::contains(), current_printer_technology(), Slic3r::GUI::GLGizmosManager::Cut, Slic3r::GUI::GLSelectionRectangle::Deselect, deselect_all(), do_move(), Slic3r::dot(), Slic3r::GUI::GLCanvas3D::LayersEditing::Editing, Slic3r::GUI::GLGizmosManager::Emboss, Slic3r::ModelVolume::emboss_shape, EPSILON, Slic3r::GUI::GLGizmosManager::FdmSupports, fff_print(), Slic3r::GUI::GLGizmosManager::FuzzySkin, get_camera_orbit_target(), get_camera_pan_anchor(), get_canvas_size(), get_first_hover_volume_idx(), has_mouse_capture(), Slic3r::GLVolume::HS_None, Slic3r::GUI::Selection::Instance, Slic3r::Linef3::intersect_plane(), is_camera_pan(), is_camera_rotate(), is_layers_editing_enabled(), L, Left, m_assemble_view_toolbar, m_camera_movement, m_canvas, m_canvas_type, m_center_of_mass, m_dirty, m_gizmos, m_hover_ghost_head, m_hover_plate_idxs, m_hover_volume_idxs, m_initialized, m_layers_editing, m_main_toolbar, m_model, m_mouse, m_moving, m_moving_enabled, m_navigator_dragging, m_picking_enabled, m_rectangle_selection, m_rotation_center, m_selection, m_sequential_print_clearance_first_displacement, m_tooltip, m_tooltip_enabled, m_volumes, Slic3r::GUI::GLGizmosManager::MeshBoolean, Middle, Slic3r::GUI::GLGizmosManager::MmSegmentation, Mouse, mouse_ray(), mouse_up_cleanup(), Slic3r::GUI::GLGizmosManager::Move, Slic3r::GLVolume::object_idx(), Slic3r::BoundingBox3Base< PointType >::offset(), Slic3r::GUI::GLGizmoBase::On, on_mouse(), Slic3r::GUI::pan_camera(), Slic3r::GUI::Camera::Perspective, PI, Slic3r::GUI::plater(), post_event(), Slic3r::print_sequence(), Slic3r::ptFFF, Slic3r::ptSLA, render(), Right, Slic3r::GUI::GLGizmosManager::Rotate, Rotation, Slic3r::GUI::GLGizmosManager::Scale, scale(), Slic3r::GUI::GLGizmosManager::Seam, Slic3r::GUI::GLSelectionRectangle::Select, Slic3r::GUI::TransformationType::set_relative(), Slic3r::GUI::GLGizmosManager::Svg, Slic3r::ModelVolume::text_configuration, TRACKBALLSIZE, Slic3r::GUI::GLGizmosManager::Undefined, Slic3r::Linef3::unit_vector(), Slic3r::GUI::GLCanvas3D::LayersEditing::Unknown, update_compacted_wipe_tower_clearance(), Slic3r::GUI::ImGuiWrapper::update_mouse_data(), update_sequential_clearance(), Slic3r::GUI::Selection::Volume, Slic3r::GLVolume::volume_idx(), Slic3r::ModelObject::volumes, and Slic3r::GUI::wxMouseEvent.

Referenced by bind_event_handlers(), Slic3r::GUI::anonymous_namespace{Plater.cpp}::emboss_svg(), on_mouse(), and unbind_event_handlers().

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

◆ on_mouse_wheel()

void Slic3r::GUI::GLCanvas3D::on_mouse_wheel ( wxMouseEvent & evt)
4474{
4475#ifdef WIN32
4476 // Try to filter out spurious mouse wheel events comming from 3D mouse.
4477 if (wxGetApp().plater()->get_mouse3d_controller().process_mouse_wheel())
4478 return;
4479#endif
4480
4481 if (!m_initialized)
4482 return;
4483
4484 // Ignore the wheel events if the middle button is pressed.
4485 if (evt.MiddleIsDown())
4486 return;
4487
4488 m_alt_wheel_used |= evt.AltDown();
4489
4490#if ENABLE_RETINA_GL
4491 const float scale = m_retina_helper->get_scale_factor();
4492 evt.SetX(evt.GetX() * scale);
4493 evt.SetY(evt.GetY() * scale);
4494#endif
4495
4496 if (wxGetApp().imgui()->update_mouse_data(evt)) {
4498 IMSlider* m_layers_slider = get_gcode_viewer().get_layers_slider();
4499 IMSlider* m_moves_slider = get_gcode_viewer().get_moves_slider();
4500 m_layers_slider->on_mouse_wheel(evt);
4501 m_moves_slider->on_mouse_wheel(evt);
4502 }
4503 render();
4504 m_dirty = true;
4505 return;
4506 }
4507
4508#ifdef __WXMSW__
4509 // For some reason the Idle event is not being generated after the mouse scroll event in case of scrolling with the two fingers on the touch pad,
4510 // if the event is not allowed to be passed further.
4511 // evt.Skip() used to trigger the needed screen refresh, but it does no more. wxWakeUpIdle() seem to work now.
4512 wxWakeUpIdle();
4513#endif /* __WXMSW__ */
4514
4515 // Performs layers editing updates, if enabled
4517 int object_idx_selected = m_selection.get_object_idx();
4518 if (object_idx_selected != -1) {
4519 // A volume is selected. Test, whether hovering over a layer thickness bar.
4520 if (m_layers_editing.bar_rect_contains(*this, (float)evt.GetX(), (float)evt.GetY())) {
4521 // Adjust the width of the selection.
4522 m_layers_editing.band_width = std::max(std::min(m_layers_editing.band_width * (1.0f + 0.1f * (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta()), 10.0f), 1.5f);
4523 if (m_canvas != nullptr)
4524 m_canvas->Refresh();
4525
4526 return;
4527 }
4528 }
4529 }
4530
4531 // Inform gizmos about the event so they have the opportunity to react.
4532 if (m_gizmos.on_mouse_wheel(evt))
4533 return;
4534
4535 if (evt.AltDown()) {
4536 set_section_view_ratio(get_section_view_ratio() + (evt.GetWheelRotation() < 0 ? -0.01 : 0.01));
4537 return;
4538 }
4539
4540 if (m_canvas_type == CanvasAssembleView && evt.CmdDown()) {
4541 float rotation = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta();
4542 m_explosion_ratio = rotation < 0.f
4543 ? std::max(1., m_explosion_ratio - 0.01)
4544 : std::min(3., m_explosion_ratio + 0.01);
4546 for (GLVolume* volume : m_volumes.volumes) {
4547 volume->set_bounding_boxes_as_dirty();
4548 }
4550 }
4551 return;
4552 }
4553 // Calculate the zoom delta and apply it to the current zoom factor
4554 double direction_factor = wxGetApp().app_config->get_bool("reverse_mouse_wheel_zoom") ? -1.0 : 1.0;
4555 auto delta = direction_factor * (double)evt.GetWheelRotation() / (double)evt.GetWheelDelta();
4556 bool zoom_to_mouse = wxGetApp().app_config->get("zoom_to_mouse") == "true";
4557 if (!zoom_to_mouse) {// zoom to center
4558 _update_camera_zoom(delta);
4559 }
4560 else {
4561 auto cnv_size = get_canvas_size();
4562 float z{0.f};
4563 auto screen_center_3d_pos = _mouse_to_3d({ cnv_size.get_width() * 0.5, cnv_size.get_height() * 0.5 }, &z);
4564 auto mouse_3d_pos = _mouse_to_3d({evt.GetX(), evt.GetY()}, &z);
4565 Vec3d displacement = mouse_3d_pos - screen_center_3d_pos;
4566
4567 wxGetApp().plater()->get_camera().translate(displacement);
4568 auto origin_zoom = wxGetApp().plater()->get_camera().get_zoom();
4569 _update_camera_zoom(delta);
4570 auto new_zoom = wxGetApp().plater()->get_camera().get_zoom();
4571 wxGetApp().plater()->get_camera().translate((-displacement) / (new_zoom / origin_zoom));
4572 }
4573}
void on_mouse_wheel(wxMouseEvent &evt)
Definition IMSlider.cpp:1645
static void process_mouse_wheel(int &mouse_wheel)
Definition ImGuiWrapper.cpp:1441

References _mouse_to_3d(), _update_camera_zoom(), CanvasAssembleView, CanvasPreview, Slic3r::GLVolume::explosion_ratio, get_canvas_size(), get_gcode_viewer(), Slic3r::GUI::GCodeViewer::get_layers_slider(), Slic3r::GUI::GCodeViewer::get_moves_slider(), get_section_view_ratio(), is_layers_editing_enabled(), m_alt_wheel_used, m_canvas, m_canvas_type, m_dirty, m_explosion_ratio, m_gizmos, m_initialized, m_layers_editing, m_selection, m_volumes, Slic3r::GUI::IMSlider::on_mouse_wheel(), Slic3r::GUI::plater(), Slic3r::GUI::process_mouse_wheel(), render(), scale(), Slic3r::GLVolume::set_bounding_boxes_as_dirty(), set_section_view_ratio(), and Slic3r::GUI::wxMouseEvent.

Referenced by bind_event_handlers(), and unbind_event_handlers().

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

◆ on_paint()

void Slic3r::GUI::GLCanvas3D::on_paint ( wxPaintEvent & evt)
5524{
5525 m_presented_signature.reset();
5526 if (m_initialized) {
5527#ifdef __WXMSW__
5528 // Idle events are not dispatched during the Windows resize modal loop,
5529 // so render immediately to avoid blank frames.
5531 m_dirty = false;
5532#else
5533 m_dirty = true;
5534#endif
5535 } else {
5536 // Call render directly, so it gets initialized immediately, not from On Idle handler.
5537 this->render();
5538 }
5539}

References _refresh_if_shown_on_screen(), m_dirty, m_initialized, m_presented_signature, and render().

Referenced by bind_event_handlers(), and unbind_event_handlers().

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

◆ on_render_timer()

void Slic3r::GUI::GLCanvas3D::on_render_timer ( wxTimerEvent & evt)
4582{
4583 // no need to wake up idle
4584 // right after this event, idle event is fired
4585 // m_dirty = true;
4586 // wxWakeUpIdle();
4587}

Referenced by bind_event_handlers(), and unbind_event_handlers().

Here is the caller graph for this function:

◆ on_set_color_timer()

void Slic3r::GUI::GLCanvas3D::on_set_color_timer ( wxTimerEvent & evt)
4590{
4591 auto obj_list = wxGetApp().obj_list();
4592 if (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation)
4594 m_timer_set_color.Stop();
4595}

References m_gizmos, m_timer_set_color, Slic3r::GUI::GLGizmosManager::MmSegmentation, and Slic3r::GUI::obj_list().

Referenced by GLCanvas3D().

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

◆ on_set_focus()

void Slic3r::GUI::GLCanvas3D::on_set_focus ( wxFocusEvent & evt)
5546{
5547#ifdef __APPLE__
5548 // The focused canvas is the one whose view takes input-method text (see ImGuiWrapper::end_frame()).
5549 ImGui::GetIO().ImeWindowHandle = m_canvas->GetHandle();
5550#endif
5551 m_tooltip_enabled = false;
5553 m_tooltip_enabled = true;
5554 m_is_touchpad_navigation = wxGetApp().app_config->get_bool("camera_navigation_style");
5555}

References _refresh_if_shown_on_screen(), m_canvas, m_is_touchpad_navigation, and m_tooltip_enabled.

Referenced by bind_event_handlers(), and unbind_event_handlers().

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

◆ on_size()

void Slic3r::GUI::GLCanvas3D::on_size ( wxSizeEvent & evt)
inline
1274{ m_dirty = true; }

References m_dirty.

Referenced by bind_event_handlers(), and unbind_event_handlers().

Here is the caller graph for this function:

◆ on_timer()

void Slic3r::GUI::GLCanvas3D::on_timer ( wxTimerEvent & evt)

References _perform_layer_editing_action(), Slic3r::GUI::GLCanvas3D::LayersEditing::Editing, and m_layers_editing.

Referenced by bind_event_handlers(), and unbind_event_handlers().

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

◆ plate_scene_bounding_box()

BoundingBoxf3 Slic3r::GUI::GLCanvas3D::plate_scene_bounding_box ( int plate_idx) const
2255{
2256 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
2257
2258 BoundingBoxf3 bb = plate->get_bounding_box(true);
2259 if (m_config != nullptr) {
2260 double h = m_config->opt_float("printable_height");
2261 bb.min(2) = std::min(bb.min(2), -h);
2262 bb.max(2) = std::max(bb.max(2), h);
2263 }
2264
2265 return bb;
2266}

References Slic3r::GUI::PartPlate::get_bounding_box(), m_config, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, and Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min.

Here is the call graph for this function:

◆ plates_count_changed()

void Slic3r::GUI::GLCanvas3D::plates_count_changed ( )
2189{
2191 m_dirty = true;
2192}

References m_dirty, and refresh_camera_scene_box().

Here is the call graph for this function:

◆ post_event()

◆ refresh_camera_scene_box()

void Slic3r::GUI::GLCanvas3D::refresh_camera_scene_box ( )
2205{
2206 wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box());
2207}
BoundingBoxf3 scene_bounding_box() const
Definition GLCanvas3D.cpp:2236

References scene_bounding_box().

Referenced by bed_shape_changed(), finish_selection_edit(), plates_count_changed(), and reload_scene().

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

◆ release_held_modifiers()

void Slic3r::GUI::GLCanvas3D::release_held_modifiers ( )
4359{
4360 for (const int key : { WXK_SHIFT, WXK_CONTROL, WXK_ALT }) {
4361 if (s_keys_down.count(key) == 0)
4362 continue;
4363 wxKeyEvent release(wxEVT_KEY_UP);
4364 release.m_keyCode = key;
4365 on_key(release);
4366 }
4367}
static std::set< int > s_keys_down
Definition GLCanvas3D.cpp:4347

References on_key(), and Slic3r::GUI::s_keys_down.

Referenced by bind_event_handlers().

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

◆ reload_scene()

void Slic3r::GUI::GLCanvas3D::reload_scene ( bool refresh_immediately,
bool force_full_scene_refresh = false )

print->is_step_done(psWipeTower)

print->is_step_done(psWipeTower)

3163{
3164 if (m_canvas == nullptr || m_config == nullptr || m_model == nullptr)
3165 return;
3166
3167 if (!m_initialized || !_set_current()) {
3168 m_reload_delayed = true;
3169 set_as_dirty();
3170 return;
3171 }
3172
3173 m_hover_volume_idxs.clear();
3174
3175 struct ModelVolumeState {
3176 ModelVolumeState(const GLVolume* volume) :
3177 model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {}
3178 ModelVolumeState(const ModelVolume* model_volume, const ObjectID& instance_id, const GLVolume::CompositeID& composite_id) :
3179 model_volume(model_volume), geometry_id(std::make_pair(model_volume->id().id, instance_id.id)), composite_id(composite_id), volume_idx(-1) {}
3180 ModelVolumeState(const ObjectID& volume_id, const ObjectID& instance_id) :
3181 model_volume(nullptr), geometry_id(std::make_pair(volume_id.id, instance_id.id)), volume_idx(-1) {}
3182 bool new_geometry() const { return this->volume_idx == size_t(-1); }
3183 const ModelVolume* model_volume;
3184 // ObjectID of ModelVolume + ObjectID of ModelInstance
3185 // or timestamp of an SLAPrintObjectStep + ObjectID of ModelInstance
3186 std::pair<size_t, size_t> geometry_id;
3187 GLVolume::CompositeID composite_id;
3188 // Volume index in the new GLVolume vector.
3189 size_t volume_idx;
3190 };
3191 std::vector<ModelVolumeState> model_volume_state;
3192 std::vector<ModelVolumeState> aux_volume_state;
3193
3194 struct GLVolumeState {
3195 GLVolumeState() :
3196 volume_idx(size_t(-1)) {}
3197 GLVolumeState(const GLVolume* volume, unsigned int volume_idx) :
3198 composite_id(volume->composite_id), volume_idx(volume_idx) {}
3199 GLVolumeState(const GLVolume::CompositeID &composite_id) :
3200 composite_id(composite_id), volume_idx(size_t(-1)) {}
3201
3202 GLVolume::CompositeID composite_id;
3203 // Volume index in the old GLVolume vector.
3204 size_t volume_idx;
3205 };
3206
3207 // SLA steps to pull the preview meshes for.
3208 typedef std::array<SLAPrintObjectStep, 3> SLASteps;
3209 SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad };
3210 struct SLASupportState {
3211 std::array<PrintStateBase::StateWithTimeStamp, std::tuple_size<SLASteps>::value> step;
3212 };
3213 // State of the sla_steps for all SLAPrintObjects.
3214 std::vector<SLASupportState> sla_support_state;
3215
3216 std::vector<size_t> instance_ids_selected;
3217 std::vector<size_t> map_glvolume_old_to_new(m_volumes.volumes.size(), size_t(-1));
3218 std::vector<GLVolumeState> deleted_volumes;
3219 // BBS
3220 std::vector<GLVolumeState> deleted_wipe_towers;
3221 std::vector<GLVolume*> glvolumes_new;
3222 glvolumes_new.reserve(m_volumes.volumes.size());
3223 auto model_volume_state_lower = [](const ModelVolumeState& m1, const ModelVolumeState& m2) { return m1.geometry_id < m2.geometry_id; };
3224
3225 m_reload_delayed = !m_canvas->IsShown() && !refresh_immediately && !force_full_scene_refresh;
3226 if (m_reload_delayed) {
3227 set_as_dirty();
3228 return;
3229 }
3230
3232
3233 // BBS: support wipe tower for multi-plates
3234 PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
3235 int n_plates = ppl.get_plate_count();
3236 std::vector<int> volume_idxs_wipe_tower_old(n_plates, -1);
3237
3238 // Release invalidated volumes to conserve GPU memory in case of delayed refresh (see m_reload_delayed).
3239 // First initialize model_volumes_new_sorted & model_instances_new_sorted.
3240 for (int object_idx = 0; object_idx < (int)m_model->objects.size(); ++object_idx) {
3241 const ModelObject* model_object = m_model->objects[object_idx];
3242 for (int instance_idx = 0; instance_idx < (int)model_object->instances.size(); ++instance_idx) {
3243 const ModelInstance* model_instance = model_object->instances[instance_idx];
3244 for (int volume_idx = 0; volume_idx < (int)model_object->volumes.size(); ++volume_idx) {
3245 const ModelVolume* model_volume = model_object->volumes[volume_idx];
3247 if (model_volume->is_model_part())
3248 model_volume_state.emplace_back(model_volume, model_instance->id(), GLVolume::CompositeID(object_idx, volume_idx, instance_idx));
3249 }
3250 else {
3251 model_volume_state.emplace_back(model_volume, model_instance->id(), GLVolume::CompositeID(object_idx, volume_idx, instance_idx));
3252 }
3253 }
3254 }
3255 }
3256 if (printer_technology == ptSLA) {
3257 const SLAPrint* sla_print = this->sla_print();
3258#ifndef NDEBUG
3259 // Verify that the SLAPrint object is synchronized with m_model.
3261#endif /* NDEBUG */
3262 sla_support_state.reserve(sla_print->objects().size());
3263 for (const SLAPrintObject* print_object : sla_print->objects()) {
3264 SLASupportState state;
3265 for (size_t istep = 0; istep < sla_steps.size(); ++istep) {
3266 state.step[istep] = print_object->step_state_with_timestamp(sla_steps[istep]);
3267 if (state.step[istep].state == PrintStateBase::DONE) {
3268 if (!print_object->has_mesh(sla_steps[istep]))
3269 // Consider the DONE step without a valid mesh as invalid for the purpose
3270 // of mesh visualization.
3271 state.step[istep].state = PrintStateBase::INVALID;
3272 else if (sla_steps[istep] != slaposDrillHoles)
3273 for (const ModelInstance* model_instance : print_object->model_object()->instances)
3274 // Only the instances, which are currently printable, will have the SLA support structures kept.
3275 // The instances outside the print bed will have the GLVolumes of their support structures released.
3276 if (model_instance->is_printable())
3277 aux_volume_state.emplace_back(state.step[istep].timestamp, model_instance->id());
3278 }
3279 }
3280 sla_support_state.emplace_back(state);
3281 }
3282 }
3283 std::sort(model_volume_state.begin(), model_volume_state.end(), model_volume_state_lower);
3284 std::sort(aux_volume_state.begin(), aux_volume_state.end(), model_volume_state_lower);
3285
3286 // BBS: normalize painting data with current filament count
3287 for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++obj_idx) {
3288 const ModelObject& model_object = *m_model->objects[obj_idx];
3289 for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++volume_idx) {
3290 ModelVolume& model_volume = *model_object.volumes[volume_idx];
3291 if (!model_volume.is_model_part())
3292 continue;
3293
3294 unsigned int filaments_count = (unsigned int)dynamic_cast<const ConfigOptionStrings*>(m_config->option("filament_colour"))->values.size();
3295 model_volume.update_extruder_count(filaments_count);
3296 }
3297 }
3298
3299 // Release all ModelVolume based GLVolumes not found in the current Model. Find the GLVolume of a hollowed mesh.
3300 for (size_t volume_id = 0; volume_id < m_volumes.volumes.size(); ++volume_id) {
3301 GLVolume* volume = m_volumes.volumes[volume_id];
3302 ModelVolumeState key(volume);
3303 ModelVolumeState* mvs = nullptr;
3304 if (volume->volume_idx() < 0) {
3305 auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
3306 if (it != aux_volume_state.end() && it->geometry_id == key.geometry_id)
3307 // This can be an SLA support structure that should not be rendered (in case someone used undo
3308 // to revert to before it was generated). We only reuse the volume if that's not the case.
3309 if (m_model->objects[volume->composite_id.object_id]->sla_points_status != sla::PointsStatus::NoPoints)
3310 mvs = &(*it);
3311 }
3312 else {
3313 auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
3314 if (it != model_volume_state.end() && it->geometry_id == key.geometry_id)
3315 mvs = &(*it);
3316 }
3317 // Emplace instance ID of the volume. Both the aux volumes and model volumes share the same instance ID.
3318 // The wipe tower has its own wipe_tower_instance_id().
3319 if (m_selection.contains_volume(volume_id)) {
3321 if (!volume->is_modifier)
3322 instance_ids_selected.emplace_back(volume->geometry_id.second);
3323 }
3324 else {
3325 instance_ids_selected.emplace_back(volume->geometry_id.second);
3326 }
3327 }
3328 if (mvs == nullptr || force_full_scene_refresh) {
3329 // This GLVolume will be released.
3330 if (volume->is_wipe_tower) {
3331 // There is only one wipe tower.
3332 //assert(volume_idx_wipe_tower_old == -1);
3333 int plate_id = volume->composite_id.object_id - 1000;
3334 if (plate_id < n_plates)
3335 volume_idxs_wipe_tower_old[plate_id] = (int)volume_id;
3336 }
3337 if (!m_reload_delayed) {
3338 deleted_volumes.emplace_back(volume, volume_id);
3339 // BBS
3340 if (volume->is_wipe_tower)
3341 deleted_wipe_towers.emplace_back(volume, volume_id);
3342 delete volume;
3343 }
3344 }
3345 else {
3346 // This GLVolume will be reused.
3347 volume->set_sla_shift_z(0.0);
3348 map_glvolume_old_to_new[volume_id] = glvolumes_new.size();
3349 mvs->volume_idx = glvolumes_new.size();
3350 glvolumes_new.emplace_back(volume);
3351 // Update color of the volume based on the current extruder.
3352 if (mvs->model_volume != nullptr) {
3353 int extruder_id = mvs->model_volume->extruder_id();
3354 if (extruder_id != -1)
3355 volume->extruder_id = extruder_id;
3356
3357 volume->is_modifier = !mvs->model_volume->is_model_part();
3358 volume->set_color(color_from_model_volume(*mvs->model_volume));
3359
3360 // updates volumes transformations
3362 volume->set_instance_transformation(mvs->model_volume->get_object()->instances[mvs->composite_id.instance_id]->get_transformation());
3363 volume->set_volume_transformation(mvs->model_volume->get_transformation());
3364 // updates volumes convex hull
3365 if (mvs->model_volume->is_model_part() && ! volume->convex_hull())
3366 // Model volume was likely changed from modifier or support blocker / enforcer to a model part.
3367 // Only model parts require convex hulls.
3368 volume->set_convex_hull(mvs->model_volume->get_convex_hull_shared_ptr());
3369 volume->set_offset_to_assembly(Vec3d(0, 0, 0));
3370 }
3371 else {
3372 volume->set_instance_transformation(mvs->model_volume->get_object()->instances[mvs->composite_id.instance_id]->get_assemble_transformation());
3373 volume->set_volume_transformation(mvs->model_volume->get_transformation());
3374 // updates volumes convex hull
3375 if (mvs->model_volume->is_model_part() && ! volume->convex_hull())
3376 // Model volume was likely changed from modifier or support blocker / enforcer to a model part.
3377 // Only model parts require convex hulls.
3378 volume->set_convex_hull(mvs->model_volume->get_convex_hull_shared_ptr());
3379 volume->set_offset_to_assembly(mvs->model_volume->get_object()->instances[mvs->composite_id.instance_id]->get_offset_to_assembly());
3380 }
3381 }
3382 }
3383 }
3384 sort_remove_duplicates(instance_ids_selected);
3385 auto deleted_volumes_lower = [](const GLVolumeState &v1, const GLVolumeState &v2) { return v1.composite_id < v2.composite_id; };
3386 std::sort(deleted_volumes.begin(), deleted_volumes.end(), deleted_volumes_lower);
3387
3388 //BBS clean hover_volume_idxs
3389 m_hover_volume_idxs.clear();
3390
3391 // BBS: do not check wipe tower changes
3392 bool update_object_list = false;
3393 if (deleted_volumes.size() != deleted_wipe_towers.size())
3394 update_object_list = true;
3395
3396 if (m_volumes.volumes != glvolumes_new && !update_object_list) {
3397 int vol_idx = 0;
3398 for (; vol_idx < std::min(m_volumes.volumes.size(), glvolumes_new.size()); vol_idx++) {
3399 if (m_volumes.volumes[vol_idx] != glvolumes_new[vol_idx]) {
3400 update_object_list = true;
3401 break;
3402 }
3403 }
3404 for (int temp_idx = vol_idx; temp_idx < m_volumes.volumes.size() && !update_object_list; temp_idx++) {
3405 // Volumes in m_volumes might not exist anymore, so we cannot
3406 // directly check if they are is_wipe_towers, for which we do
3407 // not want to update the object list. Instead, we do a kind of
3408 // slow thing of seeing if they were in the deleted list, and if
3409 // so, if they were a wipe tower.
3410 bool was_deleted_wipe_tower = false;
3411 for (int del_idx = 0; del_idx < deleted_wipe_towers.size(); del_idx++) {
3412 if (deleted_wipe_towers[del_idx].volume_idx == temp_idx) {
3413 was_deleted_wipe_tower = true;
3414 break;
3415 }
3416 }
3417 if (!was_deleted_wipe_tower) {
3418 update_object_list = true;
3419 }
3420 }
3421 for (int temp_idx = vol_idx; temp_idx < glvolumes_new.size() && !update_object_list; temp_idx++) {
3422 if (!glvolumes_new[temp_idx]->is_wipe_tower)
3423 update_object_list = true;
3424 }
3425 }
3426 m_volumes.volumes = std::move(glvolumes_new);
3427 for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++ obj_idx) {
3428 const ModelObject &model_object = *m_model->objects[obj_idx];
3429 for (int volume_idx = 0; volume_idx < (int)model_object.volumes.size(); ++ volume_idx) {
3430 const ModelVolume &model_volume = *model_object.volumes[volume_idx];
3431 if (m_canvas_type == ECanvasType::CanvasAssembleView && !model_volume.is_model_part())
3432 continue;
3433 for (int instance_idx = 0; instance_idx < (int)model_object.instances.size(); ++ instance_idx) {
3434 const ModelInstance &model_instance = *model_object.instances[instance_idx];
3435 ModelVolumeState key(model_volume.id(), model_instance.id());
3436 auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
3437 assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
3438 if (it->new_geometry()) {
3439 // New volume.
3440 auto it_old_volume = std::lower_bound(deleted_volumes.begin(), deleted_volumes.end(), GLVolumeState(it->composite_id), deleted_volumes_lower);
3441 if (it_old_volume != deleted_volumes.end() && it_old_volume->composite_id == it->composite_id)
3442 // If a volume changed its ObjectID, but it reuses a GLVolume's CompositeID, maintain its selection.
3443 map_glvolume_old_to_new[it_old_volume->volume_idx] = m_volumes.volumes.size();
3444 // Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
3445 // later in this function.
3446 it->volume_idx = m_volumes.volumes.size();
3447 m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized, m_canvas_type == ECanvasType::CanvasAssembleView);
3448 m_volumes.volumes.back()->geometry_id = key.geometry_id;
3449 update_object_list = true;
3450 } else {
3451 // Recycling an old GLVolume.
3452 GLVolume &existing_volume = *m_volumes.volumes[it->volume_idx];
3453 assert(existing_volume.geometry_id == key.geometry_id);
3454 // Update the Object/Volume/Instance indices into the current Model.
3455 if (existing_volume.composite_id != it->composite_id) {
3456 existing_volume.composite_id = it->composite_id;
3457 update_object_list = true;
3458 }
3459 }
3460 }
3461 }
3462 }
3463 if (printer_technology == ptSLA) {
3464 size_t idx = 0;
3465 const SLAPrint *sla_print = this->sla_print();
3466 std::vector<double> shift_zs(m_model->objects.size(), 0);
3467 double relative_correction_z = sla_print->relative_correction().z();
3468 if (relative_correction_z <= EPSILON)
3469 relative_correction_z = 1.;
3470 for (const SLAPrintObject *print_object : sla_print->objects()) {
3471 SLASupportState &state = sla_support_state[idx ++];
3472 const ModelObject *model_object = print_object->model_object();
3473 // Find an index of the ModelObject
3474 int object_idx;
3475 // There may be new SLA volumes added to the scene for this print_object.
3476 // Find the object index of this print_object in the Model::objects list.
3477 auto it = std::find(sla_print->model().objects.begin(), sla_print->model().objects.end(), model_object);
3478 assert(it != sla_print->model().objects.end());
3479 object_idx = it - sla_print->model().objects.begin();
3480 // Cache the Z offset to be applied to all volumes with this object_idx.
3481 shift_zs[object_idx] = print_object->get_current_elevation() / relative_correction_z;
3482 // Collect indices of this print_object's instances, for which the SLA support meshes are to be added to the scene.
3483 // pairs of <instance_idx, print_instance_idx>
3484 std::vector<std::pair<size_t, size_t>> instances[std::tuple_size<SLASteps>::value];
3485 for (size_t print_instance_idx = 0; print_instance_idx < print_object->instances().size(); ++ print_instance_idx) {
3486 const SLAPrintObject::Instance &instance = print_object->instances()[print_instance_idx];
3487 // Find index of ModelInstance corresponding to this SLAPrintObject::Instance.
3488 auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
3489 [&instance](const ModelInstance *mi) { return mi->id() == instance.instance_id; });
3490 assert(it != model_object->instances.end());
3491 int instance_idx = it - model_object->instances.begin();
3492 for (size_t istep = 0; istep < sla_steps.size(); ++ istep)
3493 if (sla_steps[istep] == slaposDrillHoles) {
3494 // Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance,
3495 // not into its own GLVolume.
3496 // There shall always be such a GLVolume allocated.
3497 ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id);
3498 auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
3499 assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
3500 assert(!it->new_geometry());
3501 GLVolume &volume = *m_volumes.volumes[it->volume_idx];
3502 if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) {
3503 // The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
3504 volume.model.reset();
3505 if (state.step[istep].state == PrintStateBase::DONE) {
3506 TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
3507 assert(! mesh.empty());
3508 mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse());
3509 volume.model.init_from(mesh);
3510 volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
3511 }
3512 else {
3513 // Reload the original volume.
3514 const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
3515 volume.model.init_from(new_mesh);
3516 volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
3517 }
3518 }
3519 //FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
3520 // to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
3521 // of various concenrs (model vs. 3D print path).
3522 volume.offsets = { state.step[istep].timestamp };
3523 }
3524 else if (state.step[istep].state == PrintStateBase::DONE) {
3525 // Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
3526 ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
3527 auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
3528 assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id);
3529 if (it->new_geometry()) {
3530 // This can be an SLA support structure that should not be rendered (in case someone used undo
3531 // to revert to before it was generated). If that's the case, we should not generate anything.
3532 if (model_object->sla_points_status != sla::PointsStatus::NoPoints)
3533 instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx));
3534 else
3535 shift_zs[object_idx] = 0.;
3536 }
3537 else {
3538 // Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
3539 m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
3540 m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
3541 }
3542 }
3543 }
3544
3545 for (size_t istep = 0; istep < sla_steps.size(); ++istep)
3546 if (!instances[istep].empty())
3547 m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
3548 }
3549
3550 // Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
3551 for (GLVolume* volume : m_volumes.volumes)
3552 if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable())
3553 volume->set_sla_shift_z(shift_zs[volume->object_idx()]);
3554 }
3555
3556 // BBS
3557 if (printer_technology == ptFFF && m_config->has("filament_colour") && (m_canvas_type != ECanvasType::CanvasAssembleView)) {
3558 // Should the wipe tower be visualized ?
3559 unsigned int filaments_count = (unsigned int)dynamic_cast<const ConfigOptionStrings*>(m_config->option("filament_colour"))->values.size();
3560
3561 bool wt = dynamic_cast<const ConfigOptionBool*>(m_config->option("enable_prime_tower"))->value;
3562 auto co = dynamic_cast<const ConfigOptionEnum<PrintSequence>*>(m_config->option<ConfigOptionEnum<PrintSequence>>("print_sequence"));
3563
3564 const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
3565 auto timelapse_type = dconfig.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
3566 bool need_wipe_tower = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
3567
3568 if (dconfig.has("enable_wrapping_detection")) {
3569 need_wipe_tower |= dynamic_cast<const ConfigOptionBool*>(dconfig.option("enable_wrapping_detection"))->value;
3570 }
3571
3572 // Belt printers replace the classic wipe tower with the auto-generated
3573 // belt purge prism (a real model object), so never draw the tower widget.
3574 bool is_belt_printer = false;
3575 if (const auto *belt_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionBool>("belt_printer"))
3576 is_belt_printer = belt_opt->value;
3577
3578 if (wt && !is_belt_printer && (need_wipe_tower || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) {
3579 // The tower size estimate reads printer- and filament-scope keys, which the print preset
3580 // does not carry; built once here rather than per plate.
3581 const DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config();
3582 for (int plate_id = 0; plate_id < n_plates; plate_id++) {
3583 // If print ByObject and there is only one object in the plate, the wipe tower is allowed to be generated.
3584 PartPlate* part_plate = ppl.get_plate(plate_id);
3585 if (part_plate->get_print_seq() == PrintSequence::ByObject ||
3586 (part_plate->get_print_seq() == PrintSequence::ByDefault && co != nullptr && co->value == PrintSequence::ByObject)) {
3587 if (ppl.get_plate(plate_id)->printable_instance_size() != 1)
3588 continue;
3589 }
3590
3591 DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
3592 float x = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->get_at(plate_id);
3593 float y = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_y"))->get_at(plate_id);
3594 float a = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_rotation_angle"))->value;
3595 Vec3d plate_origin = ppl.get_plate(plate_id)->get_origin();
3596
3597 const Print* current_print = part_plate->fff_print();
3598 if (part_plate->get_objects_on_this_plate().empty()) continue;
3599
3600 // Body and brim from this plate's own estimate: m_process->fff_print() is the
3601 // selected plate's, so an auto brim drew every tower with that plate's brim.
3602 const WipeTowerFootprint footprint = part_plate->estimate_wipe_tower_footprint(full_config);
3603 // The estimate is also the answer to whether this plate prints a tower;
3604 // deciding it here as well only gave the two room to drift.
3605 if (footprint.depth <= 0.) continue;
3606 float brim_width = float(footprint.brim_width);
3607 Vec3d wipe_tower_size(footprint.width, footprint.depth, footprint.height);
3608
3609 // set_default_wipe_tower_pos_for_plate doesn't rerun when painting changes the
3610 // filament count, so redo its clamp here on every reload — unconditionally: a
3611 // paint-triggered reload can arrive before the background process invalidates
3612 // psWipeTower, so gating on it would skip the clamp exactly when it is needed.
3613 {
3614 Vec3d clamped_pos, clamped_size;
3615 WipeTowerRelocation relocation;
3616 part_plate->estimate_wipe_tower_polygon(full_config, plate_id, clamped_pos, clamped_size, 0, false, &relocation);
3617 if (std::abs(x - (float) clamped_pos(0)) > EPSILON || std::abs(y - (float) clamped_pos(1)) > EPSILON) {
3618 x = (float) clamped_pos(0);
3619 y = (float) clamped_pos(1);
3620 ConfigOptionFloat wt_x_opt(x), wt_y_opt(y);
3621 dynamic_cast<ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0);
3622 dynamic_cast<ConfigOptionFloats*>(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0);
3623 // The stored position changes once, so this is shown once per move.
3624 if (NotificationManager *notifications = wxGetApp().notification_manager(); notifications != nullptr && relocation.moved) {
3625 if (relocation.overlaps_objects)
3627 // TRN %1% is the plate number.
3628 format(_u8L("The prime tower on plate %1% no longer fits where it was placed. There is no free space left on the plate for it, so it was moved onto an object."), plate_id + 1));
3629 else
3631 // TRN %1% is the plate number.
3632 format(_u8L("The prime tower on plate %1% no longer fits where it was placed, so it was moved to free space on the plate."), plate_id + 1));
3633 }
3634 }
3635 }
3636
3637 if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) {
3638 // update for wipe tower position
3639 int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1),
3640 (float) wipe_tower_size(0), (float) wipe_tower_size(1), (float) wipe_tower_size(2),
3641 a, true, brim_width);
3643 int volume_idx_wipe_tower_old = volume_idxs_wipe_tower_old[plate_id];
3644 if (volume_idx_wipe_tower_old != -1) map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
3645 } else {
3646 int volume_idx_wipe_tower_new = m_volumes.load_real_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1),
3647 current_print->wipe_tower_data().wipe_tower_mesh_data->real_wipe_tower_mesh,
3648 current_print->wipe_tower_data().wipe_tower_mesh_data->real_brim_mesh,
3649 true,a, true, m_initialized);
3650 int volume_idx_wipe_tower_old = volume_idxs_wipe_tower_old[plate_id];
3651 if (volume_idx_wipe_tower_old != -1) map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
3652 }
3653 }
3654 }
3655 }
3656
3658
3659 // ORCA-Belt: render the auto-generated belt purge prism like a wipe tower —
3660 // semi-transparent, in its (filament) color. It is a real sliced object, so
3661 // the G-code preview already shows the actual per-layer purge colors; here in
3662 // the editor we just make the block translucent so it reads as a purge tower
3663 // rather than a solid part. update_colors_by_extruder() preserves alpha when
3664 // not updating alpha, so lowering it once sticks across recolors.
3665 if (m_model != nullptr) {
3666 for (GLVolume *volume : m_volumes.volumes) {
3667 if (volume == nullptr || volume->volume_idx() < 0)
3668 continue;
3669 const int obj_idx = volume->object_idx();
3670 if (obj_idx < 0 || obj_idx >= (int) m_model->objects.size())
3671 continue;
3672 const ConfigOption *opt = m_model->objects[obj_idx]->config.option("belt_purge_tower_object");
3673 if (opt != nullptr && opt->getBool()) {
3674 volume->color.a(0.66f);
3675 volume->force_transparent = true;
3676 }
3677 }
3678 }
3679
3680 // Update selection indices based on the old/new GLVolumeCollection.
3681 if (m_selection.get_mode() == Selection::Instance)
3682 m_selection.instances_changed(instance_ids_selected);
3683 else
3684 m_selection.volumes_changed(map_glvolume_old_to_new);
3685
3686 // @Enrico suggest this solution to preven accessing pointer on caster without data
3689 m_gizmos.update_data();
3690 m_gizmos.refresh_on_off_state();
3691
3692 // Update the toolbar
3693 //BBS: notify the PartPlateList to reload all objects
3694 if (update_object_list)
3695 post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
3696
3697 //BBS:exclude the assmble view
3700 // checks for geometry outside the print volume to render it accordingly
3701 if (!m_volumes.empty()) {
3703 ObjectFilamentResults object_results;
3704 const bool contained_min_one = m_volumes.check_outside_state(m_bed.build_volume(), &state, &object_results);
3707 // const bool objectLimited = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Limited);
3708
3709 PartPlate *cur_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
3710 bool show_read_wipe_tower = cur_plate->fff_print()->is_step_done(psWipeTower);
3711 bool wipe_tower_outside = m_volumes.check_wipe_tower_outside_state(m_bed.build_volume(), wxGetApp().plater()->get_partplate_list().get_curr_plate_index());
3712 bool show_wipe_tower_outside_error = show_read_wipe_tower ? !wipe_tower_outside : false;
3713 _set_warning_notification(EWarning::PrimeTowerOutside, show_wipe_tower_outside_error);
3714
3715 auto clash_flag = construct_error_string(object_results, get_object_clashed_text());
3717
3718 bool is_flushing_volume_valid = is_flushing_matrix_error();
3723 //_set_warning_notification(EWarning::ObjectLimited, objectLimited);
3724 //BBS: turn off the warning when fully outside
3725 //_set_warning_notification(EWarning::ObjectOutside, fullyOut);
3726 //if (printer_technology != ptSLA || !contained_min_one)
3727 // _set_warning_notification(EWarning::SlaSupportsOutside, false);
3728
3729 auto full_config_temp = wxGetApp().preset_bundle->full_config();
3730 bool tpu_valid = cur_plate->check_tpu_printable_status(full_config_temp, wxGetApp().preset_bundle->get_used_tpu_filaments(cur_plate->get_extruders(true)));
3732
3733 bool filament_printable = cur_plate->check_filament_printable(full_config_temp, filament_printable_error_msg);
3735
3736 bool mix_pla_and_petg = cur_plate->check_mixture_of_pla_and_petg(full_config_temp);
3738
3739 bool single_extruder_mixed_risk = cur_plate->check_single_extruder_mixed_filament_risk(full_config_temp, get_single_extruder_mixed_filament_warning_text());
3741
3742 bool filament_nozzle_compatible = cur_plate->check_compatible_of_nozzle_and_filament(full_config_temp, wxGetApp().preset_bundle->filament_presets, get_nozzle_filament_incompatible_text());
3744
3745 bool filament_mixture_compatible = cur_plate->check_mixture_filament_compatible(full_config_temp, get_filament_mixture_warning_text());
3747
3748 bool model_fits = contained_min_one && !m_model->objects.empty() && !partlyOut && object_results.filaments.empty() && tpu_valid && filament_printable;
3749 // Honor the missing-plugin block so this geometry-only path does not re-enable slicing
3750 // that Plater::validate_current_plate disabled (otherwise moving an object would briefly
3751 // re-enable the Slice button while required plugins are still missing).
3752 if (wxGetApp().plater() && wxGetApp().plater()->plugins_block_slicing())
3753 model_fits = false;
3754 post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, model_fits));
3755 ppl.get_curr_plate()->update_slice_ready_status(model_fits);
3756 }
3757 else {
3763 //_set_warning_notification(EWarning::ObjectLimited, false);
3764 //_set_warning_notification(EWarning::SlaSupportsOutside, false);
3774
3775 post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false));
3776 }
3777 }
3778
3780
3781 if (m_selection.is_empty()) {
3782 // If no object is selected, deactivate the active gizmo, if any
3783 // Otherwise it may be shown after cleaning the scene (if it was active while the objects were deleted)
3784 m_gizmos.reset_all_states();
3785 // BBS
3786#if 0
3787 // If no object is selected, reset the objects manipulator on the sidebar
3788 // to force a reset of its cache
3789 auto manip = wxGetApp().obj_manipul();
3790 if (manip != nullptr)
3791 manip->set_dirty();
3792#endif
3793 }
3794
3795 // refresh bed raycasters for picking
3797 wxGetApp().plater()->get_partplate_list().register_raycasters_for_picking(*this);
3798 }
3799
3800 // refresh volume raycasters for picking
3801 for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
3802 const GLVolume* v = m_volumes.volumes[i];
3803 assert(v->mesh_raycaster != nullptr);
3804 std::shared_ptr<SceneRaycasterItem> raycaster = add_raycaster_for_picking(SceneRaycaster::EType::Volume, i, *v->mesh_raycaster, v->world_matrix());
3805 raycaster->set_active(v->is_active);
3806 }
3807
3808 // refresh gizmo elements raycasters for picking
3809 GLGizmoBase* curr_gizmo = m_gizmos.get_current();
3810 if (curr_gizmo != nullptr)
3811 curr_gizmo->unregister_raycasters_for_picking();
3814 if (curr_gizmo != nullptr && !m_selection.is_empty())
3815 curr_gizmo->register_raycasters_for_picking();
3816
3817 // and force this canvas to be redrawn.
3818 m_dirty = true;
3819}
std::shared_ptr< SceneRaycasterItem > add_raycaster_for_picking(SceneRaycaster::EType type, int id, const MeshRaycaster &raycaster, const Transform3d &trafo=Transform3d::Identity(), bool use_back_faces=false)
Definition GLCanvas3D.hpp:961
bool is_flushing_matrix_error()
Definition GLCanvas3D.cpp:12646
@ WarningNotificationLevel
Definition NotificationManager.hpp:224
@ RegularNotificationLevel
Definition NotificationManager.hpp:216
@ DONE
Definition PrintBase.hpp:58
@ INVALID
Definition PrintBase.hpp:56
static PrinterTechnology printer_technology()
Definition GUI_Factories.cpp:60
@ CustomNotification
Definition NotificationManager.hpp:66
static int filaments_count()
Definition GUI_Factories.cpp:65
@ NoPoints
Definition SupportPoint.hpp:14
void check_model_ids_equal(const Model &model1, const Model &model2)
Definition Model.cpp:4399
@ psWipeTower
Definition Print.hpp:109
@ tlSmooth
Definition PrintConfig.hpp:470
@ ByDefault
Definition PrintConfig.hpp:313
@ slaposDrillHoles
Definition SLAPrint.hpp:44
void sort_remove_duplicates(std::vector< T > &vec)
Definition libslic3r.h:231
@ ModelInstancePVS_Partly_Outside
Definition Model.hpp:1413
@ ModelInstancePVS_Fully_Outside
Definition Model.hpp:1414
ColorRGBA color_from_model_volume(const ModelVolume &model_volume)
Definition 3DScene.cpp:407

References _set_current(), _set_warning_notification(), _u8L, _update_slice_error_status(), Slic3r::ColorRGBA::a(), add_raycaster_for_picking(), Slic3r::GUI::SceneRaycaster::Bed, Slic3r::WipeTowerFootprint::brim_width, Slic3r::ByDefault, Slic3r::ByObject, CanvasAssembleView, CanvasView3D, Slic3r::GUI::PartPlate::check_compatible_of_nozzle_and_filament(), Slic3r::GUI::PartPlate::check_filament_printable(), Slic3r::GUI::PartPlate::check_mixture_filament_compatible(), Slic3r::GUI::PartPlate::check_mixture_of_pla_and_petg(), Slic3r::check_model_ids_equal(), Slic3r::GUI::PartPlate::check_single_extruder_mixed_filament_risk(), Slic3r::GUI::PartPlate::check_tpu_printable_status(), Slic3r::GLVolume::color, Slic3r::color_from_model_volume(), Slic3r::GLVolume::composite_id, Slic3r::GUI::construct_error_string(), Slic3r::GUI::construct_extruder_unprintable_error(), Slic3r::GLVolume::convex_hull(), current_printer_technology(), Slic3r::GUI::CustomNotification, Slic3r::WipeTowerFootprint::depth, Slic3r::PrintStateBase::DONE, Slic3r::empty(), Slic3r::TriangleMesh::empty(), EPSILON, Slic3r::GUI::PartPlate::estimate_wipe_tower_footprint(), Slic3r::GUI::PartPlate::estimate_wipe_tower_polygon(), Slic3r::GLVolume::extruder_id, Slic3r::GUI::SceneRaycaster::FallbackGizmo, Slic3r::GUI::PartPlate::fff_print(), Slic3r::GUI::filament_printable_error_msg, FilamentPrintableError, Slic3r::ObjectFilamentResults::filaments, Slic3r::GUI::filaments_count(), FlushingVolumeZero, Slic3r::GUI::format(), Slic3r::GLVolume::geometry_id, Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::get_extruders(), Slic3r::GUI::get_filament_mixture_warning_text(), Slic3r::GUI::get_left_extruder_unprintable_text(), Slic3r::GUI::get_nozzle_filament_incompatible_text(), Slic3r::GUI::get_object_clashed_text(), Slic3r::GUI::PartPlate::get_objects_on_this_plate(), Slic3r::GUI::PartPlate::get_origin(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), Slic3r::GUI::PartPlate::get_print_seq(), Slic3r::GUI::get_right_extruder_unprintable_text(), Slic3r::GUI::get_single_extruder_mixed_filament_warning_text(), Slic3r::GUI::SceneRaycaster::Gizmo, Slic3r::ConfigOptionEnum< T >::has(), Slic3r::WipeTowerFootprint::height, Slic3r::ObjectBase::id(), Slic3r::ObjectID::id, Slic3r::GUI::GLModel::init_from(), Slic3r::GUI::Selection::Instance, Slic3r::SLAPrintObject::Instance::instance_id, Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::PrintStateBase::INVALID, is_flushing_matrix_error(), Slic3r::ModelVolume::is_model_part(), Slic3r::Print::is_step_done(), LeftExtruderPrintableError, m_bed, m_canvas, m_canvas_type, m_color_by, m_config, m_dirty, m_gizmos, m_hover_volume_idxs, m_initialized, m_model, m_reload_delayed, m_scene_raycaster, m_selection, m_volumes, Slic3r::GLVolume::mesh_raycaster, MixtureFilamentIncompatible, MixUsePLAAndPETG, Slic3r::GLVolume::model, Slic3r::ModelInstancePVS_Fully_Outside, Slic3r::ModelInstancePVS_Partly_Outside, Slic3r::GUI::WipeTowerRelocation::moved, MultiExtruderHeightOutside, MultiExtruderPrintableError, Slic3r::sla::NoPoints, NozzleFilamentIncompatible, Slic3r::GLVolume::CompositeID::object_id, Slic3r::GLVolume::object_idx(), ObjectClashed, ObjectOutside, Slic3r::GLVolume::offsets, Slic3r::ConfigBase::option(), Slic3r::GUI::WipeTowerRelocation::overlaps_objects, Slic3r::GUI::plater(), post_event(), PrimeTowerOutside, Slic3r::GUI::PartPlate::printable_instance_size(), Slic3r::GUI::printer_technology(), Slic3r::psWipeTower, Slic3r::ptFFF, Slic3r::ptSLA, refresh_camera_scene_box(), Slic3r::GUI::GLGizmoBase::register_raycasters_for_picking(), Slic3r::GUI::NotificationManager::RegularNotificationLevel, Slic3r::GUI::GLModel::reset(), RightExtruderPrintableError, set_as_dirty(), Slic3r::GLVolume::set_color(), Slic3r::GLVolume::set_convex_hull(), Slic3r::GLVolume::set_instance_transformation(), Slic3r::GLVolume::set_offset_to_assembly(), Slic3r::GLVolume::set_sla_shift_z(), Slic3r::GLVolume::set_volume_transformation(), SingleExtruderMixedFilament, Slic3r::ModelObject::sla_points_status, sla_print(), Slic3r::slaposDrillHoles, Slic3r::slaposPad, Slic3r::slaposSupportTree, Slic3r::sort_remove_duplicates(), Slic3r::tlSmooth, TPUPrintableError, Slic3r::TriangleMesh::transform(), Slic3r::GUI::GLGizmoBase::unregister_raycasters_for_picking(), Slic3r::ModelVolume::update_extruder_count(), Slic3r::GUI::PartPlate::update_slice_ready_status(), update_volumes_colors_by_extruder(), Slic3r::ConfigOptionSingle< T >::value, Slic3r::ConfigOptionVector< T >::values, Slic3r::GUI::SceneRaycaster::Volume, Slic3r::GLVolume::volume_idx(), Slic3r::ModelObject::volumes, Slic3r::GUI::NotificationManager::WarningNotificationLevel, Slic3r::WipeTowerFootprint::width, Slic3r::Print::wipe_tower_data(), Slic3r::WipeTowerData::wipe_tower_mesh_data, and Slic3r::GLVolume::world_matrix().

Referenced by _render_frame(), anonymous_namespace{EmbossJob.cpp}::CreateObjectJob::finalize(), Slic3r::GUI::ObjectList::list_manipulation(), and Slic3r::GUI::ObjectList::OnEditingStarted().

Here is the caller graph for this function:

◆ remove_curr_plate_all()

void Slic3r::GUI::GLCanvas3D::remove_curr_plate_all ( )
3041{
3042 m_selection.remove_curr_plate();
3043 m_dirty = true;
3044}

References m_dirty, and m_selection.

◆ remove_raycasters_for_picking() [1/2]

void Slic3r::GUI::GLCanvas3D::remove_raycasters_for_picking ( SceneRaycaster::EType type)
inline
968 {
969 m_scene_raycaster.remove_raycasters(type);
970 }

References m_scene_raycaster.

◆ remove_raycasters_for_picking() [2/2]

void Slic3r::GUI::GLCanvas3D::remove_raycasters_for_picking ( SceneRaycaster::EType type,
int id )
inline
965 {
966 m_scene_raycaster.remove_raycasters(type, id);
967 }

References m_scene_raycaster.

Referenced by Slic3r::GUI::PartPlate::register_raycasters_for_picking().

Here is the caller graph for this function:

◆ render()

void Slic3r::GUI::GLCanvas3D::render ( bool only_init = false)
2482{
2483 m_presented_signature.reset();
2484 _render_frame(true, only_init);
2485}

References _render_frame(), and m_presented_signature.

Referenced by bind_event_handlers(), Slic3r::GUI::GLToolbar::do_action(), on_char(), on_key(), on_mouse(), on_mouse_wheel(), and on_paint().

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

◆ render_thumbnail() [1/3]

void Slic3r::GUI::GLCanvas3D::render_thumbnail ( ThumbnailData & thumbnail_data,
std::vector< ColorRGBA > & extruder_colors,
unsigned int w,
unsigned int h,
const ThumbnailsParams & thumbnail_params,
ModelObjectPtrs & model_objects,
const GLVolumeCollection & volumes,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
3004{
3006 return;
3007
3008 GLShaderProgram *shader = wxGetApp().get_shader("thumbnail");
3011 render_thumbnail_framebuffer(thumbnail_data, w, h, thumbnail_params, wxGetApp().plater()->get_partplate_list(), model_objects, volumes, extruder_colors, shader,
3012 camera_type, camera_view_angle_type, for_picking, ban_light);
3013 break;
3014 }
3016 render_thumbnail_framebuffer_ext(thumbnail_data, w, h, thumbnail_params, wxGetApp().plater()->get_partplate_list(), model_objects, volumes, extruder_colors, shader,
3017 camera_type, camera_view_angle_type, for_picking, ban_light);
3018 break;
3019 }
3020 default: {
3021 render_thumbnail_legacy(thumbnail_data, w, h, thumbnail_params, wxGetApp().plater()->get_partplate_list(), model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type, for_picking, ban_light);
3022 break;
3023 }
3024 }
3025}
static void render_thumbnail_framebuffer_ext(ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
Definition GLCanvas3D.cpp:7250
static void render_thumbnail_framebuffer(ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
Definition GLCanvas3D.cpp:7137
static void render_thumbnail_legacy(ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
Definition GLCanvas3D.cpp:7359

References _set_shown_canvas_current(), Slic3r::GUI::OpenGLManager::Arb, Slic3r::GUI::OpenGLManager::Ext, Slic3r::GUI::OpenGLManager::get_framebuffers_type(), Slic3r::GUI::plater(), render_thumbnail_framebuffer(), render_thumbnail_framebuffer_ext(), and render_thumbnail_legacy().

Here is the call graph for this function:

◆ render_thumbnail() [2/3]

void Slic3r::GUI::GLCanvas3D::render_thumbnail ( ThumbnailData & thumbnail_data,
unsigned int w,
unsigned int h,
const ThumbnailsParams & thumbnail_params,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
2941{
2942 ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects;
2943 render_thumbnail(thumbnail_data, w, h, thumbnail_params, model_objects, m_volumes, camera_type, camera_view_angle_type, for_picking, ban_light);
2944}
void render_thumbnail(ThumbnailData &thumbnail_data, unsigned int w, unsigned int h, const ThumbnailsParams &thumbnail_params, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
Definition GLCanvas3D.cpp:2933

References m_volumes, and render_thumbnail().

Referenced by render_thumbnail(), Slic3r::GUI::Plater::update_obj_preview_thumbnail(), and Slic3r::GUI::Plater::update_plate_thumbnails().

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

◆ render_thumbnail() [3/3]

void Slic3r::GUI::GLCanvas3D::render_thumbnail ( ThumbnailData & thumbnail_data,
unsigned int w,
unsigned int h,
const ThumbnailsParams & thumbnail_params,
ModelObjectPtrs & model_objects,
const GLVolumeCollection & volumes,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
2963{
2965 return;
2966
2967 GLShaderProgram* shader = nullptr;
2968 if (for_picking)
2969 shader = wxGetApp().get_shader("flat");
2970 else
2971 shader = wxGetApp().get_shader("thumbnail");
2972 std::vector<ColorRGBA> colors = wxGetApp().plater()->get_extruders_colors();
2974 {
2976 { render_thumbnail_framebuffer(thumbnail_data, w, h, thumbnail_params, wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type,
2977 camera_view_angle_type, for_picking, ban_light);
2978 break;
2979 }
2981 { render_thumbnail_framebuffer_ext(thumbnail_data, w, h, thumbnail_params, wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type,
2982 camera_view_angle_type, for_picking, ban_light);
2983 break;
2984 }
2985 default:{
2986 render_thumbnail_legacy(thumbnail_data, w, h, thumbnail_params, wxGetApp().plater()->get_partplate_list(), model_objects, volumes, colors, shader, camera_type,
2987 camera_view_angle_type, for_picking, ban_light);
2988 break;
2989 }
2990 }
2991}

References _set_shown_canvas_current(), Slic3r::GUI::OpenGLManager::Arb, Slic3r::GUI::OpenGLManager::Ext, Slic3r::GUI::OpenGLManager::get_framebuffers_type(), Slic3r::GUI::plater(), render_thumbnail_framebuffer(), render_thumbnail_framebuffer_ext(), and render_thumbnail_legacy().

Here is the call graph for this function:

◆ render_thumbnail_framebuffer()

void Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer ( ThumbnailData & thumbnail_data,
unsigned int w,
unsigned int h,
const ThumbnailsParams & thumbnail_params,
PartPlateList & partplate_list,
ModelObjectPtrs & model_objects,
const GLVolumeCollection & volumes,
std::vector< ColorRGBA > & extruder_colors,
GLShaderProgram * shader,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
static
7144{
7145 thumbnail_data.set(w, h);
7146 if (!thumbnail_data.is_valid())
7147 return;
7148
7149 bool multisample = OpenGLManager::can_multisample();
7150 if (for_picking)
7151 multisample = false;
7152 //if (!multisample)
7153 // glsafe(::glEnable(GL_MULTISAMPLE));
7154
7155 GLint max_samples;
7156 glsafe(::glGetIntegerv(GL_MAX_SAMPLES, &max_samples));
7157 GLsizei num_samples = max_samples / 2;
7158
7159 GLuint render_fbo;
7160 glsafe(::glGenFramebuffers(1, &render_fbo));
7162
7163 BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail prepare: w %1%, h %2%, max_samples %3%, render_fbo %4%") %w %h %max_samples % render_fbo;
7164 GLuint render_tex = 0;
7165 GLuint render_tex_buffer = 0;
7166 if (multisample) {
7167 // use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
7168 glsafe(::glGenRenderbuffers(1, &render_tex_buffer));
7169 glsafe(::glBindRenderbuffer(GL_RENDERBUFFER, render_tex_buffer));
7172 }
7173 else {
7174 glsafe(::glGenTextures(1, &render_tex));
7175 glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
7180 }
7181
7182 GLuint render_depth;
7183 glsafe(::glGenRenderbuffers(1, &render_depth));
7185 if (multisample)
7187 else
7189
7191
7192 GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0 };
7193 glsafe(::glDrawBuffers(1, drawBufs));
7194
7196 render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type,
7197 for_picking, ban_light);
7198
7199 if (multisample) {
7200 GLuint resolve_fbo;
7201 glsafe(::glGenFramebuffers(1, &resolve_fbo));
7203
7204 GLuint resolve_tex;
7205 glsafe(::glGenTextures(1, &resolve_tex));
7206 glsafe(::glBindTexture(GL_TEXTURE_2D, resolve_tex));
7211
7212 glsafe(::glDrawBuffers(1, drawBufs));
7213
7217 glsafe(::glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR));
7218
7220 glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
7221 }
7222
7223 glsafe(::glDeleteTextures(1, &resolve_tex));
7224 glsafe(::glDeleteFramebuffers(1, &resolve_fbo));
7225 }
7226 else
7227 glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
7228
7229#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
7230 debug_output_thumbnail(thumbnail_data);
7231#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
7232 }
7233 else {
7234 BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail prepare: GL_FRAMEBUFFER not complete");
7235 }
7236
7238 glsafe(::glDeleteRenderbuffers(1, &render_depth));
7239 if (render_tex_buffer != 0)
7240 glsafe(::glDeleteRenderbuffers(1, &render_tex_buffer));
7241 if (render_tex != 0)
7242 glsafe(::glDeleteTextures(1, &render_tex));
7243 glsafe(::glDeleteFramebuffers(1, &render_fbo));
7244
7245 //if (!multisample)
7246 // glsafe(::glDisable(GL_MULTISAMPLE));
7247 BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail prepare: finished");
7248}
static void render_thumbnail_internal(ThumbnailData &thumbnail_data, const ThumbnailsParams &thumbnail_params, PartPlateList &partplate_list, ModelObjectPtrs &model_objects, const GLVolumeCollection &volumes, std::vector< ColorRGBA > &extruder_colors, GLShaderProgram *shader, Camera::EType camera_type, Camera::ViewAngleType camera_view_angle_type=Camera::ViewAngleType::Iso, bool for_picking=false, bool ban_light=false)
Definition GLCanvas3D.cpp:6899
static bool can_multisample()
Definition OpenGLManager.hpp:100
#define glBlitFramebuffer
Definition gl.h:3333
#define glRenderbufferStorageMultisample
Definition gl.h:4687
#define GL_DRAW_FRAMEBUFFER
Definition gl.h:617
#define GL_MAX_SAMPLES
Definition gl.h:1111
int GLsizei
Definition gl.h:2065
#define GL_READ_FRAMEBUFFER
Definition gl.h:1405

References Slic3r::GUI::OpenGLManager::can_multisample(), GL_COLOR_ATTACHMENT0, GL_COLOR_BUFFER_BIT, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, GL_LINEAR, GL_MAX_SAMPLES, GL_READ_FRAMEBUFFER, GL_RENDERBUFFER, GL_RGBA, GL_RGBA8, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_UNSIGNED_BYTE, glBindFramebuffer, glBindRenderbuffer, glBindTexture, glBlitFramebuffer, glCheckFramebufferStatus, glDeleteFramebuffers, glDeleteRenderbuffers, glDeleteTextures, glDrawBuffers, glFramebufferRenderbuffer, glFramebufferTexture2D, glGenFramebuffers, glGenRenderbuffers, glGenTextures, glGetIntegerv, glReadPixels, glRenderbufferStorage, glRenderbufferStorageMultisample, glsafe, glTexImage2D, glTexParameteri, Slic3r::ThumbnailData::is_valid(), Slic3r::ThumbnailData::pixels, render_thumbnail_internal(), and Slic3r::ThumbnailData::set().

Referenced by Slic3r::GUI::CalibUtils::process_and_store_3mf(), render_thumbnail(), render_thumbnail(), and Slic3r::CLI::run().

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

◆ render_thumbnail_framebuffer_ext()

void Slic3r::GUI::GLCanvas3D::render_thumbnail_framebuffer_ext ( ThumbnailData & thumbnail_data,
unsigned int w,
unsigned int h,
const ThumbnailsParams & thumbnail_params,
PartPlateList & partplate_list,
ModelObjectPtrs & model_objects,
const GLVolumeCollection & volumes,
std::vector< ColorRGBA > & extruder_colors,
GLShaderProgram * shader,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
static
7257{
7258 thumbnail_data.set(w, h);
7259 if (!thumbnail_data.is_valid())
7260 return;
7261
7262 bool multisample = OpenGLManager::can_multisample();
7263 if (for_picking)
7264 multisample = false;
7265 //if (!multisample)
7266 // glsafe(::glEnable(GL_MULTISAMPLE));
7267
7268 GLint max_samples;
7270 GLsizei num_samples = max_samples / 2;
7271
7272 GLuint render_fbo;
7273 glsafe(::glGenFramebuffersEXT(1, &render_fbo));
7275
7276 GLuint render_tex = 0;
7277 GLuint render_tex_buffer = 0;
7278 if (multisample) {
7279 // use renderbuffer instead of texture to avoid the need to use glTexImage2DMultisample which is available only since OpenGL 3.2
7280 glsafe(::glGenRenderbuffersEXT(1, &render_tex_buffer));
7284 }
7285 else {
7286 glsafe(::glGenTextures(1, &render_tex));
7287 glsafe(::glBindTexture(GL_TEXTURE_2D, render_tex));
7292 }
7293
7294 GLuint render_depth;
7295 glsafe(::glGenRenderbuffersEXT(1, &render_depth));
7297 if (multisample)
7299 else
7301
7303
7304 GLenum drawBufs[] = { GL_COLOR_ATTACHMENT0_EXT };
7305 glsafe(::glDrawBuffers(1, drawBufs));
7306
7308 render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type,
7309 for_picking,
7310 ban_light);
7311
7312 if (multisample) {
7313 GLuint resolve_fbo;
7314 glsafe(::glGenFramebuffersEXT(1, &resolve_fbo));
7316
7317 GLuint resolve_tex;
7318 glsafe(::glGenTextures(1, &resolve_tex));
7319 glsafe(::glBindTexture(GL_TEXTURE_2D, resolve_tex));
7324
7325 glsafe(::glDrawBuffers(1, drawBufs));
7326
7331
7333 glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
7334 }
7335
7336 glsafe(::glDeleteTextures(1, &resolve_tex));
7337 glsafe(::glDeleteFramebuffersEXT(1, &resolve_fbo));
7338 }
7339 else
7340 glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
7341
7342#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
7343 debug_output_thumbnail(thumbnail_data);
7344#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
7345 }
7346
7348 glsafe(::glDeleteRenderbuffersEXT(1, &render_depth));
7349 if (render_tex_buffer != 0)
7350 glsafe(::glDeleteRenderbuffersEXT(1, &render_tex_buffer));
7351 if (render_tex != 0)
7352 glsafe(::glDeleteTextures(1, &render_tex));
7353 glsafe(::glDeleteFramebuffersEXT(1, &render_fbo));
7354
7355 //if (!multisample)
7356 // glsafe(::glDisable(GL_MULTISAMPLE));
7357}
#define GL_MAX_SAMPLES_EXT
Definition gl.h:1112
#define glRenderbufferStorageMultisampleEXT
Definition gl.h:4689
#define GL_READ_FRAMEBUFFER_EXT
Definition gl.h:1408
#define GL_DRAW_FRAMEBUFFER_EXT
Definition gl.h:620
#define glBlitFramebufferEXT
Definition gl.h:3335

References Slic3r::GUI::OpenGLManager::can_multisample(), GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_BUFFER_BIT, GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_DRAW_FRAMEBUFFER_EXT, GL_FRAMEBUFFER_COMPLETE_EXT, GL_FRAMEBUFFER_EXT, GL_LINEAR, GL_MAX_SAMPLES_EXT, GL_READ_FRAMEBUFFER_EXT, GL_RENDERBUFFER_EXT, GL_RGBA, GL_RGBA8, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_UNSIGNED_BYTE, glBindFramebufferEXT, glBindRenderbufferEXT, glBindTexture, glBlitFramebufferEXT, glCheckFramebufferStatusEXT, glDeleteFramebuffersEXT, glDeleteRenderbuffersEXT, glDeleteTextures, glDrawBuffers, glFramebufferRenderbufferEXT, glFramebufferTexture2DEXT, glGenFramebuffersEXT, glGenRenderbuffersEXT, glGenTextures, glGetIntegerv, glReadPixels, glRenderbufferStorageEXT, glRenderbufferStorageMultisampleEXT, glsafe, glTexImage2D, glTexParameteri, Slic3r::ThumbnailData::is_valid(), Slic3r::ThumbnailData::pixels, render_thumbnail_internal(), and Slic3r::ThumbnailData::set().

Referenced by Slic3r::GUI::CalibUtils::process_and_store_3mf(), render_thumbnail(), render_thumbnail(), and Slic3r::CLI::run().

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

◆ render_thumbnail_internal()

void Slic3r::GUI::GLCanvas3D::render_thumbnail_internal ( ThumbnailData & thumbnail_data,
const ThumbnailsParams & thumbnail_params,
PartPlateList & partplate_list,
ModelObjectPtrs & model_objects,
const GLVolumeCollection & volumes,
std::vector< ColorRGBA > & extruder_colors,
GLShaderProgram * shader,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
static
6906{
6907 //BBS modify visible calc function
6908 static ColorRGBA curr_color;
6909 static const std::array<float, 4> orange = {0.923f, 0.504f, 0.264f, 1.0f};
6910 static const std::array<float, 4> gray = {0.64f, 0.64f, 0.64f, 1.0f};
6911 GLVolumePtrs visible_volumes;
6912 BoundingBoxf3 plate_build_volume;
6913 if (thumbnail_params.use_plate_box) {
6914 int plate_idx = thumbnail_params.plate_id;
6915 PartPlate * plate = partplate_list.get_plate(plate_idx);
6916 plate_build_volume = plate->get_build_volume();
6917 plate_build_volume.min(0) -= Slic3r::BuildVolume::SceneEpsilon;
6918 plate_build_volume.min(1) -= Slic3r::BuildVolume::SceneEpsilon;
6919 plate_build_volume.min(2) -= Slic3r::BuildVolume::SceneEpsilon;
6920 plate_build_volume.max(0) += Slic3r::BuildVolume::SceneEpsilon;
6921 plate_build_volume.max(1) += Slic3r::BuildVolume::SceneEpsilon;
6922 plate_build_volume.max(2) += Slic3r::BuildVolume::SceneEpsilon;
6923 /*if (m_config != nullptr) {
6924 double h = m_config->opt_float("printable_height");
6925 plate_build_volume.min(2) = std::min(plate_build_volume.min(2), -h);
6926 plate_build_volume.max(2) = std::max(plate_build_volume.max(2), h);
6927 }*/
6928
6929 auto is_visible = [plate_idx, plate_build_volume](const GLVolume &v) {
6930 bool ret = v.printable;
6931 if (plate_idx >= 0) {
6932 bool contained = false;
6933 BoundingBoxf3 plate_bbox = plate_build_volume;
6934 plate_bbox.min(2) = -1e10;
6935 const BoundingBoxf3 &volume_bbox = v.transformed_convex_hull_bounding_box();
6936 if (plate_bbox.contains(volume_bbox) && (volume_bbox.max(2) > 0)) { contained = true; }
6937 ret &= contained;
6938 } else {
6939 ret &= (!v.shader_outside_printer_detection_enabled || !v.is_outside);
6940 }
6941 return ret;
6942 };
6943
6944 for (GLVolume *vol : volumes.volumes) {
6945 if (!vol->is_modifier && !vol->is_wipe_tower && (!thumbnail_params.parts_only || vol->composite_id.volume_id >= 0)) {
6946 if (is_visible(*vol)) { visible_volumes.emplace_back(vol); }
6947 }
6948 }
6949 BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: plate_idx %1% volumes size %2%, shader %3%, use_top_view=%4%, for_picking=%5%") % plate_idx %
6950 visible_volumes.size() % shader % (int)camera_view_angle_type % for_picking;
6951 } else {
6952 visible_volumes = volumes.volumes;
6953 }
6954 //BoundingBoxf3 volumes_box = plate_build_volume;
6955 BoundingBoxf3 volumes_box;
6956 volumes_box.min.z() = 0;
6957 volumes_box.max.z() = 0;
6958 if (!visible_volumes.empty()) {
6959 for (const GLVolume* vol : visible_volumes) {
6960 volumes_box.merge(vol->transformed_bounding_box());
6961 }
6962 }
6963 volumes_box.min.z() = -Slic3r::BuildVolume::SceneEpsilon;
6964 double width = volumes_box.max.x() - volumes_box.min.x();
6965 double depth = volumes_box.max.y() - volumes_box.min.y();
6966 double height = volumes_box.max.z() - volumes_box.min.z();
6967 volumes_box.max.x() = volumes_box.max.x() + width * 0.01f;
6968 volumes_box.min.x() = volumes_box.min.x() - width * 0.01f;
6969 volumes_box.max.y() = volumes_box.max.y() + depth * 0.01f;
6970 volumes_box.min.y() = volumes_box.min.y() - depth * 0.01f;
6971 volumes_box.max.z() = volumes_box.max.z() + height * 0.02f;
6972 volumes_box.min.z() = volumes_box.min.z() - height * 0.02f;
6973
6974 Camera camera;
6975 camera.set_type(camera_type);
6976 //BBS modify scene box to plate scene bounding box
6977 //plate_build_volume.min(2) = - plate_build_volume.max(2);
6978 if (thumbnail_params.use_plate_box) {
6979 camera.set_scene_box(plate_build_volume);
6980 }
6981
6982 camera.set_viewport(0, 0, thumbnail_data.width, thumbnail_data.height);
6983 camera.apply_viewport();
6984
6985 //BoundingBoxf3 plate_box = plate->get_bounding_box(false);
6986 //plate_box.min.z() = 0.0;
6987 //plate_box.max.z() = 0.0;
6988
6989 if (camera_view_angle_type == Camera::ViewAngleType::Top_Plate) {
6990 float center_x = (plate_build_volume.max(0) + plate_build_volume.min(0))/2;
6991 float center_y = (plate_build_volume.max(1) + plate_build_volume.min(1))/2;
6992 float distance_z = plate_build_volume.max(2) - plate_build_volume.min(2);
6993 Vec3d center(center_x, center_y, 0.f);
6994 double zoom_ratio, scale_x, scale_y;
6995
6996 scale_x = ((double)thumbnail_data.width)/(plate_build_volume.max(0) - plate_build_volume.min(0));
6997 scale_y = ((double)thumbnail_data.height)/(plate_build_volume.max(1) - plate_build_volume.min(1));
6998 zoom_ratio = (scale_x <= scale_y)?scale_x:scale_y;
6999 camera.look_at(center + distance_z * Vec3d::UnitZ(), center, Vec3d::UnitY());
7000 camera.set_zoom(zoom_ratio);
7001 //camera.select_view("top");
7002 }
7003 else {
7004 camera.select_view(camera_view_angle_type);
7005 camera.zoom_to_box(volumes_box);
7006 }
7007
7008 const Transform3d &view_matrix = camera.get_view_matrix();
7009 if (thumbnail_params.use_plate_box) {
7010 camera.apply_projection(plate_build_volume);
7011 }
7012 else {
7013 camera.apply_projection(volumes_box);
7014 }
7015
7016 //GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
7017 if (!for_picking && (shader == nullptr)) {
7018 BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail with no picking: shader is null, return directly");
7019 return;
7020 }
7021
7022 //if (thumbnail_params.transparent_background)
7023 glsafe(::glClearColor(0.f, 0.f, 0.f, 0.f));
7024
7025
7028 if (ban_light) {
7030 }
7031 const Transform3d &projection_matrix = camera.get_projection_matrix();
7032
7033 if (for_picking) {
7034 //if (OpenGLManager::can_multisample())
7035 // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer.
7036 // glsafe(::glDisable(GL_MULTISAMPLE));
7037 shader->start_using();
7038
7040
7041 static const GLfloat INV_255 = 1.0f / 255.0f;
7042
7043 // do not cull backfaces to show broken geometry, if any
7045
7046 for (GLVolume* vol : visible_volumes) {
7047 // Object picking mode. Render the object with a color encoding the object index.
7048 // we reserve color = (0,0,0) for occluders (as the printbed)
7049 // so we shift volumes' id by 1 to get the proper color
7050 //BBS: remove the bed picking logic
7051 unsigned int id = vol->model_object_ID;
7052 //unsigned int id = 1 + volume.second.first;
7053 unsigned int r = (id & (0x000000FF << 0)) >> 0;
7054 unsigned int g = (id & (0x000000FF << 8)) >> 8;
7055 unsigned int b = (id & (0x000000FF << 16)) >> 16;
7056 unsigned int a = 0xFF;
7057 vol->model.set_color({(GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255});
7058 /*curr_color[0] = (GLfloat)r * INV_255;
7059 curr_color[1] = (GLfloat)g * INV_255;
7060 curr_color[2] = (GLfloat)b * INV_255;
7061 curr_color[3] = (GLfloat)a * INV_255;
7062 shader->set_uniform("uniform_color", curr_color);*/
7063
7064 const bool is_active = vol->is_active;
7065 vol->is_active = true;
7066 vol->picking = true;
7067
7068 const Transform3d model_matrix = vol->world_matrix();
7069 shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
7070 shader->set_uniform("projection_matrix", projection_matrix);
7071 vol->simple_render(shader, model_objects, extruder_colors);
7072 vol->is_active = is_active;
7073 vol->picking = false;
7074 }
7075
7076 //glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
7077 //glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
7078
7080
7081 //if (OpenGLManager::can_multisample())
7082 // glsafe(::glEnable(GL_MULTISAMPLE));
7083 }
7084 else {
7085 shader->start_using();
7086 shader->set_uniform("emission_factor", 0.1f);
7087 shader->set_uniform("ban_light", ban_light);
7088 for (GLVolume* vol : visible_volumes) {
7089 //BBS set render color for thumbnails
7090 curr_color = vol->color;
7091
7092 ColorRGBA new_color = adjust_color_for_rendering(curr_color);
7093 if (ban_light) {
7094 new_color[3] =(255 - (vol->extruder_id -1))/255.0f;
7095 }
7096 vol->model.set_color(new_color);
7097 shader->set_uniform("volume_world_matrix", vol->world_matrix());
7098 //BBS set all volume to orange
7099 //shader->set_uniform("uniform_color", orange);
7100 /*if (plate_idx > 0) {
7101 shader->set_uniform("uniform_color", orange);
7102 }
7103 else {
7104 shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray);
7105 }*/
7106 // the volume may have been deactivated by an active gizmo
7107 const bool is_active = vol->is_active;
7108 vol->is_active = true;
7109 const Transform3d model_matrix = vol->world_matrix();
7110 shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
7111 shader->set_uniform("projection_matrix", projection_matrix);
7112 const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
7113 shader->set_uniform("view_normal_matrix", view_normal_matrix);
7114 vol->simple_render(shader, model_objects, extruder_colors, ban_light);
7115 vol->is_active = is_active;
7116 }
7117 shader->stop_using();
7118 }
7119
7121
7122 //don't render plate in thumbnail
7123 //plate->render( false, true, true);
7124
7125 // restore background color
7126 //if (thumbnail_params.transparent_background)
7127 // glsafe(::glClearColor(1.0f, 1.0f, 1.0f, 1.0f));
7128 BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: finished");
7129
7130 // Puts the canvas viewport back in place of the thumbnail one set above. The CLI renders
7131 // thumbnails with no application and no plater, so there is no canvas viewport to restore.
7132 if (wxTheApp != nullptr)
7133 if (Plater *plater = wxGetApp().plater(); plater != nullptr)
7135}
Slic3r::ColorRGBA adjust_color_for_rendering(const Slic3r::ColorRGBA &colors)
Definition 3DScene.cpp:112
static const float INV_255
Definition Color.cpp:14
const Camera & get_camera() const
Definition Plater.cpp:22567
khronos_float_t GLfloat
Definition gl.h:2066
static std::string orange
Definition UnsavedChangesDialog.cpp:103
std::vector< GLVolume * > GLVolumePtrs
Definition 3DScene.hpp:412
bool is_active(id view)
Definition MacIME.mm:26
void apply_viewport() const
Definition Camera.cpp:287
@ Top_Plate
Definition Camera.hpp:53

References adjust_color_for_rendering(), camera, Slic3r::center(), Slic3r::GLVolume::composite_id, Slic3r::BoundingBox3Base< PointType >::contains(), Slic3r::GUI::PartPlate::get_build_volume(), Slic3r::GUI::PartPlateList::get_plate(), GL_BLEND, GL_COLOR_BUFFER_BIT, GL_CULL_FACE, GL_DEPTH_BUFFER_BIT, GL_DEPTH_TEST, glClear, glClearColor, glDisable, glEnable, glsafe, Slic3r::ThumbnailData::height, INV_255, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GUI::orange, Slic3r::ThumbnailsParams::parts_only, Slic3r::ThumbnailsParams::plate_id, Slic3r::GUI::plater(), Slic3r::BuildVolume::SceneEpsilon, Slic3r::GLShaderProgram::set_uniform(), Slic3r::GLShaderProgram::start_using(), Slic3r::GLShaderProgram::stop_using(), Slic3r::GUI::Camera::Top_Plate, Slic3r::ThumbnailsParams::use_plate_box, Slic3r::GLVolume::CompositeID::volume_id, Slic3r::GLVolumeCollection::volumes, and Slic3r::ThumbnailData::width.

Referenced by render_thumbnail_framebuffer(), render_thumbnail_framebuffer_ext(), and render_thumbnail_legacy().

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

◆ render_thumbnail_legacy()

void Slic3r::GUI::GLCanvas3D::render_thumbnail_legacy ( ThumbnailData & thumbnail_data,
unsigned int w,
unsigned int h,
const ThumbnailsParams & thumbnail_params,
PartPlateList & partplate_list,
ModelObjectPtrs & model_objects,
const GLVolumeCollection & volumes,
std::vector< ColorRGBA > & extruder_colors,
GLShaderProgram * shader,
Camera::EType camera_type,
Camera::ViewAngleType camera_view_angle_type = Camera::ViewAngleType::Iso,
bool for_picking = false,
bool ban_light = false )
static
7363{
7364 // check that thumbnail size does not exceed the default framebuffer size
7365 /*const Size& cnv_size = get_canvas_size();
7366 unsigned int cnv_w = (unsigned int)cnv_size.get_width();
7367 unsigned int cnv_h = (unsigned int)cnv_size.get_height();
7368 if (w > cnv_w || h > cnv_h) {
7369 float ratio = std::min((float)cnv_w / (float)w, (float)cnv_h / (float)h);
7370 w = (unsigned int)(ratio * (float)w);
7371 h = (unsigned int)(ratio * (float)h);
7372 }*/
7373
7374 thumbnail_data.set(w, h);
7375 if (!thumbnail_data.is_valid())
7376 return;
7377
7378 render_thumbnail_internal(thumbnail_data, thumbnail_params, partplate_list, model_objects, volumes, extruder_colors, shader, camera_type, camera_view_angle_type, for_picking,
7379 ban_light);
7380
7381 glsafe(::glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)thumbnail_data.pixels.data()));
7382#if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
7383 debug_output_thumbnail(thumbnail_data);
7384#endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT
7385}

References GL_RGBA, GL_UNSIGNED_BYTE, glReadPixels, glsafe, Slic3r::ThumbnailData::is_valid(), Slic3r::ThumbnailData::pixels, render_thumbnail_internal(), and Slic3r::ThumbnailData::set().

Referenced by Slic3r::GUI::CalibUtils::process_and_store_3mf(), render_thumbnail(), and render_thumbnail().

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

◆ request_extra_frame()

◆ requires_check_outside_state()

void Slic3r::GUI::GLCanvas3D::requires_check_outside_state ( )
inline

References m_requires_check_outside_state.

Referenced by Slic3r::GUI::Plater::changed_object(), and Slic3r::GUI::Plater::on_config_change().

Here is the caller graph for this function:

◆ reset_all_gizmos()

void Slic3r::GUI::GLCanvas3D::reset_all_gizmos ( )
inline
1325{ m_gizmos.reset_all_states(); }

References m_gizmos.

◆ reset_clipping_planes_cache()

void Slic3r::GUI::GLCanvas3D::reset_clipping_planes_cache ( )
inline
1050{ m_sla_caps[0].triangles.clear(); m_sla_caps[1].triangles.clear(); }

References m_sla_caps.

◆ reset_explosion_ratio()

void Slic3r::GUI::GLCanvas3D::reset_explosion_ratio ( )
inline
981{ m_explosion_ratio = 1.0; }

References m_explosion_ratio.

◆ reset_gcode_layers_times_cache()

void Slic3r::GUI::GLCanvas3D::reset_gcode_layers_times_cache ( )
inline

◆ reset_gcode_toolpaths()

void Slic3r::GUI::GLCanvas3D::reset_gcode_toolpaths ( )
inline

References _set_shown_canvas_current(), and m_gcode_viewer.

Here is the call graph for this function:

◆ reset_layer_height_profile()

void Slic3r::GUI::GLCanvas3D::reset_layer_height_profile ( )
2269{
2270 wxGetApp().plater()->take_snapshot("Variable layer height - Reset");
2271 m_layers_editing.reset_layer_height_profile(*this);
2273 m_dirty = true;
2274}

References Slic3r::GUI::GLCanvas3D::LayersEditing::Completed, m_dirty, and m_layers_editing.

◆ reset_old_size()

void Slic3r::GUI::GLCanvas3D::reset_old_size ( )
inline
1454{ m_old_size = { 0, 0 }; }

References m_old_size.

◆ reset_select_plate_toolbar_selection()

void Slic3r::GUI::GLCanvas3D::reset_select_plate_toolbar_selection ( )
2298 {
2299 if (m_sel_plate_toolbar.m_all_plates_stats_item)
2300 m_sel_plate_toolbar.m_all_plates_stats_item->selected = false;
2301 if (wxGetApp().mainframe)
2302 wxGetApp().mainframe->update_slice_print_status(MainFrame::eEventSliceUpdate, true, true);
2303}
@ eEventSliceUpdate
Definition MainFrame.hpp:340

References Slic3r::GUI::MainFrame::eEventSliceUpdate, and m_sel_plate_toolbar.

◆ reset_sequential_print_clearance()

void Slic3r::GUI::GLCanvas3D::reset_sequential_print_clearance ( )
inline
1426 {
1427 m_sequential_print_clearance.set_visible(false);
1428 m_sequential_print_clearance.set_render_fill(false);
1429 //BBS: add the height logic
1430 m_sequential_print_clearance.set_polygons(Polygons(), std::vector<std::pair<Polygon, float>>());
1431 }
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22

References m_sequential_print_clearance.

Referenced by do_move(), and update_compacted_wipe_tower_clearance().

Here is the caller graph for this function:

◆ reset_shells()

void Slic3r::GUI::GLCanvas3D::reset_shells ( )
inline
1261{ m_gcode_viewer.reset_shell(); }

References m_gcode_viewer.

◆ reset_volumes()

void Slic3r::GUI::GLCanvas3D::reset_volumes ( )
1821{
1822 if (!m_initialized)
1823 return;
1824
1825 if (m_volumes.empty())
1826 return;
1827
1828 _set_current();
1829
1830 m_selection.clear();
1831 m_volumes.clear();
1832 m_section_view_caps.clear();
1833 m_dirty = true;
1834
1836}

References _set_current(), _set_warning_notification(), m_dirty, m_initialized, m_section_view_caps, m_selection, m_volumes, and ObjectOutside.

Referenced by ~GLCanvas3D(), and load_sla_preview().

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

◆ scene_bounding_box()

BoundingBoxf3 Slic3r::GUI::GLCanvas3D::scene_bounding_box ( ) const
2237{
2238 BoundingBoxf3 bb = volumes_bounding_box();
2239 bb.merge(m_bed.extended_bounding_box());
2240 double h = m_bed.build_volume().printable_height();
2241 //FIXME why -h?
2242 bb.min.z() = std::min(bb.min.z(), -h);
2243 bb.max.z() = std::max(bb.max.z(), h);
2244
2245 //BBS merge plate scene bounding box
2247 PartPlateList& plate = wxGetApp().plater()->get_partplate_list();
2248 bb.merge(plate.get_bounding_box());
2249 }
2250
2251 return bb;
2252}

References CanvasView3D, Slic3r::GUI::PartPlateList::get_bounding_box(), m_bed, m_canvas_type, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, and volumes_bounding_box().

Referenced by refresh_camera_scene_box().

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

◆ schedule_extra_frame()

void Slic3r::GUI::GLCanvas3D::schedule_extra_frame ( int milliseconds)
4605{
4606 // Schedule idle event right now
4607 if (milliseconds == 0)
4608 {
4609 // We want to wakeup idle event but most likely this is call inside render cycle so we need to wait
4610 if (m_in_render)
4611 milliseconds = 33;
4612 else {
4613 m_dirty = true;
4614 wxWakeUpIdle();
4615 return;
4616 }
4617 }
4618 int remaining_time = m_render_timer.GetInterval();
4619 // Timer is not running
4620 if (!m_render_timer.IsRunning()) {
4621 m_render_timer.StartOnce(milliseconds);
4622 // Timer is running - restart only if new period is shorter than remaining period
4623 } else {
4624 if (milliseconds + 20 < remaining_time) {
4625 m_render_timer.Stop();
4626 m_render_timer.StartOnce(milliseconds);
4627 }
4628 }
4629}

References m_dirty, m_in_render, and m_render_timer.

Referenced by on_idle(), Slic3r::GUI::NotificationManager::push_notification_data(), and Slic3r::GUI::NotificationManager::update_notifications().

Here is the caller graph for this function:

◆ select_all()

void Slic3r::GUI::GLCanvas3D::select_all ( )
3047{
3048 if (!m_gizmos.is_allow_select_all()) {
3049 return;
3050 }
3051 m_selection.add_all();
3052 m_dirty = true;
3053}

References m_dirty, m_gizmos, and m_selection.

◆ select_curr_plate_all()

void Slic3r::GUI::GLCanvas3D::select_curr_plate_all ( )
3029{
3030 m_selection.add_curr_plate();
3031 m_dirty = true;
3032}

References m_dirty, and m_selection.

◆ select_object_from_idx()

void Slic3r::GUI::GLCanvas3D::select_object_from_idx ( std::vector< int > & object_idxs)
3034 {
3035 m_selection.add_object_from_idx(object_idxs);
3036 m_dirty = true;
3037}

References m_dirty, and m_selection.

◆ select_plate()

void Slic3r::GUI::GLCanvas3D::select_plate ( )
2404{
2405 wxGetApp().plater()->get_partplate_list().select_plate_view();
2406 if (m_canvas != nullptr)
2407 m_canvas->Refresh();
2408}

References m_canvas.

◆ select_view()

void Slic3r::GUI::GLCanvas3D::select_view ( const std::string & direction)
2397{
2398 wxGetApp().plater()->get_camera().select_view(direction);
2399 if (m_canvas != nullptr)
2400 m_canvas->Refresh();
2401}

References m_canvas.

Referenced by _render_canvas_toolbar().

Here is the caller graph for this function:

◆ set_as_dirty()

◆ set_benchmarking()

void Slic3r::GUI::GLCanvas3D::set_benchmarking ( bool benchmarking)
inline
1390{ m_benchmarking = benchmarking; }

References m_benchmarking.

Referenced by Slic3r::GUI::anonymous_namespace{SceneBenchmark.cpp}::SceneBenchmarkDialog::begin_scene().

Here is the caller graph for this function:

◆ set_clipping_plane()

void Slic3r::GUI::GLCanvas3D::set_clipping_plane ( unsigned int id,
const ClippingPlane & plane )
inline
1043 {
1044 if (id < 2)
1045 {
1046 m_clipping_planes[id] = plane;
1047 m_sla_caps[id].reset();
1048 }
1049 }

References m_clipping_planes, and m_sla_caps.

Referenced by Slic3r::GUI::CommonGizmosDataObjects::InstancesHider::on_update().

Here is the caller graph for this function:

◆ set_collapse_toolbar()

void Slic3r::GUI::GLCanvas3D::set_collapse_toolbar ( GLToolbar * toolbar,
std::function< CollapseSide()> side )
2331{
2332 m_collapse_toolbar = toolbar;
2333 m_collapse_side = std::move(side);
2334}

References m_collapse_side, and m_collapse_toolbar.

◆ set_color_by()

void Slic3r::GUI::GLCanvas3D::set_color_by ( const std::string & value)
2200{
2201 m_color_by = value;
2202}

References m_color_by.

◆ set_color_clip_plane()

void Slic3r::GUI::GLCanvas3D::set_color_clip_plane ( const Vec3d & cp_normal,
double offset )
inline
1057{ m_volumes.set_color_clip_plane(cp_normal, offset); }

References m_volumes, and Slic3r::offset().

Here is the call graph for this function:

◆ set_color_clip_plane_colors()

void Slic3r::GUI::GLCanvas3D::set_color_clip_plane_colors ( const std::array< ColorRGBA, 2 > & colors)
inline
1058{ m_volumes.set_color_clip_plane_colors(colors); }

References m_volumes.

◆ set_config()

void Slic3r::GUI::GLCanvas3D::set_config ( const DynamicPrintConfig * config)
2165{
2166 m_config = config;
2167 m_layers_editing.set_config(config);
2168
2169 // Orca: Filament shrinkage compensation
2170 const Print *print = fff_print();
2171 if (print != nullptr)
2172 m_layers_editing.set_shrinkage_compensation(fff_print()->shrinkage_compensation());
2173}

References fff_print(), m_config, and m_layers_editing.

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

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

◆ set_context()

void Slic3r::GUI::GLCanvas3D::set_context ( wxGLContext * context)
inline
950{ m_context = context; }

References m_context.

◆ set_cursor()

void Slic3r::GUI::GLCanvas3D::set_cursor ( ECursorType type)
6261{
6262 if ((m_canvas != nullptr) && (m_cursor_type != type))
6263 {
6264 switch (type)
6265 {
6266 case Standard: { m_canvas->SetCursor(*wxSTANDARD_CURSOR); break; }
6267 case Cross: { m_canvas->SetCursor(*wxCROSS_CURSOR); break; }
6268 }
6269
6270 m_cursor_type = type;
6271 }
6272}

References Cross, m_canvas, m_cursor_type, and Standard.

◆ set_design_canvas()

void Slic3r::GUI::GLCanvas3D::set_design_canvas ( bool b)
inline
1111{ m_design_canvas = b; }

References m_design_canvas.

◆ set_gcode_view_type()

void Slic3r::GUI::GLCanvas3D::set_gcode_view_type ( libvgcode::EViewType type)
inline
1267{ return m_gcode_viewer.set_view_type(type); }

References m_gcode_viewer.

◆ set_imgui_scaling()

void Slic3r::GUI::GLCanvas3D::set_imgui_scaling ( )
7880{
7881 float font_size = wxGetApp().em_unit();
7882
7883#ifdef _WIN32
7884 // On Windows, if manually scaled here, rendering issues can occur when the system's Display
7885 // scaling is greater than 300% as the font's size gets to be to large. So, use imgui font
7886 // scaling instead (see: ImGuiWrapper::init_font() and issue #3401)
7887 font_size *= (font_size > 30.0f) ? 1.0f : 1.5f;
7888#else
7889 font_size *= 1.5f;
7890#endif
7891
7892#if ENABLE_RETINA_GL
7893 wxGetApp().imgui()->set_scaling(font_size, 1.0f, m_retina_helper->get_scale_factor());
7894#else
7895 wxGetApp().imgui()->set_scaling(font_size, m_canvas->GetContentScaleFactor(), 1.0f);
7896#endif
7897}

References m_canvas.

Referenced by _resize(), and Slic3r::GUI::MainFrame::GLResourcesPrebuild::build_step().

Here is the caller graph for this function:

◆ set_model()

void Slic3r::GUI::GLCanvas3D::set_model ( Model * model)
2176{
2177 m_model = model;
2178 m_selection.set_model(m_model);
2179}

References m_model, and m_selection.

◆ set_mouse_as_dragging()

void Slic3r::GUI::GLCanvas3D::set_mouse_as_dragging ( )
inline
1366{ m_mouse.dragging = true; }

References m_mouse.

◆ set_popup_menu_position()

void Slic3r::GUI::GLCanvas3D::set_popup_menu_position ( const Vec2d & position)
inline
1309{ m_popup_menu_positon = position; }

References m_popup_menu_positon.

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

Here is the caller graph for this function:

◆ set_process()

void Slic3r::GUI::GLCanvas3D::set_process ( BackgroundSlicingProcess * process)
inline
1024{ m_process = process; }
bool process(std::exception_ptr &eptr)
Definition EmbossJob.cpp:1427

References m_process.

◆ set_raycaster_gizmos_on_top()

void Slic3r::GUI::GLCanvas3D::set_raycaster_gizmos_on_top ( bool value)
inline
976 {
977 m_scene_raycaster.set_gizmos_on_top(value);
978 }

References m_scene_raycaster.

◆ set_section_view_ratio()

void Slic3r::GUI::GLCanvas3D::set_section_view_ratio ( double ratio)
1988{
1989 ratio = std::clamp(ratio, 0., 1.);
1990 if (ratio == m_section_view->ratio)
1991 return;
1992
1993 if (ratio == 0.)
1994 m_section_view->last_ratio = m_section_view->ratio;
1995 m_section_view->ratio = ratio;
1996 // Only the first cut faces the camera; later ones keep their angle until it is set again.
1997 if (m_section_view->normal.isZero())
1999 else
2001}

References _on_section_view_changed(), align_section_view_to_camera(), and m_section_view.

Referenced by _render_canvas_toolbar(), _render_section_view_panel(), on_mouse_wheel(), and toggle_section_view().

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

◆ set_selected_extruder()

void Slic3r::GUI::GLCanvas3D::set_selected_extruder ( int extruder)
inline
1336{ m_selected_extruder = extruder;}
int m_selected_extruder
Definition GLCanvas3D.hpp:811

References m_selected_extruder.

◆ set_selected_visible()

void Slic3r::GUI::GLCanvas3D::set_selected_visible ( bool visible)
3073{
3074 for (unsigned int i : m_selection.get_volume_idxs()) {
3075 GLVolume* volume = const_cast<GLVolume*>(m_selection.get_volume(i));
3076 volume->visible = visible;
3077 volume->color.a(visible ? 1.f : GLVolume::MODEL_HIDDEN_COL.a());
3078 volume->render_color.a(volume->color.a());
3079 volume->force_native_color = !visible;
3080 }
3081}
static ColorRGBA MODEL_HIDDEN_COL
Definition 3DScene.hpp:104

References Slic3r::ColorRGBA::a(), Slic3r::GLVolume::color, m_selection, Slic3r::GLVolume::MODEL_HIDDEN_COL, and Slic3r::GLVolume::render_color.

Here is the call graph for this function:

◆ set_sequential_print_clearance_polygons()

void Slic3r::GUI::GLCanvas3D::set_sequential_print_clearance_polygons ( const Polygons & polygons,
const std::vector< std::pair< Polygon, float > > & height_polygons )
inline
1442 {
1443 m_sequential_print_clearance.set_polygons(polygons, height_polygons);
1444 }

References m_sequential_print_clearance.

Referenced by update_compacted_wipe_tower_clearance(), and update_sequential_clearance().

Here is the caller graph for this function:

◆ set_sequential_print_clearance_render_fill()

void Slic3r::GUI::GLCanvas3D::set_sequential_print_clearance_render_fill ( bool render_fill)
inline
1437 {
1438 m_sequential_print_clearance.set_render_fill(render_fill);
1439 }

References m_sequential_print_clearance.

Referenced by update_compacted_wipe_tower_clearance(), and update_sequential_clearance().

Here is the caller graph for this function:

◆ set_sequential_print_clearance_visible()

void Slic3r::GUI::GLCanvas3D::set_sequential_print_clearance_visible ( bool visible)
inline
1433 {
1434 m_sequential_print_clearance.set_visible(visible);
1435 }

References m_sequential_print_clearance.

Referenced by update_compacted_wipe_tower_clearance(), and update_sequential_clearance().

Here is the caller graph for this function:

◆ set_shell_transparence()

void Slic3r::GUI::GLCanvas3D::set_shell_transparence ( float alpha = 0.2f)
3831 {
3832 m_gcode_viewer.set_shell_transparency(alpha);
3833
3834}

References m_gcode_viewer.

◆ set_shells_on_previewing()

void Slic3r::GUI::GLCanvas3D::set_shells_on_previewing ( bool is_preview)
inline
1262{ m_gcode_viewer.set_shells_on_preview(is_preview); }

References m_gcode_viewer.

◆ set_show_bed()

void Slic3r::GUI::GLCanvas3D::set_show_bed ( bool b)
inline
1112{ m_show_bed = b; }

References m_show_bed.

◆ set_slope_normal_angle()

void Slic3r::GUI::GLCanvas3D::set_slope_normal_angle ( float angle_in_deg)
inline
1410{ m_slope.set_normal_angle(angle_in_deg); }

References m_slope.

◆ set_studio_lighting()

void Slic3r::GUI::GLCanvas3D::set_studio_lighting ( bool on)
inline
952{ m_studio_lighting = on; }

References m_studio_lighting.

◆ set_tooltip()

void Slic3r::GUI::GLCanvas3D::set_tooltip ( const std::string & tooltip)
5630{
5631 if (m_canvas != nullptr)
5632 m_tooltip.set_text(tooltip);
5633}

References m_canvas, and m_tooltip.

Referenced by _render_frame().

Here is the caller graph for this function:

◆ set_type()

void Slic3r::GUI::GLCanvas3D::set_type ( ECanvasType type)
inline
951{ m_canvas_type = type; }

References m_canvas_type.

◆ set_use_clipping_planes()

void Slic3r::GUI::GLCanvas3D::set_use_clipping_planes ( bool use)
inline
1051{ m_use_clipping_planes = use; }

References m_use_clipping_planes.

Referenced by Slic3r::GUI::CommonGizmosDataObjects::InstancesHider::on_release(), and Slic3r::GUI::CommonGizmosDataObjects::InstancesHider::on_update().

Here is the caller graph for this function:

◆ set_use_color_clip_plane()

void Slic3r::GUI::GLCanvas3D::set_use_color_clip_plane ( bool use)
inline
1056{ m_volumes.set_use_color_clip_plane(use); }

References m_volumes.

◆ set_volumes_z_range()

void Slic3r::GUI::GLCanvas3D::set_volumes_z_range ( const std::array< double, 2 > & range)
inline
1249{ m_volumes.set_range(range[0] - 1e-6, range[1] + 1e-6); }

References m_volumes, and Slic3r::range().

Referenced by _render_gcode_overlay().

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

◆ share_section_view()

void Slic3r::GUI::GLCanvas3D::share_section_view ( const GLCanvas3D & owner)
inline
1066{ m_section_view = owner.m_section_view; }

References GLCanvas3D(), and m_section_view.

Here is the call graph for this function:

◆ show_labels()

void Slic3r::GUI::GLCanvas3D::show_labels ( bool show)
inline
1403{ m_labels.show(show); }

References m_labels.

◆ show_overhang()

void Slic3r::GUI::GLCanvas3D::show_overhang ( bool show)
inline
1406{ m_slope.globalUse(show); }

References m_slope.

◆ sla_print()

const SLAPrint * Slic3r::GUI::GLCanvas3D::sla_print ( ) const
12821{
12822 return (m_process == nullptr) ? nullptr : m_process->sla_print();
12823}

References m_process, and sla_print().

Referenced by _load_sla_shells(), _render_sla_slices(), load_sla_preview(), reload_scene(), and sla_print().

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

◆ smooth_layer_height_profile()

void Slic3r::GUI::GLCanvas3D::smooth_layer_height_profile ( const HeightProfileSmoothingParams & smoothing_params)
2285{
2286 wxGetApp().plater()->take_snapshot("Variable layer height - Smooth all");
2287 m_layers_editing.smooth_layer_height_profile(*this, smoothing_params);
2289 m_dirty = true;
2290}

References Slic3r::GUI::GLCanvas3D::LayersEditing::Completed, m_dirty, and m_layers_editing.

◆ timestamp_now()

int64_t Slic3r::GUI::GLCanvas3D::timestamp_now ( )
inlinestatic
1416 {
1417#ifdef _WIN32
1418 // Cheaper on Windows, calls GetSystemTimeAsFileTime()
1419 return wxGetUTCTimeMillis().GetValue();
1420#else
1421 // calls clock()
1422 return wxGetLocalTimeMillis().GetValue();
1423#endif
1424 }

Referenced by Slic3r::GUI::NotificationManager::HintNotification::init(), Slic3r::GUI::NotificationManager::PopNotification::init(), Slic3r::GUI::NotificationManager::render_notifications(), Slic3r::GUI::NotificationManager::PopNotification::reset_timer(), Slic3r::GUI::NotificationManager::URLDownloadNotification::set_percentage(), Slic3r::GUI::NotificationManager::SlicingProgressNotification::set_progress_state(), Slic3r::GUI::NotificationManager::update_notifications(), and Slic3r::GUI::NotificationManager::PopNotification::update_state().

Here is the caller graph for this function:

◆ toggle_model_objects_visibility()

void Slic3r::GUI::GLCanvas3D::toggle_model_objects_visibility ( bool visible,
const ModelObject * mo = nullptr,
int instance_idx = -1,
const ModelVolume * mv = nullptr )
2088{
2089 std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume);
2090 for (GLVolume* vol : m_volumes.volumes) {
2091 // BBS: add partplate logic
2092 if (vol->composite_id.object_id >= 1000 &&
2093 vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count()) { // wipe tower
2094 vol->is_active = (visible && mo == nullptr);
2095 }
2096 else {
2097 if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo)
2098 && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx)
2099 && (mv == nullptr || m_model->objects[vol->composite_id.object_id]->volumes[vol->composite_id.volume_id] == mv)) {
2100 vol->is_active = visible;
2101 if (!vol->is_modifier)
2102 vol->color.a(1.f);
2103
2104 if (instance_idx == -1) {
2105 vol->force_native_color = false;
2106 vol->force_neutral_color = false;
2107 } else {
2108 const GLGizmosManager& gm = get_gizmos_manager();
2109 auto gizmo_type = gm.get_current_type();
2110 if ( (gizmo_type == GLGizmosManager::FdmSupports
2111 || gizmo_type == GLGizmosManager::Seam
2112 || gizmo_type == GLGizmosManager::Cut
2113 || gizmo_type == GLGizmosManager::FuzzySkin)
2114 && !vol->is_modifier) {
2115 vol->force_neutral_color = true;
2116 }
2117 else if (gizmo_type == GLGizmosManager::BrimEars)
2118 vol->force_neutral_color = false;
2119 else if (gizmo_type == GLGizmosManager::MmSegmentation)
2120 vol->is_active = false;
2121 else
2122 vol->force_native_color = true;
2123 }
2124 }
2125 }
2126
2127 auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == vol->mesh_raycaster.get(); });
2128 if (it != raycasters->end())
2129 (*it)->set_active(vol->is_active);
2130 }
2131
2132 if (visible && !mo)
2133 toggle_sla_auxiliaries_visibility(true, mo, instance_idx);
2134
2135 if (!mo && !visible && !m_model->objects.empty() && (m_model->objects.size() > 1 || m_model->objects.front()->instances.size() > 1))
2137
2138 if (!mo && visible)
2140}
void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject *mo=nullptr, int instance_idx=-1)
Definition GLCanvas3D.cpp:2063

References _set_warning_notification(), Slic3r::ColorRGBA::a(), Slic3r::GUI::GLGizmosManager::BrimEars, Slic3r::GLVolume::color, Slic3r::GLVolume::composite_id, Slic3r::GUI::GLGizmosManager::Cut, Slic3r::GUI::GLGizmosManager::FdmSupports, Slic3r::GUI::GLGizmosManager::FuzzySkin, Slic3r::GUI::GLGizmosManager::get_current_type(), get_gizmos_manager(), get_raycasters_for_picking(), Slic3r::GLVolume::CompositeID::instance_id, m_model, m_volumes, Slic3r::GUI::GLGizmosManager::MmSegmentation, Slic3r::GLVolume::CompositeID::object_id, Slic3r::GUI::plater(), Slic3r::GUI::GLGizmosManager::Seam, SomethingNotShown, toggle_sla_auxiliaries_visibility(), Slic3r::GUI::SceneRaycaster::Volume, and Slic3r::GLVolume::CompositeID::volume_id.

Referenced by Slic3r::GUI::CommonGizmosDataObjects::InstancesHider::on_release(), and Slic3r::GUI::CommonGizmosDataObjects::InstancesHider::on_update().

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

◆ toggle_section_view()

void Slic3r::GUI::GLCanvas3D::toggle_section_view ( )
2004{
2005 const double last_ratio = m_section_view->last_ratio;
2006 set_section_view_ratio(is_section_view_active() ? 0. : last_ratio > 0. ? last_ratio : 0.5);
2007}

References is_section_view_active(), m_section_view, and set_section_view_ratio().

Referenced by _render_canvas_toolbar().

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

◆ toggle_selected_volume_visibility()

void Slic3r::GUI::GLCanvas3D::toggle_selected_volume_visibility ( bool selected_visible)
2035{
2036 m_render_sla_auxiliaries = !selected_visible;
2037 if (selected_visible) {
2038 const Selection::IndicesList &idxs = m_selection.get_volume_idxs();
2039 if (idxs.size() > 0) {
2040 for (GLVolume *vol : m_volumes.volumes) {
2041 if (vol->composite_id.object_id >= 1000 && vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count())
2042 continue; // the wipe tower
2043 if (vol->composite_id.volume_id >= 0) {
2044 vol->is_active = false;
2045 }
2046 }
2047 for (unsigned int idx : idxs) {
2048 GLVolume *v = const_cast<GLVolume *>(m_selection.get_volume(idx));
2049 v->is_active = true;
2050 }
2051 }
2052 } else { // show all
2053 for (GLVolume *vol : m_volumes.volumes) {
2054 if (vol->composite_id.object_id >= 1000 && vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count())
2055 continue; // the wipe tower
2056 if (vol->composite_id.volume_id >= 0) {
2057 vol->is_active = true;
2058 }
2059 }
2060 }
2061}

References Slic3r::GLVolume::composite_id, m_render_sla_auxiliaries, m_selection, m_volumes, Slic3r::GLVolume::CompositeID::object_id, Slic3r::GUI::plater(), and Slic3r::GLVolume::CompositeID::volume_id.

Here is the call graph for this function:

◆ toggle_sla_auxiliaries_visibility()

void Slic3r::GUI::GLCanvas3D::toggle_sla_auxiliaries_visibility ( bool visible,
const ModelObject * mo = nullptr,
int instance_idx = -1 )
2064{
2066 return;
2067
2068 m_render_sla_auxiliaries = visible;
2069
2070 std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume);
2071
2072 for (GLVolume* vol : m_volumes.volumes) {
2073 if (vol->composite_id.object_id >= 1000 &&
2074 vol->composite_id.object_id < 1000 + wxGetApp().plater()->get_partplate_list().get_plate_count())
2075 continue; // the wipe tower
2076 if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo)
2077 && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx)
2078 && vol->composite_id.volume_id < 0) {
2079 vol->is_active = visible;
2080 auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == vol->mesh_raycaster.get(); });
2081 if (it != raycasters->end())
2082 (*it)->set_active(vol->is_active);
2083 }
2084 }
2085}

References Slic3r::GLVolume::composite_id, current_printer_technology(), get_raycasters_for_picking(), Slic3r::GLVolume::CompositeID::instance_id, m_model, m_render_sla_auxiliaries, m_volumes, Slic3r::GLVolume::CompositeID::object_id, Slic3r::GUI::plater(), Slic3r::ptSLA, Slic3r::GUI::SceneRaycaster::Volume, and Slic3r::GLVolume::CompositeID::volume_id.

Referenced by Slic3r::GUI::CommonGizmosDataObjects::InstancesHider::on_update(), and toggle_model_objects_visibility().

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

◆ toggle_world_axes_visibility()

void Slic3r::GUI::GLCanvas3D::toggle_world_axes_visibility ( bool force_show = false)
2024{
2025 if (force_show) {
2026 m_show_world_axes = true;
2027 } else {
2029 }
2030 wxGetApp().app_config->set_bool("show_axes", m_show_world_axes);
2031 set_as_dirty();
2032}

References m_show_world_axes, and set_as_dirty().

Referenced by _render_canvas_toolbar().

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

◆ unbind_event_handlers()

void Slic3r::GUI::GLCanvas3D::unbind_event_handlers ( )
3950{
3951 if (m_canvas != nullptr && m_event_handlers_bound) {
3952 m_canvas->Unbind(wxEVT_SIZE, &GLCanvas3D::on_size, this);
3953 m_canvas->Unbind(wxEVT_IDLE, &GLCanvas3D::on_idle, this);
3954 m_canvas->Unbind(wxEVT_CHAR, &GLCanvas3D::on_char, this);
3955 m_canvas->Unbind(wxEVT_KEY_DOWN, &GLCanvas3D::on_key, this);
3956 m_canvas->Unbind(wxEVT_KEY_UP, &GLCanvas3D::on_key, this);
3957 m_canvas->Unbind(wxEVT_MOUSEWHEEL, &GLCanvas3D::on_mouse_wheel, this);
3958 m_canvas->Unbind(wxEVT_TIMER, &GLCanvas3D::on_timer, this);
3959 m_canvas->Unbind(EVT_GLCANVAS_RENDER_TIMER, &GLCanvas3D::on_render_timer, this);
3960 m_canvas->Unbind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this);
3961 m_canvas->Unbind(wxEVT_LEFT_UP, &GLCanvas3D::on_mouse, this);
3962 m_canvas->Unbind(wxEVT_MIDDLE_DOWN, &GLCanvas3D::on_mouse, this);
3963 m_canvas->Unbind(wxEVT_MIDDLE_UP, &GLCanvas3D::on_mouse, this);
3964 m_canvas->Unbind(wxEVT_RIGHT_DOWN, &GLCanvas3D::on_mouse, this);
3965 m_canvas->Unbind(wxEVT_RIGHT_UP, &GLCanvas3D::on_mouse, this);
3966 m_canvas->Unbind(wxEVT_MOTION, &GLCanvas3D::on_mouse, this);
3967 m_canvas->Unbind(wxEVT_ENTER_WINDOW, &GLCanvas3D::on_mouse, this);
3968 m_canvas->Unbind(wxEVT_LEAVE_WINDOW, &GLCanvas3D::on_mouse, this);
3969 m_canvas->Unbind(wxEVT_LEFT_DCLICK, &GLCanvas3D::on_mouse, this);
3970 m_canvas->Unbind(wxEVT_MIDDLE_DCLICK, &GLCanvas3D::on_mouse, this);
3971 m_canvas->Unbind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
3972 m_canvas->Unbind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
3973 m_canvas->Unbind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
3974 m_event_handlers_bound = false;
3975
3976 m_canvas->Unbind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
3977 m_canvas->Unbind(wxEVT_GESTURE_ZOOM, &GLCanvas3D::on_gesture, this);
3978 m_canvas->Unbind(wxEVT_GESTURE_ROTATE, &GLCanvas3D::on_gesture, this);
3979#if __WXOSX__
3980 initGestures(m_canvas->GetHandle(), nullptr);
3981#endif
3982 }
3983}

References Slic3r::GUI::initGestures(), m_canvas, m_event_handlers_bound, on_char(), on_gesture(), on_idle(), on_key(), on_mouse(), on_mouse_wheel(), on_paint(), on_render_timer(), on_set_focus(), on_size(), and on_timer().

Here is the call graph for this function:

◆ update_compacted_wipe_tower_clearance()

void Slic3r::GUI::GLCanvas3D::update_compacted_wipe_tower_clearance ( )
6316{
6318 return;
6319 const Print *print = fff_print();
6320 if (print == nullptr)
6321 return;
6322 const PrintConfig &config = print->config();
6323 if (config.print_sequence != PrintSequence::ByLayer || ! wipe_tower_sparse_layers_skipped(config) || ! print->has_wipe_tower())
6324 return;
6325
6326 PartPlateList &plate_list = wxGetApp().plater()->get_partplate_list();
6327 PartPlate *plate = plate_list.get_curr_plate();
6328 if (plate == nullptr)
6329 return;
6330 const int plate_id = plate_list.get_curr_plate_index();
6331
6332 // Once the tower has been generated the scene shows its real mesh with the brim merged in,
6333 // otherwise it is a bare estimated cube with no brim at all. Only the latter needs the brim added
6334 // here, and the width comes from WipeTowerData, the same source the preview box is sized from, so
6335 // the zone cannot be padded against a brim the preview was not built with.
6336 const bool preview_carries_brim = print->is_step_done(psWipeTower) && print->wipe_tower_data().wipe_tower_mesh_data.has_value();
6337 const double brim = preview_carries_brim ? 0. : double(print->wipe_tower_data(print->extruders().size()).brim_width);
6338 const double padding = compacted_tower_footprint_padding(config, brim);
6339
6340 // Tower footprint straight from the volume the user sees, so that dragging either the tower or an
6341 // object updates the zone on the very next frame.
6342 Polygon tower_footprint;
6343 for (const GLVolume *v : m_volumes.volumes) {
6344 if (! v->is_wipe_tower || v->object_idx() - 1000 != plate_id)
6345 continue;
6346 const BoundingBoxf3 bbox = v->transformed_convex_hull_bounding_box();
6347 tower_footprint = Polygon({ Point(scale_(bbox.min.x() - padding), scale_(bbox.min.y() - padding)),
6348 Point(scale_(bbox.max.x() + padding), scale_(bbox.min.y() - padding)),
6349 Point(scale_(bbox.max.x() + padding), scale_(bbox.max.y() + padding)),
6350 Point(scale_(bbox.min.x() - padding), scale_(bbox.max.y() + padding)) });
6351 break;
6352 }
6353
6354 const CompactedTowerZone zone = compacted_wipe_tower_zone(config, tower_footprint);
6355 if (zone.empty()) {
6357 return;
6358 }
6359
6360 // While dragging, outline every on-plate instance next to the tower ring, the way sequential print
6361 // outlines every object. Both carry half of the clearance, so the two outlines meeting is precisely
6362 // the moment that object goes over its limit - which is what makes the pair worth drawing at all.
6363 // The tier is per object, so a short object gets the narrow nozzle outline rather than the wide
6364 // body one it is not subject to; without that, a 3 mm object parked beside the tower would be drawn
6365 // deep inside the keep-out ring while passing the check. Only the instances that already exceed
6366 // allowed_rise also get a height limit plane.
6367 Polygons outlines;
6368 std::vector<std::pair<Polygon, float>> height_polygons;
6369 bool body_tier_used = false;
6370 const BoundingBox plate_bb = plate->get_bounding_box_crd();
6371 for (const ModelObject *model_object : m_model->objects) {
6372 for (size_t i = 0; i < model_object->instances.size(); ++i) {
6373 Geometry::Transformation trafo(model_object->instances[i]->get_transformation());
6374 const Vec3d offset = trafo.get_offset();
6375 trafo.set_offset(Vec3d(offset.x(), offset.y(), 0.0));
6376 const Polygon inst_hull = model_object->convex_hull_2d(trafo.get_matrix());
6377 if (inst_hull.points.empty() || ! plate_bb.overlap(inst_hull.bounding_box()))
6378 continue;
6379
6380 // Same tiers and the same rise measured from the plate as
6381 // Print::compacted_wipe_tower_clearance_valid(), so that the preview and the validation
6382 // that follows it never contradict each other.
6383 const double object_top = model_object->get_instance_max_z(i);
6384 const CompactedTowerClearance clearance = compacted_wipe_tower_clearance(config, zone, inst_hull, object_top);
6385 body_tier_used = body_tier_used || compacted_tower_body_tier(clearance);
6386
6387 const Polygon outline = compacted_wipe_tower_offender_outline(inst_hull, clearance.body_clearance);
6388 outlines.emplace_back(outline);
6389 if (object_top <= clearance.allowed_rise + EPSILON)
6390 continue;
6391 height_polygons.emplace_back(outline, float(clearance.allowed_rise));
6392 }
6393 }
6394
6395 Polygons polygons = compacted_wipe_tower_rings(zone, body_tier_used);
6396 append(polygons, outlines);
6397
6400 set_sequential_print_clearance_polygons(polygons, height_polygons);
6401}
void set_sequential_print_clearance_polygons(const Polygons &polygons, const std::vector< std::pair< Polygon, float > > &height_polygons)
Definition GLCanvas3D.hpp:1442
void set_sequential_print_clearance_render_fill(bool render_fill)
Definition GLCanvas3D.hpp:1437
void set_sequential_print_clearance_visible(bool visible)
Definition GLCanvas3D.hpp:1433
double compacted_tower_footprint_padding(const PrintConfig &config, double brim_width)
Definition Print.cpp:1220
CompactedTowerClearance compacted_wipe_tower_clearance(const PrintConfig &config, const CompactedTowerZone &zone, const Polygon &inst_hull, double object_rise)
Definition Print.cpp:1295
CompactedTowerZone compacted_wipe_tower_zone(const PrintConfig &config, const Polygon &tower_footprint)
Definition Print.cpp:1242
@ ByLayer
Definition PrintConfig.hpp:311
bool compacted_tower_body_tier(const CompactedTowerClearance &clearance)
Definition Print.hpp:1666
bool wipe_tower_sparse_layers_skipped(const PrintConfig &config)
Definition WipeTower.cpp:53
Polygons compacted_wipe_tower_rings(const CompactedTowerZone &zone, bool any_body_tier)
Definition Print.cpp:1234
void append(std::vector< T, Alloc > &dest, const std::vector< T, Alloc2 > &src)
Definition libslic3r.h:157
Polygon compacted_wipe_tower_offender_outline(const Polygon &inst_hull, double body_clearance)
Definition Print.cpp:1337

References Slic3r::CompactedTowerClearance::allowed_rise, Slic3r::append(), Slic3r::CompactedTowerClearance::body_clearance, Slic3r::MultiPoint::bounding_box(), Slic3r::WipeTowerData::brim_width, Slic3r::ByLayer, Slic3r::compacted_tower_body_tier(), Slic3r::compacted_tower_footprint_padding(), Slic3r::compacted_wipe_tower_clearance(), Slic3r::compacted_wipe_tower_offender_outline(), Slic3r::compacted_wipe_tower_rings(), Slic3r::compacted_wipe_tower_zone(), Slic3r::Print::config(), Slic3r::ModelObject::convex_hull_2d(), current_printer_technology(), Slic3r::CompactedTowerZone::empty(), EPSILON, Slic3r::Print::extruders(), fff_print(), Slic3r::GUI::PartPlate::get_bounding_box_crd(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlateList::get_curr_plate_index(), Slic3r::ModelObject::get_instance_max_z(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::Geometry::Transformation::get_offset(), Slic3r::Print::has_wipe_tower(), Slic3r::ModelObject::instances, Slic3r::Print::is_step_done(), m_model, m_volumes, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GLVolume::object_idx(), Slic3r::offset(), Slic3r::BoundingBoxBase< PointType, APointsType >::overlap(), Slic3r::MultiPoint::points, Slic3r::psWipeTower, Slic3r::ptFFF, reset_sequential_print_clearance(), scale_, Slic3r::Geometry::Transformation::set_offset(), set_sequential_print_clearance_polygons(), set_sequential_print_clearance_render_fill(), set_sequential_print_clearance_visible(), Slic3r::GLVolume::transformed_convex_hull_bounding_box(), Slic3r::Print::wipe_tower_data(), Slic3r::WipeTowerData::wipe_tower_mesh_data, and Slic3r::wipe_tower_sparse_layers_skipped().

Referenced by on_mouse().

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

◆ update_gcode_sequential_view_current()

void Slic3r::GUI::GLCanvas3D::update_gcode_sequential_view_current ( unsigned int first,
unsigned int last )
inline
1011{ m_gcode_viewer.update_sequential_view_current(first, last); }

References m_gcode_viewer.

◆ update_gizmos_on_off_state()

void Slic3r::GUI::GLCanvas3D::update_gizmos_on_off_state ( )
6089{
6090 set_as_dirty();
6091 m_gizmos.update_data();
6092 m_gizmos.refresh_on_off_state();
6093}

References m_gizmos, and set_as_dirty().

Here is the call graph for this function:

◆ update_instance_printable_state_for_object()

void Slic3r::GUI::GLCanvas3D::update_instance_printable_state_for_object ( size_t obj_idx)
2143{
2144 ModelObject* model_object = m_model->objects[obj_idx];
2145 for (int inst_idx = 0; inst_idx < (int)model_object->instances.size(); ++inst_idx) {
2146 ModelInstance* instance = model_object->instances[inst_idx];
2147
2148 for (GLVolume* volume : m_volumes.volumes) {
2149 if ((volume->object_idx() == (int)obj_idx) && (volume->instance_idx() == inst_idx))
2150 volume->printable = instance->printable;
2151 if (!volume->printable) {
2152 volume->render_color = GLVolume::UNPRINTABLE_COLOR;
2153 }
2154 }
2155 }
2156}
static ColorRGBA UNPRINTABLE_COLOR
Definition 3DScene.hpp:98

References Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, m_model, m_volumes, Slic3r::GLVolume::object_idx(), Slic3r::ModelInstance::printable, Slic3r::GLVolume::render_color, and Slic3r::GLVolume::UNPRINTABLE_COLOR.

Referenced by anonymous_namespace{EmbossJob.cpp}::create_volume(), and update_instance_printable_state_for_objects().

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

◆ update_instance_printable_state_for_objects()

void Slic3r::GUI::GLCanvas3D::update_instance_printable_state_for_objects ( const std::vector< size_t > & object_idxs)
2159{
2160 for (size_t obj_idx : object_idxs)
2162}
void update_instance_printable_state_for_object(size_t obj_idx)
Definition GLCanvas3D.cpp:2142

References update_instance_printable_state_for_object().

Here is the call graph for this function:

◆ update_render_colors()

void Slic3r::GUI::GLCanvas3D::update_render_colors ( )
staticprivate
200{
202}
static ColorRGBA from_ImVec4(const ImVec4 &color)
Definition ImGuiWrapper.cpp:2254

References Slic3r::RenderColor::colors, DEFAULT_BG_LIGHT_COLOR, Slic3r::GUI::ImGuiWrapper::from_ImVec4(), and RenderCol_3D_Background.

Referenced by _render_style_editor().

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

◆ update_sequential_clearance()

void Slic3r::GUI::GLCanvas3D::update_sequential_clearance ( )
6404{
6406 return;
6407
6408 if (m_gizmos.is_dragging())
6409 return;
6410
6411 // collects instance transformations from volumes
6412 // first define temporary cache
6413 unsigned int instances_count = 0;
6414 std::vector<std::vector<std::optional<Geometry::Transformation>>> instance_transforms;
6415 for (size_t obj = 0; obj < m_model->objects.size(); ++obj) {
6416 instance_transforms.emplace_back(std::vector<std::optional<Geometry::Transformation>>());
6417 const ModelObject* model_object = m_model->objects[obj];
6418 for (size_t i = 0; i < model_object->instances.size(); ++i) {
6419 instance_transforms[obj].emplace_back(std::optional<Geometry::Transformation>());
6420 ++instances_count;
6421 }
6422 }
6423
6424 //if (instances_count == 1)
6425 // return;
6426
6427 // second fill temporary cache with data from volumes
6428 for (const GLVolume* v : m_volumes.volumes) {
6429 if (v->is_modifier || v->is_wipe_tower)
6430 continue;
6431
6432 auto& transform = instance_transforms[v->object_idx()][v->instance_idx()];
6433 if (!transform.has_value())
6434 transform = v->get_instance_transformation();
6435 }
6436
6437 // calculates objects 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
6438 // this is done only the first time this method is called while moving the mouse,
6439 // the results are then cached for following displacements
6441 m_sequential_print_clearance.m_hull_2d_cache.clear();
6442 auto [object_skirt_offset, _] = fff_print()->object_skirt_offset();
6443 float shrink_factor;
6444 if (fff_print()->is_all_objects_are_short())
6445 shrink_factor = scale_(std::max(0.5f * MAX_OUTER_NOZZLE_DIAMETER, object_skirt_offset) - 0.1);
6446 else
6447 shrink_factor = static_cast<float>(scale_(0.5 * fff_print()->config().extruder_clearance_radius.value + object_skirt_offset - 0.1));
6448
6449 double mitter_limit = scale_(0.1);
6450 m_sequential_print_clearance.m_hull_2d_cache.reserve(m_model->objects.size());
6451 for (size_t i = 0; i < m_model->objects.size(); ++i) {
6452 ModelObject* model_object = m_model->objects[i];
6453 ModelInstance* model_instance0 = model_object->instances.front();
6454 Polygon hull_no_offset = model_object->convex_hull_2d(Geometry::assemble_transform({ 0.0, 0.0, model_instance0->get_offset().z() }, model_instance0->get_rotation(),
6455 model_instance0->get_scaling_factor(), model_instance0->get_mirror()));
6456 auto tmp = offset(hull_no_offset,
6457 // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
6458 // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
6459 shrink_factor,
6460 jtRound, mitter_limit);
6461 Polygon hull_2d = !tmp.empty() ? tmp.front() : hull_no_offset;// tmp may be empty due to clipper's bug, see STUDIO-2452
6462
6463 Pointf3s& cache_hull_2d = m_sequential_print_clearance.m_hull_2d_cache.emplace_back(Pointf3s());
6464 cache_hull_2d.reserve(hull_2d.points.size());
6465 for (const Point& p : hull_2d.points) {
6466 cache_hull_2d.emplace_back(unscale<double>(p.x()), unscale<double>(p.y()), 0.0);
6467 }
6468 }
6470 }
6471
6472 // calculates instances 2d hulls (see also: Print::sequential_print_horizontal_clearance_valid())
6473 //BBS: add the height logic
6474 PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
6475 Polygons polygons;
6476 polygons.reserve(instances_count);
6477 std::vector<SequentialClearanceInstance> convex_and_bounding_boxes;
6478 convex_and_bounding_boxes.reserve(instances_count);
6479 std::map<ObjectID, int> print_order;
6480 for (const PrintObject* print_object : fff_print()->objects())
6481 for (const PrintInstance& instance : print_object->instances())
6482 print_order.emplace(instance.model_instance->id(), instance.model_instance->arrange_order);
6483
6484 for (size_t i = 0; i < instance_transforms.size(); ++i) {
6485 const size_t first_instance = convex_and_bounding_boxes.size();
6486 const auto& instances = instance_transforms[i];
6487 double rotation_z0 = instances.front()->get_rotation().z();
6488 int index = 0;
6489 for (const auto& instance : instances) {
6490 Geometry::Transformation transformation;
6491 const Vec3d& offset = instance->get_offset();
6492 transformation.set_offset({ offset.x(), offset.y(), 0.0 });
6493 transformation.set_rotation(Z, instance->get_rotation().z() - rotation_z0);
6494 const Transform3d& trafo = transformation.get_matrix();
6495 const Pointf3s& hull_2d = m_sequential_print_clearance.m_hull_2d_cache[i];
6496 Points inst_pts;
6497 inst_pts.reserve(hull_2d.size());
6498 for (size_t j = 0; j < hull_2d.size(); ++j) {
6499 const Vec3d p = trafo * hull_2d[j];
6500 inst_pts.emplace_back(scaled<double>(p.x()), scaled<double>(p.y()));
6501 }
6502 Polygon convex_hull(std::move(inst_pts));
6503 BoundingBox bouding_box = convex_hull.bounding_box();
6504 BoundingBox plate_bb = plate->get_bounding_box_crd();
6505 const ObjectID instance_id = m_model->objects[i]->instances[index]->id();
6506 double instance_height = m_model->objects[i]->get_instance_max_z(index++);
6507 //skip the object for not current plate
6508 if (!plate_bb.overlap(bouding_box))
6509 continue;
6510 convex_and_bounding_boxes.push_back({instance_height, bouding_box, convex_hull, instance_id});
6511 polygons.emplace_back(std::move(convex_hull));
6512 }
6513 sort_sequential_clearance_instances(convex_and_bounding_boxes.begin() + first_instance, convex_and_bounding_boxes.end(), print_order);
6514 }
6515
6516 const auto& config = fff_print()->config();
6517 const auto height_polygons = sequential_clearance_height_polygons(convex_and_bounding_boxes, config.printable_height,
6518 config.extruder_clearance_height_to_lid, config.extruder_clearance_height_to_rod);
6519
6520 // sends instances 2d hulls to be rendered
6523 set_sequential_print_clearance_polygons(polygons, height_polygons);
6524}
#define _(s)
Definition 3mf.cpp:306
#define MAX_OUTER_NOZZLE_DIAMETER
Definition Print.hpp:72
BoundingBox bounding_box() const
Definition MultiPoint.cpp:100
bool empty() const
Definition MultiPoint.hpp:51
std::tuple< float, float > object_skirt_offset(double margin_height=0) const
Definition Print.cpp:5796
const PrintConfig & config() const
Definition Print.hpp:1131
void sort_sequential_clearance_instances(std::vector< SequentialClearanceInstance >::iterator first, std::vector< SequentialClearanceInstance >::iterator last, const std::map< ObjectID, int > &print_order)
Definition SequentialPrintClearance.hpp:25
std::vector< std::pair< Polygon, float > > sequential_clearance_height_polygons(const std::vector< SequentialClearanceInstance > &instances, double printable_height, double height_to_lid, double height_to_rod)
Definition SequentialPrintClearance.hpp:41
Polygon convex_hull(Points pts)
Definition ConvexHull.cpp:21
@ jtRound
Definition ClipperUtils.hpp:21
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:73
Linef3 transform(const Linef3 &line, const Transform3d &t)
Definition Line.cpp:15

References _, Slic3r::Geometry::assemble_transform(), Slic3r::ByLayer, Slic3r::Print::config(), Slic3r::Geometry::convex_hull(), Slic3r::ModelObject::convex_hull_2d(), current_printer_technology(), Slic3r::MultiPoint::empty(), fff_print(), Slic3r::GUI::PartPlate::get_bounding_box_crd(), Slic3r::GLVolume::get_instance_transformation(), Slic3r::Geometry::Transformation::get_matrix(), Slic3r::ModelInstance::get_mirror(), Slic3r::ModelInstance::get_offset(), Slic3r::ModelInstance::get_rotation(), Slic3r::ModelInstance::get_scaling_factor(), Slic3r::GLVolume::instance_idx(), Slic3r::ModelObject::instances, Slic3r::jtRound, m_gizmos, m_model, m_sequential_print_clearance, m_sequential_print_clearance_first_displacement, m_volumes, MAX_OUTER_NOZZLE_DIAMETER, Slic3r::GLVolume::object_idx(), Slic3r::Print::object_skirt_offset(), Slic3r::offset(), Slic3r::BoundingBoxBase< PointType, APointsType >::overlap(), Slic3r::MultiPoint::points, Slic3r::print_sequence(), Slic3r::ptFFF, scale_, Slic3r::scaled(), Slic3r::GUI::sequential_clearance_height_polygons(), Slic3r::Geometry::Transformation::set_offset(), Slic3r::Geometry::Transformation::set_rotation(), set_sequential_print_clearance_polygons(), set_sequential_print_clearance_render_fill(), set_sequential_print_clearance_visible(), Slic3r::GUI::sort_sequential_clearance_instances(), Slic3r::transform(), Slic3r::unscale(), and Slic3r::Z.

Referenced by on_mouse().

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

◆ update_shortcut_tooltips()

void Slic3r::GUI::GLCanvas3D::update_shortcut_tooltips ( )
7649{
7650 const ShortcutRegistry& shortcuts = wxGetApp().shortcuts();
7651 m_main_toolbar.set_tooltip(m_main_toolbar.get_item_id("add"), shortcuts.with_key(_u8L("Add"), Shortcut::ImportModel));
7652 m_main_toolbar.set_tooltip(m_main_toolbar.get_item_id("orient"), shortcuts.with_key(_u8L("Auto orient all/selected objects"), Shortcut::Orient) + "\n" + shortcuts.with_key(_u8L("Auto orient all objects on current plate"), Shortcut::OrientPlate));
7653 m_main_toolbar.set_tooltip(m_main_toolbar.get_item_id("arrange"), shortcuts.with_key(_u8L("Arrange all objects"), Shortcut::Arrange) + "\n" + shortcuts.with_key(_u8L("Arrange objects on selected plates"), Shortcut::ArrangePlate));
7654 m_main_toolbar.set_tooltip(m_main_toolbar.get_item_id("more"), shortcuts.with_key(_u8L("Add instance"), Shortcut::AddInstance));
7655 m_main_toolbar.set_tooltip(m_main_toolbar.get_item_id("fewer"), shortcuts.with_key(_u8L("Remove instance"), Shortcut::RemoveInstance));
7656}
@ ImportModel
Definition Shortcuts.hpp:27

References _u8L, Slic3r::GUI::AddInstance, Slic3r::GUI::Arrange, Slic3r::GUI::ArrangePlate, Slic3r::GUI::ImportModel, m_main_toolbar, Slic3r::GUI::Orient, Slic3r::GUI::OrientPlate, Slic3r::GUI::RemoveInstance, and Slic3r::GUI::ShortcutRegistry::with_key().

Referenced by _init_main_toolbar().

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

◆ update_ui_from_settings()

void Slic3r::GUI::GLCanvas3D::update_ui_from_settings ( )
6118{
6119 m_dirty = true;
6120
6121#if __APPLE__
6122 // Update OpenGL scaling on OSX after the user toggled the "use_retina_opengl" settings in Preferences dialog.
6123 const float orig_scaling = m_retina_helper->get_scale_factor();
6124
6125 const bool use_retina = true;
6126 BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Use Retina OpenGL: " << use_retina;
6127 m_retina_helper->set_use_retina(use_retina);
6128 const float new_scaling = m_retina_helper->get_scale_factor();
6129
6130 if (new_scaling != orig_scaling) {
6131 BOOST_LOG_TRIVIAL(debug) << "GLCanvas3D: Scaling factor: " << new_scaling;
6132
6133 Camera& camera = wxGetApp().plater()->get_camera();
6134 camera.set_zoom(camera.get_zoom() * new_scaling / orig_scaling);
6136 }
6137#endif // ENABLE_RETINA_GL
6138}

References _refresh_if_shown_on_screen(), camera, and m_dirty.

Here is the call graph for this function:

◆ update_volumes_colors_by_extruder()

void Slic3r::GUI::GLCanvas3D::update_volumes_colors_by_extruder ( )
2411{
2412 if (m_config != nullptr)
2413 m_volumes.update_colors_by_extruder(m_config);
2414}

References m_config, and m_volumes.

Referenced by _load_sla_shells(), and reload_scene().

Here is the caller graph for this function:

◆ use_slope()

void Slic3r::GUI::GLCanvas3D::use_slope ( bool use)
inline
1409{ m_slope.use(use); }

References m_slope.

◆ volumes_bounding_box()

BoundingBoxf3 Slic3r::GUI::GLCanvas3D::volumes_bounding_box ( bool current_plate_only = false) const
2210{
2211 BoundingBoxf3 bb;
2212 BoundingBoxf3 expand_part_plate_list_box;
2214 if (is_limit) {
2215 if (current_plate_only) {
2216 expand_part_plate_list_box = _current_plate_box();
2217 } else {
2218 auto plate_list_box = wxGetApp().plater()->get_partplate_list().get_bounding_box();
2219 auto horizontal_radius = 0.5 * sqrt(std::pow(plate_list_box.min[0] - plate_list_box.max[0], 2) + std::pow(plate_list_box.min[1] - plate_list_box.max[1], 2));
2220 const float scale = 2;
2221 expand_part_plate_list_box.merge(plate_list_box.min - scale * Vec3d(horizontal_radius, horizontal_radius, 0));
2222 expand_part_plate_list_box.merge(plate_list_box.max + scale * Vec3d(horizontal_radius, horizontal_radius, 0));
2223 }
2224 }
2225 for (const GLVolume *volume : m_volumes.volumes) {
2226 if (!m_apply_zoom_to_volumes_filter || ((volume != nullptr) && volume->zoom_to_volumes)) {
2227 const auto v_bb = volume->transformed_bounding_box();
2228 if (is_limit && !expand_part_plate_list_box.overlap(v_bb))
2229 continue;
2230 bb.merge(v_bb);
2231 }
2232 }
2233 return bb;
2234}

References _current_plate_box(), CanvasAssembleView, m_apply_zoom_to_volumes_filter, m_canvas_type, m_volumes, Slic3r::BoundingBox3Base< PointType >::merge(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::overlap(), scale(), and Slic3r::GLVolume::transformed_bounding_box().

Referenced by _get_section_view_plane(), _max_bounding_box(), get_camera_orbit_target(), Slic3r::GUI::anonymous_namespace{SceneBenchmark.cpp}::SceneBenchmarkDialog::on_timer(), scene_bounding_box(), and zoom_to_volumes().

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

◆ zoom_to_bed()

void Slic3r::GUI::GLCanvas3D::zoom_to_bed ( )
2346{
2347 BoundingBoxf3 box = m_bed.build_volume().bounding_volume();
2348 box.min.z() = 0.0;
2349 box.max.z() = 0.0;
2351}
static const double DefaultCameraZoomToBedMarginFactor
Definition GLCanvas3D.hpp:241

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

Referenced by _render_canvas_toolbar(), _render_frame(), _render_imgui_select_plate_toolbar(), and Slic3r::GUI::MainFrame::add_common_view_menu_items().

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

◆ zoom_to_gcode()

void Slic3r::GUI::GLCanvas3D::zoom_to_gcode ( )
2367{
2368 _zoom_to_box(m_gcode_viewer.get_paths_bounding_box(), 1.05);
2369}

References _zoom_to_box(), and m_gcode_viewer.

Here is the call graph for this function:

◆ zoom_to_plate()

void Slic3r::GUI::GLCanvas3D::zoom_to_plate ( int plate_idx = -1)
2372{
2373 BoundingBoxf3 box;
2375 plate_idx = REQUIRES_ZOOM_TO_CUR_PLATE;
2376 if (plate_idx == REQUIRES_ZOOM_TO_ALL_PLATE) {
2377 box = wxGetApp().plater()->get_partplate_list().get_bounding_box();
2378 box.min.z() = 0.0;
2379 box.max.z() = 0.0;
2381 } else {
2382 PartPlate* plate = nullptr;
2383 if (plate_idx == REQUIRES_ZOOM_TO_CUR_PLATE) {
2384 plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
2385 }else {
2386 assert(plate_idx >= 0 && plate_idx < wxGetApp().plater()->get_partplate_list().get_plate_count());
2387 plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
2388 }
2389 box = plate->get_bounding_box(true);
2390 box.min.z() = 0.0;
2391 box.max.z() = 0.0;
2393 }
2394}
#define REQUIRES_ZOOM_TO_ALL_PLATE
Definition Camera.hpp:21
static const double DefaultCameraZoomToPlateMarginFactor
Definition GLCanvas3D.hpp:242

References _hides_inactive_plates(), _zoom_to_box(), DefaultCameraZoomToPlateMarginFactor, Slic3r::GUI::PartPlate::get_bounding_box(), Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::max, Slic3r::BoundingBoxBase< PointType, std::vector< PointType > >::min, Slic3r::GUI::plater(), REQUIRES_ZOOM_TO_ALL_PLATE, and REQUIRES_ZOOM_TO_CUR_PLATE.

Referenced by _render_canvas_toolbar(), and _render_frame().

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

◆ zoom_to_selection()

void Slic3r::GUI::GLCanvas3D::zoom_to_selection ( )
2361{
2362 if (!m_selection.is_empty())
2363 _zoom_to_box(m_selection.get_bounding_box());
2364}

References _zoom_to_box(), and m_selection.

Referenced by _render_canvas_toolbar().

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

◆ zoom_to_volumes()

void Slic3r::GUI::GLCanvas3D::zoom_to_volumes ( )

References _zoom_to_box(), m_apply_zoom_to_volumes_filter, and volumes_bounding_box().

Referenced by _render_canvas_toolbar(), _render_frame(), and Slic3r::GUI::DesignSketchTool::on_mouse_impl().

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

Member Data Documentation

◆ assembly_view_count

int Slic3r::GUI::GLCanvas3D::assembly_view_count = 0
private

◆ auto_arrange_count

int Slic3r::GUI::GLCanvas3D::auto_arrange_count = 0
private

◆ auto_orient_count

int Slic3r::GUI::GLCanvas3D::auto_orient_count = 0
private

Referenced by _init_main_toolbar().

◆ camera

◆ custom_height_count

int Slic3r::GUI::GLCanvas3D::custom_height_count = 0
private

◆ DefaultCameraZoomToBedMarginFactor

const double Slic3r::GUI::GLCanvas3D::DefaultCameraZoomToBedMarginFactor = 2.00
staticprivate

◆ DefaultCameraZoomToBoxMarginFactor

const double Slic3r::GUI::GLCanvas3D::DefaultCameraZoomToBoxMarginFactor = 1.25
staticprivate

◆ DefaultCameraZoomToPlateMarginFactor

const double Slic3r::GUI::GLCanvas3D::DefaultCameraZoomToPlateMarginFactor = 1.25
staticprivate

◆ m_alt_wheel_used

bool Slic3r::GUI::GLCanvas3D::m_alt_wheel_used { false }
private
722{ false };

Referenced by on_key(), and on_mouse_wheel().

◆ m_apply_zoom_to_volumes_filter

bool Slic3r::GUI::GLCanvas3D::m_apply_zoom_to_volumes_filter
private

◆ m_arrange_settings_fff

ArrangeSettings Slic3r::GUI::GLCanvas3D::m_arrange_settings_fff
private

◆ m_arrange_settings_fff_seq_print

ArrangeSettings Slic3r::GUI::GLCanvas3D::m_arrange_settings_fff_seq_print
private

◆ m_arrange_settings_sla

ArrangeSettings Slic3r::GUI::GLCanvas3D::m_arrange_settings_sla
private

◆ m_assemble_view_toolbar

◆ m_axes

Bed3D::Axes Slic3r::GUI::GLCanvas3D::m_axes
private

◆ m_background

GLModel Slic3r::GUI::GLCanvas3D::m_background

◆ m_bed

◆ m_benchmarking

bool Slic3r::GUI::GLCanvas3D::m_benchmarking { false }
private

◆ m_cad_grid_bb

BoundingBoxf Slic3r::GUI::GLCanvas3D::m_cad_grid_bb
private

Referenced by _render_cad_grid().

◆ m_cad_grid_center

Vec2d Slic3r::GUI::GLCanvas3D::m_cad_grid_center
private

Referenced by _render_cad_grid().

◆ m_cad_grid_major

GLModel Slic3r::GUI::GLCanvas3D::m_cad_grid_major
private

Referenced by _render_cad_grid().

◆ m_cad_grid_minor

GLModel Slic3r::GUI::GLCanvas3D::m_cad_grid_minor
private

Referenced by _render_cad_grid().

◆ m_cad_grid_valid

bool Slic3r::GUI::GLCanvas3D::m_cad_grid_valid {false}
private
697{false};

Referenced by _render_cad_grid().

◆ m_camera_clipping_plane

ClippingPlane Slic3r::GUI::GLCanvas3D::m_camera_clipping_plane
private

Referenced by _render_objects().

◆ m_camera_movement

bool Slic3r::GUI::GLCanvas3D::m_camera_movement
private

◆ m_canvas

◆ m_canvas_toolbar_pos

Vec2i32 Slic3r::GUI::GLCanvas3D::m_canvas_toolbar_pos = {140, 5}
mutableprivate
669{140, 5};

Referenced by _render_3d_navigator(), and _render_canvas_toolbar().

◆ m_canvas_type

◆ m_center_of_mass

CenterOfMass Slic3r::GUI::GLCanvas3D::m_center_of_mass
private

◆ m_clipping_planes

std::array<ClippingPlane, 2> Slic3r::GUI::GLCanvas3D::m_clipping_planes
private

◆ m_collapse_side

std::function<CollapseSide()> Slic3r::GUI::GLCanvas3D::m_collapse_side
private

◆ m_collapse_toolbar

GLToolbar* Slic3r::GUI::GLCanvas3D::m_collapse_toolbar {nullptr}
private

◆ m_collapse_toolbar_enabled

bool Slic3r::GUI::GLCanvas3D::m_collapse_toolbar_enabled {true}
private
672{true};

Referenced by _render_collapse_toolbar(), and enable_collapse_toolbar().

◆ m_color_by

std::string Slic3r::GUI::GLCanvas3D::m_color_by
private

◆ m_config

◆ m_context

wxGLContext* Slic3r::GUI::GLCanvas3D::m_context
private

◆ m_cursor_type

ECursorType Slic3r::GUI::GLCanvas3D::m_cursor_type
private

Referenced by GLCanvas3D(), and set_cursor().

◆ m_design_canvas

◆ m_dirty

◆ m_dynamic_background_enabled

bool Slic3r::GUI::GLCanvas3D::m_dynamic_background_enabled
private

◆ m_enable_render

bool Slic3r::GUI::GLCanvas3D::m_enable_render { true }
private
751{ true };

Referenced by _render_frame(), enable_render(), and is_rendering_enabled().

◆ m_event_handlers_bound

bool Slic3r::GUI::GLCanvas3D::m_event_handlers_bound { false }
private
728{ false };

Referenced by bind_event_handlers(), and unbind_event_handlers().

◆ m_explosion_ratio

float Slic3r::GUI::GLCanvas3D::m_explosion_ratio = 1.0
mutableprivate

◆ m_extra_frame_requested

bool Slic3r::GUI::GLCanvas3D::m_extra_frame_requested
private

◆ m_fps_overlay_tick

bool Slic3r::GUI::GLCanvas3D::m_fps_overlay_tick { false }
private
653{ false };

Referenced by _render_frame(), and on_fps_overlay_timer().

◆ m_fps_overlay_timer

wxTimer Slic3r::GUI::GLCanvas3D::m_fps_overlay_timer
private

Referenced by GLCanvas3D(), and _render_frame().

◆ m_frame_profiler

FrameProfiler Slic3r::GUI::GLCanvas3D::m_frame_profiler
private

◆ m_fxaa_texture_id

unsigned int Slic3r::GUI::GLCanvas3D::m_fxaa_texture_id { 0 }
922{ 0 };

Referenced by ~GLCanvas3D(), and _render_fxaa_pass().

◆ m_fxaa_texture_size

std::array<unsigned int, 2> Slic3r::GUI::GLCanvas3D::m_fxaa_texture_size { 0, 0 }
923{ 0, 0 };

Referenced by _render_fxaa_pass().

◆ m_gcode_layers_times_cache

std::vector<float> Slic3r::GUI::GLCanvas3D::m_gcode_layers_times_cache
private

◆ m_gcode_viewer

◆ m_gesture_pan_anchor

std::optional<Vec3d> Slic3r::GUI::GLCanvas3D::m_gesture_pan_anchor
private

Referenced by on_gesture().

◆ m_gizmo_highlighter

struct Slic3r::GUI::GLCanvas3D::GizmoHighlighter Slic3r::GUI::GLCanvas3D::m_gizmo_highlighter

◆ m_gizmos

GLGizmosManager Slic3r::GUI::GLCanvas3D::m_gizmos
private

◆ m_hover_ghost_head

int Slic3r::GUI::GLCanvas3D::m_hover_ghost_head { -1 }
private
788{ -1 }; // physical head index, -1 when not hovering a ghost

Referenced by _picking_pass_imex_ghosts(), _render_frame(), _render_imex_ghost_tooltip(), get_hover_ghost_head(), and on_mouse().

◆ m_hover_ghost_plate

int Slic3r::GUI::GLCanvas3D::m_hover_ghost_plate { -1 }
private
789{ -1 }; // plate index for the hovered ghost, -1 when none

Referenced by _picking_pass_imex_ghosts(), _render_imex_ghost_tooltip(), and get_hover_ghost_plate().

◆ m_hover_plate_idxs

std::vector<int> Slic3r::GUI::GLCanvas3D::m_hover_plate_idxs
private

◆ m_hover_volume_idxs

std::vector<int> Slic3r::GUI::GLCanvas3D::m_hover_volume_idxs
mutableprivate

◆ m_imgui_undo_redo_hovered_pos

int Slic3r::GUI::GLCanvas3D::m_imgui_undo_redo_hovered_pos { -1 }
private
809{ -1 };

◆ m_in_render

bool Slic3r::GUI::GLCanvas3D::m_in_render
private

◆ m_inactive_plates_hidden

bool Slic3r::GUI::GLCanvas3D::m_inactive_plates_hidden { false }
private
786{ false };

Referenced by _update_inactive_plates_visibility().

◆ m_initialized

◆ m_is_dark

◆ m_is_touchpad_navigation

bool Slic3r::GUI::GLCanvas3D::m_is_touchpad_navigation { false }
private
743{ false };

Referenced by is_camera_pan(), is_camera_rotate(), on_key(), and on_set_focus().

◆ m_key_down

KeyDown Slic3r::GUI::GLCanvas3D::m_key_down
private

Referenced by handle_shortcut(), and on_key().

◆ m_labels

Labels Slic3r::GUI::GLCanvas3D::m_labels
private

◆ m_last_frame_start_time

std::chrono::time_point<std::chrono::steady_clock> Slic3r::GUI::GLCanvas3D::m_last_frame_start_time { std::chrono::steady_clock::now() }
private
807{ std::chrono::steady_clock::now() };

Referenced by on_idle().

◆ m_last_h

unsigned int Slic3r::GUI::GLCanvas3D::m_last_h
private

Referenced by _resize().

◆ m_last_w

unsigned int Slic3r::GUI::GLCanvas3D::m_last_w
private

Referenced by _resize().

◆ m_layers_editing

◆ m_main_toolbar

◆ m_model

◆ m_mouse

◆ m_mouse_wheel

int Slic3r::GUI::GLCanvas3D::m_mouse_wheel { 0 }
private
810{ 0 };

◆ m_moving

bool Slic3r::GUI::GLCanvas3D::m_moving
private

◆ m_moving_enabled

bool Slic3r::GUI::GLCanvas3D::m_moving_enabled
private

Referenced by GLCanvas3D(), enable_moving(), and on_mouse().

◆ m_multisample_allowed

bool Slic3r::GUI::GLCanvas3D::m_multisample_allowed
private

◆ m_navigator_dragging

bool Slic3r::GUI::GLCanvas3D::m_navigator_dragging { false }
private
780{ false };

Referenced by _render_3d_navigator(), bind_event_handlers(), and on_mouse().

◆ m_old_size

std::array<unsigned int, 2> Slic3r::GUI::GLCanvas3D::m_old_size { 0, 0 }
private
741{ 0, 0 };

Referenced by _resize(), and reset_old_size().

◆ m_orient_settings_fff

OrientSettings Slic3r::GUI::GLCanvas3D::m_orient_settings_fff
private

◆ m_orient_settings_sla

OrientSettings Slic3r::GUI::GLCanvas3D::m_orient_settings_sla
private

◆ m_overlay_dirty

bool Slic3r::GUI::GLCanvas3D::m_overlay_dirty { false }
private
747{ false };

Referenced by _set_overlay_as_dirty(), and on_idle().

◆ m_paint_toolbar_width

float Slic3r::GUI::GLCanvas3D::m_paint_toolbar_width
mutableprivate

◆ m_picking_enabled

◆ m_plate_chrome_enabled

bool Slic3r::GUI::GLCanvas3D::m_plate_chrome_enabled {true}
private
676{true};

Referenced by _render_platelist(), and enable_plate_chrome().

◆ m_plate_shadow_mask

GLModel Slic3r::GUI::GLCanvas3D::m_plate_shadow_mask

Referenced by ~GLCanvas3D(), and _render_shadows().

◆ m_plate_shadow_mask_key

std::string Slic3r::GUI::GLCanvas3D::m_plate_shadow_mask_key

Referenced by ~GLCanvas3D(), and _render_shadows().

◆ m_plate_switcher_items

std::vector<std::unique_ptr<IMToolbarItem> > Slic3r::GUI::GLCanvas3D::m_plate_switcher_items
private

◆ m_plate_switcher_scrollbar

bool Slic3r::GUI::GLCanvas3D::m_plate_switcher_scrollbar { false }
private
666{ false };

Referenced by _render_plate_switcher().

◆ m_plate_switcher_version

unsigned Slic3r::GUI::GLCanvas3D::m_plate_switcher_version { unsigned(-1) }
private
665{ unsigned(-1) };

Referenced by _render_plate_switcher().

◆ m_popup_menu_positon

std::optional<Vec2d> Slic3r::GUI::GLCanvas3D::m_popup_menu_positon

◆ m_presented_signature

std::optional<size_t> Slic3r::GUI::GLCanvas3D::m_presented_signature

Referenced by _render_frame(), on_paint(), and render().

◆ m_process

◆ m_rectangle_selection

◆ m_reload_delayed

bool Slic3r::GUI::GLCanvas3D::m_reload_delayed
private

◆ m_render_preview

bool Slic3r::GUI::GLCanvas3D::m_render_preview { true }
private

◆ m_render_sla_auxiliaries

◆ m_render_stats

RenderStats Slic3r::GUI::GLCanvas3D::m_render_stats
private

◆ m_render_timer

RenderTimer Slic3r::GUI::GLCanvas3D::m_render_timer
private

Referenced by GLCanvas3D(), and schedule_extra_frame().

◆ m_requires_check_outside_state

bool Slic3r::GUI::GLCanvas3D::m_requires_check_outside_state { false }
private
739{ false };

Referenced by _render_objects(), and requires_check_outside_state().

◆ m_return_toolbar

IMReturnToolbar Slic3r::GUI::GLCanvas3D::m_return_toolbar
mutableprivate

◆ m_rotation_center

Vec3d Slic3r::GUI::GLCanvas3D::m_rotation_center { 0.0, 0.0, 0.0}
mutableprivate
792{ 0.0, 0.0, 0.0};

Referenced by on_mouse().

◆ m_sc

float Slic3r::GUI::GLCanvas3D::m_sc {1}
mutableprivate
670{1};

◆ m_scene_cache

SceneCache Slic3r::GUI::GLCanvas3D::m_scene_cache

◆ m_scene_raycaster

◆ m_section_view

◆ m_section_view_caps

std::map<const GLVolume*, MeshClipper> Slic3r::GUI::GLCanvas3D::m_section_view_caps
private

◆ m_sel_plate_toolbar

◆ m_selected_extruder

int Slic3r::GUI::GLCanvas3D::m_selected_extruder
private

Referenced by set_selected_extruder().

◆ m_selection

◆ m_selection_edit

◆ m_separator_toolbar

◆ m_sequential_print_clearance

◆ m_sequential_print_clearance_first_displacement

bool Slic3r::GUI::GLCanvas3D::m_sequential_print_clearance_first_displacement { true }
878{ true };

Referenced by on_mouse(), and update_sequential_clearance().

◆ m_shadow_light_vp

Transform3d Slic3r::GUI::GLCanvas3D::m_shadow_light_vp { Transform3d::Identity() }
938{ Transform3d::Identity() };

Referenced by _render_gcode(), _render_objects(), and _render_shadows().

◆ m_shadow_map_fbo

unsigned int Slic3r::GUI::GLCanvas3D::m_shadow_map_fbo { 0 }
935{ 0 };

Referenced by ~GLCanvas3D(), and _render_shadows().

◆ m_shadow_map_key

size_t Slic3r::GUI::GLCanvas3D::m_shadow_map_key { 0 }
941{ 0 };

Referenced by _render_shadows().

◆ m_shadow_map_size

unsigned int Slic3r::GUI::GLCanvas3D::m_shadow_map_size { 0 }

◆ m_shadow_map_texture_id

unsigned int Slic3r::GUI::GLCanvas3D::m_shadow_map_texture_id { 0 }

◆ m_shadow_map_valid

bool Slic3r::GUI::GLCanvas3D::m_shadow_map_valid { false }

◆ m_shadow_plate_bounds

std::array<float, 4> Slic3r::GUI::GLCanvas3D::m_shadow_plate_bounds { { 0.0f, 0.0f, 0.0f, 0.0f } }
943{ { 0.0f, 0.0f, 0.0f, 0.0f } };

Referenced by _render_shadows().

◆ m_shortcuts_assembly_view

std::vector<std::pair<wxString, wxString> > Slic3r::GUI::GLCanvas3D::m_shortcuts_assembly_view
private

◆ m_show_bed

bool Slic3r::GUI::GLCanvas3D::m_show_bed {true}
private

◆ m_show_world_axes

bool Slic3r::GUI::GLCanvas3D::m_show_world_axes {true}
private

◆ m_sidebar_field

std::string Slic3r::GUI::GLCanvas3D::m_sidebar_field
private

◆ m_sinking_contours_enabled

bool Slic3r::GUI::GLCanvas3D::m_sinking_contours_enabled {true}
private
687{true};

Referenced by _render_objects(), and enable_sinking_contours().

◆ m_sla_caps

std::array<SlaCap, 2> Slic3r::GUI::GLCanvas3D::m_sla_caps
private

◆ m_slope

◆ m_ssao_color_texture_id

unsigned int Slic3r::GUI::GLCanvas3D::m_ssao_color_texture_id { 0 }
924{ 0 };

Referenced by ~GLCanvas3D(), and _render_ssao_pass().

◆ m_ssao_depth_texture_id

unsigned int Slic3r::GUI::GLCanvas3D::m_ssao_depth_texture_id { 0 }
925{ 0 };

Referenced by ~GLCanvas3D(), and _render_ssao_pass().

◆ m_ssao_texture_size

std::array<unsigned int, 2> Slic3r::GUI::GLCanvas3D::m_ssao_texture_size { { 0, 0 } }
926{ { 0, 0 } };

Referenced by _render_ssao_pass().

◆ m_studio_lighting

bool Slic3r::GUI::GLCanvas3D::m_studio_lighting {false}
private
706{false};

Referenced by _render_objects(), and set_studio_lighting().

◆ m_timer

wxTimer Slic3r::GUI::GLCanvas3D::m_timer
private

◆ m_timer_set_color

wxTimer Slic3r::GUI::GLCanvas3D::m_timer_set_color
private

◆ m_toolbar_highlighter

struct Slic3r::GUI::GLCanvas3D::ToolbarHighlighter Slic3r::GUI::GLCanvas3D::m_toolbar_highlighter

◆ m_toolpath_outside

bool Slic3r::GUI::GLCanvas3D::m_toolpath_outside { false }
private
777{ false };

Referenced by _render_background().

◆ m_tooltip

Tooltip Slic3r::GUI::GLCanvas3D::m_tooltip
private

◆ m_tooltip_enabled

bool Slic3r::GUI::GLCanvas3D::m_tooltip_enabled { true }
private
816{ true };

Referenced by _render_frame(), on_mouse(), and on_set_focus().

◆ m_use_clipping_planes

bool Slic3r::GUI::GLCanvas3D::m_use_clipping_planes
private

◆ m_volumes

◆ s_frames_in_progress

int Slic3r::GUI::GLCanvas3D::s_frames_in_progress = 0
staticprivate

◆ split_to_objects_count

int Slic3r::GUI::GLCanvas3D::split_to_objects_count = 0
private

◆ split_to_part_count

int Slic3r::GUI::GLCanvas3D::split_to_part_count = 0
private

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