OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::Plater::priv Struct Reference
Collaboration diagram for Slic3r::GUI::Plater::priv:

Classes

struct  DockPane
struct  SidebarLayout
struct  TextureImportResult

Public Types

enum class  UpdateParams { FORCE_FULL_SCREEN_REFRESH = 1 , FORCE_BACKGROUND_PROCESSING_UPDATE = 2 , POSTPONE_VALIDATION_ERROR_MESSAGE = 4 }
enum  UpdateBackgroundProcessReturnState {
  UPDATE_BACKGROUND_PROCESS_RESTART = 1 , UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE = 2 , UPDATE_BACKGROUND_PROCESS_INVALID = 4 , UPDATE_BACKGROUND_PROCESS_FORCE_RESTART = 8 ,
  UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT = 16
}
using LoadProgressCallback = std::function<bool(int, const wxString&)>

Public Member Functions

 priv (Plater *q, MainFrame *main_frame)
 ~priv ()
bool need_update () const
void set_need_update (bool need_update)
void set_plater_dirty (bool is_dirty)
bool is_project_dirty () const
bool is_presets_dirty () const
void update_project_dirty_from_presets ()
int save_project_if_dirty (const wxString &reason)
void reset_project_dirty_after_save ()
void reset_project_dirty_initial_presets ()
void update (unsigned int flags=0)
void select_view (const std::string &direction)
void select_view_3D (const std::string &name, bool no_slice=true)
void select_next_view_3D ()
bool is_preview_shown () const
bool is_preview_loaded () const
bool is_view3D_shown () const
bool is_assemble_view_show () const
bool are_view3D_labels_shown () const
void show_view3D_labels (bool show)
bool is_view3D_overhang_shown () const
void show_view3D_overhang (bool show)
void enable_sidebar (bool enabled)
void collapse_sidebar (bool collapse)
void update_sidebar (bool force_update=false)
bool gcode_preview_without_settings () const
void reset_window_layout ()
Sidebar::DockingState get_sidebar_docking_state ()
void add_dock_pane (wxWindow *window, const std::string &name, const wxString &caption, const std::string &dock, const wxSize &size, std::function< void()> on_close)
void remove_dock_pane (wxWindow *window)
void show_dock_pane (wxWindow *window, bool show)
bool dock_pane_visible (const DockPane &dock_pane, const wxAuiPaneInfo &pane) const
bool is_view3D_layers_editing_enabled () const
void set_current_canvas_as_dirty ()
GLCanvas3D * get_current_canvas3D (bool exclude_preview=false)
void unbind_canvas_event_handlers ()
void reset_canvas_volumes ()
bool check_ams_status_impl (bool is_slice_all)
bool get_machine_sync_status ()
bool init_collapse_toolbar ()
void hide_select_machine_dlg ()
void enter_prepare_mode ()
void hide_send_to_printer_dlg ()
void update_preview_bottom_toolbar ()
void reset_gcode_toolpaths ()
void reset_all_gizmos ()
void apply_free_camera_correction (bool apply=true)
void update_ui_from_settings ()
std::shared_ptr< BBLStatusBar > statusbar ()
std::string get_config (const std::string &key) const
BoundingBoxf bed_shape_bb () const
BoundingBox scaled_bed_shape_bb () const
std::vector< size_t > load_files (const std::vector< fs::path > &input_files, LoadStrategy strategy, bool ask_multi=false, bool *published_out=nullptr, bool *config_loaded_out=nullptr)
std::vector< size_t > load_model_objects (const ModelObjectPtrs &model_objects, bool allow_negative_z=false, bool split_object=false, bool auto_drop=true)
bool run_textured_mesh_import_dialog (Slic3r::Model &loaded_model, TextureImportResult &result, std::function< bool()> cancel_callback={}, std::function< bool(int)> progress_callback={})
void apply_textured_mesh_import_result (Slic3r::Model &loaded_model, const std::vector< size_t > &obj_idxs, const TextureImportResult &result, LoadProgressCallback progress_callback={}, bool update_scene=true)
void handle_textured_mesh_import (Slic3r::Model &model, const std::vector< size_t > &obj_idxs, std::function< bool()> cancel_callback={})
fs::path get_export_file_path (GUI::FileType file_type)
wxString get_export_file (GUI::FileType file_type, const wxString &title={}, bool published=false)
void load_auxiliary_files ()
const Selection & get_selection () const
Selection & get_selection ()
Selection & get_curr_selection ()
int get_selected_object_idx () const
int get_selected_volume_idx () const
void selection_changed ()
void object_list_changed ()
void select_curr_plate_all ()
void remove_curr_plate_all ()
void select_all ()
void deselect_all ()
void exit_gizmo ()
void remove (size_t obj_idx)
bool delete_object_from_model (size_t obj_idx, bool refresh_immediately=true)
bool ensure_belt_purge_tower ()
void delete_all_objects_from_model ()
void reset (bool apply_presets_change=false, bool reload_presets=true)
void center_selection ()
void drop_selection ()
void mirror (Axis axis)
void split_object (bool auto_drop=true)
void split_object (int obj_idx, bool auto_drop=true)
void split_volume ()
void scale_selection_to_fit_print_volume ()
Slic3r::UndoRedo::Stack & undo_redo_stack ()
Slic3r::UndoRedo::Stack & undo_redo_stack_main ()
void enter_gizmos_stack ()
bool leave_gizmos_stack ()
void take_snapshot (const std::string &snapshot_name, UndoRedo::SnapshotType snapshot_type=UndoRedo::SnapshotType::Action)
int get_active_snapshot_index ()
void undo ()
void redo ()
bool undo_redo_blocked_by_job ()
void undo_redo_to (size_t time_to_load)
bool up_to_date (bool saved, bool backup)
void suppress_snapshots ()
void allow_snapshots ()
void single_snapshots_enter (SingleSnapshot *single)
void single_snapshots_leave (SingleSnapshot *single)
void process_validation_warning (StringObjectException const &warning) const
void process_validation_warnings (const std::vector< StringObjectException > &warnings) const
bool background_processing_enabled () const
std::vector< std::vector< DynamicPrintConfig > > get_extruder_filament_info ()
void update_print_volume_state ()
void schedule_background_process ()
void schedule_auto_reslice_if_needed ()
void trigger_auto_reslice_now ()
int auto_slice_delay_seconds () const
unsigned int update_background_process (bool force_validation=false, bool postpone_error_messages=false, bool switch_print=true)
bool restart_background_process (unsigned int state)
unsigned int update_restart_background_process (bool force_scene_update, bool force_preview_update)
void show_delayed_error_message ()
void export_gcode (fs::path output_path, bool output_path_on_removable_media)
void export_gcode (fs::path output_path, bool output_path_on_removable_media, PrintHostJob upload_job)
void reload_from_disk ()
bool replace_volume_with_stl (int object_idx, int volume_idx, const fs::path &new_path, const std::string &snapshot="")
void replace_with_stl ()
void replace_all_with_stl ()
void reload_all_from_disk ()
void set_current_panel (wxPanel *panel, bool no_slice=true)
void on_combobox_select (wxCommandEvent &)
void on_select_bed_type (wxCommandEvent &)
void on_select_preset (wxCommandEvent &)
void on_slicing_update (SlicingStatusEvent &)
void on_slicing_completed (wxCommandEvent &)
void on_process_completed (SlicingProcessCompletedEvent &)
void on_export_began (wxCommandEvent &)
void on_export_finished (wxCommandEvent &)
void on_slicing_began ()
void clear_warnings ()
void add_warning (const Slic3r::PrintStateBase::Warning &warning, size_t oid)
void actualize_slicing_warnings (const PrintBase &print)
void actualize_object_warnings (const PrintBase &print)
bool warnings_dialog ()
void on_action_add (SimpleEvent &)
void on_action_add_plate (SimpleEvent &)
void on_action_del_plate (SimpleEvent &)
void on_action_split_objects (SimpleEvent &)
void on_action_split_volumes (SimpleEvent &)
void on_action_layersediting (SimpleEvent &)
void on_create_filament (SimpleEvent &)
void on_modify_filament (SimpleEvent &)
void on_add_filament (SimpleEvent &)
void on_delete_filament (SimpleEvent &)
void on_add_custom_filament (ColorEvent &)
void on_object_select (SimpleEvent &)
void show_right_click_menu (Vec2d mouse_position, wxMenu *menu)
void on_right_click (RBtnEvent &)
void on_repair_model (wxCommandEvent &event)
void on_filament_color_changed (wxCommandEvent &event)
void show_install_plugin_hint (wxCommandEvent &event)
void install_network_plugin (wxCommandEvent &event)
void show_preview_only_hint (wxCommandEvent &event)
void on_plate_right_click (RBtnPlateEvent &)
void on_plate_selected (SimpleEvent &)
void on_action_request_model_id (wxCommandEvent &evt)
void on_action_download_project (wxCommandEvent &evt)
void on_slice_button_status (bool enable)
void on_action_open_project (SimpleEvent &)
void on_action_slice_plate (SimpleEvent &)
void on_action_slice_all (SimpleEvent &)
void on_action_print_plate (SimpleEvent &)
void open_machine_select_dialog (int plate_idx, PrintFromType print_type=PrintFromType::FROM_NORMAL)
void on_action_print_all (SimpleEvent &)
void on_action_export_gcode (SimpleEvent &)
void on_action_send_gcode (SimpleEvent &)
void on_action_export_sliced_file (SimpleEvent &)
void on_action_export_all_sliced_file (SimpleEvent &)
void on_action_select_sliced_plate (wxCommandEvent &evt)
void on_change_color_mode (SimpleEvent &evt)
void on_apple_change_color_mode (wxSysColourChangedEvent &evt)
void on_update_geometry (Vec3dsEvent< 2 > &)
void on_3dcanvas_mouse_dragging_started (SimpleEvent &)
void on_3dcanvas_mouse_dragging_finished (SimpleEvent &)
void on_action_print_plate_from_sdcard (SimpleEvent &)
void on_tab_selection_changing (wxBookCtrlEvent &)
void set_bed_shape (const Pointfs &shape, const Pointfs &exclude_areas, const Pointfs &wrapping_exclude_areas, const double printable_height, std::vector< Pointfs > extruder_areas, std::vector< double > extruder_heights, const std::string &custom_texture, const std::string &custom_model, bool force_as_custom=false)
bool can_delete () const
bool can_delete_all () const
bool can_add_plate () const
bool can_delete_plate () const
bool can_increase_instances () const
bool can_decrease_instances () const
bool can_split_to_objects () const
bool can_split_to_volumes () const
bool can_arrange () const
bool can_layers_editing () const
bool can_fix_through_cgal () const
bool can_simplify () const
bool can_smooth_mesh () const
bool can_set_instance_to_object () const
bool can_mirror () const
bool can_reload_from_disk () const
bool can_fillcolor () const
bool has_assemble_view () const
bool can_replace_with_stl () const
bool can_replace_all_with_stl () const
bool can_split (bool to_objects) const
void generate_thumbnail (ThumbnailData &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)
ThumbnailsList generate_thumbnails (const ThumbnailsParams &params, Camera::EType camera_type)
PlateBBoxData generate_first_layer_bbox ()
void bring_instance_forward () const
wxString get_project_filename (const wxString &extension=wxEmptyString) const
wxString get_export_gcode_filename (const wxString &extension=wxEmptyString, bool only_filename=false, bool export_all=false) const
void set_project_filename (const wxString &filename)
wxString get_project_name ()
void set_project_name (const wxString &project_name)
void update_title_dirty_status ()
void init_notification_manager ()
void update_objects_position_when_select_preset (const std::function< void()> &select_prest)
bool inside_snapshot_capture ()
void update_fff_scene_only_shells (bool only_shells=true)
bool PopupObjectTable (int object_id, int volume_id, const wxPoint &position)
void on_action_send_to_printer (bool isall=false)
void on_action_send_to_multi_machine (SimpleEvent &)
int update_print_required_data (Slic3r::DynamicPrintConfig config, Slic3r::Model model, Slic3r::PlateDataPtrs plate_data_list, std::string file_name, std::string file_path)

Public Attributes

Plater * q
Sidebar * sidebar
MainFrame * main_frame
MenuFactory menus
SelectMachineDialog * m_select_machine_dlg = nullptr
SendMultiMachinePage * m_send_multi_dlg = nullptr
SendToPrinterDialog * m_send_to_sdcard_dlg = nullptr
bool m_has_pending_published {false}
std::vector< std::string > m_pending_published_keys
std::vector< Slic3r::PublishedMaterialEntry > m_pending_material_keys
Slic3r::DynamicPrintConfig * config
Slic3r::Print fff_print
Slic3r::SLAPrint sla_print
Slic3r::Model model
PrinterTechnology printer_technology = ptFFF
Slic3r::GCodeProcessorResult gcode_result
AuiMgr m_aui_mgr
std::map< wxWindow *, DockPane > m_dock_panes
wxString m_default_window_layout
wxPanel * current_panel { nullptr }
std::vector< wxPanel * > panels
struct Slic3r::GUI::Plater::priv::SidebarLayout sidebar_layout
Bed3D bed
Camera camera
PartPlateList partplate_list
bool m_ignore_event {false}
bool m_slice_all {false}
bool m_is_slicing {false}
std::string m_local_missing_shown_sig
std::string m_cloud_missing_shown_sig
std::string m_inactive_shown_sig
std::string m_broken_shown_sig
bool auto_reslice_pending {false}
bool auto_reslice_after_cancel {false}
int m_is_RightClickInLeftUI {-1}
int m_cur_slice_plate
bool m_slice_all_only_has_gcode { false }
bool m_need_update {false}
Mouse3DController mouse3d_controller
View3D * view3D
GLToolbar collapse_toolbar
Preview * preview
AssembleView * assemble_view { nullptr }
UVEditorPanel * uv_editor_panel { nullptr }
UVEditorCanvas * uv_editor_canvas { nullptr }
bool first_enter_assemble { true }
std::unique_ptr< NotificationManager > notification_manager
ProjectDirtyStateManager dirty_state
BackgroundSlicingProcess background_process
bool suppressed_backround_processing_update { false }
PlaterWorker< BoostThreadWorker > m_worker
SLAImportDialog * m_sla_import_dlg
int m_job_prepare_state
bool delayed_scene_refresh
std::string delayed_error_message
wxTimer background_process_timer
wxTimer auto_reslice_timer
std::string label_btn_export
std::string label_btn_send
bool show_render_statistic_dialog { false }
bool show_wireframe { false }
bool wireframe_enabled { true }
bool show_xray { false }
bool m_is_dark = false
std::vector< BeltPurgeSignature > m_belt_purge_sigs
ExportingStatus exporting_status { NOT_EXPORTING }
std::string last_output_path
std::string last_output_dir_path
PrintPrepareData m_print_job_data
int process_completed_with_error { -1 }
BBLProject project

Static Public Attributes

static const std::regex pattern_bundle
static const std::regex pattern_3mf
static const std::regex pattern_zip_amf
static const std::regex pattern_any_amf
static const std::regex pattern_prusa

Private Member Functions

bool layers_height_allowed () const
void update_fff_scene ()
void update_sla_scene ()
void undo_redo_to (std::vector< UndoRedo::Snapshot >::const_iterator it_snapshot)
void update_after_undo_redo (const UndoRedo::Snapshot &snapshot, bool temp_snapshot_was_taken=false)
void on_action_export_to_sdcard (SimpleEvent &)
void on_action_export_to_sdcard_all (SimpleEvent &)
void update_plugin_when_launch (wxCommandEvent &event)

Private Attributes

boost::filesystem::path m_project_folder
wxString m_project_name
Slic3r::UndoRedo::Stack m_undo_redo_stack_main
Slic3r::UndoRedo::Stack m_undo_redo_stack_gizmos
Slic3r::UndoRedo::Stack * m_undo_redo_stack_active = &m_undo_redo_stack_main
int m_prevent_snapshots = 0
Plater::SingleSnapshot * m_single = nullptr
size_t m_saved_timestamp = 0
size_t m_backup_timestamp = 0
std::string m_last_fff_printer_profile_name
std::string m_last_sla_printer_profile_name
std::vector< std::pair< Slic3r::PrintStateBase::Warning, size_t > > current_warnings
bool show_warning_dialog { false }

Detailed Description


Class Documentation

◆ Slic3r::GUI::Plater::priv::DockPane

struct Slic3r::GUI::Plater::priv::DockPane
Class Members
function< void()> on_close
bool shown {true}

◆ Slic3r::GUI::Plater::priv::SidebarLayout

struct Slic3r::GUI::Plater::priv::SidebarLayout
Class Members
bool is_collapsed {false}
bool is_enabled {false}
bool show {false}

◆ Slic3r::GUI::Plater::priv::TextureImportResult

struct Slic3r::GUI::Plater::priv::TextureImportResult
Collaboration diagram for Slic3r::GUI::Plater::priv::TextureImportResult:
Class Members
size_t existing_filament_count = 0
bool fallback_to_geometry_only = false
wxString fallback_warning
vector< TextureFilamentEntry > filament_entries
vector< FilamentMatch > matches
vector< array< float, 4 > > new_filament_colors
vector< string > new_filament_preset_names
vector< TextureNewMixedFilament > new_mixed_filaments
PaintedMesh painted
bool skipped = false

Member Typedef Documentation

◆ LoadProgressCallback

using Slic3r::GUI::Plater::priv::LoadProgressCallback = std::function<bool(int, const wxString&)>

Member Enumeration Documentation

◆ UpdateBackgroundProcessReturnState

Enumerator
UPDATE_BACKGROUND_PROCESS_RESTART 
UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE 
UPDATE_BACKGROUND_PROCESS_INVALID 
UPDATE_BACKGROUND_PROCESS_FORCE_RESTART 
UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT 
7556 {
7557 // update_background_process() reports, that the Print / SLAPrint was updated in a way,
7558 // that the background process was invalidated and it needs to be re-run.
7560 // update_background_process() reports, that the Print / SLAPrint was updated in a way,
7561 // that a scene needs to be refreshed (you should call _3DScene::reload_scene(canvas3Dwidget, false))
7563 // update_background_process() reports, that the Print / SLAPrint is invalid, and the error message
7564 // was sent to the status line.
7566 // Restart even if the background processing is disabled.
7568 // Restart for G-code (or SLA zip) export or upload.
7570 };
@ UPDATE_BACKGROUND_PROCESS_INVALID
Definition Plater.cpp:7565
@ UPDATE_BACKGROUND_PROCESS_RESTART
Definition Plater.cpp:7559
@ UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT
Definition Plater.cpp:7569
@ UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE
Definition Plater.cpp:7562
@ UPDATE_BACKGROUND_PROCESS_FORCE_RESTART
Definition Plater.cpp:7567

◆ UpdateParams

Enumerator
FORCE_FULL_SCREEN_REFRESH 
FORCE_BACKGROUND_PROCESSING_UPDATE 
POSTPONE_VALIDATION_ERROR_MESSAGE 
7347 {
7348 FORCE_FULL_SCREEN_REFRESH = 1,
7349 FORCE_BACKGROUND_PROCESSING_UPDATE = 2,
7350 POSTPONE_VALIDATION_ERROR_MESSAGE = 4,
7351 };

Constructor & Destructor Documentation

◆ priv()

Slic3r::GUI::Plater::priv::priv ( Plater * q,
MainFrame * main_frame )
7834 : q(q)
7836 //BBS: add bed_exclude_area
7838 "printable_area", "bed_exclude_area", "bed_exclude_volumes", "bed_exclude_volume_mode", "extruder_bed_exclude_volumes", "extruder_offset",
7839 "wrapping_exclude_area", "extruder_printable_area", "bed_custom_texture", "bed_custom_model", "print_sequence",
7840 "extruder_clearance_radius",
7841 "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
7842 "nozzle_height", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle",
7843 "brim_width", "brim_object_gap", "brim_flow_ratio", "brim_use_efc_outline", "combine_brims", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "preferred_orientation",
7844 "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_enable_framework",
7845 "prime_tower_infill_gap", "prime_volume",
7846 "extruder_colour", "filament_colour", "filament_type", "filament_is_support", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology",
7847 // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
7848 "layer_height", "initial_layer_print_height", "min_layer_height", "max_layer_height",
7849 "wall_loops", "outer_wall_filament_id", "inner_wall_filament_id", "sparse_infill_density", "sparse_infill_filament_id", "top_shell_layers",
7850 "enable_support", "support_filament", "support_interface_filament",
7851 "support_top_z_distance", "support_bottom_z_distance", "raft_layers",
7852 "wipe_tower_rotation_angle", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extra_flow", "wipe_tower_max_purge_speed",
7853 "wipe_tower_wall_type", "wipe_tower_extra_rib_length","wipe_tower_rib_width","wipe_tower_fillet_wall",
7854 "wipe_tower_filament",
7855 "best_object_pos", "master_extruder_id",
7856 "is_imex"
7857 }))
7858 , sidebar(new Sidebar(q))
7859 , notification_manager(std::make_unique<NotificationManager>(q))
7860 , m_worker{q, std::make_unique<NotificationProgressIndicator>(notification_manager.get()), "ui_worker"}
7861 , m_sla_import_dlg{new SLAImportDialog{q}}
7863 , delayed_scene_refresh(false)
7864 , collapse_toolbar(GLToolbar::Normal, "Collapse")
7865 //BBS :partplatelist construction
7866 , partplate_list(this->q, &model)
7867{
7868 m_is_dark = wxGetApp().app_config->get("dark_color_mode") == "1";
7869
7870 m_aui_mgr.init(q);
7871
7872 this->q->SetFont(Slic3r::GUI::wxGetApp().normal_font());
7873
7874 //BBS: use the first partplate's print for background process
7875 partplate_list.update_slice_context_to_current_plate(background_process);
7876 /*
7877 background_process.set_fff_print(&fff_print);
7878 background_process.set_sla_print(&sla_print);
7879 background_process.set_gcode_result(&gcode_result);
7880 background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params, Camera::EType::Ortho); });
7881 background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
7882 background_process.set_finished_event(EVT_PROCESS_COMPLETED);
7883 background_process.set_export_began_event(EVT_EXPORT_BEGAN);
7884 // Default printer technology for default config.
7885 background_process.select_technology(this->printer_technology);
7886 // Register progress callback from the Print class to the Plater.
7887
7888 auto statuscb = [this](const Slic3r::PrintBase::SlicingStatus &status) {
7889 wxQueueEvent(this->q, new Slic3r::SlicingStatusEvent(EVT_SLICING_UPDATE, 0, status));
7890 };
7891 fff_print.set_status_callback(statuscb);
7892 sla_print.set_status_callback(statuscb); */
7893
7894 // BBS: to be checked. Not follow patch.
7895 background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params, Camera::EType::Ortho); });
7896 background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
7897 background_process.set_finished_event(EVT_PROCESS_COMPLETED);
7898 background_process.set_export_began_event(EVT_EXPORT_BEGAN);
7899 background_process.set_export_finished_event(EVT_EXPORT_FINISHED);
7900 this->q->Bind(EVT_SLICING_UPDATE, &priv::on_slicing_update, this);
7901 this->q->Bind(EVT_REPAIR_MODEL, &priv::on_repair_model, this);
7902 this->q->Bind(EVT_FILAMENT_COLOR_CHANGED, &priv::on_filament_color_changed, this);
7903 this->q->Bind(EVT_INSTALL_PLUGIN_NETWORKING, &priv::install_network_plugin, this);
7904 this->q->Bind(EVT_INSTALL_PLUGIN_HINT, &priv::show_install_plugin_hint, this);
7905 this->q->Bind(EVT_UPDATE_PLUGINS_WHEN_LAUNCH, &priv::update_plugin_when_launch, this);
7906 this->q->Bind(EVT_PREVIEW_ONLY_MODE_HINT, &priv::show_preview_only_hint, this);
7907 this->q->Bind(EVT_GLCANVAS_COLOR_MODE_CHANGED, &priv::on_change_color_mode, this);
7908 this->q->Bind(wxEVT_SYS_COLOUR_CHANGED, &priv::on_apple_change_color_mode, this);
7909 this->q->Bind(EVT_CREATE_FILAMENT, &priv::on_create_filament, this);
7910 this->q->Bind(EVT_MODIFY_FILAMENT, &priv::on_modify_filament, this);
7911 this->q->Bind(EVT_NOTICE_CHILDE_SIZE_CHANGED, &Sidebar::on_size, sidebar);
7912 this->q->Bind(EVT_NOTICE_FULL_SCREEN_CHANGED, &Sidebar::on_full_screen, sidebar);
7913 this->q->Bind(EVT_ADD_CUSTOM_FILAMENT, &priv::on_add_custom_filament, this);
7914 main_frame->m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this);
7915
7916 auto* panel_3d = new wxPanel(q);
7917 view3D = new View3D(panel_3d, bed, &model, config, &background_process);
7918 //BBS: use partplater's gcode
7919 preview = new Preview(panel_3d, bed, &model, config, &background_process, partplate_list.get_current_slice_result(), [this]() { schedule_background_process(); });
7920 preview->get_canvas3d()->share_section_view(*view3D->get_canvas3d());
7921
7922 assemble_view = new AssembleView(panel_3d, bed, &model, config, &background_process);
7923
7924#ifdef __APPLE__
7925 // BBS
7926 // set default view_toolbar icons size equal to GLGizmosManager::Default_Icons_Size
7927 //view_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size);
7928#endif // __APPLE__
7929
7930 panels.push_back(view3D);
7931 panels.push_back(preview);
7932 panels.push_back(assemble_view);
7933
7934 this->background_process_timer.SetOwner(this->q, 0);
7935 this->auto_reslice_timer.SetOwner(this->q, 0);
7936 this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt)
7937 {
7938 if (&evt.GetTimer() == &this->background_process_timer) {
7940 this->update_restart_background_process(false, false);
7941 } else if (&evt.GetTimer() == &this->auto_reslice_timer) {
7942 this->auto_reslice_timer.Stop();
7944 } else {
7945 evt.Skip();
7946 }
7947 });
7948
7949 update();
7950
7951 // Orca: Make sidebar dockable
7953
7954 // UV editor pane for GLGizmoTextureDisplacement's LSCM unwrap preview - a resizable/dockable
7955 // sibling of "sidebar"/"main" like everything else registered on this same AUI manager, not a
7956 // change to the view3D/preview/assemble_view sizer above. Hidden by default: only relevant
7957 // while that gizmo is active with a layer using the "Unwrap (LSCM)" projection method (see
7958 // Plater::show_uv_editor()), so it stays out of the way of everyone else's window layout.
7959 uv_editor_panel = new UVEditorPanel(q);
7961 m_aui_mgr.AddPane(uv_editor_panel, wxAuiPaneInfo()
7962 .Name("uv_editor")
7963 .Caption(_L("UV Editor"))
7964 .Right()
7965 .Hide()
7966 .BestSize(wxSize(40 * wxGetApp().em_unit(), 40 * wxGetApp().em_unit())));
7967 // Closing the pane with its own X has to reach the gizmo, or its next update would simply show the pane again.
7968 q->Bind(wxEVT_AUI_PANE_CLOSE, [this](wxAuiManagerEvent &evt) {
7969 evt.Skip();
7970 if (evt.GetPane() != nullptr && evt.GetPane()->window == uv_editor_panel && uv_editor_canvas != nullptr)
7972 });
7973
7974 auto* panel_sizer = new wxBoxSizer(wxHORIZONTAL);
7975 panel_sizer->Add(view3D, 1, wxEXPAND | wxALL, 0);
7976 panel_sizer->Add(preview, 1, wxEXPAND | wxALL, 0);
7977 panel_sizer->Add(assemble_view, 1, wxEXPAND | wxALL, 0);
7978 panel_3d->SetSizer(panel_sizer);
7979 m_aui_mgr.AddPane(panel_3d, wxAuiPaneInfo().Name("main").CenterPane().PaneBorder(false));
7980
7981 q->Bind(wxEVT_AUI_PANE_CLOSE, [this](wxAuiManagerEvent& evt) {
7982 const wxAuiPaneInfo* pane = evt.GetPane();
7983 auto it = pane != nullptr ? m_dock_panes.find(pane->window) : m_dock_panes.end();
7984 if (it != m_dock_panes.end()) {
7985 const std::function<void()> on_close = std::move(it->second.on_close);
7986 m_dock_panes.erase(it);
7987 if (on_close)
7988 on_close();
7989 }
7990 evt.Skip();
7991 });
7992
7993 m_default_window_layout = m_aui_mgr.SavePerspective();
7994
7995 {
7996 auto& sidebar = m_aui_mgr.GetPane(this->sidebar);
7997
7998 // Load previous window layout
7999 const auto cfg = wxGetApp().app_config;
8000 wxString layout = wxString::FromUTF8(cfg->get("window_layout"));
8001 if (!layout.empty()) {
8002 bool removed_floating_state = false;
8003#ifdef __WXGTK__
8004 layout = sanitize_window_layout_for_wayland(layout, &removed_floating_state);
8005#endif
8006
8007 if (!m_aui_mgr.LoadPerspective(layout, false)) {
8008 BOOST_LOG_TRIVIAL(warning) << "Failed to restore saved window layout";
8009 m_aui_mgr.LoadPerspective(m_default_window_layout, false);
8010 } else if (removed_floating_state) {
8011 BOOST_LOG_TRIVIAL(info) << "Removed floating AUI state from saved window layout for Wayland";
8012 }
8013
8014 // The UV editor is a transient, gizmo-driven pane (see show_uv_editor()); a saved layout
8015 // from a session that happened to close with it open would otherwise restore it visible on
8016 // startup, with nothing painted in it. Force it hidden here so it only ever appears when the
8017 // texture-displacement gizmo asks for it.
8018 if (wxAuiPaneInfo &uv_pane = m_aui_mgr.GetPane("uv_editor"); uv_pane.IsOk())
8019 uv_pane.Hide();
8020
8021 sidebar_layout.is_collapsed = !sidebar.IsShown();
8022 }
8023
8024 // Keep tracking the current sidebar size, by storing it using `best_size`, which will be stored
8025 // in the config and re-applied when the app is opened again.
8026 m_aui_mgr.track_docked_size(this->sidebar);
8027
8028 // Hide sidebar initially, will re-show it after initialization when we got proper window size
8029 sidebar.Hide();
8030 m_aui_mgr.Update();
8031 }
8032
8033 menus.init(main_frame);
8034
8035
8036 // Events:
8037
8038 if (wxGetApp().is_editor()) {
8039 // Preset change event
8040 sidebar->Bind(wxEVT_COMBOBOX, &priv::on_combobox_select, this);
8041 sidebar->Bind(EVT_OBJ_LIST_OBJECT_SELECT, [this](wxEvent&) { priv::selection_changed(); });
8042 // BBS: should bind BACKGROUND_PROCESS event to plater
8043 q->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });
8044 // jump to found option from SearchDialog
8045 q->Bind(wxCUSTOMEVT_JUMP_TO_OPTION, [this](wxCommandEvent& evt) { sidebar->jump_to_option(evt.GetInt()); });
8046 q->Bind(wxCUSTOMEVT_JUMP_TO_OBJECT, [this](wxCommandEvent& evt) {
8047 auto client_data = evt.GetClientData();
8048 ObjectDataViewModelNode* data = static_cast<ObjectDataViewModelNode*>(client_data);
8049 sidebar->jump_to_object(data);
8050 }
8051 );
8052 }
8053
8054 wxGLCanvas* view3D_canvas = view3D->get_wxglcanvas();
8055 //BBS: GUI refactor
8056 wxGLCanvas* preview_canvas = preview->get_wxglcanvas();
8057
8058 if (wxGetApp().is_editor()) {
8059 // 3DScene events:
8060 view3D_canvas->Bind(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) {
8061 delayed_error_message.clear();
8062 this->background_process_timer.Start(500, wxTIMER_ONE_SHOT);
8063 });
8064 view3D_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this);
8065 view3D_canvas->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this);
8066 //BBS: add part plate related logic
8067 view3D_canvas->Bind(EVT_GLCANVAS_PLATE_RIGHT_CLICK, &priv::on_plate_right_click, this);
8068 view3D_canvas->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); });
8069 view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent& evt) {
8070 //BBS arrange from EVT set default state.
8071 this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
8072 this->q->arrange(); });
8073 view3D_canvas->Bind(EVT_GLCANVAS_ARRANGE_PARTPLATE, [this](SimpleEvent& evt) {
8074 //BBS arrange from EVT set default state.
8075 this->q->set_prepare_state(Job::PREPARE_STATE_MENU);
8076 this->q->arrange(); });
8077 view3D_canvas->Bind(EVT_GLCANVAS_ORIENT, [this](SimpleEvent& evt) {
8078 //BBS orient from EVT set default state.
8079 this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
8080 this->q->orient(); });
8081 view3D_canvas->Bind(EVT_GLCANVAS_ORIENT_PARTPLATE, [this](SimpleEvent& evt) {
8082 //BBS orient from EVT set default state.
8083 this->q->set_prepare_state(Job::PREPARE_STATE_MENU);
8084 this->q->orient(); });
8085 //BBS
8086 view3D_canvas->Bind(EVT_GLCANVAS_SELECT_CURR_PLATE_ALL, [this](SimpleEvent&) {this->q->select_curr_plate_all(); });
8087 view3D_canvas->Bind(EVT_GLCANVAS_PRINTABLE, [this](SimpleEvent& evt) { this->sidebar->obj_list()->toggle_printable_state(); });
8088
8089 view3D_canvas->Bind(EVT_GLCANVAS_SELECT_ALL, [this](SimpleEvent&) { this->q->select_all(); });
8090 view3D_canvas->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) {
8091 wxGetApp().keyboard_shortcuts(view3D->get_canvas3d()->get_gizmos_manager().is_paint_gizmo() ? ShortcutContext::Painting : ShortcutContext::Plater);
8092 });
8093 view3D_canvas->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [this](Event<int>& evt)
8094 { if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); });
8095 view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); });
8096 view3D_canvas->Bind(EVT_GLCANVAS_FORCE_UPDATE, [this](SimpleEvent&) { update(); });
8097 view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
8098 view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); });
8099 // BBS
8100 //view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool>& evt) { this->sidebar->enable_buttons(evt.data); });
8101 view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool>& evt) { on_slice_button_status(evt.data); });
8102 view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this);
8103 view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED, &priv::on_3dcanvas_mouse_dragging_started, this);
8104 view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this);
8105 view3D_canvas->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
8106 view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); });
8107 view3D_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); });
8108 view3D_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); });
8109 view3D_canvas->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
8110 view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); });
8111 view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event<float>& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); });
8112 view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); });
8113 view3D_canvas->Bind(EVT_GLCANVAS_RELOAD_FROM_DISK, [this](SimpleEvent&) { this->reload_all_from_disk(); });
8114
8115 // 3DScene/Toolbar:
8116 view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
8117 view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); });
8118 view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { delete_all_objects_from_model(); });
8119// view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE_ALL, [q](SimpleEvent&) { q->reset_with_confirm(); });
8120
8121 view3D_canvas->Bind(EVT_GLTOOLBAR_ADD_PLATE, &priv::on_action_add_plate, this);
8122 view3D_canvas->Bind(EVT_GLTOOLBAR_DEL_PLATE, &priv::on_action_del_plate, this);
8123 view3D_canvas->Bind(EVT_GLTOOLBAR_ORIENT, [this](SimpleEvent&) {
8124 //BBS arrange from EVT set default state.
8125 this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
8126 this->q->orient(); });
8127 view3D_canvas->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) {
8128 //BBS arrange from EVT set default state.
8129 this->q->set_prepare_state(Job::PREPARE_STATE_DEFAULT);
8130 this->q->arrange();
8131 });
8132 view3D_canvas->Bind(EVT_GLTOOLBAR_CUT, [q](SimpleEvent&) { q->cut_selection_to_clipboard(); });
8133 view3D_canvas->Bind(EVT_GLTOOLBAR_COPY, [q](SimpleEvent&) { q->copy_selection_to_clipboard(); });
8134 view3D_canvas->Bind(EVT_GLTOOLBAR_PASTE, [q](SimpleEvent&) { q->paste_from_clipboard(); });
8135 view3D_canvas->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this);
8136 //BBS: add clone
8137 view3D_canvas->Bind(EVT_GLTOOLBAR_CLONE, [q](SimpleEvent&) { q->clone_selection(); });
8138 view3D_canvas->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); });
8139 view3D_canvas->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); });
8140 view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this);
8141 view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this);
8142 //BBS: GUI refactor: GLToolbar
8143 view3D_canvas->Bind(EVT_GLTOOLBAR_OPEN_PROJECT, &priv::on_action_open_project, this);
8144 //view3D_canvas->Bind(EVT_GLTOOLBAR_SLICE_PLATE, &priv::on_action_slice_plate, this);
8145 //view3D_canvas->Bind(EVT_GLTOOLBAR_SLICE_ALL, &priv::on_action_slice_all, this);
8146 //view3D_canvas->Bind(EVT_GLTOOLBAR_PRINT_PLATE, &priv::on_action_print_plate, this);
8147 //view3D_canvas->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this);
8148 //view3D_canvas->Bind(EVT_GLTOOLBAR_EXPORT_GCODE, &priv::on_action_export_gcode, this);
8149 view3D_canvas->Bind(EVT_GLVIEWTOOLBAR_ASSEMBLE, [q](SimpleEvent&) { q->select_view_3D("Assemble"); });
8150 //preview also send these events
8151 //preview_canvas->Bind(EVT_GLTOOLBAR_SLICE_PLATE, &priv::on_action_slice_plate, this);
8152 //preview_canvas->Bind(EVT_GLTOOLBAR_PRINT_PLATE, &priv::on_action_print_plate, this);
8153 //preview_canvas->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this);
8154 //review_canvas->Bind(EVT_GLTOOLBAR_EXPORT_GCODE, &priv::on_action_export_gcode, this);
8155 view3D_canvas->Bind(EVT_GLCANVAS_SWITCH_TO_OBJECT, [main_frame](SimpleEvent&) {
8156 if (main_frame->m_param_panel) {
8157 main_frame->m_param_panel->switch_to_object(false);
8158 }
8159 });
8160 view3D_canvas->Bind(EVT_GLCANVAS_SWITCH_TO_GLOBAL, [main_frame](SimpleEvent&) {
8161 if (main_frame->m_param_panel) {
8162 main_frame->m_param_panel->switch_to_global();
8163 }
8164 });
8165 }
8166 view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); });
8167
8168 // Preview events:
8169 preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_QUESTION_MARK, [](SimpleEvent&) { wxGetApp().keyboard_shortcuts(ShortcutContext::Preview); });
8170 preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); });
8171 preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_UPDATE, [this](SimpleEvent &) {
8172 preview->get_canvas3d()->set_as_dirty();
8173 });
8174 if (wxGetApp().is_editor()) {
8175 preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
8176 preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
8177 preview->get_wxglcanvas()->Bind(EVT_CUSTOMEVT_TICKSCHANGED, [this](wxCommandEvent& event) {
8178 CustomGCode::Type tick_event_type = (CustomGCode::Type)event.GetInt();
8179 Model& model = wxGetApp().plater()->model();
8180 //BBS: replace model custom gcode with current plate custom gcode
8181 model.plates_custom_gcodes[model.curr_plate_index] = preview->get_canvas3d()->get_gcode_viewer().get_layers_slider()->GetTicksValues();
8182
8183 // BBS set to invalid state only
8184 if (tick_event_type == CustomGCode::Type::ToolChange || tick_event_type == CustomGCode::Type::Custom || tick_event_type == CustomGCode::Type::Template || tick_event_type == CustomGCode::Type::PausePrint) {
8185 PartPlate *plate = this->q->get_partplate_list().get_curr_plate();
8186 if (plate) {
8187 plate->update_slice_result_valid_state(false);
8188 }
8189 }
8190 set_plater_dirty(true);
8191
8192 preview->on_tick_changed(tick_event_type);
8193
8194 // update slice and print button
8195 wxGetApp().mainframe->update_slice_print_status(MainFrame::SlicePrintEventType::eEventSliceUpdate, true, false);
8196 set_need_update(true);
8197 });
8198 }
8199 if (wxGetApp().is_gcode_viewer())
8200 preview->Bind(EVT_GLCANVAS_RELOAD_FROM_DISK, [this](SimpleEvent&) { this->q->reload_gcode_from_disk(); });
8201
8202 //BBS
8203 wxGLCanvas* assemble_canvas = assemble_view->get_wxglcanvas();
8204 if (wxGetApp().is_editor()) {
8205 assemble_canvas->Bind(EVT_GLTOOLBAR_FILLCOLOR, [q](IntEvent& evt) { q->fill_color(evt.get_data()); });
8206 assemble_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this);
8207 assemble_canvas->Bind(EVT_GLVIEWTOOLBAR_3D, [q](SimpleEvent&) { q->select_view_3D("3D"); });
8208 assemble_canvas->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this);
8209 assemble_canvas->Bind(EVT_GLCANVAS_FORCE_UPDATE, [this](SimpleEvent&) { update(); });
8210 assemble_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); });
8211 assemble_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); });
8212 }
8213
8214 if (wxGetApp().is_editor()) {
8215 q->Bind(EVT_SLICING_COMPLETED, &priv::on_slicing_completed, this);
8216 q->Bind(EVT_PROCESS_COMPLETED, &priv::on_process_completed, this);
8217 q->Bind(EVT_EXPORT_BEGAN, &priv::on_export_began, this);
8218 q->Bind(EVT_EXPORT_FINISHED, &priv::on_export_finished, this);
8219 q->Bind(EVT_GLVIEWTOOLBAR_3D, [q](SimpleEvent&) { q->select_view_3D("3D"); });
8220 //BBS: set on_slice to false
8221 q->Bind(EVT_GLVIEWTOOLBAR_PREVIEW, [q](SimpleEvent&) { q->select_view_3D("Preview", false); });
8222 q->Bind(EVT_GLTOOLBAR_SLICE_PLATE, &priv::on_action_slice_plate, this);
8223 q->Bind(EVT_GLTOOLBAR_SLICE_ALL, &priv::on_action_slice_all, this);
8224 q->Bind(EVT_GLTOOLBAR_PRINT_PLATE, &priv::on_action_print_plate, this);
8225 q->Bind(EVT_PRINT_FROM_SDCARD_VIEW, &priv::on_action_print_plate_from_sdcard, this);
8226 q->Bind(EVT_GLTOOLBAR_SELECT_SLICED_PLATE, &priv::on_action_select_sliced_plate, this);
8227 q->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this);
8228 q->Bind(EVT_GLTOOLBAR_EXPORT_GCODE, &priv::on_action_export_gcode, this);
8229 q->Bind(EVT_GLTOOLBAR_SEND_GCODE, &priv::on_action_send_gcode, this);
8230 q->Bind(EVT_GLTOOLBAR_EXPORT_SLICED_FILE, &priv::on_action_export_sliced_file, this);
8231 q->Bind(EVT_GLTOOLBAR_EXPORT_ALL_SLICED_FILE, &priv::on_action_export_all_sliced_file, this);
8232 q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER, &priv::on_action_export_to_sdcard, this);
8233 q->Bind(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, &priv::on_action_export_to_sdcard_all, this);
8234 q->Bind(EVT_GLTOOLBAR_PRINT_MULTI_MACHINE, &priv::on_action_send_to_multi_machine, this);
8235 q->Bind(EVT_GLCANVAS_PLATE_SELECT, &priv::on_plate_selected, this);
8236 q->Bind(EVT_DOWNLOAD_PROJECT, &priv::on_action_download_project, this);
8237 q->Bind(EVT_IMPORT_MODEL_ID, &priv::on_action_request_model_id, this);
8238 q->Bind(EVT_PRINT_FINISHED, [q](wxCommandEvent& evt) { q->print_job_finished(evt); });
8239 q->Bind(EVT_SEND_CALIBRATION_FINISHED, [q](wxCommandEvent& evt) { q->send_calibration_job_finished(evt); });
8240 q->Bind(EVT_SEND_FINISHED, [q](wxCommandEvent& evt) { q->send_job_finished(evt); });
8241 q->Bind(EVT_OPEN_PLATESETTINGSDIALOG, [q](wxCommandEvent& evt) { q->open_platesettings_dialog(evt);});
8242 q->Bind(EVT_OPEN_FILAMENT_MAP_SETTINGS_DIALOG, [q](wxCommandEvent &evt) { q->open_filament_map_setting_dialog(evt); });
8243 //q->Bind(EVT_GLVIEWTOOLBAR_ASSEMBLE, [q](SimpleEvent&) { q->select_view_3D("Assemble"); });
8244 }
8245
8246 // Drop target:
8247 q->SetDropTarget(new PlaterDropTarget(*main_frame, *q)); // if my understanding is right, wxWindow takes the owenership
8248 q->Layout();
8249
8250 set_current_panel(wxGetApp().is_editor() ? static_cast<wxPanel*>(view3D) : static_cast<wxPanel*>(preview));
8251
8252 // updates camera type from .ini file
8253 camera.enable_update_config_on_type_change(true);
8254 // BBS set config
8255 bool use_perspective_camera = get_config("use_perspective_camera").compare("true") == 0;
8256 if (use_perspective_camera) {
8258 } else {
8259 camera.set_type(Camera::EType::Ortho);
8260 }
8261
8262 // Load the 3DConnexion device database.
8263 mouse3d_controller.load_config(*wxGetApp().app_config);
8264 // Start the background thread to detect and connect to a HID device (Windows and Linux).
8265 // Connect to a 3DConnextion driver (OSX).
8266 mouse3d_controller.init();
8267#ifdef _WIN32
8268 // Register an USB HID (Human Interface Device) attach event. evt contains Win32 path to the USB device containing VID, PID and other info.
8269 // This event wakes up the Mouse3DController's background thread to enumerate HID devices, if the VID of the callback event
8270 // is one of the 3D Mouse vendors (3DConnexion or Logitech).
8271 this->q->Bind(EVT_HID_DEVICE_ATTACHED, [this](HIDDeviceAttachedEvent &evt) {
8272 mouse3d_controller.device_attached(evt.data);
8273 });
8274 this->q->Bind(EVT_HID_DEVICE_DETACHED, [this](HIDDeviceAttachedEvent& evt) {
8275 mouse3d_controller.device_detached(evt.data);
8276 });
8277#endif /* _WIN32 */
8278 //notification_manager = new NotificationManager(this->q);
8279
8280 if (wxGetApp().is_editor()) {
8281 this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
8282 this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
8283 this->q->Bind(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, [](PresetUpdateAvailableClickedEvent&) { wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
8284 this->q->Bind(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED, [](PrinterConfigUpdateAvailableClickedEvent&) {
8285 wxGetApp().get_preset_updater()->do_printer_config_update();
8286 wxGetApp().getDeviceManager()->reload_printer_settings(); });
8287
8288 /* BBS do not handle removeable driver event */
8289 this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
8290 if (evt.data.second) {
8291 // BBS
8292 //this->show_action_buttons(this->ready_to_slice);
8293 notification_manager->close_notification_of_type(NotificationType::ExportFinished);
8296 format(_L("Successfully unmounted. The device %s (%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path)
8297 );
8298 } else {
8301 format(_L("Ejecting of device %s (%s) has failed."), evt.data.first.name, evt.data.first.path)
8302 );
8303 }
8304 });
8305 this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this](RemovableDrivesChangedEvent &) {
8306 // BBS
8307 //this->show_action_buttons(this->ready_to_slice);
8308 // Close notification ExportingFinished but only if last export was to removable
8309 notification_manager->device_ejected();
8310 });
8311 // Start the background thread and register this window as a target for update events.
8312 wxGetApp().removable_drive_manager()->init(this->q);
8313#ifdef _WIN32
8314 //Trigger enumeration of removable media on Win32 notification.
8315 this->q->Bind(EVT_VOLUME_ATTACHED, [](VolumeAttachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
8316 this->q->Bind(EVT_VOLUME_DETACHED, [](VolumeDetachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
8317#endif /* _WIN32 */
8318 }
8319
8320 // Initialize the Undo / Redo stack with a first snapshot.
8321 //this->take_snapshot("New Project", UndoRedo::SnapshotType::ProjectSeparator);
8322 // Reset the "dirty project" flag.
8323 m_undo_redo_stack_main.mark_current_as_saved();
8324 dirty_state.update_from_undo_redo_stack(false);
8325 //this->take_snapshot("New Project");
8326 // BBS: save project confirm
8327 up_to_date(true, false);
8328 up_to_date(true, true);
8329 model.set_need_backup();
8330
8331 // BBS: restore project
8332 if (wxGetApp().is_editor()) {
8333 auto last_backup = wxGetApp().app_config->get_last_backup_dir();
8334 this->q->Bind(EVT_RESTORE_PROJECT, [this, last = last_backup](wxCommandEvent& e) {
8335 std::string last_backup = last;
8336 std::string originfile;
8337 if (Slic3r::has_restore_data(last_backup, originfile)) {
8338 auto result = MessageDialog(this->q, _L("Previously unsaved items have been detected. Do you want to restore them\?"), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Restore"), wxYES_NO | wxYES_DEFAULT | wxCENTRE).ShowModal();
8339 if (result == wxID_YES) {
8340 this->q->load_project(from_path(last_backup), from_path(originfile));
8342 return;
8343 }
8344 }
8345
8346 try {
8347 if (originfile != "<lock>") // see bbs_3mf.cpp for lock detail
8348 boost::filesystem::remove_all(last);
8349 }
8350
8351 catch (...) {}
8352
8353 if (this->q->get_project_filename().IsEmpty() && this->q->is_empty_project()) {
8354 int skip_confirm = e.GetInt();
8355 // Skips the preset reload; trigger_restore_project()'s callers load the presets first.
8356 this->q->new_project(skip_confirm, true, wxString(), false);
8357 }
8358 });
8359 //wxPostEvent(this->q, wxCommandEvent{EVT_RESTORE_PROJECT});
8360 }
8361
8362 this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) {
8363 BOOST_LOG_TRIVIAL(trace) << "Received load from other instance event.";
8364 wxArrayString input_files;
8365 for (size_t i = 0; i < evt.data.size(); ++i) {
8366 input_files.push_back(from_u8(evt.data[i].string()));
8367 }
8368 wxGetApp().mainframe->Show();
8369 wxGetApp().mainframe->Raise();
8370 this->q->load_files(input_files);
8371 });
8372
8373 this->q->Bind(EVT_START_DOWNLOAD_OTHER_INSTANCE, [](StartDownloadOtherInstanceEvent& evt) {
8374 BOOST_LOG_TRIVIAL(trace) << "Received url from other instance event.";
8375 wxGetApp().mainframe->Show();
8376 wxGetApp().mainframe->Raise();
8377 for (size_t i = 0; i < evt.data.size(); ++i) {
8378 wxGetApp().start_download(evt.data[i]);
8379 }
8380
8381 });
8382 this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) {
8384 });
8385 wxGetApp().other_instance_message_handler()->init(this->q);
8386
8387 // collapse sidebar according to saved value
8388 //if (wxGetApp().is_editor()) {
8389 // bool is_collapsed = wxGetApp().app_config->get("collapsed_sidebar") == "1";
8390 // sidebar->collapse(is_collapsed);
8391 //}
8392 update_sidebar(true);
8393}
#define _L(s)
Definition OBJ.cpp:34
static DynamicPrintConfig * new_from_defaults_keys(const std::vector< std::string > &keys)
Definition PrintConfig.cpp:10311
static wxAuiPaneInfo sidebar_pane_info()
Definition AuiMgr.cpp:68
@ Normal
Definition GLToolbar.hpp:274
@ PREPARE_STATE_MENU
Definition Job.hpp:24
@ PREPARE_STATE_DEFAULT
Definition Job.hpp:23
@ eEventSliceUpdate
Definition MainFrame.hpp:340
@ RegularNotificationLevel
Definition NotificationManager.hpp:216
@ ErrorNotificationLevel
Definition NotificationManager.hpp:228
friend class PlaterDropTarget
Definition Plater.hpp:1126
void on_full_screen(IntEvent &)
Definition Plater.cpp:6217
void on_size(SimpleEvent &e)
Definition Plater.cpp:6208
@ PaneClosed
Definition UVEditorCanvas.hpp:116
#define SLIC3R_APP_FULL_NAME
Definition libslic3r.h:11
Type
Definition CustomGCode.hpp:18
@ PausePrint
Definition CustomGCode.hpp:20
@ ToolChange
Definition CustomGCode.hpp:21
@ Template
Definition CustomGCode.hpp:22
@ Custom
Definition CustomGCode.hpp:23
wxString from_path(const boost::filesystem::path &path)
Definition GUI.cpp:555
Event< HeightProfileSmoothingParams > HeightProfileSmoothEvent
Definition GLCanvas3D.hpp:196
SimpleEvent EjectDriveNotificationClickedEvent
Definition NotificationManager.hpp:37
SimpleEvent ExportGcodeNotificationClickedEvent
Definition NotificationManager.hpp:39
Event< std::pair< DriveData, bool > > RemovableDriveEjectEvent
Definition RemovableDriveManager.hpp:38
SimpleEvent PresetUpdateAvailableClickedEvent
Definition NotificationManager.hpp:41
SimpleEvent PrinterConfigUpdateAvailableClickedEvent
Definition NotificationManager.hpp:43
@ Right
Definition GLToolbar.hpp:462
@ CustomNotification
Definition NotificationManager.hpp:66
@ ExportFinished
Definition NotificationManager.hpp:73
Event< std::vector< std::string > > StartDownloadOtherInstanceEvent
Definition InstanceCheck.hpp:51
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:36
@ Painting
Definition Shortcuts.hpp:21
@ Preview
Definition Shortcuts.hpp:21
@ Plater
Definition Shortcuts.hpp:21
@ Name
Definition CalibrationWizardSavePage.cpp:126
wxString from_u8(const std::string &str)
Definition GUI.cpp:544
SimpleEvent RemovableDrivesChangedEvent
Definition RemovableDriveManager.hpp:41
SimpleEvent InstanceGoToFrontEvent
Definition InstanceCheck.hpp:55
Event< std::vector< boost::filesystem::path > > LoadFromOtherInstanceEvent
Definition InstanceCheck.hpp:50
void trace(unsigned int level, const char *message)
Definition utils.cpp:247
bool has_restore_data(std::string &path, std::string &origin)
Definition bbs_3mf.cpp:9794
void backup_soon()
Definition bbs_3mf.cpp:9769
@ Ortho
Definition Camera.hpp:39
@ Perspective
Definition Camera.hpp:40
UVEditorCanvas * uv_editor_canvas
Definition Plater.cpp:7261
void on_action_export_all_sliced_file(SimpleEvent &)
Definition Plater.cpp:13992
bool can_decrease_instances() const
Definition Plater.cpp:15108
void set_current_panel(wxPanel *panel, bool no_slice=true)
Definition Plater.cpp:12558
void on_action_send_to_multi_machine(SimpleEvent &)
Definition Plater.cpp:13855
void on_right_click(RBtnEvent &)
Definition Plater.cpp:14200
void on_action_layersediting(SimpleEvent &)
Definition Plater.cpp:15148
bool delayed_scene_refresh
Definition Plater.cpp:7282
void on_modify_filament(SimpleEvent &)
Definition Plater.cpp:15184
Slic3r::UndoRedo::Stack m_undo_redo_stack_main
Definition Plater.cpp:7773
std::unique_ptr< NotificationManager > notification_manager
Definition Plater.cpp:7263
void schedule_background_process()
Definition Plater.cpp:11113
void redo()
Definition Plater.cpp:15368
ThumbnailsList generate_thumbnails(const ThumbnailsParams &params, Camera::EType camera_type)
Definition Plater.cpp:14307
void on_action_print_all(SimpleEvent &)
Definition Plater.cpp:13954
void on_process_completed(SlicingProcessCompletedEvent &)
Definition Plater.cpp:13340
void on_action_split_objects(SimpleEvent &)
Definition Plater.cpp:14047
UVEditorPanel * uv_editor_panel
Definition Plater.cpp:7260
Slic3r::DynamicPrintConfig * config
Definition Plater.cpp:7191
void on_tab_selection_changing(wxBookCtrlEvent &)
Definition Plater.cpp:13873
AuiMgr m_aui_mgr
Definition Plater.cpp:7199
void on_action_split_volumes(SimpleEvent &)
Definition Plater.cpp:14052
SLAImportDialog * m_sla_import_dlg
Definition Plater.cpp:7278
Slic3r::Model model
Definition Plater.cpp:7194
void on_export_finished(wxCommandEvent &)
Definition Plater.cpp:13254
void delete_all_objects_from_model()
Definition Plater.cpp:10792
PlaterWorker< BoostThreadWorker > m_worker
Definition Plater.cpp:7277
void on_change_color_mode(SimpleEvent &evt)
Definition Plater.cpp:14155
void on_action_export_gcode(SimpleEvent &)
Definition Plater.cpp:13968
bool up_to_date(bool saved, bool backup)
Definition Plater.cpp:15391
AssembleView * assemble_view
Definition Plater.cpp:7254
Mouse3DController mouse3d_controller
Definition Plater.cpp:7248
void reset_all_gizmos()
Definition Plater.cpp:8766
void set_need_update(bool need_update)
Definition Plater.cpp:7309
void undo()
Definition Plater.cpp:15349
Plater * q
Definition Plater.cpp:7174
Sidebar * sidebar
Definition Plater.cpp:7175
void on_action_slice_plate(SimpleEvent &)
Definition Plater.cpp:13737
void on_action_open_project(SimpleEvent &)
Definition Plater.cpp:13576
void update(unsigned int flags=0)
Definition Plater.cpp:8404
bool suppressed_backround_processing_update
Definition Plater.cpp:7268
void on_object_select(SimpleEvent &)
Definition Plater.cpp:14057
wxTimer auto_reslice_timer
Definition Plater.cpp:7286
void on_action_print_plate_from_sdcard(SimpleEvent &)
Definition Plater.cpp:13863
void on_action_send_gcode(SimpleEvent &)
Definition Plater.cpp:13976
void reload_all_from_disk()
Definition Plater.cpp:12537
void on_repair_model(wxCommandEvent &event)
Definition Plater.cpp:14067
std::map< wxWindow *, DockPane > m_dock_panes
Definition Plater.cpp:7207
PartPlateList partplate_list
Definition Plater.cpp:7221
void on_update_geometry(Vec3dsEvent< 2 > &)
Definition Plater.cpp:14271
void on_3dcanvas_mouse_dragging_started(SimpleEvent &)
Definition Plater.cpp:14276
void on_export_began(wxCommandEvent &)
Definition Plater.cpp:13248
bool m_is_dark
Definition Plater.cpp:7302
void on_plate_right_click(RBtnPlateEvent &)
Definition Plater.cpp:14265
void on_action_print_plate(SimpleEvent &)
Definition Plater.cpp:13831
BackgroundSlicingProcess background_process
Definition Plater.cpp:7267
void on_slicing_completed(wxCommandEvent &)
Definition Plater.cpp:13225
void on_action_add(SimpleEvent &)
Definition Plater.cpp:13549
void select_next_view_3D()
Definition Plater.cpp:8600
void on_filament_color_changed(wxCommandEvent &event)
Definition Plater.cpp:14072
void trigger_auto_reslice_now()
Definition Plater.cpp:11161
void update_sidebar(bool force_update=false)
Definition Plater.cpp:8635
GLToolbar collapse_toolbar
Definition Plater.cpp:7252
Camera camera
Definition Plater.cpp:7219
View3D * view3D
Definition Plater.cpp:7249
void on_action_request_model_id(wxCommandEvent &evt)
Definition Plater.cpp:14023
void on_slicing_update(SlicingStatusEvent &)
Definition Plater.cpp:13144
void selection_changed()
Definition Plater.cpp:10655
void on_3dcanvas_mouse_dragging_finished(SimpleEvent &)
Definition Plater.cpp:14283
unsigned int update_restart_background_process(bool force_scene_update, bool force_preview_update)
Definition Plater.cpp:11724
void on_action_download_project(wxCommandEvent &evt)
Definition Plater.cpp:14031
void show_preview_only_hint(wxCommandEvent &event)
Definition Plater.cpp:14139
void set_plater_dirty(bool is_dirty)
Definition Plater.cpp:7311
void show_install_plugin_hint(wxCommandEvent &event)
Definition Plater.cpp:14134
void on_action_export_to_sdcard_all(SimpleEvent &)
Definition Plater.cpp:14008
void update_plugin_when_launch(wxCommandEvent &event)
Definition Plater.cpp:14096
void bring_instance_forward() const
Definition Plater.cpp:15584
void on_action_select_sliced_plate(wxCommandEvent &evt)
Definition Plater.cpp:13945
void on_slice_button_status(bool enable)
Definition Plater.cpp:14040
struct Slic3r::GUI::Plater::priv::SidebarLayout sidebar_layout
void on_action_slice_all(SimpleEvent &)
Definition Plater.cpp:13778
std::string get_config(const std::string &key) const
Definition Plater.cpp:8789
wxTimer background_process_timer
Definition Plater.cpp:7285
Preview * preview
Definition Plater.cpp:7253
MainFrame * main_frame
Definition Plater.cpp:7176
void on_apple_change_color_mode(wxSysColourChangedEvent &evt)
Definition Plater.cpp:14144
ProjectDirtyStateManager dirty_state
Definition Plater.cpp:7265
wxString m_default_window_layout
Definition Plater.cpp:7208
Bed3D bed
Definition Plater.cpp:7218
void on_action_add_plate(SimpleEvent &)
Definition Plater.cpp:13559
void on_action_del_plate(SimpleEvent &)
Definition Plater.cpp:13566
void on_action_export_to_sdcard(SimpleEvent &)
Definition Plater.cpp:14000
int m_job_prepare_state
Definition Plater.cpp:7280
std::vector< wxPanel * > panels
Definition Plater.cpp:7210
void on_combobox_select(wxCommandEvent &)
Definition Plater.cpp:12862
void on_create_filament(SimpleEvent &)
Definition Plater.cpp:15171
MenuFactory menus
Definition Plater.cpp:7178
void on_plate_selected(SimpleEvent &)
Definition Plater.cpp:14017
void on_action_export_sliced_file(SimpleEvent &)
Definition Plater.cpp:13984
void install_network_plugin(wxCommandEvent &event)
Definition Plater.cpp:14090
std::string delayed_error_message
Definition Plater.cpp:7283
void on_add_custom_filament(ColorEvent &)
Definition Plater.cpp:15221
int em_unit(wxWindow *win)
Definition wxExtensions.cpp:424

References Slic3r::GUI::Plater::Plater(), config, main_frame, and q.

Here is the call graph for this function:

◆ ~priv()

Slic3r::GUI::Plater::priv::~priv ( )
8396{
8397 if (config != nullptr)
8398 delete config;
8399 // Saves the database of visited (already shown) hints into hints.ini.
8400 notification_manager->deactivate_loaded_hints();
8401 main_frame->m_tabpanel->Unbind(wxEVT_NOTEBOOK_PAGE_CHANGING, &priv::on_tab_selection_changing, this);
8402}

References config, main_frame, notification_manager, and on_tab_selection_changing().

Here is the call graph for this function:

Member Function Documentation

◆ actualize_object_warnings()

void Slic3r::GUI::Plater::priv::actualize_object_warnings ( const PrintBase & print)
13305{
13306 std::vector<ObjectID> ids;
13307 for (const ModelObject* object : print.model().objects )
13308 {
13309 ids.push_back(object->id());
13310 }
13311 std::sort(ids.begin(), ids.end());
13312 notification_manager->remove_simplify_suggestion_of_released_objects(ids);
13313}

References Slic3r::PrintBase::model(), notification_manager, and Slic3r::Model::objects.

Referenced by update_background_process().

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

◆ actualize_slicing_warnings()

void Slic3r::GUI::Plater::priv::actualize_slicing_warnings ( const PrintBase & print)
13293{
13294 std::vector<ObjectID> ids = print.print_object_ids();
13295 if (ids.empty()) {
13297 return;
13298 }
13299 ids.emplace_back(print.id());
13300 std::sort(ids.begin(), ids.end());
13301 notification_manager->remove_slicing_warnings_of_released_objects(ids);
13302 notification_manager->set_all_slicing_warnings_gray(true);
13303}
void clear_warnings()
Definition Plater.cpp:13314

References clear_warnings(), Slic3r::ObjectBase::id(), notification_manager, and Slic3r::PrintBase::print_object_ids().

Referenced by update_background_process().

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

◆ add_dock_pane()

void Slic3r::GUI::Plater::priv::add_dock_pane ( wxWindow * window,
const std::string & name,
const wxString & caption,
const std::string & dock,
const wxSize & size,
std::function< void()> on_close )
8691{
8692 const wxString base_name = wxString::FromUTF8(name);
8693 wxString unique_name = base_name;
8694 for (int i = 2; m_aui_mgr.GetPane(unique_name).IsOk(); ++i)
8695 unique_name = base_name + wxString::Format("#%d", i);
8696
8697 // A restored layout below already holds pixels.
8698 const wxSize pixels = q->FromDIP(size);
8699 wxAuiPaneInfo info;
8700 info.Name(unique_name).Caption(caption).BestSize(pixels).FloatingSize(pixels).DestroyOnClose(true);
8701 if (dock == "left")
8702 info.Left();
8703 else if (dock == "bottom")
8704 info.Bottom();
8705 else
8706 info.Right();
8707 if (dock == "float")
8708 info.Float();
8709
8710 // Put the pane back where it was the last time the window layout was saved with it open.
8711 const std::string saved = aui_pane_layout_entry(wxGetApp().app_config->get("window_layout"), unique_name.utf8_string());
8712 if (!saved.empty()) {
8713 m_aui_mgr.LoadPaneInfo(wxString::FromUTF8(saved), info);
8714 info.Caption(caption).DestroyOnClose(true).Show();
8715 }
8716
8717 // Floating is disabled on Wayland.
8718 if ((m_aui_mgr.GetFlags() & wxAUI_MGR_ALLOW_FLOATING) == 0) {
8719 info.Dock().Floatable(false);
8720 if (info.dock_direction == wxAUI_DOCK_NONE)
8721 info.Right();
8722 }
8723
8724 const DockPane& dock_pane = m_dock_panes[window] = DockPane{std::move(on_close)};
8725 info.Show(dock_pane_visible(dock_pane, info));
8726 m_aui_mgr.AddPane(window, info);
8727
8728 m_aui_mgr.track_docked_size(window);
8729 m_aui_mgr.Update();
8730}
std::string aui_pane_layout_entry(const std::string &layout, const std::string &pane_name)
Definition AuiPaneLayout.cpp:7
bool dock_pane_visible(const DockPane &dock_pane, const wxAuiPaneInfo &pane) const
Definition Plater.cpp:8683
Definition Plater.cpp:7203

References Slic3r::GUI::aui_pane_layout_entry(), dock_pane_visible(), m_aui_mgr, m_dock_panes, and q.

Here is the call graph for this function:

◆ add_warning()

void Slic3r::GUI::Plater::priv::add_warning ( const Slic3r::PrintStateBase::Warning & warning,
size_t oid )
13279{
13280 for (auto& it : current_warnings) {
13281 if (warning.message_id == it.first.message_id) {
13282 if (warning.message_id != 0 || (warning.message_id == 0 && warning.message == it.first.message))
13283 {
13284 if (warning.message_id != 0)
13285 it.first.message = warning.message;
13286 return;
13287 }
13288 }
13289 }
13290 current_warnings.emplace_back(std::pair<Slic3r::PrintStateBase::Warning, size_t>(warning, oid));
13291}
std::string message
Definition PrintBase.hpp:96
int message_id
Definition PrintBase.hpp:100
std::vector< std::pair< Slic3r::PrintStateBase::Warning, size_t > > current_warnings
Definition Plater.cpp:7790

References current_warnings, Slic3r::PrintStateBase::Warning::message, and Slic3r::PrintStateBase::Warning::message_id.

Referenced by on_slicing_update().

Here is the caller graph for this function:

◆ allow_snapshots()

void Slic3r::GUI::Plater::priv::allow_snapshots ( )
inline
int m_prevent_snapshots
Definition Plater.cpp:7776

References m_prevent_snapshots.

◆ apply_free_camera_correction()

void Slic3r::GUI::Plater::priv::apply_free_camera_correction ( bool apply = true)
8556{
8557 bool use_perspective_camera = get_config("use_perspective_camera").compare("true") == 0;
8558 if (use_perspective_camera)
8560 else
8561 camera.set_type(Camera::EType::Ortho);
8562 if (apply && wxGetApp().app_config->get_bool("use_free_camera"))
8563 camera.recover_from_free_camera();
8564}
static bool apply(std::optional< T > &val, const MinMax< T > &limit)
Definition Point.hpp:738

References Slic3r::apply(), camera, get_config(), Slic3r::GUI::Camera::Ortho, and Slic3r::GUI::Camera::Perspective.

Referenced by select_view_3D(), and update_ui_from_settings().

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

◆ apply_textured_mesh_import_result()

void Slic3r::GUI::Plater::priv::apply_textured_mesh_import_result ( Slic3r::Model & loaded_model,
const std::vector< size_t > & obj_idxs,
const TextureImportResult & result,
LoadProgressCallback progress_callback = {},
bool update_scene = true )
15843{
15844 auto update_apply_progress = [&progress_callback](int percent, const wxString& message) {
15845 return !progress_callback || progress_callback(std::clamp(percent, 0, 100), message);
15846 };
15847
15848 const auto& painted = result.painted;
15849 const auto& final_matches = result.matches;
15850
15851 if (painted.face_colors.empty() || final_matches.empty()) {
15852 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: no painting result";
15853 loaded_model.texture_mesh.reset();
15854 return;
15855 }
15856
15857 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: got " << painted.cluster_colors.size()
15858 << " clusters, skipped=" << result.skipped;
15859 if (!update_apply_progress(0, _L("Applying texture colors...")))
15860 return;
15861
15862 auto collect_physical_color_strs = []() {
15863 std::vector<std::string> colors;
15864 auto& project_config = wxGetApp().preset_bundle->project_config;
15865 auto* colours_opt = project_config.option<ConfigOptionStrings>("filament_colour");
15866 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
15867 const size_t total = wxGetApp().preset_bundle->filament_presets.size();
15868 for (size_t i = 0; i < total; ++i) {
15869 const bool is_mixed = is_mixed_opt && i < is_mixed_opt->values.size() && is_mixed_opt->values[i];
15870 if (!is_mixed)
15871 colors.push_back(colours_opt && i < colours_opt->values.size() ? colours_opt->values[i] : "#808080");
15872 }
15873 return colors;
15874 };
15875
15876 const auto& entries = result.filament_entries;
15877 std::vector<int> filament_index_remap(entries.size(), -1);
15878 size_t existing_physical_count = 0;
15879 size_t new_physical_count = 0;
15880 for (const auto& entry : entries) {
15881 if (entry.kind == TextureFilamentKind::ExistingPhysical)
15882 ++existing_physical_count;
15883 else if (entry.kind == TextureFilamentKind::NewPhysical)
15884 ++new_physical_count;
15885 }
15886
15887 for (const auto& entry : entries) {
15888 if (entry.dialog_index < 0 || entry.dialog_index >= (int)filament_index_remap.size())
15889 continue;
15890 if (entry.kind == TextureFilamentKind::ExistingPhysical) {
15891 filament_index_remap[entry.dialog_index] = (int)entry.project_config_index;
15892 } else if (entry.kind == TextureFilamentKind::ExistingMixed) {
15893 filament_index_remap[entry.dialog_index] = (int)(entry.project_config_index + new_physical_count);
15894 }
15895 }
15896
15897 size_t new_physical_order = 0;
15898 for (const auto& entry : entries) {
15899 if (entry.kind != TextureFilamentKind::NewPhysical)
15900 continue;
15901 wxColour new_col(entry.color_hex);
15902 const size_t final_idx = existing_physical_count + new_physical_order;
15903 sidebar->add_custom_filament(new_col, entry.preset_name);
15904 if (entry.dialog_index >= 0 && entry.dialog_index < (int)filament_index_remap.size())
15905 filament_index_remap[entry.dialog_index] = (int)final_idx;
15906 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: created pending physical filament dialog="
15907 << entry.dialog_index << " final=" << final_idx
15908 << " color=" << entry.color_hex
15909 << " preset=" << entry.preset_name;
15910 ++new_physical_order;
15911 }
15912
15913 std::vector<std::string> physical_colors_for_mixing = collect_physical_color_strs();
15914 for (const auto& mixed : result.new_mixed_filaments) {
15915 MixedFilamentResult mixed_result;
15916 mixed_result.ratios = mixed.ratios;
15917 mixed_result.components.reserve(mixed.component_dialog_indices.size());
15918 bool valid_components = true;
15919 for (int component_dialog_idx : mixed.component_dialog_indices) {
15920 if (component_dialog_idx < 0 || component_dialog_idx >= (int)filament_index_remap.size() ||
15921 filament_index_remap[component_dialog_idx] < 0) {
15922 valid_components = false;
15923 break;
15924 }
15925 mixed_result.components.push_back((unsigned int)(filament_index_remap[component_dialog_idx] + 1));
15926 }
15927 if (!valid_components || mixed_result.components.size() < 2 ||
15928 mixed_result.components.size() != mixed_result.ratios.size()) {
15929 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: invalid pending mixed filament dialog="
15930 << mixed.dialog_index;
15931 continue;
15932 }
15933
15934 const int final_idx = (int)wxGetApp().preset_bundle->filament_presets.size();
15935 if (create_mixed_filament_from_result(sidebar, mixed_result, physical_colors_for_mixing)) {
15936 if (mixed.dialog_index >= 0 && mixed.dialog_index < (int)filament_index_remap.size())
15937 filament_index_remap[mixed.dialog_index] = final_idx;
15938 physical_colors_for_mixing = collect_physical_color_strs();
15939 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: created pending mixed filament dialog="
15940 << mixed.dialog_index << " final=" << final_idx;
15941 }
15942 }
15943
15944 std::vector<Slic3r::FilamentMatch> remapped_matches = final_matches;
15945 for (auto& m : remapped_matches) {
15946 if (m.filament_index < 0)
15947 continue;
15948 if (m.filament_index < (int)filament_index_remap.size() && filament_index_remap[m.filament_index] >= 0) {
15949 m.filament_index = filament_index_remap[m.filament_index];
15950 } else {
15951 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: invalid filament index "
15952 << m.filament_index << " in texture mapping";
15953 m.filament_index = -1;
15954 }
15955 }
15956
15957 int min_used_filament_1based = -1;
15958 {
15959 std::map<std::array<std::size_t, 3>, int> color_to_filament;
15960 for (const auto& m : remapped_matches) {
15961 if (m.cluster_index >= 0 && m.cluster_index < (int)painted.cluster_colors.size() && m.filament_index >= 0)
15962 color_to_filament[painted.cluster_colors[m.cluster_index]] = m.filament_index + 1;
15963 }
15964 for (const auto& face_color : painted.face_colors) {
15965 auto it = color_to_filament.find(face_color);
15966 if (it == color_to_filament.end())
15967 continue;
15968 if (min_used_filament_1based < 0 || it->second < min_used_filament_1based)
15969 min_used_filament_1based = it->second;
15970 }
15971 }
15972 if (min_used_filament_1based < 0)
15973 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: cannot determine base filament from painted faces";
15974
15975 if (!update_apply_progress(25, _L("Applying texture colors...")))
15976 return;
15977
15978 for (size_t obj_order = 0; obj_order < obj_idxs.size(); ++obj_order) {
15979 size_t idx = obj_idxs[obj_order];
15980 if (idx >= loaded_model.objects.size()) continue;
15981 ModelObject* obj = loaded_model.objects[idx];
15982 if (!obj) continue;
15983
15984 // painted is derived from the whole textured mesh and is meaningful
15985 // only against a single MODEL_PART volume. Applying it to every
15986 // volume of a multi-part / modifier object would overwrite each
15987 // volume with the same painted geometry. Restrict to the first
15988 // model_part and warn when the object holds more than one.
15989 ModelVolume* target = nullptr;
15990 int part_count = 0;
15991 for (ModelVolume* vol : obj->volumes) {
15992 if (vol && vol->is_model_part()) {
15993 ++part_count;
15994 if (!target) target = vol;
15995 }
15996 }
15997 if (!target) continue;
15998 if (part_count > 1) {
15999 BOOST_LOG_TRIVIAL(warning)
16000 << "handle_textured_mesh_import: object has " << part_count
16001 << " model parts; painting only applied to the first part.";
16002 }
16003 if (Slic3r::apply_painted_mesh_to_volume(painted, remapped_matches, *target)
16004 && min_used_filament_1based > 0) {
16005 target->config.set("extruder", min_used_filament_1based);
16006 obj->config.set("extruder", min_used_filament_1based);
16007 if (update_scene) {
16008 if (auto* obj_list = wxGetApp().obj_list()) {
16010 wxGetApp().filaments_cnt(), (size_t)min_used_filament_1based));
16012 }
16013 }
16014 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: set base filament to "
16015 << min_used_filament_1based << " for object index " << idx
16016 << ", object extruder=" << obj->config.extruder()
16017 << ", volume extruder=" << target->config.extruder();
16018 }
16019 // bbox invalidation is performed inside apply_painted_mesh_to_volume.
16020 obj->ensure_on_bed();
16021 const int object_percent = 25 + (int)(60 * (obj_order + 1) / std::max<size_t>(obj_idxs.size(), 1));
16022 if (!update_apply_progress(object_percent, _L("Applying texture colors...")))
16023 return;
16024 }
16025
16026 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: painting applied to model volumes";
16027 loaded_model.texture_mesh.reset();
16028 if (update_scene) {
16029 if (!update_apply_progress(90, _L("Updating 3D view...")))
16030 return;
16031 update();
16032 }
16033 update_apply_progress(100, _L("Texture colors applied."));
16034}
size_t size() const override
Definition Config.hpp:722
void update_objects_list_filament_column(size_t filaments_count)
Definition GUI_ObjectList.cpp:1046
void update_info_items(size_t obj_idx, wxDataViewItemArray *selections=nullptr, bool added_object=false, bool color_mode_changed=false)
Definition GUI_ObjectList.cpp:4039
std::shared_ptr< TexturedMesh > texture_mesh
Definition Model.hpp:1718
ModelObjectPtrs objects
Definition Model.hpp:1702
static ObjectList * obj_list()
Definition GUI_Factories.cpp:405
static bool create_mixed_filament_from_result(Sidebar *sidebar, const MixedFilamentResult &result, const std::vector< std::string > &color_strs)
Definition Plater.cpp:5033
@ ExistingMixed
Definition TextureImportDialog.hpp:56
@ NewPhysical
Definition TextureImportDialog.hpp:57
@ ExistingPhysical
Definition TextureImportDialog.hpp:55
bool apply_painted_mesh_to_volume(const PaintedMesh &painted, const std::vector< FilamentMatch > &matches, ModelVolume &volume)
Definition TexturePainting.cpp:468
ConfigOptionBoolsTempl< false > ConfigOptionBools
Definition Config.hpp:2066

References _L, Slic3r::apply_painted_mesh_to_volume(), Slic3r::GUI::MixedFilamentResult::components, Slic3r::ModelObject::config, Slic3r::ModelVolume::config, Slic3r::GUI::create_mixed_filament_from_result(), Slic3r::ModelObject::ensure_on_bed(), Slic3r::GUI::ExistingMixed, Slic3r::GUI::ExistingPhysical, Slic3r::ModelConfig::extruder(), Slic3r::GUI::Plater::priv::TextureImportResult::filament_entries, Slic3r::ModelVolume::is_model_part(), Slic3r::GUI::Plater::priv::TextureImportResult::matches, Slic3r::GUI::Plater::priv::TextureImportResult::new_mixed_filaments, Slic3r::GUI::NewPhysical, Slic3r::GUI::obj_list(), Slic3r::Model::objects, Slic3r::GUI::Plater::priv::TextureImportResult::painted, Slic3r::GUI::MixedFilamentResult::ratios, Slic3r::ModelConfig::set(), sidebar, Slic3r::GUI::Plater::priv::TextureImportResult::skipped, Slic3r::Model::texture_mesh, Slic3r::GUI::Plater::update(), Slic3r::ConfigOptionVector< T >::values, and Slic3r::ModelObject::volumes.

Referenced by handle_textured_mesh_import(), and load_files().

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

◆ are_view3D_labels_shown()

bool Slic3r::GUI::Plater::priv::are_view3D_labels_shown ( ) const
inline
7363{ return (current_panel == view3D) && view3D->get_canvas3d()->are_labels_shown(); }
wxPanel * current_panel
Definition Plater.cpp:7209

References current_panel, and view3D.

◆ auto_slice_delay_seconds()

int Slic3r::GUI::Plater::priv::auto_slice_delay_seconds ( ) const
11186{
11187 AppConfig* cfg = wxGetApp().app_config;
11188 if (cfg == nullptr)
11189 return 0;
11190
11191 std::string delay_str = cfg->get("auto_slice_change_delay_seconds");
11192 if (delay_str.empty())
11193 return 0;
11194
11195 long delay_seconds = 0;
11196 try {
11197 delay_seconds = std::stol(delay_str);
11198 } catch (...) {
11199 delay_seconds = 0;
11200 }
11201
11202 if (delay_seconds < 0)
11203 delay_seconds = 0;
11204
11205 const long max_seconds = std::numeric_limits<int>::max() / 1000;
11206 if (delay_seconds > max_seconds)
11207 delay_seconds = max_seconds;
11208
11209 return static_cast<int>(delay_seconds);
11210}

References Slic3r::AppConfig::get().

Referenced by schedule_auto_reslice_if_needed().

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

◆ background_processing_enabled()

bool Slic3r::GUI::Plater::priv::background_processing_enabled ( ) const
inline
7542 {
7543#ifdef SUPPORT_BACKGROUND_PROCESSING
7544 return this->get_config("background_processing") == "1";
7545#else
7546 return false;
7547#endif
7548 }

References get_config().

Referenced by update_background_process().

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

◆ bed_shape_bb()

BoundingBoxf Slic3r::GUI::Plater::priv::bed_shape_bb ( ) const
8795{
8796 BoundingBox bb = scaled_bed_shape_bb();
8797 return BoundingBoxf(unscale(bb.min), unscale(bb.max));
8798}
T unscale(Q v)
Definition libslic3r.h:138
BoundingBox scaled_bed_shape_bb() const
Definition Plater.cpp:8800

References Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::min, scaled_bed_shape_bb(), and Slic3r::unscale().

Here is the call graph for this function:

◆ bring_instance_forward()

void Slic3r::GUI::Plater::priv::bring_instance_forward ( ) const
15585{
15586#ifdef __APPLE__
15587 wxGetApp().other_instance_message_handler()->bring_instance_forward();
15588 return;
15589#endif //__APPLE__
15590 if (main_frame == nullptr) {
15591 BOOST_LOG_TRIVIAL(debug) << "Couldnt bring instance forward - mainframe is null";
15592 return;
15593 }
15594 BOOST_LOG_TRIVIAL(debug) << "Orca Slicer window going forward";
15595 //this code maximize app window on Fedora
15596 {
15597 main_frame->Iconize(false);
15598 if (main_frame->IsMaximized())
15599 main_frame->Maximize(true);
15600 else
15601 main_frame->Maximize(false);
15602 }
15603 //this code maximize window on Ubuntu
15604 {
15605 main_frame->Restore();
15606 wxGetApp().GetTopWindow()->SetFocus(); // focus on my window
15607 wxGetApp().GetTopWindow()->Show(true); // show the window
15608 wxGetApp().GetTopWindow()->Raise(); // bring window to front
15609 }
15610}

References main_frame.

◆ can_add_plate()

bool Slic3r::GUI::Plater::priv::can_add_plate ( ) const
15049{
15050 return q->get_partplate_list().get_plate_count() < PartPlateList::MAX_PLATES_COUNT;
15051}
static constexpr unsigned int MAX_PLATES_COUNT
Definition PartPlate.hpp:893

References Slic3r::GUI::PartPlateList::MAX_PLATES_COUNT, and q.

◆ can_arrange()

bool Slic3r::GUI::Plater::priv::can_arrange ( ) const
15130{
15131 return !model.objects.empty() && m_worker.is_idle();
15132}

References m_worker, and model.

◆ can_decrease_instances()

bool Slic3r::GUI::Plater::priv::can_decrease_instances ( ) const
15109{
15110 if (!m_worker.is_idle()
15111 || q->get_view3D_canvas3D()->get_gizmos_manager().is_in_editing_mode())
15112 return false;
15113
15114 int obj_idx = get_selected_object_idx();
15115 return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1)
15116 && !sidebar->obj_list()->has_selected_cut_object();
15117}
int get_selected_object_idx() const
Definition Plater.cpp:10637

References Slic3r::GUI::Plater::get_selected_object_idx(), m_worker, model, q, and sidebar.

Here is the call graph for this function:

◆ can_delete()

bool Slic3r::GUI::Plater::priv::can_delete ( ) const
15039{
15041}
bool is_wipe_tower() const
Definition Selection.hpp:273
bool is_empty() const
Definition Selection.hpp:272
const Selection & get_selection() const
Definition Plater.cpp:10622

References Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::is_empty(), and Slic3r::GUI::Selection::is_wipe_tower().

Here is the call graph for this function:

◆ can_delete_all()

bool Slic3r::GUI::Plater::priv::can_delete_all ( ) const
15044{
15045 return !model.objects.empty();
15046}

References model.

◆ can_delete_plate()

bool Slic3r::GUI::Plater::priv::can_delete_plate ( ) const
15054{
15055 return q->get_partplate_list().get_plate_count() > 1;
15056}

References q.

◆ can_fillcolor()

bool Slic3r::GUI::Plater::priv::can_fillcolor ( ) const
14858{
14859 //BBS TODO
14860 return true;
14861}

◆ can_fix_through_cgal()

bool Slic3r::GUI::Plater::priv::can_fix_through_cgal ( ) const
15059{
15060 std::vector<int> obj_idxs, vol_idxs;
15061 sidebar->obj_list()->get_selection_indexes(obj_idxs, vol_idxs);
15062
15063 // A closed mesh may still self-intersect, so fixing is always allowed.
15064 return ! obj_idxs.empty() || ! vol_idxs.empty();
15065}

References sidebar.

◆ can_increase_instances()

bool Slic3r::GUI::Plater::priv::can_increase_instances ( ) const
15097{
15098 if (!m_worker.is_idle()
15099 || q->get_view3D_canvas3D()->get_gizmos_manager().is_in_editing_mode())
15100 return false;
15101
15102 int obj_idx = get_selected_object_idx();
15103 return (0 <= obj_idx) && (obj_idx < (int)model.objects.size())
15104 && !sidebar->obj_list()->has_selected_cut_object()
15105 && std::all_of(model.objects[obj_idx]->instances.begin(), model.objects[obj_idx]->instances.end(), [](auto& inst) {return inst->printable; });
15106}

References Slic3r::GUI::Plater::get_selected_object_idx(), m_worker, model, q, and sidebar.

Here is the call graph for this function:

◆ can_layers_editing()

bool Slic3r::GUI::Plater::priv::can_layers_editing ( ) const
15144{
15145 return layers_height_allowed();
15146}
bool layers_height_allowed() const
Definition Plater.cpp:15134

References layers_height_allowed().

Here is the call graph for this function:

◆ can_mirror()

bool Slic3r::GUI::Plater::priv::can_mirror ( ) const
14894{
14895 return !sidebar->obj_list()->has_selected_cut_object()
14897}
bool is_from_single_instance() const
Definition Selection.hpp:287

References Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::is_from_single_instance(), and sidebar.

Here is the call graph for this function:

◆ can_reload_from_disk()

bool Slic3r::GUI::Plater::priv::can_reload_from_disk ( ) const
14912{
14913 if (sidebar->obj_list()->has_selected_cut_object())
14914 return false;
14915
14916#if ENABLE_RELOAD_FROM_DISK_REWORK
14917 // collect selected reloadable ModelVolumes
14918 std::vector<std::pair<int, int>> selected_volumes = reloadable_volumes(model, get_selection());
14919 // nothing to reload, return
14920 if (selected_volumes.empty())
14921 return false;
14922#else
14923 // struct to hold selected ModelVolumes by their indices
14924 struct SelectedVolume
14925 {
14926 int object_idx;
14927 int volume_idx;
14928
14929 // operators needed by std::algorithms
14930 bool operator < (const SelectedVolume& other) const { return (object_idx < other.object_idx) || ((object_idx == other.object_idx) && (volume_idx < other.volume_idx)); }
14931 bool operator == (const SelectedVolume& other) const { return (object_idx == other.object_idx) && (volume_idx == other.volume_idx); }
14932 };
14933 std::vector<SelectedVolume> selected_volumes;
14934
14935 const Selection& selection = get_selection();
14936
14937 // collects selected ModelVolumes
14938 const std::set<unsigned int>& selected_volumes_idxs = selection.get_volume_idxs();
14939 for (unsigned int idx : selected_volumes_idxs) {
14940 const GLVolume* v = selection.get_volume(idx);
14941 int v_idx = v->volume_idx();
14942 if (v_idx >= 0) {
14943 int o_idx = v->object_idx();
14944 if (0 <= o_idx && o_idx < (int)model.objects.size())
14945 selected_volumes.push_back({ o_idx, v_idx });
14946 }
14947 }
14948#endif // ENABLE_RELOAD_FROM_DISK_REWORK
14949
14950#if ENABLE_RELOAD_FROM_DISK_REWORK
14951 std::sort(selected_volumes.begin(), selected_volumes.end(), [](const std::pair<int, int> &v1, const std::pair<int, int> &v2) {
14952 return (v1.first < v2.first) || (v1.first == v2.first && v1.second < v2.second);
14953 });
14954 selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end(), [](const std::pair<int, int> &v1, const std::pair<int, int> &v2) {
14955 return (v1.first == v2.first) && (v1.second == v2.second);
14956 }), selected_volumes.end());
14957
14958 // collects paths of files to load
14959 std::vector<fs::path> paths;
14960 for (auto [obj_idx, vol_idx] : selected_volumes) {
14961 paths.push_back(model.objects[obj_idx]->volumes[vol_idx]->source.input_file);
14962 }
14963#else
14964 std::sort(selected_volumes.begin(), selected_volumes.end());
14965 selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end()), selected_volumes.end());
14966
14967 // collects paths of files to load
14968 std::vector<fs::path> paths;
14969 for (const SelectedVolume& v : selected_volumes) {
14970 const ModelObject* object = model.objects[v.object_idx];
14971 const ModelVolume* volume = object->volumes[v.volume_idx];
14972 if (!volume->source.input_file.empty())
14973 paths.push_back(volume->source.input_file);
14974 else if (!object->input_file.empty() && !volume->name.empty() && !volume->source.is_from_builtin_objects)
14975 paths.push_back(volume->name);
14976 }
14977#endif // ENABLE_RELOAD_FROM_DISK_REWORK
14978 std::sort(paths.begin(), paths.end());
14979 paths.erase(std::unique(paths.begin(), paths.end()), paths.end());
14980
14981 return !paths.empty();
14982}
static bool operator<(wxColour const &l, wxColour const &r)
Definition StateColor.cpp:11
@ Selection
Definition Shortcuts.hpp:72

References Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::ModelObject::input_file, Slic3r::ModelVolume::Source::input_file, Slic3r::ModelVolume::Source::is_from_builtin_objects, model, Slic3r::ModelVolume::name, Slic3r::GLVolume::object_idx(), operator<(), sidebar, Slic3r::ModelVolume::source, and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ can_replace_all_with_stl()

bool Slic3r::GUI::Plater::priv::can_replace_all_with_stl ( ) const
14906{
14907 return !sidebar->obj_list()->has_selected_cut_object()
14908 && get_selection().get_volume_idxs().size() != 1;
14909}
const IndicesList & get_volume_idxs() const
Definition Selection.hpp:315

References Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::get_volume_idxs(), and sidebar.

Here is the call graph for this function:

◆ can_replace_with_stl()

bool Slic3r::GUI::Plater::priv::can_replace_with_stl ( ) const
14900{
14901 return !sidebar->obj_list()->has_selected_cut_object()
14902 && get_selection().get_volume_idxs().size() == 1;
14903}

References Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::get_volume_idxs(), and sidebar.

Here is the call graph for this function:

◆ can_set_instance_to_object()

bool Slic3r::GUI::Plater::priv::can_set_instance_to_object ( ) const
14847{
14848 const int obj_idx = get_selected_object_idx();
14849 return 0 <= obj_idx && obj_idx < (int)model.objects.size() && model.objects[obj_idx]->instances.size() > 1;
14850}

References Slic3r::GUI::Plater::get_selected_object_idx(), and model.

Here is the call graph for this function:

◆ can_simplify()

bool Slic3r::GUI::Plater::priv::can_simplify ( ) const
15068{
15069 // is object for simplification selected
15070 if (get_selected_object_idx() < 0) return false;
15071 // is already opened?
15072 if (q->get_view3D_canvas3D()->get_gizmos_manager().get_current_type() ==
15074 return false;
15075 return true;
15076}
@ Simplify
Definition GLGizmosManager.hpp:103

References Slic3r::GUI::Plater::get_selected_object_idx(), q, and Slic3r::GUI::GLGizmosManager::Simplify.

Here is the call graph for this function:

◆ can_smooth_mesh()

bool Slic3r::GUI::Plater::priv::can_smooth_mesh ( ) const
15079{
15080 std::vector<int> obj_idxs, vol_idxs;
15081 sidebar->obj_list()->get_selection_indexes(obj_idxs, vol_idxs);
15082 if (vol_idxs.empty()) {
15083 for (auto obj_idx : obj_idxs)
15084 if (model.objects[obj_idx]->get_object_stl_stats().open_edges > 0)
15085 return false;
15086 return true;
15087 }
15088
15089 int obj_idx = obj_idxs.front();
15090 for (auto vol_idx : vol_idxs)
15091 if (model.objects[obj_idx]->get_object_stl_stats().open_edges > 0)
15092 return false;
15093 return true;
15094}

References model, and sidebar.

◆ can_split()

bool Slic3r::GUI::Plater::priv::can_split ( bool to_objects) const
14853{
14854 return sidebar->obj_list()->is_splittable(to_objects);
14855}

References sidebar.

◆ can_split_to_objects()

bool Slic3r::GUI::Plater::priv::can_split_to_objects ( ) const
15120{
15121 return q->can_split(true);
15122}

References q.

◆ can_split_to_volumes()

bool Slic3r::GUI::Plater::priv::can_split_to_volumes ( ) const
15125{
15126 return (printer_technology != ptSLA) && q->can_split(false);
15127}
@ ptSLA
Definition Config.hpp:233
PrinterTechnology printer_technology
Definition Plater.cpp:7195

References printer_technology, Slic3r::ptSLA, and q.

◆ center_selection()

void Slic3r::GUI::Plater::priv::center_selection ( )
10926{
10927 view3D->center_selected();
10928}

References view3D.

◆ check_ams_status_impl()

bool Slic3r::GUI::Plater::priv::check_ams_status_impl ( bool is_slice_all)
14652{
14653 Slic3r::DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
14654 if (!dev)
14655 return true;
14656
14657 MachineObject* obj = dev->get_selected_machine();
14658 if (!obj || !obj->is_multi_extruders())
14659 return true;
14660 if (q->is_gcode_3mf() || q->only_gcode_mode() || q->get_partplate_list().get_curr_plate()->get_objects().empty()) {
14661 return true;
14662 }
14663 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
14664 if (preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->get_show_printer_type()) {
14665 bool is_same_as_printer = true;
14666 auto nozzle_volumes_values = preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type")->values;
14667 assert(obj->GetExtderSystem()->GetTotalExtderCount() == 2 && nozzle_volumes_values.size() == 2);
14668 if (obj->GetExtderSystem()->GetTotalExtderCount() == 2 && nozzle_volumes_values.size() == 2) {
14669 // [Vortek] H2C: Use BBS-style NozzleGroupInfo comparison instead of direct nozzle type match.
14670 // This correctly handles Hybrid presets (which expand into per-type counts) and detects
14671 // never-synced state (nozzle_count==0) so the first sync dialog appears.
14672 // After device sync, extruder_nozzle_stats matches printer → dialog suppressed.
14673 // Reference to BBS: BambuStudio/src/slic3r/GUI/Plater.cpp is_extruder_stat_synced()
14674 using namespace MultiNozzleUtils;
14675 auto nozzle_diameter_values = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloatsNullable>("nozzle_diameter")->values;
14676
14677 // Build preset nozzle groups from extruder_nozzle_stats config
14678 std::vector<std::vector<NozzleGroupInfo>> preset_nozzle_infos(nozzle_diameter_values.size());
14679 for (size_t extruder_id = 0; extruder_id < nozzle_diameter_values.size(); ++extruder_id) {
14680 NozzleVolumeType preset_volume_type = NozzleVolumeType(nozzle_volumes_values[extruder_id]);
14681 std::string preset_diameter = format_diameter_to_str(nozzle_diameter_values[extruder_id]);
14682
14683 if (preset_volume_type == nvtHybrid) {
14684 // Hybrid: expand into separate groups for each nozzle type from stats
14685 int std_count = getExtruderNozzleCount(preset_bundle, extruder_id, nvtStandard);
14686 int hf_count = getExtruderNozzleCount(preset_bundle, extruder_id, nvtHighFlow);
14687 if (std_count > 0)
14688 preset_nozzle_infos[extruder_id].emplace_back(preset_diameter, nvtStandard, extruder_id, std_count);
14689 if (hf_count > 0)
14690 preset_nozzle_infos[extruder_id].emplace_back(preset_diameter, nvtHighFlow, extruder_id, hf_count);
14691 // If both are 0 → never synced → empty group → will mismatch
14692 } else {
14693 int count = getExtruderNozzleCount(preset_bundle, extruder_id, preset_volume_type);
14694 preset_nozzle_infos[extruder_id].emplace_back(preset_diameter, preset_volume_type, extruder_id, count);
14695 }
14696 }
14697
14698 // Compare with printer nozzle groups
14699 auto printer_groups = obj->GetNozzleSystem()->GetNozzleGroups();
14700 for (const auto& preset_groups : preset_nozzle_infos) {
14701 for (const auto& preset_group : preset_groups) {
14702 if (preset_group.nozzle_count == 0) {
14703 // Never synced: if printer has nozzles of this type → needs sync
14704 if (std::find_if(printer_groups.begin(), printer_groups.end(),
14705 [&preset_group](const NozzleGroupInfo& elem) { return preset_group.is_same_type(elem); })
14706 != printer_groups.end()) {
14707 is_same_as_printer = false;
14708 break;
14709 }
14710 } else if (std::find(printer_groups.begin(), printer_groups.end(), preset_group) == printer_groups.end()) {
14711 is_same_as_printer = false;
14712 break;
14713 }
14714 }
14715 }
14716 }
14717
14718 std::vector<std::map<int, int>> ams_count_info;
14719 ams_count_info.resize(2);
14720 int deputy_4 = 0, main_4 = 0, deputy_1 = 0, main_1 = 0;
14721 for (auto ams : obj->GetFilaSystem()->GetAmsList()) {
14722 // Main (first) extruder at right
14723 if (ams.second->GetExtruderId() == 0) {
14724 if (ams.second->GetAmsType() == DevAms::N3S) // N3S
14725 ++main_1;
14726 else
14727 ++main_4;
14728 } else if (ams.second->GetExtruderId() == 1) {
14729 if (ams.second->GetAmsType() == DevAms::N3S) // N3S
14730 ++deputy_1;
14731 else
14732 ++deputy_4;
14733 }
14734 }
14735
14736 int left_4 = main_4;
14737 int left_1 = main_1;
14738 int right_4 = deputy_4;
14739 int right_1 = deputy_1;
14740 if (!obj->is_main_extruder_on_left()) {
14741 left_4 = deputy_4;
14742 left_1 = deputy_1;
14743 right_4 = main_4;
14744 right_1 = main_1;
14745 }
14746
14747 if (!preset_bundle->extruder_ams_counts.empty() && !preset_bundle->extruder_ams_counts.front().empty()) {
14748 is_same_as_printer &= preset_bundle->extruder_ams_counts[0][4] == left_4
14749 && preset_bundle->extruder_ams_counts[0][1] == left_1
14750 && preset_bundle->extruder_ams_counts[1][4] == right_4
14751 && preset_bundle->extruder_ams_counts[1][1] == right_1;
14752 }
14753
14754 if (!is_same_as_printer) {
14755 struct SyncInfoDialog : MessageDialog
14756 {
14757 SyncInfoDialog(wxWindow *parent)
14758 : MessageDialog(parent,
14759 _L("The nozzle type and AMS quantity information has not been synced from the connected printer.\n"
14760 "After syncing, software can optimize printing time and filament usage when slicing.\n"
14761 "Would you like to sync now?"),
14762 _L("Warning"), 0)
14763 {
14764 add_button(wxID_YES, true, _L("Sync now"));
14765 add_button(wxID_NO, true, _L("Later"));
14766 }
14767 } dlg(q);
14768 dlg.Fit();
14769 if (dlg.ShowModal() == wxID_YES) {
14770 if (GUI::wxGetApp().sidebar().sync_extruder_list()) {
14771 if (is_slice_all)
14772 wxPostEvent(q, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL));
14773 else
14774 wxPostEvent(q, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE));
14775 wxGetApp().mainframe->m_tabpanel->SelectPageByName(TAB_ID_PREVIEW);
14776 }
14777 return false;
14778 }
14779 }
14780 }
14781
14782 return true;
14783}
static unsigned int count
Definition AuxiliaryDataViewModel.cpp:246
#define TAB_ID_PREVIEW
Definition MainFrame.hpp:61
static constexpr AmsType N3S
Definition DevFilaSystem.h:147
MachineObject * get_selected_machine()
Definition DevManager.cpp:747
int getExtruderNozzleCount(PresetBundle *preset_bundle, int extruder_id, NozzleVolumeType volume_type)
Definition MultiNozzleSync.cpp:72
NozzleVolumeType
Definition PrintConfig.hpp:618
@ nvtHybrid
Definition PrintConfig.hpp:621
@ nvtHighFlow
Definition PrintConfig.hpp:620
@ nvtStandard
Definition PrintConfig.hpp:619
ConfigOptionEnumsGenericTempl< false > ConfigOptionEnumsGeneric
Definition Config.hpp:2311
ConfigOptionFloatsTempl< true > ConfigOptionFloatsNullable
Definition Config.hpp:1016
std::string format_diameter_to_str(double diameter, int precision)
Definition utils.cpp:1739

References _L, Slic3r::Preset::config, count, Slic3r::PresetBundle::extruder_ams_counts, Slic3r::format_diameter_to_str(), Slic3r::PresetCollection::get_edited_preset(), Slic3r::Preset::get_printer_type(), Slic3r::DeviceManager::get_selected_machine(), Slic3r::MachineObject::get_show_printer_type(), Slic3r::MachineObject::GetExtderSystem(), Slic3r::GUI::getExtruderNozzleCount(), Slic3r::MachineObject::GetFilaSystem(), Slic3r::DevNozzleSystem::GetNozzleGroups(), Slic3r::MachineObject::GetNozzleSystem(), Slic3r::DevExtderSystem::GetTotalExtderCount(), Slic3r::MachineObject::is_main_extruder_on_left(), Slic3r::MachineObject::is_multi_extruders(), Slic3r::DevAms::N3S, Slic3r::nvtHighFlow, Slic3r::nvtHybrid, Slic3r::nvtStandard, Slic3r::ConfigBase::option(), Slic3r::PresetBundle::printers, Slic3r::PresetBundle::project_config, q, Slic3r::GUI::Plater::sidebar(), and TAB_ID_PREVIEW.

Here is the call graph for this function:

◆ clear_warnings()

void Slic3r::GUI::Plater::priv::clear_warnings ( )
13315{
13316 notification_manager->close_slicing_errors_and_warnings();
13317 this->current_warnings.clear();
13318}

References current_warnings, and notification_manager.

Referenced by actualize_slicing_warnings(), on_slicing_began(), and reset().

Here is the caller graph for this function:

◆ collapse_sidebar()

void Slic3r::GUI::Plater::priv::collapse_sidebar ( bool collapse)
8621{
8623 return;
8624
8625 sidebar_layout.is_collapsed = collapse;
8626
8627 // Now update the tooltip in the toolbar.
8628 const std::string new_tooltip = wxGetApp().shortcuts().with_key(collapse ? _u8L("Expand sidebar") : _u8L("Collapse sidebar"), Shortcut::CollapseSidebar);
8629 int id = collapse_toolbar.get_item_id("collapse_sidebar");
8630 collapse_toolbar.set_tooltip(id, new_tooltip);
8631
8633}
@ CollapseSidebar
Definition Shortcuts.hpp:51
#define _u8L(s)
Definition I18N.hpp:11
bool gcode_preview_without_settings() const
Definition Plater.cpp:7386

References _u8L, collapse_toolbar, Slic3r::GUI::CollapseSidebar, gcode_preview_without_settings(), sidebar_layout, and update_sidebar().

Here is the call graph for this function:

◆ delete_all_objects_from_model()

void Slic3r::GUI::Plater::priv::delete_all_objects_from_model ( )
10793{
10794 Plater::TakeSnapshot snapshot(q, _u8L("Delete All Objects"));
10795
10796 if (view3D->is_layers_editing_enabled())
10797 view3D->enable_layers_editing(false);
10798
10800 gcode_result.reset();
10801
10802 view3D->get_canvas3d()->reset_sequential_print_clearance();
10803
10804 m_worker.cancel_all();
10805
10806 // Stop and reset the Print content.
10807 background_process.reset();
10808
10809 //BBS: update partplate
10810 partplate_list.clear();
10811
10812 model.clear_objects();
10813 update();
10814 // Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
10815 sidebar->obj_list()->delete_all_objects_from_list();
10817
10818 //BBS
10819 model.calib_pa_pattern.reset();
10820 model.plates_custom_gcodes.clear();
10821}
Slic3r::GCodeProcessorResult gcode_result
Definition Plater.cpp:7196
void reset_gcode_toolpaths()
Definition Plater.cpp:14841
void object_list_changed()
Definition Plater.cpp:10671

References _u8L, background_process, gcode_result, m_worker, model, Slic3r::GUI::Plater::object_list_changed(), partplate_list, q, Slic3r::GUI::Plater::reset_gcode_toolpaths(), sidebar, Slic3r::GUI::Plater::update(), and view3D.

Here is the call graph for this function:

◆ delete_object_from_model()

bool Slic3r::GUI::Plater::priv::delete_object_from_model ( size_t obj_idx,
bool refresh_immediately = true )
10750{
10751 // check if object isn't cut
10752 // show warning message that "cut consistancy" will not be supported any more
10753 ModelObject *obj = model.objects[obj_idx];
10754 if (obj->is_cut()) {
10755 InfoDialog dialog(q, _L("Delete object which is a part of cut object"),
10756 _L("You are trying to delete an object which is a part of a cut object.\nThis action will break a cut correspondence.\nAfter that, model consistency can\'t be guaranteed."),
10757 false, wxYES | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING);
10758 dialog.SetButtonLabel(wxID_YES, _L("Delete"));
10759 if (dialog.ShowModal() == wxID_CANCEL)
10760 return false;
10761 }
10762
10763 std::string snapshot_label = _u8L("Delete Object");
10764 if (!obj->name.empty())
10765 snapshot_label += ": " + obj->name;
10766 Plater::TakeSnapshot snapshot(q, snapshot_label);
10767 m_worker.cancel_all();
10768
10769 if (obj->is_cut())
10770 sidebar->obj_list()->invalidate_cut_info_for_object(obj_idx);
10771
10772 std::string obj_name = obj->name;
10773 model.delete_object(obj_idx);
10774 {
10775 Slic3r::LifecycleEventContext ctx;
10776 ctx.name = obj_name;
10779 }
10780 //BBS: notify partplate the instance removed
10781 partplate_list.notify_instance_removed(obj_idx, -1);
10782
10783 //BBS
10784 if (refresh_immediately) {
10785 update();
10787 }
10788
10789 return true;
10790}
std::string name
Definition LifecycleEvents.hpp:75
@ ObjectDeleted
Definition LifecycleEvents.hpp:37
@ Ok
Definition LifecycleEvents.hpp:68
LifecycleEvtCode code
Definition LifecycleEvents.hpp:79
void fire_lifecycle_event(LifecycleEvent event, const LifecycleEventContext &ctx)
Definition LifecycleEvents.hpp:234

References _L, _u8L, Slic3r::LifecycleEventContext::code, Slic3r::fire_lifecycle_event(), Slic3r::ModelObject::is_cut(), m_worker, model, Slic3r::LifecycleEventContext::name, Slic3r::ModelObject::name, Slic3r::GUI::Plater::object_list_changed(), Slic3r::ObjectDeleted, Slic3r::Ok, partplate_list, q, Slic3r::GUI::MsgDialog::SetButtonLabel(), Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, and Slic3r::GUI::Plater::update().

Here is the call graph for this function:

◆ deselect_all()

void Slic3r::GUI::Plater::priv::deselect_all ( )
10717{
10718 view3D->deselect_all();
10719}

References view3D.

◆ dock_pane_visible()

bool Slic3r::GUI::Plater::priv::dock_pane_visible ( const DockPane & dock_pane,
const wxAuiPaneInfo & pane ) const
8684{
8685 // A floating pane is a top-level window, so it does not hide with the Plater on other tabs.
8686 return dock_pane.shown && (!pane.IsFloating() || sidebar_layout.show);
8687}

References Slic3r::GUI::Plater::priv::DockPane::shown, and sidebar_layout.

Referenced by add_dock_pane(), reset_window_layout(), show_dock_pane(), and update_sidebar().

Here is the caller graph for this function:

◆ drop_selection()

void Slic3r::GUI::Plater::priv::drop_selection ( )
10931{
10932 view3D->drop_selected();
10933}

References view3D.

◆ enable_sidebar()

void Slic3r::GUI::Plater::priv::enable_sidebar ( bool enabled)
8612{
8614 enabled = false;
8615
8616 sidebar_layout.is_enabled = enabled;
8618}

References gcode_preview_without_settings(), sidebar_layout, and update_sidebar().

Here is the call graph for this function:

◆ ensure_belt_purge_tower()

bool Slic3r::GUI::Plater::priv::ensure_belt_purge_tower ( )
11355{
11357}
bool ensure_belt_purge_tower(Model &model, PartPlateList &partplate_list, ObjectList *obj_list, std::vector< BeltPurgeSignature > &sigs)
Definition BeltPurgeTower.cpp:43
std::vector< BeltPurgeSignature > m_belt_purge_sigs
Definition Plater.cpp:7496

References Slic3r::GUI::ensure_belt_purge_tower(), m_belt_purge_sigs, model, partplate_list, and sidebar.

Here is the call graph for this function:

◆ enter_gizmos_stack()

void Slic3r::GUI::Plater::priv::enter_gizmos_stack ( )
15227{
15231 assert(m_undo_redo_stack_active->empty());
15232 // Take the initial snapshot of the gizmos.
15233 // Not localized on purpose, the text will never be shown to the user.
15234 this->take_snapshot(std::string("Gizmos-Initial"));
15235 }
15236}
Slic3r::UndoRedo::Stack m_undo_redo_stack_gizmos
Definition Plater.cpp:7774
Slic3r::UndoRedo::Stack * m_undo_redo_stack_active
Definition Plater.cpp:7775
void take_snapshot(const std::string &snapshot_name, UndoRedo::SnapshotType snapshot_type=UndoRedo::SnapshotType::Action)
Definition Plater.cpp:15259

References m_undo_redo_stack_active, m_undo_redo_stack_gizmos, m_undo_redo_stack_main, and Slic3r::GUI::Plater::take_snapshot().

Here is the call graph for this function:

◆ enter_prepare_mode()

void Slic3r::GUI::Plater::priv::enter_prepare_mode ( )
inline
7415 {
7417 m_select_machine_dlg->prepare_mode();
7418 }
SelectMachineDialog * m_select_machine_dlg
Definition Plater.cpp:7180

References m_select_machine_dlg.

◆ exit_gizmo()

void Slic3r::GUI::Plater::priv::exit_gizmo ( )
10722{
10723 view3D->exit_gizmo();
10724}

References view3D.

◆ export_gcode() [1/2]

void Slic3r::GUI::Plater::priv::export_gcode ( fs::path output_path,
bool output_path_on_removable_media )
11660{
11661 wxCHECK_RET(!(output_path.empty()), "export_gcode: output_path and upload_job empty");
11662
11663 BOOST_LOG_TRIVIAL(trace) << boost::format("export_gcode: output_path %1%")%output_path.string();
11664 if (model.objects.empty())
11665 return;
11666
11667 if (background_process.is_export_scheduled()) {
11668 GUI::show_error(q, _L("Another export job is running."));
11669 return;
11670 }
11671
11672 // bitmask of UpdateBackgroundProcessReturnState
11673 unsigned int state = update_background_process(true);
11675 view3D->reload_scene(false);
11676
11677 if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
11678 return;
11679
11680 show_warning_dialog = true;
11681 if (! output_path.empty()) {
11682 background_process.schedule_export(output_path.string(), output_path_on_removable_media);
11683 notification_manager->push_delayed_notification(NotificationType::ExportOngoing, []() {return true; }, 1000, 0);
11684 } else {
11685 BOOST_LOG_TRIVIAL(info) << "output_path is empty";
11686 }
11687
11688 // If the SLA processing of just a single object's supports is running, restart slicing for the whole object.
11689 this->background_process.set_task(PrintBase::TaskParams());
11691}
void show_error(wxWindow *parent, const wxString &message, bool has_code_excerpts)
Definition GUI.cpp:296
@ ExportOngoing
Definition NotificationManager.hpp:151
bool restart_background_process(unsigned int state)
Definition Plater.cpp:11622
unsigned int update_background_process(bool force_validation=false, bool postpone_error_messages=false, bool switch_print=true)
Definition Plater.cpp:11396
bool show_warning_dialog
Definition Plater.cpp:7791

References _L, background_process, Slic3r::GUI::ExportOngoing, model, notification_manager, q, restart_background_process(), Slic3r::BackgroundSlicingProcess::set_task(), Slic3r::GUI::show_error(), show_warning_dialog, Slic3r::trace(), update_background_process(), UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT, UPDATE_BACKGROUND_PROCESS_INVALID, UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE, and view3D.

Here is the call graph for this function:

◆ export_gcode() [2/2]

void Slic3r::GUI::Plater::priv::export_gcode ( fs::path output_path,
bool output_path_on_removable_media,
PrintHostJob upload_job )
11693{
11694 wxCHECK_RET(!(output_path.empty() && upload_job.empty()), "export_gcode: output_path and upload_job empty");
11695
11696 if (model.objects.empty())
11697 return;
11698
11699 if (background_process.is_export_scheduled()) {
11700 GUI::show_error(q, _L("Another export job is running."));
11701 return;
11702 }
11703
11704 // bitmask of UpdateBackgroundProcessReturnState
11705 unsigned int state = update_background_process(true);
11707 view3D->reload_scene(false);
11708
11709 if ((state & priv::UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
11710 return;
11711
11712 show_warning_dialog = true;
11713 if (! output_path.empty()) {
11714 background_process.schedule_export(output_path.string(), output_path_on_removable_media);
11715 notification_manager->push_delayed_notification(NotificationType::ExportOngoing, []() {return true; }, 1000, 0);
11716 } else {
11717 background_process.schedule_upload(std::move(upload_job));
11718 }
11719
11720 // If the SLA processing of just a single object's supports is running, restart slicing for the whole object.
11721 this->background_process.set_task(PrintBase::TaskParams());
11723}

References _L, background_process, Slic3r::PrintHostJob::empty(), Slic3r::GUI::ExportOngoing, model, notification_manager, q, restart_background_process(), Slic3r::BackgroundSlicingProcess::set_task(), Slic3r::GUI::show_error(), show_warning_dialog, update_background_process(), UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT, UPDATE_BACKGROUND_PROCESS_INVALID, UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE, and view3D.

Here is the call graph for this function:

◆ gcode_preview_without_settings()

bool Slic3r::GUI::Plater::priv::gcode_preview_without_settings ( ) const
inline
7386{ return q->m_only_gcode && !q->m_gcode_settings_loaded; }

References q.

Referenced by collapse_sidebar(), and enable_sidebar().

Here is the caller graph for this function:

◆ generate_first_layer_bbox()

PlateBBoxData Slic3r::GUI::Plater::priv::generate_first_layer_bbox ( )
14321{
14322 PlateBBoxData bboxdata;
14323 std::vector<BBoxData>& id_bboxes = bboxdata.bbox_objs;
14324 BoundingBoxf bbox_all;
14325 auto print = this->background_process.m_fff_print;
14326 auto curr_plate = this->partplate_list.get_curr_plate();
14327 auto curr_plate_seq = curr_plate->get_real_print_seq();
14328 bboxdata.is_seq_print = (curr_plate_seq == PrintSequence::ByObject);
14329 bboxdata.first_extruder = print->get_tool_ordering().first_extruder();
14330 bboxdata.bed_type = bed_type_to_gcode_string(print->config().curr_bed_type.value);
14331 bboxdata.first_layer_time = partplate_list.get_curr_plate()->get_slice_result()->initial_layer_time;
14332 // get nozzle diameter
14333 auto opt_nozzle_diameters = print->config().option<ConfigOptionFloats>("nozzle_diameter");
14334 if (opt_nozzle_diameters != nullptr)
14335 bboxdata.nozzle_diameter = float(opt_nozzle_diameters->get_at(bboxdata.first_extruder));
14336 //PrintObjectPtrs objects;
14337 //if (this->printer_technology == ptFFF) {
14338 // objects = this->background_process.m_fff_print->objects().vector();
14339 //}
14340 //else {
14341 // objects = this->background_process.m_sla_print->objects();
14342 //}
14343 auto objects = print->objects();
14344 auto orig = this->partplate_list.get_curr_plate()->get_origin();
14345 Vec2d orig2d = { orig[0], orig[1] };
14346
14347 BBoxData data;
14348 for (auto obj : objects)
14349 {
14350 auto bb_scaled = obj->get_first_layer_bbox(data.area, data.layer_height, data.name);
14351 // get_first_layer_bbox() is already plate-local, unlike the wipe tower corners below.
14352 auto bb = unscaled(bb_scaled);
14353 bbox_all.merge(bb);
14354 data.area *= (SCALING_FACTOR * SCALING_FACTOR); // unscale area
14355 data.id = obj->id().id;
14356 data.bbox = { bb.min.x(),bb.min.y(),bb.max.x(),bb.max.y() };
14357 id_bboxes.emplace_back(data);
14358 }
14359
14360 // add wipe tower bounding box
14361 if (print->has_wipe_tower()) {
14362 auto wt_corners = print->first_layer_wipe_tower_corners();
14363 // when loading gcode.3mf, wipe tower info may not be correct
14364 if (!wt_corners.empty()) {
14365 BoundingBox bb_scaled = {wt_corners[0], wt_corners[2]};
14366 auto bb = unscaled(bb_scaled);
14367 bb.min -= orig2d;
14368 bb.max -= orig2d;
14369 bbox_all.merge(bb);
14370 data.name = "wipe_tower";
14371 data.id = partplate_list.get_curr_plate()->get_index() + 1000;
14372 data.bbox = {bb.min.x(), bb.min.y(), bb.max.x(), bb.max.y()};
14373 id_bboxes.emplace_back(data);
14374 }
14375 }
14376
14377 bboxdata.bbox_all = { bbox_all.min.x(),bbox_all.min.y(),bbox_all.max.x(),bbox_all.max.y() };
14378 return bboxdata;
14379}
double SCALING_FACTOR
Definition libslic3r.cpp:3
@ ByObject
Definition PrintConfig.hpp:312
static std::string bed_type_to_gcode_string(const BedType type)
Definition PrintConfig.hpp:701
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
ConfigOptionFloatsTempl< false > ConfigOptionFloats
Definition Config.hpp:1015

References Slic3r::BBoxData::area, Slic3r::BBoxData::bbox, Slic3r::PlateBBoxData::bbox_all, Slic3r::PlateBBoxData::bbox_objs, Slic3r::PlateBBoxData::bed_type, Slic3r::bed_type_to_gcode_string(), Slic3r::ByObject, Slic3r::PlateBBoxData::first_extruder, Slic3r::PlateBBoxData::first_layer_time, Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::get_origin(), Slic3r::GUI::PartPlate::get_real_print_seq(), Slic3r::BBoxData::id, Slic3r::ObjectBase::id(), Slic3r::ObjectID::id, Slic3r::PlateBBoxData::is_seq_print, Slic3r::BBoxData::layer_height, Slic3r::BackgroundSlicingProcess::m_fff_print, Slic3r::BoundingBoxBase< PointType, APointsType >::max, Slic3r::BoundingBoxBase< PointType, APointsType >::merge(), Slic3r::BoundingBoxBase< PointType, APointsType >::min, Slic3r::BBoxData::name, Slic3r::PlateBBoxData::nozzle_diameter, partplate_list, SCALING_FACTOR, and Slic3r::unscaled().

Referenced by on_process_completed().

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

◆ generate_thumbnail()

void Slic3r::GUI::Plater::priv::generate_thumbnail ( ThumbnailData & 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 )
14302{
14303 view3D->get_canvas3d()->render_thumbnail(data, w, h, thumbnail_params, camera_type, camera_view_angle_type, for_picking, ban_light);
14304}

References view3D.

Referenced by generate_thumbnails().

Here is the caller graph for this function:

◆ generate_thumbnails()

ThumbnailsList Slic3r::GUI::Plater::priv::generate_thumbnails ( const ThumbnailsParams & params,
Camera::EType camera_type )
14308{
14309 ThumbnailsList thumbnails;
14310 for (const Vec2d& size : params.sizes) {
14311 thumbnails.push_back(ThumbnailData());
14312 Point isize(size); // round to ints
14313 generate_thumbnail(thumbnails.back(), isize.x(), isize.y(), params, camera_type);
14314 if (!thumbnails.back().is_valid())
14315 thumbnails.pop_back();
14316 }
14317 return thumbnails;
14318}
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
std::vector< ThumbnailData > ThumbnailsList
Definition ThumbnailData.hpp:34
void generate_thumbnail(ThumbnailData &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 Plater.cpp:14294

References generate_thumbnail(), and Slic3r::ThumbnailsParams::sizes.

Here is the call graph for this function:

◆ get_active_snapshot_index()

int Slic3r::GUI::Plater::priv::get_active_snapshot_index ( )
15252{
15253 const size_t active_snapshot_time = this->undo_redo_stack().active_snapshot_time();
15254 const std::vector<UndoRedo::Snapshot>& ss_stack = this->undo_redo_stack().snapshots();
15255 const auto it = std::lower_bound(ss_stack.begin(), ss_stack.end(), UndoRedo::Snapshot(active_snapshot_time));
15256 return it - ss_stack.begin();
15257}
size_t active_snapshot_time() const
Definition UndoRedo.cpp:1391
const std::vector< Snapshot > & snapshots() const
Definition UndoRedo.cpp:1389
Slic3r::UndoRedo::Stack & undo_redo_stack()
Definition Plater.cpp:7508

References undo_redo_stack().

Here is the call graph for this function:

◆ get_config()

std::string Slic3r::GUI::Plater::priv::get_config ( const std::string & key) const
8790{
8791 return wxGetApp().app_config->get(key);
8792}

Referenced by apply_free_camera_correction(), background_processing_enabled(), and update().

Here is the caller graph for this function:

◆ get_curr_selection()

Selection & Slic3r::GUI::Plater::priv::get_curr_selection ( )
10633{
10635}
const Selection & get_selection() const
Definition GLCanvas3D.hpp:1028
GLCanvas3D * get_current_canvas3D(bool exclude_preview=false)
Definition Plater.cpp:14603

References Slic3r::GUI::Plater::get_current_canvas3D(), and Slic3r::GUI::GLCanvas3D::get_selection().

Here is the call graph for this function:

◆ get_current_canvas3D()

GLCanvas3D * Slic3r::GUI::Plater::priv::get_current_canvas3D ( bool exclude_preview = false)
14604{
14605 if (current_panel == view3D)
14606 return view3D->get_canvas3d();
14607 else if (!exclude_preview && (current_panel == preview))
14608 return preview->get_canvas3d();
14609 else if (current_panel == assemble_view)
14610 return assemble_view->get_canvas3d();
14611 else //BBS default set to view3D
14612 return view3D->get_canvas3d();
14613
14614 //return (current_panel == view3D) ? view3D->get_canvas3d() : ((current_panel == preview) ? preview->get_canvas3d() : nullptr);
14615}

References assemble_view, current_panel, preview, and view3D.

Referenced by undo_redo_to().

Here is the caller graph for this function:

◆ get_export_file()

wxString Slic3r::GUI::Plater::priv::get_export_file ( GUI::FileType file_type,
const wxString & title = {},
bool published = false )
10532{
10533 wxString wildcard;
10534 switch (file_type) {
10535 case FT_STL:
10536 case FT_DRC:
10537 case FT_AMF:
10538 case FT_3MF:
10539 case FT_GCODE:
10540 case FT_OBJ:
10541 wildcard = file_wildcards(file_type);
10542 break;
10543 default:
10544 wildcard = file_wildcards(FT_MODEL);
10545 break;
10546 }
10547
10548 fs::path output_file = get_export_file_path(file_type);
10549
10550 wxString dlg_title;
10551 switch (file_type) {
10552 case FT_STL:
10553 {
10554 output_file.replace_extension("stl");
10555 dlg_title = _L("Export STL file:");
10556 break;
10557 }
10558 case FT_DRC:
10559 {
10560 output_file.replace_extension("drc");
10561 dlg_title = _L("Export Draco file:");
10562 break;
10563 }
10564 case FT_AMF:
10565 {
10566 // XXX: Problem on OS X with double extension?
10567 output_file.replace_extension("zip.amf");
10568 dlg_title = _L("Export AMF file:");
10569 break;
10570 }
10571 case FT_3MF:
10572 {
10573 // A published export is suggested as "<name>.published.3mf" so the role is visible in the
10574 // dialog and in the recent-files list. This is only a pre-filled suggestion; the user's
10575 // typed filename wins, keeping a plain ".3mf" output fully valid.
10576 output_file.replace_extension(published ? "published.3mf" : "3mf");
10577 dlg_title = title.empty() ? _L("Save file as") : title;
10578 break;
10579 }
10580 case FT_OBJ:
10581 {
10582 output_file.replace_extension("obj");
10583 dlg_title = _L("Export OBJ file:");
10584 break;
10585 }
10586 default: break;
10587 }
10588
10589 std::string out_dir = (boost::filesystem::path(output_file).parent_path()).string();
10590
10591 wxFileDialog dlg(q, dlg_title,
10592 is_shapes_dir(out_dir) ? from_u8(wxGetApp().app_config->get_last_dir()) : from_path(output_file.parent_path()), from_path(output_file.filename()),
10593 wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxPD_APP_MODAL);
10594
10595 int result = dlg.ShowModal();
10596 if (result == wxID_CANCEL)
10597 return "<cancel>";
10598 if (result != wxID_OK)
10599 return wxEmptyString;
10600
10601 wxString out_path = dlg.GetPath();
10602 fs::path path(into_path(out_path));
10603#ifdef __WXMSW__
10604 if (boost::iequals(path.extension().string(), output_file.extension().string()) == false) {
10605 out_path += output_file.extension().string();
10606 boost::system::error_code ec;
10607 if (boost::filesystem::exists(into_u8(out_path), ec)) {
10608 auto result = MessageBox(q->GetHandle(),
10609 wxString::Format(_L("The file %s already exists.\nDo you want to replace it\?"), out_path),
10610 _L("Confirm Save As"),
10611 MB_YESNO | MB_ICONWARNING);
10612 if (result != IDYES)
10613 return wxEmptyString;
10614 }
10615 }
10616#endif
10617 wxGetApp().app_config->update_last_output_dir(path.parent_path().string());
10618
10619 return out_path;
10620}
@ FT_MODEL
Definition GUI_App.hpp:127
@ FT_DRC
Definition GUI_App.hpp:139
@ FT_3MF
Definition GUI_App.hpp:124
@ FT_STL
Definition GUI_App.hpp:121
@ FT_AMF
Definition GUI_App.hpp:123
@ FT_OBJ
Definition GUI_App.hpp:122
@ FT_GCODE
Definition GUI_App.hpp:126
wxString file_wildcards(FileType file_type, const std::string &custom_extension)
Definition GUI_App.cpp:695
std::string into_u8(const wxString &str)
Definition GUI.cpp:549
boost::filesystem::path into_path(const wxString &str)
Definition GUI.cpp:564
bool is_shapes_dir(const std::string &dir)
Definition utils.cpp:1295
fs::path get_export_file_path(GUI::FileType file_type)
Definition Plater.cpp:10483

References _L, Slic3r::GUI::file_wildcards(), Slic3r::GUI::from_path(), Slic3r::GUI::from_u8(), Slic3r::GUI::FT_3MF, Slic3r::GUI::FT_AMF, Slic3r::GUI::FT_DRC, Slic3r::GUI::FT_GCODE, Slic3r::GUI::FT_MODEL, Slic3r::GUI::FT_OBJ, Slic3r::GUI::FT_STL, get_export_file_path(), Slic3r::GUI::into_path(), Slic3r::GUI::into_u8(), Slic3r::is_shapes_dir(), and q.

Here is the call graph for this function:

◆ get_export_file_path()

fs::path Slic3r::GUI::Plater::priv::get_export_file_path ( GUI::FileType file_type)
10484{
10485 // Update printbility state of each of the ModelInstances.
10487
10488 const Selection& selection = get_selection();
10489 int obj_idx = selection.get_object_idx();
10490
10491 fs::path output_file;
10492 if (file_type == FT_3MF)
10493 // for 3mf take the path from the project filename, if any
10494 output_file = into_path(get_project_filename(".3mf"));
10495 else if (file_type == FT_STL) {
10496 if (obj_idx > 0 && obj_idx < this->model.objects.size() && selection.is_single_full_object()) {
10497 output_file = this->model.objects[obj_idx]->get_export_filename();
10498 }
10499 else {
10500 output_file = into_path(get_project_name());
10501 }
10502 }
10503 //bbs name the project using the part name
10504 if (output_file.empty()) {
10505 if (get_project_name() != _L("Untitled")) {
10506 output_file = into_path(get_project_name() + ".3mf");
10507 }
10508 }
10509
10510 if (output_file.empty())
10511 {
10512 // first try to get the file name from the current selection
10513 if ((0 <= obj_idx) && (obj_idx < (int)this->model.objects.size()))
10514 output_file = this->model.objects[obj_idx]->get_export_filename();
10515
10516 if (output_file.empty())
10517 // Find the file name of the first printable object.
10518 output_file = this->model.propose_export_file_name_and_path();
10519
10520 if (output_file.empty() && !model.objects.empty())
10521 // Find the file name of the first object.
10522 output_file = this->model.objects[0]->get_export_filename();
10523
10524 if (output_file.empty())
10525 // Use _L("Untitled") name
10526 output_file = into_path(_L("Untitled"));
10527 }
10528 return output_file;
10529}
wxString get_project_filename(const wxString &extension=wxEmptyString) const
Definition Plater.cpp:14381
void update_print_volume_state()
Definition Plater.cpp:11230
wxString get_project_name()
Definition Plater.cpp:14430

References _L, Slic3r::GUI::FT_3MF, Slic3r::GUI::FT_STL, Slic3r::GUI::Selection::get_object_idx(), Slic3r::GUI::Plater::get_project_filename(), Slic3r::GUI::Plater::get_project_name(), Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::into_path(), Slic3r::GUI::Selection::is_single_full_object(), model, and update_print_volume_state().

Referenced by get_export_file(), and save_project_if_dirty().

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

◆ get_export_gcode_filename()

wxString Slic3r::GUI::Plater::priv::get_export_gcode_filename ( const wxString & extension = wxEmptyString,
bool only_filename = false,
bool export_all = false ) const
14392{
14393 std::string plate_index_str;
14394 auto plate_name = partplate_list.get_curr_plate()->get_plate_name();
14395 if (!plate_name.empty())
14396 plate_index_str = (boost::format("_%1%") % plate_name).str();
14397 else if (partplate_list.get_plate_count() > 1)
14398 plate_index_str = (boost::format("_plate_%1%") % std::to_string(partplate_list.get_curr_plate_index() + 1)).str();
14399
14400 if (!m_project_folder.empty()) {
14401 if (!only_filename) {
14402 if (export_all) {
14403 auto full_filename = m_project_folder / std::string((m_project_name + extension).mb_str(wxConvUTF8));
14404 return from_path(full_filename);
14405 } else {
14406 auto full_filename = m_project_folder / std::string((m_project_name + from_u8(plate_index_str) + extension).mb_str(wxConvUTF8));
14407 return from_path(full_filename);
14408 }
14409 } else {
14410 if (export_all)
14411 return m_project_name + extension;
14412 else
14413 return m_project_name + from_u8(plate_index_str) + extension;
14414 }
14415 } else {
14416 if (only_filename) {
14417 if(!model.objects.empty() && m_project_name == _L("Untitled"))
14418 return wxString(fs::path(model.objects.front()->name).replace_extension().c_str()) + from_u8(plate_index_str) + extension;
14419
14420 if (export_all)
14421 return m_project_name + extension;
14422 else
14423 return m_project_name + from_u8(plate_index_str) + extension;
14424 }
14425 else
14426 return "";
14427 }
14428}
boost::filesystem::path m_project_folder
Definition Plater.cpp:7768
wxString m_project_name
Definition Plater.cpp:7771

References _L, Slic3r::GUI::from_path(), Slic3r::GUI::from_u8(), m_project_folder, m_project_name, model, and partplate_list.

Here is the call graph for this function:

◆ get_extruder_filament_info()

std::vector< std::vector< DynamicPrintConfig > > Slic3r::GUI::Plater::priv::get_extruder_filament_info ( )
11213{
11214 std::vector<std::vector<DynamicPrintConfig>> filament_infos;
11215 DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
11216 if (!dev)
11217 return filament_infos;
11218
11219 MachineObject *obj_ = dev->get_selected_machine();
11220 if (obj_ == nullptr)
11221 return filament_infos;
11222
11223 if (!obj_->is_multi_extruders())
11224 return filament_infos;
11225
11226 filament_infos = wxGetApp().preset_bundle->get_extruder_filament_info();
11227 return filament_infos;
11228}

References Slic3r::DeviceManager::get_selected_machine(), and Slic3r::MachineObject::is_multi_extruders().

Referenced by update_background_process().

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

◆ get_machine_sync_status()

bool Slic3r::GUI::Plater::priv::get_machine_sync_status ( )
14786{
14787 Slic3r::DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
14788 if (!dev)
14789 return false;
14790
14791 MachineObject* obj = dev->get_selected_machine();
14792 if (!obj)
14793 return false;
14794
14795 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
14796 return preset_bundle && preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle) == obj->get_show_printer_type();
14797}
std::string get_show_printer_type() const
Definition DeviceManager.cpp:582

References Slic3r::PresetCollection::get_edited_preset(), Slic3r::Preset::get_printer_type(), Slic3r::DeviceManager::get_selected_machine(), Slic3r::MachineObject::get_show_printer_type(), and Slic3r::PresetBundle::printers.

Here is the call graph for this function:

◆ get_project_filename()

wxString Slic3r::GUI::Plater::priv::get_project_filename ( const wxString & extension = wxEmptyString) const
14382{
14383 if (m_project_name.empty())
14384 return "";
14385 else {
14386 auto full_filename = m_project_folder / std::string((m_project_name + extension).mb_str(wxConvUTF8));
14387 return m_project_folder.empty() ? "" : from_path(full_filename);
14388 }
14389}

References Slic3r::GUI::from_path(), m_project_folder, and m_project_name.

Referenced by save_project_if_dirty().

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

◆ get_project_name()

wxString Slic3r::GUI::Plater::priv::get_project_name ( )
14431{
14432 return m_project_name;
14433}

References m_project_name.

◆ get_selected_object_idx()

int Slic3r::GUI::Plater::priv::get_selected_object_idx ( ) const
10638{
10639 int idx = get_selection().get_object_idx();
10640 return ((0 <= idx) && (idx < 1000)) ? idx : -1;
10641}
int get_object_idx() const
Definition Selection.cpp:962

References Slic3r::GUI::Selection::get_object_idx(), and Slic3r::GUI::Plater::get_selection().

Here is the call graph for this function:

◆ get_selected_volume_idx()

int Slic3r::GUI::Plater::priv::get_selected_volume_idx ( ) const
10644{
10645 auto& selection = get_selection();
10646 int idx = selection.get_object_idx();
10647 if ((0 > idx) || (idx > 1000))
10648 return-1;
10649 const GLVolume* v = selection.get_first_volume();
10650 if (model.objects[idx]->volumes.size() > 1)
10651 return v->volume_idx();
10652 return -1;
10653}

References Slic3r::GUI::Plater::get_selection(), model, and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ get_selection() [1/2]

Selection & Slic3r::GUI::Plater::priv::get_selection ( )
10628{
10629 return view3D->get_canvas3d()->get_selection();
10630}

References view3D.

◆ get_selection() [2/2]

const Selection & Slic3r::GUI::Plater::priv::get_selection ( ) const
10623{
10624 return view3D->get_canvas3d()->get_selection();
10625}

References view3D.

Referenced by replace_with_stl().

Here is the caller graph for this function:

◆ get_sidebar_docking_state()

Sidebar::DockingState Slic3r::GUI::Plater::priv::get_sidebar_docking_state ( )
8753 {
8754 if (!sidebar_layout.is_enabled) {
8755 return Sidebar::None;
8756 }
8757
8758 const auto& sidebar = m_aui_mgr.GetPane(this->sidebar);
8759 if(sidebar.IsFloating()) {
8760 return Sidebar::None;
8761 }
8762
8763 return sidebar.dock_direction == wxAUI_DOCK_RIGHT ? Sidebar::Right : Sidebar::Left;
8764}
@ Right
Definition Plater.hpp:175
@ None
Definition Plater.hpp:175
@ Left
Definition Plater.hpp:175

References Slic3r::GUI::Sidebar::Left, m_aui_mgr, Slic3r::GUI::Sidebar::None, Slic3r::GUI::Sidebar::Right, sidebar, and sidebar_layout.

◆ handle_textured_mesh_import()

void Slic3r::GUI::Plater::priv::handle_textured_mesh_import ( Slic3r::Model & model,
const std::vector< size_t > & obj_idxs,
std::function< bool()> cancel_callback = {} )
16038{
16039 TextureImportResult result;
16040 if (!run_textured_mesh_import_dialog(loaded_model, result, std::move(cancel_callback)))
16041 return;
16042 if (!result.painted.face_colors.empty())
16043 apply_textured_mesh_import_result(loaded_model, obj_idxs, result);
16044}
void apply_textured_mesh_import_result(Slic3r::Model &loaded_model, const std::vector< size_t > &obj_idxs, const TextureImportResult &result, LoadProgressCallback progress_callback={}, bool update_scene=true)
Definition Plater.cpp:15840
bool run_textured_mesh_import_dialog(Slic3r::Model &loaded_model, TextureImportResult &result, std::function< bool()> cancel_callback={}, std::function< bool(int)> progress_callback={})
Definition Plater.cpp:15728

References apply_textured_mesh_import_result(), Slic3r::PaintedMesh::face_colors, Slic3r::GUI::Plater::priv::TextureImportResult::painted, and run_textured_mesh_import_dialog().

Here is the call graph for this function:

◆ has_assemble_view()

bool Slic3r::GUI::Plater::priv::has_assemble_view ( ) const
14864{
14865 for (auto object: model.objects)
14866 {
14867 for (auto instance : object->instances)
14868 if (instance->is_assemble_initialized())
14869 return true;
14870
14871 int part_cnt = 0;
14872 for (auto volume : object->volumes) {
14873 if (volume->is_model_part())
14874 part_cnt++;
14875 }
14876
14877 if (part_cnt > 1)
14878 return true;
14879 }
14880 return false;
14881}

References model.

◆ hide_select_machine_dlg()

void Slic3r::GUI::Plater::priv::hide_select_machine_dlg ( )
inline
7409 {
7411 m_select_machine_dlg->EndModal(wxID_OK);
7412 }

References m_select_machine_dlg.

◆ hide_send_to_printer_dlg()

void Slic3r::GUI::Plater::priv::hide_send_to_printer_dlg ( )
inline
7420{ m_send_to_sdcard_dlg->EndModal(wxID_OK); }
SendToPrinterDialog * m_send_to_sdcard_dlg
Definition Plater.cpp:7182

References m_send_to_sdcard_dlg.

◆ init_collapse_toolbar()

bool Slic3r::GUI::Plater::priv::init_collapse_toolbar ( )
14800{
14801 if (wxGetApp().is_gcode_viewer())
14802 return true;
14803
14804 if (collapse_toolbar.get_items_count() > 0)
14805 // already initialized
14806 return true;
14807
14808 BackgroundTexture::Metadata background_data;
14809 background_data.filename = m_is_dark ? "toolbar_background_dark.png" : "toolbar_background.png";
14810 background_data.left = 16;
14811 background_data.top = 16;
14812 background_data.right = 16;
14813 background_data.bottom = 16;
14814
14815 if (!collapse_toolbar.init(background_data))
14816 return false;
14817
14819 wxGetApp().plater()->collapse_sidebar(!wxGetApp().plater()->is_sidebar_collapsed());
14820 }))
14821 return false;
14822
14823 // Now "collapse" sidebar to current state. This is done so the tooltip
14824 // is updated before the toolbar is first used.
14825 wxGetApp().plater()->collapse_sidebar(wxGetApp().plater()->is_sidebar_collapsed());
14826 return true;
14827}
bool is_sidebar_collapsed() const
Definition Plater.cpp:19150
static Plater * plater()
Definition GUI_Factories.cpp:400
bool setup_collapse_toolbar(GLToolbar &toolbar, std::function< void()> toggle)
Definition GLToolbar.cpp:1679

References Slic3r::GUI::BackgroundTexture::Metadata::bottom, collapse_toolbar, Slic3r::GUI::BackgroundTexture::Metadata::filename, Slic3r::GUI::Plater::is_sidebar_collapsed(), Slic3r::GUI::BackgroundTexture::Metadata::left, m_is_dark, Slic3r::GUI::plater(), Slic3r::GUI::BackgroundTexture::Metadata::right, Slic3r::GUI::setup_collapse_toolbar(), and Slic3r::GUI::BackgroundTexture::Metadata::top.

Here is the call graph for this function:

◆ init_notification_manager()

void Slic3r::GUI::Plater::priv::init_notification_manager ( )
14507{
14509 return;
14510 notification_manager->init();
14511
14512 auto cancel_callback = [this]() {
14513 if (this->background_process.idle())
14514 return false;
14515 this->background_process.stop();
14516 return true;
14517 };
14518 notification_manager->init_slicing_progress_notification(cancel_callback);
14520 notification_manager->init_progress_indicator();
14521}
@ ptFFF
Definition Config.hpp:231

References Slic3r::BackgroundSlicingProcess::idle(), notification_manager, printer_technology, Slic3r::ptFFF, and Slic3r::BackgroundSlicingProcess::stop().

Here is the call graph for this function:

◆ inside_snapshot_capture()

bool Slic3r::GUI::Plater::priv::inside_snapshot_capture ( )
inline
7743{ return m_prevent_snapshots != 0; }

References m_prevent_snapshots.

◆ install_network_plugin()

void Slic3r::GUI::Plater::priv::install_network_plugin ( wxCommandEvent & event)
14091{
14092 wxGetApp().ShowDownNetPluginDlg();
14093 return;
14094}

◆ is_assemble_view_show()

bool Slic3r::GUI::Plater::priv::is_assemble_view_show ( ) const
inline
7361{ return current_panel == assemble_view; }

References assemble_view, and current_panel.

◆ is_presets_dirty()

bool Slic3r::GUI::Plater::priv::is_presets_dirty ( ) const
inline
7313{ return dirty_state.is_presets_dirty(); }

References dirty_state.

◆ is_preview_loaded()

bool Slic3r::GUI::Plater::priv::is_preview_loaded ( ) const
inline
7359{ return preview->is_loaded(); }

References preview.

◆ is_preview_shown()

bool Slic3r::GUI::Plater::priv::is_preview_shown ( ) const
inline
7358{ return current_panel == preview; }

References current_panel, and preview.

◆ is_project_dirty()

bool Slic3r::GUI::Plater::priv::is_project_dirty ( ) const
inline
7312{ return dirty_state.is_dirty(); }

References dirty_state.

◆ is_view3D_layers_editing_enabled()

bool Slic3r::GUI::Plater::priv::is_view3D_layers_editing_enabled ( ) const
inline
7395{ return (current_panel == view3D) && view3D->get_canvas3d()->is_layers_editing_enabled(); }

References current_panel, and view3D.

◆ is_view3D_overhang_shown()

bool Slic3r::GUI::Plater::priv::is_view3D_overhang_shown ( ) const
inline
7372{ return (current_panel == view3D) && view3D->get_canvas3d()->is_overhang_shown(); }

References current_panel, and view3D.

◆ is_view3D_shown()

bool Slic3r::GUI::Plater::priv::is_view3D_shown ( ) const
inline
7360{ return current_panel == view3D; }

References current_panel, and view3D.

◆ layers_height_allowed()

bool Slic3r::GUI::Plater::priv::layers_height_allowed ( ) const
private
15135{
15137 return false;
15138
15139 int obj_idx = get_selected_object_idx();
15140 return 0 <= obj_idx && obj_idx < (int)model.objects.size() && model.objects[obj_idx]->max_z() > SINKING_Z_THRESHOLD && view3D->is_layers_editing_allowed();
15141}
static const float SINKING_Z_THRESHOLD
Definition Model.hpp:1967

References Slic3r::GUI::Plater::get_selected_object_idx(), model, printer_technology, Slic3r::ptFFF, Slic3r::SINKING_Z_THRESHOLD, and view3D.

Referenced by can_layers_editing(), and selection_changed().

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

◆ leave_gizmos_stack()

bool Slic3r::GUI::Plater::priv::leave_gizmos_stack ( )
15239{
15240 bool changed = false;
15243 assert(! m_undo_redo_stack_active->empty());
15244 changed = m_undo_redo_stack_gizmos.has_undo_snapshot();
15245 m_undo_redo_stack_active->clear();
15247 }
15248 return changed;
15249}

References m_undo_redo_stack_active, m_undo_redo_stack_gizmos, and m_undo_redo_stack_main.

◆ load_auxiliary_files()

void Slic3r::GUI::Plater::priv::load_auxiliary_files ( )
10478{
10479 std::string auxiliary_path = encode_path(q->model().get_auxiliary_file_temp_path().c_str());
10480 //wxGetApp().mainframe->m_project->Reload(auxiliary_path);
10481}
std::string encode_path(const char *src)
Definition utils.cpp:1382

References Slic3r::encode_path(), and q.

Referenced by load_files().

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

◆ load_files()

std::vector< size_t > Slic3r::GUI::Plater::priv::load_files ( const std::vector< fs::path > & input_files,
LoadStrategy strategy,
bool ask_multi = false,
bool * published_out = nullptr,
bool * config_loaded_out = nullptr )
8949{
8950 if (config_loaded_out != nullptr)
8951 *config_loaded_out = false;
8952
8953 std::vector<size_t> empty_result;
8954 bool dlg_cont = true;
8955 bool is_user_cancel = false;
8956 bool translate_old = false;
8957 int current_width = 0, current_depth = 0, project_filament_count = 1;
8958 double current_height = 0;
8959
8960 if (input_files.empty())
8961 return std::vector<size_t>();
8962
8963 if (!input_files.empty())
8964 q->m_3mf_path = input_files[0].string();
8965
8966 // SoftFever: ugly fix so we can exist pa calib mode
8967 background_process.fff_print()->calib_mode() = CalibMode::Calib_None;
8968
8969
8970 // BBS
8971 int filaments_cnt = config->opt<ConfigOptionStrings>("filament_colour")->values.size();
8972 bool one_by_one = input_files.size() == 1 || printer_technology == ptSLA/* || filaments_cnt <= 1*/;
8973 if (! one_by_one) {
8974 for (const auto &path : input_files) {
8975 if (std::regex_match(path.string(), pattern_bundle)) {
8976 one_by_one = true;
8977 break;
8978 }
8979 }
8980 }
8981
8982 bool load_model = strategy & LoadStrategy::LoadModel;
8983 bool load_config = strategy & LoadStrategy::LoadConfig;
8984 bool imperial_units = strategy & LoadStrategy::ImperialUnits;
8985 bool silence = strategy & LoadStrategy::Silence;
8986
8987 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": load_model %1%, load_config %2%, input_files size %3%")%load_model %load_config %input_files.size();
8988
8989 const auto loading = _L("Loading") + dots;
8990 ProgressDialog dlg(loading, "", 100, find_toplevel_parent(q), wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_APP_MODAL);
8991 wxBusyCursor busy;
8992
8993 auto *new_model = (!load_model || one_by_one) ? nullptr : new Slic3r::Model();
8994 std::vector<size_t> obj_idxs;
8995
8996 std::string designer_model_id;
8997 std::string designer_country_code;
8998
8999 int answer_convert_from_meters = wxOK_DEFAULT;
9000 int answer_convert_from_imperial_units = wxOK_DEFAULT;
9001 int tolal_model_count = 0;
9002 // Whether one of the files being loaded here carried a CAD recipe. A statement about these
9003 // files, not about the plater — q->model() may still hold the previous project's recipe.
9004 bool loaded_cad_recipe = false;
9005
9006 int progress_percent = 0;
9007 int total_files = input_files.size();
9008 const int stage_percent[IMPORT_STAGE_MAX+1] = {
9009 5, // IMPORT_STAGE_RESTORE
9010 10, // IMPORT_STAGE_OPEN
9011 30, // IMPORT_STAGE_READ_FILES
9012 50, // IMPORT_STAGE_EXTRACT
9013 60, // IMPORT_STAGE_LOADING_OBJECTS
9014 70, // IMPORT_STAGE_LOADING_PLATES
9015 80, // IMPORT_STAGE_FINISH
9016 85, // IMPORT_STAGE_ADD_INSTANCE
9017 90, // IMPORT_STAGE_UPDATE_GCODE
9018 92, // IMPORT_STAGE_CHECK_MODE_GCODE
9019 95, // UPDATE_GCODE_RESULT
9020 98, // IMPORT_LOAD_CONFIG
9021 99, // IMPORT_LOAD_MODEL_OBJECTS
9022 100
9023 };
9024 const int step_percent[LOAD_STEP_STAGE_NUM+1] = {
9025 5, // LOAD_STEP_STAGE_READ_FILE
9026 30, // LOAD_STEP_STAGE_GET_SOLID
9027 60, // LOAD_STEP_STAGE_GET_MESH
9028 100
9029 };
9030
9031 const float INPUT_FILES_RATIO = 0.7;
9032 const float INIT_MODEL_RATIO = 0.75;
9033 const float CENTER_AROUND_ORIGIN_RATIO = 0.8;
9034
9035 const float LOAD_MODEL_RATIO = 0.9;
9036
9037 for (size_t i = 0; i < input_files.size(); ++i) {
9038
9039#ifdef _WIN32
9040 auto path = input_files[i];
9041 // On Windows, we swap slashes to back slashes, see GH #6803 as read_from_file() does not understand slashes on Windows thus it assignes full path to names of loaded objects.
9042 path.make_preferred();
9043#else // _WIN32
9044 // Don't make a copy on Posix. Slash is a path separator, back slashes are not accepted as a substitute.
9045 const auto &path = input_files[i];
9046#endif // _WIN32
9047 const auto filename = path.filename();
9048 int progress_percent = static_cast<int>(100.0f * static_cast<float>(i) / static_cast<float>(input_files.size()));
9049 const auto real_filename = (strategy & LoadStrategy::Restore) ? input_files[++i].filename() : filename;
9050 const auto dlg_info = _L("Loading file") + ": " + from_path(real_filename);
9051 BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << boost::format(": load file %1%") % filename;
9052 dlg_cont = dlg.Update(progress_percent, dlg_info);
9053 if (!dlg_cont) return empty_result;
9054
9055 const bool type_3mf = std::regex_match(path.string(), pattern_3mf);
9056 // const bool type_zip_amf = !type_3mf && std::regex_match(path.string(), pattern_zip_amf);
9057 const bool type_any_amf = !type_3mf && std::regex_match(path.string(), pattern_any_amf);
9058 // const bool type_prusa = std::regex_match(path.string(), pattern_prusa);
9059
9060 Slic3r::Model model;
9061 // BBS: add auxiliary files related logic
9062 bool load_aux = strategy & LoadStrategy::LoadAuxiliary, load_old_project = false;
9063 if (load_model && load_config && type_3mf) {
9064 load_aux = true;
9065 strategy = strategy | LoadStrategy::LoadAuxiliary;
9066 }
9067 if (load_config) strategy = strategy | LoadStrategy::CheckVersion;
9068 bool is_project_file = false;
9069 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": is_project_file %1%, type_3mf %2%") % is_project_file % type_3mf;
9070 try {
9071 if (type_3mf) {
9072 DynamicPrintConfig config;
9073 Semver file_version;
9074 En3mfType en_3mf_file_type = En3mfType::From_BBS;
9075 // BBS: a "published" 3MF carries a flag plus the author-selected setting keys;
9076 // on load keep the user's current presets and overlay only those keys. Declared
9077 // here (outside the config block below) so it stays alive for the embedded-preset
9078 // gate, the metadata strip and the preset overlay after the block closes.
9079 PublishedConfig published_config;
9080 {
9081 DynamicPrintConfig config_loaded;
9082
9083 // BBS: add part plate related logic
9084 PlateDataPtrs plate_data;
9085 ConfigSubstitutionContext config_substitutions{ForwardCompatibilitySubstitutionRule::Enable};
9086 std::vector<Preset *> project_presets;
9087 // BBS: backup & restore
9088 q->skip_thumbnail_invalid = true;
9089 model = Slic3r::Model::read_from_archive(path.string(), &config_loaded, &config_substitutions, en_3mf_file_type, strategy, &plate_data, &project_presets,
9090 &file_version,
9091 [&dlg, real_filename, &progress_percent, stage_percent, INPUT_FILES_RATIO, total_files, i,
9092 &is_user_cancel](int import_stage, int current, int total, bool &cancel) {
9093 bool cont = true;
9094 float percent_float = (100.0f * (float)i / (float)total_files) + INPUT_FILES_RATIO * ((float)stage_percent[import_stage] + (float)current * (float)(stage_percent[import_stage + 1] - stage_percent[import_stage]) /(float) total) / (float)total_files;
9095 BOOST_LOG_TRIVIAL(trace) << "load_3mf_file: percent(float)=" << percent_float << ", stage = " << import_stage << ", curr = " << current << ", total = " << total;
9096 progress_percent = (int)percent_float;
9097 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
9098 cont = dlg.Update(progress_percent, msg);
9099 cancel = !cont;
9100 if (cancel)
9101 is_user_cancel = cancel;
9102 });
9103 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
9104 << boost::format(", plate_data.size %1%, project_preset.size %2%, is_bbs_or_orca_3mf %3%, file_version %4% \n") % plate_data.size() %
9105 project_presets.size() % (en_3mf_file_type == En3mfType::From_BBS || en_3mf_file_type == En3mfType::From_Orca) % file_version.to_string();
9106
9107 // BBS: a "published" 3MF carries a flag plus the author-selected setting keys;
9108 // on load keep the user's current presets and overlay only those keys. Parsed
9109 // here (before the version/fallback chain below) because a published file has
9110 // no project_settings.config: its values travel in the published_config
9111 // metadata payload, which must fill config_loaded before the chain decides
9112 // whether to import geometry only.
9113 if (model.model_info != nullptr) {
9114 auto published_it = model.model_info->metadata_items.find(ORCA_PUBLISHED_TAG);
9115 if (published_it != model.model_info->metadata_items.end() && is_published_3mf_flag(published_it->second)) {
9116 published_config.published = true;
9117 auto keys_it = model.model_info->metadata_items.find(ORCA_PUBLISHED_KEYS_TAG);
9118 if (keys_it != model.model_info->metadata_items.end()) {
9119 try {
9120 auto j = nlohmann::json::parse(keys_it->second);
9121 if (j.is_array())
9122 for (const auto& k : j)
9123 if (k.is_string())
9124 published_config.published_keys.emplace_back(k.get<std::string>());
9125 } catch (...) {
9126 // Ignore malformed published_keys; the project still loads normally.
9127 }
9128 }
9129
9130 auto material_keys_it = model.model_info->metadata_items.find(ORCA_PUBLISHED_MATERIAL_TAG);
9131 if (material_keys_it != model.model_info->metadata_items.end()) {
9132 try {
9133 auto jm = nlohmann::json::parse(material_keys_it->second);
9134 if (jm.is_array())
9135 for (const auto& m : jm) {
9136 try {
9137 // Malformed entries are isolated so one bad item
9138 // cannot discard valid entries that follow it.
9139 if (!m.is_object())
9140 continue;
9141 PublishedMaterialEntry entry;
9142 const auto mat_it = m.find("material");
9143 if (mat_it != m.end() && mat_it->is_object()) {
9144 const auto& mat = *mat_it;
9145 if (mat.contains("filament_type") && mat["filament_type"].is_string())
9146 entry.filament_type = mat["filament_type"].get<std::string>();
9147 if (mat.contains("filament_vendor") && mat["filament_vendor"].is_string())
9148 entry.filament_vendor = mat["filament_vendor"].get<std::string>();
9149 if (mat.contains("filament_id") && mat["filament_id"].is_string())
9150 entry.filament_id = mat["filament_id"].get<std::string>();
9151 if (mat.contains("setting_id") && mat["setting_id"].is_string())
9152 entry.setting_id = mat["setting_id"].get<std::string>();
9153 if (mat.contains("name") && mat["name"].is_string())
9154 entry.preset_name = mat["name"].get<std::string>();
9155 }
9156 if (m.contains("slot") && m["slot"].is_number_integer())
9157 entry.slot = m["slot"].get<int>();
9158 const auto entry_keys_it = m.find("keys");
9159 if (entry_keys_it != m.end() && entry_keys_it->is_array())
9160 for (const auto& k : *entry_keys_it)
9161 if (k.is_string())
9162 entry.keys.emplace_back(k.get<std::string>());
9163 // Fields always written by the current exporter.
9164 if (m.contains("full") && m["full"].is_boolean())
9165 entry.full = m["full"].get<bool>();
9166 const auto entry_full_keys_it = m.find("full_keys");
9167 if (entry_full_keys_it != m.end() && entry_full_keys_it->is_array())
9168 for (const auto& k : *entry_full_keys_it)
9169 if (k.is_string())
9170 entry.full_keys.emplace_back(k.get<std::string>());
9171 if (m.contains("publish_type") && m["publish_type"].is_boolean())
9172 entry.publish_type = m["publish_type"].get<bool>();
9173 if (m.contains("type") && m["type"].is_string())
9174 entry.publish_type_value = m["type"].get<std::string>();
9175 if (m.contains("publish_color") && m["publish_color"].is_boolean())
9176 entry.publish_color = m["publish_color"].get<bool>();
9177 if (m.contains("color") && m["color"].is_string())
9178 entry.color = m["color"].get<std::string>();
9179 published_config.material_keys.emplace_back(std::move(entry));
9180 } catch (const nlohmann::json::exception&) {
9181 // Ignore only this malformed material entry.
9182 }
9183 }
9184 } catch (const nlohmann::json::exception&) {
9185 // Ignore malformed published_material_keys; the project still loads normally.
9186 }
9187 }
9188
9189 // Rebuild the published values from the metadata payload: a published
9190 // file carries no project_settings.config, so config_loaded is filled
9191 // from here; a missing or malformed payload leaves it empty and the
9192 // fallback chain below imports the geometry only.
9193 auto payload_it = model.model_info->metadata_items.find(ORCA_PUBLISHED_CONFIG_TAG);
9194 if (payload_it != model.model_info->metadata_items.end()) {
9195 try {
9196 ConfigSubstitutions payload_substitutions =
9197 config_loaded.load_from_ini_string(payload_it->second, ForwardCompatibilitySubstitutionRule::Enable);
9198 config_substitutions.substitutions.insert(config_substitutions.substitutions.end(),
9199 std::make_move_iterator(payload_substitutions.begin()),
9200 std::make_move_iterator(payload_substitutions.end()));
9201 } catch (...) {
9202 // Ignore malformed published_config; the project still loads normally.
9203 }
9204 }
9205 }
9206 }
9207
9208 // 1. add extruder for prusa model if the number of existing extruders is not enough
9209 // 2. add extruder for BBS or Other model if only import geometry
9210 if (en_3mf_file_type == En3mfType::From_Prusa || (load_model && !load_config)) {
9211 std::set<int> extruderIds;
9212 for (ModelObject *o : model.objects) {
9213 if (o->config.option("extruder")) extruderIds.insert(o->config.extruder());
9214 for (auto volume : o->volumes) {
9215 if (volume->config.option("extruder")) extruderIds.insert(volume->config.extruder());
9216 for (int extruder : volume->get_extruders()) { extruderIds.insert(extruder); }
9217 }
9218 }
9219 int size = extruderIds.size() == 0 ? 0 : *(extruderIds.rbegin());
9220
9221 int filament_size = sidebar->combos_filament().size();
9222 while (filament_size < MAXIMUM_EXTRUDER_NUMBER && filament_size < size) {
9223 int filament_count = filament_size + 1;
9224 wxColour new_col = Plater::get_next_color_for_filament();
9225 std::string new_color = new_col.GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
9226 wxGetApp().preset_bundle->set_num_filaments(filament_count, new_color);
9227 wxGetApp().plater()->on_filament_count_change(filament_count);
9228 ++filament_size;
9229 }
9230 wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
9231 }
9232
9233 std::string import_project_action = wxGetApp().app_config->get("import_project_action");
9234 LoadType load_type;
9235 if (import_project_action.empty())
9236 load_type = LoadType::Unknown;
9237 else
9238 load_type = static_cast<LoadType>(std::stoi(import_project_action));
9239
9240 // BBS: version check
9241 Semver app_version = *(Semver::parse(SoftFever_VERSION));
9242 const wxString load_3mf_title = _L("Load 3MF");
9243 const wxString newer_3mf_title = _L("Newer 3MF version");
9244 const wxString msg_unsupported_geometry = _L("The 3MF is not supported by OrcaSlicer, loading geometry data only.");
9245 const wxString msg_old_orca_geometry = _L("The 3MF file was generated by an old OrcaSlicer version, loading geometry data only.");
9246 const wxString msg_older_geometry = _L("The 3MF file was generated by an older version, loading geometry data only.");
9247 const wxString msg_bambu_geometry = _L("The 3MF file was generated by BambuStudio, loading geometry data only.");
9248 auto log_and_show_3mf_info = [&](const wxString& text, const wxString& title) {
9249 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
9250 << " "
9251 << boost::format("3MF import message [%1%]: %2% | file: %3%") % into_u8(title) % into_u8(text) % path.string();
9252 show_info(q, text, title);
9253 };
9254 // Untagged files up to 2.3.2 may also come from OrcaSlicer, which only started tagging its 3MFs after it.
9255 const bool is_bambu_studio_project = en_3mf_file_type == En3mfType::From_BBS && file_version > Semver(2, 3, 2);
9256 if (en_3mf_file_type == En3mfType::From_Prusa) {
9257 // do not reset the model config
9258 load_config = false;
9259 if (load_type != LoadType::LoadGeometry)
9260 log_and_show_3mf_info(msg_unsupported_geometry, load_3mf_title);
9261 }
9262 else if (en_3mf_file_type == En3mfType::From_Orca) {
9263 // OrcaSlicer file (has OrcaSlicer tag) - compare file_version with SoftFever_VERSION
9264 // Migration fix for OrcaSlicer 2.3.1-alpha sparse infill rotation template
9265 if (load_config && (file_version < app_version) && file_version == Semver("2.3.1-alpha")) {
9266 if (!config_loaded.opt_string("sparse_infill_rotate_template").empty()) {
9267 const auto _sparse_infill_pattern =
9268 config_loaded.option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value;
9269 bool is_safe_to_rotate = _sparse_infill_pattern == ipRectilinear || _sparse_infill_pattern == ipLine ||
9270 _sparse_infill_pattern == ipZigZag || _sparse_infill_pattern == ipCrossZag ||
9271 _sparse_infill_pattern == ipLockedZag;
9272 if (!is_safe_to_rotate) {
9273 wxString msg_text = _(
9274 L("This project was created with an OrcaSlicer 2.3.1-alpha and uses "
9275 "infill rotation template settings that may not work properly with your current infill pattern. "
9276 "This could result in weak support or print quality issues."));
9277 msg_text += "\n\n" +
9278 _(L("Would you like OrcaSlicer to automatically fix this by clearing the rotation template settings?"));
9279 MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO);
9280 dialog.SetButtonLabel(wxID_YES, _L("Yes"));
9281 dialog.SetButtonLabel(wxID_NO, _L("No"));
9282 if (dialog.ShowModal() == wxID_YES) {
9283 config_loaded.opt_string("sparse_infill_rotate_template") = "";
9284 }
9285 }
9286 }
9287 } else if (load_config && (file_version > app_version)) {
9288 if (config_substitutions.unrecogized_keys.size() > 0) {
9289 wxString text = wxString::Format(_L("The 3MF file version %s is newer than %s's version %s, found the following unrecognized keys:"),
9290 file_version.to_string_sf(), std::string(SLIC3R_APP_FULL_NAME), app_version.to_string_sf());
9291 text += "\n" + from_u8(boost::algorithm::join(config_substitutions.unrecogized_keys, ", ")) + "\n\n";
9292 text += _L("You should update your software.\n");
9293 log_and_show_3mf_info(text, newer_3mf_title);
9294 }
9295 else {
9296 //if the minor version is not matched
9297 if (file_version.min() != app_version.min()) {
9298 wxString text = wxString::Format(_L("The 3MF file version %s is newer than %s's version %s, we suggest to upgrade your software."),
9299 file_version.to_string_sf(), std::string(SLIC3R_APP_FULL_NAME), app_version.to_string_sf());
9300 text += "\n";
9301 log_and_show_3mf_info(text, newer_3mf_title);
9302 }
9303 }
9304 }
9305 else if (load_config && config_loaded.empty()) {
9306 load_config = false;
9307 log_and_show_3mf_info(msg_old_orca_geometry, load_3mf_title);
9308 }
9309 }
9310 else if (en_3mf_file_type == En3mfType::From_BBS) {
9311 // No OrcaSlicer tag - check Bambu/Application version
9312 if (!is_bambu_studio_project) {
9313 // Compatible old version (before OrcaSlicer tagging was introduced after 2.3.2).
9314 // Any version prior or equal to 2.3.2 is older than the current one, no version warnings needed.
9315 // Still apply migration fixes for known old versions.
9316 if (load_config && (file_version == Semver("2.3.1-alpha"))) {
9317 if (!config_loaded.opt_string("sparse_infill_rotate_template").empty()) {
9318 const auto _sparse_infill_pattern =
9319 config_loaded.option<ConfigOptionEnum<InfillPattern>>("sparse_infill_pattern")->value;
9320 bool is_safe_to_rotate = _sparse_infill_pattern == ipRectilinear || _sparse_infill_pattern == ipLine ||
9321 _sparse_infill_pattern == ipZigZag || _sparse_infill_pattern == ipCrossZag ||
9322 _sparse_infill_pattern == ipLockedZag;
9323 if (!is_safe_to_rotate) {
9324 wxString msg_text = _(
9325 L("This project was created with an OrcaSlicer 2.3.1-alpha and uses "
9326 "infill rotation template settings that may not work properly with your current infill pattern. "
9327 "This could result in weak support or print quality issues."));
9328 msg_text += "\n\n" +
9329 _(L("Would you like OrcaSlicer to automatically fix this by clearing the rotation template settings?"));
9330 MessageDialog dialog(wxGetApp().plater(), msg_text, "", wxICON_WARNING | wxYES | wxNO);
9331 dialog.SetButtonLabel(wxID_YES, _L("Yes"));
9332 dialog.SetButtonLabel(wxID_NO, _L("No"));
9333 if (dialog.ShowModal() == wxID_YES) {
9334 config_loaded.opt_string("sparse_infill_rotate_template") = "";
9335 }
9336 }
9337 }
9338 }
9339 else if (load_config && config_loaded.empty()) {
9340 load_config = false;
9341 log_and_show_3mf_info(msg_older_geometry, load_3mf_title);
9342 }
9343 } else {
9344 // BambuStudio project (version > 2.3.2 without OrcaSlicer tag)
9345 if (load_config && config_loaded.empty()) {
9346 load_config = false;
9347 log_and_show_3mf_info(msg_bambu_geometry, load_3mf_title);
9348 }
9349 else if (load_config) {
9350 // Logged, not shown: it is the same for every BambuStudio project and needs no action.
9351 const std::string unrecognized = boost::algorithm::join(config_substitutions.unrecogized_keys, ", ");
9352 BOOST_LOG_TRIVIAL(info) << "BambuStudio " << file_version.to_string() << " project " << path.string()
9353 << ", unrecognized settings: " << (unrecognized.empty() ? "none" : unrecognized);
9354 }
9355 }
9356 }
9357 else if (en_3mf_file_type == En3mfType::From_Other) {
9358 // Generic CAD/other 3MF without slicer metadata: import geometry silently.
9359 if (load_config && config_loaded.empty()) {
9360 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
9361 << " "
9362 << boost::format("3MF has no slicer metadata/project config, importing geometry only: %1%") % path.string();
9363 load_config = false;
9364 }
9365 }
9366 else if (load_config && config_loaded.empty()) {
9367 load_config = false;
9368 log_and_show_3mf_info(msg_old_orca_geometry, load_3mf_title);
9369 }
9370 else if (!load_config) {
9371 // reset config except color
9372 for (ModelObject *model_object : model.objects) {
9373 bool has_extruder = model_object->config.has("extruder");
9374 int extruder_id = -1;
9375 // save the extruder information before reset
9376 if (has_extruder) { extruder_id = model_object->config.extruder(); }
9377
9378 model_object->config.reset();
9379
9380 // restore the extruder after reset
9381 if (has_extruder) { model_object->config.set("extruder", extruder_id); }
9382
9383 // Is there any modifier or advanced config data?
9384 for (ModelVolume *model_volume : model_object->volumes) {
9385 has_extruder = model_volume->config.has("extruder");
9386 if (has_extruder) { extruder_id = model_volume->config.extruder(); }
9387
9388 model_volume->config.reset();
9389
9390 if (has_extruder) { model_volume->config.set("extruder", extruder_id); }
9391 }
9392 }
9393 }
9394
9395 // ORCA: legacy feature-filament default migration (1 -> 0) is now handled
9396 // uniformly in PrintConfigDef::handle_legacy() via the old->new key rename
9397 // (wall_filament -> wall_filament_id, etc.), which also covers saved presets.
9398
9399 // plate data
9400 if (plate_data.size() > 0) {
9401 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", import 3mf UPDATE_GCODE_RESULT \n");
9402 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
9403 dlg_cont = dlg.Update(progress_percent, msg);
9404 if (!dlg_cont) {
9405 q->skip_thumbnail_invalid = false;
9406 return empty_result;
9407 }
9408
9409 Semver old_version(1, 5, 9);
9410 // A published 3MF has no project config to migrate: skip the old-version
9411 // translations even if a slicer tag slipped through classification.
9412 if ((en_3mf_file_type == En3mfType::From_BBS || en_3mf_file_type == En3mfType::From_Orca) && (file_version < old_version) && !published_config.published && load_model && load_config && !config_loaded.empty()) {
9413 translate_old = true;
9414 partplate_list.get_plate_size(current_width, current_depth, current_height);
9415 }
9416
9417 if (load_config) {
9418 if (translate_old) {
9419 //set the size back
9420 partplate_list.reset_size(current_width + Bed3D::Axes::DefaultTipRadius, current_depth + Bed3D::Axes::DefaultTipRadius, current_height, false);
9421 }
9422 project_filament_count = config_loaded.option<ConfigOptionStrings>("filament_colour")->size();
9423 partplate_list.load_from_3mf_structure(plate_data, project_filament_count);
9424 partplate_list.update_slice_context_to_current_plate(background_process);
9425 this->preview->update_gcode_result(partplate_list.get_current_slice_result());
9426 release_PlateData_list(plate_data);
9427 sidebar->obj_list()->reload_all_plates();
9428 q->suppress_background_process(true);
9429 } else {
9430 partplate_list.reload_all_objects();
9431 }
9432 }
9433
9434 // BBS:: project embedded presets (skipped for published projects: the author's
9435 // embedded presets must not pollute the receiver's library, the overlay applies
9436 // the published keys to the receiver's own presets instead).
9437 if ((project_presets.size() > 0) && load_config && !published_config.published) {
9438 // load project embedded presets
9439 PresetsConfigSubstitutions preset_substitutions;
9440 PresetBundle & preset_bundle = *wxGetApp().preset_bundle;
9441 preset_substitutions = preset_bundle.load_project_embedded_presets(project_presets, ForwardCompatibilitySubstitutionRule::Enable);
9442 if (is_bambu_studio_project)
9443 log_substitutions(preset_substitutions, path.string());
9444 else if (!preset_substitutions.empty())
9445 show_substitutions_info(preset_substitutions);
9446 }
9447 if (project_presets.size() > 0) {
9448 for (unsigned int i = 0; i < project_presets.size(); i++) { delete project_presets[i]; }
9449 project_presets.clear();
9450 }
9451
9452 if (load_config && !config_loaded.empty()) {
9453 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", import 3mf IMPORT_LOAD_CONFIG \n");
9454 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
9455 dlg_cont = dlg.Update(progress_percent, msg);
9456 if (!dlg_cont) {
9457 q->skip_thumbnail_invalid = false;
9458 return empty_result;
9459 }
9460
9461 // Based on the printer technology field found in the loaded config, select the base for the config,
9463
9464 config.apply(static_cast<const ConfigBase &>(FullPrintConfig::defaults()));
9465 // and place the loaded config over the base.
9466 config += std::move(config_loaded);
9467 std::map<std::string, std::string> validity = config.validate();
9468 if (!validity.empty()) {
9469 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("Param values in 3mf error: ");
9470 for (std::map<std::string, std::string>::iterator it=validity.begin(); it!=validity.end(); ++it)
9471 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("%1%: %2%")%it->first %it->second;
9472 //
9473 NotificationManager *notify_manager = q->get_notification_manager();
9474 std::string error_message = _u8L("Invalid values found in the 3MF:");
9475 error_message += "\n";
9476 for (std::map<std::string, std::string>::iterator it=validity.begin(); it!=validity.end(); ++it)
9477 error_message += "-" + it->first + ": " + it->second + "\n";
9478 error_message += "\n";
9479 error_message += _u8L("Please correct them in the Param tabs");
9480 notify_manager->bbl_show_3mf_warn_notification(error_message);
9481 }
9482 }
9483 // BambuStudio projects routinely carry values Orca replaces; log them rather than showing a dialog on every open.
9484 if (is_bambu_studio_project)
9485 log_substitutions(config_substitutions.substitutions, path.string());
9486 else if (!config_substitutions.empty())
9487 show_substitutions_info(config_substitutions.substitutions, filename.string());
9488
9489 // BBS
9490 if (load_model && !load_config) {
9491 ;
9492 }
9493 else {
9494 this->model.plates_custom_gcodes = model.plates_custom_gcodes;
9495 this->model.design_info = model.design_info;
9496 this->model.model_info = model.model_info;
9497 }
9498 }
9499
9500 // BBS: a "published" 3MF loads as a new project: its path must not become the
9501 // project filename (Save/Ctrl-S would overwrite the shared file), and the
9502 // published metadata is consumed above and stripped so a later save is a normal
9503 // unpublished 3MF.
9504 if (published_out != nullptr && published_config.published)
9505 *published_out = true;
9506 if (published_config.published && load_config && this->model.model_info != nullptr) {
9507 this->model.model_info->metadata_items.erase(ORCA_PUBLISHED_TAG);
9508 this->model.model_info->metadata_items.erase(ORCA_PUBLISHED_KEYS_TAG);
9509 this->model.model_info->metadata_items.erase(ORCA_PUBLISHED_MATERIAL_TAG);
9510 this->model.model_info->metadata_items.erase(ORCA_PUBLISHED_CONFIG_TAG);
9511 }
9512
9513 if (load_config) {
9514 if (!config.empty()) {
9516 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
9517
9518 {
9519 // BBS: modify the prime tower params for old version file
9520 Semver old_version3(2, 0, 0);
9521 if ((en_3mf_file_type == En3mfType::From_BBS || en_3mf_file_type == En3mfType::From_Orca) && !published_config.published && file_version < old_version3) {
9522 double old_filament_prime_volume = 0.;
9523 int filament_count = 0;
9524 {
9525 ConfigOptionFloats *filament_prime_volume_option = config.option<ConfigOptionFloats>("filament_prime_volume");
9526 ConfigOptionStrings *filament_colors_option = config.option<ConfigOptionStrings>("filament_colour", true);
9527 filament_count = filament_colors_option->values.size();
9528 if (filament_prime_volume_option) {
9529 std::vector<double> &filament_prime_volume_values = filament_prime_volume_option->values;
9530 if (!filament_prime_volume_values.empty()) {
9531 old_filament_prime_volume = filament_prime_volume_values[0];
9532 if (filament_count > 1) filament_prime_volume_values.resize(filament_count, old_filament_prime_volume);
9533 }
9534 }
9535 }
9536 ConfigOptionEnum<WipeTowerWallType> *prime_tower_rib_wall_option = config.option<ConfigOptionEnum<WipeTowerWallType>>("wipe_tower_wall_type", true);
9537 prime_tower_rib_wall_option->value = WipeTowerWallType::wtwRectangle;
9538
9539 ConfigOptionPercent *prime_tower_infill_gap_option = config.option<ConfigOptionPercent>("prime_tower_infill_gap", true);
9540 prime_tower_infill_gap_option->value = 100;
9541
9542 ConfigOptionInts *filament_adhesiveness_category_option = config.option<ConfigOptionInts>("filament_adhesiveness_category", true);
9543 std::vector<int> &filament_adhesiveness_category_values = filament_adhesiveness_category_option->values;
9544 filament_adhesiveness_category_values.resize(filament_count);
9545 for (int index = 0; index < filament_count; index++)
9546 filament_adhesiveness_category_values[index] = 100;
9547
9548 std::vector<std::string> &diff_settings = config.option<ConfigOptionStrings>("different_settings_to_system", true)->values;
9549 diff_settings.resize(filament_count + 2);
9550
9551 std::vector<std::string> diff_process_keys;
9552 std::string diff_process_settings = diff_settings[0];
9553 Slic3r::unescape_strings_cstyle(diff_process_settings, diff_process_keys);
9554 diff_process_keys.emplace_back("wipe_tower_wall_type");
9555 diff_process_keys.emplace_back("prime_tower_infill_gap");
9556 diff_process_settings = Slic3r::escape_strings_cstyle(diff_process_keys);
9557 diff_settings[0] = diff_process_settings;
9558
9559 for (int index = 0; index < filament_count; index++) {
9560 std::vector<std::string> diff_filament_keys;
9561 std::string diff_filament_settings = diff_settings[index + 1];
9562 Slic3r::unescape_strings_cstyle(diff_filament_settings, diff_filament_keys);
9563 diff_filament_keys.emplace_back("filament_adhesiveness_category");
9564 diff_filament_settings = Slic3r::escape_strings_cstyle(diff_filament_keys);
9565 diff_settings[index + 1] = diff_filament_settings;
9566 }
9567 }
9568 }
9569
9570 auto choise = wxGetApp().app_config->get("no_warn_when_modified_gcodes");
9571 if (!published_config.published && (choise.empty() || choise != "true")) {
9572 // BBS: first validate the printer
9573 // validate the system profiles
9574 std::set<std::string> modified_gcodes;
9575 int validated = preset_bundle->validate_presets(filename.string(), config, modified_gcodes);
9576 if (validated == VALIDATE_PRESETS_MODIFIED_GCODES) {
9577 std::string warning_message;
9578 warning_message += "\n";
9579 for (std::set<std::string>::iterator it=modified_gcodes.begin(); it!=modified_gcodes.end(); ++it)
9580 warning_message += "-" + *it + "\n";
9581 warning_message += "\n";
9582 //show_info(q, _L("The 3MF has the following modified G-code in filament or printer presets:") + warning_message + _L("Please confirm that all modified G-code is safe to prevent any damage to the machine!"), _L("Modified G-code"));
9583 MessageDialog dlg(q, _L("The 3MF has the following modified G-code in filament or printer presets:") + warning_message + _L("Please confirm that all modified G-code is safe to prevent any damage to the machine!"), _L("Modified G-code"));
9584 dlg.show_dsa_button();
9585 auto res = dlg.ShowModal();
9586 if (dlg.get_checkbox_state())
9587 wxGetApp().app_config->set("no_warn_when_modified_gcodes", "true");
9588 }
9589 else if ((validated == VALIDATE_PRESETS_PRINTER_NOT_FOUND) || (validated == VALIDATE_PRESETS_FILAMENTS_NOT_FOUND)) {
9590 std::string warning_message;
9591 warning_message += "\n";
9592 for (std::set<std::string>::iterator it=modified_gcodes.begin(); it!=modified_gcodes.end(); ++it)
9593 warning_message += "-" + *it + "\n";
9594 warning_message += "\n";
9595 //show_info(q, _L("The 3MF has the following customized filament or printer presets:") + warning_message + _L("Please confirm that the G-code within these presets is safe to prevent any damage to the machine!"), _L("Customized Preset"));
9596 MessageDialog dlg(q, _L("The 3MF has the following customized filament or printer presets:") + from_u8(warning_message)+ _L("Please confirm that the G-code within these presets is safe to prevent any damage to the machine!"), _L("Customized Preset"));
9597 dlg.show_dsa_button();
9598 auto res = dlg.ShowModal();
9599 if (dlg.get_checkbox_state())
9600 wxGetApp().app_config->set("no_warn_when_modified_gcodes", "true");
9601 }
9602 }
9603
9604 //always load config
9605 {
9606 // BBS: save the wipe tower pos in file here, will be used later
9607 ConfigOptionFloats* wipe_tower_x_opt = config.opt<ConfigOptionFloats>("wipe_tower_x");
9608 ConfigOptionFloats* wipe_tower_y_opt = config.opt<ConfigOptionFloats>("wipe_tower_y");
9609 std::optional<ConfigOptionFloats>file_wipe_tower_x;
9610 std::optional<ConfigOptionFloats>file_wipe_tower_y;
9611 if (wipe_tower_x_opt)
9612 file_wipe_tower_x = *wipe_tower_x_opt;
9613 if (wipe_tower_y_opt)
9614 file_wipe_tower_y = *wipe_tower_y_opt;
9615
9616 // Convert the printer's filament ids to Orca ids before loading.
9617 if (auto* agent = wxGetApp().getAgent()) {
9618 if (auto* ids = config.opt<ConfigOptionStrings>("filament_ids"))
9619 for (std::string& id : ids->values)
9620 id = agent->to_orca_filament_id(id);
9621 }
9622 preset_bundle->load_config_model(filename.string(), std::move(config), file_version, &published_config);
9623 if (config_loaded_out != nullptr)
9624 *config_loaded_out = true;
9625
9626 // Mixed-filament definitions that collided with one of the
9627 // receiver's real slots were relocated during the preset load.
9628 // Re-point the freshly parsed model's extruder references and
9629 // color painting from the author's slot numbers to where each
9630 // definition landed, so volumes colored with a mix follow it.
9631 // Runs before the objects are handed over to the plater below.
9632 if (load_model && !published_config.mixed_slot_relocations.empty())
9633 Slic3r::remap_model_filament_slots(model, published_config.mixed_slot_relocations);
9634
9635 // BBS: notify the user about published settings that could not be applied.
9636 if (!published_config.skipped_keys.empty()) {
9637 NotificationManager* notify_manager = q->get_notification_manager();
9638 std::string message = _u8L("Some published settings could not be applied:");
9639 for (const std::string& key : published_config.skipped_keys)
9640 message += "\n-" + key;
9641 // Informational: the load succeeded, these keys were skipped.
9642 notify_manager
9643 ->bbl_show_3mf_warn_notification(message,
9645 }
9646
9647 // BBS: notify the user about slot materials that were replaced while
9648 // loading a published project (type mismatch / no same-type match).
9649 if (!published_config.material_replacements.empty()) {
9650 NotificationManager* notify_manager = q->get_notification_manager();
9651 std::string message = _u8L("Some filament slots were changed:");
9652 for (const std::string& replacement : published_config.material_replacements)
9653 message += "\n-" + replacement;
9654 // Informational: the load succeeded, the slots were adapted.
9655 notify_manager
9656 ->bbl_show_3mf_warn_notification(message,
9658 }
9659
9660 // Remember the imported published selection so the Publish dialog is
9661 // pre-seeded with the file's settings. Stored after the load so any
9662 // per-slot relocations are already reflected in material_keys.
9663 if (published_config.published) {
9664 this->m_has_pending_published = true;
9665 this->m_pending_published_keys = published_config.published_keys;
9666 this->m_pending_material_keys = published_config.material_keys;
9667 }
9668
9669 ConfigOption* bed_type_opt = preset_bundle->project_config.option("curr_bed_type");
9670 if (bed_type_opt != nullptr) {
9671 BedType bed_type = (BedType)bed_type_opt->getInt();
9672 // update app config for bed type
9673 bool is_bbl_preset = preset_bundle->is_bbl_vendor();
9674 if (is_bbl_preset) {
9675 AppConfig* app_config = wxGetApp().app_config;
9676 if (app_config)
9677 app_config->set("curr_bed_type", std::to_string(int(bed_type)));
9678 }
9679 q->on_bed_type_change(bed_type);
9680 }
9681
9682 // BBS: moved this logic to presetcollection
9683 //{
9684 // // After loading of the presets from project, check if they are visible.
9685 // // Set them to visible if they are not.
9686
9687 // auto update_selected_preset_visibility = [](PresetCollection& presets, std::vector<std::string>& names) {
9688 // if (!presets.get_selected_preset().is_visible) {
9689 // assert(presets.get_selected_preset().name == presets.get_edited_preset().name);
9690 // presets.get_selected_preset().is_visible = true;
9691 // presets.get_edited_preset().is_visible = true;
9692 // names.emplace_back(presets.get_selected_preset().name);
9693 // }
9694 // };
9695
9696 // std::vector<std::string> names;
9697 // if (printer_technology == ptFFF) {
9698 // update_selected_preset_visibility(preset_bundle->prints, names);
9699 // for (const std::string& filament : preset_bundle->filament_presets) {
9700 // Preset* preset = preset_bundle->filaments.find_preset(filament);
9701 // if (preset && !preset->is_visible) {
9702 // preset->is_visible = true;
9703 // names.emplace_back(preset->name);
9704 // if (preset->name == preset_bundle->filaments.get_edited_preset().name)
9705 // preset_bundle->filaments.get_selected_preset().is_visible = true;
9706 // }
9707 // }
9708 // }
9709 // else {
9710 // update_selected_preset_visibility(preset_bundle->sla_prints, names);
9711 // update_selected_preset_visibility(preset_bundle->sla_materials, names);
9712 // }
9713 // update_selected_preset_visibility(preset_bundle->printers, names);
9714
9715 // preset_bundle->update_compatible(PresetSelectCompatibleType::Never);
9716
9717 // // show notification about temporarily installed presets
9718 // if (!names.empty()) {
9719 // std::string notif_text = into_u8(_L_PLURAL("The preset below was temporarily installed on the active instance of PrusaSlicer",
9720 // "The presets below were temporarily installed on the active instance of PrusaSlicer",
9721 // names.size())) + ":";
9722 // for (std::string& name : names)
9723 // notif_text += "\n - " + name;
9724 // notification_manager->push_notification(NotificationType::CustomNotification,
9725 // NotificationManager::NotificationLevel::PrintInfoNotificationLevel, notif_text);
9726 // }
9727 //}
9728
9729 // BBS
9730 // if (printer_technology == ptFFF)
9731 // CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &preset_bundle->project_config);
9732
9733 // For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload"
9734 // BBS: add preset combo box re-active logic
9735 // currently found only needs re-active here
9736 wxGetApp().load_current_presets(false, false);
9737 // Update filament colors for the MM-printer profile in the full config
9738 // to avoid black (default) colors for Extruders in the ObjectList,
9739 // when for extruder colors are used filament colors
9740 q->on_filament_count_change(preset_bundle->filament_presets.size());
9741 is_project_file = true;
9742
9743 DynamicConfig& proj_cfg = preset_bundle->project_config;
9744 // do some post process after loading config
9745 {
9746 //BBS: rewrite wipe tower pos stored in 3mf file , the code above should be seriously reconsidered
9747 ConfigOptionFloats* wipe_tower_x = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_x");
9748 ConfigOptionFloats* wipe_tower_y = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_y");
9749 if (file_wipe_tower_x)
9750 *wipe_tower_x = *file_wipe_tower_x;
9751 if (file_wipe_tower_y)
9752 *wipe_tower_y = *file_wipe_tower_y;
9753
9755 }
9756 // Update filament combobox after loading config
9757 if (published_config.published) {
9758 q->update_filament_colors_in_full_config();
9759 wxGetApp().plater()->sidebar().update_all_preset_comboboxes();
9760 wxGetApp().plater()->sidebar().update_dynamic_filament_list();
9761 } else {
9762 wxGetApp().plater()->sidebar().update_presets(Preset::TYPE_FILAMENT);
9763 }
9764 // The loaded project supplies nozzle_volume_type; refresh the sidebar
9765 // nozzle-count badges against it.
9766 if (auto *nozzle_volumes = wxGetApp().preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type")) {
9767 const int extruder_count = wxGetApp().preset_bundle->get_printer_extruder_count();
9768 for (int extruder_id = 0; extruder_id < extruder_count && extruder_id < (int) nozzle_volumes->values.size(); ++extruder_id)
9769 updateNozzleCountDisplay(wxGetApp().preset_bundle, extruder_id, NozzleVolumeType(nozzle_volumes->values[extruder_id]));
9770 }
9771 }
9772 }
9773 if (!silence) wxGetApp().app_config->update_config_dir(path.parent_path().string());
9774 }
9775 } else {
9776 // BBS: add plate data related logic
9777 PlateDataPtrs plate_data;
9778 // BBS: project embedded settings
9779 std::vector<Preset *> project_presets;
9780 bool is_xxx;
9781 Semver file_version;
9782
9783 if (boost::iends_with(path.string(), ".stp") ||
9784 boost::iends_with(path.string(), ".step")) {
9785 double linear = string_to_double_decimal_point(wxGetApp().app_config->get("linear_deflection"));
9786 if (linear <= 0) linear = 0.003;
9787 double angle = string_to_double_decimal_point(wxGetApp().app_config->get("angle_deflection"));
9788 if (angle <= 0) angle = 0.5;
9789 bool split_compound = wxGetApp().app_config->get_bool("is_split_compound");
9790 model = Slic3r::Model:: read_from_step(path.string(), strategy,
9791 [&dlg, real_filename, &progress_percent, step_percent, INPUT_FILES_RATIO, total_files, i](int load_stage, int current, int total, bool &cancel)
9792 {
9793 bool cont = true;
9794 float percent_float = (100.0f * (float)i / (float)total_files) + INPUT_FILES_RATIO * ((float)step_percent[load_stage] + (float)current * (float)(step_percent[load_stage + 1] - step_percent[load_stage]) / (float)total) / (float)total_files;
9795 BOOST_LOG_TRIVIAL(trace) << "load_step_file: percent(float)=" << percent_float << ", stage = " << load_stage << ", curr = " << current << ", total = " << total;
9796 progress_percent = (int)percent_float;
9797 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
9798 cont = dlg.Update(progress_percent, msg);
9799 cancel = !cont;
9800 },
9801 [](int isUtf8StepFile) {
9802 if (!isUtf8StepFile) {
9803 const auto no_warn = wxGetApp().app_config->get_bool("step_not_utf8_no_warn");
9804 if (!no_warn) {
9805 MessageDialog dlg(nullptr, _L("Component name(s) inside step file not in UTF-8 format!") + "\n\n" + _L("Because of unsupported text encoding, garbage characters may appear!"),
9806 wxString(SLIC3R_APP_FULL_NAME " - ") + _L("Attention!"), wxOK | wxICON_INFORMATION);
9807 dlg.show_dsa_button(_L("Remember my choice."));
9808 dlg.ShowModal();
9809 if (dlg.get_checkbox_state()) {
9810 wxGetApp().app_config->set_bool("step_not_utf8_no_warn", true);
9811 }
9812 }
9813 }
9814 },
9815 [&is_user_cancel, &linear, &angle, &split_compound](Slic3r::Step& file, double& linear_value, double& angle_value, bool& is_split)-> int {
9816 if (wxGetApp().app_config->get_bool("enable_step_mesh_setting")) {
9817 StepMeshDialog mesh_dlg(nullptr, file, linear, angle);
9818 if (mesh_dlg.ShowModal() == wxID_OK) {
9819 linear_value = mesh_dlg.get_linear_deflection();
9820 angle_value = mesh_dlg.get_angle_deflection();
9821 is_split = mesh_dlg.get_split_compound_value();
9822 return 1;
9823 }
9824 }else {
9825 linear_value = linear;
9826 angle_value = angle;
9827 is_split = split_compound;
9828 return 1;
9829 }
9830 is_user_cancel = true;
9831 return -1;
9832 }, linear, angle, split_compound);
9833 }else {
9835 path.string(), nullptr, nullptr, strategy, &plate_data, &project_presets, &is_xxx, &file_version, nullptr,
9836 [&dlg, real_filename, &progress_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id, &designer_country_code](int current, int total, bool &cancel, std::string &mode_id, std::string &code)
9837 {
9838 designer_model_id = mode_id;
9839 designer_country_code = code;
9840
9841 bool cont = true;
9842 float percent_float = (100.0f * (float)i / (float)total_files) + INPUT_FILES_RATIO * 100.0f * ((float)current / (float)total) / (float)total_files;
9843 BOOST_LOG_TRIVIAL(trace) << "load_stl_file: percent(float)=" << percent_float << ", curr = " << current << ", total = " << total;
9844 progress_percent = (int)percent_float;
9845 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
9846 cont = dlg.Update(progress_percent, msg);
9847 cancel = !cont;
9848 },
9849 nullptr, 0);
9850 }
9851
9852 if (designer_model_id.empty() && boost::algorithm::iends_with(path.string(), ".stl")) {
9853 read_binary_stl(path.string(), designer_model_id, designer_country_code);
9854 }
9855
9856 if (type_any_amf && is_xxx) imperial_units = true;
9857
9858 for (auto obj : model.objects) {
9859 if (obj->name.empty()) {
9860 obj->name = fs::path(obj->input_file).filename().string();
9861 }
9862 obj->rotate(Geometry::deg2rad(config->opt_float("preferred_orientation")), Axis::Z);
9863 }
9864
9865 if (plate_data.size() > 0) {
9866 partplate_list.load_from_3mf_structure(plate_data, project_filament_count);
9867 partplate_list.update_slice_context_to_current_plate(background_process);
9868 this->preview->update_gcode_result(partplate_list.get_current_slice_result());
9869 release_PlateData_list(plate_data);
9870 sidebar->obj_list()->reload_all_plates();
9871 }
9872
9873 // BBS:: project embedded presets
9874 if (project_presets.size() > 0) {
9875 // load project embedded presets
9876 PresetsConfigSubstitutions preset_substitutions;
9877 PresetBundle & preset_bundle = *wxGetApp().preset_bundle;
9878 preset_substitutions = preset_bundle.load_project_embedded_presets(project_presets, ForwardCompatibilitySubstitutionRule::Enable);
9879 if (!preset_substitutions.empty()) show_substitutions_info(preset_substitutions);
9880
9881 for (unsigned int i = 0; i < project_presets.size(); i++) { delete project_presets[i]; }
9882 project_presets.clear();
9883 }
9884 }
9885 } catch (const ConfigurationError &e) {
9886 std::string message = GUI::format(_L("Failed loading file \"%1%\". An invalid configuration was found."), filename.string()) + "\n\n" + e.what();
9887 GUI::show_error(q, message);
9888 continue;
9889 } catch (const std::exception &e) {
9890 if (!is_user_cancel)
9891 GUI::show_error(q, e.what());
9892 continue;
9893 }
9894
9895 progress_percent = 100.0f * (float)i / (float)total_files + INIT_MODEL_RATIO * 100.0f / (float)total_files;
9896 dlg_cont = dlg.Update(progress_percent);
9897 if (!dlg_cont) {
9898 q->skip_thumbnail_invalid = false;
9899 return empty_result;
9900 }
9901
9902 if (load_model) {
9903 // The model should now be initialized
9904 auto convert_from_imperial_units = [](Model &model, bool only_small_volumes) { model.convert_from_imperial_units(only_small_volumes); };
9905
9906 // BBS: add load_old_project logic
9907 if ((!is_project_file) && (!load_old_project)) {
9908 // if (!is_project_file) {
9909 if (int deleted_objects = model.removed_objects_with_zero_volume(); deleted_objects > 0) {
9910 MessageDialog(q, _L("Objects with zero volume removed"), _L("The volume of the object is zero"), wxICON_INFORMATION | wxOK).ShowModal();
9911 }
9912 if (imperial_units)
9913 // Convert even if the object is big.
9914 convert_from_imperial_units(model, false);
9915 else if (model.looks_like_saved_in_meters()) {
9916 // BBS do not handle look like in meters
9917 MessageDialog dlg(q,
9918 format_wxstr(_L("The object from file %s is too small, and may be in meters or inches.\nDo you want to scale to millimeters\?"),
9919 from_path(filename)),
9920 _L("Object too small"), wxICON_QUESTION | wxYES_NO);
9921 int answer = dlg.ShowModal();
9922 if (answer == wxID_YES) model.convert_from_meters(true);
9923 } else if (model.looks_like_imperial_units()) {
9924 // BBS do not handle look like in meters
9925 MessageDialog dlg(q,
9926 format_wxstr(_L("The object from file %s is too small, and may be in meters or inches.\nDo you want to scale to millimeters\?"),
9927 from_path(filename)),
9928 _L("Object too small"), wxICON_QUESTION | wxYES_NO);
9929 int answer = dlg.ShowModal();
9930 if (answer == wxID_YES) convert_from_imperial_units(model, true);
9931 }
9932 // else if (model.looks_like_imperial_units()) {
9933 // BBS do not handle look like in imperial
9934 // auto convert_model_if = [convert_from_imperial_units](Model& model, bool condition) {
9935 // if (condition)
9936 // //FIXME up-scale only the small parts?
9937 // convert_from_imperial_units(model, true);
9938 //};
9939 // if (answer_convert_from_imperial_units == wxOK_DEFAULT) {
9940 // RichMessageDialog dlg(q, format_wxstr(_L_PLURAL(
9941 // "The dimensions of the object from file %s seem to be defined in inches.\n"
9942 // "The internal unit of PrusaSlicer is a millimeter. Do you want to recalculate the dimensions of the object?",
9943 // "The dimensions of some objects from file %s seem to be defined in inches.\n"
9944 // "The internal unit of PrusaSlicer is a millimeter. Do you want to recalculate the dimensions of these objects?", model.objects.size()), from_path(filename))
9945 // + "\n", _L("The object is too small"), wxICON_QUESTION | wxYES_NO);
9946 // dlg.ShowCheckBox(_L("Apply to all the remaining small objects being loaded."));
9947 // int answer = dlg.ShowModal();
9948 // if (dlg.IsCheckBoxChecked())
9949 // answer_convert_from_imperial_units = answer;
9950 // else
9951 // convert_model_if(model, answer == wxID_YES);
9952 //}
9953 // convert_model_if(model, answer_convert_from_imperial_units == wxID_YES);
9954 }
9955
9956 if (!is_project_file && model.looks_like_multipart_object()) {
9957 MessageDialog msg_dlg(q, _L("This file contains several objects positioned at multiple heights.\nInstead of considering them as multiple objects, should \nthe file be loaded as a single object with multiple parts\?") + "\n",
9958 _L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO);
9959 if (msg_dlg.ShowModal() == wxID_YES) {
9960 model.convert_multipart_object(filaments_cnt);
9961 }
9962 }
9963 }
9964 // else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) {
9965 // MessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n",
9966 // _L("Detected advanced data"), wxICON_WARNING | wxYES | wxNO);
9967 // if (msg_dlg.ShowModal() == wxID_YES) {
9968 // Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
9969 // view3D->set_as_dirty();
9970 // }
9971 // else
9972 // return obj_idxs;
9973 //}
9974
9975 progress_percent = 100.0f * (float)i / (float)total_files + CENTER_AROUND_ORIGIN_RATIO * 100.0f / (float)total_files;
9976 dlg_cont = dlg.Update(progress_percent);
9977 if (!dlg_cont) {
9978 q->skip_thumbnail_invalid = false;
9979 return empty_result;
9980 }
9981
9982 int model_idx = 0;
9983 for (ModelObject *model_object : model.objects) {
9984 if (!type_3mf && !type_any_amf)
9985 model_object->center_around_origin(false);
9986
9987 // BBS
9988 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << " " << boost::format("import 3mf IMPORT_LOAD_MODEL_OBJECTS \n");
9989 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
9990 model_idx++;
9991 dlg_cont = dlg.Update(progress_percent, msg);
9992 if (!dlg_cont) {
9993 q->skip_thumbnail_invalid = false;
9994 return empty_result;
9995 }
9996
9997 if (!model_object->instances.empty())
9998 model_object->ensure_on_bed(is_project_file);
9999 }
10000
10001 tolal_model_count += model_idx;
10002
10003 progress_percent = 100.0f * (float)i / (float)total_files + LOAD_MODEL_RATIO * 100.0f / (float)total_files;
10004 dlg_cont = dlg.Update(progress_percent);
10005 if (!dlg_cont) {
10006 q->skip_thumbnail_invalid = false;
10007 return empty_result;
10008 }
10009
10010 if (one_by_one) {
10011 // BBS: add load_old_project logic
10012 if (type_3mf && !is_project_file && !load_old_project)
10013 // if (type_3mf && !is_project_file)
10014 model.center_instances_around_point(this->bed.build_volume().bed_center());
10015 // BBS: add auxiliary files logic
10016 // BBS: backup & restore
10017 if (load_aux) {
10018 q->model().load_from(model);
10020 }
10021 // Texture-to-color: a mesh that arrived with UVs and a decoded texture gets its
10022 // faces clustered into printable colours and matched against the filament list,
10023 // before the objects are handed to the plater. Inert for every other model.
10024 if (model.texture_mesh && has_importable_texture(*model.texture_mesh)) {
10025 TextureImportResult texture_import_result;
10026 auto cancel_cb = [&dlg, &dlg_cont]() { return !dlg_cont || dlg.WasCancelled(); };
10027 auto progress_cb = [&dlg, &dlg_cont, &progress_percent](int percent) {
10028 progress_percent = std::clamp(percent, 0, 100);
10029 dlg_cont = dlg.Update(progress_percent, _L("Matching textures to filaments"));
10030 return dlg_cont;
10031 };
10032 if (!run_textured_mesh_import_dialog(model, texture_import_result, cancel_cb, progress_cb)) {
10033 q->skip_thumbnail_invalid = false;
10034 return empty_result;
10035 }
10036 if (texture_import_result.fallback_to_geometry_only && !texture_import_result.fallback_warning.empty()) {
10037 MessageDialog(q, texture_import_result.fallback_warning,
10038 _L("Texture Import Warning"),
10039 wxOK | wxICON_WARNING).ShowModal();
10040 }
10041 if (!texture_import_result.painted.face_colors.empty()) {
10042 std::vector<size_t> texture_object_idxs(model.objects.size());
10043 std::iota(texture_object_idxs.begin(), texture_object_idxs.end(), 0);
10044 auto apply_progress_cb = [&dlg](int percent, const wxString& msg) {
10045 dlg.Update(std::clamp(percent, 0, 100), msg);
10046 return true;
10047 };
10048 apply_textured_mesh_import_result(model, texture_object_idxs, texture_import_result,
10049 apply_progress_cb, false);
10050 }
10051 }
10052
10053 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", before load_model_objects, count %1%")%model.objects.size();
10054 auto loaded_idxs = load_model_objects(model.objects, is_project_file);
10055 obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
10056
10057 // load_model_objects only transfers ModelObjects; carry the Model-level CAD recipe
10058 // onto the plater model so the Design tab can rehydrate the editable feature tree on
10059 // reopen. Assigned unconditionally on the project-replacing path so that opening a
10060 // project without a recipe clears whatever the previous one left behind; importing a
10061 // plain model into the open project leaves the current recipe alone.
10062 if (is_project_file) {
10063 q->model().cad_recipe = model.cad_recipe;
10064 loaded_cad_recipe = !model.cad_recipe.empty();
10065 }
10066
10067 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", finished load_model_objects");
10068 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
10069 dlg_cont = dlg.Update(progress_percent, msg);
10070 if (!dlg_cont) {
10071 q->skip_thumbnail_invalid = false;
10072 return empty_result;
10073 }
10074 } else {
10075 // This must be an .stl or .obj file, which may contain a maximum of one volume.
10076 for (const ModelObject *model_object : model.objects) {
10077 new_model->add_object(*model_object);
10078
10079 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":" << __LINE__ << boost::format(", added object %1%")%model_object->name;
10080 wxString msg = wxString::Format(_L("Loading file: %s"), from_path(real_filename));
10081 dlg_cont = dlg.Update(progress_percent, msg);
10082 if (!dlg_cont) {
10083 q->skip_thumbnail_invalid = false;
10084 return empty_result;
10085 }
10086 }
10087 }
10088 }
10089
10090 if (new_model != nullptr && new_model->objects.size() > 1) {
10091 //BBS do not popup this dialog
10092
10093 bool new_model_auto_drop = true;
10094 int single_object_answer = false;
10095 if (ask_multi) {
10096 RichMessageDialog dlg(q, _L("Load these files as a single object with multiple parts?\n"),
10097 _L("An object with multiple parts was detected"), wxICON_QUESTION | wxYES_NO);
10098
10099 dlg.ShowCheckBox(_L("Auto-Drop"), true);
10100 single_object_answer = dlg.ShowModal();
10101
10102 if (dlg.IsCheckBoxChecked() == false)
10103 new_model_auto_drop = false;
10104
10105 // convert to multipart and split after load_model_objects
10106 // to keep relative positioning if auto_drop == false
10107 if (single_object_answer == wxID_YES || new_model_auto_drop == false)
10108 new_model->convert_multipart_object(filaments_cnt);
10109 }
10110
10111 // TODO
10112 // DONE always convert to multipart, split afterwards to retain relative position
10113 // DONE if !auto_drop move all objects over the z-position 0, so that none are clipped by the bed.
10114 // DONE retain auto_drop (and printable) state when assembling or splitting objects.
10115 // DONE when manually split to object ask users if looks_like_multipart and none have auto_drob disabled if they want to disable auto_drop for all resulting objects.
10116 // - add icon in object list, similar to fuzzy painting, etc.
10117
10118 auto loaded_idxs = load_model_objects(new_model->objects, false, false, new_model_auto_drop);
10119 obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end());
10120
10121 if (single_object_answer == wxID_NO && new_model_auto_drop == false) {
10122 split_object(loaded_idxs[0], new_model_auto_drop);
10123 }
10124 }
10125
10126 if (load_config) {
10127 DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
10128 if (dev) {
10129 MachineObject *obj = dev->get_selected_machine();
10130 if (obj && obj->is_info_ready()) {
10131 if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) {
10132 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
10133 Preset &printer_preset = preset_bundle->printers.get_selected_preset();
10134
10135 double preset_nozzle_diameter = 0.4;
10136 const ConfigOption *opt = printer_preset.config.option("nozzle_diameter");
10137 if (opt) preset_nozzle_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
10138
10139 std::string machine_type = obj->printer_type;
10140 if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) machine_type = "C12";
10141
10142 bool nozzle_mismatch = !obj->GetExtderSystem()->NozzleDiameterMatchesOrUnknown(0, (float) preset_nozzle_diameter);
10143 if (printer_preset.get_current_printer_type(preset_bundle) != machine_type || nozzle_mismatch) {
10144 Preset *machine_preset = get_printer_preset(obj);
10145 if (machine_preset != nullptr) {
10146 std::string printer_model = machine_preset->config.option<ConfigOptionString>("printer_model")->value;
10147 bool sync_printer_info = false;
10148 if (!wxGetApp().app_config->has("sync_after_load_file_show_flag")) {
10149 wxString tips = from_u8((boost::format(_u8L("Connected printer is %s. It must match the project preset for printing.\n")) % printer_model).str());
10150
10151 tips += _L("Do you want to sync the printer information and automatically switch the preset?");
10152 TipsDialog dlg(wxGetApp().mainframe, _L("Tips"), tips, "sync_after_load_file_show_flag", wxYES_NO);
10153 if (dlg.ShowModal() == wxID_YES) { sync_printer_info = true; }
10154 }
10155 else {
10156 sync_printer_info = wxGetApp().app_config->get("sync_after_load_file_show_flag") == "true";
10157 }
10158 if (sync_printer_info) {
10159 Tab *printer_tab = GUI::wxGetApp().get_tab(Preset::Type::TYPE_PRINTER);
10160 printer_tab->select_preset(machine_preset->name);
10161 if (obj->is_multi_extruders()) GUI::wxGetApp().sidebar().sync_extruder_list();
10162 }
10163 }
10164 }
10165 }
10166 }
10167 }
10168 }
10169
10170 if (new_model) delete new_model;
10171
10172 //BBS: translate old 3mf to correct positions
10173 if (translate_old) {
10174 //translate the objects
10175 int plate_count = partplate_list.get_plate_count();
10176 for (int index = 1; index < plate_count; index ++) {
10177 PartPlate* cur_plate = (PartPlate *)partplate_list.get_plate(index);
10178
10179 Vec3d cur_origin = cur_plate->get_origin();
10180 Vec3d new_origin = partplate_list.compute_origin_using_new_size(index, current_width, current_depth);
10181
10182 cur_plate->translate_all_instance(new_origin - cur_origin);
10183 }
10184 view3D->get_canvas3d()->remove_raycasters_for_picking(SceneRaycaster::EType::Bed);
10185 partplate_list.reset_size(current_width, current_depth, current_height, true, true);
10186 partplate_list.register_raycasters_for_picking(*view3D->get_canvas3d());
10187 }
10188
10189 //BBS: add gcode loading logic in the end
10190 q->m_exported_file = false;
10191 q->skip_thumbnail_invalid = false;
10192 if (load_model && load_config) {
10193 if (model.objects.empty()) {
10194 partplate_list.load_gcode_files();
10195 PartPlate * first_plate = nullptr, *cur_plate = nullptr;
10196 int plate_cnt = partplate_list.get_plate_count();
10197 int index = 0, first_plate_index = 0;
10198 q->m_valid_plates_count = 0;
10199 for (index = 0; index < plate_cnt; index ++)
10200 {
10201 cur_plate = partplate_list.get_plate(index);
10202 if (!first_plate && cur_plate->is_slice_result_valid()) {
10203 first_plate = cur_plate;
10204 first_plate_index = index;
10205 }
10206 if (cur_plate->is_slice_result_valid())
10207 q->m_valid_plates_count ++;
10208 }
10209 if (first_plate&&first_plate->is_slice_result_valid()) {
10210 q->m_exported_file = true;
10211 //select plate 0 as default
10212 q->select_plate(first_plate_index);
10213 //set to 3d tab
10214 q->select_view_3D("Preview");
10215 wxGetApp().mainframe->select_tab(TAB_ID_PREVIEW);
10216 }
10217 else {
10218 //set to 3d tab
10219 q->select_view_3D("3D");
10220 //select plate 0 as default
10221 q->select_plate(0);
10222 }
10223 }
10224 else {
10225 //set to 3d tab
10226 q->select_view_3D("3D");
10227 //select plate 0 as default
10228 q->select_plate(0);
10229 }
10230 }
10231 else {
10232 //always set to 3D after loading files
10233 q->select_view_3D("3D");
10234 wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
10235 }
10236
10237 if (load_model) {
10238 if (!q->m_exported_file && view3D != nullptr) {
10239 // Force a 3D scene refresh after view/plate selection to avoid losing the first load
10240 // on platforms where the GL canvas mapping lags behind model loading.
10241 view3D->reload_scene(true);
10242 view3D->set_as_dirty();
10243 }
10244 if (!silence) wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().make_preferred().string());
10245 // XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames...
10246 }
10247
10248 // automatic selection of added objects
10249 if (!obj_idxs.empty() && view3D != nullptr) {
10250 // update printable state for new volumes on canvas3D
10251 wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_objects(obj_idxs);
10252
10253 if (!load_config) {
10254 Selection& selection = view3D->get_canvas3d()->get_selection();
10255 selection.clear();
10256 for (size_t idx : obj_idxs) {
10257 selection.add_object((unsigned int)idx, false);
10258 }
10259 }
10260 // BBS: update object list selection
10261 this->sidebar->obj_list()->update_selections();
10262
10263 if (view3D->get_canvas3d()->get_gizmos_manager().is_enabled())
10264 // this is required because the selected object changed and the flatten on face an sla support gizmos need to be updated accordingly
10265 view3D->get_canvas3d()->update_gizmos_on_off_state();
10266 }
10267
10269 obj_idxs, model.objects, *notification_manager);
10270
10271 //set designer_model_id
10272 q->model().stl_design_id = designer_model_id;
10273 q->model().stl_design_country = designer_country_code;
10274 //if (!designer_model_id.empty() && q->model().stl_design_id.empty() && !designer_country_code.empty()) {
10275 // q->model().stl_design_id = designer_model_id;
10276 // q->model().stl_design_country = designer_country_code;
10277 //}
10278 //else {
10279 // q->model().stl_design_id = "";
10280 // q->model().stl_design_country = "";
10281 //}
10282
10283 // A CAD project legitimately carries no mesh: the model lives in the feature tree until it is
10284 // committed to the plate. Warning "no geometry data" for one is false, and it is the LAST thing
10285 // a user sees after opening a design they spent an hour on — it reads as "your work is gone"
10286 // when the recipe has in fact just been loaded and the Design tab will rehydrate it. Count a
10287 // recipe that came from THESE files as geometry.
10288 //
10289 // Only where the Design tab can actually show it, though. With the CAD feature switched off
10290 // (or not built) the recipe is still carried through to the next save, but nothing will
10291 // display it, so an empty plate needs saying — and saying why.
10292 bool cad_can_show = false;
10293#ifdef SLIC3R_CAD
10294 cad_can_show = wxGetApp().is_enable_cad_feature();
10295#endif
10296 if (tolal_model_count <= 0 && !q->m_exported_file && (!loaded_cad_recipe || !cad_can_show)) {
10297 dlg.Hide();
10298 if (!is_user_cancel) {
10299 const wxString text = loaded_cad_recipe
10300 ? _L("This project contains a model made in the Design tab and no other geometry. "
10301 "Enable \"CAD feature (experimental)\" in Preferences and restart to see and edit it; "
10302 "it is kept when the project is saved.")
10303 : _L("The file does not contain any geometry data.");
10304 MessageDialog msg(wxGetApp().mainframe, text, _L("Warning"), wxOK | wxICON_WARNING);
10305 msg.ShowModal();
10306 }
10307 }
10308 q->schedule_background_process(true);
10309 q->mark_plate_toolbar_image_dirty();
10310 return obj_idxs;
10311}
#define _(s)
Definition 3mf.cpp:306
#define L(s)
Definition ExtrusionEntity.cpp:25
#define TAB_ID_PREPARE
Definition MainFrame.hpp:60
#define VALIDATE_PRESETS_PRINTER_NOT_FOUND
Definition PresetBundle.hpp:35
#define VALIDATE_PRESETS_MODIFIED_GCODES
Definition PresetBundle.hpp:37
#define VALIDATE_PRESETS_FILAMENTS_NOT_FOUND
Definition PresetBundle.hpp:36
std::vector< int > values
Definition Config.hpp:418
static const float DefaultTipRadius
Definition 3DBed.hpp:73
static void add_simplify_suggestion_notification(const std::vector< size_t > &object_ids, const std::vector< ModelObject * > &objects, NotificationManager &manager)
Definition GLGizmoSimplify.cpp:113
@ WarningNotificationLevel
Definition NotificationManager.hpp:224
bool m_exported_file
Definition Plater.hpp:1097
static wxColour get_next_color_for_filament()
Definition Plater.cpp:8511
@ Bed
Definition SceneRaycaster.hpp:49
static Model read_from_archive(const std::string &input_file, DynamicPrintConfig *config, ConfigSubstitutionContext *config_substitutions, En3mfType &out_file_type, LoadStrategy options=LoadStrategy::AddDefaultInstances, PlateDataPtrs *plate_data=nullptr, std::vector< Preset * > *project_presets=nullptr, Semver *file_version=nullptr, Import3mfProgressFn proFn=nullptr, BBLProject *project=nullptr)
Definition Model.cpp:522
static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config=nullptr, ConfigSubstitutionContext *config_substitutions=nullptr, LoadStrategy options=LoadStrategy::AddDefaultInstances, PlateDataPtrs *plate_data=nullptr, std::vector< Preset * > *project_presets=nullptr, bool *is_xxx=nullptr, Semver *file_version=nullptr, Import3mfProgressFn proFn=nullptr, ImportstlProgressFn stlFn=nullptr, BBLProject *project=nullptr, int plate_id=0)
Definition Model.cpp:318
static Model read_from_step(const std::string &input_file, LoadStrategy options, ImportStepProgressFn stepFn, StepIsUtf8Fn stepIsUtf8Fn, std::function< int(Slic3r::Step &, double &, double &, bool &)> step_mesh_fn, double linear_deflection, double angle_deflection, bool is_split_compound)
Definition Model.cpp:240
PrinterTechnology printer_technology() const
Definition Preset.hpp:399
static void normalize(DynamicPrintConfig &config)
Definition Preset.cpp:524
@ TYPE_PRINTER
Definition Preset.hpp:250
@ TYPE_PRINT
Definition Preset.hpp:246
@ TYPE_FILAMENT
Definition Preset.hpp:248
static boost::optional< Semver > parse(const std::string &str)
Definition Semver.hpp:63
static constexpr size_t MAXIMUM_EXTRUDER_NUMBER
Definition libslic3r.h:70
LoadType
Definition Plater.cpp:484
@ Unknown
Definition Plater.cpp:485
@ LoadGeometry
Definition Plater.cpp:487
wxTopLevelWindow * find_toplevel_parent(wxWindow *window)
Definition GUI_Utils.cpp:155
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:22
static void sync_loaded_project_filament_config(DynamicConfig &proj_cfg)
Definition Plater.cpp:8887
static wxString dots("...", wxConvUTF8)
void updateNozzleCountDisplay(PresetBundle *preset_bundle, int extruder_id, NozzleVolumeType volume_type)
Definition MultiNozzleSync.cpp:263
void read_binary_stl(const std::string &filename, std::string &model_id, std::string &code)
Definition Plater.cpp:8808
void show_substitutions_info(const PresetsConfigSubstitutions &presets_config_substitutions)
Definition GUI.cpp:429
void show_info(wxWindow *parent, const wxString &message, const wxString &title)
Definition GUI.cpp:316
static void log_substitutions(const ConfigSubstitutions &substitutions, const std::string &source)
Definition Plater.cpp:8872
static bool has_importable_texture(const Slic3r::TexturedMesh &textured_mesh)
Definition Plater.cpp:315
Preset * get_printer_preset(const MachineObject *obj)
Definition Plater.cpp:19913
constexpr T deg2rad(const T angle)
Definition Geometry.hpp:312
@ ipZigZag
Definition PrintConfig.hpp:128
@ ipCrossZag
Definition PrintConfig.hpp:128
@ ipLine
Definition PrintConfig.hpp:129
@ ipRectilinear
Definition PrintConfig.hpp:128
@ ipLockedZag
Definition PrintConfig.hpp:128
std::vector< PlateData * > PlateDataPtrs
Definition bbs_3mf.hpp:278
@ Enable
Definition Config.hpp:245
void release_PlateData_list(PlateDataPtrs &plate_data_list)
Definition bbs_3mf.cpp:9740
@ Calib_None
Definition calib.hpp:24
bool unescape_strings_cstyle(const std::string &str, std::vector< std::string > &out)
Definition Config.cpp:173
std::vector< ConfigSubstitution > ConfigSubstitutions
Definition Config.hpp:269
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
void load_config(cereal::BinaryInputArchive &ar, DynamicPrintConfig &config, const CacheDictionary &dict)
Definition PresetCacheFormat.cpp:242
std::vector< PresetConfigSubstitutions > PresetsConfigSubstitutions
Definition Preset.hpp:552
BedType
Definition PrintConfig.hpp:507
PrinterTechnology
Definition Config.hpp:229
constexpr const char * ORCA_PUBLISHED_CONFIG_TAG
Definition bbs_3mf.hpp:195
@ Preset
Definition calib.hpp:39
En3mfType
Definition Model.hpp:751
@ From_Prusa
Definition Model.hpp:754
@ From_Other
Definition Model.hpp:755
@ From_BBS
Definition Model.hpp:753
@ From_Orca
Definition Model.hpp:752
constexpr const char * ORCA_PUBLISHED_TAG
Definition bbs_3mf.hpp:192
constexpr const char * ORCA_PUBLISHED_KEYS_TAG
Definition bbs_3mf.hpp:193
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
const int IMPORT_STAGE_MAX
Definition bbs_3mf.hpp:272
ConfigOptionIntsTempl< false > ConfigOptionInts
Definition Config.hpp:1154
constexpr const char * ORCA_PUBLISHED_MATERIAL_TAG
Definition bbs_3mf.hpp:194
zaa_minimize_perimeter_height ConfigOptionString
Definition PrintConfig.hpp:1702
bool is_published_3mf_flag(const std::string &value)
Definition bbs_3mf.cpp:724
const int LOAD_STEP_STAGE_NUM
Definition STEP.hpp:31
@ LoadModel
Definition bbs_3mf.hpp:222
@ Restore
Definition bbs_3mf.hpp:228
@ LoadConfig
Definition bbs_3mf.hpp:223
@ ImperialUnits
Definition bbs_3mf.hpp:226
@ Silence
Definition bbs_3mf.hpp:225
@ CheckVersion
Definition bbs_3mf.hpp:221
@ LoadAuxiliary
Definition bbs_3mf.hpp:224
double string_to_double_decimal_point(const std::string_view str, size_t *pos)
Definition LocalesUtils.cpp:86
@ wtwRectangle
Definition PrintConfig.hpp:606
void remap_model_filament_slots(Model &model, const std::map< int, int > &slot_relocations)
Definition Model.cpp:4336
@ Z
Definition libslic3r.h:143
zaa_minimize_perimeter_height wipe_tower_y((ConfigOptionFloat, prime_tower_width))((ConfigOptionFloat
std::string escape_strings_cstyle(const std::vector< std::string > &strs)
Definition Config.cpp:99
std::vector< std::string > m_pending_published_keys
Definition Plater.cpp:7187
std::vector< size_t > load_model_objects(const ModelObjectPtrs &model_objects, bool allow_negative_z=false, bool split_object=false, bool auto_drop=true)
Definition Plater.cpp:10315
std::vector< Slic3r::PublishedMaterialEntry > m_pending_material_keys
Definition Plater.cpp:7188
static const std::regex pattern_3mf
Definition Plater.cpp:7297
void load_auxiliary_files()
Definition Plater.cpp:10477
static const std::regex pattern_any_amf
Definition Plater.cpp:7299
void split_object(bool auto_drop=true)
Definition Plater.cpp:10974
bool m_has_pending_published
Definition Plater.cpp:7186
static const std::regex pattern_bundle
Definition Plater.cpp:7296

References _, _L, _u8L, Slic3r::angle(), apply_textured_mesh_import_result(), background_process, Slic3r::GUI::NotificationManager::bbl_show_3mf_warn_notification(), Slic3r::BuildVolume::bed_center(), Slic3r::GUI::Bed3D::build_volume(), Slic3r::Calib_None, Slic3r::ModelObject::center_around_origin(), Slic3r::CheckVersion, Slic3r::PublishedMaterialEntry::color, config, Slic3r::ModelObject::config, Slic3r::ModelVolume::config, Slic3r::GUI::Bed3D::Axes::DefaultTipRadius, Slic3r::Geometry::deg2rad(), Slic3r::Model::design_info, Slic3r::GUI::dots(), Slic3r::ConfigSubstitutionContext::empty(), Slic3r::DynamicConfig::empty(), Slic3r::Enable, Slic3r::ModelObject::ensure_on_bed(), Slic3r::escape_strings_cstyle(), Slic3r::ModelConfig::extruder(), Slic3r::PaintedMesh::face_colors, Slic3r::GUI::Plater::priv::TextureImportResult::fallback_to_geometry_only, Slic3r::GUI::Plater::priv::TextureImportResult::fallback_warning, Slic3r::PublishedMaterialEntry::filament_id, Slic3r::PresetBundle::filament_presets, Slic3r::PublishedMaterialEntry::filament_type, Slic3r::PublishedMaterialEntry::filament_vendor, Slic3r::GUI::find_toplevel_parent(), Slic3r::GUI::format(), Slic3r::GUI::format_wxstr(), Slic3r::From_BBS, Slic3r::From_Orca, Slic3r::From_Other, Slic3r::GUI::from_path(), Slic3r::From_Prusa, Slic3r::GUI::from_u8(), Slic3r::PublishedMaterialEntry::full, Slic3r::PublishedMaterialEntry::full_keys, StepMeshDialog::get_angle_deflection(), Slic3r::GUI::MsgDialog::get_checkbox_state(), StepMeshDialog::get_linear_deflection(), Slic3r::GUI::Plater::get_next_color_for_filament(), StepMeshDialog::get_split_compound_value(), Slic3r::ConfigOption::getInt(), Slic3r::ModelConfig::has(), Slic3r::GUI::has_importable_texture(), Slic3r::ImperialUnits, Slic3r::IMPORT_STAGE_MAX, Slic3r::ModelObject::instances, Slic3r::GUI::into_u8(), Slic3r::ipCrossZag, Slic3r::ipLine, Slic3r::ipLockedZag, Slic3r::ipRectilinear, Slic3r::ipZigZag, Slic3r::PresetBundle::is_bbl_vendor(), Slic3r::is_published_3mf_flag(), Slic3r::PublishedMaterialEntry::keys, L, load_auxiliary_files(), Slic3r::load_config(), Slic3r::PresetBundle::load_config_model(), Slic3r::ConfigBase::load_from_ini_string(), load_model_objects(), Slic3r::PresetBundle::load_project_embedded_presets(), Slic3r::LOAD_STEP_STAGE_NUM, Slic3r::LoadAuxiliary, Slic3r::LoadConfig, Slic3r::GUI::LoadGeometry, Slic3r::LoadModel, Slic3r::GUI::log_substitutions(), Slic3r::PublishedConfig::material_keys, Slic3r::PublishedConfig::material_replacements, MAXIMUM_EXTRUDER_NUMBER, Slic3r::Semver::min(), Slic3r::PublishedConfig::mixed_slot_relocations, model, Slic3r::Model::model_info, Slic3r::ModelObject::name, Slic3r::Preset::normalize(), Slic3r::DynamicConfig::opt(), Slic3r::DynamicConfig::opt_string(), Slic3r::ConfigBase::option(), Slic3r::ModelConfig::option(), Slic3r::ORCA_PUBLISHED_CONFIG_TAG, Slic3r::ORCA_PUBLISHED_KEYS_TAG, Slic3r::ORCA_PUBLISHED_MATERIAL_TAG, Slic3r::ORCA_PUBLISHED_TAG, Slic3r::GUI::Plater::priv::TextureImportResult::painted, Slic3r::Semver::parse(), partplate_list, pattern_3mf, pattern_any_amf, pattern_bundle, Slic3r::GUI::plater(), Slic3r::Model::plates_custom_gcodes, Slic3r::PublishedMaterialEntry::preset_name, printer_technology, Slic3r::Preset::printer_technology(), Slic3r::PresetBundle::project_config, Slic3r::ptSLA, Slic3r::PublishedMaterialEntry::publish_color, Slic3r::PublishedMaterialEntry::publish_type, Slic3r::PublishedMaterialEntry::publish_type_value, Slic3r::PublishedConfig::published, Slic3r::PublishedConfig::published_keys, q, Slic3r::GUI::read_binary_stl(), Slic3r::Model::read_from_archive(), Slic3r::Model::read_from_file(), Slic3r::Model::read_from_step(), Slic3r::release_PlateData_list(), Slic3r::remap_model_filament_slots(), Slic3r::ModelConfig::reset(), Slic3r::Restore, run_textured_mesh_import_dialog(), Slic3r::AppConfig::set(), Slic3r::ModelConfig::set(), Slic3r::GUI::MsgDialog::SetButtonLabel(), Slic3r::PublishedMaterialEntry::setting_id, Slic3r::GUI::MsgDialog::show_dsa_button(), Slic3r::GUI::show_error(), Slic3r::GUI::show_info(), Slic3r::GUI::show_substitutions_info(), Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, Slic3r::Silence, Slic3r::ConfigOptionVector< T >::size(), Slic3r::PublishedConfig::skipped_keys, SLIC3R_APP_FULL_NAME, Slic3r::PublishedMaterialEntry::slot, Slic3r::string_to_double_decimal_point(), Slic3r::ConfigSubstitutionContext::substitutions, Slic3r::GUI::sync_loaded_project_filament_config(), Slic3r::Semver::to_string(), Slic3r::Semver::to_string_sf(), Slic3r::trace(), Slic3r::Preset::TYPE_FILAMENT, Slic3r::Preset::TYPE_PRINT, Slic3r::unescape_strings_cstyle(), Slic3r::GUI::Unknown, Slic3r::ConfigSubstitutionContext::unrecogized_keys, Slic3r::GUI::ProgressDialog::Update(), Slic3r::GUI::Preview::update_gcode_result(), Slic3r::GUI::updateNozzleCountDisplay(), Slic3r::PresetBundle::validate_presets(), VALIDATE_PRESETS_FILAMENTS_NOT_FOUND, VALIDATE_PRESETS_MODIFIED_GCODES, VALIDATE_PRESETS_PRINTER_NOT_FOUND, Slic3r::ConfigOptionSingle< T >::value, Slic3r::ConfigOptionVector< T >::values, Slic3r::ConfigOptionVector< double >::values, Slic3r::ConfigOptionVector< int >::values, Slic3r::ModelObject::volumes, Slic3r::GUI::NotificationManager::WarningNotificationLevel, Slic3r::GUI::ProgressDialog::WasCancelled(), Slic3r::wipe_tower_y(), Slic3r::wtwRectangle, and Slic3r::Z.

◆ load_model_objects()

std::vector< size_t > Slic3r::GUI::Plater::priv::load_model_objects ( const ModelObjectPtrs & model_objects,
bool allow_negative_z = false,
bool split_object = false,
bool auto_drop = true )
10316{
10317 const Vec3d bed_size = Slic3r::to_3d(this->bed.build_volume().bounding_volume2d().size(), 1.0) - 2.0 * Vec3d::Ones();
10318
10319#ifndef AUTOPLACEMENT_ON_LOAD
10320 // bool need_arrange = false;
10321#endif /* AUTOPLACEMENT_ON_LOAD */
10322 bool scaled_down = false;
10323 std::vector<size_t> obj_idxs;
10324 unsigned int obj_count = model.objects.size();
10325
10326#ifdef AUTOPLACEMENT_ON_LOAD
10327 ModelInstancePtrs new_instances;
10328#endif /* AUTOPLACEMENT_ON_LOAD */
10329 for (ModelObject *model_object : model_objects) {
10330 auto *object = model.add_object(*model_object);
10331 object->sort_volumes(true);
10332 std::string object_name = object->name.empty() ? fs::path(object->input_file).filename().string() : object->name;
10333 obj_idxs.push_back(obj_count++);
10334
10335 if (model_object->instances.empty()) {
10336#ifdef AUTOPLACEMENT_ON_LOAD
10337 object->center_around_origin();
10338 new_instances.emplace_back(object->add_instance());
10339#else /* AUTOPLACEMENT_ON_LOAD */
10340 // if object has no defined position(s) we need to rearrange everything after loading
10341 // need_arrange = true;
10342 // add a default instance and center object around origin
10343 object->center_around_origin(); // also aligns object to Z = 0
10344 ModelInstance* instance = object->add_instance();
10345
10346 //BBS calc transformation
10347 Geometry::Transformation t = instance->get_transformation();
10348 instance->set_offset(Slic3r::to_3d(this->bed.build_volume().bed_center(), -object->origin_translation(2)));
10349#endif /* AUTOPLACEMENT_ON_LOAD */
10350 }
10351
10352 //BBS: when the object is too large, let the user choose whether to scale it down
10353 for (size_t i = 0; i < object->instances.size(); ++i) {
10354 ModelInstance* instance = object->instances[i];
10355 const Vec3d size = object->instance_bounding_box(i).size();
10356 const Vec3d ratio = size.cwiseQuotient(bed_size);
10357 const double max_ratio = std::max(ratio(0), ratio(1));
10358 if (max_ratio > 10000) {
10359 MessageDialog dlg(q, _L("Your object appears to be too large, do you want to scale it down to fit the print bed automatically?"), _L("Object too large"),
10360 wxICON_QUESTION | wxYES);
10361 int answer = dlg.ShowModal();
10362 // the size of the object is too big -> this could lead to overflow when moving to clipper coordinates,
10363 // so scale down the mesh
10364 object->scale_mesh_after_creation(1. / max_ratio);
10365 object->origin_translation = Vec3d::Zero();
10366 object->center_around_origin();
10367 scaled_down = true;
10368 break;
10369 }
10370 else if (max_ratio > 10) {
10371 MessageDialog dlg(q, _L("Your object appears to be too large, do you want to scale it down to fit the print bed automatically?"), _L("Object too large"),
10372 wxICON_QUESTION | wxYES_NO);
10373 int answer = dlg.ShowModal();
10374 if (answer == wxID_YES) {
10375 instance->set_scaling_factor(instance->get_scaling_factor() / max_ratio);
10376 scaled_down = true;
10377 }
10378 }
10379 }
10380
10381 if (!auto_drop) {
10382 object->auto_drop = false;
10383
10384 // if under the bed, move over the bed
10385 double dist_to_bed = std::min(object->min_z(), double(0));
10386 object->translate_instances(Vec3d(0, 0, -dist_to_bed));
10387 }
10388 else {
10389 object->ensure_on_bed(allow_negative_z);
10390 }
10391
10392 if (!split_object) {
10393 //BBS initial assemble transformation
10394 for (ModelObject* model_object : model.objects) {
10395 //BBS initialize assemble transformation
10396 for (int i = 0; i < model_object->instances.size(); i++) {
10397 if (!model_object->instances[i]->is_assemble_initialized()) {
10398 model_object->instances[i]->set_assemble_transformation(model_object->instances[i]->get_transformation());
10399 }
10400 }
10401 }
10402 }
10403 }
10404
10405 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", loaded objects, begin to auto placement");
10406#ifdef AUTOPLACEMENT_ON_LOAD
10407#if 0
10408 // FIXME distance should be a config value /////////////////////////////////
10409 auto min_obj_distance = static_cast<coord_t>(6/SCALING_FACTOR);
10410 const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("printable_area");
10411 assert(bed_shape_opt);
10412 auto& bedpoints = bed_shape_opt->values;
10413 Polyline bed; bed.points.reserve(bedpoints.size());
10414 for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
10415
10416 // BBS: get wipe tower of current plate
10417 int cur_plate_idx = partplate_list.get_curr_plate_index();
10418 std::pair<bool, GLCanvas3D::WipeTowerInfo> wti = view3D->get_canvas3d()->get_wipe_tower_info(cur_plate_idx);
10419
10420 arr::find_new_position(model, new_instances, min_obj_distance, bed, wti);
10421
10422 // it remains to move the wipe tower:
10423 view3D->get_canvas3d()->arrange_wipe_tower(wti);
10424#else
10425 // BBS: find an empty cell to put the copied object
10426 for (auto& instance : new_instances) {
10427 auto offset = instance->get_offset();
10428 auto start_point = this->bed.build_volume().bed_center();
10429 bool plate_empty = partplate_list.get_curr_plate()->empty();
10430 Vec3d displacement;
10431 if (plate_empty)
10432 displacement = {start_point(0), start_point(1), offset(2)};
10433 else {
10434 auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
10435 displacement = {empty_cell.x(), empty_cell.y(), offset(2)};
10436 }
10437 instance->set_offset(displacement);
10438 }
10439#endif
10440
10441#endif /* AUTOPLACEMENT_ON_LOAD */
10442
10443 //BBS: remove the auto scaled_down logic when load models
10444 //if (scaled_down) {
10445 // GUI::show_info(q,
10446 // _L("Your object appears to be too large, so it was automatically scaled down to fit your print bed."),
10447 // _L("Object too large?"));
10448 //}
10449
10450 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", finished auto placement, before add_objects_to_list");
10451 notification_manager->close_notification_of_type(NotificationType::UpdatedItemsInfo);
10452
10453 if (obj_idxs.size() > 1) {
10454 std::vector<size_t> obj_idxs_1 (obj_idxs.begin(), obj_idxs.end() - 1);
10455
10456 wxGetApp().obj_list()->add_objects_to_list(obj_idxs_1, false);
10457 wxGetApp().obj_list()->add_object_to_list(obj_idxs[obj_idxs.size() - 1]);
10458 }
10459 else
10460 wxGetApp().obj_list()->add_objects_to_list(obj_idxs);
10461
10462 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", after add_objects_to_list");
10463 update();
10464 // Update InfoItems in ObjectList after update() to use of a correct value of the GLCanvas3D::is_sinking(),
10465 // which is updated after a view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH) call
10466 for (const size_t idx : obj_idxs)
10467 wxGetApp().obj_list()->update_info_items(idx);
10468
10470
10472
10473 return obj_idxs;
10474}
static Point new_scale(coordf_t x, coordf_t y)
Definition Point.hpp:214
int64_t coord_t
Definition libslic3r.h:48
@ UpdatedItemsInfo
Definition NotificationManager.hpp:140
Eigen::Matrix< typename Derived::Scalar, 3, 1, Eigen::DontAlign > to_3d(const Eigen::MatrixBase< Derived > &pt, const typename Derived::Scalar z)
Definition Point.hpp:153
Slic3r::Polygons offset(const Slic3r::Polygon &polygon, const float delta, JoinType joinType, double miterLimit)
Definition ClipperUtils.cpp:582
std::vector< ModelInstance * > ModelInstancePtrs
Definition Model.hpp:140

References _L, bed, Slic3r::BuildVolume::bed_center(), Slic3r::BuildVolume::bounding_volume2d(), Slic3r::GUI::Bed3D::build_volume(), config, Slic3r::ModelInstance::get_scaling_factor(), Slic3r::ModelInstance::get_transformation(), Slic3r::ModelObject::instances, model, Slic3r::Point::new_scale(), notification_manager, object_list_changed(), Slic3r::offset(), partplate_list, q, SCALING_FACTOR, schedule_background_process(), Slic3r::ModelInstance::set_offset(), Slic3r::ModelInstance::set_scaling_factor(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::BoundingBoxBase< PointType, APointsType >::size(), split_object(), Slic3r::to_3d(), update(), Slic3r::GUI::UpdatedItemsInfo, and view3D.

Referenced by load_files(), and split_object().

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

◆ mirror()

void Slic3r::GUI::Plater::priv::mirror ( Axis axis)
10936{
10937 view3D->mirror_selection(axis);
10938}

References view3D.

◆ need_update()

bool Slic3r::GUI::Plater::priv::need_update ( ) const
inline
7308{ return m_need_update; }
bool m_need_update
Definition Plater.cpp:7241

References m_need_update.

Referenced by set_need_update(), and undo_redo_to().

Here is the caller graph for this function:

◆ object_list_changed()

void Slic3r::GUI::Plater::priv::object_list_changed ( )
10672{
10673 const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty());
10674 // XXX: is this right?
10675 //const bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() == ModelInstancePVS_Inside;
10676 ObjectFilamentResults object_results;
10677 bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state(&object_results) != ModelInstancePVS_Partly_Outside;
10678 model_fits = model_fits && object_results.filaments.empty();
10679
10680 PartPlate* part_plate = partplate_list.get_curr_plate();
10681
10682 // BBS
10683 //sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits && part_plate->has_printable_instances());
10684 // A mixed filament with deleted or type-mismatched components cannot be resolved at slicing
10685 // time, so block the slice buttons the same way MainFrame::get_enable_slice_status() does.
10686 bool mixed_broken = sidebar->has_broken_mixed_filament();
10687 bool can_slice = !model.objects.empty() && !export_in_progress && model_fits && part_plate->has_printable_instances()
10688 && !mixed_broken;
10689 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": can_slice %1%, model_fits= %2%, export_in_progress %3%, has_printable_instances %4% ")%can_slice %model_fits %export_in_progress %part_plate->has_printable_instances();
10690 main_frame->update_slice_print_status(MainFrame::eEventObjectUpdate, can_slice);
10691
10692 wxGetApp().params_panel()->notify_object_config_changed();
10693
10694 q->mark_plate_toolbar_image_dirty();
10695}
@ eEventObjectUpdate
Definition MainFrame.hpp:337
@ ModelInstancePVS_Partly_Outside
Definition Model.hpp:1413

References Slic3r::GUI::MainFrame::eEventObjectUpdate, Slic3r::ObjectFilamentResults::filaments, Slic3r::GUI::PartPlate::has_printable_instances(), Slic3r::BackgroundSlicingProcess::is_export_scheduled(), main_frame, model, Slic3r::ModelInstancePVS_Partly_Outside, partplate_list, q, sidebar, and view3D.

Referenced by load_model_objects().

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

◆ on_3dcanvas_mouse_dragging_finished()

void Slic3r::GUI::Plater::priv::on_3dcanvas_mouse_dragging_finished ( SimpleEvent & )
14284{
14286 delayed_scene_refresh = false;
14288 }
14289
14290 //partplate_list.reload_all_objects();
14291}
void update_sla_scene()
Definition Plater.cpp:11776

References delayed_scene_refresh, and update_sla_scene().

Here is the call graph for this function:

◆ on_3dcanvas_mouse_dragging_started()

void Slic3r::GUI::Plater::priv::on_3dcanvas_mouse_dragging_started ( SimpleEvent & )
14277{
14278 view3D->get_canvas3d()->reset_sequential_print_clearance();
14279}

References view3D.

◆ on_action_add()

void Slic3r::GUI::Plater::priv::on_action_add ( SimpleEvent & )
13550{
13551 if (q != nullptr) {
13552 //q->add_model();
13553 //BBS open file in toolbar add
13554 q->add_file();
13555 }
13556}

References q.

◆ on_action_add_plate()

void Slic3r::GUI::Plater::priv::on_action_add_plate ( SimpleEvent & )
13560{
13561 if (q != nullptr)
13562 q->add_plate();
13563}

References q.

◆ on_action_del_plate()

void Slic3r::GUI::Plater::priv::on_action_del_plate ( SimpleEvent & )
13567{
13568 if (q != nullptr) {
13569 q->delete_plate();
13570 //q->get_camera().select_view("topfront");
13571 //q->get_camera().requires_zoom_to_plate = REQUIRES_ZOOM_TO_ALL_PLATE;
13572 }
13573}

References q.

◆ on_action_download_project()

void Slic3r::GUI::Plater::priv::on_action_download_project ( wxCommandEvent & evt)
14032{
14033 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received download project event\n" ;
14034 if (q != nullptr) {
14035 q->download_project(evt.GetString());
14036 }
14037}

References q.

◆ on_action_export_all_sliced_file()

void Slic3r::GUI::Plater::priv::on_action_export_all_sliced_file ( SimpleEvent & )
13993{
13994 if (q != nullptr) {
13995 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export all sliced file event\n";
13996 q->export_gcode_3mf(true);
13997 }
13998}

References q.

◆ on_action_export_gcode()

void Slic3r::GUI::Plater::priv::on_action_export_gcode ( SimpleEvent & )
13969{
13970 if (q != nullptr) {
13971 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export gcode event\n" ;
13972 q->export_gcode(false);
13973 }
13974}

References q.

◆ on_action_export_sliced_file()

void Slic3r::GUI::Plater::priv::on_action_export_sliced_file ( SimpleEvent & )
13985{
13986 if (q != nullptr) {
13987 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export sliced file event\n" ;
13988 q->export_gcode_3mf();
13989 }
13990}

References q.

◆ on_action_export_to_sdcard()

void Slic3r::GUI::Plater::priv::on_action_export_to_sdcard ( SimpleEvent & )
private
14001{
14002 if (q != nullptr) {
14003 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export sliced file event\n";
14004 q->send_to_printer();
14005 }
14006}

References q.

◆ on_action_export_to_sdcard_all()

void Slic3r::GUI::Plater::priv::on_action_export_to_sdcard_all ( SimpleEvent & )
private
14009{
14010 if (q != nullptr) {
14011 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export sliced file event\n";
14012 q->send_to_printer(true);
14013 }
14014}

References q.

◆ on_action_layersediting()

void Slic3r::GUI::Plater::priv::on_action_layersediting ( SimpleEvent & )
15149{
15150 // Sub-layer splitting divides each layer by the mix ratio, so a variable layer height profile
15151 // makes those sub-layer heights uneven and degrades the blend. ConfigManipulation warns for the
15152 // opposite order, when the option is switched on while a variable profile already exists.
15153 if (!view3D->is_layers_editing_enabled()) {
15154 const auto& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
15155 if (print_config.opt_bool("enable_mixed_color_sublayer")) {
15156 if (wxGetApp().app_config->get("no_warn_mixed_sublayer_variable_layer") != "1") {
15157 MessageDialog dlg(q,
15158 _L("Using variable layer height together with mixed color sublayer may result in poor color mixing quality."),
15159 _L("Warning"), wxICON_WARNING | wxOK);
15160 dlg.show_dsa_button();
15161 dlg.ShowModal();
15162 if (dlg.get_checkbox_state())
15163 wxGetApp().app_config->set("no_warn_mixed_sublayer_variable_layer", "1");
15164 }
15165 }
15166 }
15167 view3D->enable_layers_editing(!view3D->is_layers_editing_enabled());
15168 notification_manager->set_move_from_overlay(view3D->is_layers_editing_enabled());
15169}

References _L, Slic3r::GUI::MsgDialog::get_checkbox_state(), notification_manager, q, Slic3r::GUI::MsgDialog::show_dsa_button(), Slic3r::GUI::DPIAware< P >::ShowModal(), and view3D.

Referenced by selection_changed().

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

◆ on_action_open_project()

void Slic3r::GUI::Plater::priv::on_action_open_project ( SimpleEvent & )
13577{
13578 if (q != nullptr) {
13579 q->load_project();
13580 }
13581}

References q.

◆ on_action_print_all()

void Slic3r::GUI::Plater::priv::on_action_print_all ( SimpleEvent & )
13955{
13956 if (q != nullptr) {
13957 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received print all event\n" ;
13958 }
13959
13960 PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
13961 if (preset_bundle.use_bbl_network() || wxGetApp().app_config->get_bool("use_printer_agents")) {
13963 } else {
13964 q->send_gcode_legacy(PLATE_ALL_IDX, nullptr);
13965 }
13966}
#define PLATE_ALL_IDX
Definition PartPlate.hpp:57
void open_machine_select_dialog(int plate_idx, PrintFromType print_type=PrintFromType::FROM_NORMAL)
Definition Plater.cpp:13845

References open_machine_select_dialog(), PLATE_ALL_IDX, q, and Slic3r::PresetBundle::use_bbl_network().

Here is the call graph for this function:

◆ on_action_print_plate()

void Slic3r::GUI::Plater::priv::on_action_print_plate ( SimpleEvent & )
13832{
13833 if (q != nullptr) {
13834 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received print plate event\n" ;
13835 }
13836
13837 PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
13838 if (preset_bundle.use_bbl_network() || wxGetApp().app_config->get_bool("use_printer_agents")) {
13839 open_machine_select_dialog(partplate_list.get_curr_plate_index());
13840 } else {
13841 q->send_gcode_legacy(PLATE_CURRENT_IDX, nullptr);
13842 }
13843}
#define PLATE_CURRENT_IDX
Definition PartPlate.hpp:56

References open_machine_select_dialog(), partplate_list, PLATE_CURRENT_IDX, q, and Slic3r::PresetBundle::use_bbl_network().

Here is the call graph for this function:

◆ on_action_print_plate_from_sdcard()

void Slic3r::GUI::Plater::priv::on_action_print_plate_from_sdcard ( SimpleEvent & )
13864{
13865 if (q != nullptr) {
13866 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received print plate event\n";
13867 }
13868
13869 //BBS
13871}
@ FROM_SDCARD_VIEW
Definition DevDefs.h:174

References Slic3r::GUI::FROM_SDCARD_VIEW, open_machine_select_dialog(), and q.

Here is the call graph for this function:

◆ on_action_request_model_id()

void Slic3r::GUI::Plater::priv::on_action_request_model_id ( wxCommandEvent & evt)
14024{
14025 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received import model id event\n" ;
14026 if (q != nullptr) {
14027 q->import_model_id(evt.GetString());
14028 }
14029}

References q.

◆ on_action_select_sliced_plate()

void Slic3r::GUI::Plater::priv::on_action_select_sliced_plate ( wxCommandEvent & evt)
13946{
13947 if (q != nullptr) {
13948 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received select sliced plate event\n" ;
13949 }
13950 bool skip_zoom = evt.GetExtraLong() == 1;
13951 q->select_sliced_plate(evt.GetInt(), skip_zoom);
13952}

References q.

◆ on_action_send_gcode()

void Slic3r::GUI::Plater::priv::on_action_send_gcode ( SimpleEvent & )
13977{
13978 if (q != nullptr) {
13979 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received export gcode event\n" ;
13980 q->send_gcode_legacy();
13981 }
13982}

References q.

◆ on_action_send_to_multi_machine()

void Slic3r::GUI::Plater::priv::on_action_send_to_multi_machine ( SimpleEvent & )
13856{
13857 if (!m_send_multi_dlg)
13858 m_send_multi_dlg = new SendMultiMachinePage(q);
13859 m_send_multi_dlg->prepare(partplate_list.get_curr_plate_index());
13860 m_send_multi_dlg->ShowModal();
13861}
SendMultiMachinePage * m_send_multi_dlg
Definition Plater.cpp:7181

References m_send_multi_dlg, partplate_list, and q.

◆ on_action_send_to_printer()

void Slic3r::GUI::Plater::priv::on_action_send_to_printer ( bool isall = false)
13932{
13933 if (!m_send_to_sdcard_dlg) m_send_to_sdcard_dlg = new SendToPrinterDialog(q);
13934 if (isall) {
13936 }
13937 else {
13938 m_send_to_sdcard_dlg->prepare(partplate_list.get_curr_plate_index());
13939 }
13940
13941 m_send_to_sdcard_dlg->ShowModal();
13942}

References m_send_to_sdcard_dlg, partplate_list, PLATE_ALL_IDX, and q.

◆ on_action_slice_all()

void Slic3r::GUI::Plater::priv::on_action_slice_all ( SimpleEvent & )
13779{
13780 if (q != nullptr) {
13781 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received slice project event\n" ;
13782 // IMEX parallel mode warnings (all plates)
13783 if (wxGetApp().app_config->get("imex_pre_slice_warnings") != "false") {
13784 wxString combined_msg;
13785 int plate_count = partplate_list.get_plate_count();
13786 for (int i = 0; i < plate_count; ++i) {
13787 PartPlate* plate = partplate_list.get_plate(i);
13788 std::vector<wxString> warnings = collect_imex_warnings(plate);
13789 if (warnings.empty()) continue;
13790 combined_msg += wxString::Format(_L("Plate %d:\n"), i + 1);
13791 for (const wxString& w : warnings)
13792 combined_msg += L" \u2022 " + w + "\n";
13793 combined_msg += "\n";
13794 }
13795 if (!combined_msg.empty()) {
13796 wxString msg = _L("The following IDEX/IQEX parallel mode concerns were detected:\n\n")
13797 + combined_msg
13798 + _L("Continue slicing?");
13799 RichMessageDialog dlg(q, msg, _L("IDEX/IQEX Parallel Mode Warning"), wxICON_WARNING | wxYES | wxNO);
13800 dlg.ShowCheckBox(_L("Don't show these warnings again"));
13801 int result = dlg.ShowModal();
13802 if (dlg.IsCheckBoxChecked())
13803 wxGetApp().app_config->set("imex_pre_slice_warnings", "false");
13804 if (result != wxID_YES) {
13805 q->select_view_3D("3D");
13806 return;
13807 }
13808 }
13809 }
13810
13811 //BBS update extruder params and speed table before slicing
13812 const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
13813 auto& print = q->get_partplate_list().get_current_fff_print();
13814 auto print_config = print.config();
13815 int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
13816
13817 Model::setExtruderParams(config, numExtruders);
13818 Model::setPrintSpeedTable(config, print_config);
13819 m_slice_all = true;
13822 //select plate
13823 q->select_plate(m_cur_slice_plate);
13824 q->reslice();
13825 q->select_view_3D("Preview");
13826 //BBS: wish to select all plates stats item
13827 preview->get_canvas3d()->_update_select_plate_toolbar_stats_item(true);
13828 }
13829}
static void setPrintSpeedTable(const DynamicPrintConfig &config, const PrintConfig &print_config)
Definition Model.cpp:3209
static void setExtruderParams(const DynamicPrintConfig &config, int extruders_count)
Definition Model.cpp:3267
static std::vector< wxString > collect_imex_warnings(PartPlate *plate)
Definition Plater.cpp:13598
int m_cur_slice_plate
Definition Plater.cpp:7237
bool m_slice_all_only_has_gcode
Definition Plater.cpp:7239
bool m_slice_all
Definition Plater.cpp:7224

References _L, Slic3r::GUI::collect_imex_warnings(), config, Slic3r::GUI::RichMessageDialog::IsCheckBoxChecked(), L, m_cur_slice_plate, m_slice_all, m_slice_all_only_has_gcode, partplate_list, preview, q, Slic3r::Model::setExtruderParams(), Slic3r::Model::setPrintSpeedTable(), Slic3r::GUI::RichMessageDialog::ShowCheckBox(), and Slic3r::GUI::RichMessageDialog::ShowModal().

Here is the call graph for this function:

◆ on_action_slice_plate()

void Slic3r::GUI::Plater::priv::on_action_slice_plate ( SimpleEvent & )
13738{
13739 if (q != nullptr) {
13740 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received slice plate event\n" ;
13741 // IMEX parallel mode warnings (current plate only)
13742 if (wxGetApp().app_config->get("imex_pre_slice_warnings") != "false") {
13743 PartPlate* plate = partplate_list.get_curr_plate();
13744 std::vector<wxString> warnings = collect_imex_warnings(plate);
13745 if (!warnings.empty()) {
13746 int plate_num = partplate_list.get_curr_plate_index() + 1;
13747 wxString msg = wxString::Format(_L("Plate %d has IDEX/IQEX parallel mode active with the following concerns:\n\n"), plate_num);
13748 for (const wxString& w : warnings)
13749 msg += L"\u2022 " + w + "\n\n";
13750 msg += _L("Continue slicing?");
13751 RichMessageDialog dlg(q, msg, _L("IDEX/IQEX Parallel Mode Warning"), wxICON_WARNING | wxYES | wxNO);
13752 dlg.ShowCheckBox(_L("Don't show these warnings again"));
13753 int result = dlg.ShowModal();
13754 if (dlg.IsCheckBoxChecked())
13755 wxGetApp().app_config->set("imex_pre_slice_warnings", "false");
13756 if (result != wxID_YES) {
13757 q->select_view_3D("3D");
13758 return;
13759 }
13760 }
13761 }
13762
13763 //BBS update extruder params and speed table before slicing
13764 const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
13765 auto& print = q->get_partplate_list().get_current_fff_print();
13766 auto print_config = print.config();
13767 int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
13768
13769 Model::setExtruderParams(config, numExtruders);
13770 Model::setPrintSpeedTable(config, print_config);
13771 m_slice_all = false;
13772 q->reslice();
13773 q->select_view_3D("Preview");
13774 }
13775}

References _L, Slic3r::GUI::collect_imex_warnings(), config, Slic3r::GUI::RichMessageDialog::IsCheckBoxChecked(), L, m_slice_all, partplate_list, q, Slic3r::Model::setExtruderParams(), Slic3r::Model::setPrintSpeedTable(), Slic3r::GUI::RichMessageDialog::ShowCheckBox(), and Slic3r::GUI::RichMessageDialog::ShowModal().

Here is the call graph for this function:

◆ on_action_split_objects()

void Slic3r::GUI::Plater::priv::on_action_split_objects ( SimpleEvent & )
14048{
14049 split_object();
14050}

References Slic3r::GUI::Plater::split_object().

Here is the call graph for this function:

◆ on_action_split_volumes()

void Slic3r::GUI::Plater::priv::on_action_split_volumes ( SimpleEvent & )
14053{
14054 split_volume();
14055}
void split_volume()
Definition Plater.cpp:11041

References Slic3r::GUI::Plater::split_volume().

Here is the call graph for this function:

◆ on_add_custom_filament()

void Slic3r::GUI::Plater::priv::on_add_custom_filament ( ColorEvent & evt)
15222{
15223 sidebar->add_custom_filament(evt.data);
15224}

References Slic3r::GUI::Event< T >::data, and sidebar.

◆ on_add_filament()

void Slic3r::GUI::Plater::priv::on_add_filament ( SimpleEvent & evt)
15213 {
15214 sidebar->add_filament();
15215}

References sidebar.

◆ on_apple_change_color_mode()

void Slic3r::GUI::Plater::priv::on_apple_change_color_mode ( wxSysColourChangedEvent & evt)
14144 {
14145 m_is_dark = wxSystemSettings::GetAppearance().IsDark();
14146 if (view3D->get_canvas3d() && view3D->get_canvas3d()->is_initialized()) {
14147 view3D->get_canvas3d()->on_change_color_mode(m_is_dark);
14148 preview->get_canvas3d()->on_change_color_mode(m_is_dark);
14149 assemble_view->get_canvas3d()->on_change_color_mode(m_is_dark);
14150 }
14151
14152 m_aui_mgr.apply_color_mode();
14153}

References assemble_view, m_aui_mgr, m_is_dark, preview, and view3D.

◆ on_change_color_mode()

void Slic3r::GUI::Plater::priv::on_change_color_mode ( SimpleEvent & evt)
14155 {
14156 m_is_dark = wxGetApp().app_config->get("dark_color_mode") == "1";
14157 sidebar->on_change_color_mode(m_is_dark);
14158 view3D->get_canvas3d()->on_change_color_mode(m_is_dark);
14159 preview->get_canvas3d()->on_change_color_mode(m_is_dark);
14160 assemble_view->get_canvas3d()->on_change_color_mode(m_is_dark);
14161 if (m_send_to_sdcard_dlg) m_send_to_sdcard_dlg->on_change_color_mode();
14162
14163 m_aui_mgr.apply_color_mode();
14164}

References assemble_view, m_aui_mgr, m_is_dark, m_send_to_sdcard_dlg, preview, sidebar, and view3D.

◆ on_combobox_select()

void Slic3r::GUI::Plater::priv::on_combobox_select ( wxCommandEvent & evt)
12863{
12864 PlaterPresetComboBox* preset_combo_box = dynamic_cast<PlaterPresetComboBox*>(evt.GetEventObject());
12865 if (preset_combo_box) {
12866 this->on_select_preset(evt);
12867 sidebar->update_printer_thumbnail();
12868 }
12869 else {
12870 this->on_select_bed_type(evt);
12871 }
12872}
void on_select_preset(wxCommandEvent &)
Definition Plater.cpp:12927
void on_select_bed_type(wxCommandEvent &)
Definition Plater.cpp:12874

References on_select_bed_type(), on_select_preset(), and sidebar.

Here is the call graph for this function:

◆ on_create_filament()

void Slic3r::GUI::Plater::priv::on_create_filament ( SimpleEvent & )
15172{
15173 CreateFilamentPresetDialog dlg(wxGetApp().mainframe);
15174 int res = dlg.ShowModal();
15175 if (wxID_OK == res) {
15176 wxGetApp().mainframe->update_side_preset_ui();
15178 sidebar->update_all_preset_comboboxes();
15179 CreatePresetSuccessfulDialog success_dlg(wxGetApp().mainframe, SuccessType::FILAMENT);
15180 int res = success_dlg.ShowModal();
15181 }
15182}
@ FILAMENT
Definition CreatePresetsDialog.hpp:229
void update_ui_from_settings()
Definition Plater.cpp:8773

References Slic3r::GUI::FILAMENT, Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, and Slic3r::GUI::Plater::update_ui_from_settings().

Here is the call graph for this function:

◆ on_delete_filament()

void Slic3r::GUI::Plater::priv::on_delete_filament ( SimpleEvent & evt)
15217 {
15218 sidebar->delete_filament();
15219}

References sidebar.

◆ on_export_began()

void Slic3r::GUI::Plater::priv::on_export_began ( wxCommandEvent & evt)
13249{
13252}
bool warnings_dialog()
Definition Plater.cpp:13319

References show_warning_dialog, and warnings_dialog().

Here is the call graph for this function:

◆ on_export_finished()

void Slic3r::GUI::Plater::priv::on_export_finished ( wxCommandEvent & evt)
13255{
13256#if 0
13257 //BBS: also export 3mf to the same directory for debugging
13258 std::string gcode_path_str(evt.GetString().ToUTF8().data());
13259 fs::path gcode_path(gcode_path_str);
13260
13261 if (q) {
13262 q->export_3mf(gcode_path.replace_extension(".3mf"), SaveStrategy::Silence); // BBS: silence
13263 }
13264#endif
13265}
@ Silence
Definition bbs_3mf.hpp:170

References q, and Slic3r::Silence.

◆ on_filament_color_changed()

void Slic3r::GUI::Plater::priv::on_filament_color_changed ( wxCommandEvent & event)
14073{
14074 //q->update_all_plate_thumbnails(true);
14075 //q->get_preview_canvas3D()->update_plate_thumbnails();
14076 int modify_id = event.GetInt();
14077
14078 auto& ams_multi_color_filment = wxGetApp().preset_bundle->ams_multi_color_filment;
14079 if (modify_id >= 0 && modify_id < ams_multi_color_filment.size())
14080 ams_multi_color_filment[modify_id].clear();
14081
14082 if (wxGetApp().app_config->get("auto_calculate_flush") != "disabled") {
14083 sidebar->auto_calc_flushing_volumes(modify_id);
14084 }
14085
14086 // A mixed slot's colour is derived from its components, so recompute the swatches.
14087 sidebar->update_mixed_filament_list();
14088}

References sidebar.

◆ on_modify_filament()

void Slic3r::GUI::Plater::priv::on_modify_filament ( SimpleEvent & evt)
15185{
15186 Filamentinformation *filament_info = static_cast<Filamentinformation *>(evt.GetEventObject());
15187 int res;
15188 std::shared_ptr<Preset> need_edit_preset;
15189 {
15190 EditFilamentPresetDialog dlg(wxGetApp().mainframe, filament_info);
15191 res = dlg.ShowModal();
15192 need_edit_preset = dlg.get_need_edit_preset();
15193 }
15194 wxGetApp().mainframe->update_side_preset_ui();
15196 sidebar->update_all_preset_comboboxes();
15197 if (wxID_EDIT == res) {
15198 Tab *tab = wxGetApp().get_tab(Preset::Type::TYPE_FILAMENT);
15199 //tab->restore_last_select_item();
15200 if (tab == nullptr) { return; }
15201 // Popup needs to be called before "restore_last_select_item", otherwise the page may not be updated
15202 wxGetApp().params_dialog()->Popup();
15203 tab->restore_last_select_item();
15204 // Opening Studio and directly accessing the Filament settings interface through the edit preset button will not take effect and requires manual settings.
15205 tab->set_just_edit(true);
15206 tab->select_preset(need_edit_preset->name);
15207 // when some preset have modified, if the printer is not need_edit_preset_name compatible printer, the preset will jump to other preset, need select again
15208 if (!need_edit_preset->is_compatible) tab->select_preset(need_edit_preset->name);
15209 }
15210
15211}

References Slic3r::GUI::EditFilamentPresetDialog::get_need_edit_preset(), Slic3r::GUI::Tab::restore_last_select_item(), Slic3r::GUI::Tab::select_preset(), Slic3r::GUI::Tab::set_just_edit(), Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, Slic3r::Preset::TYPE_FILAMENT, and Slic3r::GUI::Plater::update_ui_from_settings().

Here is the call graph for this function:

◆ on_object_select()

void Slic3r::GUI::Plater::priv::on_object_select ( SimpleEvent & evt)
14058{
14059 if (wxGetApp().is_closing())
14060 return;
14061
14062 wxGetApp().obj_list()->update_selections();
14064}

References selection_changed().

Here is the call graph for this function:

◆ on_plate_right_click()

void Slic3r::GUI::Plater::priv::on_plate_right_click ( RBtnPlateEvent & evt)
14266{
14267 wxMenu *menu = menus.plate_menu();
14268 show_right_click_menu(evt.data.first, menu);
14269}
void show_right_click_menu(Vec2d mouse_position, wxMenu *menu)
Definition Plater.cpp:14182

References Slic3r::GUI::Event< T >::data, menus, and show_right_click_menu().

Here is the call graph for this function:

◆ on_plate_selected()

void Slic3r::GUI::Plater::priv::on_plate_selected ( SimpleEvent & )
14018{
14019 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received plate selected event\n" ;
14020 sidebar->obj_list()->on_plate_selected(partplate_list.get_curr_plate_index());
14021}

References partplate_list, and sidebar.

◆ on_process_completed()

void Slic3r::GUI::Plater::priv::on_process_completed ( SlicingProcessCompletedEvent & evt)
13341{
13342 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": enter, m_ignore_event %1%, status %2%")%m_ignore_event %evt.status();
13343 //BBS:ignore cancel event for some special case
13344 if (m_ignore_event)
13345 {
13346 m_ignore_event = false;
13347 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": ignore this event %1%") % evt.status();
13348 return;
13349 }
13350 //BBS: add project slice logic
13351 bool is_finished = !m_slice_all || (m_cur_slice_plate == (partplate_list.get_plate_count() - 1));
13352
13353 //BBS: slice .gcode.3mf file related logic, assign is_finished again
13354 bool only_has_gcode_need_preview = false;
13355 auto plate_list = this->partplate_list.get_plate_list();
13356 bool has_print_instances = false;
13357 for (auto plate : plate_list)
13358 has_print_instances = has_print_instances || plate->has_printable_instances();
13359 if (this->model.objects.empty() && !has_print_instances)
13360 only_has_gcode_need_preview = true;
13361 if (only_has_gcode_need_preview && m_slice_all_only_has_gcode) {
13362 is_finished = (m_cur_slice_plate == (partplate_list.get_plate_count() - 1));
13363 if (is_finished)
13365 }
13366
13367 // Stop the background task, wait until the thread goes into the "Idle" state.
13368 // At this point of time the thread should be either finished or canceled,
13369 // so the following call just confirms, that the produced data were consumed.
13370 this->background_process.stop();
13371 notification_manager->set_slicing_progress_export_possible();
13372
13373 // Reset the "export G-code path" name, so that the automatic background processing will be enabled again.
13374 this->background_process.reset_export();
13375 // This bool stops showing export finished notification even when process_completed_with_error is false
13376 bool has_error = false;
13377 std::string lifecycle_error_msg;
13378 if (evt.error()) {
13379 auto message = evt.format_error_message();
13380 lifecycle_error_msg = message.first;
13381 if (evt.critical_error()) {
13382 if (q->m_tracking_popup_menu) {
13383 // We don't want to pop-up a message box when tracking a pop-up menu.
13384 // We postpone the error message instead.
13385 q->m_tracking_popup_menu_error_message = message.first;
13386 } else {
13387 show_error(q, message.first, message.second.size() != 0 && message.second[0] != 0);
13388 notification_manager->set_slicing_progress_hidden();
13389 }
13390 } else {
13391 std::vector<const ModelObject *> ptrs;
13392 for (auto oid : message.second)
13393 {
13394 const PrintObject *print_object = this->background_process.m_fff_print->get_object(ObjectID(oid));
13395 if (print_object) { ptrs.push_back(print_object->model_object()); }
13396 }
13397 notification_manager->push_slicing_error_notification(message.first, ptrs);
13398 }
13399 if (evt.invalidate_plater())
13400 {
13401 // BBS
13402#if 0
13403 const wxString invalid_str = _L("Invalid data");
13405 sidebar->set_btn_label(btn, invalid_str);
13406#endif
13407 process_completed_with_error = partplate_list.get_curr_plate_index();;
13408 }
13409 has_error = true;
13410 is_finished = true;
13411 }
13412 if (evt.cancelled()) {
13413 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", cancel event, status: %1%") % evt.status();
13414 this->notification_manager->set_slicing_progress_canceled(_u8L("Slicing Canceled"));
13415 is_finished = true;
13416 }
13417
13418 {
13419 Slic3r::LifecycleEventContext ctx;
13420 if (const PrintBase* print = this->background_process.current_print()) {
13421 const Model& model = print->model();
13422 ctx.id = std::to_string(model.id().id);
13423 if (model.model_info)
13424 ctx.name = model.model_info->model_name;
13425 } else {
13426 // Realistically Printbase* print will never be null because select_technology already asserts an active print
13427 // and the worker thread asserts it before processing.
13428 BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": slicing completed without an active print; lifecycle event has no model ID";
13429 }
13430 ctx.code = evt.cancelled() ? Slic3r::LifecycleEvtCode::Warn :
13432 ctx.msg = evt.cancelled() ? "cancelled" : (has_error ? lifecycle_error_msg : std::string());
13434 }
13435
13436 //BBS: set the current plater's slice result to valid
13437 if (!this->background_process.empty())
13438 this->background_process.get_current_plate()->update_slice_result_valid_state(evt.success());
13439
13440 //BBS: update the action button according to the current plate's status
13441 bool ready_to_slice = !this->partplate_list.get_curr_plate()->is_slice_result_valid();
13442
13443 // BBS
13444#if 0
13445 this->sidebar->show_sliced_info_sizer(evt.success());
13446#endif
13447
13448 // This updates the "Slice now", "Export G-code", "Arrange" buttons status.
13449 // Namely, it refreshes the "Out of print bed" property of all the ModelObjects, and it enables
13450 // the "Slice now" and "Export G-code" buttons based on their "out of bed" status.
13451 //BBS: remove this update here, will be updated in update_fff_scene later
13452 //this->object_list_changed();
13453
13454 // refresh preview
13455 if (view3D->is_dragging()) // updating scene now would interfere with the gizmo dragging
13456 delayed_scene_refresh = true;
13457 else {
13458 if (this->printer_technology == ptFFF) {
13459 if (is_finished)
13460 this->update_fff_scene();
13461 }
13462 else
13463 this->update_sla_scene();
13464 }
13465
13466 //BBS: add slice&&print status update logic
13467 if (evt.cancelled()) {
13468 /*if (wxGetApp().get_mode() == comSimple)
13469 sidebar->set_btn_label(ActionButtonType::abReslice, "Slice now");
13470 show_action_buttons(true);*/
13471 ready_to_slice = true;
13472 //this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, true, true);
13473 } else {
13474 if((ready_to_slice) || (wxGetApp().get_mode() == comSimple)) {
13475 //this means the current plate is not the slicing plate
13476 //show_action_buttons(ready_to_slice);
13477 //this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, ready_to_slice, true);
13478 }
13479 if (exporting_status != ExportingStatus::NOT_EXPORTING && !has_error) {
13480 notification_manager->stop_delayed_notifications_of_type(NotificationType::ExportOngoing);
13481 notification_manager->close_notification_of_type(NotificationType::ExportOngoing);
13482 }
13483 // If writing to removable drive was scheduled, show notification with eject button
13485 //show_action_buttons(ready_to_slice);
13486 this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, ready_to_slice, true);
13487 notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path,
13488 // Don't offer the "Eject" button on ChromeOS, the Linux side has no control over it.
13490 wxGetApp().removable_drive_manager()->set_exporting_finished(true);
13491 }else
13493 notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, false);
13494
13495 // BBS, Generate calibration thumbnail for current plate
13496 if (!has_error && preview) {
13497 // generate calibration data
13498 /* BBS generate calibration data by printer
13499 preview->reload_print();
13500 ThumbnailData* calibration_data = &partplate_list.get_curr_plate()->cali_thumbnail_data;
13501 const ThumbnailsParams calibration_params = { {}, false, true, true, true, partplate_list.get_curr_plate_index() };
13502 generate_calibration_thumbnail(*calibration_data, PartPlate::cali_thumbnail_width, PartPlate::cali_thumbnail_height, calibration_params);
13503 preview->get_canvas3d()->reset_gcode_toolpaths();*/
13504
13505 // generate bbox data
13506 PlateBBoxData* plate_bbox_data = &partplate_list.get_curr_plate()->cali_bboxes_data;
13507 *plate_bbox_data = generate_first_layer_bbox();
13508 }
13509 }
13510
13512
13513
13514
13515
13516 if (is_finished)
13517 {
13518 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":finished, reload print soon");
13519 m_is_slicing = false;
13520 this->preview->reload_print(false);
13521 q->mark_plate_toolbar_image_dirty();
13522 q->SetDropTarget(new PlaterDropTarget(*main_frame, *q));
13523 }
13524 else
13525 {
13526 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":slicing all, plate %1% finished, start next slice...")%m_cur_slice_plate;
13528
13529 q->Freeze();
13530 q->select_plate(m_cur_slice_plate);
13531 partplate_list.select_plate_view();
13532 int ret = q->start_next_slice();
13533 if (ret) {
13534 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":slicing all, plate %1% can not be sliced, will stop")%m_cur_slice_plate;
13535 m_is_slicing = false;
13536 }
13537 //not the last plate
13539 q->Thaw();
13540 }
13544 }
13545
13546 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(", exit.");
13547}
@ abReslice
Definition Plater.cpp:603
@ abSendGCode
Definition Plater.cpp:605
@ abExport
Definition Plater.cpp:604
@ EXPORTING_TO_REMOVABLE
Definition Plater.cpp:7166
@ EXPORTING_TO_LOCAL
Definition Plater.cpp:7167
@ NOT_EXPORTING
Definition Plater.cpp:7165
@ comSimple
Definition Config.hpp:222
@ LinuxOnChromium
Definition Platform.hpp:24
std::string msg
Definition LifecycleEvents.hpp:83
PlatformFlavor platform_flavor()
Definition Platform.cpp:108
@ SlicingJobComplete
Definition LifecycleEvents.hpp:33
@ Warn
Definition LifecycleEvents.hpp:68
@ Error
Definition LifecycleEvents.hpp:68
std::string id
Definition LifecycleEvents.hpp:86
bool m_is_slicing
Definition Plater.cpp:7225
ExportingStatus exporting_status
Definition Plater.cpp:7738
std::string last_output_path
Definition Plater.cpp:7739
int process_completed_with_error
Definition Plater.cpp:7744
std::string last_output_dir_path
Definition Plater.cpp:7740
void update_fff_scene()
Definition Plater.cpp:11745
bool m_ignore_event
Definition Plater.cpp:7223
void schedule_auto_reslice_if_needed()
Definition Plater.cpp:11122
PlateBBoxData generate_first_layer_bbox()
Definition Plater.cpp:14320
bool auto_reslice_after_cancel
Definition Plater.cpp:7235
void update_fff_scene_only_shells(bool only_shells=true)
Definition Plater.cpp:11758

References _L, _u8L, Slic3r::GUI::abExport, Slic3r::GUI::abReslice, Slic3r::GUI::abSendGCode, auto_reslice_after_cancel, Slic3r::SlicingProcessCompletedEvent::cancelled(), Slic3r::LifecycleEventContext::code, Slic3r::comSimple, Slic3r::SlicingProcessCompletedEvent::critical_error(), Slic3r::BackgroundSlicingProcess::current_print(), delayed_scene_refresh, Slic3r::GUI::MainFrame::eEventSliceUpdate, Slic3r::BackgroundSlicingProcess::empty(), Slic3r::Error, Slic3r::SlicingProcessCompletedEvent::error(), exporting_status, Slic3r::GUI::EXPORTING_TO_LOCAL, Slic3r::GUI::EXPORTING_TO_REMOVABLE, Slic3r::GUI::ExportOngoing, Slic3r::fire_lifecycle_event(), Slic3r::SlicingProcessCompletedEvent::format_error_message(), generate_first_layer_bbox(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::BackgroundSlicingProcess::get_current_plate(), Slic3r::Print::get_object(), Slic3r::GUI::PartPlateList::get_plate_list(), Slic3r::LifecycleEventContext::id, Slic3r::SlicingProcessCompletedEvent::invalidate_plater(), Slic3r::GUI::PartPlate::is_slice_result_valid(), last_output_dir_path, last_output_path, Slic3r::LinuxOnChromium, m_cur_slice_plate, Slic3r::BackgroundSlicingProcess::m_fff_print, m_ignore_event, m_is_slicing, m_slice_all, m_slice_all_only_has_gcode, main_frame, model, Slic3r::PrintObjectBase::model_object(), Slic3r::LifecycleEventContext::msg, Slic3r::LifecycleEventContext::name, Slic3r::GUI::NOT_EXPORTING, notification_manager, Slic3r::Model::objects, Slic3r::Ok, partplate_list, Slic3r::GUI::Plater::PlaterDropTarget, Slic3r::platform_flavor(), preview, process_completed_with_error, Slic3r::ptFFF, q, Slic3r::GUI::Preview::reload_print(), Slic3r::BackgroundSlicingProcess::reset_export(), schedule_auto_reslice_if_needed(), Slic3r::GUI::show_error(), sidebar, Slic3r::SlicingJobComplete, Slic3r::SlicingProcessCompletedEvent::status(), Slic3r::BackgroundSlicingProcess::stop(), Slic3r::SlicingProcessCompletedEvent::success(), update_fff_scene(), update_fff_scene_only_shells(), update_sla_scene(), Slic3r::GUI::MainFrame::update_slice_print_status(), Slic3r::GUI::PartPlate::update_slice_result_valid_state(), view3D, and Slic3r::Warn.

Here is the call graph for this function:

◆ on_repair_model()

void Slic3r::GUI::Plater::priv::on_repair_model ( wxCommandEvent & event)
14068{
14069 wxGetApp().obj_list()->fix_through_cgal();
14070}

◆ on_right_click()

void Slic3r::GUI::Plater::priv::on_right_click ( RBtnEvent & evt)
14201{
14202 int obj_idx = get_selected_object_idx();
14203
14204 wxMenu* menu = nullptr;
14205
14206 if (obj_idx == -1) { // no one or several object are selected
14207 if (evt.data.second) { // right button was clicked on empty space
14208 if (!get_selection().is_empty()) // several objects are selected in 3DScene
14209 return;
14210 menu = menus.default_menu();
14211 }
14212 else {
14214 menu = menus.assemble_multi_selection_menu();
14215 }
14216 else {
14217 menu = menus.multi_selection_menu();
14218 }
14219 }
14220 }
14221 else {
14222 // If in 3DScene is(are) selected volume(s), but right button was clicked on empty space
14223 if (evt.data.second)
14224 return;
14225
14226 // Each context menu respects to the selected item in ObjectList,
14227 // so this selection should be updated before menu agyuicreation
14228 wxGetApp().obj_list()->update_selections();
14229
14231 menu = menus.sla_object_menu();
14232 else {
14233 const Selection& selection = get_selection();
14234 // show "Object menu" for each one or several FullInstance instead of FullObject
14235 const bool is_some_full_instances = selection.is_single_full_instance() ||
14236 selection.is_single_full_object() ||
14237 selection.is_multiple_full_instance();
14238 const bool is_part = selection.is_single_volume() || selection.is_single_modifier();
14239
14240 //BBS get assemble view menu
14242 menu = is_some_full_instances ? menus.assemble_object_menu() :
14243 is_part ? menus.assemble_part_menu() : menus.assemble_multi_selection_menu();
14244 } else {
14245 if (is_some_full_instances)
14246 menu = printer_technology == ptSLA ? menus.sla_object_menu() : menus.object_menu();
14247 else if (is_part) {
14248 const GLVolume* gl_volume = selection.get_first_volume();
14249 const ModelVolume *model_volume = get_model_volume(*gl_volume, selection.get_model()->objects);
14250 menu = (model_volume != nullptr && model_volume->is_text()) ? menus.text_part_menu() :
14251 (model_volume != nullptr && model_volume->is_svg()) ? menus.svg_part_menu() :
14252 menus.part_menu();
14253 } else
14254 menu = menus.multi_selection_menu();
14255 }
14256 }
14257 }
14258
14259 if (q != nullptr && menu) {
14260 show_right_click_menu(evt.data.first, menu);
14261 }
14262}
static ModelVolume * get_model_volume(const Selection &selection, Model &model)
Definition GLGizmoBrimEars.cpp:66

References assemble_view, current_panel, Slic3r::GUI::Event< T >::data, Slic3r::GUI::Selection::get_first_volume(), Slic3r::GUI::Selection::get_model(), Slic3r::GUI::get_model_volume(), Slic3r::GUI::Plater::get_selected_object_idx(), Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::is_multiple_full_instance(), Slic3r::GUI::Selection::is_single_full_instance(), Slic3r::GUI::Selection::is_single_full_object(), Slic3r::GUI::Selection::is_single_modifier(), Slic3r::GUI::Selection::is_single_volume(), Slic3r::ModelVolume::is_svg(), Slic3r::ModelVolume::is_text(), menus, Slic3r::Model::objects, printer_technology, Slic3r::ptSLA, q, and show_right_click_menu().

Here is the call graph for this function:

◆ on_select_bed_type()

void Slic3r::GUI::Plater::priv::on_select_bed_type ( wxCommandEvent & evt)
12875{
12876 ComboBox* combo = static_cast<ComboBox*>(evt.GetEventObject());
12877 auto select_bed_type = sidebar->get_cur_select_bed_type();
12878 std::string bed_type_name = print_config_def.get("curr_bed_type")->enum_values[(int)select_bed_type - 1];
12879
12880 PresetBundle& preset_bundle = *wxGetApp().preset_bundle;
12881 DynamicPrintConfig& proj_config = wxGetApp().preset_bundle->project_config;
12882 const t_config_enum_values* keys_map = print_config_def.get("curr_bed_type")->enum_keys_map;
12883
12884 if (keys_map) {
12885 BedType new_bed_type = btCount;
12886 for (auto item : *keys_map) {
12887 if (item.first == bed_type_name) {
12888 new_bed_type = (BedType)item.second;
12889 break;
12890 }
12891 }
12892
12893 if (new_bed_type != btCount) {
12894 BedType old_bed_type = proj_config.opt_enum<BedType>("curr_bed_type");
12895 if (old_bed_type != new_bed_type) {
12896 proj_config.set_key_value("curr_bed_type", new ConfigOptionEnum<BedType>(new_bed_type));
12897
12898 wxGetApp().plater()->update_project_dirty_from_presets();
12899
12900 // update plater with new config
12901 q->on_config_change(wxGetApp().preset_bundle->full_config());
12902 // Rebuild the plate tab from the current selection; its cached plates may be gone after a reset.
12903 wxGetApp().obj_list()->update_and_show_object_settings_item();
12904
12905 // update app_config
12906 AppConfig* app_config = wxGetApp().app_config;
12907 app_config->set("curr_bed_type", std::to_string(int(new_bed_type)));
12908 app_config->set_printer_setting(wxGetApp().preset_bundle->printers.get_selected_preset_name(),
12909 "curr_bed_type", std::to_string(int(new_bed_type)));
12910
12911 //update slice status
12912 auto plate_list = partplate_list.get_plate_list();
12913 for (auto plate : plate_list) {
12914 if (plate->get_bed_type() == btDefault) {
12915 plate->update_slice_result_valid_state(false);
12916 }
12917 }
12918
12919 // update render
12920 view3D->get_canvas3d()->render();
12921 preview->msw_rescale();
12922 }
12923 }
12924 }
12925}
const ConfigOptionDef * get(const t_config_option_key &opt_key) const
Definition Config.hpp:2662
const t_config_enum_values * enum_keys_map
Definition Config.hpp:2619
std::vector< std::string > enum_values
Definition Config.hpp:2615
@ btDefault
Definition PrintConfig.hpp:508
@ btCount
Definition PrintConfig.hpp:515
const PrintConfigDef print_config_def
Definition PrintConfig.cpp:10099
std::map< std::string, int > t_config_enum_values
Definition Config.hpp:2072

References Slic3r::btCount, Slic3r::btDefault, Slic3r::PresetBundle::full_config(), Slic3r::PresetCollection::get_selected_preset_name(), Slic3r::DynamicConfig::opt_enum(), partplate_list, preview, Slic3r::print_config_def, Slic3r::PresetBundle::printers, q, Slic3r::AppConfig::set(), Slic3r::DynamicConfig::set_key_value(), Slic3r::AppConfig::set_printer_setting(), sidebar, and view3D.

Referenced by on_combobox_select().

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

◆ on_select_preset()

void Slic3r::GUI::Plater::priv::on_select_preset ( wxCommandEvent & evt)

Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, but the OSX version derived from wxOwnerDrawnCombo. So, to get selected string we do combo->GetString(combo->GetSelection()) instead of combo->GetStringSelection().ToUTF8().data());

12928{
12929 PlaterPresetComboBox* combo = static_cast<PlaterPresetComboBox*>(evt.GetEventObject());
12930 Preset::Type preset_type = combo->get_type();
12931
12932 // Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender"),
12933 // m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
12934 // So, use GetSelection() from event parameter
12935 int selection = evt.GetSelection();
12936
12937 auto marker = reinterpret_cast<size_t>(combo->GetClientData(selection));
12939 sidebar->create_printer_preset();
12940 return;
12941 }
12942
12943 auto idx = combo->get_filament_idx();
12944
12945 // BBS:Save the plate parameters before switching
12946 PartPlateList& old_plate_list = this->partplate_list;
12947 PartPlate* old_plate = old_plate_list.get_selected_plate();
12948 Vec3d old_plate_pos = old_plate->get_center_origin();
12949
12950 // BBS: Save the model in the current platelist
12951 std::vector<std::vector<int> > plate_object;
12952 for (size_t i = 0; i < old_plate_list.get_plate_count(); ++i) {
12953 PartPlate* plate = old_plate_list.get_plate(i);
12954 std::vector<int> obj_idxs;
12955 for (int obj_idx = 0; obj_idx < model.objects.size(); obj_idx++) {
12956 if (plate && plate->contain_instance(obj_idx, 0)) {
12957 obj_idxs.emplace_back(obj_idx);
12958 }
12959 }
12960 plate_object.emplace_back(obj_idxs);
12961 }
12962
12963 bool flag = is_support_filament(idx);
12970
12971 // Prefer the internal preset name stored per combo item to avoid alias collisions
12972 // (e.g. user preset and bundle preset sharing the same display alias).
12973 wxString wx_stored_name = combo->GetItemAlias(selection);
12974 std::string preset_name;
12975 if (!wx_stored_name.empty()) {
12976 preset_name = Preset::remove_suffix_modified(wx_stored_name.ToUTF8().data());
12977 } else {
12978 wxString wx_name = combo->GetString(selection);
12979 preset_name = wxGetApp().preset_bundle->get_preset_name_by_alias(preset_type,
12980 Preset::remove_suffix_modified(wx_name.ToUTF8().data()));
12981 }
12982
12983 if (preset_type == Preset::TYPE_FILAMENT) {
12984 wxGetApp().preset_bundle->set_filament_preset(idx, preset_name);
12985 wxGetApp().plater()->update_project_dirty_from_presets();
12986 wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
12987 sidebar->update_dynamic_filament_list();
12988 bool flag_is_change = is_support_filament(idx);
12989 if (flag != flag_is_change && wxGetApp().app_config->get("auto_calculate_flush") == "all") {
12990 sidebar->auto_calc_flushing_volumes(idx);
12991 }
12992 auto select_flag = combo->GetFlag(selection);
12993 combo->set_sync_badge(select_flag == (int)PresetComboBox::FilamentAMSType::FROM_AMS);
12994 q->on_filament_change(idx);
12995 }
12996 bool select_preset = !combo->selection_is_changed_according_to_physical_printers();
12997 // TODO: ?
12998 if (preset_type == Preset::TYPE_FILAMENT && sidebar->is_multifilament()) {
12999 // Only update the plater UI for the 2nd and other filaments.
13000 combo->update();
13001 }
13002 else if (select_preset) {
13003 if (preset_type == Preset::TYPE_PRINTER) {
13004 PhysicalPrinterCollection& physical_printers = wxGetApp().preset_bundle->physical_printers;
13005 if(combo->is_selected_physical_printer())
13006 preset_name = physical_printers.get_selected_printer_preset_name();
13007 else
13008 physical_printers.unselect_printer();
13009
13010 if (combo->is_selected_printer_model()) {
13011 auto preset = wxGetApp().preset_bundle->get_similar_printer_preset(preset_name, {});
13012 if (preset == nullptr) {
13013 MessageDialog dlg(this->sidebar, "", "");
13014 dlg.ShowModal();
13015 }
13016 preset->is_visible = true; // force visible
13017 preset_name = preset->name;
13018 }
13019 std::string old_preset_name = wxGetApp().preset_bundle->printers.get_edited_preset().name;
13020
13021 update_objects_position_when_select_preset([this, &preset_type, &preset_name]() {
13022 wxWindowUpdateLocker noUpdates2(sidebar->filament_panel());
13023 wxGetApp().get_tab(preset_type)->select_preset(preset_name);
13024 // update plater with new config
13025 q->on_config_change(wxGetApp().preset_bundle->full_config());
13026 });
13027
13028
13029 if (old_preset_name != preset_name && wxGetApp().app_config->get("auto_calculate_flush") == "all") {
13030 wxGetApp().plater()->sidebar().auto_calc_flushing_volumes(-1);
13031 }
13032
13033 // sync extruder info when select multi_extruder preset
13034 if (Slic3r::DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager()) {
13035 MachineObject *obj = dev->get_selected_machine();
13036 if (obj && obj->is_multi_extruders()) {
13037 PresetBundle *preset_bundle = wxGetApp().preset_bundle;
13038 Preset& cur_preset = preset_bundle->printers.get_edited_preset();
13039 if (cur_preset.get_printer_type(preset_bundle) == obj->get_show_printer_type()) {
13040 double preset_nozzle_diameter = cur_preset.config.option<ConfigOptionFloats>("nozzle_diameter")->values[0];
13041 bool same_nozzle_diameter = true;
13042
13043 const auto& extruders = obj->GetExtderSystem()->GetExtruders();
13044 for (const DevExtder &extruder : extruders) {
13045 if (!obj->GetExtderSystem()->NozzleDiameterMatchesOrUnknown(extruder.GetExtId(), float(preset_nozzle_diameter))) {
13046 same_nozzle_diameter = false;
13047 }
13048 }
13049
13050 if (cur_preset.is_system || (!cur_preset.is_system && same_nozzle_diameter)) {
13051 GUI::wxGetApp().sidebar().sync_extruder_list();
13052 }
13053 }
13054 }
13055 }
13056 } else {
13057 // BBS
13058 // wxWindowUpdateLocker noUpdates1(sidebar->print_panel());
13059 wxWindowUpdateLocker noUpdates2(sidebar->filament_panel());
13060 wxGetApp().get_tab(preset_type)->select_preset(preset_name);
13061 // update plater with new config
13062 q->on_config_change(wxGetApp().preset_bundle->full_config());
13063 }
13064 }
13065
13066 // ORCA: Always refresh the selected filament combo so its color swatch (clr_picker)
13067 // matches the chosen preset. update_ams_color() (in OnSelect) updates the project
13068 // filament color when the preset defines one; this repaints the swatch to match.
13069 if (preset_type == Preset::TYPE_FILAMENT)
13070 combo->update();
13071
13072 // update plater with new config
13073 q->on_config_change(wxGetApp().preset_bundle->full_config());
13074 if (preset_type == Preset::TYPE_PRINTER) {
13075 /* Settings list can be changed after printer preset changing, so
13076 * update all settings items for all item had it.
13077 * Furthermore, Layers editing is implemented only for FFF printers
13078 * and for SLA presets they should be deleted
13079 */
13080 wxGetApp().obj_list()->update_object_list_by_printer_technology();
13081
13082 // BBS:Model reset by plate center
13083 PartPlateList& cur_plate_list = this->partplate_list;
13084 PartPlate* cur_plate = cur_plate_list.get_curr_plate();
13085 Vec3d cur_plate_pos = cur_plate->get_center_origin();
13086
13087 if (old_plate_pos.x() != cur_plate_pos.x() || old_plate_pos.y() != cur_plate_pos.y()) {
13088 for (int i = 0; i < plate_object.size(); ++i) {
13089 view3D->select_object_from_idx(plate_object[i]);
13090 this->sidebar->obj_list()->update_selections();
13091 view3D->center_selected_plate(i);
13092 }
13093
13094 view3D->deselect_all();
13095 }
13096#if 0 // do not toggle auto calc when change printer
13097 // update flush matrix
13098 size_t filament_size = wxGetApp().plater()->get_extruder_colors_from_plater_config().size();
13099 for (size_t idx = 0; idx < filament_size; ++idx)
13100 wxGetApp().plater()->sidebar().auto_calc_flushing_volumes(idx);
13101#endif
13102
13103 // Show shared profiles notification for the newly selected printer
13104 if (wxGetApp().app_config->get_bool("show_shared_profiles_notification"))
13105 {
13106 std::string printer_name = wxGetApp().preset_bundle->printers.get_selected_preset_base().name;
13107 std::string encoded_name = Http::url_encode(printer_name);
13108
13109 std::string cloud_url;
13110 if (auto agent = wxGetApp().getAgent()) {
13111 if (auto orca_agent = std::dynamic_pointer_cast<OrcaCloudServiceAgent>(agent->get_cloud_agent())) {
13112 cloud_url = orca_agent->get_cloud_base_url();
13113 }
13114 }
13115 if (cloud_url.empty())
13116 cloud_url = "https://cloud.orcaslicer.com";
13117
13118 std::string explore_url = cloud_url + "/app/bundles/explore?printers=" + encoded_name;
13119
13120 wxGetApp().plater()->get_notification_manager()->push_shared_profiles_notification(explore_url);
13121 }
13122 }
13123
13124#ifdef __WXMSW__
13125 // From the Win 2004 preset combobox lose a focus after change the preset selection
13126 // and that is why the up/down arrow doesn't work properly
13127 // So, set the focus to the combobox explicitly
13128 combo->SetFocus();
13129#endif
13130 if (preset_type == Preset::TYPE_FILAMENT && wxGetApp().app_config->get("auto_calculate_flush") == "all") {
13131 wxGetApp().plater()->sidebar().auto_calc_flushing_volumes(idx);
13132 }
13133
13134 // BBS: log modify of filament selection
13136
13137 // update slice state and set bedtype default for 3rd-party printer
13138 auto plate_list = partplate_list.get_plate_list();
13139 for (auto plate : plate_list) {
13140 plate->update_slice_result_valid_state(false);
13141 }
13142}
@ LABEL_ITEM_WIZARD_ADD_PRINTERS
Definition PresetComboBoxes.hpp:60
@ FROM_AMS
Definition PresetComboBoxes.hpp:67
static std::string url_encode(const std::string &str)
Definition Http.cpp:969
static std::string remove_suffix_modified(const std::string &name)
Definition Preset.cpp:516
Type
Definition Preset.hpp:244
bool is_support_filament(int extruder_id, bool strict_check)
Definition GUI_App.cpp:10492
void put_other_changes()
Definition bbs_3mf.cpp:9838
void update_objects_position_when_select_preset(const std::function< void()> &select_prest)
Definition Plater.cpp:14523

References Slic3r::Preset::config, Slic3r::GUI::PartPlate::contain_instance(), Slic3r::GUI::PresetComboBox::FROM_AMS, Slic3r::GUI::PartPlate::get_center_origin(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::PresetCollection::get_edited_preset(), Slic3r::GUI::PresetComboBox::get_filament_idx(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::PartPlateList::get_plate_count(), Slic3r::Preset::get_printer_type(), Slic3r::GUI::PartPlateList::get_selected_plate(), Slic3r::PhysicalPrinterCollection::get_selected_printer_preset_name(), Slic3r::MachineObject::get_show_printer_type(), Slic3r::GUI::PresetComboBox::get_type(), Slic3r::MachineObject::GetExtderSystem(), Slic3r::DevExtderSystem::GetExtruders(), ComboBox::GetFlag(), ComboBox::GetItemAlias(), ComboBox::GetString(), Slic3r::MachineObject::is_multi_extruders(), Slic3r::GUI::PresetComboBox::is_selected_physical_printer(), Slic3r::GUI::PresetComboBox::is_selected_printer_model(), Slic3r::GUI::is_support_filament(), Slic3r::Preset::is_system, Slic3r::GUI::PresetComboBox::LABEL_ITEM_WIZARD_ADD_PRINTERS, model, Slic3r::DevExtderSystem::NozzleDiameterMatchesOrUnknown(), Slic3r::GUI::Sidebar::obj_list(), Slic3r::ConfigBase::option(), partplate_list, Slic3r::PresetBundle::printers, Slic3r::put_other_changes(), q, Slic3r::Preset::remove_suffix_modified(), Slic3r::GUI::PresetComboBox::selection_is_changed_according_to_physical_printers(), Slic3r::GUI::PlaterPresetComboBox::set_sync_badge(), Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, Slic3r::Preset::TYPE_FILAMENT, Slic3r::Preset::TYPE_PRINTER, Slic3r::PhysicalPrinterCollection::unselect_printer(), Slic3r::GUI::PlaterPresetComboBox::update(), Slic3r::GUI::Plater::update_objects_position_when_select_preset(), Slic3r::GUI::ObjectList::update_selections(), Slic3r::Http::url_encode(), and view3D.

Referenced by on_combobox_select().

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

◆ on_slice_button_status()

void Slic3r::GUI::Plater::priv::on_slice_button_status ( bool enable)
14041{
14042 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": enable = "<<enable<<"\n";
14043 if (!background_process.running())
14044 main_frame->update_slice_print_status(MainFrame::eEventObjectUpdate, enable);
14045}

References background_process, Slic3r::GUI::MainFrame::eEventObjectUpdate, and main_frame.

◆ on_slicing_began()

void Slic3r::GUI::Plater::priv::on_slicing_began ( )
13268{
13270 notification_manager->close_notification_of_type(NotificationType::SignDetected);
13271 notification_manager->close_notification_of_type(NotificationType::ExportFinished);
13272 bool is_first_plate = m_cur_slice_plate == 0;
13273 bool slice_all = q->m_only_gcode ? m_slice_all_only_has_gcode : m_slice_all;
13274 bool need_change_dailytips = !(slice_all && !is_first_plate);
13275 notification_manager->set_slicing_progress_began();
13276 notification_manager->update_slicing_notif_dailytips(need_change_dailytips);
13277}
@ SignDetected
Definition NotificationManager.hpp:126

References clear_warnings(), Slic3r::GUI::ExportFinished, m_cur_slice_plate, m_slice_all, m_slice_all_only_has_gcode, notification_manager, q, and Slic3r::GUI::SignDetected.

Referenced by restart_background_process().

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

◆ on_slicing_completed()

void Slic3r::GUI::Plater::priv::on_slicing_completed ( wxCommandEvent & evt)
13226{
13227 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": event_type %1%, string %2%") % evt.GetEventType() % evt.GetString();
13228 //BBS: add slice project logic
13229 if (m_slice_all && (m_cur_slice_plate < (partplate_list.get_plate_count() - 1))) {
13230 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format("slicing all, finished plate %1%, will continue next.")%m_cur_slice_plate;
13231 return;
13232 }
13233
13234 if (view3D->is_dragging()) // updating scene now would interfere with the gizmo dragging
13235 delayed_scene_refresh = true;
13236 else {
13237 if (this->printer_technology == ptFFF) {
13238 //BBS: only reload shells
13239 this->update_fff_scene_only_shells(false);
13240 //this->update_fff_scene();
13241 }
13242 else
13243 this->update_sla_scene();
13244 }
13245 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format("exit.");
13246}

References delayed_scene_refresh, m_cur_slice_plate, m_slice_all, partplate_list, Slic3r::ptFFF, update_fff_scene_only_shells(), update_sla_scene(), and view3D.

Here is the call graph for this function:

◆ on_slicing_update()

void Slic3r::GUI::Plater::priv::on_slicing_update ( SlicingStatusEvent & evt)
13145{
13146 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": event_type %1%, percent %2%, text %3%") % evt.GetEventType() % evt.status.percent % evt.status.text;
13147 // The plate's status callback has already prefixed the text with "Slicing plate N:".
13148 if (evt.status.percent >= 0) {
13149 if (!m_worker.is_idle()) {
13150 // Avoid a race condition
13151 return;
13152 }
13153
13154 notification_manager->set_slicing_progress_percentage(evt.status.text, (float)evt.status.percent / 100.0f);
13155
13156 // update slicing percent
13157 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
13158 //slicing parallel, only update if percent is greater than before
13159 if (evt.status.percent > plate_list.get_curr_plate()->get_slicing_percent())
13160 plate_list.get_curr_plate()->update_slicing_percent(evt.status.percent);
13161 }
13162
13164 switch (this->printer_technology) {
13165 case ptFFF:
13166 //BBS: add slice project logic, only display shells at the beginning
13167 if (!m_slice_all || (m_cur_slice_plate == (partplate_list.get_plate_count() - 1)))
13168 //this->update_fff_scene();
13170 break;
13171 case ptSLA:
13172 // If RELOAD_SLA_SUPPORT_POINTS, then the SLA gizmo is updated (reload_scene calls update_gizmos_data)
13173 if (view3D->is_dragging())
13174 delayed_scene_refresh = true;
13175 else
13176 this->update_sla_scene();
13177 break;
13178 default: break;
13179 }
13180 } else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
13181 // Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
13182 this->preview->reload_print();
13183 }
13184
13186 // Update notification center with warnings of object_id and its warning_step.
13187 ObjectID object_id = evt.status.warning_object_id;
13188 int warning_step = evt.status.warning_step;
13189 PrintStateBase::StateWithWarnings state;
13190 ModelObject const * model_object = nullptr;
13191
13192 //BBS: add partplate related logic, use the print in background process
13194 state = this->printer_technology == ptFFF ?
13195 this->background_process.m_fff_print->step_state_with_warnings(static_cast<PrintStep>(warning_step)) :
13196 this->background_process.m_sla_print->step_state_with_warnings(static_cast<SLAPrintStep>(warning_step));
13197 } else if (this->printer_technology == ptFFF) {
13198 const PrintObject *print_object = this->background_process.m_fff_print->get_object(object_id);
13199 if (print_object) {
13200 state = print_object->step_state_with_warnings(static_cast<PrintObjectStep>(warning_step));
13201 model_object = print_object->model_object();
13202 }
13203 } else {
13204 const SLAPrintObject *print_object = this->background_process.m_sla_print->get_object(object_id);
13205 if (print_object) {
13206 state = print_object->step_state_with_warnings(static_cast<SLAPrintObjectStep>(warning_step));
13207 model_object = print_object->model_object();
13208 }
13209 }
13210 // Now process state.warnings.
13211 for (auto const& warning : state.warnings) {
13212 if (warning.current) {
13216 }
13217 notification_manager->push_slicing_warning_notification(warning.message, false, model_object, object_id, warning_step, warning.message_id, notif_level);
13218 add_warning(warning, object_id.id);
13219 }
13220 }
13221 }
13222 BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format("exit.");
13223}
NotificationLevel
Definition NotificationManager.hpp:208
@ SeriousWarningNotificationLevel
Definition NotificationManager.hpp:226
@ SlicingEmptyGcodeLayers
Definition PrintBase.hpp:71
@ SlicingReplaceInitEmptyLayers
Definition PrintBase.hpp:69
PrintStep
Definition Print.hpp:108
SLAPrintObjectStep
Definition SLAPrint.hpp:42
PrintObjectStep
Definition Print.hpp:123
SLAPrintStep
Definition SLAPrint.hpp:36
void add_warning(const Slic3r::PrintStateBase::Warning &warning, size_t oid)
Definition Plater.cpp:13278
@ RELOAD_SLA_PREVIEW
Definition PrintBase.hpp:466
@ RELOAD_SLA_SUPPORT_POINTS
Definition PrintBase.hpp:465
@ UPDATE_PRINT_OBJECT_STEP_WARNINGS
Definition PrintBase.hpp:469
@ UPDATE_PRINT_STEP_WARNINGS
Definition PrintBase.hpp:468
@ RELOAD_SCENE
Definition PrintBase.hpp:464

References add_warning(), delayed_scene_refresh, Slic3r::PrintBase::SlicingStatus::flags, Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::Print::get_object(), Slic3r::SLAPrint::get_object(), Slic3r::GUI::PartPlate::get_slicing_percent(), Slic3r::ObjectID::id, m_cur_slice_plate, Slic3r::BackgroundSlicingProcess::m_fff_print, Slic3r::BackgroundSlicingProcess::m_sla_print, m_slice_all, m_worker, Slic3r::PrintBase::SlicingStatus::message_type, Slic3r::PrintObjectBase::model_object(), notification_manager, partplate_list, Slic3r::PrintBase::SlicingStatus::percent, Slic3r::ptFFF, Slic3r::ptSLA, Slic3r::GUI::Preview::reload_print(), Slic3r::PrintBase::SlicingStatus::RELOAD_SCENE, Slic3r::PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW, Slic3r::PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS, Slic3r::GUI::NotificationManager::SeriousWarningNotificationLevel, Slic3r::PrintStateBase::SlicingEmptyGcodeLayers, Slic3r::PrintStateBase::SlicingReplaceInitEmptyLayers, Slic3r::SlicingStatusEvent::status, Slic3r::PrintBaseWithState< PrintStepEnum, COUNT >::step_state_with_warnings(), Slic3r::PrintObjectBaseWithState< PrintType, PrintObjectStepEnum, COUNT >::step_state_with_warnings(), Slic3r::PrintBase::SlicingStatus::text, update_fff_scene_only_shells(), Slic3r::PrintBase::SlicingStatus::UPDATE_PRINT_OBJECT_STEP_WARNINGS, Slic3r::PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS, update_sla_scene(), Slic3r::GUI::PartPlate::update_slicing_percent(), view3D, Slic3r::PrintBase::SlicingStatus::warning_object_id, Slic3r::PrintBase::SlicingStatus::warning_step, Slic3r::GUI::NotificationManager::WarningNotificationLevel, and Slic3r::PrintStateBase::StateWithWarnings::warnings.

Here is the call graph for this function:

◆ on_tab_selection_changing()

void Slic3r::GUI::Plater::priv::on_tab_selection_changing ( wxBookCtrlEvent & e)
13874{
13875 // Ignore event raised by child controls
13876 if (!(main_frame->m_tabpanel && e.GetId() == main_frame->m_tabpanel->GetId())) {
13877 e.Skip();
13878 return;
13879 }
13880
13881 const int new_sel = e.GetSelection();
13882 if (new_sel == wxNOT_FOUND) {
13883 // GetPage(new_sel) below needs a valid index.
13884 e.Skip();
13885 return;
13886 }
13887 const wxString new_name = main_frame->m_tabpanel->GetPageName(new_sel);
13888 sidebar_layout.show = new_name == TAB_ID_PREPARE || new_name == TAB_ID_PREVIEW;
13890 int old_sel = e.GetOldSelection();
13891 const bool use_printer_agents = wxGetApp().app_config->get_bool("use_printer_agents");
13892 const bool use_native_device_tab = wxGetApp().preset_bundle &&
13893 (wxGetApp().preset_bundle->use_bbl_device_tab() || use_printer_agents);
13894 if (use_native_device_tab && new_name == TAB_ID_MONITOR) {
13895 // BBL network module is only required for BBL-vendor printers.
13896 // Non-BBL Python plugins (e.g. moonraker) drive the Device tab without it.
13897 if (!use_printer_agents && wxGetApp().preset_bundle->is_bbl_vendor() && !Slic3r::NetworkAgent::is_network_module_loaded()) {
13898 e.Veto();
13899 BOOST_LOG_TRIVIAL(info) << boost::format("skipped tab switch from %1% to %2%, lack of network plugins") % old_sel % new_sel;
13900 if (q) {
13901 wxCommandEvent* evt = new wxCommandEvent(EVT_INSTALL_PLUGIN_HINT);
13902 wxQueueEvent(q, evt);
13903 }
13904 }
13905 } else {
13906 // Pointer test, not a name lookup: in printer-agents mode this page is TAB_ID_MONITOR_WEB
13907 // while the native Device tab holds TAB_ID_MONITOR, and in legacy-web mode it holds
13908 // TAB_ID_MONITOR itself.
13909 const bool selecting_web_device_tab = main_frame->m_printer_view_page &&
13910 main_frame->m_tabpanel->GetPage(new_sel) == main_frame->m_printer_view_page;
13911 if (selecting_web_device_tab) {
13912 // Use the selected discovered machine when the preset has no host.
13913 main_frame->load_printer_url();
13914 } else if (new_name == TAB_ID_MONITOR && wxGetApp().preset_bundle != nullptr) {
13915 auto cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
13916 wxString url = from_u8(PrintHost::get_print_host_webui(&cfg));
13917 if (PrinterWebView* view = PrinterWebView::if_built(); view != nullptr && url.empty()) {
13918 // It's missing_connection page, reload so that we can replay the gif image
13919 view->reload();
13920 }
13921 }
13922 }
13923}
#define TAB_ID_MONITOR
Definition MainFrame.hpp:62
static PrinterWebView * if_built()
Definition Lazy.hpp:183
static bool is_network_module_loaded()
Definition NetworkAgent.cpp:76
static std::string get_print_host_webui(DynamicPrintConfig *config)
Definition PrintHost.cpp:98

References Slic3r::GUI::from_u8(), Slic3r::PrintHost::get_print_host_webui(), Slic3r::GUI::LazyInstance< PrinterWebView >::if_built(), Slic3r::NetworkAgent::is_network_module_loaded(), main_frame, q, sidebar_layout, TAB_ID_MONITOR, TAB_ID_PREPARE, TAB_ID_PREVIEW, and update_sidebar().

Referenced by ~priv().

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

◆ on_update_geometry()

void Slic3r::GUI::Plater::priv::on_update_geometry ( Vec3dsEvent< 2 > & )
14272{
14273 // TODO
14274}

◆ open_machine_select_dialog()

void Slic3r::GUI::Plater::priv::open_machine_select_dialog ( int plate_idx,
PrintFromType print_type = PrintFromType::FROM_NORMAL )
13846{
13847 // BBS
13849 m_select_machine_dlg = new SelectMachineDialog(q);
13850 m_select_machine_dlg->set_print_type(print_type);
13851 m_select_machine_dlg->prepare(plate_idx);
13852 m_select_machine_dlg->ShowModal();
13853}

References m_select_machine_dlg, and q.

Referenced by on_action_print_all(), on_action_print_plate(), and on_action_print_plate_from_sdcard().

Here is the caller graph for this function:

◆ PopupObjectTable()

bool Slic3r::GUI::Plater::priv::PopupObjectTable ( int object_id,
int volume_id,
const wxPoint & position )
15614{
15615 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, create ObjectTableDialog");
15616 int max_width{1920}, max_height{1080};
15617
15618 max_width = q->GetMaxWidth();
15619 max_height = q->GetMaxHeight();
15620 ObjectTableDialog table_dialog(q, q, &model, wxSize(max_width, max_height));
15621 //m_popup_table = new ObjectTableDialog(q, q, &model);
15622
15623 wxRect rect = sidebar->GetRect();
15624 wxPoint pos = sidebar->ClientToScreen(wxPoint(rect.x, rect.y));
15625
15626 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": show ObjectTableDialog");
15627 table_dialog.Popup(object_id, volume_id, pos);
15628
15629 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" finished, will destroy ObjectTableDialog");
15630 return true;
15631}
Vec3d pos(const Pt &p)
Definition ReprojectPointsOnMesh.hpp:16

References model, Slic3r::GUI::ObjectTableDialog::Popup(), q, and sidebar.

Here is the call graph for this function:

◆ process_validation_warning()

void Slic3r::GUI::Plater::priv::process_validation_warning ( StringObjectException const & warning) const
11239{
11240 if (warning.string.empty())
11241 notification_manager->close_notification_of_type(NotificationType::ValidateWarning);
11242 else {
11243 std::string text = warning.string;
11244 auto po = dynamic_cast<PrintObjectBase const *>(warning.object);
11245 auto mo = po ? po->model_object() : dynamic_cast<ModelObject const *>(warning.object);
11246 //ORCA: Update process_validation_warning to handle ModelInstance selection and include fallback
11247 auto mi = dynamic_cast<ModelInstance const *>(warning.object);
11248
11249 auto action_fn = (mo || mi || !warning.opt_key.empty()) ? [id = mo ? mo->id() : (mi ? mi->id() : 0),
11250 parent_id = mi ? mi->get_object()->id() : 0,
11251 is_inst = (mi != nullptr),
11252 opt = warning.opt_key](wxEvtHandler *) {
11253 auto & objects = wxGetApp().model().objects;
11254
11255 if (is_inst) {
11256 bool selected = false;
11257 auto iter = std::find_if(objects.begin(), objects.end(), [parent_id](auto o) { return o->id() == parent_id; });
11258 if (iter != objects.end()) {
11259 ModelObject* obj = *iter;
11260 int inst_idx = -1;
11261 for(size_t i=0; i<obj->instances.size(); ++i) {
11262 if (obj->instances[i]->id() == id) {
11263 inst_idx = i;
11264 break;
11265 }
11266 }
11267
11268 wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
11269
11270 if (inst_idx != -1) {
11271 auto* model = wxGetApp().obj_list()->GetModel();
11272 wxDataViewItem item;
11273 wxDataViewItem objItem = model->GetObjectItem(obj);
11274 if (objItem.IsOk()) {
11275 int vm_obj_idx = model->GetIdByItem(objItem);
11276 if (vm_obj_idx != -1) {
11277 item = model->GetItemByInstanceId(vm_obj_idx, inst_idx);
11278 }
11279 }
11280 if (item.IsOk()) {
11281 wxDataViewItemArray sel_items;
11282 sel_items.Add(item);
11283 wxGetApp().obj_list()->select_items(sel_items);
11284 wxGetApp().obj_list()->update_selections_on_canvas();
11285 selected = true;
11286 }
11287 }
11288
11289 if (!selected) {
11290 wxGetApp().obj_list()->select_items({ {obj, nullptr} });
11291 wxGetApp().obj_list()->update_selections_on_canvas();
11292 }
11293 }
11294 } else {
11295 auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
11296 if (iter != objects.end()) {
11297 wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
11298 wxGetApp().obj_list()->select_items({{*iter, nullptr}});
11299 wxGetApp().obj_list()->update_selections_on_canvas();
11300 }
11301 }
11302 if (!opt.empty()) {
11303 if ((!is_inst && id.id) || (is_inst && parent_id.id))
11304 wxGetApp().params_panel()->switch_to_object();
11305 wxGetApp().sidebar().jump_to_option(opt, Preset::TYPE_PRINT, L"");
11306 }
11307 return false;
11308 } : std::function<bool(wxEvtHandler *)>();
11309 auto hypertext = (mo || mi || !warning.opt_key.empty()) ? _u8L("Jump to") : "";
11310 if (mo) hypertext += std::string(" [") + mo->name + "]";
11311 if (mi) hypertext += std::string(" [") + mi->get_object()->name + "]";
11312 if (!warning.opt_key.empty()) hypertext += std::string(" (") + warning.opt_key + ")";
11313
11314 // BBS disable support enforcer
11315 //if (text == "_SUPPORTS_OFF") {
11316 // text = _u8L("An object has custom support enforcers which will not be used "
11317 // "because supports are disabled.")+"\n";
11318 // hypertext = _u8L("Enable supports for enforcers only");
11319
11320 // action_fn = [](wxEvtHandler*) {
11321 // Tab* print_tab = wxGetApp().get_tab(Preset::TYPE_PRINT);
11322 // assert(print_tab);
11323 // DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
11324 // config.set_key_value("enable_support", new ConfigOptionBool(true));
11325 // config.set_key_value("auto_support_type", new ConfigOptionEnum<SupportType>(stNormalAuto));
11326 // print_tab->on_value_change("enable_support", config.opt_bool("enable_support"));
11327 // print_tab->on_value_change("support_material_auto", config.opt_bool("support_material_auto"));
11328 // return true;
11329 // };
11330 //}
11331
11332 notification_manager->push_notification(
11335 _u8L("WARNING:") + "\n" + text, hypertext, action_fn
11336 );
11337 }
11338}
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841
@ ValidateWarning
Definition NotificationManager.hpp:94

References _u8L, Slic3r::ModelObject::instances, L, model, Slic3r::PrintObjectBase::model_object(), notification_manager, Slic3r::StringObjectException::object, Slic3r::StringObjectException::opt_key, Slic3r::StringObjectException::string, TAB_ID_PREPARE, Slic3r::Preset::TYPE_PRINT, Slic3r::GUI::ValidateWarning, and Slic3r::GUI::NotificationManager::WarningNotificationLevel.

Referenced by process_validation_warnings(), and update_background_process().

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

◆ process_validation_warnings()

void Slic3r::GUI::Plater::priv::process_validation_warnings ( const std::vector< StringObjectException > & warnings) const
11341{
11342 // ValidateWarning stacks by text (m_multiple_types), so clear the stale set before re-adding.
11343 notification_manager->close_notification_of_type(NotificationType::ValidateWarning);
11344 for (const StringObjectException &warning : warnings)
11345 if (!warning.string.empty())
11347}
void process_validation_warning(StringObjectException const &warning) const
Definition Plater.cpp:11238

References notification_manager, process_validation_warning(), and Slic3r::GUI::ValidateWarning.

Referenced by update_background_process().

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

◆ redo()

void Slic3r::GUI::Plater::priv::redo ( )
15369{
15370 if (this->undo_redo_blocked_by_job())
15371 return;
15372 const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack().snapshots();
15373 auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time()));
15374 // BBS: undo-redo until modify record
15375 while (it_current != snapshots.end() && !snapshot_modifies_project(*it_current++));
15376 if (it_current != snapshots.end()) {
15377 while (it_current != snapshots.end() && !snapshot_modifies_project(*it_current++));
15378 this->undo_redo_to(--it_current);
15379 }
15380}
bool snapshot_modifies_project(SnapshotType type)
Definition UndoRedo.hpp:98
void undo_redo_to(size_t time_to_load)
Definition Plater.cpp:15382
bool undo_redo_blocked_by_job()
Definition Plater.cpp:15338

References undo_redo_blocked_by_job(), undo_redo_stack(), and undo_redo_to().

Here is the call graph for this function:

◆ reload_all_from_disk()

void Slic3r::GUI::Plater::priv::reload_all_from_disk ( )
12538{
12539 if (model.objects.empty())
12540 return;
12541
12542 Plater::TakeSnapshot snapshot(q, _u8L("Reload all"));
12543 Plater::SuppressSnapshots suppress(q);
12544
12545 Selection& selection = get_selection();
12546 Selection::IndicesList curr_idxs = selection.get_volume_idxs();
12547 // reload from disk uses selection
12548 select_all();
12550 // restore previous selection
12551 selection.clear();
12552 for (unsigned int idx : curr_idxs) {
12553 selection.add(idx, false);
12554 }
12555}
std::set< unsigned int > IndicesList
Definition Selection.hpp:49
void reload_from_disk()
Definition Plater.cpp:12091
void select_all()
Definition Plater.cpp:10710

References _u8L, Slic3r::GUI::Selection::add(), Slic3r::GUI::Selection::clear(), Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::get_volume_idxs(), model, q, Slic3r::GUI::Plater::reload_from_disk(), and Slic3r::GUI::Plater::select_all().

Here is the call graph for this function:

◆ reload_from_disk()

void Slic3r::GUI::Plater::priv::reload_from_disk ( )
12092{
12093#if ENABLE_RELOAD_FROM_DISK_REWORK
12094 // collect selected reloadable ModelVolumes
12095 std::vector<std::pair<int, int>> selected_volumes = reloadable_volumes(model, get_selection());
12096 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " entry, and reloadable volumes number is: " << selected_volumes.size();
12097 // nothing to reload, return
12098 if (selected_volumes.empty())
12099 return;
12100
12101 std::sort(selected_volumes.begin(), selected_volumes.end(), [](const std::pair<int, int> &v1, const std::pair<int, int> &v2) {
12102 return (v1.first < v2.first) || (v1.first == v2.first && v1.second < v2.second);
12103 });
12104 selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end(), [](const std::pair<int, int> &v1, const std::pair<int, int> &v2) {
12105 return (v1.first == v2.first) && (v1.second == v2.second);
12106 }), selected_volumes.end());
12107#else
12108 Plater::TakeSnapshot snapshot(q, _u8L("Reload from disk"));
12109
12110 const Selection& selection = get_selection();
12111
12112 if (selection.is_wipe_tower())
12113 return;
12114
12115 // struct to hold selected ModelVolumes by their indices
12116 struct SelectedVolume
12117 {
12118 int object_idx;
12119 int volume_idx;
12120
12121 // operators needed by std::algorithms
12122 bool operator < (const SelectedVolume& other) const { return object_idx < other.object_idx || (object_idx == other.object_idx && volume_idx < other.volume_idx); }
12123 bool operator == (const SelectedVolume& other) const { return object_idx == other.object_idx && volume_idx == other.volume_idx; }
12124 };
12125 std::vector<SelectedVolume> selected_volumes;
12126
12127 // collects selected ModelVolumes
12128 const std::set<unsigned int>& selected_volumes_idxs = selection.get_volume_idxs();
12129 for (unsigned int idx : selected_volumes_idxs) {
12130 const GLVolume* v = selection.get_volume(idx);
12131 int v_idx = v->volume_idx();
12132 if (v_idx >= 0) {
12133 int o_idx = v->object_idx();
12134 if (0 <= o_idx && o_idx < (int)model.objects.size())
12135 selected_volumes.push_back({ o_idx, v_idx });
12136 }
12137 }
12138 std::sort(selected_volumes.begin(), selected_volumes.end());
12139 selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end()), selected_volumes.end());
12140#endif // ENABLE_RELOAD_FROM_DISK_REWORK
12141
12142 // collects paths of files to load
12143 std::vector<fs::path> input_paths;
12144 std::vector<fs::path> missing_input_paths;
12145#if ENABLE_RELOAD_FROM_DISK_REWORK
12146 std::vector<std::pair<fs::path, fs::path>> replace_paths;
12147 for (auto [obj_idx, vol_idx] : selected_volumes) {
12148 const ModelObject *object = model.objects[obj_idx];
12149 const ModelVolume *volume = object->volumes[vol_idx];
12150 if (fs::exists(volume->source.input_file))
12151 input_paths.push_back(volume->source.input_file);
12152 else {
12153 // searches the source in the same folder containing the object
12154 bool found = false;
12155 if (!object->input_file.empty()) {
12156 fs::path object_path = fs::path(object->input_file).remove_filename();
12157 if (!object_path.empty()) {
12158 object_path /= fs::path(volume->source.input_file).filename();
12159 if (fs::exists(object_path)) {
12160 input_paths.push_back(object_path);
12161 found = true;
12162 }
12163 }
12164 }
12165 if (!found)
12166 missing_input_paths.push_back(volume->source.input_file);
12167 }
12168 }
12169#else
12170 std::vector<fs::path> replace_paths;
12171 for (const SelectedVolume& v : selected_volumes) {
12172 const ModelObject* object = model.objects[v.object_idx];
12173 const ModelVolume* volume = object->volumes[v.volume_idx];
12174
12175 if (!volume->source.input_file.empty()) {
12176 if (fs::exists(volume->source.input_file))
12177 input_paths.push_back(volume->source.input_file);
12178 else {
12179 // searches the source in the same folder containing the object
12180 bool found = false;
12181 if (!object->input_file.empty()) {
12182 fs::path object_path = fs::path(object->input_file).remove_filename();
12183 if (!object_path.empty()) {
12184 object_path /= fs::path(volume->source.input_file).filename();
12185 const std::string source_input_file = object_path.string();
12186 if (fs::exists(source_input_file)) {
12187 input_paths.push_back(source_input_file);
12188 found = true;
12189 }
12190 }
12191 }
12192 if (!found)
12193 missing_input_paths.push_back(volume->source.input_file);
12194 }
12195 }
12196 else if (!object->input_file.empty() && volume->is_model_part() && !volume->name.empty() && !volume->source.is_from_builtin_objects)
12197 missing_input_paths.push_back(volume->name);
12198 }
12199#endif // ENABLE_RELOAD_FROM_DISK_REWORK
12200
12201 std::sort(missing_input_paths.begin(), missing_input_paths.end());
12202 missing_input_paths.erase(std::unique(missing_input_paths.begin(), missing_input_paths.end()), missing_input_paths.end());
12203
12204 while (!missing_input_paths.empty()) {
12205 // ask user to select the missing file
12206 fs::path search = missing_input_paths.back();
12207 wxString title = _L("Please select a file");
12208#if defined(__APPLE__)
12209 title += " (" + from_u8(search.filename().string()) + ")";
12210#endif // __APPLE__
12211 title += ":";
12212 wxFileDialog dialog(q, title, "", from_u8(search.filename().string()), file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
12213 if (dialog.ShowModal() != wxID_OK)
12214 return;
12215
12216 std::string sel_filename_path = dialog.GetPath().ToUTF8().data();
12217 std::string sel_filename = fs::path(sel_filename_path).filename().string();
12218 if (boost::algorithm::iequals(search.filename().string(), sel_filename)) {
12219 input_paths.push_back(sel_filename_path);
12220 missing_input_paths.pop_back();
12221
12222 fs::path sel_path = fs::path(sel_filename_path).remove_filename().string();
12223
12224 std::vector<fs::path>::iterator it = missing_input_paths.begin();
12225 while (it != missing_input_paths.end()) {
12226 // try to use the path of the selected file with all remaining missing files
12227 fs::path repathed_filename = sel_path;
12228 repathed_filename /= it->filename();
12229 if (fs::exists(repathed_filename)) {
12230 input_paths.push_back(repathed_filename.string());
12231 it = missing_input_paths.erase(it);
12232 }
12233 else
12234 ++it;
12235 }
12236 }
12237 else {
12238 wxString message = _L("Do you want to replace it?");
12239 MessageDialog dlg(q, message, _L("Message"), wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
12240 if (dlg.ShowModal() == wxID_YES)
12241#if ENABLE_RELOAD_FROM_DISK_REWORK
12242 replace_paths.emplace_back(search, sel_filename_path);
12243#else
12244 replace_paths.emplace_back(sel_filename_path);
12245#endif // ENABLE_RELOAD_FROM_DISK_REWORK
12246 missing_input_paths.pop_back();
12247 }
12248 }
12249
12250 std::sort(input_paths.begin(), input_paths.end());
12251 input_paths.erase(std::unique(input_paths.begin(), input_paths.end()), input_paths.end());
12252
12253 std::sort(replace_paths.begin(), replace_paths.end());
12254 replace_paths.erase(std::unique(replace_paths.begin(), replace_paths.end()), replace_paths.end());
12255
12256#if ENABLE_RELOAD_FROM_DISK_REWORK
12257 Plater::TakeSnapshot snapshot(q, _u8L("Reload from disk"));
12258#endif // ENABLE_RELOAD_FROM_DISK_REWORK
12259
12260 std::vector<wxString> fail_list;
12261
12262 // load one file at a time
12263 for (size_t i = 0; i < input_paths.size(); ++i) {
12264 const auto& path = input_paths[i].string();
12265 wxBusyCursor wait;
12266 wxBusyInfo info(_L("Reload from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
12267
12268 Model new_model;
12269 try
12270 {
12271 //BBS: add plate data related logic
12272 PlateDataPtrs plate_data;
12273 //BBS: project embedded settings
12274 std::vector<Preset*> project_presets;
12275
12276 // BBS: backup
12277 if (boost::iends_with(path, ".stp") ||
12278 boost::iends_with(path, ".step")) {
12279 double linear = string_to_double_decimal_point(wxGetApp().app_config->get("linear_deflection"));
12280 double angle = string_to_double_decimal_point(wxGetApp().app_config->get("angle_deflection"));
12281 bool is_split = wxGetApp().app_config->get_bool("is_split_compound");
12282 new_model = Model::read_from_step(path, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel, nullptr, nullptr, nullptr, linear, angle, is_split);
12283 }else {
12284 new_model = Model::read_from_file(path, nullptr, nullptr, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel, &plate_data, &project_presets, nullptr, nullptr, nullptr, nullptr, nullptr, 0);
12285 }
12286
12287
12288 for (ModelObject* model_object : new_model.objects)
12289 {
12290 model_object->center_around_origin();
12291 model_object->ensure_on_bed();
12292 }
12293
12294 if (plate_data.size() > 0)
12295 {
12296 //partplate_list.load_from_3mf_structure(plate_data);
12297 partplate_list.update_slice_context_to_current_plate(background_process);
12298 this->preview->update_gcode_result(partplate_list.get_current_slice_result());
12299 release_PlateData_list(plate_data);
12300 sidebar->obj_list()->reload_all_plates();
12301 }
12302 }
12303 catch (std::exception&)
12304 {
12305 // error while loading
12306 return;
12307 }
12308
12309#if ENABLE_RELOAD_FROM_DISK_REWORK
12310 for (auto [obj_idx, vol_idx] : selected_volumes) {
12311 ModelObject *old_model_object = model.objects[obj_idx];
12312 ModelVolume *old_volume = old_model_object->volumes[vol_idx];
12313
12314 bool sinking = old_model_object->min_z() < SINKING_Z_THRESHOLD;
12315
12316 bool has_source = !old_volume->source.input_file.empty() &&
12317 boost::algorithm::iequals(fs::path(old_volume->source.input_file).filename().string(), fs::path(path).filename().string());
12318 bool has_name = !old_volume->name.empty() && boost::algorithm::iequals(old_volume->name, fs::path(path).filename().string());
12319 if (has_source || has_name) {
12320 int new_volume_idx = -1;
12321 int new_object_idx = -1;
12322 bool match_found = false;
12323 // take idxs from the matching volume
12324 if (has_source && old_volume->source.object_idx < int(new_model.objects.size())) {
12325 const ModelObject *obj = new_model.objects[old_volume->source.object_idx];
12326 if (old_volume->source.volume_idx < int(obj->volumes.size())) {
12327 const std::string &new_input_file = obj->volumes[old_volume->source.volume_idx]->source.input_file;
12328 const std::string &old_input_file = old_volume->source.input_file;
12329 // Orca: match on the exact source path first, then fall back to filename-only so reload
12330 // still matches when the project stored a bare filename and the file was found next to
12331 // the project (same-folder fallback) or picked via the locate dialog (#12992).
12332 if (new_input_file == old_input_file ||
12333 boost::algorithm::iequals(fs::path(new_input_file).filename().string(),
12334 fs::path(old_input_file).filename().string())) {
12335 new_volume_idx = old_volume->source.volume_idx;
12336 new_object_idx = old_volume->source.object_idx;
12337 match_found = true;
12338 }
12339 }
12340 }
12341
12342 if (!match_found && has_name) {
12343 // take idxs from the 1st matching volume
12344 for (size_t o = 0; o < new_model.objects.size(); ++o) {
12345 ModelObject *obj = new_model.objects[o];
12346 bool found = false;
12347 for (size_t v = 0; v < obj->volumes.size(); ++v) {
12348 if (obj->volumes[v]->name == old_volume->name) {
12349 new_volume_idx = (int) v;
12350 new_object_idx = (int) o;
12351 found = true;
12352 break;
12353 }
12354 }
12355 if (found) break;
12356 // BBS: step model,object loaded as a volume. GUI_ObfectList.cpp load_modifier()
12357 if (obj->name == old_volume->name) {
12358 new_object_idx = (int) o;
12359 break;
12360 }
12361 }
12362 }
12363
12364 if (new_object_idx < 0 || int(new_model.objects.size()) <= new_object_idx) {
12365 fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
12366 continue;
12367 }
12368 ModelObject *new_model_object = new_model.objects[new_object_idx];
12369 if (int(new_model_object->volumes.size()) <= new_volume_idx) {
12370 fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
12371 continue;
12372 }
12373
12374 ModelVolume *new_volume = nullptr;
12375 // BBS: step model
12376 if (new_volume_idx < 0 && new_object_idx >= 0) {
12377 TriangleMesh mesh = new_model_object->mesh();
12378 new_volume = old_model_object->add_volume(std::move(mesh));
12379 new_volume->name = new_model_object->name;
12380 new_volume->source.input_file = new_model_object->input_file;
12381 }else {
12382 new_volume = old_model_object->add_volume(*new_model_object->volumes[new_volume_idx]);
12383 // new_volume = old_model_object->volumes.back();
12384 }
12385
12386 new_volume->set_new_unique_id();
12387 new_volume->config.apply(old_volume->config);
12388 new_volume->set_type(old_volume->type());
12389 new_volume->set_material_id(old_volume->material_id());
12390
12391 new_volume->source.mesh_offset = old_volume->source.mesh_offset;
12392 new_volume->set_transformation(old_volume->get_transformation());
12393
12394 new_volume->source.object_idx = old_volume->source.object_idx;
12395 new_volume->source.volume_idx = old_volume->source.volume_idx;
12396 assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
12397 if (old_volume->source.is_converted_from_inches)
12398 new_volume->convert_from_imperial_units();
12399 else if (old_volume->source.is_converted_from_meters)
12400 new_volume->convert_from_meters();
12401
12402 // Remap paint
12403 if (wxGetApp().app_config->get_bool("keep_painting")) {
12404 auto saved_painting = old_volume->save_painting();
12405 if (saved_painting) {
12406 saved_painting->mesh.transform(Geometry::translation_transform(new_volume->mesh().get_init_shift()));
12407 new_volume->restore_painting(saved_painting);
12408 }
12409 }
12410
12411 std::swap(old_model_object->volumes[vol_idx], old_model_object->volumes.back());
12412 old_model_object->delete_volume(old_model_object->volumes.size() - 1);
12413 if (!sinking) old_model_object->ensure_on_bed();
12414 old_model_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
12415
12416 sla::reproject_points_and_holes(old_model_object);
12417
12418 // Fix warning icon in object list
12419 wxGetApp().obj_list()->update_item_error_icon(obj_idx, vol_idx);
12420 }
12421 }
12422#else
12423 // update the selected volumes whose source is the current file
12424 for (const SelectedVolume& sel_v : selected_volumes) {
12425 ModelObject* old_model_object = model.objects[sel_v.object_idx];
12426 ModelVolume* old_volume = old_model_object->volumes[sel_v.volume_idx];
12427
12428 bool sinking = old_model_object->bounding_box().min.z() < SINKING_Z_THRESHOLD;
12429
12430 bool has_source = !old_volume->source.input_file.empty() && boost::algorithm::iequals(fs::path(old_volume->source.input_file).filename().string(), fs::path(path).filename().string());
12431 bool has_name = !old_volume->name.empty() && boost::algorithm::iequals(old_volume->name, fs::path(path).filename().string());
12432 if (has_source || has_name) {
12433 int new_volume_idx = -1;
12434 int new_object_idx = -1;
12435// if (has_source) {
12436// // take idxs from source
12437// new_volume_idx = old_volume->source.volume_idx;
12438// new_object_idx = old_volume->source.object_idx;
12439// }
12440// else {
12441 // take idxs from the 1st matching volume
12442 for (size_t o = 0; o < new_model.objects.size(); ++o) {
12443 ModelObject* obj = new_model.objects[o];
12444 bool found = false;
12445 for (size_t v = 0; v < obj->volumes.size(); ++v) {
12446 if (obj->volumes[v]->name == old_volume->name) {
12447 new_volume_idx = (int)v;
12448 new_object_idx = (int)o;
12449 found = true;
12450 break;
12451 }
12452 }
12453 if (found)
12454 break;
12455 }
12456// }
12457
12458 if (new_object_idx < 0 || int(new_model.objects.size()) <= new_object_idx) {
12459 fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
12460 continue;
12461 }
12462 ModelObject* new_model_object = new_model.objects[new_object_idx];
12463 if (new_volume_idx < 0 || int(new_model_object->volumes.size()) <= new_volume_idx) {
12464 fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
12465 continue;
12466 }
12467
12468 old_model_object->add_volume(*new_model_object->volumes[new_volume_idx]);
12469 ModelVolume* new_volume = old_model_object->volumes.back();
12470 new_volume->set_new_unique_id();
12471 new_volume->config.apply(old_volume->config);
12472 new_volume->set_type(old_volume->type());
12473 new_volume->set_material_id(old_volume->material_id());
12474 new_volume->set_transformation(old_volume->get_transformation());
12475 new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
12476 new_volume->source.object_idx = old_volume->source.object_idx;
12477 new_volume->source.volume_idx = old_volume->source.volume_idx;
12478 assert(! old_volume->source.is_converted_from_inches || ! old_volume->source.is_converted_from_meters);
12479 if (old_volume->source.is_converted_from_inches)
12480 new_volume->convert_from_imperial_units();
12481 else if (old_volume->source.is_converted_from_meters)
12482 new_volume->convert_from_meters();
12483 std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back());
12484 old_model_object->delete_volume(old_model_object->volumes.size() - 1);
12485 if (!sinking)
12486 old_model_object->ensure_on_bed();
12487 old_model_object->sort_volumes(true);
12488
12489 sla::reproject_points_and_holes(old_model_object);
12490 }
12491 }
12492#endif // ENABLE_RELOAD_FROM_DISK_REWORK
12493 }
12494
12495#if ENABLE_RELOAD_FROM_DISK_REWORK
12496 for (auto [src, dest] : replace_paths) {
12497 for (auto [obj_idx, vol_idx] : selected_volumes) {
12498 if (boost::algorithm::iequals(model.objects[obj_idx]->volumes[vol_idx]->source.input_file, src.string()))
12499 // When an error occurs, either the dest parsing error occurs, or the number of objects in the dest is greater than 1 and cannot be replaced, and cannot be replaced in this loop.
12500 if (!replace_volume_with_stl(obj_idx, vol_idx, dest, "")) break;
12501 }
12502 }
12503#else
12504 for (size_t i = 0; i < replace_paths.size(); ++i) {
12505 const auto& path = replace_paths[i].string();
12506 for (const SelectedVolume& sel_v : selected_volumes) {
12507 ModelObject* old_model_object = model.objects[sel_v.object_idx];
12508 ModelVolume* old_volume = old_model_object->volumes[sel_v.volume_idx];
12509 bool has_source = !old_volume->source.input_file.empty() && boost::algorithm::iequals(fs::path(old_volume->source.input_file).filename().string(), fs::path(path).filename().string());
12510 if (!replace_volume_with_stl(sel_v.object_idx, sel_v.volume_idx, path, "")) {
12511 fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
12512 }
12513 }
12514 }
12515#endif // ENABLE_RELOAD_FROM_DISK_REWORK
12516
12517 if (!fail_list.empty()) {
12518 wxString message = _L("Unable to reload:") + "\n";
12519 for (const wxString& s : fail_list) {
12520 message += s + "\n";
12521 }
12522 MessageDialog dlg(q, message, _L("Error during reload"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
12523 dlg.ShowModal();
12524 }
12525
12526 // update 3D scene
12527 update();
12528
12529 // new GLVolumes have been created at this point, so update their printable state
12530 for (size_t i = 0; i < model.objects.size(); ++i) {
12531 view3D->get_canvas3d()->update_instance_printable_state_for_object(i);
12532 }
12533
12534 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " finish.";
12535}
void search(bool plater_is_active, Preset::Type type, wxWindow *tag, TextInput *etag, wxWindow *stag)
Definition Plater.cpp:22503
void translation_transform(Transform3d &transform, const Vec3d &translation)
Definition Geometry.cpp:346
void reproject_points_and_holes(ModelObject *object)
Definition ReprojectPointsOnMesh.hpp:30
@ AddDefaultInstances
Definition bbs_3mf.hpp:220
bool replace_volume_with_stl(int object_idx, int volume_idx, const fs::path &new_path, const std::string &snapshot="")
Definition Plater.cpp:11784

References _L, _u8L, Slic3r::ModelObject::add_volume(), Slic3r::AddDefaultInstances, Slic3r::angle(), Slic3r::ModelConfig::apply(), background_process, Slic3r::ModelObject::center_around_origin(), Slic3r::ModelVolume::config, Slic3r::ModelVolume::convert_from_imperial_units(), Slic3r::ModelVolume::convert_from_meters(), Slic3r::ModelObject::delete_volume(), Slic3r::ModelObject::ensure_on_bed(), Slic3r::GUI::file_wildcards(), Slic3r::GUI::from_u8(), Slic3r::GUI::FT_MODEL, Slic3r::TriangleMesh::get_init_shift(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), Slic3r::GUI::Plater::get_selection(), Slic3r::ModelVolume::get_transformation(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::ModelObject::input_file, Slic3r::ModelVolume::Source::input_file, Slic3r::ModelVolume::Source::is_converted_from_inches, Slic3r::ModelVolume::Source::is_converted_from_meters, Slic3r::ModelVolume::Source::is_from_builtin_objects, Slic3r::ModelVolume::is_model_part(), Slic3r::GUI::Selection::is_wipe_tower(), Slic3r::LoadModel, Slic3r::ModelVolume::material_id(), Slic3r::ModelObject::mesh(), Slic3r::ModelVolume::mesh(), Slic3r::ModelVolume::Source::mesh_offset, Slic3r::ModelObject::min_z(), model, Slic3r::ModelObject::name, Slic3r::ModelVolume::name, Slic3r::GLVolume::object_idx(), Slic3r::ModelVolume::Source::object_idx, Slic3r::Model::objects, operator<(), partplate_list, q, Slic3r::Model::read_from_file(), Slic3r::Model::read_from_step(), Slic3r::release_PlateData_list(), replace_volume_with_stl(), Slic3r::sla::reproject_points_and_holes(), Slic3r::ModelVolume::restore_painting(), Slic3r::ModelVolume::save_painting(), Slic3r::GUI::Plater::search(), Slic3r::ModelVolume::set_material_id(), Slic3r::ModelVolume::set_new_unique_id(), Slic3r::ModelVolume::set_transformation(), Slic3r::ModelVolume::set_type(), Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, Slic3r::SINKING_Z_THRESHOLD, Slic3r::ModelObject::sort_volumes(), Slic3r::ModelVolume::source, Slic3r::string_to_double_decimal_point(), Slic3r::ModelVolume::translate(), Slic3r::Geometry::translation_transform(), Slic3r::ModelVolume::type(), Slic3r::GUI::Plater::update(), Slic3r::GUI::Preview::update_gcode_result(), view3D, Slic3r::GLVolume::volume_idx(), Slic3r::ModelVolume::Source::volume_idx, and Slic3r::ModelObject::volumes.

Here is the call graph for this function:

◆ remove()

void Slic3r::GUI::Plater::priv::remove ( size_t obj_idx)
10727{
10728 if (view3D->is_layers_editing_enabled())
10729 view3D->enable_layers_editing(false);
10730
10731 m_worker.cancel_all();
10732 std::string obj_name = (obj_idx < model.objects.size()) ? model.objects[obj_idx]->name : std::to_string(obj_idx);
10733 model.delete_object(obj_idx);
10734 {
10735 Slic3r::LifecycleEventContext ctx;
10736 ctx.name = obj_name;
10739 }
10740 //BBS: notify partplate the instance removed
10741 partplate_list.notify_instance_removed(obj_idx, -1);
10742 update();
10743 // Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
10744 sidebar->obj_list()->delete_object_from_list(obj_idx);
10746}

References Slic3r::LifecycleEventContext::code, Slic3r::fire_lifecycle_event(), m_worker, model, Slic3r::LifecycleEventContext::name, Slic3r::GUI::Plater::object_list_changed(), Slic3r::ObjectDeleted, Slic3r::Ok, partplate_list, sidebar, Slic3r::GUI::Plater::update(), and view3D.

Here is the call graph for this function:

◆ remove_curr_plate_all()

void Slic3r::GUI::Plater::priv::remove_curr_plate_all ( )
10704{
10705 SingleSnapshot ss(q);
10706 view3D->remove_curr_plate_all();
10707 this->sidebar->obj_list()->update_selections();
10708}

References Slic3r::GUI::Sidebar::obj_list(), q, Slic3r::GUI::ObjectList::update_selections(), and view3D.

Here is the call graph for this function:

◆ remove_dock_pane()

void Slic3r::GUI::Plater::priv::remove_dock_pane ( wxWindow * window)
8733{
8734 m_dock_panes.erase(window);
8735 if (m_aui_mgr.DetachPane(window))
8736 m_aui_mgr.Update();
8737 window->Destroy();
8738}

References m_aui_mgr, and m_dock_panes.

◆ replace_all_with_stl()

void Slic3r::GUI::Plater::priv::replace_all_with_stl ( )
11944{
11945 if (! q->get_view3D_canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::EType::Undefined))
11946 return;
11947
11948 const Selection& selection = get_selection();
11949
11950 if (selection.is_wipe_tower())
11951 return;
11952
11953 fs::path input_path;
11954 Selection::IndicesList volume_idxs = selection.get_volume_idxs();
11955
11956 // when plates are selected instead of volumes
11957 // then selection is inaccurate, we need to
11958 // find volumes contained in selected plates
11959
11960 if (selection.is_empty() || volume_idxs.empty()) {
11961 std::vector<int> selected_plate_idxs;
11962
11963 wxDataViewItemArray sels;
11964 wxGetApp().obj_list()->GetSelections(sels);
11965 for (const wxDataViewItem& item : sels) {
11966 Slic3r::GUI::ItemType item_type = wxGetApp().obj_list()->GetModel()->GetItemType(item);
11967 if (item_type & itPlate) {
11968 if (item.IsOk()) {
11969 ObjectDataViewModelNode *node = static_cast<ObjectDataViewModelNode *>(item.GetID());
11970 selected_plate_idxs.push_back(node->GetPlateIdx());
11971 }
11972 }
11973 }
11974 PartPlateList& plate_list = wxGetApp().plater()->get_partplate_list();
11975 for (int obj_idx = 0; obj_idx < selection.get_model()->objects.size(); obj_idx++) {
11976 for (int plate_idx : selected_plate_idxs) {
11977 PartPlate* plate = plate_list.get_plate(plate_idx);
11978 if (plate && plate->contain_instance_totally(obj_idx, 0)) {
11979 std::vector<unsigned int> indices = selection.get_volume_idxs_from_object(obj_idx);
11980 volume_idxs.insert(indices.begin(), indices.end());
11981 }
11982 }
11983 }
11984 }
11985
11986 // find path for initializing the file selection dialog
11987
11988 for (unsigned int idx : volume_idxs) {
11989 const GLVolume* v = selection.get_volume(idx);
11990 int object_idx = v->object_idx();
11991 int volume_idx = v->volume_idx();
11992
11993 const ModelObject* object = model.objects[object_idx];
11994 const ModelVolume* volume = object->volumes[volume_idx];
11995
11996 if (!volume->source.input_file.empty() && fs::exists(volume->source.input_file)) {
11997 input_path = volume->source.input_file;
11998 break;
11999 }
12000 }
12001
12002 wxString title = _L("Select folder to replace from");
12003 title += ":";
12004 wxDirDialog dialog(q, title, from_u8(input_path.parent_path().string()), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
12005 if (dialog.ShowModal() != wxID_OK)
12006 return;
12007
12008 fs::path out_path = dialog.GetPath().ToUTF8().data();
12009 if (out_path.empty()) {
12010 MessageDialog dlg(q, _L("Directory for the replace wasn't selected"), _L("Error during replacement"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
12011 dlg.ShowModal();
12012 return;
12013 }
12014
12015 wxString status = _L("Replaced with 3D files from directory:\n") + from_u8(out_path.string()) + "\n\n";
12016
12017 for (unsigned int idx : volume_idxs) {
12018 const GLVolume* v = selection.get_volume(idx);
12019 int object_idx = v->object_idx();
12020 int volume_idx = v->volume_idx();
12021
12022 const ModelObject* object = model.objects[object_idx];
12023 const ModelVolume* volume = object->volumes[volume_idx];
12024
12025 if (volume->source.input_file.empty())
12026 continue;
12027
12028 input_path = volume->source.input_file;
12029
12030 fs::path new_path = out_path / input_path.filename();
12031
12032 std::string volume_name = volume->name;
12033
12034 if (new_path == input_path) {
12035 status += wxString::Format(_L("✖ Skipped %s: same file.\n"), from_u8(volume_name));
12036 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " skipping replace volume : same filename " << new_path;
12037 continue;
12038 }
12039
12040 if (!fs::exists(new_path)) {
12041 status += wxString::Format(_L("✖ Skipped %s: file does not exist.\n"), from_u8(volume_name));
12042 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " cannot replace volume : filen does not exist " << new_path;
12043 continue;
12044 }
12045
12046 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " replacing volume : " << input_path << " with " << new_path;
12047
12048 if (!replace_volume_with_stl(object_idx, volume_idx, new_path, _u8L("Replace with 3D file"))) {
12049 status += wxString::Format(_L("✖ Skipped %s: failed to replace.\n"), from_u8(volume_name));
12050 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " cannot replace volume : failed to replace with " << new_path;
12051 continue;
12052 }
12053
12054 status += wxString::Format(_L("✔ Replaced %s.\n"), from_u8(volume_name));
12055 }
12056
12057 // update 3D scene
12058 update();
12059
12060 // new GLVolumes have been created at this point, so update their printable state
12061 for (size_t i = 0; i < model.objects.size(); ++i) {
12062 view3D->get_canvas3d()->update_instance_printable_state_for_object(i);
12063 }
12064
12065 MessageDialog dlg(q, status, _L("Replaced volumes"), wxOK | wxOK_DEFAULT | wxICON_INFORMATION);
12066 dlg.ShowModal();
12067}
@ Undefined
Definition GLGizmosManager.hpp:109
ItemType
Definition ObjectDataViewModel.hpp:34
@ itPlate
Definition ObjectDataViewModel.hpp:36
std::string volume_name(const EmbossShape &shape)
Create volume name from shape information.
Definition GLGizmoSVG.cpp:2142

References _L, _u8L, Slic3r::GUI::PartPlate::contain_instance_totally(), Slic3r::GUI::from_u8(), Slic3r::GUI::Selection::get_model(), Slic3r::GUI::PartPlateList::get_plate(), Slic3r::GUI::Plater::get_selection(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::GUI::Selection::get_volume_idxs_from_object(), Slic3r::GUI::ObjectDataViewModelNode::GetPlateIdx(), Slic3r::ModelVolume::Source::input_file, Slic3r::GUI::Selection::is_empty(), Slic3r::GUI::Selection::is_wipe_tower(), Slic3r::GUI::itPlate, model, Slic3r::ModelVolume::name, Slic3r::GLVolume::object_idx(), q, replace_volume_with_stl(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::ModelVolume::source, Slic3r::GUI::GLGizmosManager::Undefined, Slic3r::GUI::Plater::update(), view3D, and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ replace_volume_with_stl()

bool Slic3r::GUI::Plater::priv::replace_volume_with_stl ( int object_idx,
int volume_idx,
const fs::path & new_path,
const std::string & snapshot = "" )
11785{
11786 const std::string path = new_path.string();
11787 wxBusyCursor wait;
11788
11789 Model new_model;
11790 try {
11791 const bool is_step = boost::algorithm::iends_with(path, ".stp") || boost::algorithm::iends_with(path, ".step");
11792 if (is_step) {
11793 auto config = wxGetApp().app_config;
11794 double linear = std::max(0.003, string_to_double_decimal_point(config->get("linear_deflection")));
11795 double angle = std::max(0.5, string_to_double_decimal_point(config->get("angle_deflection")));
11796 bool split_compound = config->get_bool("is_split_compound");
11797 bool is_user_cancel = false;
11798
11799 auto callback = [&is_user_cancel, linear, angle, split_compound](Slic3r::Step &file, double &linear_value, double &angle_value, bool &is_split) -> int {
11800 if (wxGetApp().app_config->get_bool("enable_step_mesh_setting")) {
11801 StepMeshDialog mesh_dlg(nullptr, file, linear, angle);
11802 if (mesh_dlg.ShowModal() == wxID_OK) {
11803 linear_value = mesh_dlg.get_linear_deflection();
11804 angle_value = mesh_dlg.get_angle_deflection();
11805 is_split = mesh_dlg.get_split_compound_value();
11806 return 1;
11807 }
11808 } else {
11809 linear_value = linear;
11810 angle_value = angle;
11811 is_split = split_compound;
11812 return 1;
11813 }
11814 is_user_cancel = true;
11815 return -1;
11816 };
11817
11818 new_model = Model::read_from_step(path, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel, nullptr, nullptr, callback, linear, angle, split_compound);
11819 if (is_user_cancel) return false;
11820 } else {
11822 }
11823 for (ModelObject* model_object : new_model.objects) {
11824 model_object->center_around_origin();
11825 model_object->ensure_on_bed();
11826 }
11827 }
11828 catch (std::exception&) {
11829 // error while loading
11830 return false;
11831 }
11832
11833 if (new_model.objects.size() > 1 || new_model.objects.front()->volumes.size() > 1) {
11834 MessageDialog dlg(q, _L("Unable to replace with more than one volume"), _L("Error during replacement"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
11835 dlg.ShowModal();
11836 return false;
11837 }
11838
11839 wxBusyInfo info(_L("Replace from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
11840
11841 if (!snapshot.empty())
11842 q->take_snapshot(snapshot);
11843
11844 ModelObject* old_model_object = model.objects[object_idx];
11845 ModelVolume* old_volume = old_model_object->volumes[volume_idx];
11846
11847 bool sinking = old_model_object->min_z() < SINKING_Z_THRESHOLD;
11848
11849 ModelObject* new_model_object = new_model.objects.front();
11850 old_model_object->add_volume(*new_model_object->volumes.front());
11851 ModelVolume* new_volume = old_model_object->volumes.back();
11852 new_volume->set_new_unique_id();
11853 new_volume->config.apply(old_volume->config);
11854 new_volume->set_type(old_volume->type());
11855 new_volume->set_material_id(old_volume->material_id());
11856 new_volume->set_transformation(old_volume->get_transformation());
11857 new_volume->translate(new_volume->get_transformation().get_matrix_no_offset() * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
11858 assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
11859 if (old_volume->source.is_converted_from_inches)
11860 new_volume->convert_from_imperial_units();
11861 else if (old_volume->source.is_converted_from_meters)
11862 new_volume->convert_from_meters();
11863 if (wxGetApp().app_config->get_bool("keep_painting")) {
11864 // Proper paint remapping
11865 auto saved_painting = old_volume->save_painting();
11866 if (saved_painting) {
11867 saved_painting->mesh.transform(Geometry::translation_transform(new_volume->mesh().get_init_shift()));
11868 new_volume->restore_painting(saved_painting);
11869 }
11870 } else {
11871 // Won't work well if mesh changed, but kept for old behavior
11872 new_volume->supported_facets.assign(old_volume->supported_facets);
11873 new_volume->seam_facets.assign(old_volume->seam_facets);
11874 new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets);
11875 new_volume->fuzzy_skin_facets.assign(old_volume->fuzzy_skin_facets);
11876 }
11877 std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back());
11878 old_model_object->delete_volume(old_model_object->volumes.size() - 1);
11879 if (!sinking)
11880 old_model_object->ensure_on_bed();
11881 old_model_object->sort_volumes(true);
11882
11883 // if object has just one volume, rename object too
11884 if (old_model_object->volumes.size() == 1)
11885 old_model_object->name = old_model_object->volumes.front()->name;
11886
11887 // update new name in ObjectList
11888 sidebar->obj_list()->update_name_in_list(object_idx, volume_idx);
11889
11890 sla::reproject_points_and_holes(old_model_object);
11891
11892 return true;
11893}

References _L, Slic3r::ModelObject::add_volume(), Slic3r::AddDefaultInstances, Slic3r::angle(), Slic3r::ModelConfig::apply(), Slic3r::FacetsAnnotation::assign(), Slic3r::ModelObject::center_around_origin(), config, Slic3r::ModelVolume::config, Slic3r::ModelVolume::convert_from_imperial_units(), Slic3r::ModelVolume::convert_from_meters(), Slic3r::ModelObject::delete_volume(), Slic3r::ModelObject::ensure_on_bed(), Slic3r::GUI::from_u8(), Slic3r::ModelVolume::fuzzy_skin_facets, StepMeshDialog::get_angle_deflection(), Slic3r::TriangleMesh::get_init_shift(), StepMeshDialog::get_linear_deflection(), Slic3r::Geometry::Transformation::get_matrix_no_offset(), StepMeshDialog::get_split_compound_value(), Slic3r::ModelVolume::get_transformation(), Slic3r::ModelVolume::Source::is_converted_from_inches, Slic3r::ModelVolume::Source::is_converted_from_meters, Slic3r::LoadModel, Slic3r::ModelVolume::material_id(), Slic3r::ModelVolume::mesh(), Slic3r::ModelVolume::Source::mesh_offset, Slic3r::ModelObject::min_z(), Slic3r::ModelVolume::mmu_segmentation_facets, model, Slic3r::ModelObject::name, Slic3r::Model::objects, q, Slic3r::Model::read_from_file(), Slic3r::Model::read_from_step(), Slic3r::sla::reproject_points_and_holes(), Slic3r::ModelVolume::restore_painting(), Slic3r::ModelVolume::save_painting(), Slic3r::ModelVolume::seam_facets, Slic3r::ModelVolume::set_material_id(), Slic3r::ModelVolume::set_new_unique_id(), Slic3r::ModelVolume::set_transformation(), Slic3r::ModelVolume::set_type(), Slic3r::GUI::DPIAware< P >::ShowModal(), sidebar, Slic3r::SINKING_Z_THRESHOLD, Slic3r::ModelObject::sort_volumes(), Slic3r::ModelVolume::source, Slic3r::string_to_double_decimal_point(), Slic3r::ModelVolume::supported_facets, Slic3r::ModelVolume::translate(), Slic3r::Geometry::translation_transform(), Slic3r::ModelVolume::type(), and Slic3r::ModelObject::volumes.

Referenced by reload_from_disk(), replace_all_with_stl(), and replace_with_stl().

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

◆ replace_with_stl()

void Slic3r::GUI::Plater::priv::replace_with_stl ( )
11896{
11897 if (! q->get_view3D_canvas3D()->get_gizmos_manager().check_gizmos_closed_except(GLGizmosManager::EType::Undefined))
11898 return;
11899
11900 const Selection& selection = get_selection();
11901
11902 if (selection.is_wipe_tower() || get_selection().get_volume_idxs().size() != 1)
11903 return;
11904
11905 const GLVolume* v = selection.get_first_volume();
11906 int object_idx = v->object_idx();
11907 int volume_idx = v->volume_idx();
11908
11909 // collects paths of files to load
11910
11911 const ModelObject* object = model.objects[object_idx];
11912 const ModelVolume* volume = object->volumes[volume_idx];
11913
11914 fs::path input_path;
11915 if (!volume->source.input_file.empty() && fs::exists(volume->source.input_file))
11916 input_path = volume->source.input_file;
11917
11918 wxString title = _L("Select a new file");
11919 title += ":";
11920 wxFileDialog dialog(q, title, "", from_u8(input_path.filename().string()), file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
11921 if (dialog.ShowModal() != wxID_OK)
11922 return;
11923
11924 fs::path out_path = dialog.GetPath().ToUTF8().data();
11925 if (out_path.empty()) {
11926 MessageDialog dlg(q, _L("File for the replacement wasn\'t selected"), _L("Error during replacement"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
11927 dlg.ShowModal();
11928 return;
11929 }
11930
11931 if (!replace_volume_with_stl(object_idx, volume_idx, out_path, _u8L("Replace with 3D file")))
11932 return;
11933
11934 // update 3D scene
11935 update();
11936
11937 // new GLVolumes have been created at this point, so update their printable state
11938 for (size_t i = 0; i < model.objects.size(); ++i) {
11939 view3D->get_canvas3d()->update_instance_printable_state_for_object(i);
11940 }
11941}

References _L, _u8L, Slic3r::GUI::file_wildcards(), Slic3r::GUI::from_u8(), Slic3r::GUI::FT_MODEL, Slic3r::GUI::Selection::get_first_volume(), Slic3r::GUI::Plater::get_selection(), get_selection(), Slic3r::ModelVolume::Source::input_file, Slic3r::GUI::Selection::is_wipe_tower(), model, Slic3r::GLVolume::object_idx(), q, replace_volume_with_stl(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::ModelVolume::source, Slic3r::GUI::GLGizmosManager::Undefined, Slic3r::GUI::Plater::update(), view3D, and Slic3r::GLVolume::volume_idx().

Here is the call graph for this function:

◆ reset()

void Slic3r::GUI::Plater::priv::reset ( bool apply_presets_change = false,
bool reload_presets = true )
10824{
10825 // TakeSnapshot below and load_current_presets() further down each re-evaluate the
10826 // aggregate dirty flag against a baseline that hasn't been reset yet, so they can toggle
10827 // is_dirty() back and forth several times before it settles; coalesce those into one event.
10828 ProjectDirtyStateManager::NotificationSuppressor dirty_notify_suppressor(dirty_state);
10829
10830 Plater::TakeSnapshot snapshot(q, _u8L("Reset Project"), UndoRedo::SnapshotType::ProjectSeparator);
10831
10833
10834 const std::string closed_project_name = into_u8(get_project_filename());
10835 if (!closed_project_name.empty() || !model.objects.empty()) {
10836 Slic3r::LifecycleEventContext ctx;
10837 ctx.name = closed_project_name;
10840 }
10841 // A new project must not inherit the previous project's published selection (Feature A/B).
10845
10847 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " call set_project_filename: empty";
10848
10849 if (view3D->is_layers_editing_enabled())
10850 view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
10851 view3D->get_canvas3d()->reset_all_gizmos();
10852
10854 //BBS: update gcode to current partplate's
10855 //GCodeProcessorResult* current_result = this->background_process.get_current_plate()->get_slice_result();
10856 //current_result->reset();
10857 //gcode_result.reset();
10858
10859 view3D->get_canvas3d()->reset_sequential_print_clearance();
10860
10861 m_worker.cancel_all();
10862
10863 // Stop slicing before reinit() deletes the plates' prints. Deleting a Print only cancels the
10864 // background thread once a print-level step has started, so a slice still generating
10865 // perimeters or infill would keep running on freed layers.
10866 this->background_process.stop();
10867
10868 //BBS: clear the partplate list's object before object cleared
10869 partplate_list.reinit();
10870 partplate_list.update_slice_context_to_current_plate(background_process);
10871 preview->update_gcode_result(partplate_list.get_current_slice_result());
10872
10873 // Stop and reset the Print content.
10874 this->background_process.reset();
10875 model.clear_objects();
10876 // clear_objects() only drops the ModelObjects; the CAD recipe is Model-level state and would
10877 // otherwise be written into every project saved for the rest of the session.
10878 model.cad_recipe.clear();
10879#ifdef SLIC3R_CAD
10880 // Same reason, one level up: the Design tab keeps the editable document, not the Model, so
10881 // clearing the recipe alone leaves the tab showing the previous project's feature tree —
10882 // and its next edit syncs that tree straight back into the new project.
10883 if (DesignPanel* design = DesignPanel::if_built())
10884 design->clear_document();
10885#endif
10886 assemble_view->get_canvas3d()->reset_explosion_ratio();
10887 update();
10888
10889 //BBS
10890 if (wxGetApp().is_editor()) {
10891 // Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
10892 sidebar->obj_list()->delete_all_objects_from_list();
10894 }
10895
10896 project.reset();
10897
10898 wxGetApp().sidebar().printer_combox()->clear_selected_dev_id();
10899 //BBS: reset all project embedded presets
10900 wxGetApp().preset_bundle->reset_project_embedded_presets();
10901 if (apply_presets_change)
10902 wxGetApp().apply_keeped_preset_modifications();
10903 else if (reload_presets)
10904 wxGetApp().load_current_presets(false, false);
10905
10906 //BBS
10907 model.calib_pa_pattern.reset();
10908 model.plates_custom_gcodes.clear();
10909
10910 // BBS
10912
10913 // Save window layout
10914 if (sidebar_layout.is_enabled) {
10915 // Reset show state
10916 auto& sidebar = m_aui_mgr.GetPane(this->sidebar);
10917 if (!sidebar_layout.is_collapsed && !sidebar.IsShown()) {
10918 sidebar.Show();
10919 }
10920 auto layout = m_aui_mgr.SavePerspective();
10921 wxGetApp().app_config->set("window_layout", layout.utf8_string());
10922 }
10923}
@ ProjectSeparator
Definition UndoRedo.hpp:40
@ ProjectClosed
Definition LifecycleEvents.hpp:25
BBLProject project
Definition Plater.cpp:7747
void set_project_filename(const wxString &filename)
Definition Plater.cpp:14471
size_t m_backup_timestamp
Definition Plater.cpp:7785
size_t m_saved_timestamp
Definition Plater.cpp:7784

References _u8L, assemble_view, background_process, clear_warnings(), Slic3r::LifecycleEventContext::code, dirty_state, Slic3r::fire_lifecycle_event(), Slic3r::GUI::Plater::get_project_filename(), Slic3r::GUI::LazyInstance< DesignPanel >::if_built(), Slic3r::GUI::into_u8(), m_aui_mgr, m_backup_timestamp, m_has_pending_published, m_pending_material_keys, m_pending_published_keys, m_saved_timestamp, m_worker, model, Slic3r::LifecycleEventContext::name, Slic3r::GUI::Plater::object_list_changed(), Slic3r::Ok, partplate_list, preview, project, Slic3r::ProjectClosed, Slic3r::UndoRedo::ProjectSeparator, q, Slic3r::BackgroundSlicingProcess::reset(), Slic3r::GUI::Plater::reset_gcode_toolpaths(), Slic3r::GUI::Plater::set_project_filename(), sidebar, sidebar_layout, Slic3r::BackgroundSlicingProcess::stop(), Slic3r::GUI::Plater::update(), and view3D.

Here is the call graph for this function:

◆ reset_all_gizmos()

void Slic3r::GUI::Plater::priv::reset_all_gizmos ( )
8767{
8768 view3D->get_canvas3d()->reset_all_gizmos();
8769}

References view3D.

◆ reset_canvas_volumes()

void Slic3r::GUI::Plater::priv::reset_canvas_volumes ( )
14638{
14639 if (view3D != nullptr)
14640 view3D->get_canvas3d()->reset_volumes();
14641
14642 if (preview != nullptr)
14643 preview->get_canvas3d()->reset_volumes();
14644
14645#ifdef SLIC3R_CAD
14646 if (DesignPanel* design = DesignPanel::if_built())
14647 design->reset_canvas_volumes();
14648#endif
14649}

References Slic3r::GUI::LazyInstance< DesignPanel >::if_built(), preview, and view3D.

Here is the call graph for this function:

◆ reset_gcode_toolpaths()

void Slic3r::GUI::Plater::priv::reset_gcode_toolpaths ( )
14842{
14843 preview->get_canvas3d()->reset_gcode_toolpaths();
14844}

References preview.

◆ reset_project_dirty_after_save()

void Slic3r::GUI::Plater::priv::reset_project_dirty_after_save ( )
inline
7340{ m_undo_redo_stack_main.mark_current_as_saved(); dirty_state.reset_after_save(); }

References dirty_state, and m_undo_redo_stack_main.

◆ reset_project_dirty_initial_presets()

void Slic3r::GUI::Plater::priv::reset_project_dirty_initial_presets ( )
inline
7341{ dirty_state.reset_initial_presets(); }

References dirty_state.

◆ reset_window_layout()

void Slic3r::GUI::Plater::priv::reset_window_layout ( )
8672{
8673 m_aui_mgr.LoadPerspective(m_default_window_layout, false);
8674 // Loading a layout docks and hides every pane it does not list, and the default layout lists no
8675 // dock panes: a floating dock pane is docked again, like the rest of the window.
8676 for (const auto& [window, dock_pane] : m_dock_panes)
8677 if (wxAuiPaneInfo& pane = m_aui_mgr.GetPane(window); pane.IsOk())
8678 pane.Show(dock_pane_visible(dock_pane, pane));
8679 sidebar_layout.is_collapsed = false;
8680 update_sidebar(true);
8681}

References dock_pane_visible(), m_aui_mgr, m_default_window_layout, m_dock_panes, sidebar_layout, and update_sidebar().

Here is the call graph for this function:

◆ restart_background_process()

bool Slic3r::GUI::Plater::priv::restart_background_process ( unsigned int state)
11623{
11624 if (!m_worker.is_idle()) {
11625 // Avoid a race condition
11626 BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: ui jobs running, return false")%__LINE__;
11627 return false;
11628 }
11629
11630 if ( ! this->background_process.empty() &&
11632 ( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) ||
11634 (state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) {
11635 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: print is valid, try to start it now")%__LINE__;
11636 // The print is valid and it can be started.
11637 if (this->background_process.start()) {
11640 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: start successfully")%__LINE__;
11641 return true;
11642 }
11643 }
11644 else if (this->background_process.empty()) {
11645 PartPlate* cur_plate = background_process.get_current_plate();
11646 if (cur_plate->is_slice_result_valid() && ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0)) {
11647 if (this->background_process.start()) {
11650 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: start successfully")%__LINE__;
11651 return true;
11652 }
11653 }
11654 }
11655 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: not started")%__LINE__;
11656 return false;
11657}
void on_slicing_began()
Definition Plater.cpp:13267

References background_process, Slic3r::BackgroundSlicingProcess::empty(), Slic3r::GUI::PartPlate::is_slice_result_valid(), m_worker, on_slicing_began(), show_warning_dialog, Slic3r::BackgroundSlicingProcess::start(), UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT, UPDATE_BACKGROUND_PROCESS_FORCE_RESTART, UPDATE_BACKGROUND_PROCESS_INVALID, and UPDATE_BACKGROUND_PROCESS_RESTART.

Referenced by export_gcode(), export_gcode(), update(), and update_restart_background_process().

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

◆ run_textured_mesh_import_dialog()

bool Slic3r::GUI::Plater::priv::run_textured_mesh_import_dialog ( Slic3r::Model & loaded_model,
TextureImportResult & result,
std::function< bool()> cancel_callback = {},
std::function< bool(int)> progress_callback = {} )
15731{
15732 if (!loaded_model.texture_mesh || !has_importable_texture(*loaded_model.texture_mesh)) return false;
15733
15734 // Defense in depth: if all geometry got dropped earlier (e.g. by a future
15735 // regression of the zero-volume cleanup) but the textured mesh is still
15736 // alive, there is nothing for the dialog to paint onto. Skip the dialog
15737 // gracefully so load_files() can fall through to its "no geometry"
15738 // message instead of making the user round-trip a meaningless matcher.
15739 if (loaded_model.objects.empty()) {
15740 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: skipping dialog because the loaded model has no geometry objects";
15741 loaded_model.texture_mesh.reset();
15742 result.skipped = true;
15743 return true;
15744 }
15745
15746 const wxString fallback_warning = _L("Texture import failed. The model appears to contain texture data, but the texture import process could not be completed. The model will be imported as geometry only.");
15747
15748 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: opening texture import dialog";
15749
15750 std::vector<TextureFilamentEntry> filament_entries;
15751 {
15752 auto& preset_bundle = *wxGetApp().preset_bundle;
15753 auto& project_config = preset_bundle.project_config;
15754 auto* colours_opt = project_config.option<ConfigOptionStrings>("filament_colour");
15755 auto* is_mixed_opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
15756 auto* type_opt = project_config.option<ConfigOptionStrings>("filament_type");
15757 auto* components_opt = project_config.option<ConfigOptionStrings>("filament_mixed_components");
15758 auto* ratios_opt = project_config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios");
15759 const size_t total = preset_bundle.filament_presets.size();
15760 filament_entries.reserve(total);
15761 for (size_t i = 0; i < total; ++i) {
15762 TextureFilamentEntry entry;
15763 entry.kind = (is_mixed_opt && i < is_mixed_opt->values.size() && is_mixed_opt->values[i]) ?
15765 entry.dialog_index = (int)filament_entries.size();
15766 entry.project_config_index = i;
15767 entry.color_hex = (colours_opt && i < colours_opt->values.size()) ? colours_opt->values[i] : "#808080";
15768 entry.type = (type_opt && i < type_opt->values.size()) ? type_opt->values[i] : "";
15769
15770 std::string name;
15771 if (i < preset_bundle.filament_presets.size()) {
15772 auto* preset = preset_bundle.filaments.find_preset(preset_bundle.filament_presets[i]);
15773 if (preset)
15774 name = preset->label(false);
15775 }
15776 if (name.empty())
15777 name = into_u8(wxString::Format(_L("Filament %d"), int(i + 1)));
15778 entry.name = name;
15779
15780 if (entry.kind == TextureFilamentKind::ExistingMixed) {
15781 if (components_opt && i < components_opt->values.size())
15782 entry.mixed_components = Slic3r::parse_mixed_components(components_opt->values[i]);
15783 std::vector<double> ratios = Slic3r::parse_mixed_ratios(
15784 ratios_opt && i < ratios_opt->values.size() ? ratios_opt->values[i] : "",
15785 entry.mixed_components.size());
15786 entry.mixed_ratios.reserve(ratios.size());
15787 for (double ratio : ratios)
15788 entry.mixed_ratios.push_back((int)std::lround(ratio * 100.0));
15789 }
15790 filament_entries.push_back(std::move(entry));
15791 }
15792 }
15793
15794 TextureImportDialog dlg(q, *loaded_model.texture_mesh, filament_entries,
15795 std::move(cancel_callback), std::move(progress_callback));
15796 if (dlg.ShowModal() != wxID_OK) {
15797 if (dlg.was_skipped()) {
15798 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: user skipped texture matching";
15799 result.skipped = true;
15800 loaded_model.texture_mesh.reset();
15801 return true;
15802 }
15803 if (dlg.fallback_to_geometry_only()) {
15804 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: texture import failed, falling back to geometry-only import";
15805 result.fallback_to_geometry_only = true;
15806 result.fallback_warning = fallback_warning;
15807 loaded_model.texture_mesh.reset();
15808 return true;
15809 }
15810 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: user cancelled";
15811 loaded_model.texture_mesh.reset();
15812 return false;
15813 }
15814
15815 auto painted = dlg.get_painted_mesh();
15816 auto final_matches = dlg.get_matches();
15817
15818 if (painted.face_colors.empty() || final_matches.empty()) {
15819 BOOST_LOG_TRIVIAL(warning) << "handle_textured_mesh_import: no painting result";
15820 result.fallback_to_geometry_only = true;
15821 result.fallback_warning = fallback_warning;
15822 loaded_model.texture_mesh.reset();
15823 return true;
15824 }
15825
15826 BOOST_LOG_TRIVIAL(info) << "handle_textured_mesh_import: got " << painted.cluster_colors.size()
15827 << " clusters, skipped=" << dlg.was_skipped();
15828
15829 result.painted = std::move(painted);
15830 result.matches = std::move(final_matches);
15831 result.new_filament_colors = dlg.get_new_filament_colors();
15832 result.new_filament_preset_names = dlg.get_new_filament_preset_names();
15833 result.new_mixed_filaments = dlg.get_new_mixed_filaments();
15834 result.filament_entries = dlg.get_filament_entries();
15835 result.existing_filament_count = dlg.get_existing_filament_count();
15836 result.skipped = dlg.was_skipped();
15837 return true;
15838}
std::vector< unsigned int > parse_mixed_components(const std::string &str)
Definition FilamentMixer.cpp:172
std::vector< double > parse_mixed_ratios(const std::string &str, size_t n_components)
Definition FilamentMixer.cpp:404

References _L, Slic3r::GUI::TextureFilamentEntry::color_hex, Slic3r::GUI::TextureFilamentEntry::dialog_index, Slic3r::GUI::Plater::priv::TextureImportResult::existing_filament_count, Slic3r::GUI::ExistingMixed, Slic3r::GUI::ExistingPhysical, Slic3r::GUI::Plater::priv::TextureImportResult::fallback_to_geometry_only, Slic3r::GUI::TextureImportDialog::fallback_to_geometry_only(), Slic3r::GUI::Plater::priv::TextureImportResult::fallback_warning, Slic3r::GUI::Plater::priv::TextureImportResult::filament_entries, Slic3r::GUI::TextureImportDialog::get_existing_filament_count(), Slic3r::GUI::TextureImportDialog::get_filament_entries(), Slic3r::GUI::TextureImportDialog::get_matches(), Slic3r::GUI::TextureImportDialog::get_new_filament_colors(), Slic3r::GUI::TextureImportDialog::get_new_filament_preset_names(), Slic3r::GUI::TextureImportDialog::get_new_mixed_filaments(), Slic3r::GUI::TextureImportDialog::get_painted_mesh(), Slic3r::GUI::has_importable_texture(), Slic3r::GUI::into_u8(), Slic3r::GUI::TextureFilamentEntry::kind, Slic3r::GUI::Plater::priv::TextureImportResult::matches, Slic3r::GUI::TextureFilamentEntry::mixed_components, Slic3r::GUI::TextureFilamentEntry::mixed_ratios, Slic3r::GUI::TextureFilamentEntry::name, Slic3r::GUI::Plater::priv::TextureImportResult::new_filament_colors, Slic3r::GUI::Plater::priv::TextureImportResult::new_filament_preset_names, Slic3r::GUI::Plater::priv::TextureImportResult::new_mixed_filaments, Slic3r::Model::objects, Slic3r::GUI::Plater::priv::TextureImportResult::painted, Slic3r::parse_mixed_components(), Slic3r::parse_mixed_ratios(), Slic3r::GUI::TextureFilamentEntry::project_config_index, q, Slic3r::GUI::TextureImportDialog::ShowModal(), Slic3r::ConfigOptionVector< T >::size(), Slic3r::GUI::Plater::priv::TextureImportResult::skipped, Slic3r::Model::texture_mesh, Slic3r::GUI::TextureFilamentEntry::type, Slic3r::ConfigOptionVector< T >::values, Slic3r::ConfigOptionVector< unsigned char >::values, and Slic3r::GUI::TextureImportDialog::was_skipped().

Referenced by handle_textured_mesh_import(), and load_files().

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

◆ save_project_if_dirty()

int Slic3r::GUI::Plater::priv::save_project_if_dirty ( const wxString & reason)
inline
7320 {
7321 int res = wxID_NO;
7322 if (dirty_state.is_dirty()) {
7323 MainFrame* mainframe = wxGetApp().mainframe;
7324 if (mainframe->can_save_as()) {
7325 wxString suggested_project_name;
7326 wxString project_name = suggested_project_name = get_project_filename(".3mf");
7327 if (suggested_project_name.IsEmpty()) {
7328 fs::path output_file = get_export_file_path(FT_3MF);
7329 suggested_project_name = output_file.empty() ? _L("Untitled") : from_u8(output_file.stem().string());
7330 }
7331 res = MessageDialog(mainframe, reason + "\n" + format_wxstr(_L("Do you want to save changes to \"%1%\"?"), suggested_project_name),
7332 wxString(SLIC3R_APP_FULL_NAME), wxYES_NO | wxCANCEL).ShowModal();
7333 if (res == wxID_YES)
7334 if (!mainframe->save_project_as(project_name))
7335 res = wxID_CANCEL;
7336 }
7337 }
7338 return res;
7339 }

References _L, Slic3r::GUI::MainFrame::can_save_as(), dirty_state, Slic3r::GUI::format_wxstr(), Slic3r::GUI::from_u8(), Slic3r::GUI::FT_3MF, get_export_file_path(), get_project_filename(), Slic3r::GUI::MainFrame::save_project_as(), Slic3r::GUI::DPIAware< P >::ShowModal(), and SLIC3R_APP_FULL_NAME.

Here is the call graph for this function:

◆ scale_selection_to_fit_print_volume()

void Slic3r::GUI::Plater::priv::scale_selection_to_fit_print_volume ( )
11092{
11093#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
11094 const BuildVolume volume = this->bed.build_volume();
11095 // Every plate shares the bed size, but each sits at its own origin: fit onto the
11096 // plate the selection is on instead of always onto the first one.
11097 PartPlate* plate = this->partplate_list.get_curr_plate();
11098 const Vec3d bed_center = plate != nullptr ? plate->get_center_origin() :
11099 Vec3d(volume.bed_center().x(), volume.bed_center().y(), 0.);
11100 // On a multi-nozzle printer each nozzle reaches only part of the bed, so a model fitted
11101 // to the bed can still exceed a nozzle's printable range. Fit into the volume every
11102 // nozzle shares, which is also the area Arrange places items in, minus any exclusion zone.
11103 const BoundingBoxf3 bed_box = plate != nullptr ? plate->get_build_volume(true) : volume.bounding_volume();
11104 std::vector<BoundingBoxf3> print_volumes{ bed_box };
11105 if (plate != nullptr && !plate->get_exclude_areas().empty())
11106 print_volumes = free_print_volumes(bed_box, plate->get_exclude_areas());
11107 this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(volume, Vec2d(bed_center.x(), bed_center.y()), print_volumes);
11108#else
11109 this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(*config);
11110#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
11111}
static std::vector< BoundingBoxf3 > free_print_volumes(const BoundingBoxf3 &bed, const std::vector< BoundingBoxf3 > &excludes)
Definition Plater.cpp:11048

References Slic3r::BuildVolume::bed_center(), Slic3r::BuildVolume::bounding_volume(), Slic3r::GUI::Bed3D::build_volume(), config, Slic3r::GUI::free_print_volumes(), Slic3r::GUI::PartPlate::get_build_volume(), Slic3r::GUI::View3D::get_canvas3d(), Slic3r::GUI::PartPlate::get_center_origin(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::get_exclude_areas(), Slic3r::GUI::GLCanvas3D::get_selection(), and Slic3r::GUI::Selection::scale_to_fit_print_volume().

Here is the call graph for this function:

◆ scaled_bed_shape_bb()

BoundingBox Slic3r::GUI::Plater::priv::scaled_bed_shape_bb ( ) const
8801{
8802 const auto *bed_shape_opt = config->opt<ConfigOptionPoints>("printable_area");
8803 const auto printable_area = Slic3r::Polygon::new_scale(bed_shape_opt->values);
8804 return printable_area.bounding_box();
8805}
static Polygon new_scale(const std::vector< Vec2d > &points)
Definition Polygon.hpp:38
zaa_minimize_perimeter_height printable_area((ConfigOptionPointsGroups, extruder_printable_area))((ConfigOptionBool

References config, Slic3r::Polygon::new_scale(), and Slic3r::printable_area().

Referenced by bed_shape_bb().

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

◆ schedule_auto_reslice_if_needed()

void Slic3r::GUI::Plater::priv::schedule_auto_reslice_if_needed ( )
11123{
11124 AppConfig* cfg = wxGetApp().app_config;
11125 if (cfg == nullptr || !cfg->get_bool("auto_slice_after_change"))
11126 return;
11127
11128 if (!is_preview_shown())
11129 return;
11130
11131 if (model.objects.empty())
11132 return;
11133
11134 PartPlate* plate = partplate_list.get_curr_plate();
11135 if (plate == nullptr || !plate->has_printable_instances())
11136 return;
11137
11138 if (background_process.running() || m_is_slicing) {
11139 // Remember to restart once the current slice stops and cancel it now.
11141 background_process.stop();
11142 return;
11143 }
11144
11145 const int delay_seconds = auto_slice_delay_seconds();
11146 if (delay_seconds > 0) {
11147 auto_reslice_pending = true;
11148 auto_reslice_timer.Stop();
11149 auto_reslice_timer.Start(delay_seconds * 1000, wxTIMER_ONE_SHOT);
11150 return;
11151 }
11152
11154 return;
11155
11156 auto_reslice_pending = true;
11157 auto_reslice_timer.Stop();
11158 wxGetApp().CallAfter([this]() { this->trigger_auto_reslice_now(); });
11159}
bool auto_reslice_pending
Definition Plater.cpp:7234
bool is_preview_shown() const
Definition Plater.cpp:7358
int auto_slice_delay_seconds() const
Definition Plater.cpp:11185

References auto_reslice_after_cancel, auto_reslice_pending, auto_reslice_timer, auto_slice_delay_seconds(), background_process, Slic3r::AppConfig::get_bool(), Slic3r::GUI::PartPlate::has_printable_instances(), Slic3r::GUI::Plater::is_preview_shown(), m_is_slicing, model, partplate_list, and trigger_auto_reslice_now().

Referenced by on_process_completed().

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

◆ schedule_background_process()

void Slic3r::GUI::Plater::priv::schedule_background_process ( )
11114{
11115 delayed_error_message.clear();
11116 // Trigger the timer event after 0.5s
11117 this->background_process_timer.Start(500, wxTIMER_ONE_SHOT);
11118 // Notify the Canvas3D that something has changed, so it may invalidate some of the layer editing stuff.
11119 this->view3D->get_canvas3d()->set_config(this->config);
11120}

References delayed_error_message, Slic3r::GUI::View3D::get_canvas3d(), and Slic3r::GUI::GLCanvas3D::set_config().

Referenced by load_model_objects().

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

◆ select_all()

void Slic3r::GUI::Plater::priv::select_all ( )
10711{
10712 view3D->select_all();
10713 this->sidebar->obj_list()->update_selections();
10714}

References Slic3r::GUI::Sidebar::obj_list(), Slic3r::GUI::ObjectList::update_selections(), and view3D.

Here is the call graph for this function:

◆ select_curr_plate_all()

void Slic3r::GUI::Plater::priv::select_curr_plate_all ( )
10698{
10699 view3D->select_curr_plate_all();
10700 this->sidebar->obj_list()->update_selections();
10701}

References Slic3r::GUI::Sidebar::obj_list(), Slic3r::GUI::ObjectList::update_selections(), and view3D.

Here is the call graph for this function:

◆ select_next_view_3D()

void Slic3r::GUI::Plater::priv::select_next_view_3D ( )
8601{
8602
8603 if (current_panel == view3D)
8604 wxGetApp().mainframe->select_tab(TAB_ID_PREVIEW);
8605 else if (current_panel == preview)
8606 wxGetApp().mainframe->select_tab(TAB_ID_PREPARE);
8607// else if (current_panel == assemble_view)
8608// set_current_panel(view3D);
8609}

References current_panel, preview, TAB_ID_PREPARE, TAB_ID_PREVIEW, and view3D.

◆ select_view()

void Slic3r::GUI::Plater::priv::select_view ( const std::string & direction)
8443{
8444 if (current_panel == view3D) {
8445 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << "select view3D";
8446 view3D->select_view(direction);
8447 wxGetApp().update_ui_from_settings();
8448 }
8449 else if (current_panel == preview) {
8450 BOOST_LOG_TRIVIAL(info) << "select preview";
8451 preview->select_view(direction);
8452 wxGetApp().update_ui_from_settings();
8453 }
8454 else if (current_panel == assemble_view) {
8455 BOOST_LOG_TRIVIAL(info) << "select assemble view";
8456 assemble_view->select_view(direction);
8457 }
8458}

References assemble_view, current_panel, preview, and view3D.

◆ select_view_3D()

void Slic3r::GUI::Plater::priv::select_view_3D ( const std::string & name,
bool no_slice = true )
8568{
8569 if (name == "3D") {
8570 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << "select view3D";
8571 if (q->only_gcode_mode() || q->using_exported_file()) {
8572 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("goto preview page when loading gcode/exported_3mf");
8573 }
8574 set_current_panel(view3D, no_slice);
8575 }
8576 else if (name == "Preview") {
8577 BOOST_LOG_TRIVIAL(info) << "select preview";
8578 //BBS update extruder params and speed table before slicing
8579 const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
8580 auto& print = q->get_partplate_list().get_current_fff_print();
8581 auto print_config = print.config();
8582 int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
8583
8584 Model::setExtruderParams(config, numExtruders);
8585 Model::setPrintSpeedTable(config, print_config);
8586 set_current_panel(preview, no_slice);
8587 }
8588 else if (name == "Assemble") {
8589 BOOST_LOG_TRIVIAL(info) << "select assemble view";
8591 }
8592
8593 //BBS update selection
8594 wxGetApp().obj_list()->update_selections();
8596
8598}
void apply_free_camera_correction(bool apply=true)
Definition Plater.cpp:8555

References apply_free_camera_correction(), assemble_view, config, preview, q, selection_changed(), set_current_panel(), Slic3r::Model::setExtruderParams(), Slic3r::Model::setPrintSpeedTable(), and view3D.

Here is the call graph for this function:

◆ selection_changed()

void Slic3r::GUI::Plater::priv::selection_changed ( )
10656{
10657 // if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running
10658 if (!layers_height_allowed() && view3D->is_layers_editing_enabled()) {
10659 SimpleEvent evt(EVT_GLTOOLBAR_LAYERSEDITING);
10661 }
10662
10663 // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
10664 if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
10665 assemble_view->render();
10666 } else {
10667 view3D->render();
10668 }
10669}
@ CanvasAssembleView
Definition GLCanvas3D.hpp:628

References assemble_view, Slic3r::GUI::GLCanvas3D::CanvasAssembleView, Slic3r::GUI::Plater::get_current_canvas3D(), layers_height_allowed(), on_action_layersediting(), and view3D.

Referenced by on_object_select(), and select_view_3D().

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

◆ set_bed_shape()

void Slic3r::GUI::Plater::priv::set_bed_shape ( const Pointfs & shape,
const Pointfs & exclude_areas,
const Pointfs & wrapping_exclude_areas,
const double printable_height,
std::vector< Pointfs > extruder_areas,
std::vector< double > extruder_heights,
const std::string & custom_texture,
const std::string & custom_model,
bool force_as_custom = false )
14994{
14995 //Orca: reduce resolution for large bed printer
14996 BoundingBoxf bed_size = get_extents(shape);
14997 if (bed_size.size().maxCoeff() <= LARGE_BED_THRESHOLD)
14999 else
15001
15002 //BBS: add shape position
15003 Vec2d shape_position = partplate_list.get_current_shape_position();
15004 bool new_shape = bed.set_shape(shape, printable_height, extruder_areas, extruder_heights, custom_model, force_as_custom, shape_position);
15005
15006
15007 float prev_height_lid, prev_height_rod;
15008 partplate_list.get_height_limits(prev_height_lid, prev_height_rod);
15009 double height_to_lid = config->opt_float("extruder_clearance_height_to_lid");
15010 double height_to_rod = config->opt_float("extruder_clearance_height_to_rod");
15011
15012 Pointfs prev_exclude_areas = partplate_list.get_exclude_area();
15013 Pointfs prev_wrapping_exclude_areas = partplate_list.get_wrapping_exclude_area();
15014 new_shape |= (height_to_lid != prev_height_lid) || (height_to_rod != prev_height_rod) || (prev_exclude_areas != exclude_areas)
15015 || (prev_wrapping_exclude_areas != wrapping_exclude_areas);
15016 if (!new_shape && partplate_list.get_logo_texture_filename() != custom_texture) {
15017 partplate_list.update_logo_texture_filename(custom_texture);
15018 }
15019 if (new_shape) {
15020 if (view3D) view3D->bed_shape_changed();
15021 if (preview) preview->bed_shape_changed();
15022
15023 //BBS: update part plate's size
15024 // BBS: to be checked
15025 Vec3d max = bed.printable_bounding_box().max;
15026 Vec3d min = bed.printable_bounding_box().min;
15027 double z = config->opt_float("printable_height");
15028
15029 partplate_list.reset_size(max.x() - min.x() - Bed3D::Axes::DefaultTipRadius, max.y() - min.y() - Bed3D::Axes::DefaultTipRadius, z);
15030 partplate_list.set_shapes(shape, exclude_areas, wrapping_exclude_areas, extruder_areas, extruder_heights, custom_texture, height_to_lid, height_to_rod);
15031
15032 Vec2d new_shape_position = partplate_list.get_current_shape_position();
15033 if (shape_position != new_shape_position)
15034 bed.set_shape(shape, printable_height, extruder_areas, extruder_heights, custom_model, force_as_custom, new_shape_position);
15035 }
15036}
static constexpr double SCALING_FACTOR_INTERNAL_LARGE_PRINTER
Definition libslic3r.h:66
static constexpr double SCALING_FACTOR_INTERNAL
Definition libslic3r.h:65
static constexpr double LARGE_BED_THRESHOLD
Definition libslic3r.h:67
std::vector< Vec2d > Pointfs
Definition Point.hpp:77
BoundingBox get_extents(const ExPolygonsWithIds &e)
Definition Emboss.cpp:1374
zaa_minimize_perimeter_height printable_height((ConfigOptionFloatsNullable, extruder_printable_height))((ConfigOptionPoint

References bed, config, Slic3r::GUI::Bed3D::Axes::DefaultTipRadius, Slic3r::get_extents(), LARGE_BED_THRESHOLD, partplate_list, preview, Slic3r::printable_height(), SCALING_FACTOR, SCALING_FACTOR_INTERNAL, SCALING_FACTOR_INTERNAL_LARGE_PRINTER, Slic3r::BoundingBoxBase< PointType, APointsType >::size(), and view3D.

Here is the call graph for this function:

◆ set_current_canvas_as_dirty()

void Slic3r::GUI::Plater::priv::set_current_canvas_as_dirty ( )
14594{
14595 if (current_panel == view3D)
14596 view3D->set_as_dirty();
14597 else if (current_panel == preview)
14598 preview->set_as_dirty();
14599 else if (current_panel == assemble_view)
14600 assemble_view->set_as_dirty();
14601}

References assemble_view, current_panel, preview, and view3D.

◆ set_current_panel()

void Slic3r::GUI::Plater::priv::set_current_panel ( wxPanel * panel,
bool no_slice = true )
12559{
12560 if (std::find(panels.begin(), panels.end(), panel) == panels.end())
12561 return;
12562
12563 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": current_panel %1%, new_panel %2%")%current_panel%panel;
12564#ifdef __WXMAC__
12565 bool force_render = (current_panel != nullptr);
12566#endif // __WXMAC__
12567
12568 //BBS: add slice logic when switch to preview page
12569 auto do_reslice = [this, no_slice]() {
12570 // see: Plater::priv::object_list_changed()
12571 // FIXME: it may be better to have a single function making this check and let it be called wherever needed
12572 bool export_in_progress = this->background_process.is_export_scheduled();
12573 ObjectFilamentResults object_results;
12574 bool model_fits = this->view3D->get_canvas3d()->check_volumes_outside_state(&object_results) != ModelInstancePVS_Partly_Outside;
12575 model_fits = model_fits&&object_results.filaments.empty();
12576 //BBS: add partplate logic
12577 PartPlate * current_plate = this->partplate_list.get_curr_plate();
12578 bool only_has_gcode_need_preview = false;
12579 bool current_has_print_instances = current_plate->has_printable_instances();
12580 if (current_plate->is_slice_result_valid() && this->model.objects.empty() && !current_has_print_instances)
12581 only_has_gcode_need_preview = true;
12582
12583 bool mixed_broken = sidebar->has_broken_mixed_filament();
12584
12585 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": from set_current_panel, no_slice %1%, export_in_progress %2%, model_fits %3%, m_is_slicing %4%, mixed_broken %5%")%no_slice%export_in_progress%model_fits%m_is_slicing%mixed_broken;
12586
12587 if (!no_slice && !this->model.objects.empty() && !export_in_progress && model_fits && current_has_print_instances && !mixed_broken)
12588 {
12589 //if already running in background, not relice here
12590 //BBS: add more judge for slicing
12591 if (!this->background_process.running() && !this->m_is_slicing)
12592 {
12593 this->m_slice_all = false;
12594 this->q->reslice();
12595 }
12596 else {
12597 //reset current plate to the slicing plate
12598 int plate_index = this->background_process.get_current_plate()->get_index();
12599 this->partplate_list.select_plate(plate_index);
12600 }
12601 }
12602 else if (only_has_gcode_need_preview)
12603 {
12604 this->m_slice_all = false;
12605 this->q->reslice();
12606 }
12607 //BBS: process empty plate, reset previous toolpath
12608 else
12609 {
12610 //if (!this->m_slice_all)
12611 if (!current_has_print_instances)
12613 //this->q->refresh_print();
12614 if (!preview->get_canvas3d()->is_initialized())
12615 {
12616 preview->get_canvas3d()->render(true);
12617 }
12618 }
12619 //TODO: turn off this switch currently
12620 /*auto canvas_w = float(preview->get_canvas3d()->get_canvas_size().get_width());
12621 auto canvas_h = float(preview->get_canvas3d()->get_canvas_size().get_height());
12622 Point screen_center(canvas_w/2, canvas_h/2);
12623 auto center_point = preview->get_canvas3d()->_mouse_to_3d(screen_center);
12624 center_point(2) = 0.f;
12625 if (!current_plate->contains(center_point))
12626 this->partplate_list.select_plate_view();*/
12627
12628 // keeps current gcode preview, if any
12629 if (this->m_slice_all) {
12630 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": slicing all, just reload shells");
12632 }
12633 else {
12634 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": single slice, reload print");
12635 if (model_fits)
12636 this->preview->reload_print(); // TODO
12637 else
12639 }
12640
12641 preview->set_as_dirty();
12642 };
12643
12644 // Add sidebar and toolbar collapse logic
12645 if (panel == view3D || panel == preview) {
12646 this->enable_sidebar(true);
12647 }
12648 if (panel == preview) {
12649 if (q->only_gcode_mode()) {
12650 preview->get_canvas3d()->enable_select_plate_toolbar(false);
12651 } else if (q->using_exported_file() && (q->m_valid_plates_count <= 1)) {
12652 preview->get_canvas3d()->enable_select_plate_toolbar(false);
12653 } else {
12654 preview->get_canvas3d()->enable_select_plate_toolbar(true);
12655 }
12656 }
12657
12658 if (current_panel == panel)
12659 {
12660 if (panel == view3D) {
12661 if (view3D->is_reload_delayed()) {
12662 // Delayed loading of the 3D scene when caller requests the already active tab.
12665 else
12666 view3D->reload_scene(true);
12667 }
12668
12669 view3D->set_as_dirty();
12670 view3D->get_canvas3d()->reset_old_size();
12671 if (notification_manager != nullptr)
12672 notification_manager->set_in_preview(false);
12673 }
12674 //BBS: add slice logic when switch to preview page
12675 //BBS: add only gcode mode
12676 if (!q->only_gcode_mode() && (current_panel == preview) && (wxGetApp().is_editor())) {
12677 do_reslice();
12678 }
12679 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": the same panel, exit");
12680 return;
12681 }
12682
12683 //BBS: wish to reset all plates stats item selected state when back to View3D Tab
12684 preview->get_canvas3d()->reset_select_plate_toolbar_selection();
12685
12686 wxPanel* old_panel = current_panel;
12687//#if BBL_HAS_FIRST_PAGE
12688 if (!old_panel) {
12689 // Wayland may report the first canvas as not yet shown while the frame is still mapping.
12690 // Keep the panel switch anyway so handlers are bound and the first paint can initialize GL later.
12691 panel->Show();
12692 }
12693//#endif
12694 current_panel = panel;
12695
12696 // to reduce flickering when changing view, first set as visible the new current panel
12697 for (wxPanel* p : panels) {
12698 if (p == current_panel) {
12699#ifdef __WXMAC__
12700 // On Mac we need also to force a render to avoid flickering when changing view
12701 if (force_render) {
12702 if (p == view3D)
12703 dynamic_cast<View3D*>(p)->get_canvas3d()->render();
12704 else if (p == preview)
12705 dynamic_cast<Preview*>(p)->get_canvas3d()->render();
12706 }
12707#endif // __WXMAC__
12708 p->Show();
12709 }
12710 }
12711 // then set to invisible the other
12712 for (wxPanel* p : panels) {
12713 if (p != current_panel)
12714 p->Hide();
12715 }
12716
12717 update_sidebar(true);
12718
12719 if (wxGetApp().plater()) {
12720 Camera& cam = wxGetApp().plater()->get_camera();
12721 if (old_panel == preview || old_panel == view3D) {
12722 view3D->get_canvas3d()->get_camera().load_camera_view(cam);
12723 } else if (old_panel == assemble_view) {
12724 assemble_view->get_canvas3d()->get_camera().load_camera_view(cam);
12725 }
12727 cam.load_camera_view(view3D->get_canvas3d()->get_camera());
12728 }
12729 else if (current_panel == assemble_view) {
12730 cam.load_camera_view(assemble_view->get_canvas3d()->get_camera());
12731 }
12732 }
12733
12734 if (current_panel == view3D) {
12735 if (old_panel == preview)
12736 preview->get_canvas3d()->unbind_event_handlers();
12737 else if (old_panel == assemble_view) {
12738 assemble_view->get_canvas3d()->unbind_event_handlers();
12739
12740 GLCanvas3D* assemble_canvas = assemble_view->get_canvas3d();
12741 Selection::IndicesList select_idxs = assemble_canvas->get_selection().get_volume_idxs();
12742 Selection& view3d_selection = view3D->get_canvas3d()->get_selection();
12743 view3d_selection.clear();
12744 for (unsigned int idx : select_idxs) {
12745 auto v = assemble_canvas->get_selection().get_volume(idx);
12746 auto real_idx = view3d_selection.query_real_volume_idx_from_other_view(v->object_idx(), v->instance_idx(), v->volume_idx());
12747 if (real_idx >= 0) {
12748 view3d_selection.add(real_idx, false);
12749 }
12750 }
12751 }
12752
12753 view3D->get_canvas3d()->bind_event_handlers();
12754
12755 if (view3D->is_reload_delayed()) {
12756 // Delayed loading of the 3D scene.
12757 if (printer_technology == ptSLA) {
12758 // Update the SLAPrint from the current Model, so that the reload_scene()
12759 // pulls the correct data.
12761 } else
12762 view3D->reload_scene(true);
12763 }
12764
12765 // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
12766 view3D->set_as_dirty();
12767 // reset cached size to force a resize on next call to render() to keep imgui in synch with canvas size
12768 view3D->get_canvas3d()->reset_old_size();
12769 // BBS
12770 //view_toolbar.select_item("3D");
12771 if (notification_manager != nullptr)
12772 notification_manager->set_in_preview(false);
12773 }
12774 else if (current_panel == preview) {
12775 q->invalid_all_plate_thumbnails();
12776 if (old_panel == view3D)
12777 view3D->get_canvas3d()->unbind_event_handlers();
12778 else if (old_panel == assemble_view)
12779 assemble_view->get_canvas3d()->unbind_event_handlers();
12780
12781 preview->get_canvas3d()->bind_event_handlers();
12782
12783 GLGizmosManager& gizmos = view3D->get_canvas3d()->get_gizmos_manager();
12784 if (gizmos.is_running()) {
12785 gizmos.reset_all_states();
12786 gizmos.update_data();
12787 }
12788
12789 if (wxGetApp().is_editor()) {
12790 // see: Plater::priv::object_list_changed()
12791 // FIXME: it may be better to have a single function making this check and let it be called wherever needed
12792 /*bool export_in_progress = this->background_process.is_export_scheduled();
12793 bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside;
12794 //BBS: add partplate logic
12795 PartPlate* current_plate = partplate_list.get_curr_plate();
12796 if (!no_slice && !model.objects.empty() && !export_in_progress && model_fits && current_plate->has_printable_instances()) {
12797 preview->get_canvas3d()->init_gcode_viewer();
12798 // BBS
12799 //if already running in background, not relice here
12800 if (!this->background_process.running())
12801 {
12802 m_slice_all = false;
12803 this->q->reslice();
12804 }
12805 }
12806 // keeps current gcode preview, if any
12807 preview->reload_print(true);
12808
12809 preview->set_as_dirty();*/
12810 if (wxGetApp().is_editor() && !q->only_gcode_mode())
12811 do_reslice();
12812 }
12813
12814 // reset cached size to force a resize on next call to render() to keep imgui in synch with canvas size
12815 preview->get_canvas3d()->reset_old_size();
12816 // BBS
12817 //view_toolbar.select_item("Preview");
12818 if (notification_manager != nullptr)
12819 notification_manager->set_in_preview(true);
12820 }
12821 else if (current_panel == assemble_view) {
12822 if (old_panel == view3D) {
12823 view3D->get_canvas3d()->unbind_event_handlers();
12824 }
12825 else if (old_panel == preview)
12826 preview->get_canvas3d()->unbind_event_handlers();
12827
12828 assemble_view->get_canvas3d()->bind_event_handlers();
12829 assemble_view->reload_scene(true);
12830
12831 if (old_panel == view3D) {
12832 GLCanvas3D* view3D_canvas = view3D->get_canvas3d();
12833 Selection::IndicesList select_idxs = view3D_canvas->get_selection().get_volume_idxs();
12834 Selection& assemble_selection = assemble_view->get_canvas3d()->get_selection();
12835 assemble_selection.clear();
12836 for (unsigned int idx : select_idxs) {
12837 auto v = view3D_canvas->get_selection().get_volume(idx);
12838 auto real_idx = assemble_selection.query_real_volume_idx_from_other_view(v->object_idx(), v->instance_idx(), v->volume_idx());
12839 if (real_idx >= 0) {
12840 assemble_selection.add(real_idx, false);
12841 }
12842 }
12843 }
12844
12845 // BBS set default view and zoom
12847 wxGetApp().plater()->get_camera().requires_zoom_to_volumes = true;
12848 first_enter_assemble = false;
12849 }
12850
12851 assemble_view->set_as_dirty();
12852 // BBS
12853 //view_toolbar.select_item("Assemble");
12854 }
12855
12856 current_panel->SetFocusFromKbd();
12857
12858 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": successfully, exit");
12859}
std::unique_ptr< priv > p
Definition Plater.hpp:1084
@ Camera
Definition Shortcuts.hpp:72
bool first_enter_assemble
Definition Plater.cpp:7262
void enable_sidebar(bool enabled)
Definition Plater.cpp:8611

References Slic3r::GUI::Selection::add(), assemble_view, Slic3r::GUI::GLCanvas3D::check_volumes_outside_state(), Slic3r::GUI::Selection::clear(), current_panel, Slic3r::GUI::Plater::enable_sidebar(), Slic3r::ObjectFilamentResults::filaments, first_enter_assemble, Slic3r::GUI::View3D::get_canvas3d(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::BackgroundSlicingProcess::get_current_plate(), Slic3r::GUI::PartPlate::get_index(), Slic3r::GUI::GLCanvas3D::get_selection(), Slic3r::GUI::Selection::get_volume(), Slic3r::GUI::Selection::get_volume_idxs(), Slic3r::GUI::PartPlate::has_printable_instances(), Slic3r::GLVolume::instance_idx(), Slic3r::BackgroundSlicingProcess::is_export_scheduled(), Slic3r::GUI::GLGizmosManager::is_running(), Slic3r::GUI::PartPlate::is_slice_result_valid(), Slic3r::GUI::Camera::load_camera_view(), m_is_slicing, Slic3r::ModelInstancePVS_Partly_Outside, notification_manager, Slic3r::GLVolume::object_idx(), Slic3r::Model::objects, Slic3r::GUI::Plater::p, panels, Slic3r::GUI::plater(), preview, printer_technology, Slic3r::ptSLA, q, Slic3r::GUI::Selection::query_real_volume_idx_from_other_view(), Slic3r::GUI::Preview::reload_print(), Slic3r::GUI::View3D::render(), Slic3r::GUI::GLGizmosManager::reset_all_states(), Slic3r::GUI::Plater::reset_gcode_toolpaths(), Slic3r::GUI::Plater::reslice(), Slic3r::BackgroundSlicingProcess::running(), Slic3r::GUI::PartPlateList::select_plate(), sidebar, Slic3r::GUI::GLGizmosManager::update_data(), update_fff_scene_only_shells(), update_restart_background_process(), update_sidebar(), view3D, and Slic3r::GLVolume::volume_idx().

Referenced by select_view_3D().

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

◆ set_need_update()

void Slic3r::GUI::Plater::priv::set_need_update ( bool need_update)
inline
bool need_update() const
Definition Plater.cpp:7308

References m_need_update, and need_update().

Here is the call graph for this function:

◆ set_plater_dirty()

void Slic3r::GUI::Plater::priv::set_plater_dirty ( bool is_dirty)
inline
7311{ dirty_state.set_plater_dirty(is_dirty); }

References dirty_state.

◆ set_project_filename()

void Slic3r::GUI::Plater::priv::set_project_filename ( const wxString & filename)
14472{
14473 boost::filesystem::path full_path = into_path(filename);
14474 boost::filesystem::path ext = full_path.extension();
14475 //if (boost::iequals(ext.string(), ".amf")) {
14476 // // Remove the first extension.
14477 // full_path.replace_extension("");
14478 // // It may be ".zip.amf".
14479 // if (boost::iequals(full_path.extension().string(), ".zip"))
14480 // // Remove the 2nd extension.
14481 // full_path.replace_extension("");
14482 //} else {
14483 // // Remove just one extension.
14484 // full_path.replace_extension("");
14485 //}
14486 full_path.replace_extension("");
14487
14488 m_project_folder = full_path.parent_path();
14489 BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << __LINE__ << " project folder is:" << m_project_folder.string();
14490
14491 //BBS
14492 wxString project_name = from_u8(full_path.filename().string());
14493 set_project_name(project_name);
14494 // record filename for hint when open exported file/.gcode
14495 if (q->m_only_gcode)
14496 q->m_preview_only_filename = std::string((project_name + ".gcode").mb_str());
14497 if (q->m_exported_file)
14498 q->m_preview_only_filename = std::string((project_name + ".3mf").mb_str());
14499
14500 wxGetApp().mainframe->update_title();
14501
14502 if (!m_project_folder.empty() && !q->m_only_gcode)
14503 wxGetApp().mainframe->add_to_recent_projects(filename);
14504}
void set_project_name(const wxString &project_name)
Definition Plater.cpp:14436

References Slic3r::GUI::from_u8(), Slic3r::GUI::into_path(), m_project_folder, q, set_project_name(), and Slic3r::trace().

Here is the call graph for this function:

◆ set_project_name()

void Slic3r::GUI::Plater::priv::set_project_name ( const wxString & project_name)
14437{
14438 BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << __LINE__ << " project is:" << project_name;
14439 m_project_name = project_name;
14440 //update topbar title
14441#ifdef __APPLE__
14442 wxGetApp().mainframe->SetTitle(m_project_name);
14443 if (!m_project_name.IsEmpty())
14444 wxGetApp().mainframe->update_title_colour_after_set_title();
14445#else
14446 wxGetApp().mainframe->SetTitle(m_project_name + " - OrcaSlicer");
14447 wxGetApp().mainframe->topbar()->SetTitle(m_project_name);
14448#endif
14449}

References m_project_name, and Slic3r::trace().

Referenced by set_project_filename().

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

◆ show_delayed_error_message()

void Slic3r::GUI::Plater::priv::show_delayed_error_message ( )
inline
7577 {
7578 if (!this->delayed_error_message.empty()) {
7579 std::string msg = std::move(this->delayed_error_message);
7580 this->delayed_error_message.clear();
7581 GUI::show_error(this->q, msg);
7582 }
7583 }

References Slic3r::GUI::show_error().

Referenced by update_after_undo_redo().

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

◆ show_dock_pane()

void Slic3r::GUI::Plater::priv::show_dock_pane ( wxWindow * window,
bool show )
8741{
8742 const auto it = m_dock_panes.find(window);
8743 wxAuiPaneInfo& pane = m_aui_mgr.GetPane(window);
8744 if (it == m_dock_panes.end() || !pane.IsOk())
8745 return;
8746 it->second.shown = show;
8747 if (pane.IsShown() == dock_pane_visible(it->second, pane))
8748 return;
8749 pane.Show(!pane.IsShown());
8750 m_aui_mgr.Update();
8751}

References dock_pane_visible(), m_aui_mgr, and m_dock_panes.

Here is the call graph for this function:

◆ show_install_plugin_hint()

void Slic3r::GUI::Plater::priv::show_install_plugin_hint ( wxCommandEvent & event)
14135{
14136 notification_manager->bbl_show_plugin_install_notification(into_u8(_L("The network plug-in was not detected. Network related features are unavailable.")));
14137}

References _L, Slic3r::GUI::into_u8(), and notification_manager.

Here is the call graph for this function:

◆ show_preview_only_hint()

void Slic3r::GUI::Plater::priv::show_preview_only_hint ( wxCommandEvent & event)
14140{
14141 notification_manager->bbl_show_preview_only_notification(into_u8(_L("Preview only mode:\nThe loaded file contains G-code only, cannot enter the Prepare page.")));
14142}

References _L, Slic3r::GUI::into_u8(), and notification_manager.

Here is the call graph for this function:

◆ show_right_click_menu()

void Slic3r::GUI::Plater::priv::show_right_click_menu ( Vec2d mouse_position,
wxMenu * menu )
14183{
14184 // BBS: GUI refactor: move sidebar to the left
14185 int x, y;
14186 get_position(current_panel, wxGetApp().mainframe, x, y);
14187 wxPoint position(static_cast<int>(mouse_position.x() + x), static_cast<int>(mouse_position.y() + y));
14188#ifdef __linux__
14189 // For some reason on Linux the menu isn't displayed if position is
14190 // specified (even though the position is sane).
14191 position = wxDefaultPosition;
14192#endif
14193 GLCanvas3D &canvas = *q->canvas3D();
14194 canvas.apply_retina_scale(mouse_position);
14195 canvas.set_popup_menu_position(mouse_position);
14196 q->PopupMenu(menu, position);
14197 canvas.clear_popup_menu_position();
14198}
static void get_position(wxWindowBase *child, wxWindowBase *until_parent, int &x, int &y)
Definition Plater.cpp:14166
Vec2d mouse_position(const wxMouseEvent &mouse_event)
Extract position of mouse from mouse event.
Definition SurfaceDrag.cpp:502

References Slic3r::GUI::GLCanvas3D::apply_retina_scale(), Slic3r::GUI::GLCanvas3D::clear_popup_menu_position(), current_panel, Slic3r::GUI::get_position(), q, and Slic3r::GUI::GLCanvas3D::set_popup_menu_position().

Referenced by on_plate_right_click(), and on_right_click().

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

◆ show_view3D_labels()

void Slic3r::GUI::Plater::priv::show_view3D_labels ( bool show)
inline
7365 {
7366 if (current_panel == view3D) {
7367 view3D->get_canvas3d()->show_labels(show);
7368 wxGetApp().app_config->set_bool("show_labels", show);
7369 }
7370 }

References current_panel, and view3D.

◆ show_view3D_overhang()

void Slic3r::GUI::Plater::priv::show_view3D_overhang ( bool show)
inline
7374 {
7375 if (current_panel == view3D) {
7376 view3D->get_canvas3d()->show_overhang(show);
7377 wxGetApp().app_config->set_bool("show_overhang", show);
7378 }
7379 }

References current_panel, and view3D.

◆ single_snapshots_enter()

void Slic3r::GUI::Plater::priv::single_snapshots_enter ( SingleSnapshot * single)
inline
7531 {
7532 if (m_single == nullptr) m_single = single;
7533 }
Plater::SingleSnapshot * m_single
Definition Plater.cpp:7782

References m_single.

◆ single_snapshots_leave()

void Slic3r::GUI::Plater::priv::single_snapshots_leave ( SingleSnapshot * single)
inline
7535 {
7536 if (m_single == single) m_single = nullptr;
7537 }

References m_single.

◆ split_object() [1/2]

void Slic3r::GUI::Plater::priv::split_object ( bool auto_drop = true)
10975{
10976 int obj_idx = get_selected_object_idx();
10977 priv::split_object(obj_idx, auto_drop);
10978}

References Slic3r::GUI::Plater::get_selected_object_idx(), and split_object().

Referenced by load_model_objects(), and split_object().

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

◆ split_object() [2/2]

void Slic3r::GUI::Plater::priv::split_object ( int obj_idx,
bool auto_drop = true )
10982{
10983 if (obj_idx == -1)
10984 return;
10985
10986 // we clone model object because split_object() adds the split volumes
10987 // into the same model object, thus causing duplicates when we call load_model_objects()
10988 Model new_model = model;
10989 ModelObject* current_model_object = new_model.objects[obj_idx];
10990
10991 wxBusyCursor wait;
10992 ModelObjectPtrs new_objects;
10993 current_model_object->split(&new_objects, wxGetApp().app_config->get_bool("keep_painting"));
10994 if (new_objects.size() == 1)
10995 // #ysFIXME use notification
10996 Slic3r::GUI::warning_catcher(q, _L("The selected object couldn't be split."));
10997 else
10998 {
10999 // BBS no solid parts removed
11000 // If we splited object which is contain some parts/modifiers then all non-solid parts (modifiers) were deleted
11001 //if (current_model_object->volumes.size() > 1 && current_model_object->volumes.size() != new_objects.size())
11002 // notification_manager->push_notification(NotificationType::CustomNotification,
11003 // NotificationManager::NotificationLevel::PrintInfoNotificationLevel,
11004 // _u8L("All non-solid parts (modifiers) were deleted"));
11005
11006 Plater::TakeSnapshot snapshot(q, _u8L("Split to Objects"));
11007
11008 auto is_atleast_one_floating = [new_objects]() {
11009 for (ModelObject* new_object : new_objects) {
11010 if (new_object->get_instance_min_z(0) >= SINKING_MIN_Z_THRESHOLD)
11011 return true;
11012 }
11013 return false;
11014 };
11015 bool split_auto_drop = auto_drop;
11016 if (current_model_object->auto_drop && is_atleast_one_floating()) {
11017 MessageDialog dlg(q, _L("Disable Auto-Drop to preserve Z positioning?\n"),
11018 _L("Object with floating parts was detected"), wxICON_QUESTION | wxYES_NO);
11019
11020 if (dlg.ShowModal() == wxID_YES)
11021 split_auto_drop = false;
11022 }
11023
11024 remove(obj_idx);
11025
11026 // load all model objects at once, otherwise the plate would be rearranged after each one
11027 // causing original positions not to be kept
11028 //BBS: set split_object to true to avoid re-compute assemble matrix
11029 std::vector<size_t> idxs = load_model_objects(new_objects, false, true, split_auto_drop);
11030
11031 wxGetApp().plater()->get_view3D_canvas3D()->update_instance_printable_state_for_objects(idxs);
11032
11033 // select newly added objects
11034 for (size_t idx : idxs)
11035 {
11036 get_selection().add_object((unsigned int)idx, false);
11037 }
11038 }
11039}
void add_object(unsigned int object_idx, bool as_single_selection=true)
Definition Selection.cpp:291
void warning_catcher(wxWindow *parent, const wxString &message)
Definition GUI.cpp:329
static const double SINKING_MIN_Z_THRESHOLD
Definition Model.hpp:1968
std::vector< ModelObject * > ModelObjectPtrs
Definition CutUtils.hpp:13
void remove(size_t obj_idx)
Definition Plater.cpp:10726

References _L, _u8L, Slic3r::GUI::Selection::add_object(), Slic3r::ModelObject::auto_drop, Slic3r::GUI::Plater::get_selection(), load_model_objects(), model, Slic3r::Model::objects, q, Slic3r::GUI::Plater::remove(), Slic3r::GUI::DPIAware< P >::ShowModal(), Slic3r::SINKING_MIN_Z_THRESHOLD, Slic3r::ModelObject::split(), and Slic3r::GUI::warning_catcher().

Here is the call graph for this function:

◆ split_volume()

void Slic3r::GUI::Plater::priv::split_volume ( )
11042{
11043 wxGetApp().obj_list()->split();
11044}

◆ statusbar()

std::shared_ptr< BBLStatusBar > Slic3r::GUI::Plater::priv::statusbar ( )
8785{
8786 return nullptr;
8787}

◆ suppress_snapshots()

void Slic3r::GUI::Plater::priv::suppress_snapshots ( )
inline

References m_prevent_snapshots.

◆ take_snapshot()

void Slic3r::GUI::Plater::priv::take_snapshot ( const std::string & snapshot_name,
UndoRedo::SnapshotType snapshot_type = UndoRedo::SnapshotType::Action )
15260{
15261 if (m_prevent_snapshots > 0)
15262 return;
15263 assert(m_prevent_snapshots >= 0);
15264 // BBS: single snapshot
15265 if (m_single && !m_single->check(snapshot_modifies_project(snapshot_type) && (snapshot_name.empty() || snapshot_name.back() != '!')))
15266 return;
15267 UndoRedo::SnapshotData snapshot_data;
15268 snapshot_data.snapshot_type = snapshot_type;
15269 snapshot_data.printer_technology = this->printer_technology;
15270 if (this->view3D->is_layers_editing_enabled())
15272 if (this->sidebar->obj_list()->is_selected(itSettings)) {
15274 snapshot_data.layer_range_idx = this->sidebar->obj_list()->get_selected_layers_range_idx();
15275 }
15276 else if (this->sidebar->obj_list()->is_selected(itLayer)) {
15278 snapshot_data.layer_range_idx = this->sidebar->obj_list()->get_selected_layers_range_idx();
15279 }
15280 else if (this->sidebar->obj_list()->is_selected(itLayerRoot))
15282
15283 // If SLA gizmo is active, ask it if it wants to trigger support generation
15284 // on loading this snapshot.
15285 if (view3D->get_canvas3d()->get_gizmos_manager().wants_reslice_supports_on_undo())
15287
15288 //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
15289 // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
15290 // BBS: add partplate logic
15291 if (this->printer_technology == ptFFF) {
15292 const DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
15293 const DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
15294 const ConfigOptionFloats* tower_x_opt = proj_cfg.option<ConfigOptionFloats>("wipe_tower_x");
15295 const ConfigOptionFloats* tower_y_opt = proj_cfg.option<ConfigOptionFloats>("wipe_tower_y");
15296 assert(tower_x_opt->values.size() == tower_y_opt->values.size());
15297 model.wipe_tower.positions.clear();
15298 model.wipe_tower.positions.resize(tower_x_opt->values.size());
15299 for (int plate_idx = 0; plate_idx < tower_x_opt->values.size(); plate_idx++) {
15300 ModelWipeTower& tower = model.wipe_tower;
15301
15302 tower.positions[plate_idx] = Vec2d(tower_x_opt->get_at(plate_idx), tower_y_opt->get_at(plate_idx));
15303 tower.rotation = config.opt_float("wipe_tower_rotation_angle");
15304 }
15305 }
15306 const GLGizmosManager& gizmos = get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : view3D->get_canvas3d()->get_gizmos_manager();
15307
15308 if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator)
15309 this->undo_redo_stack().clear();
15310 this->undo_redo_stack().take_snapshot(snapshot_name, model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : view3D->get_canvas3d()->get_selection(), gizmos, partplate_list, snapshot_data);
15312 // Filter all but the last UndoRedo::SnapshotType::GizmoAction in a row between the last UndoRedo::SnapshotType::EnteringGizmo and UndoRedo::SnapshotType::LeavingGizmoWithAction.
15313 // The remaining snapshot will be renamed to a more generic name,
15314 // depending on what gizmo is being left.
15315 if (gizmos.get_current() != nullptr) {
15316 std::string new_name = gizmos.get_current()->get_action_snapshot_name();
15317 this->undo_redo_stack().reduce_noisy_snapshots(new_name);
15318 }
15319 } else if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator) {
15320 // Reset the "dirty project" flag.
15321 m_undo_redo_stack_main.mark_current_as_saved();
15322 }
15323 //BBS: add PartPlateList as the paremeter for take_snapshot
15325
15326 dirty_state.update_from_undo_redo_stack(m_undo_redo_stack_main.project_modified());
15327
15328 // Save the last active preset name of a particular printer technology.
15329 ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name();
15330 BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot taken: " << snapshot_name << ", Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info();
15331}
ECanvasType get_canvas_type()
Definition GLCanvas3D.hpp:953
void take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection, const Slic3r::GUI::GLGizmosManager &gizmos, const SnapshotData &snapshot_data)
Definition UndoRedo.cpp:1376
void reduce_noisy_snapshots(const std::string &new_name)
Definition UndoRedo.cpp:1380
void clear()
Definition UndoRedo.cpp:1369
void release_least_recently_used()
Definition UndoRedo.cpp:1375
@ itSettings
Definition ObjectDataViewModel.hpp:41
@ itLayer
Definition ObjectDataViewModel.hpp:43
@ itLayerRoot
Definition ObjectDataViewModel.hpp:42
@ LeavingGizmoWithAction
Definition UndoRedo.hpp:48
std::string log_memory_info(bool ignore_loglevel)
Definition utils.cpp:1749
std::string format_memsize_MB(size_t n)
Definition utils.cpp:1677
std::string m_last_sla_printer_profile_name
Definition Plater.cpp:7787
std::string m_last_fff_printer_profile_name
Definition Plater.cpp:7786
@ SELECTED_LAYERROOT_ON_SIDEBAR
Definition UndoRedo.hpp:68
@ SELECTED_LAYER_ON_SIDEBAR
Definition UndoRedo.hpp:69
@ RECALCULATE_SLA_SUPPORTS
Definition UndoRedo.hpp:70
@ SELECTED_SETTINGS_ON_SIDEBAR
Definition UndoRedo.hpp:67
@ VARIABLE_LAYER_EDITING_ACTIVE
Definition UndoRedo.hpp:66

References assemble_view, Slic3r::GUI::GLCanvas3D::CanvasAssembleView, config, dirty_state, Slic3r::UndoRedo::SnapshotData::flags, Slic3r::format_memsize_MB(), Slic3r::GUI::GLGizmoBase::get_action_snapshot_name(), Slic3r::ConfigOptionVector< double >::get_at(), Slic3r::GUI::GLCanvas3D::get_canvas_type(), Slic3r::GUI::GLGizmosManager::get_current(), Slic3r::GUI::Plater::get_current_canvas3D(), Slic3r::GUI::ObjectList::get_selected_layers_range_idx(), Slic3r::GUI::View3D::is_layers_editing_enabled(), Slic3r::GUI::ObjectList::is_selected(), Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itSettings, Slic3r::UndoRedo::SnapshotData::layer_range_idx, Slic3r::UndoRedo::LeavingGizmoWithAction, Slic3r::log_memory_info(), m_last_fff_printer_profile_name, m_last_sla_printer_profile_name, m_prevent_snapshots, m_single, m_undo_redo_stack_main, model, Slic3r::GUI::Sidebar::obj_list(), Slic3r::ConfigBase::option(), partplate_list, Slic3r::ModelWipeTower::positions, Slic3r::UndoRedo::SnapshotData::printer_technology, Slic3r::UndoRedo::ProjectSeparator, Slic3r::ptFFF, Slic3r::UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS, Slic3r::ModelWipeTower::rotation, Slic3r::UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR, Slic3r::UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR, Slic3r::UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR, Slic3r::UndoRedo::SnapshotData::snapshot_type, undo_redo_stack(), Slic3r::ConfigOptionVector< double >::values, Slic3r::UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE, and view3D.

Here is the call graph for this function:

◆ trigger_auto_reslice_now()

void Slic3r::GUI::Plater::priv::trigger_auto_reslice_now ( )
11162{
11163 this->auto_reslice_pending = false;
11164
11165 AppConfig* cfg = wxGetApp().app_config;
11166 if (cfg == nullptr || !cfg->get_bool("auto_slice_after_change"))
11167 return;
11168
11169 if (!is_preview_shown())
11170 return;
11171
11172 if (this->model.objects.empty())
11173 return;
11174
11175 if (this->background_process.running() || this->m_is_slicing)
11176 return;
11177
11178 PartPlate* plate = this->partplate_list.get_curr_plate();
11179 if (plate == nullptr || !plate->has_printable_instances())
11180 return;
11181
11182 this->q->reslice();
11183}

References Slic3r::AppConfig::get_bool(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::GUI::PartPlate::has_printable_instances(), Slic3r::GUI::Plater::is_preview_shown(), Slic3r::GUI::Plater::reslice(), and Slic3r::BackgroundSlicingProcess::running().

Referenced by schedule_auto_reslice_if_needed().

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

◆ unbind_canvas_event_handlers()

void Slic3r::GUI::Plater::priv::unbind_canvas_event_handlers ( )
14618{
14619 if (view3D != nullptr)
14620 view3D->get_canvas3d()->unbind_event_handlers();
14621
14622 if (preview != nullptr)
14623 preview->get_canvas3d()->unbind_event_handlers();
14624
14625 if (assemble_view != nullptr)
14626 assemble_view->get_canvas3d()->unbind_event_handlers();
14627
14628#ifdef SLIC3R_CAD
14629 // The Design tab's viewport is a fourth GLCanvas3D on the same shared GL context, owned by
14630 // MainFrame rather than by us — same reach as reset() uses for clear_document(). Null until
14631 // the tab has been opened once, so most sessions skip it.
14632 if (DesignPanel* design = DesignPanel::if_built())
14633 design->unbind_canvas_event_handlers();
14634#endif
14635}

References assemble_view, Slic3r::GUI::LazyInstance< DesignPanel >::if_built(), preview, and view3D.

Here is the call graph for this function:

◆ undo()

void Slic3r::GUI::Plater::priv::undo ( )
15350{
15351 if (this->undo_redo_blocked_by_job())
15352 return;
15353 const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack().snapshots();
15354 auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(this->undo_redo_stack().active_snapshot_time()));
15355 // BBS: undo-redo until modify record
15356 while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current));
15357 if (it_current == snapshots.begin()) return;
15358 if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
15359 if (it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::GizmoAction &&
15360 it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::EnteringGizmo &&
15361 it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoNoAction &&
15362 it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoWithAction)
15363 return;
15364 }
15365 this->undo_redo_to(it_current);
15366}
@ EnteringGizmo
Definition UndoRedo.hpp:42
@ LeavingGizmoNoAction
Definition UndoRedo.hpp:45
@ GizmoAction
Definition UndoRedo.hpp:36

References Slic3r::GUI::GLCanvas3D::CanvasAssembleView, Slic3r::UndoRedo::EnteringGizmo, Slic3r::GUI::Plater::get_current_canvas3D(), Slic3r::UndoRedo::GizmoAction, Slic3r::UndoRedo::LeavingGizmoNoAction, Slic3r::UndoRedo::LeavingGizmoWithAction, undo_redo_blocked_by_job(), undo_redo_stack(), and undo_redo_to().

Here is the call graph for this function:

◆ undo_redo_blocked_by_job()

bool Slic3r::GUI::Plater::priv::undo_redo_blocked_by_job ( )
15339{
15340 if (m_worker.is_idle())
15341 return false;
15344 _u8L("Cannot undo or redo while an operation is running. Stop the operation, or wait "
15345 "for it to finish and then retry."));
15346 return true;
15347}

References _u8L, Slic3r::GUI::CustomNotification, m_worker, notification_manager, and Slic3r::GUI::NotificationManager::RegularNotificationLevel.

Referenced by redo(), and undo().

Here is the caller graph for this function:

◆ undo_redo_stack()

Slic3r::UndoRedo::Stack & Slic3r::GUI::Plater::priv::undo_redo_stack ( )
inline
7508{ assert(m_undo_redo_stack_active != nullptr); return *m_undo_redo_stack_active; }

References m_undo_redo_stack_active.

Referenced by get_active_snapshot_index(), redo(), take_snapshot(), undo(), undo_redo_to(), undo_redo_to(), and update_after_undo_redo().

Here is the caller graph for this function:

◆ undo_redo_stack_main()

Slic3r::UndoRedo::Stack & Slic3r::GUI::Plater::priv::undo_redo_stack_main ( )
inline
7509{ return m_undo_redo_stack_main; }

References m_undo_redo_stack_main.

◆ undo_redo_to() [1/2]

void Slic3r::GUI::Plater::priv::undo_redo_to ( size_t time_to_load)
15383{
15384 const std::vector<UndoRedo::Snapshot> &snapshots = this->undo_redo_stack().snapshots();
15385 auto it_current = std::lower_bound(snapshots.begin(), snapshots.end(), UndoRedo::Snapshot(time_to_load));
15386 assert(it_current != snapshots.end());
15387 this->undo_redo_to(it_current);
15388}

References undo_redo_stack(), and undo_redo_to().

Referenced by redo(), undo(), and undo_redo_to().

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

◆ undo_redo_to() [2/2]

void Slic3r::GUI::Plater::priv::undo_redo_to ( std::vector< UndoRedo::Snapshot >::const_iterator it_snapshot)
private
15406{
15407 // Make sure that no updating function calls take_snapshot until we are done.
15408 SuppressSnapshots snapshot_supressor(q);
15409
15410 bool temp_snapshot_was_taken = this->undo_redo_stack().temp_snapshot_active();
15411 PrinterTechnology new_printer_technology = it_snapshot->snapshot_data.printer_technology;
15412 bool printer_technology_changed = this->printer_technology != new_printer_technology;
15413 if (printer_technology_changed) {
15414 //BBS do not support SLA
15415 }
15416 // Save the last active preset name of a particular printer technology.
15417 ((this->printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name) = wxGetApp().preset_bundle->printers.get_selected_preset_name();
15418 //FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
15419 // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
15420 // BBS: add partplate logic
15421 if (this->printer_technology == ptFFF) {
15422 const DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
15423 const DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
15424 const ConfigOptionFloats* tower_x_opt = proj_cfg.option<ConfigOptionFloats>("wipe_tower_x");
15425 const ConfigOptionFloats* tower_y_opt = proj_cfg.option<ConfigOptionFloats>("wipe_tower_y");
15426 assert(tower_x_opt->values.size() == tower_y_opt->values.size());
15427 model.wipe_tower.positions.clear();
15428 model.wipe_tower.positions.resize(tower_x_opt->values.size());
15429 for (int plate_idx = 0; plate_idx < tower_x_opt->values.size(); plate_idx++) {
15430 ModelWipeTower& tower = model.wipe_tower;
15431
15432 tower.positions[plate_idx] = Vec2d(tower_x_opt->get_at(plate_idx), tower_y_opt->get_at(plate_idx));
15433 tower.rotation = config.opt_float("wipe_tower_rotation_angle");
15434 }
15435 }
15436 const int layer_range_idx = it_snapshot->snapshot_data.layer_range_idx;
15437 // Flags made of Snapshot::Flags enum values.
15438 unsigned int new_flags = it_snapshot->snapshot_data.flags;
15439 UndoRedo::SnapshotData top_snapshot_data;
15440 top_snapshot_data.printer_technology = this->printer_technology;
15441 if (this->view3D->is_layers_editing_enabled())
15443 if (this->sidebar->obj_list()->is_selected(itSettings)) {
15445 top_snapshot_data.layer_range_idx = this->sidebar->obj_list()->get_selected_layers_range_idx();
15446 }
15447 else if (this->sidebar->obj_list()->is_selected(itLayer)) {
15448 top_snapshot_data.flags |= UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR;
15449 top_snapshot_data.layer_range_idx = this->sidebar->obj_list()->get_selected_layers_range_idx();
15450 }
15451 else if (this->sidebar->obj_list()->is_selected(itLayerRoot))
15453 bool new_variable_layer_editing_active = (new_flags & UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE) != 0;
15454 bool new_selected_settings_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR) != 0;
15455 bool new_selected_layer_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR) != 0;
15456 bool new_selected_layerroot_on_sidebar = (new_flags & UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR) != 0;
15457
15458 if (this->view3D->get_canvas3d()->get_gizmos_manager().wants_reslice_supports_on_undo())
15459 top_snapshot_data.flags |= UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS;
15460
15461 // Disable layer editing before the Undo / Redo jump.
15462 if (!new_variable_layer_editing_active && view3D->is_layers_editing_enabled())
15463 view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
15464
15465 // Make a copy of the snapshot, undo/redo could invalidate the iterator
15466 const UndoRedo::Snapshot snapshot_copy = *it_snapshot;
15467 // Do the jump in time.
15468 if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_time() ?
15469 this->undo_redo_stack().undo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : this->view3D->get_canvas3d()->get_selection(), get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) :
15470 this->undo_redo_stack().redo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) {
15471 if (printer_technology_changed) {
15472 // Switch to the other printer technology. Switch to the last printer active for that particular technology.
15473 AppConfig *app_config = wxGetApp().app_config;
15474 app_config->set("presets", PRESET_PRINTER_NAME, (new_printer_technology == ptFFF) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name);
15475 //FIXME Why are we reloading the whole preset bundle here? Please document. This is fishy and it is unnecessarily expensive.
15476 // Anyways, don't report any config value substitutions, they have been already reported to the user at application start up.
15477 wxGetApp().preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilent);
15478 // load_current_presets() calls Tab::load_current_preset() -> TabPrint::update() -> Object_list::update_and_show_object_settings_item(),
15479 // but the Object list still keeps pointer to the old Model. Avoid a crash by removing selection first.
15480 this->sidebar->obj_list()->unselect_objects();
15481 // Load the currently selected preset into the GUI, update the preset selection box.
15482 // This also switches the printer technology based on the printer technology of the active printer profile.
15483 wxGetApp().load_current_presets();
15484 }
15485 //FIXME updating the Print config from the Wipe tower config values at the ModelWipeTower.
15486 // This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
15487 // BBS: add partplate logic
15488 if (this->printer_technology == ptFFF) {
15489 const DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
15490 const DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
15491 ConfigOptionFloats* tower_x_opt = const_cast<ConfigOptionFloats*>(proj_cfg.option<ConfigOptionFloats>("wipe_tower_x"));
15492 ConfigOptionFloats* tower_y_opt = const_cast<ConfigOptionFloats*>(proj_cfg.option<ConfigOptionFloats>("wipe_tower_y"));
15493 // BBS: don't support wipe tower rotation
15494 //double current_rotation = proj_cfg.opt_float("wipe_tower_rotation_angle");
15495 bool need_update = false;
15496 if (tower_x_opt->values.size() != model.wipe_tower.positions.size()) {
15497 tower_x_opt->clear();
15498 ConfigOptionFloat default_tower_x(40.f);
15499 tower_x_opt->resize(model.wipe_tower.positions.size(), &default_tower_x);
15500 need_update = true;
15501 }
15502
15503 if (tower_y_opt->values.size() != model.wipe_tower.positions.size()) {
15504 tower_y_opt->clear();
15505 ConfigOptionFloat default_tower_y(200.f);
15506 tower_y_opt->resize(model.wipe_tower.positions.size(), &default_tower_y);
15507 need_update = true;
15508 }
15509
15510 for (int plate_idx = 0; plate_idx < model.wipe_tower.positions.size(); plate_idx++) {
15511 if (Vec2d(tower_x_opt->get_at(plate_idx), tower_y_opt->get_at(plate_idx)) != model.wipe_tower.positions[plate_idx]) {
15512 ConfigOptionFloat tower_x_new(model.wipe_tower.positions[plate_idx].x());
15513 ConfigOptionFloat tower_y_new(model.wipe_tower.positions[plate_idx].y());
15514 tower_x_opt->set_at(&tower_x_new, plate_idx, 0);
15515 tower_y_opt->set_at(&tower_y_new, plate_idx, 0);
15516 need_update = true;
15517 break;
15518 }
15519 }
15520
15521 if (need_update) {
15522 // update print to current plate (preview->m_process)
15523 this->partplate_list.update_slice_context_to_current_plate(this->background_process);
15524 this->preview->update_gcode_result(this->partplate_list.get_current_slice_result());
15525 this->update();
15526 }
15527 }
15528 // set selection mode for ObjectList on sidebar
15529 this->sidebar->obj_list()->set_selection_mode(new_selected_settings_on_sidebar ? ObjectList::SELECTION_MODE::smSettings :
15530 new_selected_layer_on_sidebar ? ObjectList::SELECTION_MODE::smLayer :
15531 new_selected_layerroot_on_sidebar ? ObjectList::SELECTION_MODE::smLayerRoot :
15533 if (new_selected_settings_on_sidebar || new_selected_layer_on_sidebar)
15534 this->sidebar->obj_list()->set_selected_layers_range_idx(layer_range_idx);
15535
15536 this->update_after_undo_redo(snapshot_copy, temp_snapshot_was_taken);
15537 // Enable layer editing after the Undo / Redo jump.
15538 if (!view3D->is_layers_editing_enabled() && this->layers_height_allowed() && new_variable_layer_editing_active)
15539 view3D->get_canvas3d()->force_main_toolbar_left_action(view3D->get_canvas3d()->get_main_toolbar_item_id("layersediting"));
15540 }
15541
15542 dirty_state.update_from_undo_redo_stack(m_undo_redo_stack_main.project_modified());
15544}
#define PRESET_PRINTER_NAME
Definition Preset.hpp:35
@ smLayerRoot
Definition GUI_ObjectList.hpp:106
@ smLayer
Definition GUI_ObjectList.hpp:104
@ smUndef
Definition GUI_ObjectList.hpp:101
@ smSettings
Definition GUI_ObjectList.hpp:105
bool temp_snapshot_active() const
Definition UndoRedo.cpp:1392
zaa_minimize_perimeter_height ConfigOptionFloat
Definition PrintConfig.hpp:1954
@ EnableSilent
Definition Config.hpp:247
void update_title_dirty_status()
Definition Plater.cpp:14451
void update_after_undo_redo(const UndoRedo::Snapshot &snapshot, bool temp_snapshot_was_taken=false)
Definition Plater.cpp:15546

References assemble_view, Slic3r::GUI::GLCanvas3D::CanvasAssembleView, Slic3r::ConfigOptionVector< double >::clear(), config, dirty_state, Slic3r::EnableSilent, Slic3r::UndoRedo::SnapshotData::flags, Slic3r::ConfigOptionVector< double >::get_at(), Slic3r::GUI::View3D::get_canvas3d(), get_current_canvas3D(), Slic3r::GUI::PartPlateList::get_current_slice_result(), Slic3r::GUI::GLCanvas3D::get_gizmos_manager(), Slic3r::GUI::ObjectList::get_selected_layers_range_idx(), Slic3r::GUI::View3D::is_layers_editing_enabled(), Slic3r::GUI::ObjectList::is_selected(), Slic3r::GUI::itLayer, Slic3r::GUI::itLayerRoot, Slic3r::GUI::itSettings, Slic3r::UndoRedo::SnapshotData::layer_range_idx, m_last_fff_printer_profile_name, m_last_sla_printer_profile_name, m_undo_redo_stack_main, model, need_update(), Slic3r::GUI::Sidebar::obj_list(), Slic3r::ConfigBase::option(), Slic3r::ModelWipeTower::positions, PRESET_PRINTER_NAME, Slic3r::UndoRedo::SnapshotData::printer_technology, Slic3r::ptFFF, q, Slic3r::UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS, Slic3r::ConfigOptionVector< double >::resize(), Slic3r::ModelWipeTower::rotation, Slic3r::UndoRedo::SnapshotData::SELECTED_LAYER_ON_SIDEBAR, Slic3r::UndoRedo::SnapshotData::SELECTED_LAYERROOT_ON_SIDEBAR, Slic3r::UndoRedo::SnapshotData::SELECTED_SETTINGS_ON_SIDEBAR, Slic3r::AppConfig::set(), Slic3r::ConfigOptionVector< double >::set_at(), Slic3r::GUI::ObjectList::set_selected_layers_range_idx(), Slic3r::GUI::ObjectList::set_selection_mode(), Slic3r::GUI::ObjectList::smLayer, Slic3r::GUI::ObjectList::smLayerRoot, Slic3r::GUI::ObjectList::smSettings, Slic3r::GUI::ObjectList::smUndef, undo_redo_stack(), Slic3r::GUI::ObjectList::unselect_objects(), Slic3r::GUI::Plater::update(), update_after_undo_redo(), Slic3r::GUI::Preview::update_gcode_result(), Slic3r::GUI::PartPlateList::update_slice_context_to_current_plate(), Slic3r::GUI::Plater::update_title_dirty_status(), Slic3r::ConfigOptionVector< double >::values, Slic3r::UndoRedo::SnapshotData::VARIABLE_LAYER_EDITING_ACTIVE, view3D, and Slic3r::GUI::GLGizmosManager::wants_reslice_supports_on_undo().

Here is the call graph for this function:

◆ up_to_date()

bool Slic3r::GUI::Plater::priv::up_to_date ( bool saved,
bool backup )
15392{
15393 size_t& last_time = backup ? m_backup_timestamp : m_saved_timestamp;
15394 if (saved) {
15396 if (!backup)
15398 return true;
15399 }
15400 else {
15401 return !undo_redo_stack_main().has_real_change_from(last_time);
15402 }
15403}
bool has_real_change_from(size_t time) const
Definition UndoRedo.cpp:1396
void mark_current_as_saved()
Definition UndoRedo.cpp:1393
Slic3r::UndoRedo::Stack & undo_redo_stack_main()
Definition Plater.cpp:7509

References Slic3r::UndoRedo::Stack::active_snapshot_time(), Slic3r::UndoRedo::Stack::has_real_change_from(), m_backup_timestamp, m_saved_timestamp, Slic3r::UndoRedo::Stack::mark_current_as_saved(), and Slic3r::GUI::Plater::undo_redo_stack_main().

Here is the call graph for this function:

◆ update()

void Slic3r::GUI::Plater::priv::update ( unsigned int flags = 0)
8405{
8406 // the following line, when enabled, causes flickering on NVIDIA graphics cards
8407// wxWindowUpdateLocker freeze_guard(q);
8408#ifdef SUPPORT_AUTOCENTER
8409 if (get_config("autocenter") == "true")
8410 model.center_instances_around_point(this->bed.build_volume().bed_center());
8411#endif
8412
8413 unsigned int update_status = 0;
8414 const bool force_background_processing_restart = this->printer_technology == ptSLA || (flags & (unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE);
8415 if (force_background_processing_restart)
8416 // Update the SLAPrint from the current Model, so that the reload_scene()
8417 // pulls the correct data.
8418 update_status = this->update_background_process(false, flags & (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE);
8419 //BBS TODO reload_scene
8420 this->view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH);
8421 if (is_preview_shown()) this->preview->reload_print();
8422 //BBS assemble view
8423 this->assemble_view->reload_scene(false, flags);
8424
8425 // todo: better to mark thumbnail dirty here
8426 q->mark_plate_toolbar_image_dirty();
8427
8428 if (force_background_processing_restart)
8429 this->restart_background_process(update_status);
8430 else
8432
8433 // BBS
8434#if 0
8435 if (get_config("autocenter") == "true" && this->sidebar->obj_manipul()->IsShown())
8436 this->sidebar->obj_manipul()->UpdateAndShow(true);
8437#endif
8438
8440}
@ FORCE_FULL_SCREEN_REFRESH
Definition Plater.cpp:7348
@ POSTPONE_VALIDATION_ERROR_MESSAGE
Definition Plater.cpp:7350
@ FORCE_BACKGROUND_PROCESSING_UPDATE
Definition Plater.cpp:7349

References Slic3r::BuildVolume::bed_center(), Slic3r::GUI::Bed3D::build_volume(), FORCE_BACKGROUND_PROCESSING_UPDATE, FORCE_FULL_SCREEN_REFRESH, get_config(), Slic3r::GUI::Plater::is_preview_shown(), model, POSTPONE_VALIDATION_ERROR_MESSAGE, Slic3r::ptSLA, q, Slic3r::GUI::Preview::reload_print(), Slic3r::GUI::AssembleView::reload_scene(), Slic3r::GUI::View3D::reload_scene(), restart_background_process(), Slic3r::GUI::Plater::schedule_background_process(), update_background_process(), and update_sidebar().

Referenced by load_model_objects().

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

◆ update_after_undo_redo()

void Slic3r::GUI::Plater::priv::update_after_undo_redo ( const UndoRedo::Snapshot & snapshot,
bool temp_snapshot_was_taken = false )
private
15547{
15548 get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection().clear() : this->view3D->get_canvas3d()->get_selection().clear();
15549 // Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies).
15551 // Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot.
15552 //if (temp_snapshot_was_taken)
15553 // Release the old snapshots always, as it may have happened, that some of the triangle meshes got deserialized from the snapshot, while some
15554 // triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size.
15556 //YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
15558 assemble_view->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances) :
15559 this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances);
15561 assemble_view->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot) :
15562 this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot);
15563
15564 wxGetApp().obj_list()->update_after_undo_redo();
15565
15566 if (wxGetApp().get_mode() == comSimple && model_has_advanced_features(this->model)) {
15567 // If the user jumped to a snapshot that require user interface with advanced features, switch to the advanced mode without asking.
15568 // There is a little risk of surprising the user, as he already must have had the advanced or advanced mode active for such a snapshot to be taken.
15569 Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
15570 view3D->set_as_dirty();
15571 }
15572
15573 // this->update() above was called with POSTPONE_VALIDATION_ERROR_MESSAGE, so that if an error message was generated when updating the back end, it would not open immediately,
15574 // but it would be saved to be show later. Let's do it now. We do not want to display the message box earlier, because on Windows & OSX the message box takes over the message
15575 // queue pump, which in turn executes the rendering function before a full update after the Undo / Redo jump.
15577
15578 //FIXME what about the state of the manipulators?
15579 //FIXME what about the focus? Cursor in the side panel?
15580
15581 BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot reloaded. Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info();
15582}
EMode
Definition Selection.hpp:52
@ comAdvanced
Definition Config.hpp:223
bool model_has_advanced_features(const Model &model)
Definition Model.cpp:4319
void show_delayed_error_message()
Definition Plater.cpp:7577

References assemble_view, Slic3r::GUI::GLCanvas3D::CanvasAssembleView, Slic3r::GUI::Selection::clear(), Slic3r::comAdvanced, Slic3r::comSimple, FORCE_BACKGROUND_PROCESSING_UPDATE, Slic3r::format_memsize_MB(), Slic3r::GUI::View3D::get_canvas3d(), Slic3r::GUI::GLCanvas3D::get_canvas_type(), Slic3r::GUI::Plater::get_current_canvas3D(), Slic3r::GUI::GLCanvas3D::get_gizmos_manager(), Slic3r::GUI::GLCanvas3D::get_selection(), Slic3r::log_memory_info(), Slic3r::model_has_advanced_features(), POSTPONE_VALIDATION_ERROR_MESSAGE, Slic3r::GUI::Selection::set_deserialized(), show_delayed_error_message(), undo_redo_stack(), Slic3r::GUI::Plater::update(), Slic3r::GUI::GLGizmosManager::update_after_undo_redo(), and view3D.

Referenced by undo_redo_to().

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

◆ update_background_process()

unsigned int Slic3r::GUI::Plater::priv::update_background_process ( bool force_validation = false,
bool postpone_error_messages = false,
bool switch_print = true )
11397{
11398 // bitmap of enum UpdateBackgroundProcessReturnState
11399 unsigned int return_state = 0;
11400
11401 // If the update_background_process() was not called by the timer, kill the timer,
11402 // so the update_restart_background_process() will not be called again in vain.
11404 // ORCA-Belt: sync the auto-managed belt purge prism before the model is
11405 // applied to the Print below, so the prism change rides this same apply.
11408 // Update the "out of print bed" state of ModelInstances.
11410 // Apply new config to the possibly running background task.
11411 bool was_running = background_process.running();
11412 //BBS: add the switch print logic before Print::Apply
11413 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": enter, force_validation=%1% postpone_error_messages=%2%, switch_print=%3%, was_running=%4%")%force_validation %postpone_error_messages %switch_print %was_running;
11414 if (switch_print)
11415 {
11416 //BBS: update the current print to the current plate
11417 this->partplate_list.update_slice_context_to_current_plate(background_process);
11418 this->preview->update_gcode_result(partplate_list.get_current_slice_result());
11419 }
11420
11421 background_process.fff_print()->set_check_multi_filaments_compatibility(wxGetApp().app_config->get("enable_high_low_temp_mixed_printing") == "false");
11422
11423 Print::ApplyStatus invalidated;
11424 const auto& preset_bundle = wxGetApp().preset_bundle;
11425 if (preset_bundle->get_printer_extruder_count() > 1) {
11426 PartPlate* cur_plate = background_process.get_current_plate();
11427 std::vector<int> f_maps = cur_plate->get_real_filament_maps(preset_bundle->project_config);
11428 std::vector<int> f_volume_maps = cur_plate->get_filament_volume_maps();
11429 if (f_volume_maps.empty()) {
11430 f_volume_maps = preset_bundle->get_default_nozzle_volume_types_for_filaments(f_maps);
11431 }
11432 invalidated = background_process.apply(this->model, preset_bundle->full_config(false, f_maps, f_volume_maps));
11433 background_process.fff_print()->set_extruder_filament_info(get_extruder_filament_info());
11434 }
11435 else
11436 invalidated = background_process.apply(this->model, preset_bundle->full_config(false));
11437
11438 if ((invalidated == Print::APPLY_STATUS_CHANGED) || (invalidated == Print::APPLY_STATUS_INVALIDATED))
11439 // BBS: add only gcode mode
11440 q->set_only_gcode(false);
11441
11442 //BBS: add slicing related logs
11443 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": background process apply result=%1%")%invalidated;
11444 if (background_process.empty())
11445 view3D->get_canvas3d()->reset_sequential_print_clearance();
11446
11447 if (invalidated == Print::APPLY_STATUS_INVALIDATED) {
11448 //BBS: update current plater's slicer result to invalid
11449 this->background_process.get_current_plate()->update_slice_result_valid_state(false);
11450
11451 //no need, should be done in background_process.apply
11452 //this->background_process.get_current_gcode_result()->reset();
11453 // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
11454 // Otherwise they will be just refreshed.
11455 if (preview != nullptr) {
11456 // If the preview is not visible, the following line just invalidates the preview,
11457 // but the G-code paths or SLA preview are calculated first once the preview is made visible.
11459 preview->reload_print();
11460 }
11461 // In FDM mode, we need to reload the 3D scene because of the wipe tower preview box.
11462 // In SLA mode, we need to reload the 3D scene every time to show the support structures.
11463 if (printer_technology == ptSLA || (printer_technology == ptFFF && config->opt_bool("enable_prime_tower")))
11465
11466 notification_manager->set_slicing_progress_hidden();
11467 }
11468 else {
11469 if (preview && preview->get_reload_paint_after_background_process_apply()) {
11470 preview->set_reload_paint_after_background_process_apply(false);
11471 preview->reload_print();
11472 }
11473 }
11474
11475 if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! background_process.empty()) {
11476 // The delayed error message is no more valid.
11477 delayed_error_message.clear();
11478 // The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
11479
11480 //BBS: add is_warning logic
11481 std::vector<StringObjectException> warnings;
11482 //BBS: refine seq-print logic
11483 Polygons polygons;
11484 std::vector<std::pair<Polygon, float>> height_polygons;
11485 StringObjectException err = background_process.validate(&warnings, &polygons, &height_polygons);
11486 // update string by type
11487 q->post_process_string_object_exception(err);
11488 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warnings=%2%")%err.string%warnings.size();
11489
11490 if (err.string.empty())
11491 err.string = imex_placement_error(partplate_list.get_curr_plate());
11492
11493 if (err.string.empty()) {
11494 this->partplate_list.get_curr_plate()->update_apply_result_invalid(false);
11495 notification_manager->set_all_slicing_errors_gray(true);
11496 notification_manager->close_notification_of_type(NotificationType::ValidateError);
11497 notification_manager->bbl_close_3mf_warn_notification();
11498
11500 return_state |= UPDATE_BACKGROUND_PROCESS_RESTART;
11501
11503 if (printer_technology == ptFFF) {
11504 view3D->get_canvas3d()->reset_sequential_print_clearance();
11505 view3D->get_canvas3d()->set_as_dirty();
11506 view3D->get_canvas3d()->request_extra_frame();
11507 }
11508 }
11509 else {
11510 this->partplate_list.get_curr_plate()->update_apply_result_invalid(true);
11511 // The print is not valid.
11512 // Show error as notification.
11513 notification_manager->push_validate_error_notification(err);
11514 //also update the warnings
11516 return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
11517 if (printer_technology == ptFFF) {
11518 const Print* print = background_process.fff_print();
11519 //Polygons polygons;
11520 //if (print->config().print_sequence == PrintSequence::ByObject)
11521 // Print::sequential_print_clearance_valid(*print, &polygons);
11522 view3D->get_canvas3d()->set_sequential_print_clearance_visible(true);
11523 view3D->get_canvas3d()->set_sequential_print_clearance_render_fill(true);
11524 view3D->get_canvas3d()->set_sequential_print_clearance_polygons(polygons, height_polygons);
11525 }
11526 }
11527 }
11528 else if (! this->delayed_error_message.empty()) {
11529 // Reusing the old state.
11530 return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
11531 }
11532
11533 //actualizate warnings
11534 if (invalidated != Print::APPLY_STATUS_UNCHANGED || background_process.empty()) {
11535 if (background_process.empty())
11537 actualize_slicing_warnings(*this->background_process.current_print());
11538 actualize_object_warnings(*this->background_process.current_print());
11539 show_warning_dialog = false;
11541 }
11542
11543 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: was_running = %2%, running %3%, invalidated=%4%, return_state=%5%, internal_cancel=%6%")
11544 % __LINE__ % was_running % this->background_process.running() % invalidated % return_state % this->background_process.is_internal_cancelled();
11545 if (was_running && ! this->background_process.running() && (return_state & UPDATE_BACKGROUND_PROCESS_RESTART) == 0) {
11546 if (invalidated != Print::APPLY_STATUS_UNCHANGED || this->background_process.is_internal_cancelled())
11547 {
11548 // The background processing was killed and it will not be restarted.
11549 // Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages.
11550 SlicingProcessCompletedEvent evt(EVT_PROCESS_COMPLETED, 0,
11552 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%, post an EVT_PROCESS_COMPLETED to main, status %2%")%__LINE__ %evt.status();
11553 wxQueueEvent(q, evt.Clone());
11554 }
11555 }
11556
11557 if ((return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
11558 {
11559 // Validation of the background data failed.
11560 //BBS: add slice&&print status update logic
11561 this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, false);
11562
11563 process_completed_with_error = partplate_list.get_curr_plate_index();
11564 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: set to process_completed_with_error, return_state=%2%")%__LINE__%return_state;
11565 }
11566 else
11567 {
11568 // Background data is valid.
11569 if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
11570 (return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
11571 notification_manager->set_slicing_progress_hidden();
11572
11573 //BBS: add slice&&print status update logic
11574 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: background data valid, return_state=%2%")%__LINE__%return_state;
11575 PartPlate* cur_plate = background_process.get_current_plate();
11576 if (background_process.finished() && cur_plate && cur_plate->is_slice_result_valid())
11577 {
11578 //ready_to_slice = false;
11579 this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, false);
11580 }
11581 else if (!background_process.empty() &&
11582 !background_process.running()) /* Do not update buttons if background process is running
11583 * This condition is important for SLA mode especially,
11584 * when this function is called several times during calculations
11585 * */
11586 {
11587 if (cur_plate->can_slice()) {
11588 //ready_to_slice = true;
11589 this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, true);
11591 }
11592 else {
11593 //ready_to_slice = false;
11594 this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, false);
11595 process_completed_with_error = partplate_list.get_curr_plate_index();
11596 }
11597 }
11598#if 0
11599 //sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export));
11600 //sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send));
11601
11602 //const wxString slice_string = background_process.running() && wxGetApp().get_mode() == comSimple ?
11603 // _L("Slicing") + dots : _L("Slice now");
11604 //sidebar->set_btn_label(ActionButtonType::abReslice, slice_string);
11605
11606 //if (background_process.finished())
11607 // show_action_buttons(false);
11608 //else if (!background_process.empty() &&
11609 // !background_process.running()) /* Do not update buttons if background process is running
11610 // * This condition is important for SLA mode especially,
11611 // * when this function is called several times during calculations
11612 // * */
11613 // show_action_buttons(true);
11614#endif
11615 }
11616
11617 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: exit, return_state=%2%")%__LINE__%return_state;
11618 return return_state;
11619}
ApplyStatus
Definition PrintBase.hpp:410
@ APPLY_STATUS_UNCHANGED
Definition PrintBase.hpp:412
@ APPLY_STATUS_CHANGED
Definition PrintBase.hpp:415
@ APPLY_STATUS_INVALIDATED
Definition PrintBase.hpp:417
@ Cancelled
Definition BackgroundSlicingProcess.hpp:55
std::string imex_placement_error(PartPlate *plate)
Definition Plater.cpp:11377
@ ValidateError
Definition NotificationManager.hpp:92
std::vector< Polygon, PointsAllocator< Polygon > > Polygons
Definition Polygon.hpp:22
std::vector< std::vector< DynamicPrintConfig > > get_extruder_filament_info()
Definition Plater.cpp:11212
bool background_processing_enabled() const
Definition Plater.cpp:7542
void actualize_object_warnings(const PrintBase &print)
Definition Plater.cpp:13304
void actualize_slicing_warnings(const PrintBase &print)
Definition Plater.cpp:13292
bool ensure_belt_purge_tower()
Definition Plater.cpp:11354
void process_validation_warnings(const std::vector< StringObjectException > &warnings) const
Definition Plater.cpp:11340

References actualize_object_warnings(), actualize_slicing_warnings(), Slic3r::PrintBase::APPLY_STATUS_CHANGED, Slic3r::PrintBase::APPLY_STATUS_INVALIDATED, Slic3r::PrintBase::APPLY_STATUS_UNCHANGED, background_process, background_process_timer, background_processing_enabled(), Slic3r::GUI::PartPlate::can_slice(), Slic3r::SlicingProcessCompletedEvent::Cancelled, Slic3r::SlicingProcessCompletedEvent::Clone(), config, Slic3r::BackgroundSlicingProcess::current_print(), delayed_error_message, Slic3r::GUI::MainFrame::eEventSliceUpdate, Slic3r::GUI::ensure_belt_purge_tower(), Slic3r::GUI::PartPlateList::get_curr_plate(), Slic3r::BackgroundSlicingProcess::get_current_plate(), get_extruder_filament_info(), Slic3r::GUI::PartPlate::get_filament_volume_maps(), Slic3r::GUI::PartPlate::get_real_filament_maps(), Slic3r::BackgroundSlicingProcess::is_internal_cancelled(), Slic3r::GUI::PartPlate::is_slice_result_valid(), notification_manager, partplate_list, preview, printer_technology, process_completed_with_error, process_validation_warning(), process_validation_warnings(), Slic3r::ptFFF, Slic3r::ptSLA, q, Slic3r::GUI::Plater::reset_gcode_toolpaths(), Slic3r::BackgroundSlicingProcess::running(), show_warning_dialog, Slic3r::SlicingProcessCompletedEvent::status(), Slic3r::StringObjectException::string, Slic3r::GUI::PartPlate::update_apply_result_invalid(), UPDATE_BACKGROUND_PROCESS_INVALID, UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE, UPDATE_BACKGROUND_PROCESS_RESTART, Slic3r::GUI::Preview::update_gcode_result(), update_print_volume_state(), Slic3r::GUI::PartPlateList::update_slice_context_to_current_plate(), Slic3r::GUI::MainFrame::update_slice_print_status(), Slic3r::GUI::PartPlate::update_slice_result_valid_state(), Slic3r::GUI::ValidateError, and view3D.

Referenced by export_gcode(), export_gcode(), update(), and update_restart_background_process().

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

◆ update_fff_scene()

void Slic3r::GUI::Plater::priv::update_fff_scene ( )
private
11746{
11747 if (this->preview != nullptr)
11748 this->preview->reload_print();
11749 // In case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth:
11750 view3D->reload_scene(true);
11751 //BBS: add assemble view related logic
11752 assemble_view->reload_scene(true);
11753
11754 q->mark_plate_toolbar_image_dirty();
11755}

References assemble_view, q, Slic3r::GUI::Preview::reload_print(), and view3D.

Referenced by on_process_completed().

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

◆ update_fff_scene_only_shells()

void Slic3r::GUI::Plater::priv::update_fff_scene_only_shells ( bool only_shells = true)
11759{
11760 if (this->preview != nullptr)
11761 {
11762 const Print* current_print = this->background_process.fff_print();
11763 if (current_print)
11764 {
11765 //this->preview->reset_shells();
11766 this->preview->load_shells(*current_print);
11767 }
11768 }
11769
11770 if (!only_shells) {
11771 view3D->reload_scene(true);
11772 assemble_view->reload_scene(true);
11773 }
11774}

References assemble_view, Slic3r::BackgroundSlicingProcess::fff_print(), Slic3r::GUI::Preview::load_shells(), and view3D.

Referenced by on_process_completed(), on_slicing_completed(), on_slicing_update(), and set_current_panel().

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

◆ update_objects_position_when_select_preset()

void Slic3r::GUI::Plater::priv::update_objects_position_when_select_preset ( const std::function< void()> & select_prest)
14524{
14525 select_prest();
14526
14527 wxGetApp().obj_list()->update_object_list_by_printer_technology();
14528
14529 // Re-clamp wipe tower positions to new bed boundaries after preset change
14530 PartPlateList &cur_plate_list = this->partplate_list;
14531 for (size_t plate_id = 0; plate_id < cur_plate_list.get_plate_list().size(); ++plate_id) {
14532 cur_plate_list.set_default_wipe_tower_pos_for_plate(plate_id);
14533 }
14534
14535 update();
14536}

References Slic3r::GUI::PartPlateList::get_plate_list(), Slic3r::GUI::PartPlateList::set_default_wipe_tower_pos_for_plate(), and Slic3r::GUI::Plater::update().

Here is the call graph for this function:

◆ update_plugin_when_launch()

void Slic3r::GUI::Plater::priv::update_plugin_when_launch ( wxCommandEvent & event)
private
14097{
14098 std::string data_dir_str = data_dir();
14099 boost::filesystem::path data_dir_path(data_dir_str);
14100 auto cache_folder = data_dir_path / "ota";
14101 std::string changelog_file = cache_folder.string() + "/plugins/network_plugins.json";
14102
14103 UpdatePluginDialog dlg(wxGetApp().mainframe);
14104 dlg.update_info(changelog_file);
14105 auto result = dlg.ShowModal();
14106
14107 auto app_config = wxGetApp().app_config;
14108 if (!app_config) return;
14109
14110 if (result == wxID_OK) {
14111 // Apply the downloaded update right away and hot-reload the plug-in, the same
14112 // way a manual version switch in Preferences behaves. When a file is still in
14113 // use and cannot be replaced, fall back to installing on the next launch.
14114 bool had_cache = false;
14115 if (wxGetApp().install_network_plugin_from_ota(had_cache)) {
14117 app_config->set("update_network_plugin", "false");
14118 if (wxGetApp().hot_reload_network_plugin()) {
14119 MessageDialog dlg_ok(wxGetApp().mainframe, _L("Network plug-in switched successfully."), _L("Success"), wxOK | wxICON_INFORMATION);
14120 dlg_ok.ShowModal();
14121 } else {
14122 MessageDialog dlg_fail(wxGetApp().mainframe, _L("Failed to load network plug-in. Please restart the application."), _L("Restart Required"), wxOK | wxICON_WARNING);
14123 dlg_fail.ShowModal();
14124 }
14125 } else {
14126 app_config->set("update_network_plugin", had_cache ? "true" : "false");
14127 }
14128 }
14129 else if (result == wxID_NO) {
14130 app_config->set("update_network_plugin", "false");
14131 }
14132}
@ BBLPluginUpdateAvailable
Definition NotificationManager.hpp:175
const std::string & data_dir()
Definition utils.cpp:365

References _L, Slic3r::GUI::BBLPluginUpdateAvailable, Slic3r::data_dir(), notification_manager, Slic3r::GUI::DPIAware< P >::ShowModal(), and Slic3r::GUI::UpdatePluginDialog::update_info().

Here is the call graph for this function:

◆ update_preview_bottom_toolbar()

void Slic3r::GUI::Plater::priv::update_preview_bottom_toolbar ( )
14830{
14831 ;
14832}

◆ update_print_required_data()

int Slic3r::GUI::Plater::priv::update_print_required_data ( Slic3r::DynamicPrintConfig config,
Slic3r::Model model,
Slic3r::PlateDataPtrs plate_data_list,
std::string file_name,
std::string file_path )
13926{
13927 if (!m_select_machine_dlg) m_select_machine_dlg = new SelectMachineDialog(q);
13928 return m_select_machine_dlg->update_print_required_data(config, model, plate_data_list, file_name, file_path);
13929}

References config, m_select_machine_dlg, model, and q.

◆ update_print_volume_state()

void Slic3r::GUI::Plater::priv::update_print_volume_state ( )
11231{
11232 //BBS: use the plate's bounding box instead of the bed's
11233 PartPlate* pp = partplate_list.get_curr_plate();
11234 BuildVolume build_volume(pp->get_shape(), this->bed.build_volume().printable_height(), this->bed.build_volume().extruder_areas(), this->bed.build_volume().extruder_heights());
11235 this->model.update_print_volume_state(build_volume);
11236}
const BuildVolume & build_volume() const
Definition Plater.cpp:23803

References Slic3r::GUI::Plater::build_volume(), Slic3r::GUI::PartPlate::get_shape(), and partplate_list.

Referenced by get_export_file_path(), and update_background_process().

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

◆ update_project_dirty_from_presets()

void Slic3r::GUI::Plater::priv::update_project_dirty_from_presets ( )
inline
7315 {
7316 // BBS: backup
7318 dirty_state.update_from_presets();
7319 }

References dirty_state, and Slic3r::put_other_changes().

Here is the call graph for this function:

◆ update_restart_background_process()

unsigned int Slic3r::GUI::Plater::priv::update_restart_background_process ( bool force_scene_update,
bool force_preview_update )
11725{
11726 bool switch_print = true;
11727 //BBS: judge whether can switch print or not
11728 if ((partplate_list.get_plate_count() > 1) && !this->background_process.can_switch_print())
11729 {
11730 //can not switch print currently
11731 BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": plate count %1%, can not switch") % partplate_list.get_plate_count();
11732 switch_print = false;
11733 }
11734 // bitmask of UpdateBackgroundProcessReturnState
11735 unsigned int state = this->update_background_process(false, false, switch_print);
11736 if (force_update_scene || (state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0)
11737 view3D->reload_scene(false);
11738
11739 if (force_update_preview)
11740 this->preview->reload_print();
11741 this->restart_background_process(state);
11742 return state;
11743}

References partplate_list, Slic3r::GUI::Preview::reload_print(), restart_background_process(), update_background_process(), UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE, and view3D.

Referenced by set_current_panel(), and update_sla_scene().

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

◆ update_sidebar()

void Slic3r::GUI::Plater::priv::update_sidebar ( bool force_update = false)
8635 {
8636 auto& sidebar = m_aui_mgr.GetPane(this->sidebar);
8637 if (!sidebar.IsOk() || this->current_panel == nullptr) {
8638 return;
8639 }
8640 bool needs_update = force_update;
8641
8642 if (!sidebar_layout.is_enabled) {
8643 if (sidebar.IsShown()) {
8644 sidebar.Hide();
8645 needs_update = true;
8646 }
8647 } else {
8648 // Only hide if collapsed or is floating and is not 3d view
8649 const bool should_hide = sidebar_layout.is_collapsed || (sidebar.IsFloating() && !sidebar_layout.show);
8650 const bool should_show = !should_hide;
8651 if (should_show != sidebar.IsShown()) {
8652 sidebar.Show(should_show);
8653 needs_update = true;
8654 }
8655 }
8656
8657 for (const auto& [window, dock_pane] : m_dock_panes) {
8658 wxAuiPaneInfo& pane = m_aui_mgr.GetPane(window);
8659 if (pane.IsOk() && pane.IsShown() != dock_pane_visible(dock_pane, pane)) {
8660 pane.Show(!pane.IsShown());
8661 needs_update = true;
8662 }
8663 }
8664
8665 if (needs_update) {
8666 notification_manager->set_sidebar_collapsed(sidebar.IsShown());
8667 m_aui_mgr.Update();
8668 }
8669}

References dock_pane_visible(), m_aui_mgr, m_dock_panes, notification_manager, sidebar, and sidebar_layout.

Referenced by collapse_sidebar(), enable_sidebar(), on_tab_selection_changing(), reset_window_layout(), set_current_panel(), and update().

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

◆ update_sla_scene()

void Slic3r::GUI::Plater::priv::update_sla_scene ( )
private
11777{
11778 // Update the SLAPrint from the current Model, so that the reload_scene()
11779 // pulls the correct data.
11780 delayed_scene_refresh = false;
11781 this->update_restart_background_process(true, true);
11782}

References delayed_scene_refresh, and update_restart_background_process().

Referenced by on_3dcanvas_mouse_dragging_finished(), on_process_completed(), on_slicing_completed(), and on_slicing_update().

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

◆ update_title_dirty_status()

void Slic3r::GUI::Plater::priv::update_title_dirty_status ( )
14452{
14453 if (m_project_name.empty())
14454 return;
14455
14456 wxString title;
14457 if (is_project_dirty())
14458 title = "*" + m_project_name;
14459 else
14460 title = m_project_name;
14461
14462#ifdef __APPLE__
14463 wxGetApp().mainframe->SetTitle(title);
14464 wxGetApp().mainframe->update_title_colour_after_set_title();
14465#else
14466 wxGetApp().mainframe->SetTitle(title + " - OrcaSlicer");
14467 wxGetApp().mainframe->topbar()->SetTitle(title);
14468#endif
14469}
bool is_project_dirty() const
Definition Plater.cpp:7312

References Slic3r::GUI::Plater::is_project_dirty(), and m_project_name.

Here is the call graph for this function:

◆ update_ui_from_settings()

void Slic3r::GUI::Plater::priv::update_ui_from_settings ( )
8774{
8776
8777 view3D->get_canvas3d()->update_ui_from_settings();
8778 preview->get_canvas3d()->update_ui_from_settings();
8779
8780 sidebar->update_ui_from_settings();
8781}

References apply_free_camera_correction(), preview, sidebar, and view3D.

Here is the call graph for this function:

◆ warnings_dialog()

bool Slic3r::GUI::Plater::priv::warnings_dialog ( )
13320{
13321 if (current_warnings.empty())
13322 return true;
13323 std::string text = _u8L("There are warnings after slicing models:") + "\n";
13324 for (auto const& it : current_warnings) {
13325 size_t next_n = it.first.message.find_first_of('\n', 0);
13326 text += "\n";
13327 if (next_n != std::string::npos)
13328 text += it.first.message.substr(0, next_n);
13329 else
13330 text += it.first.message;
13331 }
13332 //text += "\n\nDo you still wish to export?";
13333 MessageDialog msg_window(this->q, from_u8(text), _L("warnings"), wxOK);
13334 const auto res = msg_window.ShowModal();
13335 return res == wxID_OK;
13336
13337}

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

Referenced by on_export_began().

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

Member Data Documentation

◆ assemble_view

◆ auto_reslice_after_cancel

bool Slic3r::GUI::Plater::priv::auto_reslice_after_cancel {false}

◆ auto_reslice_pending

bool Slic3r::GUI::Plater::priv::auto_reslice_pending {false}
7234{false};

Referenced by schedule_auto_reslice_if_needed().

◆ auto_reslice_timer

wxTimer Slic3r::GUI::Plater::priv::auto_reslice_timer

◆ background_process

◆ background_process_timer

wxTimer Slic3r::GUI::Plater::priv::background_process_timer

◆ bed

Bed3D Slic3r::GUI::Plater::priv::bed

◆ camera

Camera Slic3r::GUI::Plater::priv::camera

◆ collapse_toolbar

GLToolbar Slic3r::GUI::Plater::priv::collapse_toolbar

◆ config

◆ current_panel

◆ current_warnings

std::vector<std::pair<Slic3r::PrintStateBase::Warning, size_t> > Slic3r::GUI::Plater::priv::current_warnings
private

◆ delayed_error_message

std::string Slic3r::GUI::Plater::priv::delayed_error_message

◆ delayed_scene_refresh

bool Slic3r::GUI::Plater::priv::delayed_scene_refresh

◆ dirty_state

◆ exporting_status

ExportingStatus Slic3r::GUI::Plater::priv::exporting_status { NOT_EXPORTING }
7738{ NOT_EXPORTING };

Referenced by on_process_completed().

◆ fff_print

Slic3r::Print Slic3r::GUI::Plater::priv::fff_print

◆ first_enter_assemble

bool Slic3r::GUI::Plater::priv::first_enter_assemble { true }
7262{ true };

Referenced by set_current_panel().

◆ gcode_result

Slic3r::GCodeProcessorResult Slic3r::GUI::Plater::priv::gcode_result

◆ label_btn_export

std::string Slic3r::GUI::Plater::priv::label_btn_export

◆ label_btn_send

std::string Slic3r::GUI::Plater::priv::label_btn_send

◆ last_output_dir_path

std::string Slic3r::GUI::Plater::priv::last_output_dir_path

Referenced by on_process_completed().

◆ last_output_path

std::string Slic3r::GUI::Plater::priv::last_output_path

Referenced by on_process_completed().

◆ m_aui_mgr

◆ m_backup_timestamp

size_t Slic3r::GUI::Plater::priv::m_backup_timestamp = 0
private

Referenced by reset(), and up_to_date().

◆ m_belt_purge_sigs

std::vector<BeltPurgeSignature> Slic3r::GUI::Plater::priv::m_belt_purge_sigs

Referenced by ensure_belt_purge_tower().

◆ m_broken_shown_sig

std::string Slic3r::GUI::Plater::priv::m_broken_shown_sig

◆ m_cloud_missing_shown_sig

std::string Slic3r::GUI::Plater::priv::m_cloud_missing_shown_sig

◆ m_cur_slice_plate

int Slic3r::GUI::Plater::priv::m_cur_slice_plate

◆ m_default_window_layout

wxString Slic3r::GUI::Plater::priv::m_default_window_layout

Referenced by reset_window_layout().

◆ m_dock_panes

std::map<wxWindow*, DockPane> Slic3r::GUI::Plater::priv::m_dock_panes

◆ m_has_pending_published

bool Slic3r::GUI::Plater::priv::m_has_pending_published {false}
7186{false};

Referenced by reset().

◆ m_ignore_event

bool Slic3r::GUI::Plater::priv::m_ignore_event {false}
7223{false};

Referenced by on_process_completed().

◆ m_inactive_shown_sig

std::string Slic3r::GUI::Plater::priv::m_inactive_shown_sig

◆ m_is_dark

bool Slic3r::GUI::Plater::priv::m_is_dark = false

◆ m_is_RightClickInLeftUI

int Slic3r::GUI::Plater::priv::m_is_RightClickInLeftUI {-1}
7236{-1};

◆ m_is_slicing

bool Slic3r::GUI::Plater::priv::m_is_slicing {false}

◆ m_job_prepare_state

int Slic3r::GUI::Plater::priv::m_job_prepare_state

◆ m_last_fff_printer_profile_name

std::string Slic3r::GUI::Plater::priv::m_last_fff_printer_profile_name
private

Referenced by take_snapshot(), and undo_redo_to().

◆ m_last_sla_printer_profile_name

std::string Slic3r::GUI::Plater::priv::m_last_sla_printer_profile_name
private

Referenced by take_snapshot(), and undo_redo_to().

◆ m_local_missing_shown_sig

std::string Slic3r::GUI::Plater::priv::m_local_missing_shown_sig

◆ m_need_update

bool Slic3r::GUI::Plater::priv::m_need_update {false}
7241{false};

Referenced by need_update(), and set_need_update().

◆ m_pending_material_keys

std::vector<Slic3r::PublishedMaterialEntry> Slic3r::GUI::Plater::priv::m_pending_material_keys

Referenced by reset().

◆ m_pending_published_keys

std::vector<std::string> Slic3r::GUI::Plater::priv::m_pending_published_keys

Referenced by reset().

◆ m_prevent_snapshots

int Slic3r::GUI::Plater::priv::m_prevent_snapshots = 0
private

◆ m_print_job_data

PrintPrepareData Slic3r::GUI::Plater::priv::m_print_job_data

◆ m_project_folder

boost::filesystem::path Slic3r::GUI::Plater::priv::m_project_folder
private

◆ m_project_name

wxString Slic3r::GUI::Plater::priv::m_project_name
private

◆ m_saved_timestamp

size_t Slic3r::GUI::Plater::priv::m_saved_timestamp = 0
private

Referenced by reset(), and up_to_date().

◆ m_select_machine_dlg

◆ m_send_multi_dlg

SendMultiMachinePage* Slic3r::GUI::Plater::priv::m_send_multi_dlg = nullptr

◆ m_send_to_sdcard_dlg

SendToPrinterDialog* Slic3r::GUI::Plater::priv::m_send_to_sdcard_dlg = nullptr

◆ m_single

Plater::SingleSnapshot* Slic3r::GUI::Plater::priv::m_single = nullptr
private

◆ m_sla_import_dlg

SLAImportDialog* Slic3r::GUI::Plater::priv::m_sla_import_dlg

◆ m_slice_all

bool Slic3r::GUI::Plater::priv::m_slice_all {false}

◆ m_slice_all_only_has_gcode

bool Slic3r::GUI::Plater::priv::m_slice_all_only_has_gcode { false }

◆ m_undo_redo_stack_active

Slic3r::UndoRedo::Stack* Slic3r::GUI::Plater::priv::m_undo_redo_stack_active = &m_undo_redo_stack_main
private

◆ m_undo_redo_stack_gizmos

Slic3r::UndoRedo::Stack Slic3r::GUI::Plater::priv::m_undo_redo_stack_gizmos
private

◆ m_undo_redo_stack_main

◆ m_worker

◆ main_frame

◆ menus

MenuFactory Slic3r::GUI::Plater::priv::menus

◆ model

◆ mouse3d_controller

Mouse3DController Slic3r::GUI::Plater::priv::mouse3d_controller

◆ notification_manager

◆ panels

std::vector<wxPanel*> Slic3r::GUI::Plater::priv::panels

Referenced by set_current_panel().

◆ partplate_list

◆ pattern_3mf

const std::regex Slic3r::GUI::Plater::priv::pattern_3mf
static

Referenced by load_files().

◆ pattern_any_amf

const std::regex Slic3r::GUI::Plater::priv::pattern_any_amf
static

Referenced by load_files().

◆ pattern_bundle

const std::regex Slic3r::GUI::Plater::priv::pattern_bundle
static

Referenced by load_files().

◆ pattern_prusa

const std::regex Slic3r::GUI::Plater::priv::pattern_prusa
static

◆ pattern_zip_amf

const std::regex Slic3r::GUI::Plater::priv::pattern_zip_amf
static

◆ preview

◆ printer_technology

◆ process_completed_with_error

int Slic3r::GUI::Plater::priv::process_completed_with_error { -1 }
7744{ -1 }; //-1 means no error

Referenced by on_process_completed(), and update_background_process().

◆ project

BBLProject Slic3r::GUI::Plater::priv::project

Referenced by reset().

◆ q

Plater* Slic3r::GUI::Plater::priv::q

Referenced by priv(), add_dock_pane(), can_add_plate(), can_decrease_instances(), can_delete_plate(), can_increase_instances(), can_simplify(), can_split_to_objects(), can_split_to_volumes(), check_ams_status_impl(), delete_all_objects_from_model(), delete_object_from_model(), export_gcode(), export_gcode(), gcode_preview_without_settings(), get_export_file(), load_auxiliary_files(), load_files(), load_model_objects(), object_list_changed(), on_action_add(), on_action_add_plate(), on_action_del_plate(), on_action_download_project(), on_action_export_all_sliced_file(), on_action_export_gcode(), on_action_export_sliced_file(), on_action_export_to_sdcard(), on_action_export_to_sdcard_all(), on_action_layersediting(), on_action_open_project(), on_action_print_all(), on_action_print_plate(), on_action_print_plate_from_sdcard(), on_action_request_model_id(), on_action_select_sliced_plate(), on_action_send_gcode(), on_action_send_to_multi_machine(), on_action_send_to_printer(), on_action_slice_all(), on_action_slice_plate(), on_export_finished(), on_process_completed(), on_right_click(), on_select_bed_type(), on_select_preset(), on_slicing_began(), on_tab_selection_changing(), open_machine_select_dialog(), PopupObjectTable(), reload_all_from_disk(), reload_from_disk(), remove_curr_plate_all(), replace_all_with_stl(), replace_volume_with_stl(), replace_with_stl(), reset(), run_textured_mesh_import_dialog(), select_view_3D(), set_current_panel(), set_project_filename(), show_right_click_menu(), split_object(), undo_redo_to(), update(), update_background_process(), update_fff_scene(), and update_print_required_data().

◆ show_render_statistic_dialog

bool Slic3r::GUI::Plater::priv::show_render_statistic_dialog { false }
7291{ false };

◆ show_warning_dialog

bool Slic3r::GUI::Plater::priv::show_warning_dialog { false }
private

◆ show_wireframe

bool Slic3r::GUI::Plater::priv::show_wireframe { false }
7292{ false };

◆ show_xray

bool Slic3r::GUI::Plater::priv::show_xray { false }
7294{ false };

◆ sidebar

◆ sidebar_layout

◆ sla_print

Slic3r::SLAPrint Slic3r::GUI::Plater::priv::sla_print

◆ suppressed_backround_processing_update

bool Slic3r::GUI::Plater::priv::suppressed_backround_processing_update { false }
7268{ false };

◆ uv_editor_canvas

UVEditorCanvas* Slic3r::GUI::Plater::priv::uv_editor_canvas { nullptr }
7261{ nullptr };

◆ uv_editor_panel

UVEditorPanel* Slic3r::GUI::Plater::priv::uv_editor_panel { nullptr }
7260{ nullptr };

◆ view3D

◆ wireframe_enabled

bool Slic3r::GUI::Plater::priv::wireframe_enabled { true }
7293{ true };

The documentation for this struct was generated from the following file:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/Plater.cpp