2018-09-17 10:15:11 +00:00
# include "Plater.hpp"
# include <cstddef>
# include <algorithm>
2019-06-26 15:09:26 +00:00
# include <numeric>
2018-09-17 10:15:11 +00:00
# include <vector>
# include <string>
# include <regex>
2019-05-13 16:58:56 +00:00
# include <future>
2019-05-17 14:27:00 +00:00
# include <boost/algorithm/string.hpp>
2018-10-04 09:12:55 +00:00
# include <boost/optional.hpp>
2018-09-17 10:15:11 +00:00
# include <boost/filesystem/path.hpp>
2019-09-19 07:09:11 +00:00
# include <boost/filesystem/operations.hpp>
2019-06-18 15:10:13 +00:00
# include <boost/log/trivial.hpp>
2020-05-01 06:57:24 +00:00
# include <boost/nowide/convert.hpp>
2018-09-17 10:15:11 +00:00
# include <wx/sizer.h>
# include <wx/stattext.h>
# include <wx/button.h>
# include <wx/bmpcbox.h>
# include <wx/statbox.h>
# include <wx/statbmp.h>
# include <wx/filedlg.h>
# include <wx/dnd.h>
# include <wx/progdlg.h>
2018-10-01 14:48:08 +00:00
# include <wx/wupdlock.h>
2018-10-18 13:13:38 +00:00
# include <wx/numdlg.h>
# include <wx/debug.h>
2020-01-21 13:07:13 +00:00
# include <wx/busyinfo.h>
2018-09-17 10:15:11 +00:00
2018-10-09 07:35:19 +00:00
# include "libslic3r/libslic3r.h"
2018-11-26 13:41:58 +00:00
# include "libslic3r/Format/STL.hpp"
# include "libslic3r/Format/AMF.hpp"
# include "libslic3r/Format/3mf.hpp"
# include "libslic3r/GCode/PreviewData.hpp"
2019-10-24 10:09:09 +00:00
# include "libslic3r/GCode/ThumbnailData.hpp"
2018-09-17 10:15:11 +00:00
# include "libslic3r/Model.hpp"
2019-11-11 10:41:14 +00:00
# include "libslic3r/SLA/Hollowing.hpp"
# include "libslic3r/SLA/SupportPoint.hpp"
2020-05-12 13:52:33 +00:00
# include "libslic3r/SLA/ReprojectPointsOnMesh.hpp"
2018-11-26 13:41:58 +00:00
# include "libslic3r/Polygon.hpp"
2018-09-17 10:15:11 +00:00
# include "libslic3r/Print.hpp"
2018-11-26 13:41:58 +00:00
# include "libslic3r/PrintConfig.hpp"
2018-11-08 19:18:40 +00:00
# include "libslic3r/SLAPrint.hpp"
2018-09-17 10:15:11 +00:00
# include "libslic3r/Utils.hpp"
2018-11-26 13:41:58 +00:00
2018-09-17 10:15:11 +00:00
# include "GUI.hpp"
# include "GUI_App.hpp"
2018-10-04 14:43:10 +00:00
# include "GUI_ObjectList.hpp"
# include "GUI_ObjectManipulation.hpp"
2019-05-28 14:38:04 +00:00
# include "GUI_ObjectLayers.hpp"
2018-10-04 09:12:55 +00:00
# include "GUI_Utils.hpp"
2018-10-17 10:17:25 +00:00
# include "wxExtensions.hpp"
2018-09-17 10:15:11 +00:00
# include "MainFrame.hpp"
2020-04-01 08:30:33 +00:00
# include "format.hpp"
2018-09-17 10:15:11 +00:00
# include "3DScene.hpp"
2018-10-03 09:34:39 +00:00
# include "GLCanvas3D.hpp"
2019-03-19 12:30:21 +00:00
# include "Selection.hpp"
2018-09-17 10:15:11 +00:00
# include "GLToolbar.hpp"
# include "GUI_Preview.hpp"
2019-02-19 14:15:27 +00:00
# include "3DBed.hpp"
2019-03-06 14:46:19 +00:00
# include "Camera.hpp"
2019-09-27 12:52:19 +00:00
# include "Mouse3DController.hpp"
2018-09-17 10:15:11 +00:00
# include "Tab.hpp"
2020-04-23 16:56:09 +00:00
# include "Jobs/ArrangeJob.hpp"
# include "Jobs/RotoptimizeJob.hpp"
2020-04-23 17:45:55 +00:00
# include "Jobs/SLAImportJob.hpp"
2018-09-17 10:15:11 +00:00
# include "PresetBundle.hpp"
# include "BackgroundSlicingProcess.hpp"
# include "ProgressStatusBar.hpp"
2018-12-11 09:33:11 +00:00
# include "PrintHostDialogs.hpp"
2019-03-22 14:45:51 +00:00
# include "ConfigWizard.hpp"
2018-11-26 13:41:58 +00:00
# include "../Utils/ASCIIFolding.hpp"
2018-12-11 09:33:11 +00:00
# include "../Utils/PrintHost.hpp"
2018-11-07 12:40:24 +00:00
# include "../Utils/FixModelByWin10.hpp"
2019-07-02 14:42:23 +00:00
# include "../Utils/UndoRedo.hpp"
2019-11-27 12:30:45 +00:00
# include "RemovableDriveManager.hpp"
2020-04-29 08:50:28 +00:00
# include "InstanceCheck.hpp"
2020-06-16 10:57:49 +00:00
# include "PresetComboBoxes.hpp"
2020-04-29 08:50:28 +00:00
2020-03-02 11:45:04 +00:00
# ifdef __APPLE__
# include "Gizmos/GLGizmosManager.hpp"
# endif // __APPLE__
2018-09-17 10:15:11 +00:00
# include <wx/glcanvas.h> // Needs to be last because reasons :-/
2018-10-03 13:14:52 +00:00
# include "WipeTowerDialog.hpp"
2020-01-23 14:07:31 +00:00
# include "libslic3r/CustomGCode.hpp"
2018-09-17 10:15:11 +00:00
2018-10-04 09:12:55 +00:00
using boost : : optional ;
2018-09-17 10:15:11 +00:00
namespace fs = boost : : filesystem ;
using Slic3r : : _3DScene ;
using Slic3r : : Preset ;
2018-12-11 09:33:11 +00:00
using Slic3r : : PrintHostJob ;
2020-04-01 08:08:03 +00:00
using Slic3r : : GUI : : format_wxstr ;
2018-09-17 10:15:11 +00:00
2019-10-24 08:06:31 +00:00
static const std : : pair < unsigned int , unsigned int > THUMBNAIL_SIZE_3MF = { 256 , 256 } ;
2018-09-17 10:15:11 +00:00
namespace Slic3r {
namespace GUI {
2018-11-26 13:41:58 +00:00
wxDEFINE_EVENT ( EVT_SCHEDULE_BACKGROUND_PROCESS , SimpleEvent ) ;
wxDEFINE_EVENT ( EVT_SLICING_UPDATE , SlicingStatusEvent ) ;
wxDEFINE_EVENT ( EVT_SLICING_COMPLETED , wxCommandEvent ) ;
wxDEFINE_EVENT ( EVT_PROCESS_COMPLETED , wxCommandEvent ) ;
2018-09-17 10:15:11 +00:00
// Sidebar widgets
// struct InfoBox : public wxStaticBox
// {
// InfoBox(wxWindow *parent, const wxString &label) :
// wxStaticBox(parent, wxID_ANY, label)
// {
// SetFont(GUI::small_font().Bold());
// }
// };
class ObjectInfo : public wxStaticBoxSizer
{
public :
ObjectInfo ( wxWindow * parent ) ;
2018-10-05 21:29:15 +00:00
wxStaticBitmap * manifold_warning_icon ;
2018-09-17 10:15:11 +00:00
wxStaticText * info_size ;
wxStaticText * info_volume ;
wxStaticText * info_facets ;
wxStaticText * info_materials ;
wxStaticText * info_manifold ;
2019-02-19 11:14:13 +00:00
wxStaticText * label_volume ;
wxStaticText * label_materials ;
2019-02-21 14:46:04 +00:00
std : : vector < wxStaticText * > sla_hidden_items ;
2019-02-19 11:14:13 +00:00
2018-11-01 11:33:56 +00:00
bool showing_manifold_warning_icon ;
void show_sizer ( bool show ) ;
2019-04-24 23:45:00 +00:00
void msw_rescale ( ) ;
2018-09-17 10:15:11 +00:00
} ;
ObjectInfo : : ObjectInfo ( wxWindow * parent ) :
2020-04-01 07:48:56 +00:00
wxStaticBoxSizer ( new wxStaticBox ( parent , wxID_ANY , _L ( " Info " ) ) , wxVERTICAL )
2018-09-17 10:15:11 +00:00
{
2018-10-01 13:09:31 +00:00
GetStaticBox ( ) - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
2018-09-17 10:15:11 +00:00
2019-04-13 21:46:52 +00:00
auto * grid_sizer = new wxFlexGridSizer ( 4 , 5 , 15 ) ;
2018-09-17 10:15:11 +00:00
grid_sizer - > SetFlexibleDirection ( wxHORIZONTAL ) ;
2019-04-13 21:46:52 +00:00
// grid_sizer->AddGrowableCol(1, 1);
// grid_sizer->AddGrowableCol(3, 1);
2018-09-17 10:15:11 +00:00
auto init_info_label = [ parent , grid_sizer ] ( wxStaticText * * info_label , wxString text_label ) {
2019-01-21 11:34:28 +00:00
auto * text = new wxStaticText ( parent , wxID_ANY , text_label + " : " ) ;
2018-10-01 13:09:31 +00:00
text - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2018-09-17 10:15:11 +00:00
* info_label = new wxStaticText ( parent , wxID_ANY , " " ) ;
2018-10-01 13:09:31 +00:00
( * info_label ) - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2018-09-17 10:15:11 +00:00
grid_sizer - > Add ( text , 0 ) ;
grid_sizer - > Add ( * info_label , 0 ) ;
2019-02-19 11:14:13 +00:00
return text ;
2018-09-17 10:15:11 +00:00
} ;
2020-04-01 07:48:56 +00:00
init_info_label ( & info_size , _L ( " Size " ) ) ;
label_volume = init_info_label ( & info_volume , _L ( " Volume " ) ) ;
init_info_label ( & info_facets , _L ( " Facets " ) ) ;
label_materials = init_info_label ( & info_materials , _L ( " Materials " ) ) ;
2018-11-01 11:33:56 +00:00
Add ( grid_sizer , 0 , wxEXPAND ) ;
2018-09-17 10:15:11 +00:00
2020-04-01 07:48:56 +00:00
auto * info_manifold_text = new wxStaticText ( parent , wxID_ANY , _L ( " Manifold " ) + " : " ) ;
2018-10-01 13:09:31 +00:00
info_manifold_text - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2018-09-17 10:15:11 +00:00
info_manifold = new wxStaticText ( parent , wxID_ANY , " " ) ;
2018-10-01 13:09:31 +00:00
info_manifold - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2020-01-31 15:50:11 +00:00
manifold_warning_icon = new wxStaticBitmap ( parent , wxID_ANY , create_scaled_bitmap ( " exclamation " ) ) ;
2018-09-17 10:15:11 +00:00
auto * sizer_manifold = new wxBoxSizer ( wxHORIZONTAL ) ;
sizer_manifold - > Add ( info_manifold_text , 0 ) ;
sizer_manifold - > Add ( manifold_warning_icon , 0 , wxLEFT , 2 ) ;
sizer_manifold - > Add ( info_manifold , 0 , wxLEFT , 2 ) ;
2018-11-01 11:33:56 +00:00
Add ( sizer_manifold , 0 , wxEXPAND | wxTOP , 4 ) ;
2019-02-19 11:14:13 +00:00
2019-02-21 14:46:04 +00:00
sla_hidden_items = { label_volume , info_volume , label_materials , info_materials } ;
2018-11-01 11:33:56 +00:00
}
2018-09-17 10:15:11 +00:00
2018-11-01 11:33:56 +00:00
void ObjectInfo : : show_sizer ( bool show )
{
Show ( show ) ;
if ( show )
manifold_warning_icon - > Show ( showing_manifold_warning_icon & & show ) ;
2018-09-17 10:15:11 +00:00
}
2019-04-24 23:45:00 +00:00
void ObjectInfo : : msw_rescale ( )
2019-04-13 21:46:52 +00:00
{
2020-01-31 15:50:11 +00:00
manifold_warning_icon - > SetBitmap ( create_scaled_bitmap ( " exclamation " ) ) ;
2019-04-13 21:46:52 +00:00
}
2019-11-05 10:37:40 +00:00
enum SlicedInfoIdx
2018-10-31 11:26:57 +00:00
{
siFilament_m ,
siFilament_mm3 ,
siFilament_g ,
2019-02-12 15:34:42 +00:00
siMateril_unit ,
2018-10-31 11:26:57 +00:00
siCost ,
2018-11-20 09:33:54 +00:00
siEstimatedTime ,
2018-10-31 11:26:57 +00:00
siWTNumbetOfToolchanges ,
siCount
} ;
2018-09-17 10:15:11 +00:00
class SlicedInfo : public wxStaticBoxSizer
{
public :
SlicedInfo ( wxWindow * parent ) ;
2019-11-05 10:37:40 +00:00
void SetTextAndShow ( SlicedInfoIdx idx , const wxString & text , const wxString & new_label = " " ) ;
2018-09-17 10:15:11 +00:00
private :
2018-10-31 11:26:57 +00:00
std : : vector < std : : pair < wxStaticText * , wxStaticText * > > info_vec ;
2018-09-17 10:15:11 +00:00
} ;
SlicedInfo : : SlicedInfo ( wxWindow * parent ) :
2020-04-01 07:48:56 +00:00
wxStaticBoxSizer ( new wxStaticBox ( parent , wxID_ANY , _L ( " Sliced Info " ) ) , wxVERTICAL )
2018-09-17 10:15:11 +00:00
{
2018-10-01 13:09:31 +00:00
GetStaticBox ( ) - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
2018-09-17 10:15:11 +00:00
2018-11-20 09:33:54 +00:00
auto * grid_sizer = new wxFlexGridSizer ( 2 , 5 , 15 ) ;
grid_sizer - > SetFlexibleDirection ( wxVERTICAL ) ;
2018-09-17 10:15:11 +00:00
2018-10-31 11:26:57 +00:00
info_vec . reserve ( siCount ) ;
auto init_info_label = [ this , parent , grid_sizer ] ( wxString text_label ) {
2018-09-17 10:15:11 +00:00
auto * text = new wxStaticText ( parent , wxID_ANY , text_label ) ;
2018-10-01 13:09:31 +00:00
text - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2018-10-31 11:26:57 +00:00
auto info_label = new wxStaticText ( parent , wxID_ANY , " N/A " ) ;
2018-10-01 13:09:31 +00:00
info_label - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2018-09-17 10:15:11 +00:00
grid_sizer - > Add ( text , 0 ) ;
grid_sizer - > Add ( info_label , 0 ) ;
2018-10-31 11:26:57 +00:00
info_vec . push_back ( std : : pair < wxStaticText * , wxStaticText * > ( text , info_label ) ) ;
2018-09-17 10:15:11 +00:00
} ;
2020-04-01 07:48:56 +00:00
init_info_label ( _L ( " Used Filament (m) " ) ) ;
init_info_label ( _L ( " Used Filament (mm³) " ) ) ;
init_info_label ( _L ( " Used Filament (g) " ) ) ;
init_info_label ( _L ( " Used Material (unit) " ) ) ;
init_info_label ( _L ( " Cost (money) " ) ) ;
init_info_label ( _L ( " Estimated printing time " ) ) ;
init_info_label ( _L ( " Number of tool changes " ) ) ;
2018-09-17 10:15:11 +00:00
Add ( grid_sizer , 0 , wxEXPAND ) ;
2018-10-31 11:26:57 +00:00
this - > Show ( false ) ;
}
2019-11-05 10:37:40 +00:00
void SlicedInfo : : SetTextAndShow ( SlicedInfoIdx idx , const wxString & text , const wxString & new_label /*=""*/ )
2018-10-31 11:26:57 +00:00
{
const bool show = text ! = " N/A " ;
if ( show )
info_vec [ idx ] . second - > SetLabelText ( text ) ;
2018-11-20 09:33:54 +00:00
if ( ! new_label . IsEmpty ( ) )
info_vec [ idx ] . first - > SetLabelText ( new_label ) ;
2018-10-31 11:26:57 +00:00
info_vec [ idx ] . first - > Show ( show ) ;
info_vec [ idx ] . second - > Show ( show ) ;
2018-09-17 10:15:11 +00:00
}
2018-10-04 14:43:10 +00:00
// Frequently changed parameters
class FreqChangedParams : public OG_Settings
{
double m_brim_width = 0.0 ;
wxButton * m_wiping_dialog_button { nullptr } ;
2019-01-15 08:31:53 +00:00
wxSizer * m_sizer { nullptr } ;
std : : shared_ptr < ConfigOptionsGroup > m_og_sla ;
2019-07-10 15:50:24 +00:00
std : : vector < ScalableButton * > m_empty_buttons ;
2018-10-04 14:43:10 +00:00
public :
2019-07-10 13:55:53 +00:00
FreqChangedParams ( wxWindow * parent ) ;
2018-10-04 14:43:10 +00:00
~ FreqChangedParams ( ) { }
wxButton * get_wiping_dialog_button ( ) { return m_wiping_dialog_button ; }
2019-01-15 08:31:53 +00:00
wxSizer * get_sizer ( ) override ;
ConfigOptionsGroup * get_og ( const bool is_fff ) ;
void Show ( const bool is_fff ) ;
2019-07-10 15:50:24 +00:00
void msw_rescale ( ) ;
2018-10-04 14:43:10 +00:00
} ;
2019-07-10 15:50:24 +00:00
void FreqChangedParams : : msw_rescale ( )
{
m_og - > msw_rescale ( ) ;
m_og_sla - > msw_rescale ( ) ;
for ( auto btn : m_empty_buttons )
btn - > msw_rescale ( ) ;
}
2019-07-10 13:55:53 +00:00
FreqChangedParams : : FreqChangedParams ( wxWindow * parent ) :
2018-10-04 14:43:10 +00:00
OG_Settings ( parent , false )
{
DynamicPrintConfig * config = & wxGetApp ( ) . preset_bundle - > prints . get_edited_preset ( ) . config ;
2019-01-15 08:31:53 +00:00
// Frequently changed parameters for FFF_technology
2018-10-04 14:43:10 +00:00
m_og - > set_config ( config ) ;
2019-07-10 13:55:53 +00:00
m_og - > hide_labels ( ) ;
2018-10-04 14:43:10 +00:00
2018-10-31 11:56:08 +00:00
m_og - > m_on_change = [ config , this ] ( t_config_option_key opt_key , boost : : any value ) {
2019-01-15 08:31:53 +00:00
Tab * tab_print = wxGetApp ( ) . get_tab ( Preset : : TYPE_PRINT ) ;
if ( ! tab_print ) return ;
2018-10-04 14:43:10 +00:00
2018-10-31 11:56:08 +00:00
if ( opt_key = = " fill_density " ) {
2018-10-04 14:43:10 +00:00
value = m_og - > get_config_value ( * config , opt_key ) ;
tab_print - > set_value ( opt_key , value ) ;
tab_print - > update ( ) ;
}
else {
DynamicPrintConfig new_conf = * config ;
2018-10-31 11:56:08 +00:00
if ( opt_key = = " brim " ) {
2018-10-04 14:43:10 +00:00
double new_val ;
double brim_width = config - > opt_float ( " brim_width " ) ;
if ( boost : : any_cast < bool > ( value ) = = true )
{
2018-12-11 15:33:43 +00:00
new_val = m_brim_width = = 0.0 ? 5 :
2018-10-04 14:43:10 +00:00
m_brim_width < 0.0 ? m_brim_width * ( - 1 ) :
m_brim_width ;
}
2018-12-11 15:33:43 +00:00
else {
2018-10-04 14:43:10 +00:00
m_brim_width = brim_width * ( - 1 ) ;
new_val = 0 ;
}
new_conf . set_key_value ( " brim_width " , new ConfigOptionFloat ( new_val ) ) ;
}
2019-05-03 16:01:39 +00:00
else {
assert ( opt_key = = " support " ) ;
2018-10-04 14:43:10 +00:00
const wxString & selection = boost : : any_cast < wxString > ( value ) ;
2019-05-03 16:01:39 +00:00
PrinterTechnology printer_technology = wxGetApp ( ) . preset_bundle - > printers . get_edited_preset ( ) . printer_technology ( ) ;
2018-10-04 14:43:10 +00:00
auto support_material = selection = = _ ( " None " ) ? false : true ;
new_conf . set_key_value ( " support_material " , new ConfigOptionBool ( support_material ) ) ;
2019-05-03 16:01:39 +00:00
if ( selection = = _ ( " Everywhere " ) ) {
2018-10-04 14:43:10 +00:00
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( false ) ) ;
2019-05-03 16:01:39 +00:00
if ( printer_technology = = ptFFF )
new_conf . set_key_value ( " support_material_auto " , new ConfigOptionBool ( true ) ) ;
} else if ( selection = = _ ( " Support on build plate only " ) ) {
2018-10-04 14:43:10 +00:00
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( true ) ) ;
2019-05-03 16:01:39 +00:00
if ( printer_technology = = ptFFF )
new_conf . set_key_value ( " support_material_auto " , new ConfigOptionBool ( true ) ) ;
} else if ( selection = = _ ( " For support enforcers only " ) ) {
assert ( printer_technology = = ptFFF ) ;
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( false ) ) ;
new_conf . set_key_value ( " support_material_auto " , new ConfigOptionBool ( false ) ) ;
}
2018-10-04 14:43:10 +00:00
}
tab_print - > load_config ( new_conf ) ;
}
tab_print - > update_dirty ( ) ;
} ;
2019-08-06 16:16:02 +00:00
2019-02-07 13:44:05 +00:00
Line line = Line { " " , " " } ;
2018-10-04 14:43:10 +00:00
2019-03-11 15:00:13 +00:00
ConfigOptionDef support_def ;
support_def . label = L ( " Supports " ) ;
support_def . type = coStrings ;
support_def . gui_type = " select_open " ;
support_def . tooltip = L ( " Select what kind of support do you need " ) ;
support_def . enum_labels . push_back ( L ( " None " ) ) ;
support_def . enum_labels . push_back ( L ( " Support on build plate only " ) ) ;
2019-05-03 16:01:39 +00:00
support_def . enum_labels . push_back ( L ( " For support enforcers only " ) ) ;
2019-03-11 15:00:13 +00:00
support_def . enum_labels . push_back ( L ( " Everywhere " ) ) ;
2019-05-03 16:01:39 +00:00
support_def . set_default_value ( new ConfigOptionStrings { " None " } ) ;
2019-03-11 15:00:13 +00:00
Option option = Option ( support_def , " support " ) ;
2018-10-04 14:43:10 +00:00
option . opt . full_width = true ;
2019-02-07 13:44:05 +00:00
line . append_option ( option ) ;
2019-07-10 15:50:24 +00:00
/* Not a best solution, but
* Temporary workaround for right border alignment
*/
auto empty_widget = [ this ] ( wxWindow * parent ) {
auto sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
auto btn = new ScalableButton ( parent , wxID_ANY , " mirroring_transparent.png " , wxEmptyString ,
wxDefaultSize , wxDefaultPosition , wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW ) ;
sizer - > Add ( btn , 0 , wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT , int ( 0.3 * wxGetApp ( ) . em_unit ( ) ) ) ;
m_empty_buttons . push_back ( btn ) ;
return sizer ;
} ;
line . append_widget ( empty_widget ) ;
2019-02-07 13:44:05 +00:00
m_og - > append_line ( line ) ;
2019-08-06 16:16:02 +00:00
2019-02-07 13:44:05 +00:00
line = Line { " " , " " } ;
option = m_og - > get_option ( " fill_density " ) ;
option . opt . label = L ( " Infill " ) ;
2019-05-13 16:21:17 +00:00
option . opt . width = 7 /*6*/ ;
2019-07-13 08:37:21 +00:00
option . opt . sidetext = " " ;
2019-02-07 13:44:05 +00:00
line . append_option ( option ) ;
2018-10-04 14:43:10 +00:00
m_brim_width = config - > opt_float ( " brim_width " ) ;
2019-03-11 15:00:13 +00:00
ConfigOptionDef def ;
2018-10-04 14:43:10 +00:00
def . label = L ( " Brim " ) ;
def . type = coBool ;
def . tooltip = L ( " This flag enables the brim that will be printed around each object on the first layer. " ) ;
def . gui_type = " " ;
2019-05-03 16:01:39 +00:00
def . set_default_value ( new ConfigOptionBool { m_brim_width > 0.0 ? true : false } ) ;
2018-10-04 14:43:10 +00:00
option = Option ( def , " brim " ) ;
2019-07-13 08:37:21 +00:00
option . opt . sidetext = " " ;
2019-02-07 13:44:05 +00:00
line . append_option ( option ) ;
2018-10-04 14:43:10 +00:00
2019-04-26 08:16:08 +00:00
auto wiping_dialog_btn = [ this ] ( wxWindow * parent ) {
2020-04-01 07:48:56 +00:00
m_wiping_dialog_button = new wxButton ( parent , wxID_ANY , _L ( " Purging volumes " ) + dots , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT ) ;
2019-07-10 13:55:53 +00:00
m_wiping_dialog_button - > SetFont ( wxGetApp ( ) . normal_font ( ) ) ;
2018-10-04 14:43:10 +00:00
auto sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2019-07-10 15:50:24 +00:00
sizer - > Add ( m_wiping_dialog_button , 0 , wxALIGN_CENTER_VERTICAL ) ;
2018-10-04 14:43:10 +00:00
m_wiping_dialog_button - > Bind ( wxEVT_BUTTON , ( [ parent ] ( wxCommandEvent & e )
{
2019-04-26 08:16:08 +00:00
auto & project_config = wxGetApp ( ) . preset_bundle - > project_config ;
const std : : vector < double > & init_matrix = ( project_config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) ) - > values ;
const std : : vector < double > & init_extruders = ( project_config . option < ConfigOptionFloats > ( " wiping_volumes_extruders " ) ) - > values ;
2018-10-04 14:43:10 +00:00
2019-09-30 12:03:50 +00:00
const std : : vector < std : : string > extruder_colours = wxGetApp ( ) . plater ( ) - > get_extruder_colors_from_plater_config ( ) ;
2019-04-26 08:16:08 +00:00
WipingDialog dlg ( parent , cast < float > ( init_matrix ) , cast < float > ( init_extruders ) , extruder_colours ) ;
2018-10-04 14:43:10 +00:00
if ( dlg . ShowModal ( ) = = wxID_OK ) {
std : : vector < float > matrix = dlg . get_matrix ( ) ;
std : : vector < float > extruders = dlg . get_extruders ( ) ;
2019-04-26 08:16:08 +00:00
( project_config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) ) - > values = std : : vector < double > ( matrix . begin ( ) , matrix . end ( ) ) ;
( project_config . option < ConfigOptionFloats > ( " wiping_volumes_extruders " ) ) - > values = std : : vector < double > ( extruders . begin ( ) , extruders . end ( ) ) ;
2019-02-07 13:44:05 +00:00
wxPostEvent ( parent , SimpleEvent ( EVT_SCHEDULE_BACKGROUND_PROCESS , parent ) ) ;
2018-10-04 14:43:10 +00:00
}
} ) ) ;
2019-07-10 15:50:24 +00:00
2019-08-06 16:16:02 +00:00
auto btn = new ScalableButton ( parent , wxID_ANY , " mirroring_transparent.png " , wxEmptyString ,
2019-07-10 15:50:24 +00:00
wxDefaultSize , wxDefaultPosition , wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW ) ;
sizer - > Add ( btn , 0 , wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT ,
int ( 0.3 * wxGetApp ( ) . em_unit ( ) ) ) ;
m_empty_buttons . push_back ( btn ) ;
2018-10-04 14:43:10 +00:00
return sizer ;
} ;
2019-02-07 13:44:05 +00:00
line . append_widget ( wiping_dialog_btn ) ;
2019-01-15 08:31:53 +00:00
2019-02-07 13:44:05 +00:00
m_og - > append_line ( line ) ;
2019-01-15 08:31:53 +00:00
2019-03-11 15:00:13 +00:00
2019-01-15 08:31:53 +00:00
// Frequently changed parameters for SLA_technology
m_og_sla = std : : make_shared < ConfigOptionsGroup > ( parent , " " ) ;
2019-07-10 13:55:53 +00:00
m_og_sla - > hide_labels ( ) ;
2019-01-15 08:31:53 +00:00
DynamicPrintConfig * config_sla = & wxGetApp ( ) . preset_bundle - > sla_prints . get_edited_preset ( ) . config ;
m_og_sla - > set_config ( config_sla ) ;
m_og_sla - > m_on_change = [ config_sla , this ] ( t_config_option_key opt_key , boost : : any value ) {
Tab * tab = wxGetApp ( ) . get_tab ( Preset : : TYPE_SLA_PRINT ) ;
if ( ! tab ) return ;
2019-08-06 16:16:02 +00:00
DynamicPrintConfig new_conf = * config_sla ;
if ( opt_key = = " pad " ) {
const wxString & selection = boost : : any_cast < wxString > ( value ) ;
const bool pad_enable = selection = = _ ( " None " ) ? false : true ;
new_conf . set_key_value ( " pad_enable " , new ConfigOptionBool ( pad_enable ) ) ;
if ( selection = = _ ( " Below object " ) )
2019-08-28 09:32:49 +00:00
new_conf . set_key_value ( " pad_around_object " , new ConfigOptionBool ( false ) ) ;
2019-08-06 16:16:02 +00:00
else if ( selection = = _ ( " Around object " ) )
2019-08-28 09:32:49 +00:00
new_conf . set_key_value ( " pad_around_object " , new ConfigOptionBool ( true ) ) ;
2019-03-11 15:00:13 +00:00
}
2019-05-03 16:01:39 +00:00
else
2019-03-11 15:00:13 +00:00
{
2019-05-03 16:01:39 +00:00
assert ( opt_key = = " support " ) ;
2019-03-11 15:00:13 +00:00
const wxString & selection = boost : : any_cast < wxString > ( value ) ;
2019-01-15 08:31:53 +00:00
2019-03-11 15:00:13 +00:00
const bool supports_enable = selection = = _ ( " None " ) ? false : true ;
new_conf . set_key_value ( " supports_enable " , new ConfigOptionBool ( supports_enable ) ) ;
if ( selection = = _ ( " Everywhere " ) )
new_conf . set_key_value ( " support_buildplate_only " , new ConfigOptionBool ( false ) ) ;
else if ( selection = = _ ( " Support on build plate only " ) )
new_conf . set_key_value ( " support_buildplate_only " , new ConfigOptionBool ( true ) ) ;
}
2019-08-06 16:16:02 +00:00
tab - > load_config ( new_conf ) ;
2019-03-11 15:00:13 +00:00
tab - > update_dirty ( ) ;
} ;
2019-02-07 13:44:05 +00:00
line = Line { " " , " " } ;
2019-05-03 16:01:39 +00:00
ConfigOptionDef support_def_sla = support_def ;
support_def_sla . set_default_value ( new ConfigOptionStrings { " None " } ) ;
assert ( support_def_sla . enum_labels [ 2 ] = = L ( " For support enforcers only " ) ) ;
support_def_sla . enum_labels . erase ( support_def_sla . enum_labels . begin ( ) + 2 ) ;
option = Option ( support_def_sla , " support " ) ;
2019-03-11 15:00:13 +00:00
option . opt . full_width = true ;
2019-08-06 16:16:02 +00:00
line . append_option ( option ) ;
2019-07-10 15:50:24 +00:00
line . append_widget ( empty_widget ) ;
2019-03-11 15:00:13 +00:00
m_og_sla - > append_line ( line ) ;
line = Line { " " , " " } ;
2019-02-07 13:44:05 +00:00
2019-08-06 16:16:02 +00:00
ConfigOptionDef pad_def ;
pad_def . label = L ( " Pad " ) ;
pad_def . type = coStrings ;
pad_def . gui_type = " select_open " ;
pad_def . tooltip = L ( " Select what kind of pad do you need " ) ;
pad_def . enum_labels . push_back ( L ( " None " ) ) ;
pad_def . enum_labels . push_back ( L ( " Below object " ) ) ;
pad_def . enum_labels . push_back ( L ( " Around object " ) ) ;
pad_def . set_default_value ( new ConfigOptionStrings { " Below object " } ) ;
option = Option ( pad_def , " pad " ) ;
option . opt . full_width = true ;
2019-02-07 13:44:05 +00:00
line . append_option ( option ) ;
2019-08-06 16:16:02 +00:00
line . append_widget ( empty_widget ) ;
2019-02-07 13:44:05 +00:00
m_og_sla - > append_line ( line ) ;
2019-01-15 08:31:53 +00:00
m_sizer = new wxBoxSizer ( wxVERTICAL ) ;
m_sizer - > Add ( m_og - > sizer , 0 , wxEXPAND ) ;
2019-02-07 13:44:05 +00:00
m_sizer - > Add ( m_og_sla - > sizer , 0 , wxEXPAND ) ;
2018-10-04 14:43:10 +00:00
}
2019-01-15 08:31:53 +00:00
wxSizer * FreqChangedParams : : get_sizer ( )
{
return m_sizer ;
}
void FreqChangedParams : : Show ( const bool is_fff )
2018-10-24 10:57:23 +00:00
{
2019-01-15 08:31:53 +00:00
const bool is_wdb_shown = m_wiping_dialog_button - > IsShown ( ) ;
m_og - > Show ( is_fff ) ;
m_og_sla - > Show ( ! is_fff ) ;
2018-10-24 10:57:23 +00:00
2019-08-06 16:16:02 +00:00
// correct showing of the FreqChangedParams sizer when m_wiping_dialog_button is hidden
2019-01-15 08:31:53 +00:00
if ( is_fff & & ! is_wdb_shown )
2018-10-24 10:57:23 +00:00
m_wiping_dialog_button - > Hide ( ) ;
}
2019-01-15 08:31:53 +00:00
ConfigOptionsGroup * FreqChangedParams : : get_og ( const bool is_fff )
{
return is_fff ? m_og . get ( ) : m_og_sla . get ( ) ;
}
2018-09-17 10:15:11 +00:00
// Sidebar / private
2019-03-01 10:00:34 +00:00
enum class ActionButtonType : int {
abReslice ,
abExport ,
abSendGCode
} ;
2018-09-17 10:15:11 +00:00
struct Sidebar : : priv
{
2018-10-04 09:12:55 +00:00
Plater * plater ;
2018-09-17 10:15:11 +00:00
wxScrolledWindow * scrolled ;
2019-03-13 12:13:18 +00:00
wxPanel * presets_panel ; // Used for MSW better layouts
2018-09-17 10:15:11 +00:00
2019-04-24 23:45:00 +00:00
ModeSizer * mode_sizer ;
2018-09-17 10:15:11 +00:00
wxFlexGridSizer * sizer_presets ;
2020-06-16 10:57:49 +00:00
PlaterPresetComboBox * combo_print ;
std : : vector < PlaterPresetComboBox * > combos_filament ;
2018-09-17 10:15:11 +00:00
wxBoxSizer * sizer_filaments ;
2020-06-16 10:57:49 +00:00
PlaterPresetComboBox * combo_sla_print ;
PlaterPresetComboBox * combo_sla_material ;
PlaterPresetComboBox * combo_printer ;
2018-09-17 10:15:11 +00:00
wxBoxSizer * sizer_params ;
2019-06-27 13:16:36 +00:00
FreqChangedParams * frequently_changed_parameters { nullptr } ;
ObjectList * object_list { nullptr } ;
ObjectManipulation * object_manipulation { nullptr } ;
ObjectSettings * object_settings { nullptr } ;
2019-06-29 10:38:03 +00:00
ObjectLayers * object_layers { nullptr } ;
2018-09-17 10:15:11 +00:00
ObjectInfo * object_info ;
SlicedInfo * sliced_info ;
wxButton * btn_export_gcode ;
wxButton * btn_reslice ;
2019-12-13 12:23:55 +00:00
ScalableButton * btn_send_gcode ;
ScalableButton * btn_remove_device ;
2020-01-10 15:25:32 +00:00
ScalableButton * btn_export_gcode_removable ; //exports to removable drives (appears only if removable drive is connected)
2018-10-04 09:12:55 +00:00
2020-03-28 21:07:56 +00:00
bool is_collapsed { false } ;
2020-04-13 15:55:38 +00:00
Search : : OptionsSearcher searcher ;
2020-03-28 18:39:24 +00:00
2018-10-04 09:12:55 +00:00
priv ( Plater * plater ) : plater ( plater ) { }
2019-06-27 13:16:36 +00:00
~ priv ( ) ;
2018-10-09 06:30:48 +00:00
2018-10-10 11:53:45 +00:00
void show_preset_comboboxes ( ) ;
2018-09-17 10:15:11 +00:00
} ;
2019-06-27 13:16:36 +00:00
Sidebar : : priv : : ~ priv ( )
{
if ( object_manipulation ! = nullptr )
delete object_manipulation ;
if ( object_settings ! = nullptr )
delete object_settings ;
if ( frequently_changed_parameters ! = nullptr )
delete frequently_changed_parameters ;
2019-06-29 10:38:03 +00:00
if ( object_layers ! = nullptr )
delete object_layers ;
2019-06-27 13:16:36 +00:00
}
2018-10-10 11:53:45 +00:00
void Sidebar : : priv : : show_preset_comboboxes ( )
{
2019-02-22 08:38:56 +00:00
const bool showSLA = wxGetApp ( ) . preset_bundle - > printers . get_edited_preset ( ) . printer_technology ( ) = = ptSLA ;
2018-10-10 11:53:45 +00:00
2018-11-15 15:22:25 +00:00
for ( size_t i = 0 ; i < 4 ; + + i )
sizer_presets - > Show ( i , ! showSLA ) ;
2018-10-10 11:53:45 +00:00
2018-11-16 16:36:23 +00:00
for ( size_t i = 4 ; i < 8 ; + + i ) {
2018-11-09 17:39:07 +00:00
if ( sizer_presets - > IsShown ( i ) ! = showSLA )
sizer_presets - > Show ( i , showSLA ) ;
}
2018-10-10 11:53:45 +00:00
2018-11-15 15:22:25 +00:00
frequently_changed_parameters - > Show ( ! showSLA ) ;
2018-10-10 11:53:45 +00:00
2018-11-15 10:15:24 +00:00
scrolled - > GetParent ( ) - > Layout ( ) ;
scrolled - > Refresh ( ) ;
2018-10-10 11:53:45 +00:00
}
2018-09-17 10:15:11 +00:00
// Sidebar / public
2018-10-04 09:12:55 +00:00
Sidebar : : Sidebar ( Plater * parent )
2019-04-13 21:46:52 +00:00
: wxPanel ( parent , wxID_ANY , wxDefaultPosition , wxSize ( 40 * wxGetApp ( ) . em_unit ( ) , - 1 ) ) , p ( new priv ( parent ) )
2018-09-17 10:15:11 +00:00
{
2019-08-23 14:04:58 +00:00
p - > scrolled = new wxScrolledWindow ( this ) ;
p - > scrolled - > SetScrollbars ( 0 , 100 , 1 , 2 ) ;
2018-11-09 17:39:07 +00:00
2020-04-23 10:41:38 +00:00
SetFont ( wxGetApp ( ) . normal_font ( ) ) ;
2020-05-22 13:23:05 +00:00
# ifndef __APPLE__
2020-04-23 10:41:38 +00:00
SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
2020-05-22 13:23:05 +00:00
# endif
2019-03-12 10:39:16 +00:00
2018-11-09 17:39:07 +00:00
// Sizer in the scrolled area
auto * scrolled_sizer = new wxBoxSizer ( wxVERTICAL ) ;
p - > scrolled - > SetSizer ( scrolled_sizer ) ;
2018-09-17 10:15:11 +00:00
2019-01-10 10:05:58 +00:00
// Sizer with buttons for mode changing
2019-07-25 14:23:32 +00:00
p - > mode_sizer = new ModeSizer ( p - > scrolled ) ;
2019-01-10 10:05:58 +00:00
2018-09-17 10:15:11 +00:00
// The preset chooser
2019-02-07 13:44:05 +00:00
p - > sizer_presets = new wxFlexGridSizer ( 10 , 1 , 1 , 2 ) ;
p - > sizer_presets - > AddGrowableCol ( 0 , 1 ) ;
2018-10-10 11:53:45 +00:00
p - > sizer_presets - > SetFlexibleDirection ( wxBOTH ) ;
2019-03-13 12:13:18 +00:00
bool is_msw = false ;
# ifdef __WINDOWS__
p - > scrolled - > SetDoubleBuffered ( true ) ;
p - > presets_panel = new wxPanel ( p - > scrolled , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxTAB_TRAVERSAL ) ;
p - > presets_panel - > SetSizer ( p - > sizer_presets ) ;
is_msw = true ;
# else
2019-03-13 12:37:36 +00:00
p - > presets_panel = p - > scrolled ;
2019-03-13 12:13:18 +00:00
# endif //__WINDOWS__
2018-09-17 10:15:11 +00:00
p - > sizer_filaments = new wxBoxSizer ( wxVERTICAL ) ;
2020-06-16 10:57:49 +00:00
auto init_combo = [ this ] ( PlaterPresetComboBox * * combo , wxString label , Preset : : Type preset_type , bool filament ) {
2019-03-13 12:13:18 +00:00
auto * text = new wxStaticText ( p - > presets_panel , wxID_ANY , label + " : " ) ;
2018-10-01 13:09:31 +00:00
text - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
2020-06-16 10:57:49 +00:00
* combo = new PlaterPresetComboBox ( p - > presets_panel , preset_type ) ;
2018-09-17 10:15:11 +00:00
2019-03-18 14:10:40 +00:00
auto combo_and_btn_sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
combo_and_btn_sizer - > Add ( * combo , 1 , wxEXPAND ) ;
if ( ( * combo ) - > edit_btn )
2019-08-06 16:16:02 +00:00
combo_and_btn_sizer - > Add ( ( * combo ) - > edit_btn , 0 , wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT ,
2019-05-17 13:49:37 +00:00
int ( 0.3 * wxGetApp ( ) . em_unit ( ) ) ) ;
2019-03-18 14:10:40 +00:00
2018-09-17 10:15:11 +00:00
auto * sizer_presets = this - > p - > sizer_presets ;
auto * sizer_filaments = this - > p - > sizer_filaments ;
2019-02-07 13:44:05 +00:00
sizer_presets - > Add ( text , 0 , wxALIGN_LEFT | wxEXPAND | wxRIGHT , 4 ) ;
2018-09-17 10:15:11 +00:00
if ( ! filament ) {
2019-03-18 14:10:40 +00:00
sizer_presets - > Add ( combo_and_btn_sizer , 0 , wxEXPAND | wxBOTTOM , 1 ) ;
2018-09-17 10:15:11 +00:00
} else {
2019-03-18 14:10:40 +00:00
sizer_filaments - > Add ( combo_and_btn_sizer , 0 , wxEXPAND | wxBOTTOM , 1 ) ;
2018-10-10 11:53:45 +00:00
( * combo ) - > set_extruder_idx ( 0 ) ;
2018-09-17 10:15:11 +00:00
sizer_presets - > Add ( sizer_filaments , 1 , wxEXPAND ) ;
}
} ;
p - > combos_filament . push_back ( nullptr ) ;
2020-04-01 07:48:56 +00:00
init_combo ( & p - > combo_print , _L ( " Print settings " ) , Preset : : TYPE_PRINT , false ) ;
init_combo ( & p - > combos_filament [ 0 ] , _L ( " Filament " ) , Preset : : TYPE_FILAMENT , true ) ;
init_combo ( & p - > combo_sla_print , _L ( " SLA print settings " ) , Preset : : TYPE_SLA_PRINT , false ) ;
init_combo ( & p - > combo_sla_material , _L ( " SLA material " ) , Preset : : TYPE_SLA_MATERIAL , false ) ;
init_combo ( & p - > combo_printer , _L ( " Printer " ) , Preset : : TYPE_PRINTER , false ) ;
2018-09-17 10:15:11 +00:00
2019-02-07 13:44:05 +00:00
const int margin_5 = int ( 0.5 * wxGetApp ( ) . em_unit ( ) ) ; // 5;
2018-10-01 13:09:31 +00:00
2018-09-17 10:15:11 +00:00
p - > sizer_params = new wxBoxSizer ( wxVERTICAL ) ;
2018-10-04 14:43:10 +00:00
// Frequently changed parameters
2019-07-10 13:55:53 +00:00
p - > frequently_changed_parameters = new FreqChangedParams ( p - > scrolled ) ;
p - > sizer_params - > Add ( p - > frequently_changed_parameters - > get_sizer ( ) , 0 , wxEXPAND | wxTOP | wxBOTTOM , wxOSX ? 1 : margin_5 ) ;
2019-08-06 16:16:02 +00:00
2018-10-03 13:14:52 +00:00
// Object List
2018-10-04 14:43:10 +00:00
p - > object_list = new ObjectList ( p - > scrolled ) ;
2019-02-07 13:44:05 +00:00
p - > sizer_params - > Add ( p - > object_list - > get_sizer ( ) , 1 , wxEXPAND ) ;
2019-08-06 16:16:02 +00:00
2018-11-09 17:39:07 +00:00
// Object Manipulations
2018-10-04 14:43:10 +00:00
p - > object_manipulation = new ObjectManipulation ( p - > scrolled ) ;
2018-11-09 17:39:07 +00:00
p - > object_manipulation - > Hide ( ) ;
2019-02-07 13:44:05 +00:00
p - > sizer_params - > Add ( p - > object_manipulation - > get_sizer ( ) , 0 , wxEXPAND | wxTOP , margin_5 ) ;
2018-09-17 10:15:11 +00:00
2018-11-09 17:39:07 +00:00
// Frequently Object Settings
p - > object_settings = new ObjectSettings ( p - > scrolled ) ;
p - > object_settings - > Hide ( ) ;
2019-02-07 13:44:05 +00:00
p - > sizer_params - > Add ( p - > object_settings - > get_sizer ( ) , 0 , wxEXPAND | wxTOP , margin_5 ) ;
2019-08-06 16:16:02 +00:00
2019-05-28 14:38:04 +00:00
// Object Layers
p - > object_layers = new ObjectLayers ( p - > scrolled ) ;
p - > object_layers - > Hide ( ) ;
p - > sizer_params - > Add ( p - > object_layers - > get_sizer ( ) , 0 , wxEXPAND | wxTOP , margin_5 ) ;
2018-11-09 17:39:07 +00:00
2018-09-17 10:15:11 +00:00
// Info boxes
2018-10-01 13:09:31 +00:00
p - > object_info = new ObjectInfo ( p - > scrolled ) ;
p - > sliced_info = new SlicedInfo ( p - > scrolled ) ;
2018-09-17 10:15:11 +00:00
// Sizer in the scrolled area
2019-02-07 13:44:05 +00:00
scrolled_sizer - > Add ( p - > mode_sizer , 0 , wxALIGN_CENTER_HORIZONTAL /*RIGHT | wxBOTTOM | wxRIGHT, 5*/ ) ;
2019-03-13 12:13:18 +00:00
is_msw ?
2019-08-06 16:16:02 +00:00
scrolled_sizer - > Add ( p - > presets_panel , 0 , wxEXPAND | wxLEFT , margin_5 ) :
2019-03-13 12:13:18 +00:00
scrolled_sizer - > Add ( p - > sizer_presets , 0 , wxEXPAND | wxLEFT , margin_5 ) ;
2019-02-07 13:44:05 +00:00
scrolled_sizer - > Add ( p - > sizer_params , 1 , wxEXPAND | wxLEFT , margin_5 ) ;
scrolled_sizer - > Add ( p - > object_info , 0 , wxEXPAND | wxTOP | wxLEFT , margin_5 ) ;
scrolled_sizer - > Add ( p - > sliced_info , 0 , wxEXPAND | wxTOP | wxLEFT , margin_5 ) ;
2018-09-17 10:15:11 +00:00
// Buttons underneath the scrolled area
2019-04-13 21:46:52 +00:00
2019-12-13 12:23:55 +00:00
// rescalable bitmap buttons "Send to printer" and "Remove device"
2019-12-10 16:31:27 +00:00
2019-12-13 12:23:55 +00:00
auto init_scalable_btn = [ this ] ( ScalableButton * * btn , const std : : string & icon_name , wxString tooltip = wxEmptyString )
{
2019-12-13 16:56:04 +00:00
# ifdef __APPLE__
int bmp_px_cnt = 16 ;
# else
int bmp_px_cnt = 32 ;
# endif //__APPLE__
ScalableBitmap bmp = ScalableBitmap ( this , icon_name , bmp_px_cnt ) ;
2019-12-13 12:23:55 +00:00
* btn = new ScalableButton ( this , wxID_ANY , bmp , " " , wxBU_EXACTFIT ) ;
( * btn ) - > SetToolTip ( tooltip ) ;
( * btn ) - > Hide ( ) ;
2019-04-13 21:46:52 +00:00
} ;
2020-04-01 07:48:56 +00:00
init_scalable_btn ( & p - > btn_send_gcode , " export_gcode " , _L ( " Send to printer " ) + " \t Ctrl+Shift+G " ) ;
init_scalable_btn ( & p - > btn_remove_device , " eject_sd " , _L ( " Remove device " ) + " \t Ctrl+T " ) ;
init_scalable_btn ( & p - > btn_export_gcode_removable , " export_to_sd " , _L ( " Export to SD card / Flash drive " ) + " \t Ctrl+U " ) ;
2019-12-13 12:23:55 +00:00
// regular buttons "Slice now" and "Export G-code"
2019-12-10 16:31:27 +00:00
2019-12-13 16:56:04 +00:00
const int scaled_height = p - > btn_remove_device - > GetBitmapHeight ( ) + 4 ;
2019-12-13 12:23:55 +00:00
auto init_btn = [ this ] ( wxButton * * btn , wxString label , const int button_height ) {
2019-08-06 16:16:02 +00:00
* btn = new wxButton ( this , wxID_ANY , label , wxDefaultPosition ,
2019-12-13 12:23:55 +00:00
wxSize ( - 1 , button_height ) , wxBU_EXACTFIT ) ;
2019-04-13 21:46:52 +00:00
( * btn ) - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
} ;
2020-04-01 07:48:56 +00:00
init_btn ( & p - > btn_export_gcode , _L ( " Export G-code " ) + dots , scaled_height ) ;
init_btn ( & p - > btn_reslice , _L ( " Slice now " ) , scaled_height ) ;
2019-12-10 16:31:27 +00:00
2018-12-04 09:28:05 +00:00
enable_buttons ( false ) ;
2018-09-17 10:15:11 +00:00
auto * btns_sizer = new wxBoxSizer ( wxVERTICAL ) ;
2019-12-10 16:31:27 +00:00
auto * complect_btns_sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
complect_btns_sizer - > Add ( p - > btn_export_gcode , 1 , wxEXPAND ) ;
2019-12-13 16:56:04 +00:00
complect_btns_sizer - > Add ( p - > btn_send_gcode ) ;
2020-01-02 15:30:28 +00:00
complect_btns_sizer - > Add ( p - > btn_export_gcode_removable ) ;
2019-12-13 12:23:55 +00:00
complect_btns_sizer - > Add ( p - > btn_remove_device ) ;
2020-01-10 15:25:32 +00:00
2019-12-10 16:31:27 +00:00
2019-02-07 13:44:05 +00:00
btns_sizer - > Add ( p - > btn_reslice , 0 , wxEXPAND | wxTOP , margin_5 ) ;
2019-12-10 16:31:27 +00:00
btns_sizer - > Add ( complect_btns_sizer , 0 , wxEXPAND | wxTOP , margin_5 ) ;
2018-09-17 10:15:11 +00:00
auto * sizer = new wxBoxSizer ( wxVERTICAL ) ;
2019-02-11 14:36:05 +00:00
sizer - > Add ( p - > scrolled , 1 , wxEXPAND ) ;
2019-02-07 13:44:05 +00:00
sizer - > Add ( btns_sizer , 0 , wxEXPAND | wxLEFT , margin_5 ) ;
2018-09-17 10:15:11 +00:00
SetSizer ( sizer ) ;
2018-10-04 09:12:55 +00:00
// Events
2020-01-10 15:25:32 +00:00
p - > btn_export_gcode - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > export_gcode ( false ) ; } ) ;
2019-03-01 11:03:14 +00:00
p - > btn_reslice - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & )
{
const bool export_gcode_after_slicing = wxGetKeyState ( WXK_SHIFT ) ;
if ( export_gcode_after_slicing )
p - > plater - > export_gcode ( ) ;
2019-03-12 08:41:57 +00:00
else
p - > plater - > reslice ( ) ;
2019-08-06 16:16:02 +00:00
p - > plater - > select_view_3D ( " Preview " ) ;
2019-03-01 11:03:14 +00:00
} ) ;
2018-10-04 09:12:55 +00:00
p - > btn_send_gcode - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > send_gcode ( ) ; } ) ;
2019-12-13 12:23:55 +00:00
p - > btn_remove_device - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > eject_drive ( ) ; } ) ;
2020-01-10 15:25:32 +00:00
p - > btn_export_gcode_removable - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > export_gcode ( true ) ; } ) ;
2018-09-17 10:15:11 +00:00
}
Sidebar : : ~ Sidebar ( ) { }
2020-06-16 10:57:49 +00:00
void Sidebar : : init_filament_combo ( PlaterPresetComboBox * * combo , const int extr_idx ) {
* combo = new PlaterPresetComboBox ( p - > presets_panel , Slic3r : : Preset : : TYPE_FILAMENT ) ;
2018-10-10 11:53:45 +00:00
// # copy icons from first choice
// $choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets;
( * combo ) - > set_extruder_idx ( extr_idx ) ;
2019-03-18 14:10:40 +00:00
auto combo_and_btn_sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
combo_and_btn_sizer - > Add ( * combo , 1 , wxEXPAND ) ;
2019-05-17 14:05:32 +00:00
combo_and_btn_sizer - > Add ( ( * combo ) - > edit_btn , 0 , wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT ,
2019-05-17 13:49:37 +00:00
int ( 0.3 * wxGetApp ( ) . em_unit ( ) ) ) ;
2019-03-18 14:10:40 +00:00
2018-10-10 11:53:45 +00:00
auto /***/ sizer_filaments = this - > p - > sizer_filaments ;
2019-03-18 14:10:40 +00:00
sizer_filaments - > Add ( combo_and_btn_sizer , 1 , wxEXPAND | wxBOTTOM , 1 ) ;
2018-10-10 11:53:45 +00:00
}
2019-09-06 15:46:55 +00:00
void Sidebar : : remove_unused_filament_combos ( const size_t current_extruder_count )
2018-10-10 11:53:45 +00:00
{
if ( current_extruder_count > = p - > combos_filament . size ( ) )
return ;
auto sizer_filaments = this - > p - > sizer_filaments ;
while ( p - > combos_filament . size ( ) > current_extruder_count ) {
const int last = p - > combos_filament . size ( ) - 1 ;
sizer_filaments - > Remove ( last ) ;
( * p - > combos_filament [ last ] ) . Destroy ( ) ;
p - > combos_filament . pop_back ( ) ;
}
}
2019-04-10 07:56:32 +00:00
void Sidebar : : update_all_preset_comboboxes ( )
{
PresetBundle & preset_bundle = * wxGetApp ( ) . preset_bundle ;
const auto print_tech = preset_bundle . printers . get_edited_preset ( ) . printer_technology ( ) ;
// Update the print choosers to only contain the compatible presets, update the dirty flags.
if ( print_tech = = ptFFF )
2020-06-16 10:57:49 +00:00
p - > combo_print - > update ( ) ;
2019-04-10 07:56:32 +00:00
else {
2020-06-16 10:57:49 +00:00
p - > combo_sla_print - > update ( ) ;
p - > combo_sla_material - > update ( ) ;
2019-04-10 07:56:32 +00:00
}
// Update the printer choosers, update the dirty flags.
2020-06-16 10:57:49 +00:00
p - > combo_printer - > update ( ) ;
2019-04-10 07:56:32 +00:00
// Update the filament choosers to only contain the compatible presets, update the color preview,
// update the dirty flags.
if ( print_tech = = ptFFF ) {
2020-06-16 10:57:49 +00:00
for ( PlaterPresetComboBox * cb : p - > combos_filament )
cb - > update ( ) ;
2019-04-10 07:56:32 +00:00
}
}
2018-09-17 10:15:11 +00:00
void Sidebar : : update_presets ( Preset : : Type preset_type )
{
2019-08-06 16:16:02 +00:00
PresetBundle & preset_bundle = * wxGetApp ( ) . preset_bundle ;
2019-02-22 08:38:56 +00:00
const auto print_tech = preset_bundle . printers . get_edited_preset ( ) . printer_technology ( ) ;
2018-10-31 15:22:36 +00:00
2018-09-17 10:15:11 +00:00
switch ( preset_type ) {
2019-08-06 16:16:02 +00:00
case Preset : : TYPE_FILAMENT :
2019-01-15 14:54:20 +00:00
{
2019-09-06 15:46:55 +00:00
const size_t extruder_cnt = print_tech ! = ptFFF ? 1 :
2019-01-15 14:54:20 +00:00
dynamic_cast < ConfigOptionFloats * > ( preset_bundle . printers . get_edited_preset ( ) . config . option ( " nozzle_diameter " ) ) - > values . size ( ) ;
2019-09-06 15:46:55 +00:00
const size_t filament_cnt = p - > combos_filament . size ( ) > extruder_cnt ? extruder_cnt : p - > combos_filament . size ( ) ;
2019-01-15 14:54:20 +00:00
if ( filament_cnt = = 1 ) {
2018-09-17 10:15:11 +00:00
// Single filament printer, synchronize the filament presets.
2019-05-22 09:31:36 +00:00
const std : : string & name = preset_bundle . filaments . get_selected_preset_name ( ) ;
2019-01-15 14:54:20 +00:00
preset_bundle . set_filament_preset ( 0 , name ) ;
2018-09-17 10:15:11 +00:00
}
2020-06-16 10:57:49 +00:00
for ( size_t i = 0 ; i < filament_cnt ; i + + )
p - > combos_filament [ i ] - > update ( ) ;
2018-10-03 14:27:02 +00:00
2018-09-17 10:15:11 +00:00
break ;
2019-01-15 14:54:20 +00:00
}
2018-09-17 10:15:11 +00:00
case Preset : : TYPE_PRINT :
2020-06-16 10:57:49 +00:00
p - > combo_print - > update ( ) ;
2018-09-17 10:15:11 +00:00
break ;
2018-11-16 16:36:23 +00:00
case Preset : : TYPE_SLA_PRINT :
2020-06-16 10:57:49 +00:00
p - > combo_sla_print - > update ( ) ;
2018-11-16 16:36:23 +00:00
break ;
2018-09-17 10:15:11 +00:00
case Preset : : TYPE_SLA_MATERIAL :
2020-06-16 10:57:49 +00:00
p - > combo_sla_material - > update ( ) ;
2018-09-17 10:15:11 +00:00
break ;
2019-08-06 16:16:02 +00:00
case Preset : : TYPE_PRINTER :
{
2019-04-10 07:56:32 +00:00
update_all_preset_comboboxes ( ) ;
2019-08-06 16:16:02 +00:00
p - > show_preset_comboboxes ( ) ;
break ;
}
2018-09-17 10:15:11 +00:00
default : break ;
}
// Synchronize config.ini with the current selections.
2018-10-03 14:27:02 +00:00
wxGetApp ( ) . preset_bundle - > export_selections ( * wxGetApp ( ) . app_config ) ;
2018-09-17 10:15:11 +00:00
}
2019-03-01 11:03:14 +00:00
void Sidebar : : update_mode_sizer ( ) const
2019-01-10 10:05:58 +00:00
{
2019-03-01 11:03:14 +00:00
p - > mode_sizer - > SetMode ( m_mode ) ;
}
void Sidebar : : update_reslice_btn_tooltip ( ) const
2019-01-10 10:05:58 +00:00
{
2019-03-26 13:00:53 +00:00
wxString tooltip = wxString ( " Slice " ) + " [ " + GUI : : shortkey_ctrl_prefix ( ) + " R] " ;
if ( m_mode ! = comSimple )
2020-04-01 07:48:56 +00:00
tooltip + = wxString ( " \n " ) + _L ( " Hold Shift to Slice & Export G-code " ) ;
2019-03-01 11:03:14 +00:00
p - > btn_reslice - > SetToolTip ( tooltip ) ;
2019-01-10 10:05:58 +00:00
}
2019-08-06 16:16:02 +00:00
void Sidebar : : msw_rescale ( )
2019-04-13 21:46:52 +00:00
{
SetMinSize ( wxSize ( 40 * wxGetApp ( ) . em_unit ( ) , - 1 ) ) ;
2019-04-24 23:45:00 +00:00
p - > mode_sizer - > msw_rescale ( ) ;
2019-04-13 21:46:52 +00:00
2020-06-16 10:57:49 +00:00
for ( PlaterPresetComboBox * combo : std : : vector < PlaterPresetComboBox * > { p - > combo_print ,
2019-04-13 21:46:52 +00:00
p - > combo_sla_print ,
p - > combo_sla_material ,
p - > combo_printer } )
2019-04-24 23:45:00 +00:00
combo - > msw_rescale ( ) ;
2020-06-16 10:57:49 +00:00
for ( PlaterPresetComboBox * combo : p - > combos_filament )
2019-04-24 23:45:00 +00:00
combo - > msw_rescale ( ) ;
2019-04-13 21:46:52 +00:00
2019-07-10 15:50:24 +00:00
p - > frequently_changed_parameters - > msw_rescale ( ) ;
2019-04-24 23:45:00 +00:00
p - > object_list - > msw_rescale ( ) ;
2019-04-29 13:27:59 +00:00
p - > object_manipulation - > msw_rescale ( ) ;
2019-04-24 23:45:00 +00:00
p - > object_settings - > msw_rescale ( ) ;
2019-05-28 14:38:04 +00:00
p - > object_layers - > msw_rescale ( ) ;
2019-04-13 21:46:52 +00:00
2019-04-24 23:45:00 +00:00
p - > object_info - > msw_rescale ( ) ;
2019-04-13 21:46:52 +00:00
2019-12-13 12:23:55 +00:00
p - > btn_send_gcode - > msw_rescale ( ) ;
p - > btn_remove_device - > msw_rescale ( ) ;
2020-01-02 15:30:28 +00:00
p - > btn_export_gcode_removable - > msw_rescale ( ) ;
2019-12-13 12:23:55 +00:00
const int scaled_height = p - > btn_remove_device - > GetBitmap ( ) . GetHeight ( ) + 4 ;
p - > btn_export_gcode - > SetMinSize ( wxSize ( - 1 , scaled_height ) ) ;
p - > btn_reslice - > SetMinSize ( wxSize ( - 1 , scaled_height ) ) ;
2019-04-13 21:46:52 +00:00
p - > scrolled - > Layout ( ) ;
}
2020-05-21 15:29:00 +00:00
void Sidebar : : sys_color_changed ( )
{
// Update preset comboboxes in respect to the system color ...
// combo->msw_rescale() updates icon on button, so use it
2020-06-16 10:57:49 +00:00
for ( PlaterPresetComboBox * combo : std : : vector < PlaterPresetComboBox * > { p - > combo_print ,
2020-05-21 15:29:00 +00:00
p - > combo_sla_print ,
p - > combo_sla_material ,
p - > combo_printer } )
combo - > msw_rescale ( ) ;
2020-06-16 10:57:49 +00:00
for ( PlaterPresetComboBox * combo : p - > combos_filament )
2020-05-21 15:29:00 +00:00
combo - > msw_rescale ( ) ;
// ... then refill them and set min size to correct layout of the sidebar
update_all_preset_comboboxes ( ) ;
p - > object_list - > sys_color_changed ( ) ;
p - > object_manipulation - > sys_color_changed ( ) ;
// p->object_settings->msw_rescale();
2020-05-22 13:23:05 +00:00
p - > object_layers - > sys_color_changed ( ) ;
2020-05-21 15:29:00 +00:00
// btn...->msw_rescale() updates icon on button, so use it
p - > btn_send_gcode - > msw_rescale ( ) ;
p - > btn_remove_device - > msw_rescale ( ) ;
p - > btn_export_gcode_removable - > msw_rescale ( ) ;
p - > scrolled - > Layout ( ) ;
}
2020-04-24 09:01:14 +00:00
void Sidebar : : search ( )
2020-03-28 18:39:24 +00:00
{
2020-04-24 09:01:14 +00:00
p - > searcher . search ( ) ;
2020-03-28 18:39:24 +00:00
}
void Sidebar : : jump_to_option ( size_t selected )
{
2020-04-13 15:55:38 +00:00
const Search : : Option & opt = p - > searcher . get_option ( selected ) ;
2020-05-01 06:57:24 +00:00
wxGetApp ( ) . get_tab ( opt . type ) - > activate_option ( boost : : nowide : : narrow ( opt . opt_key ) , boost : : nowide : : narrow ( opt . category ) ) ;
2020-04-23 10:41:38 +00:00
2020-05-04 20:30:38 +00:00
// Switch to the Settings NotePad
wxGetApp ( ) . mainframe - > select_tab ( ) ;
2020-03-28 18:39:24 +00:00
}
2018-10-04 14:43:10 +00:00
ObjectManipulation * Sidebar : : obj_manipul ( )
{
return p - > object_manipulation ;
}
2018-10-05 21:29:15 +00:00
ObjectList * Sidebar : : obj_list ( )
2018-10-03 13:14:52 +00:00
{
2018-10-05 21:29:15 +00:00
return p - > object_list ;
2018-10-03 13:14:52 +00:00
}
2018-11-09 17:39:07 +00:00
ObjectSettings * Sidebar : : obj_settings ( )
{
return p - > object_settings ;
}
2019-05-28 14:38:04 +00:00
ObjectLayers * Sidebar : : obj_layers ( )
{
return p - > object_layers ;
}
2018-11-09 17:39:07 +00:00
wxScrolledWindow * Sidebar : : scrolled_panel ( )
{
return p - > scrolled ;
}
2019-03-13 12:13:18 +00:00
wxPanel * Sidebar : : presets_panel ( )
{
return p - > presets_panel ;
}
2019-01-15 08:31:53 +00:00
ConfigOptionsGroup * Sidebar : : og_freq_chng_params ( const bool is_fff )
2018-10-05 21:29:15 +00:00
{
2019-01-15 08:31:53 +00:00
return p - > frequently_changed_parameters - > get_og ( is_fff ) ;
2018-10-03 13:14:52 +00:00
}
wxButton * Sidebar : : get_wiping_dialog_button ( )
{
2018-10-04 14:43:10 +00:00
return p - > frequently_changed_parameters - > get_wiping_dialog_button ( ) ;
}
2019-09-06 15:46:55 +00:00
void Sidebar : : update_objects_list_extruder_column ( size_t extruders_count )
2018-10-04 14:43:10 +00:00
{
p - > object_list - > update_objects_list_extruder_column ( extruders_count ) ;
}
2018-11-13 11:19:56 +00:00
void Sidebar : : show_info_sizer ( )
2018-10-05 21:29:15 +00:00
{
2018-11-13 11:19:56 +00:00
if ( ! p - > plater - > is_single_full_object_selection ( ) | |
2019-01-10 10:05:58 +00:00
m_mode < comExpert | |
2018-11-14 15:24:36 +00:00
p - > plater - > model ( ) . objects . empty ( ) ) {
2018-11-01 11:33:56 +00:00
p - > object_info - > Show ( false ) ;
return ;
}
2018-11-09 17:39:07 +00:00
int obj_idx = p - > plater - > get_selected_object_idx ( ) ;
2018-11-14 15:24:36 +00:00
const ModelObject * model_object = p - > plater - > model ( ) . objects [ obj_idx ] ;
2018-11-13 14:24:05 +00:00
// hack to avoid crash when deleting the last object on the bed
if ( model_object - > volumes . empty ( ) )
{
p - > object_info - > Show ( false ) ;
return ;
}
2020-04-29 17:10:13 +00:00
bool imperial_units = wxGetApp ( ) . app_config - > get ( " use_inches " ) = = " 1 " ;
double koef = imperial_units ? ObjectManipulation : : mm_to_in : 1.0f ;
2018-11-15 10:15:24 +00:00
auto size = model_object - > bounding_box ( ) . size ( ) ;
2020-04-29 17:10:13 +00:00
p - > object_info - > info_size - > SetLabel ( wxString : : Format ( " %.2f x %.2f x %.2f " , size ( 0 ) * koef , size ( 1 ) * koef , size ( 2 ) * koef ) ) ;
2018-11-01 11:33:56 +00:00
p - > object_info - > info_materials - > SetLabel ( wxString : : Format ( " %d " , static_cast < int > ( model_object - > materials_count ( ) ) ) ) ;
2019-04-24 14:04:47 +00:00
const auto & stats = model_object - > get_object_stl_stats ( ) ; //model_object->volumes.front()->mesh.stl.stats;
2020-04-29 17:10:13 +00:00
p - > object_info - > info_volume - > SetLabel ( wxString : : Format ( " %.2f " , stats . volume * pow ( koef , 3 ) ) ) ;
2020-04-01 07:48:56 +00:00
p - > object_info - > info_facets - > SetLabel ( wxString : : Format ( _L ( " %d (%d shells) " ) , static_cast < int > ( model_object - > facets_count ( ) ) , stats . number_of_parts ) ) ;
2018-11-01 11:33:56 +00:00
int errors = stats . degenerate_facets + stats . edges_fixed + stats . facets_removed +
stats . facets_added + stats . facets_reversed + stats . backwards_edges ;
if ( errors > 0 ) {
2020-04-01 07:48:56 +00:00
wxString tooltip = wxString : : Format ( _L ( " Auto-repaired (%d errors) " ) , errors ) ;
2018-11-01 11:33:56 +00:00
p - > object_info - > info_manifold - > SetLabel ( tooltip ) ;
2019-08-06 16:16:02 +00:00
2020-04-01 07:48:56 +00:00
tooltip + = " : \n " + wxString : : Format ( _L ( " %d degenerate facets, %d edges fixed, %d facets removed, "
" %d facets added, %d facets reversed, %d backwards edges " ) ,
2018-11-01 11:33:56 +00:00
stats . degenerate_facets , stats . edges_fixed , stats . facets_removed ,
stats . facets_added , stats . facets_reversed , stats . backwards_edges ) ;
p - > object_info - > showing_manifold_warning_icon = true ;
p - > object_info - > info_manifold - > SetToolTip ( tooltip ) ;
p - > object_info - > manifold_warning_icon - > SetToolTip ( tooltip ) ;
2019-08-06 16:16:02 +00:00
}
2018-11-01 11:33:56 +00:00
else {
2020-04-01 07:48:56 +00:00
p - > object_info - > info_manifold - > SetLabel ( _L ( " Yes " ) ) ;
2018-11-01 11:33:56 +00:00
p - > object_info - > showing_manifold_warning_icon = false ;
p - > object_info - > info_manifold - > SetToolTip ( " " ) ;
p - > object_info - > manifold_warning_icon - > SetToolTip ( " " ) ;
}
p - > object_info - > show_sizer ( true ) ;
2019-02-19 11:14:13 +00:00
if ( p - > plater - > printer_technology ( ) = = ptSLA ) {
2019-02-21 14:46:04 +00:00
for ( auto item : p - > object_info - > sla_hidden_items )
2019-02-19 11:14:13 +00:00
item - > Show ( false ) ;
}
2018-10-31 11:26:57 +00:00
}
2019-09-26 14:33:55 +00:00
void Sidebar : : update_sliced_info_sizer ( )
2018-10-31 11:26:57 +00:00
{
2019-09-26 14:33:55 +00:00
if ( p - > sliced_info - > IsShown ( size_t ( 0 ) ) )
{
2019-02-12 15:34:42 +00:00
if ( p - > plater - > printer_technology ( ) = = ptSLA )
{
const SLAPrintStatistics & ps = p - > plater - > sla_print ( ) . print_statistics ( ) ;
2020-04-01 07:48:56 +00:00
wxString new_label = _L ( " Used Material (ml) " ) + " : " ;
2019-02-13 14:35:41 +00:00
const bool is_supports = ps . support_used_material > 0.0 ;
if ( is_supports )
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " \n - %s \n - %s " , _L ( " object(s) " ) , _L ( " supports and pad " ) ) ;
2019-02-13 14:35:41 +00:00
wxString info_text = is_supports ?
2019-02-18 11:28:58 +00:00
wxString : : Format ( " %.2f \n %.2f \n %.2f " , ( ps . objects_used_material + ps . support_used_material ) / 1000 ,
ps . objects_used_material / 1000 ,
ps . support_used_material / 1000 ) :
2019-02-18 12:18:47 +00:00
wxString : : Format ( " %.2f " , ( ps . objects_used_material + ps . support_used_material ) / 1000 ) ;
2019-02-13 14:35:41 +00:00
p - > sliced_info - > SetTextAndShow ( siMateril_unit , info_text , new_label ) ;
2019-09-26 14:33:55 +00:00
wxString str_total_cost = " N/A " ;
DynamicPrintConfig * cfg = wxGetApp ( ) . get_tab ( Preset : : TYPE_SLA_MATERIAL ) - > get_config ( ) ;
if ( cfg - > option ( " bottle_cost " ) - > getFloat ( ) > 0.0 & &
cfg - > option ( " bottle_volume " ) - > getFloat ( ) > 0.0 )
{
double material_cost = cfg - > option ( " bottle_cost " ) - > getFloat ( ) /
cfg - > option ( " bottle_volume " ) - > getFloat ( ) ;
2020-01-08 14:23:46 +00:00
str_total_cost = wxString : : Format ( " %.3f " , material_cost * ( ps . objects_used_material + ps . support_used_material ) / 1000 ) ;
2019-09-26 14:33:55 +00:00
}
2020-01-08 14:23:46 +00:00
p - > sliced_info - > SetTextAndShow ( siCost , str_total_cost , " Cost " ) ;
2019-09-26 14:33:55 +00:00
2019-09-11 10:13:59 +00:00
wxString t_est = std : : isnan ( ps . estimated_print_time ) ? " N/A " : get_time_dhms ( float ( ps . estimated_print_time ) ) ;
2020-04-01 07:48:56 +00:00
p - > sliced_info - > SetTextAndShow ( siEstimatedTime , t_est , _L ( " Estimated printing time " ) + " : " ) ;
2019-02-12 15:34:42 +00:00
// Hide non-SLA sliced info parameters
p - > sliced_info - > SetTextAndShow ( siFilament_m , " N/A " ) ;
p - > sliced_info - > SetTextAndShow ( siFilament_mm3 , " N/A " ) ;
p - > sliced_info - > SetTextAndShow ( siFilament_g , " N/A " ) ;
p - > sliced_info - > SetTextAndShow ( siWTNumbetOfToolchanges , " N/A " ) ;
}
else
2019-08-06 16:16:02 +00:00
{
2019-02-21 14:46:04 +00:00
const PrintStatistics & ps = p - > plater - > fff_print ( ) . print_statistics ( ) ;
const bool is_wipe_tower = ps . total_wipe_tower_filament > 0 ;
2020-04-29 17:10:13 +00:00
bool imperial_units = wxGetApp ( ) . app_config - > get ( " use_inches " ) = = " 1 " ;
double koef = imperial_units ? ObjectManipulation : : in_to_mm : 1000.0 ;
wxString new_label = imperial_units ? _L ( " Used Filament (in) " ) : _L ( " Used Filament (m) " ) ;
2019-02-21 14:46:04 +00:00
if ( is_wipe_tower )
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " : \n - %1% \n - %2% " , _L ( " objects " ) , _L ( " wipe tower " ) ) ;
2019-02-21 14:46:04 +00:00
wxString info_text = is_wipe_tower ?
2020-04-29 17:10:13 +00:00
wxString : : Format ( " %.2f \n %.2f \n %.2f " , ps . total_used_filament / /*1000*/ koef ,
( ps . total_used_filament - ps . total_wipe_tower_filament ) / /*1000*/ koef ,
ps . total_wipe_tower_filament / /*1000*/ koef ) :
wxString : : Format ( " %.2f " , ps . total_used_filament / /*1000*/ koef ) ;
2019-02-21 14:46:04 +00:00
p - > sliced_info - > SetTextAndShow ( siFilament_m , info_text , new_label ) ;
2020-04-29 17:10:13 +00:00
koef = imperial_units ? pow ( ObjectManipulation : : mm_to_in , 3 ) : 1.0f ;
new_label = imperial_units ? _L ( " Used Filament (in³) " ) : _L ( " Used Filament (mm³) " ) ;
info_text = wxString : : Format ( " %.2f " , imperial_units ? ps . total_extruded_volume * koef : ps . total_extruded_volume ) ;
p - > sliced_info - > SetTextAndShow ( siFilament_mm3 , info_text , new_label ) ;
2020-02-17 10:51:22 +00:00
p - > sliced_info - > SetTextAndShow ( siFilament_g , ps . total_weight = = 0.0 ? " N/A " : wxString : : Format ( " %.2f " , ps . total_weight ) ) ;
2019-02-21 14:46:04 +00:00
2020-04-01 07:48:56 +00:00
new_label = _L ( " Cost " ) ;
2019-02-21 14:46:04 +00:00
if ( is_wipe_tower )
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " : \n - %1% \n - %2% " , _L ( " objects " ) , _L ( " wipe tower " ) ) ;
2019-08-06 16:16:02 +00:00
2020-02-17 10:51:22 +00:00
info_text = ps . total_cost = = 0.0 ? " N/A " :
is_wipe_tower ?
2019-02-21 14:46:04 +00:00
wxString : : Format ( " %.2f \n %.2f \n %.2f " , ps . total_cost ,
2019-08-06 16:16:02 +00:00
( ps . total_cost - ps . total_wipe_tower_cost ) ,
2019-02-21 14:46:04 +00:00
ps . total_wipe_tower_cost ) :
wxString : : Format ( " %.2f " , ps . total_cost ) ;
2020-02-17 10:51:22 +00:00
p - > sliced_info - > SetTextAndShow ( siCost , info_text , new_label ) ;
2019-02-21 14:46:04 +00:00
if ( ps . estimated_normal_print_time = = " N/A " & & ps . estimated_silent_print_time = = " N/A " )
p - > sliced_info - > SetTextAndShow ( siEstimatedTime , " N/A " ) ;
else {
2020-04-01 07:48:56 +00:00
new_label = _L ( " Estimated printing time " ) + " : " ;
2019-02-21 14:46:04 +00:00
info_text = " " ;
2020-04-01 07:48:56 +00:00
wxString str_color = _L ( " Color " ) ;
wxString str_pause = _L ( " Pause " ) ;
2020-02-20 16:32:46 +00:00
2020-06-03 08:42:47 +00:00
auto fill_labels = [ str_color , str_pause ] ( const std : : vector < std : : pair < CustomGCode : : Type , std : : string > > & times ,
2020-02-20 16:32:46 +00:00
wxString & new_label , wxString & info_text )
{
int color_change_count = 0 ;
for ( auto time : times )
2020-06-03 08:42:47 +00:00
if ( time . first = = CustomGCode : : ColorChange )
2020-02-20 16:32:46 +00:00
color_change_count + + ;
for ( int i = ( int ) times . size ( ) - 1 ; i > = 0 ; - - i )
2019-07-08 06:40:20 +00:00
{
2020-06-03 08:42:47 +00:00
if ( i = = 0 | | times [ i - 1 ] . first = = CustomGCode : : PausePrint )
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " \n - %1%%2% " , str_color + " " , color_change_count ) ;
2020-06-03 08:42:47 +00:00
else if ( times [ i - 1 ] . first = = CustomGCode : : ColorChange )
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " \n - %1%%2% " , str_color + " " , color_change_count - - ) ;
2020-02-20 16:32:46 +00:00
2020-06-03 08:42:47 +00:00
if ( i ! = ( int ) times . size ( ) - 1 & & times [ i ] . first = = CustomGCode : : PausePrint )
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " -> %1% " , str_pause ) ;
2020-02-20 16:32:46 +00:00
2020-04-01 07:48:56 +00:00
info_text + = format_wxstr ( " \n %1% " , times [ i ] . second ) ;
2019-07-08 06:40:20 +00:00
}
2020-02-20 16:32:46 +00:00
} ;
if ( ps . estimated_normal_print_time ! = " N/A " ) {
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " \n - %1% " , _L ( " normal mode " ) ) ;
info_text + = format_wxstr ( " \n %1% " , ps . estimated_normal_print_time ) ;
2020-02-20 16:32:46 +00:00
fill_labels ( ps . estimated_normal_custom_gcode_print_times , new_label , info_text ) ;
2019-02-21 14:46:04 +00:00
}
if ( ps . estimated_silent_print_time ! = " N/A " ) {
2020-04-01 07:48:56 +00:00
new_label + = format_wxstr ( " \n - %1% " , _L ( " stealth mode " ) ) ;
info_text + = format_wxstr ( " \n %1% " , ps . estimated_silent_print_time ) ;
2020-02-20 16:32:46 +00:00
fill_labels ( ps . estimated_silent_custom_gcode_print_times , new_label , info_text ) ;
2019-02-21 14:46:04 +00:00
}
p - > sliced_info - > SetTextAndShow ( siEstimatedTime , info_text , new_label ) ;
2018-11-20 09:33:54 +00:00
}
2018-10-31 11:26:57 +00:00
2019-02-21 14:46:04 +00:00
// if there is a wipe tower, insert number of toolchanges info into the array:
2019-11-05 10:37:40 +00:00
p - > sliced_info - > SetTextAndShow ( siWTNumbetOfToolchanges , is_wipe_tower ? wxString : : Format ( " %.d " , ps . total_toolchanges ) : " N/A " ) ;
2019-02-12 15:34:42 +00:00
2019-02-21 14:46:04 +00:00
// Hide non-FFF sliced info parameters
p - > sliced_info - > SetTextAndShow ( siMateril_unit , " N/A " ) ;
2019-08-06 16:16:02 +00:00
}
2018-10-31 11:26:57 +00:00
}
2019-09-26 14:33:55 +00:00
}
void Sidebar : : show_sliced_info_sizer ( const bool show )
{
wxWindowUpdateLocker freeze_guard ( this ) ;
p - > sliced_info - > Show ( show ) ;
if ( show )
update_sliced_info_sizer ( ) ;
2018-10-31 11:26:57 +00:00
2018-11-13 11:19:56 +00:00
Layout ( ) ;
2018-11-15 10:15:24 +00:00
p - > scrolled - > Refresh ( ) ;
2018-10-05 21:29:15 +00:00
}
2018-10-08 17:14:55 +00:00
void Sidebar : : enable_buttons ( bool enable )
{
p - > btn_reslice - > Enable ( enable ) ;
p - > btn_export_gcode - > Enable ( enable ) ;
p - > btn_send_gcode - > Enable ( enable ) ;
2019-12-13 12:23:55 +00:00
p - > btn_remove_device - > Enable ( enable ) ;
2020-01-02 15:30:28 +00:00
p - > btn_export_gcode_removable - > Enable ( enable ) ;
2018-10-08 17:14:55 +00:00
}
2020-01-02 15:30:28 +00:00
bool Sidebar : : show_reslice ( bool show ) const { return p - > btn_reslice - > Show ( show ) ; }
bool Sidebar : : show_export ( bool show ) const { return p - > btn_export_gcode - > Show ( show ) ; }
bool Sidebar : : show_send ( bool show ) const { return p - > btn_send_gcode - > Show ( show ) ; }
bool Sidebar : : show_disconnect ( bool show ) const { return p - > btn_remove_device - > Show ( show ) ; }
bool Sidebar : : show_export_removable ( bool show ) const { return p - > btn_export_gcode_removable - > Show ( show ) ; }
2018-10-15 08:53:47 +00:00
2018-10-09 10:41:05 +00:00
bool Sidebar : : is_multifilament ( )
{
2018-11-01 14:58:14 +00:00
return p - > combos_filament . size ( ) > 1 ;
2018-10-09 10:41:05 +00:00
}
2020-04-13 15:55:38 +00:00
static std : : vector < Search : : InputInfo > get_search_inputs ( ConfigOptionMode mode )
2020-03-13 21:37:18 +00:00
{
2020-04-13 15:55:38 +00:00
std : : vector < Search : : InputInfo > ret { } ;
2020-03-13 21:37:18 +00:00
auto & tabs_list = wxGetApp ( ) . tabs_list ;
auto print_tech = wxGetApp ( ) . preset_bundle - > printers . get_selected_preset ( ) . printer_technology ( ) ;
for ( auto tab : tabs_list )
if ( tab - > supports_printer_technology ( print_tech ) )
2020-04-13 15:55:38 +00:00
ret . emplace_back ( Search : : InputInfo { tab - > get_config ( ) , tab - > type ( ) , mode } ) ;
2020-03-13 21:37:18 +00:00
return ret ;
}
2020-04-13 15:55:38 +00:00
void Sidebar : : update_searcher ( )
2020-04-03 08:01:23 +00:00
{
2020-04-13 15:55:38 +00:00
p - > searcher . init ( get_search_inputs ( m_mode ) ) ;
2020-03-13 21:37:18 +00:00
}
2018-10-10 11:53:45 +00:00
2019-03-01 11:03:14 +00:00
void Sidebar : : update_mode ( )
{
m_mode = wxGetApp ( ) . get_mode ( ) ;
update_reslice_btn_tooltip ( ) ;
update_mode_sizer ( ) ;
2020-04-13 15:55:38 +00:00
update_searcher ( ) ;
2019-03-01 11:03:14 +00:00
wxWindowUpdateLocker noUpdates ( this ) ;
p - > object_list - > get_sizer ( ) - > Show ( m_mode > comSimple ) ;
p - > object_list - > unselect_objects ( ) ;
p - > object_list - > update_selections ( ) ;
p - > object_list - > update_object_menu ( ) ;
2019-08-06 16:16:02 +00:00
2019-03-01 11:03:14 +00:00
Layout ( ) ;
}
2020-03-16 11:49:39 +00:00
bool Sidebar : : is_collapsed ( ) { return p - > is_collapsed ; }
void Sidebar : : collapse ( bool collapse )
{
p - > is_collapsed = collapse ;
this - > Show ( ! collapse ) ;
p - > plater - > Layout ( ) ;
// save collapsing state to the AppConfig
wxGetApp ( ) . app_config - > set ( " collapsed_sidebar " , collapse ? " 1 " : " 0 " ) ;
}
2020-04-29 17:10:13 +00:00
void Sidebar : : update_ui_from_settings ( )
{
p - > object_manipulation - > update_ui_from_settings ( ) ;
show_info_sizer ( ) ;
update_sliced_info_sizer ( ) ;
}
2020-06-16 10:57:49 +00:00
std : : vector < PlaterPresetComboBox * > & Sidebar : : combos_filament ( )
2018-10-10 11:53:45 +00:00
{
return p - > combos_filament ;
}
2020-04-13 15:55:38 +00:00
Search : : OptionsSearcher & Sidebar : : get_searcher ( )
2020-03-28 18:39:24 +00:00
{
2020-04-13 15:55:38 +00:00
return p - > searcher ;
2020-03-28 18:39:24 +00:00
}
std : : string & Sidebar : : get_search_line ( )
{
2020-04-24 09:01:14 +00:00
return p - > searcher . search_string ( ) ;
2020-03-28 18:39:24 +00:00
}
2018-09-17 10:15:11 +00:00
// Plater::DropTarget
class PlaterDropTarget : public wxFileDropTarget
{
public :
2019-08-06 16:16:02 +00:00
PlaterDropTarget ( Plater * plater ) : plater ( plater ) { this - > SetDefaultAction ( wxDragCopy ) ; }
2018-09-17 10:15:11 +00:00
virtual bool OnDropFiles ( wxCoord x , wxCoord y , const wxArrayString & filenames ) ;
private :
Plater * plater ;
2018-10-08 17:14:55 +00:00
static const std : : regex pattern_drop ;
2018-09-17 10:15:11 +00:00
} ;
2018-10-22 09:52:13 +00:00
const std : : regex PlaterDropTarget : : pattern_drop ( " .*[.](stl|obj|amf|3mf|prusa) " , std : : regex : : icase ) ;
2018-10-08 17:14:55 +00:00
2018-09-17 10:15:11 +00:00
bool PlaterDropTarget : : OnDropFiles ( wxCoord x , wxCoord y , const wxArrayString & filenames )
{
2018-10-08 17:14:55 +00:00
std : : vector < fs : : path > paths ;
for ( const auto & filename : filenames ) {
2019-01-02 14:11:05 +00:00
fs : : path path ( into_path ( filename ) ) ;
2018-10-08 17:14:55 +00:00
if ( std : : regex_match ( path . string ( ) , pattern_drop ) ) {
paths . push_back ( std : : move ( path ) ) ;
} else {
return false ;
}
}
2019-08-06 16:16:02 +00:00
wxString snapshot_label ;
assert ( ! paths . empty ( ) ) ;
if ( paths . size ( ) = = 1 ) {
2020-04-01 07:48:56 +00:00
snapshot_label = _L ( " Load File " ) ;
2019-08-06 16:16:02 +00:00
snapshot_label + = " : " ;
snapshot_label + = wxString : : FromUTF8 ( paths . front ( ) . filename ( ) . string ( ) . c_str ( ) ) ;
} else {
2020-04-01 07:48:56 +00:00
snapshot_label = _L ( " Load Files " ) ;
2019-08-06 16:16:02 +00:00
snapshot_label + = " : " ;
snapshot_label + = wxString : : FromUTF8 ( paths . front ( ) . filename ( ) . string ( ) . c_str ( ) ) ;
for ( size_t i = 1 ; i < paths . size ( ) ; + + i ) {
snapshot_label + = " , " ;
snapshot_label + = wxString : : FromUTF8 ( paths [ i ] . filename ( ) . string ( ) . c_str ( ) ) ;
}
}
Plater : : TakeSnapshot snapshot ( plater , snapshot_label ) ;
2019-07-17 13:48:53 +00:00
2019-05-15 12:09:16 +00:00
// FIXME: when drag and drop is done on a .3mf or a .amf file we should clear the plater for consistence with the open project command
// (the following call to plater->load_files() will load the config data, if present)
2019-09-02 13:15:28 +00:00
std : : vector < size_t > res = plater - > load_files ( paths ) ;
2019-05-15 12:09:16 +00:00
// because right now the plater is not cleared, we set the project file (from the latest imported .3mf or .amf file)
// only if not set yet
2019-09-02 13:15:28 +00:00
// if res is empty no data has been loaded
if ( ! res . empty ( ) & & plater - > get_project_filename ( ) . empty ( ) )
2019-05-15 12:09:16 +00:00
{
for ( std : : vector < fs : : path > : : const_reverse_iterator it = paths . rbegin ( ) ; it ! = paths . rend ( ) ; + + it )
{
std : : string filename = ( * it ) . filename ( ) . string ( ) ;
if ( boost : : algorithm : : iends_with ( filename , " .3mf " ) | | boost : : algorithm : : iends_with ( filename , " .amf " ) )
{
plater - > set_project_filename ( from_path ( * it ) ) ;
break ;
}
}
}
2018-10-08 17:14:55 +00:00
return true ;
2018-09-17 10:15:11 +00:00
}
// Plater / private
struct Plater : : priv
{
// PIMPL back pointer ("Q-Pointer")
Plater * q ;
MainFrame * main_frame ;
2018-10-17 10:17:25 +00:00
// Object popup menu
2019-04-24 23:45:00 +00:00
MenuWithSeparators object_menu ;
2018-12-07 16:50:48 +00:00
// Part popup menu
2019-04-24 23:45:00 +00:00
MenuWithSeparators part_menu ;
2018-12-07 16:50:48 +00:00
// SLA-Object popup menu
2019-04-24 23:45:00 +00:00
MenuWithSeparators sla_object_menu ;
2019-09-20 07:57:27 +00:00
// Default popup menu (when nothing is selected on 3DScene)
MenuWithSeparators default_menu ;
2019-01-25 09:34:32 +00:00
2019-03-19 08:51:50 +00:00
// Removed/Prepended Items according to the view mode
std : : vector < wxMenuItem * > items_increase ;
std : : vector < wxMenuItem * > items_decrease ;
std : : vector < wxMenuItem * > items_set_number_of_copies ;
enum MenuIdentifier {
miObjectFFF = 0 ,
miObjectSLA
} ;
2018-09-17 10:15:11 +00:00
// Data
2018-12-05 14:22:03 +00:00
Slic3r : : DynamicPrintConfig * config ; // FIXME: leak?
2018-12-03 12:14:28 +00:00
Slic3r : : Print fff_print ;
2019-08-06 16:16:02 +00:00
Slic3r : : SLAPrint sla_print ;
2018-11-13 16:45:44 +00:00
Slic3r : : Model model ;
PrinterTechnology printer_technology = ptFFF ;
Slic3r : : GCodePreviewData gcode_preview_data ;
2019-07-26 11:44:33 +00:00
2018-09-17 10:15:11 +00:00
// GUI elements
2019-03-05 09:54:03 +00:00
wxSizer * panel_sizer { nullptr } ;
wxPanel * current_panel { nullptr } ;
2018-12-04 12:55:25 +00:00
std : : vector < wxPanel * > panels ;
2018-09-17 10:15:11 +00:00
Sidebar * sidebar ;
2019-02-19 14:15:27 +00:00
Bed3D bed ;
2019-03-06 14:46:19 +00:00
Camera camera ;
2020-05-28 13:27:29 +00:00
# if ENABLE_ENVIRONMENT_MAP
GLTexture environment_texture ;
# endif // ENABLE_ENVIRONMENT_MAP
2019-09-27 12:52:19 +00:00
Mouse3DController mouse3d_controller ;
2018-12-04 12:55:25 +00:00
View3D * view3D ;
2018-12-17 09:55:14 +00:00
GLToolbar view_toolbar ;
2020-06-05 10:33:09 +00:00
GLToolbar collapse_toolbar ;
2018-10-04 14:43:10 +00:00
Preview * preview ;
2018-11-15 14:27:39 +00:00
2018-10-17 09:12:38 +00:00
BackgroundSlicingProcess background_process ;
2019-06-26 07:48:52 +00:00
bool suppressed_backround_processing_update { false } ;
2019-08-06 16:16:02 +00:00
2019-06-18 14:24:30 +00:00
// Jobs defined inside the group class will be managed so that only one can
// run at a time. Also, the background process will be stopped if a job is
2020-04-23 16:47:51 +00:00
// started. It is up the the plater to ensure that the background slicing
// can't be restarted while a ui job is still running.
class Jobs : public ExclusiveJobGroup
{
priv * m ;
2020-04-23 17:45:55 +00:00
size_t m_arrange_id , m_rotoptimize_id , m_sla_import_id ;
2020-04-23 16:47:51 +00:00
void before_start ( ) override { m - > background_process . stop ( ) ; }
2019-05-13 16:58:56 +00:00
public :
2020-04-23 16:47:51 +00:00
Jobs ( priv * _m ) : m ( _m )
{
m_arrange_id = add_job ( std : : make_unique < ArrangeJob > ( m - > statusbar ( ) , m - > q ) ) ;
m_rotoptimize_id = add_job ( std : : make_unique < RotoptimizeJob > ( m - > statusbar ( ) , m - > q ) ) ;
2020-04-23 17:45:55 +00:00
m_sla_import_id = add_job ( std : : make_unique < SLAImportJob > ( m - > statusbar ( ) , m - > q ) ) ;
2019-06-18 14:24:30 +00:00
}
2020-04-23 16:47:51 +00:00
void arrange ( )
2019-06-18 14:24:30 +00:00
{
2020-04-23 16:47:51 +00:00
m - > take_snapshot ( _ ( L ( " Arrange " ) ) ) ;
start ( m_arrange_id ) ;
2019-06-18 14:24:30 +00:00
}
2020-04-23 16:47:51 +00:00
void optimize_rotation ( )
2019-06-18 14:24:30 +00:00
{
2020-04-23 16:47:51 +00:00
m - > take_snapshot ( _ ( L ( " Optimize Rotation " ) ) ) ;
start ( m_rotoptimize_id ) ;
2019-06-18 14:24:30 +00:00
}
2020-04-23 16:47:51 +00:00
2020-04-23 17:45:55 +00:00
void import_sla_arch ( )
{
m - > take_snapshot ( _ ( L ( " Import SLA archive " ) ) ) ;
start ( m_sla_import_id ) ;
}
2020-04-23 16:47:51 +00:00
} m_ui_jobs ;
2019-06-18 14:24:30 +00:00
2018-11-23 11:47:32 +00:00
bool delayed_scene_refresh ;
2019-02-19 13:57:59 +00:00
std : : string delayed_error_message ;
2018-11-08 15:01:21 +00:00
2018-10-17 09:12:38 +00:00
wxTimer background_process_timer ;
2018-09-17 10:15:11 +00:00
2019-03-01 10:00:34 +00:00
std : : string label_btn_export ;
2019-03-12 08:41:57 +00:00
std : : string label_btn_send ;
2019-03-01 10:00:34 +00:00
2018-09-17 10:15:11 +00:00
static const std : : regex pattern_bundle ;
static const std : : regex pattern_3mf ;
static const std : : regex pattern_zip_amf ;
2019-01-03 11:04:14 +00:00
static const std : : regex pattern_any_amf ;
2019-01-18 15:01:43 +00:00
static const std : : regex pattern_prusa ;
2018-09-17 10:15:11 +00:00
priv ( Plater * q , MainFrame * main_frame ) ;
2019-06-27 13:23:03 +00:00
~ priv ( ) ;
2018-09-17 10:15:11 +00:00
2020-04-23 16:47:51 +00:00
enum class UpdateParams {
FORCE_FULL_SCREEN_REFRESH = 1 ,
FORCE_BACKGROUND_PROCESSING_UPDATE = 2 ,
POSTPONE_VALIDATION_ERROR_MESSAGE = 4 ,
2019-08-23 13:53:45 +00:00
} ;
void update ( unsigned int flags = 0 ) ;
2018-10-17 10:59:58 +00:00
void select_view ( const std : : string & direction ) ;
2018-12-04 12:55:25 +00:00
void select_view_3D ( const std : : string & name ) ;
2018-12-21 09:43:22 +00:00
void select_next_view_3D ( ) ;
2019-08-20 07:01:09 +00:00
bool is_preview_shown ( ) const { return current_panel = = preview ; }
bool is_preview_loaded ( ) const { return preview - > is_loaded ( ) ; }
bool is_view3D_shown ( ) const { return current_panel = = view3D ; }
2020-02-04 13:42:26 +00:00
bool are_view3D_labels_shown ( ) const { return ( current_panel = = view3D ) & & view3D - > get_canvas3d ( ) - > are_labels_shown ( ) ; }
void show_view3D_labels ( bool show ) { if ( current_panel = = view3D ) view3D - > get_canvas3d ( ) - > show_labels ( show ) ; }
2020-03-16 11:49:39 +00:00
bool is_sidebar_collapsed ( ) const { return sidebar - > is_collapsed ( ) ; }
2020-04-29 13:58:57 +00:00
void collapse_sidebar ( bool show ) { sidebar - > collapse ( show ) ; }
2020-03-16 11:49:39 +00:00
2020-03-13 14:09:07 +00:00
# if ENABLE_SLOPE_RENDERING
bool is_view3D_slope_shown ( ) const { return ( current_panel = = view3D ) & & view3D - > get_canvas3d ( ) - > is_slope_shown ( ) ; }
void show_view3D_slope ( bool show ) { if ( current_panel = = view3D ) view3D - > get_canvas3d ( ) - > show_slope ( show ) ; }
bool is_view3D_layers_editing_enabled ( ) const { return ( current_panel = = view3D ) & & view3D - > get_canvas3d ( ) - > is_layers_editing_enabled ( ) ; }
# endif // ENABLE_SLOPE_RENDERING
2020-01-03 10:41:29 +00:00
void set_current_canvas_as_dirty ( ) ;
2020-01-21 13:07:13 +00:00
GLCanvas3D * get_current_canvas3D ( ) ;
2020-03-04 14:19:48 +00:00
void unbind_canvas_event_handlers ( ) ;
2020-04-01 07:58:31 +00:00
void reset_canvas_volumes ( ) ;
2020-01-03 10:41:29 +00:00
2019-12-10 09:56:21 +00:00
bool init_view_toolbar ( ) ;
2020-06-05 10:33:09 +00:00
bool init_collapse_toolbar ( ) ;
2019-12-10 09:56:21 +00:00
2019-03-27 13:16:38 +00:00
void reset_all_gizmos ( ) ;
2018-09-17 10:15:11 +00:00
void update_ui_from_settings ( ) ;
2020-05-05 15:23:58 +00:00
void update_main_toolbar_tooltips ( ) ;
2019-12-16 08:47:31 +00:00
std : : shared_ptr < ProgressStatusBar > statusbar ( ) ;
2018-10-01 14:48:08 +00:00
std : : string get_config ( const std : : string & key ) const ;
2018-10-03 14:18:23 +00:00
BoundingBoxf bed_shape_bb ( ) const ;
BoundingBox scaled_bed_shape_bb ( ) const ;
2019-08-06 16:16:02 +00:00
2020-04-29 17:10:13 +00:00
std : : vector < size_t > load_files ( const std : : vector < fs : : path > & input_files , bool load_model , bool load_config , bool used_inches = false ) ;
2018-10-01 14:48:08 +00:00
std : : vector < size_t > load_model_objects ( const ModelObjectPtrs & model_objects ) ;
2019-04-04 09:31:26 +00:00
wxString get_export_file ( GUI : : FileType file_type ) ;
2018-10-04 09:12:55 +00:00
2019-03-19 12:30:21 +00:00
const Selection & get_selection ( ) const ;
Selection & get_selection ( ) ;
2018-10-17 07:30:07 +00:00
int get_selected_object_idx ( ) const ;
2018-12-06 13:49:14 +00:00
int get_selected_volume_idx ( ) const ;
2018-10-04 09:12:55 +00:00
void selection_changed ( ) ;
2018-10-08 17:14:55 +00:00
void object_list_changed ( ) ;
2018-10-04 09:12:55 +00:00
2018-11-21 14:28:35 +00:00
void select_all ( ) ;
2019-05-14 09:57:39 +00:00
void deselect_all ( ) ;
2018-10-08 17:14:55 +00:00
void remove ( size_t obj_idx ) ;
2018-11-13 13:17:35 +00:00
void delete_object_from_model ( size_t obj_idx ) ;
2018-10-04 09:12:55 +00:00
void reset ( ) ;
2018-10-18 13:09:41 +00:00
void mirror ( Axis axis ) ;
2018-10-09 07:35:19 +00:00
void split_object ( ) ;
2018-10-24 10:55:38 +00:00
void split_volume ( ) ;
2019-05-22 12:42:38 +00:00
void scale_selection_to_fit_print_volume ( ) ;
2019-07-02 14:42:23 +00:00
2019-07-26 11:44:33 +00:00
// Return the active Undo/Redo stack. It may be either the main stack or the Gimzo stack.
Slic3r : : UndoRedo : : Stack & undo_redo_stack ( ) { assert ( m_undo_redo_stack_active ! = nullptr ) ; return * m_undo_redo_stack_active ; }
Slic3r : : UndoRedo : : Stack & undo_redo_stack_main ( ) { return m_undo_redo_stack_main ; }
void enter_gizmos_stack ( ) ;
void leave_gizmos_stack ( ) ;
2019-08-06 16:16:02 +00:00
void take_snapshot ( const std : : string & snapshot_name ) ;
void take_snapshot ( const wxString & snapshot_name ) { this - > take_snapshot ( std : : string ( snapshot_name . ToUTF8 ( ) . data ( ) ) ) ; }
2019-07-09 18:45:00 +00:00
int get_active_snapshot_index ( ) ;
2019-07-26 11:44:33 +00:00
2019-07-04 08:45:41 +00:00
void undo ( ) ;
void redo ( ) ;
2019-07-18 15:41:47 +00:00
void undo_redo_to ( size_t time_to_load ) ;
2019-07-11 16:42:02 +00:00
void suppress_snapshots ( ) { this - > m_prevent_snapshots + + ; }
void allow_snapshots ( ) { this - > m_prevent_snapshots - - ; }
2019-07-02 14:42:23 +00:00
2019-05-22 12:42:38 +00:00
bool background_processing_enabled ( ) const { return this - > get_config ( " background_processing " ) = = " 1 " ; }
2018-12-03 12:14:28 +00:00
void update_print_volume_state ( ) ;
2018-10-09 07:35:19 +00:00
void schedule_background_process ( ) ;
2018-11-13 16:45:44 +00:00
// Update background processing thread from the current config and Model.
enum UpdateBackgroundProcessReturnState {
// update_background_process() reports, that the Print / SLAPrint was updated in a way,
// that the background process was invalidated and it needs to be re-run.
UPDATE_BACKGROUND_PROCESS_RESTART = 1 ,
// update_background_process() reports, that the Print / SLAPrint was updated in a way,
2018-11-23 11:47:32 +00:00
// that a scene needs to be refreshed (you should call _3DScene::reload_scene(canvas3Dwidget, false))
2019-08-06 16:16:02 +00:00
UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE = 2 ,
2018-11-13 16:45:44 +00:00
// update_background_process() reports, that the Print / SLAPrint is invalid, and the error message
// was sent to the status line.
UPDATE_BACKGROUND_PROCESS_INVALID = 4 ,
2018-12-22 09:02:42 +00:00
// Restart even if the background processing is disabled.
UPDATE_BACKGROUND_PROCESS_FORCE_RESTART = 8 ,
// Restart for G-code (or SLA zip) export or upload.
UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT = 16 ,
2018-11-13 16:45:44 +00:00
} ;
// returns bit mask of UpdateBackgroundProcessReturnState
2019-08-23 13:53:45 +00:00
unsigned int update_background_process ( bool force_validation = false , bool postpone_error_messages = false ) ;
2018-12-22 09:02:42 +00:00
// Restart background processing thread based on a bitmask of UpdateBackgroundProcessReturnState.
bool restart_background_process ( unsigned int state ) ;
2019-08-06 16:16:02 +00:00
// returns bit mask of UpdateBackgroundProcessReturnState
unsigned int update_restart_background_process ( bool force_scene_update , bool force_preview_update ) ;
2019-08-23 13:53:45 +00:00
void show_delayed_error_message ( ) {
if ( ! this - > delayed_error_message . empty ( ) ) {
std : : string msg = std : : move ( this - > delayed_error_message ) ;
this - > delayed_error_message . clear ( ) ;
GUI : : show_error ( this - > q , msg ) ;
}
}
2020-03-12 11:43:01 +00:00
void export_gcode ( fs : : path output_path , bool output_path_on_removable_media , PrintHostJob upload_job ) ;
2018-10-09 07:35:19 +00:00
void reload_from_disk ( ) ;
2020-01-31 11:15:04 +00:00
void reload_all_from_disk ( ) ;
2019-01-30 15:27:07 +00:00
void fix_through_netfabb ( const int obj_idx , const int vol_idx = - 1 ) ;
2018-09-17 10:15:11 +00:00
2018-12-04 12:55:25 +00:00
void set_current_panel ( wxPanel * panel ) ;
2019-01-03 11:59:06 +00:00
2018-10-08 17:55:30 +00:00
void on_select_preset ( wxCommandEvent & ) ;
2018-11-20 12:22:26 +00:00
void on_slicing_update ( SlicingStatusEvent & ) ;
void on_slicing_completed ( wxCommandEvent & ) ;
2018-10-08 17:55:30 +00:00
void on_process_completed ( wxCommandEvent & ) ;
2018-09-17 10:15:11 +00:00
void on_layer_editing_toggled ( bool enable ) ;
2018-10-08 17:55:30 +00:00
2018-10-03 09:34:39 +00:00
void on_action_add ( SimpleEvent & ) ;
2018-10-24 10:55:38 +00:00
void on_action_split_objects ( SimpleEvent & ) ;
void on_action_split_volumes ( SimpleEvent & ) ;
2018-10-04 09:12:55 +00:00
void on_action_layersediting ( SimpleEvent & ) ;
2018-10-03 12:25:35 +00:00
2018-10-16 14:04:19 +00:00
void on_object_select ( SimpleEvent & ) ;
2019-09-20 07:57:27 +00:00
void on_right_click ( RBtnEvent & ) ;
2018-10-08 17:55:30 +00:00
void on_wipetower_moved ( Vec3dEvent & ) ;
2019-04-26 13:34:26 +00:00
void on_wipetower_rotated ( Vec3dEvent & ) ;
2018-10-08 17:55:30 +00:00
void on_update_geometry ( Vec3dsEvent < 2 > & ) ;
2018-11-23 11:47:32 +00:00
void on_3dcanvas_mouse_dragging_finished ( SimpleEvent & ) ;
2018-10-17 10:17:25 +00:00
2018-12-07 16:50:48 +00:00
void update_object_menu ( ) ;
2019-03-01 10:00:34 +00:00
void show_action_buttons ( const bool is_ready_to_slice ) const ;
2018-12-07 16:50:48 +00:00
2019-02-19 14:15:27 +00:00
// Set the bed shape to a single closed 2D polygon(array of two element arrays),
// triangulate the bed and store the triangles into m_bed.m_triangles,
// fills the m_bed.m_grid_lines and sets m_bed.m_origin.
// Sets m_bed.m_polygon to limit the object placement.
2019-07-24 12:02:36 +00:00
void set_bed_shape ( const Pointfs & shape , const std : : string & custom_texture , const std : : string & custom_model ) ;
2019-02-19 14:15:27 +00:00
2019-03-14 12:54:05 +00:00
bool can_delete ( ) const ;
bool can_delete_all ( ) 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 ;
2019-04-24 14:04:47 +00:00
bool can_fix_through_netfabb ( ) const ;
2019-05-13 12:27:51 +00:00
bool can_set_instance_to_object ( ) const ;
bool can_mirror ( ) const ;
2019-09-19 07:09:11 +00:00
bool can_reload_from_disk ( ) const ;
2019-03-14 12:54:05 +00:00
2019-11-28 13:18:24 +00:00
void generate_thumbnail ( ThumbnailData & data , unsigned int w , unsigned int h , bool printable_only , bool parts_only , bool show_bed , bool transparent_background ) ;
void generate_thumbnails ( ThumbnailsList & thumbnails , const Vec2ds & sizes , bool printable_only , bool parts_only , bool show_bed , bool transparent_background ) ;
2019-03-14 12:54:05 +00:00
2019-05-03 07:44:19 +00:00
void msw_rescale_object_menu ( ) ;
2019-05-15 12:09:16 +00:00
// returns the path to project file with the given extension (none if extension == wxEmptyString)
// extension should contain the leading dot, i.e.: ".3mf"
wxString get_project_filename ( const wxString & extension = wxEmptyString ) const ;
2019-05-14 13:00:24 +00:00
void set_project_filename ( const wxString & filename ) ;
2020-03-06 14:10:58 +00:00
// Caching last value of show_action_buttons parameter for show_action_buttons(), so that a callback which does not know this state will not override it.
mutable bool ready_to_slice = { false } ;
// Flag indicating that the G-code export targets a removable device, therefore the show_action_buttons() needs to be called at any case when the background processing finishes.
bool writing_to_removable_device = { false } ;
2020-03-20 12:41:36 +00:00
bool inside_snapshot_capture ( ) { return m_prevent_snapshots ! = 0 ; }
2020-03-06 14:10:58 +00:00
2018-10-17 10:17:25 +00:00
private :
bool init_object_menu ( ) ;
2018-12-07 16:50:48 +00:00
bool init_common_menu ( wxMenu * menu , const bool is_part = false ) ;
bool complit_init_object_menu ( ) ;
bool complit_init_sla_object_menu ( ) ;
bool complit_init_part_menu ( ) ;
2018-10-18 07:27:37 +00:00
2018-12-17 14:44:30 +00:00
bool can_split ( ) const ;
2018-10-18 07:27:37 +00:00
bool layers_height_allowed ( ) const ;
2018-11-23 11:47:32 +00:00
2018-12-06 14:40:41 +00:00
void update_fff_scene ( ) ;
2018-11-23 11:47:32 +00:00
void update_sla_scene ( ) ;
2019-08-06 16:16:02 +00:00
void undo_redo_to ( std : : vector < UndoRedo : : Snapshot > : : const_iterator it_snapshot ) ;
2019-08-22 14:44:49 +00:00
void update_after_undo_redo ( const UndoRedo : : Snapshot & snapshot , bool temp_snapshot_was_taken = false ) ;
2019-05-14 13:00:24 +00:00
2019-05-15 12:09:16 +00:00
// path to project file stored with no extension
2019-07-26 11:44:33 +00:00
wxString m_project_filename ;
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 ;
2019-08-06 16:16:02 +00:00
int m_prevent_snapshots = 0 ; /* Used for avoid of excess "snapshoting".
2019-07-26 11:44:33 +00:00
* Like for " delete selected " or " set numbers of copies "
2019-08-06 16:16:02 +00:00
* we should call tack_snapshot just ones
2019-07-26 11:44:33 +00:00
* instead of calls for each action separately
* */
2020-03-06 14:10:58 +00:00
std : : string m_last_fff_printer_profile_name ;
std : : string m_last_sla_printer_profile_name ;
2018-09-17 10:15:11 +00:00
} ;
2018-10-22 09:52:13 +00:00
const std : : regex Plater : : priv : : pattern_bundle ( " .*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa) " , std : : regex : : icase ) ;
const std : : regex Plater : : priv : : pattern_3mf ( " .*3mf " , std : : regex : : icase ) ;
const std : : regex Plater : : priv : : pattern_zip_amf ( " .*[.]zip[.]amf " , std : : regex : : icase ) ;
2019-01-03 11:04:14 +00:00
const std : : regex Plater : : priv : : pattern_any_amf ( " .*[.](amf|amf[.]xml|zip[.]amf) " , std : : regex : : icase ) ;
2019-01-18 15:01:43 +00:00
const std : : regex Plater : : priv : : pattern_prusa ( " .*prusa " , std : : regex : : icase ) ;
2019-01-03 11:04:14 +00:00
2018-10-18 13:13:38 +00:00
Plater : : priv : : priv ( Plater * q , MainFrame * main_frame )
: q ( q )
, main_frame ( main_frame )
, config ( Slic3r : : DynamicPrintConfig : : new_from_defaults_keys ( {
2019-07-18 12:39:19 +00:00
" bed_shape " , " bed_custom_texture " , " bed_custom_model " , " complete_objects " , " duplicate_distance " , " extruder_clearance_radius " , " skirts " , " skirt_distance " ,
2018-09-17 10:15:11 +00:00
" brim_width " , " variable_layer_height " , " serial_port " , " serial_speed " , " host_type " , " print_host " ,
" printhost_apikey " , " printhost_cafile " , " nozzle_diameter " , " single_extruder_multi_material " ,
" wipe_tower " , " wipe_tower_x " , " wipe_tower_y " , " wipe_tower_width " , " wipe_tower_rotation_angle " ,
2019-01-21 09:06:51 +00:00
" extruder_colour " , " filament_colour " , " max_print_height " , " printer_model " , " printer_technology " ,
2019-01-21 16:02:16 +00:00
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
" layer_height " , " first_layer_height " , " min_layer_height " , " max_layer_height " ,
2020-02-05 15:53:26 +00:00
" brim_width " , " perimeters " , " perimeter_extruder " , " fill_density " , " infill_extruder " , " top_solid_layers " ,
2019-01-21 16:02:16 +00:00
" support_material " , " support_material_extruder " , " support_material_interface_extruder " , " support_material_contact_distance " , " raft_layers "
2018-10-18 13:13:38 +00:00
} ) )
, sidebar ( new Sidebar ( q ) )
2020-04-23 16:47:51 +00:00
, m_ui_jobs ( this )
2018-11-23 11:47:32 +00:00
, delayed_scene_refresh ( false )
2019-02-26 11:56:13 +00:00
, view_toolbar ( GLToolbar : : Radio , " View " )
2020-06-05 10:33:09 +00:00
, collapse_toolbar ( GLToolbar : : Normal , " Collapse " )
2019-05-14 13:00:24 +00:00
, m_project_filename ( wxEmptyString )
2018-09-17 10:15:11 +00:00
{
2019-08-06 16:16:02 +00:00
this - > q - > SetFont ( Slic3r : : GUI : : wxGetApp ( ) . normal_font ( ) ) ;
2019-05-06 16:28:23 +00:00
2018-12-03 12:14:28 +00:00
background_process . set_fff_print ( & fff_print ) ;
2019-08-06 16:16:02 +00:00
background_process . set_sla_print ( & sla_print ) ;
2018-09-17 10:15:11 +00:00
background_process . set_gcode_preview_data ( & gcode_preview_data ) ;
2019-11-28 13:18:24 +00:00
background_process . set_thumbnail_cb ( [ this ] ( ThumbnailsList & thumbnails , const Vec2ds & sizes , bool printable_only , bool parts_only , bool show_bed , bool transparent_background )
2019-11-22 11:39:03 +00:00
{
2019-11-28 13:18:24 +00:00
std : : packaged_task < void ( ThumbnailsList & , const Vec2ds & , bool , bool , bool , bool ) > task ( [ this ] ( ThumbnailsList & thumbnails , const Vec2ds & sizes , bool printable_only , bool parts_only , bool show_bed , bool transparent_background ) {
generate_thumbnails ( thumbnails , sizes , printable_only , parts_only , show_bed , transparent_background ) ;
2019-11-22 11:39:03 +00:00
} ) ;
std : : future < void > result = task . get_future ( ) ;
2019-11-28 13:18:24 +00:00
wxTheApp - > CallAfter ( [ & ] ( ) { task ( thumbnails , sizes , printable_only , parts_only , show_bed , transparent_background ) ; } ) ;
2019-11-22 11:39:03 +00:00
result . wait ( ) ;
} ) ;
2018-11-20 12:22:26 +00:00
background_process . set_slicing_completed_event ( EVT_SLICING_COMPLETED ) ;
2018-09-17 10:15:11 +00:00
background_process . set_finished_event ( EVT_PROCESS_COMPLETED ) ;
2019-08-06 16:16:02 +00:00
// Default printer technology for default config.
2018-11-13 16:45:44 +00:00
background_process . select_technology ( this - > printer_technology ) ;
2019-12-03 03:48:01 +00:00
// Register progress callback from the Print class to the Plater.
2018-11-13 10:53:54 +00:00
2018-11-20 15:27:30 +00:00
auto statuscb = [ this ] ( const Slic3r : : PrintBase : : SlicingStatus & status ) {
2018-11-20 12:22:26 +00:00
wxQueueEvent ( this - > q , new Slic3r : : SlicingStatusEvent ( EVT_SLICING_UPDATE , 0 , status ) ) ;
2018-11-13 10:53:54 +00:00
} ;
2018-12-03 12:14:28 +00:00
fff_print . set_status_callback ( statuscb ) ;
2018-11-13 10:53:54 +00:00
sla_print . set_status_callback ( statuscb ) ;
2018-11-20 12:22:26 +00:00
this - > q - > Bind ( EVT_SLICING_UPDATE , & priv : : on_slicing_update , this ) ;
2018-09-17 10:15:11 +00:00
2020-03-02 09:58:46 +00:00
view3D = new View3D ( q , & model , config , & background_process ) ;
preview = new Preview ( q , & model , config , & background_process , & gcode_preview_data , [ this ] ( ) { schedule_background_process ( ) ; } ) ;
2020-03-02 11:45:04 +00:00
# ifdef __APPLE__
// set default view_toolbar icons size equal to GLGizmosManager::Default_Icons_Size
2020-03-02 12:09:12 +00:00
view_toolbar . set_icons_size ( GLGizmosManager : : Default_Icons_Size ) ;
2020-03-02 11:45:04 +00:00
# endif // __APPLE__
2019-02-19 14:15:27 +00:00
2018-12-04 12:55:25 +00:00
panels . push_back ( view3D ) ;
panels . push_back ( preview ) ;
2018-09-17 10:15:11 +00:00
2018-10-23 13:27:31 +00:00
this - > background_process_timer . SetOwner ( this - > q , 0 ) ;
2019-06-26 07:48:52 +00:00
this - > q - > Bind ( wxEVT_TIMER , [ this ] ( wxTimerEvent & evt )
{
if ( ! this - > suppressed_backround_processing_update )
this - > update_restart_background_process ( false , false ) ;
} ) ;
2018-09-17 10:15:11 +00:00
update ( ) ;
auto * hsizer = new wxBoxSizer ( wxHORIZONTAL ) ;
2018-12-04 12:55:25 +00:00
panel_sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
panel_sizer - > Add ( view3D , 1 , wxEXPAND | wxALL , 0 ) ;
panel_sizer - > Add ( preview , 1 , wxEXPAND | wxALL , 0 ) ;
hsizer - > Add ( panel_sizer , 1 , wxEXPAND | wxALL , 0 ) ;
2018-09-17 10:15:11 +00:00
hsizer - > Add ( sidebar , 0 , wxEXPAND | wxLEFT | wxRIGHT , 0 ) ;
q - > SetSizer ( hsizer ) ;
2018-10-17 10:17:25 +00:00
init_object_menu ( ) ;
2018-09-17 10:15:11 +00:00
// Events:
// Preset change event
sidebar - > Bind ( wxEVT_COMBOBOX , & priv : : on_select_preset , this ) ;
2018-11-01 11:33:56 +00:00
sidebar - > Bind ( EVT_OBJ_LIST_OBJECT_SELECT , [ this ] ( wxEvent & ) { priv : : selection_changed ( ) ; } ) ;
2018-12-04 10:14:39 +00:00
sidebar - > Bind ( EVT_SCHEDULE_BACKGROUND_PROCESS , [ this ] ( SimpleEvent & ) { this - > schedule_background_process ( ) ; } ) ;
2018-11-01 11:33:56 +00:00
2018-12-04 12:55:25 +00:00
wxGLCanvas * view3D_canvas = view3D - > get_wxglcanvas ( ) ;
2020-04-23 16:47:51 +00:00
2018-12-04 12:55:25 +00:00
// 3DScene events:
view3D_canvas - > Bind ( EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS , [ this ] ( SimpleEvent & ) { this - > schedule_background_process ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_OBJECT_SELECT , & priv : : on_object_select , this ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_RIGHT_CLICK , & priv : : on_right_click , this ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_REMOVE_OBJECT , [ q ] ( SimpleEvent & ) { q - > remove_selected ( ) ; } ) ;
2020-04-23 16:47:51 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_ARRANGE , [ this ] ( SimpleEvent & ) { this - > q - > arrange ( ) ; } ) ;
2019-02-03 13:06:13 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_SELECT_ALL , [ this ] ( SimpleEvent & ) { this - > q - > select_all ( ) ; } ) ;
2020-04-23 16:47:51 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_QUESTION_MARK , [ ] ( SimpleEvent & ) { wxGetApp ( ) . keyboard_shortcuts ( ) ; } ) ;
2019-08-06 16:16:02 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_INCREASE_INSTANCES , [ this ] ( Event < int > & evt )
2018-12-19 11:07:45 +00:00
{ if ( evt . data = = 1 ) this - > q - > increase_instances ( ) ; else if ( this - > can_decrease_instances ( ) ) this - > q - > decrease_instances ( ) ; } ) ;
2018-12-04 12:55:25 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_INSTANCE_MOVED , [ this ] ( SimpleEvent & ) { update ( ) ; } ) ;
2020-02-04 12:03:28 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_FORCE_UPDATE , [ this ] ( SimpleEvent & ) { update ( ) ; } ) ;
2018-12-04 12:55:25 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_WIPETOWER_MOVED , & priv : : on_wipetower_moved , this ) ;
2019-04-26 13:34:26 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_WIPETOWER_ROTATED , & priv : : on_wipetower_rotated , this ) ;
2019-01-03 10:24:03 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_INSTANCE_ROTATED , [ this ] ( SimpleEvent & ) { update ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_INSTANCE_SCALED , [ this ] ( SimpleEvent & ) { update ( ) ; } ) ;
2018-12-04 12:55:25 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_ENABLE_ACTION_BUTTONS , [ this ] ( Event < bool > & evt ) { this - > sidebar - > enable_buttons ( evt . data ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_UPDATE_GEOMETRY , & priv : : on_update_geometry , this ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED , & priv : : on_3dcanvas_mouse_dragging_finished , this ) ;
2019-02-21 10:54:18 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_TAB , [ this ] ( SimpleEvent & ) { select_next_view_3D ( ) ; } ) ;
2019-03-27 13:16:38 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_RESETGIZMOS , [ this ] ( SimpleEvent & ) { reset_all_gizmos ( ) ; } ) ;
2019-07-04 08:45:41 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_UNDO , [ this ] ( SimpleEvent & ) { this - > undo ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_REDO , [ this ] ( SimpleEvent & ) { this - > redo ( ) ; } ) ;
2020-04-29 13:58:57 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_COLLAPSE_SIDEBAR , [ this ] ( SimpleEvent & ) { this - > q - > collapse_sidebar ( ! this - > q - > is_sidebar_collapsed ( ) ) ; } ) ;
2019-11-29 10:01:51 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE , [ this ] ( SimpleEvent & ) { this - > view3D - > get_canvas3d ( ) - > reset_layer_height_profile ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE , [ this ] ( Event < float > & evt ) { this - > view3D - > get_canvas3d ( ) - > adaptive_layer_height_profile ( evt . data ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE , [ this ] ( HeightProfileSmoothEvent & evt ) { this - > view3D - > get_canvas3d ( ) - > smooth_layer_height_profile ( evt . data ) ; } ) ;
2020-02-03 14:47:09 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_RELOAD_FROM_DISK , [ this ] ( SimpleEvent & ) { this - > reload_all_from_disk ( ) ; } ) ;
2019-04-26 13:34:26 +00:00
2018-12-04 12:55:25 +00:00
// 3DScene/Toolbar:
view3D_canvas - > Bind ( EVT_GLTOOLBAR_ADD , & priv : : on_action_add , this ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_DELETE , [ q ] ( SimpleEvent & ) { q - > remove_selected ( ) ; } ) ;
2019-05-02 11:52:13 +00:00
view3D_canvas - > Bind ( EVT_GLTOOLBAR_DELETE_ALL , [ q ] ( SimpleEvent & ) { q - > reset_with_confirm ( ) ; } ) ;
2020-04-23 16:47:51 +00:00
view3D_canvas - > Bind ( EVT_GLTOOLBAR_ARRANGE , [ this ] ( SimpleEvent & ) { this - > q - > arrange ( ) ; } ) ;
2019-04-11 11:20:34 +00:00
view3D_canvas - > Bind ( EVT_GLTOOLBAR_COPY , [ q ] ( SimpleEvent & ) { q - > copy_selection_to_clipboard ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_PASTE , [ q ] ( SimpleEvent & ) { q - > paste_from_clipboard ( ) ; } ) ;
2018-12-04 12:55:25 +00:00
view3D_canvas - > Bind ( EVT_GLTOOLBAR_MORE , [ q ] ( SimpleEvent & ) { q - > increase_instances ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_FEWER , [ q ] ( SimpleEvent & ) { q - > decrease_instances ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_SPLIT_OBJECTS , & priv : : on_action_split_objects , this ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_SPLIT_VOLUMES , & priv : : on_action_split_volumes , this ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_LAYERSEDITING , & priv : : on_action_layersediting , this ) ;
2019-07-18 12:39:19 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_UPDATE_BED_SHAPE , [ this ] ( SimpleEvent & )
{
set_bed_shape ( config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ,
2019-07-24 12:02:36 +00:00
config - > option < ConfigOptionString > ( " bed_custom_texture " ) - > value ,
config - > option < ConfigOptionString > ( " bed_custom_model " ) - > value ) ;
2019-07-18 12:39:19 +00:00
} ) ;
2018-10-04 09:12:55 +00:00
2018-10-08 17:55:30 +00:00
// Preview events:
2018-12-22 09:02:42 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_QUESTION_MARK , [ this ] ( SimpleEvent & ) { wxGetApp ( ) . keyboard_shortcuts ( ) ; } ) ;
2019-07-18 12:39:19 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_UPDATE_BED_SHAPE , [ this ] ( SimpleEvent & )
{
set_bed_shape ( config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ,
2019-07-24 12:02:36 +00:00
config - > option < ConfigOptionString > ( " bed_custom_texture " ) - > value ,
config - > option < ConfigOptionString > ( " bed_custom_model " ) - > value ) ;
2019-07-18 12:39:19 +00:00
} ) ;
2019-02-21 10:54:18 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_TAB , [ this ] ( SimpleEvent & ) { select_next_view_3D ( ) ; } ) ;
2019-06-13 14:10:33 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_MOVE_DOUBLE_SLIDER , [ this ] ( wxKeyEvent & evt ) { preview - > move_double_slider ( evt ) ; } ) ;
2019-06-18 09:40:26 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_EDIT_COLOR_CHANGE , [ this ] ( wxKeyEvent & evt ) { preview - > edit_double_slider ( evt ) ; } ) ;
2019-01-03 11:59:06 +00:00
2018-11-20 12:22:26 +00:00
q - > Bind ( EVT_SLICING_COMPLETED , & priv : : on_slicing_completed , this ) ;
2018-09-17 10:15:11 +00:00
q - > Bind ( EVT_PROCESS_COMPLETED , & priv : : on_process_completed , this ) ;
2018-12-06 09:38:19 +00:00
q - > Bind ( EVT_GLVIEWTOOLBAR_3D , [ q ] ( SimpleEvent & ) { q - > select_view_3D ( " 3D " ) ; } ) ;
q - > Bind ( EVT_GLVIEWTOOLBAR_PREVIEW , [ q ] ( SimpleEvent & ) { q - > select_view_3D ( " Preview " ) ; } ) ;
2018-09-17 10:15:11 +00:00
// Drop target:
q - > SetDropTarget ( new PlaterDropTarget ( q ) ) ; // if my understanding is right, wxWindow takes the owenership
q - > Layout ( ) ;
2018-12-20 11:51:42 +00:00
set_current_panel ( view3D ) ;
2019-06-20 08:02:52 +00:00
// updates camera type from .ini file
2019-06-24 13:55:14 +00:00
camera . set_type ( get_config ( " use_perspective_camera " ) ) ;
2019-07-02 14:42:23 +00:00
2020-03-04 10:36:36 +00:00
// Load the 3DConnexion device database.
mouse3d_controller . load_config ( * wxGetApp ( ) . app_config ) ;
// Start the background thread to detect and connect to a HID device (Windows and Linux).
2020-03-13 13:19:02 +00:00
// Connect to a 3DConnextion driver (OSX).
2019-09-27 12:52:19 +00:00
mouse3d_controller . init ( ) ;
2020-03-13 13:19:02 +00:00
# ifdef _WIN32
// Register an USB HID (Human Interface Device) attach event. evt contains Win32 path to the USB device containing VID, PID and other info.
// This event wakes up the Mouse3DController's background thread to enumerate HID devices, if the VID of the callback event
// is one of the 3D Mouse vendors (3DConnexion or Logitech).
this - > q - > Bind ( EVT_HID_DEVICE_ATTACHED , [ this ] ( HIDDeviceAttachedEvent & evt ) {
mouse3d_controller . device_attached ( evt . data ) ;
} ) ;
# endif /* _WIN32 */
2019-09-27 12:52:19 +00:00
2020-03-06 14:10:58 +00:00
this - > q - > Bind ( EVT_REMOVABLE_DRIVE_EJECTED , [ this ] ( RemovableDriveEjectEvent & evt ) {
2020-03-12 08:38:46 +00:00
if ( evt . data . second ) {
this - > show_action_buttons ( this - > ready_to_slice ) ;
2020-04-01 07:48:56 +00:00
Slic3r : : GUI : : show_info ( this - > q , format_wxstr ( _L ( " Unmounting successful. The device %s(%s) can now be safely removed from the computer. " ) ,
evt . data . first . name , evt . data . first . path ) ) ;
2020-03-12 08:38:46 +00:00
} else
2020-04-01 07:48:56 +00:00
Slic3r : : GUI : : show_info ( this - > q , format_wxstr ( _L ( " Ejecting of device %s(%s) has failed. " ) ,
evt . data . first . name , evt . data . first . path ) ) ;
2020-03-06 14:10:58 +00:00
} ) ;
this - > q - > Bind ( EVT_REMOVABLE_DRIVES_CHANGED , [ this ] ( RemovableDrivesChangedEvent & ) { this - > show_action_buttons ( this - > ready_to_slice ) ; } ) ;
// Start the background thread and register this window as a target for update events.
wxGetApp ( ) . removable_drive_manager ( ) - > init ( this - > q ) ;
2020-03-13 13:19:02 +00:00
# ifdef _WIN32
// Trigger enumeration of removable media on Win32 notification.
this - > q - > Bind ( EVT_VOLUME_ATTACHED , [ this ] ( VolumeAttachedEvent & evt ) { wxGetApp ( ) . removable_drive_manager ( ) - > volumes_changed ( ) ; } ) ;
this - > q - > Bind ( EVT_VOLUME_DETACHED , [ this ] ( VolumeDetachedEvent & evt ) { wxGetApp ( ) . removable_drive_manager ( ) - > volumes_changed ( ) ; } ) ;
# endif /* _WIN32 */
2020-03-06 14:10:58 +00:00
2019-07-05 17:06:19 +00:00
// Initialize the Undo / Redo stack with a first snapshot.
2020-04-01 07:48:56 +00:00
this - > take_snapshot ( _L ( " New Project " ) ) ;
2020-04-29 08:50:28 +00:00
this - > q - > Bind ( EVT_LOAD_MODEL_OTHER_INSTANCE , [ this ] ( LoadFromOtherInstanceEvent & evt ) {
BOOST_LOG_TRIVIAL ( debug ) < < " received load from other instance event " ;
this - > load_files ( evt . data , true , true ) ;
} ) ;
this - > q - > Bind ( EVT_INSTANCE_GO_TO_FRONT , [ this ] ( InstanceGoToFrontEvent & ) {
BOOST_LOG_TRIVIAL ( debug ) < < " prusaslicer window going forward " ;
//this code maximize app window on Fedora
2020-05-14 10:15:02 +00:00
{
wxGetApp ( ) . mainframe - > Iconize ( false ) ;
if ( wxGetApp ( ) . mainframe - > IsMaximized ( ) )
wxGetApp ( ) . mainframe - > Maximize ( true ) ;
else
wxGetApp ( ) . mainframe - > Maximize ( false ) ;
}
//this code maximize window on Ubuntu
{
wxGetApp ( ) . mainframe - > Restore ( ) ;
wxGetApp ( ) . GetTopWindow ( ) - > SetFocus ( ) ; // focus on my window
wxGetApp ( ) . GetTopWindow ( ) - > Raise ( ) ; // bring window to front
wxGetApp ( ) . GetTopWindow ( ) - > Show ( true ) ; // show the window
}
2020-04-29 08:50:28 +00:00
} ) ;
wxGetApp ( ) . other_instance_message_handler ( ) - > init ( this - > q ) ;
2020-03-16 11:49:39 +00:00
// collapse sidebar according to saved value
2020-05-05 15:23:58 +00:00
bool is_collapsed = wxGetApp ( ) . app_config - > get ( " collapsed_sidebar " ) = = " 1 " ;
sidebar - > collapse ( is_collapsed ) ;
// Update an enable of the collapse_toolbar: if sidebar is collapsed, then collapse_toolbar should be visible
if ( is_collapsed )
wxGetApp ( ) . app_config - > set ( " show_collapse_button " , " 1 " ) ;
2018-09-17 10:15:11 +00:00
}
2019-06-27 13:23:03 +00:00
Plater : : priv : : ~ priv ( )
{
if ( config ! = nullptr )
delete config ;
}
2019-08-23 13:53:45 +00:00
void Plater : : priv : : update ( unsigned int flags )
2018-09-17 10:15:11 +00:00
{
2019-06-19 09:05:34 +00:00
// the following line, when enabled, causes flickering on NVIDIA graphics cards
// wxWindowUpdateLocker freeze_guard(q);
2018-11-21 12:32:24 +00:00
if ( get_config ( " autocenter " ) = = " 1 " ) {
2018-10-01 14:48:08 +00:00
// auto *bed_shape_opt = config->opt<ConfigOptionPoints>("bed_shape");
// const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values);
// const BoundingBox bed_shape_bb = bed_shape.bounding_box();
2018-10-03 14:18:23 +00:00
const Vec2d & bed_center = bed_shape_bb ( ) . center ( ) ;
2018-10-01 14:48:08 +00:00
model . center_instances_around_point ( bed_center ) ;
}
2018-12-22 09:02:42 +00:00
unsigned int update_status = 0 ;
2019-08-23 13:53:45 +00:00
if ( this - > printer_technology = = ptSLA | | ( flags & ( unsigned int ) UpdateParams : : FORCE_BACKGROUND_PROCESSING_UPDATE ) )
2018-11-13 16:45:44 +00:00
// Update the SLAPrint from the current Model, so that the reload_scene()
// pulls the correct data.
2019-08-23 13:53:45 +00:00
update_status = this - > update_background_process ( false , flags & ( unsigned int ) UpdateParams : : POSTPONE_VALIDATION_ERROR_MESSAGE ) ;
this - > view3D - > reload_scene ( false , flags & ( unsigned int ) UpdateParams : : FORCE_FULL_SCREEN_REFRESH ) ;
2019-08-06 16:16:02 +00:00
this - > preview - > reload_print ( ) ;
2018-12-22 09:02:42 +00:00
if ( this - > printer_technology = = ptSLA )
this - > restart_background_process ( update_status ) ;
else
this - > schedule_background_process ( ) ;
2018-09-17 10:15:11 +00:00
}
2018-12-04 12:55:25 +00:00
void Plater : : priv : : select_view ( const std : : string & direction )
{
if ( current_panel = = view3D )
view3D - > select_view ( direction ) ;
else if ( current_panel = = preview )
preview - > select_view ( direction ) ;
}
void Plater : : priv : : select_view_3D ( const std : : string & name )
{
if ( name = = " 3D " )
set_current_panel ( view3D ) ;
else if ( name = = " Preview " )
set_current_panel ( preview ) ;
2018-12-21 09:43:22 +00:00
}
void Plater : : priv : : select_next_view_3D ( )
{
if ( current_panel = = view3D )
set_current_panel ( preview ) ;
else if ( current_panel = = preview )
set_current_panel ( view3D ) ;
2018-12-04 12:55:25 +00:00
}
2018-10-17 10:59:58 +00:00
2019-03-27 13:16:38 +00:00
void Plater : : priv : : reset_all_gizmos ( )
{
view3D - > get_canvas3d ( ) - > reset_all_gizmos ( ) ;
}
2018-12-04 10:14:39 +00:00
// Called after the Preferences dialog is closed and the program settings are saved.
// Update the UI based on the current preferences.
2018-09-17 10:15:11 +00:00
void Plater : : priv : : update_ui_from_settings ( )
{
2020-03-09 14:23:29 +00:00
camera . set_type ( wxGetApp ( ) . app_config - > get ( " use_perspective_camera " ) ) ;
if ( wxGetApp ( ) . app_config - > get ( " use_free_camera " ) ! = " 1 " )
2020-03-10 12:02:39 +00:00
camera . recover_from_free_camera ( ) ;
2020-03-09 14:23:29 +00:00
2019-01-24 12:16:46 +00:00
view3D - > get_canvas3d ( ) - > update_ui_from_settings ( ) ;
preview - > get_canvas3d ( ) - > update_ui_from_settings ( ) ;
2020-04-29 17:10:13 +00:00
sidebar - > update_ui_from_settings ( ) ;
2018-09-17 10:15:11 +00:00
}
2020-05-05 15:23:58 +00:00
// Called after the print technology was changed.
// Update the tooltips for "Switch to Settings" button in maintoolbar
void Plater : : priv : : update_main_toolbar_tooltips ( )
{
view3D - > get_canvas3d ( ) - > update_tooltip_for_settings_item_in_main_toolbar ( ) ;
}
2019-12-16 08:47:31 +00:00
std : : shared_ptr < ProgressStatusBar > Plater : : priv : : statusbar ( )
2018-09-17 10:15:11 +00:00
{
2019-12-16 08:47:31 +00:00
return main_frame - > m_statusbar ;
2018-09-17 10:15:11 +00:00
}
2018-10-01 14:48:08 +00:00
std : : string Plater : : priv : : get_config ( const std : : string & key ) const
{
return wxGetApp ( ) . app_config - > get ( key ) ;
}
2018-10-03 14:18:23 +00:00
BoundingBoxf Plater : : priv : : bed_shape_bb ( ) const
{
BoundingBox bb = scaled_bed_shape_bb ( ) ;
return BoundingBoxf ( unscale ( bb . min ) , unscale ( bb . max ) ) ;
}
BoundingBox Plater : : priv : : scaled_bed_shape_bb ( ) const
2018-10-01 14:48:08 +00:00
{
const auto * bed_shape_opt = config - > opt < ConfigOptionPoints > ( " bed_shape " ) ;
const auto bed_shape = Slic3r : : Polygon : : new_scale ( bed_shape_opt - > values ) ;
return bed_shape . bounding_box ( ) ;
}
2020-04-29 17:10:13 +00:00
std : : vector < size_t > Plater : : priv : : load_files ( const std : : vector < fs : : path > & input_files , bool load_model , bool load_config , bool imperial_units /* = false*/ )
2018-09-17 10:15:11 +00:00
{
2018-10-04 09:12:55 +00:00
if ( input_files . empty ( ) ) { return std : : vector < size_t > ( ) ; }
2018-09-17 10:15:11 +00:00
auto * nozzle_dmrs = config - > opt < ConfigOptionFloats > ( " nozzle_diameter " ) ;
2020-02-14 13:44:17 +00:00
bool one_by_one = input_files . size ( ) = = 1 | | printer_technology = = ptSLA | | nozzle_dmrs - > values . size ( ) < = 1 ;
2018-09-17 10:15:11 +00:00
if ( ! one_by_one ) {
for ( const auto & path : input_files ) {
if ( std : : regex_match ( path . string ( ) , pattern_bundle ) ) {
one_by_one = true ;
break ;
}
}
}
2020-04-01 07:48:56 +00:00
const auto loading = _L ( " Loading " ) + dots ;
2018-09-17 10:15:11 +00:00
wxProgressDialog dlg ( loading , loading ) ;
dlg . Pulse ( ) ;
2018-11-16 08:26:41 +00:00
auto * new_model = ( ! load_model | | one_by_one ) ? nullptr : new Slic3r : : Model ( ) ;
2018-10-01 14:48:08 +00:00
std : : vector < size_t > obj_idxs ;
2018-09-17 10:15:11 +00:00
for ( size_t i = 0 ; i < input_files . size ( ) ; i + + ) {
const auto & path = input_files [ i ] ;
const auto filename = path . filename ( ) ;
2020-04-01 07:48:56 +00:00
const auto dlg_info = format_wxstr ( _L ( " Processing input file %s " ) , from_path ( filename ) ) + " \n " ;
2018-09-17 10:15:11 +00:00
dlg . Update ( 100 * i / input_files . size ( ) , dlg_info ) ;
const bool type_3mf = std : : regex_match ( path . string ( ) , pattern_3mf ) ;
const bool type_zip_amf = ! type_3mf & & std : : regex_match ( path . string ( ) , pattern_zip_amf ) ;
2019-01-03 11:04:14 +00:00
const bool type_any_amf = ! type_3mf & & std : : regex_match ( path . string ( ) , pattern_any_amf ) ;
2019-01-18 15:01:43 +00:00
const bool type_prusa = std : : regex_match ( path . string ( ) , pattern_prusa ) ;
2018-09-17 10:15:11 +00:00
Slic3r : : Model model ;
2019-05-22 13:30:35 +00:00
bool is_project_file = type_prusa ;
2018-09-17 10:15:11 +00:00
try {
if ( type_3mf | | type_zip_amf ) {
DynamicPrintConfig config ;
2018-11-06 18:09:54 +00:00
{
DynamicPrintConfig config_loaded ;
2019-08-23 11:12:31 +00:00
model = Slic3r : : Model : : read_from_archive ( path . string ( ) , & config_loaded , false , load_config ) ;
2018-11-16 08:26:41 +00:00
if ( load_config & & ! config_loaded . empty ( ) ) {
// Based on the printer technology field found in the loaded config, select the base for the config,
2019-08-06 16:16:02 +00:00
PrinterTechnology printer_technology = Preset : : printer_technology ( config_loaded ) ;
2019-06-17 15:04:19 +00:00
// We can't to load SLA project if there is at least one multi-part object on the bed
if ( printer_technology = = ptSLA )
{
const ModelObjectPtrs & objects = q - > model ( ) . objects ;
for ( auto object : objects )
if ( object - > volumes . size ( ) > 1 )
{
Slic3r : : GUI : : show_info ( nullptr ,
2020-04-01 07:48:56 +00:00
_L ( " You cannot load SLA project with a multi-part object on the bed " ) + " \n \n " +
_L ( " Please check your object list before preset changing. " ) ,
_L ( " Attention! " ) ) ;
2019-06-17 15:04:19 +00:00
return obj_idxs ;
}
}
2019-08-06 16:16:02 +00:00
config . apply ( printer_technology = = ptFFF ?
static_cast < const ConfigBase & > ( FullPrintConfig : : defaults ( ) ) :
2018-11-06 18:09:54 +00:00
static_cast < const ConfigBase & > ( SLAFullPrintConfig : : defaults ( ) ) ) ;
// and place the loaded config over the base.
config + = std : : move ( config_loaded ) ;
}
2019-11-11 15:01:34 +00:00
2019-12-17 07:37:50 +00:00
this - > model . custom_gcode_per_print_z = model . custom_gcode_per_print_z ;
2018-11-06 18:09:54 +00:00
}
2018-12-03 14:06:02 +00:00
2018-11-16 08:26:41 +00:00
if ( load_config )
{
if ( ! config . empty ( ) ) {
Preset : : normalize ( config ) ;
wxGetApp ( ) . preset_bundle - > load_config_model ( filename . string ( ) , std : : move ( config ) ) ;
wxGetApp ( ) . load_current_presets ( ) ;
2019-05-22 13:30:35 +00:00
is_project_file = true ;
2018-11-16 08:26:41 +00:00
}
wxGetApp ( ) . app_config - > update_config_dir ( path . parent_path ( ) . string ( ) ) ;
}
}
else {
2019-08-23 11:12:31 +00:00
model = Slic3r : : Model : : read_from_file ( path . string ( ) , nullptr , false , load_config ) ;
2018-10-19 09:02:50 +00:00
for ( auto obj : model . objects )
if ( obj - > name . empty ( ) )
obj - > name = fs : : path ( obj - > input_file ) . filename ( ) . string ( ) ;
2018-09-17 10:15:11 +00:00
}
2018-12-03 12:14:28 +00:00
} catch ( const std : : exception & e ) {
2018-09-17 10:15:11 +00:00
GUI : : show_error ( q , e . what ( ) ) ;
continue ;
}
2018-11-16 08:26:41 +00:00
if ( load_model )
{
// The model should now be initialized
2020-04-29 17:10:13 +00:00
auto convert_from_imperial_units = [ ] ( Model & model ) {
model . convert_from_imperial_units ( ) ;
wxGetApp ( ) . app_config - > set ( " use_inches " , " 1 " ) ;
wxGetApp ( ) . sidebar ( ) . update_ui_from_settings ( ) ;
} ;
if ( imperial_units )
convert_from_imperial_units ( model ) ;
else if ( model . looks_like_imperial_units ( ) ) {
2020-05-27 08:55:48 +00:00
wxMessageDialog msg_dlg ( q , format_wxstr ( _L (
" Some object(s) in file %s looks like saved in inches. \n "
" Should I consider them as a saved in inches and convert them? " ) , from_path ( filename ) ) + " \n " ,
2020-04-29 17:10:13 +00:00
_L ( " Saved in inches object detected " ) , wxICON_WARNING | wxYES | wxNO ) ;
if ( msg_dlg . ShowModal ( ) = = wxID_YES )
convert_from_imperial_units ( model ) ;
}
2019-05-22 13:30:35 +00:00
if ( ! is_project_file ) {
2019-01-18 11:52:09 +00:00
if ( model . looks_like_multipart_object ( ) ) {
2020-04-01 07:48:56 +00:00
wxMessageDialog msg_dlg ( q , _L (
2019-12-04 10:12:28 +00:00
" This file contains several objects positioned at multiple heights. \n "
2019-01-21 11:34:28 +00:00
" Instead of considering them as multiple objects, should I consider \n "
2020-04-01 07:48:56 +00:00
" this file as a single object having multiple parts? " ) + " \n " ,
_L ( " Multi-part object detected " ) , wxICON_WARNING | wxYES | wxNO ) ;
2019-09-03 08:27:16 +00:00
if ( msg_dlg . ShowModal ( ) = = wxID_YES ) {
2019-01-21 13:43:57 +00:00
model . convert_multipart_object ( nozzle_dmrs - > values . size ( ) ) ;
}
2019-01-18 11:52:09 +00:00
}
2018-09-17 10:15:11 +00:00
}
2019-07-18 15:41:47 +00:00
else if ( ( wxGetApp ( ) . get_mode ( ) = = comSimple ) & & ( type_3mf | | type_any_amf ) & & model_has_advanced_features ( model ) ) {
2020-04-01 07:48:56 +00:00
wxMessageDialog msg_dlg ( q , _L ( " This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode? " ) + " \n " ,
_L ( " Detected advanced data " ) , wxICON_WARNING | wxYES | wxNO ) ;
2019-09-03 08:27:16 +00:00
if ( msg_dlg . ShowModal ( ) = = wxID_YES )
2019-04-04 10:02:13 +00:00
{
2019-07-18 15:41:47 +00:00
Slic3r : : GUI : : wxGetApp ( ) . save_mode ( comAdvanced ) ;
view3D - > set_as_dirty ( ) ;
2019-04-04 10:02:13 +00:00
}
2019-07-18 15:41:47 +00:00
else
return obj_idxs ;
2019-04-04 10:02:13 +00:00
}
2018-09-17 10:15:11 +00:00
2019-07-18 15:41:47 +00:00
for ( ModelObject * model_object : model . objects ) {
2019-09-17 10:50:54 +00:00
if ( ! type_3mf & & ! type_zip_amf )
model_object - > center_around_origin ( false ) ;
2019-07-18 15:41:47 +00:00
model_object - > ensure_on_bed ( ) ;
}
2018-09-17 10:15:11 +00:00
2018-12-10 12:39:56 +00:00
// check multi-part object adding for the SLA-printing
if ( printer_technology = = ptSLA )
{
for ( auto obj : model . objects )
if ( obj - > volumes . size ( ) > 1 ) {
2019-08-06 16:16:02 +00:00
Slic3r : : GUI : : show_error ( nullptr ,
2020-04-01 07:48:56 +00:00
format_wxstr ( _L ( " You can't to add the object(s) from %s because of one or some of them is(are) multi-part " ) ,
from_path ( filename ) ) ) ;
2019-04-04 10:02:13 +00:00
return obj_idxs ;
2018-12-10 12:39:56 +00:00
}
}
2018-11-16 08:26:41 +00:00
if ( one_by_one ) {
auto loaded_idxs = load_model_objects ( model . objects ) ;
obj_idxs . insert ( obj_idxs . end ( ) , loaded_idxs . begin ( ) , loaded_idxs . end ( ) ) ;
} else {
// This must be an .stl or .obj file, which may contain a maximum of one volume.
for ( const ModelObject * model_object : model . objects ) {
new_model - > add_object ( * model_object ) ;
}
2018-09-17 10:15:11 +00:00
}
}
}
2019-08-05 15:49:21 +00:00
if ( new_model ! = nullptr & & new_model - > objects . size ( ) > 1 ) {
2020-04-01 07:48:56 +00:00
wxMessageDialog msg_dlg ( q , _L (
2018-09-17 10:15:11 +00:00
" Multiple objects were loaded for a multi-material printer. \n "
" Instead of considering them as multiple objects, should I consider \n "
2020-04-01 07:48:56 +00:00
" these files to represent a single object having multiple parts? " ) + " \n " ,
_L ( " Multi-part object detected " ) , wxICON_WARNING | wxYES | wxNO ) ;
2019-09-03 08:27:16 +00:00
if ( msg_dlg . ShowModal ( ) = = wxID_YES ) {
2018-09-17 10:15:11 +00:00
new_model - > convert_multipart_object ( nozzle_dmrs - > values . size ( ) ) ;
}
2018-10-19 09:02:50 +00:00
auto loaded_idxs = load_model_objects ( new_model - > objects ) ;
2018-10-01 14:48:08 +00:00
obj_idxs . insert ( obj_idxs . end ( ) , loaded_idxs . begin ( ) , loaded_idxs . end ( ) ) ;
2018-09-17 10:15:11 +00:00
}
2018-11-16 08:26:41 +00:00
if ( load_model )
{
wxGetApp ( ) . app_config - > update_skein_dir ( input_files [ input_files . size ( ) - 1 ] . parent_path ( ) . string ( ) ) ;
// XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames...
2020-04-01 07:48:56 +00:00
statusbar ( ) - > set_status_text ( _L ( " Loaded " ) ) ;
2018-11-16 08:26:41 +00:00
}
2018-12-03 14:06:02 +00:00
2019-01-03 08:12:50 +00:00
// automatic selection of added objects
if ( ! obj_idxs . empty ( ) & & ( view3D ! = nullptr ) )
{
2019-08-06 12:54:38 +00:00
// update printable state for new volumes on canvas3D
wxGetApp ( ) . plater ( ) - > canvas3D ( ) - > update_instance_printable_state_for_objects ( obj_idxs ) ;
2019-03-19 12:30:21 +00:00
Selection & selection = view3D - > get_canvas3d ( ) - > get_selection ( ) ;
2019-01-03 08:12:50 +00:00
selection . clear ( ) ;
for ( size_t idx : obj_idxs )
{
selection . add_object ( ( unsigned int ) idx , false ) ;
}
2019-09-09 13:55:04 +00:00
2020-03-14 08:42:24 +00:00
if ( view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) . is_enabled ( ) )
2019-09-09 13:55:04 +00:00
// this is required because the selected object changed and the flatten on face an sla support gizmos need to be updated accordingly
view3D - > get_canvas3d ( ) - > update_gizmos_on_off_state ( ) ;
2019-01-03 08:12:50 +00:00
}
2018-10-01 14:48:08 +00:00
return obj_idxs ;
2018-09-17 10:15:11 +00:00
}
2019-01-28 09:56:02 +00:00
// #define AUTOPLACEMENT_ON_LOAD
2018-10-04 09:12:55 +00:00
std : : vector < size_t > Plater : : priv : : load_model_objects ( const ModelObjectPtrs & model_objects )
2018-09-17 10:15:11 +00:00
{
2018-10-03 14:18:23 +00:00
const BoundingBoxf bed_shape = bed_shape_bb ( ) ;
2018-12-19 08:54:15 +00:00
const Vec3d bed_size = Slic3r : : to_3d ( bed_shape . size ( ) . cast < double > ( ) , 1.0 ) - 2.0 * Vec3d : : Ones ( ) ;
2018-09-17 10:15:11 +00:00
2019-01-28 09:56:02 +00:00
# ifndef AUTOPLACEMENT_ON_LOAD
bool need_arrange = false ;
# endif /* AUTOPLACEMENT_ON_LOAD */
2018-09-17 10:15:11 +00:00
bool scaled_down = false ;
2018-10-01 14:48:08 +00:00
std : : vector < size_t > obj_idxs ;
2018-10-19 09:02:50 +00:00
unsigned int obj_count = model . objects . size ( ) ;
2018-09-17 10:15:11 +00:00
2019-01-28 09:56:02 +00:00
# ifdef AUTOPLACEMENT_ON_LOAD
2019-01-22 16:50:33 +00:00
ModelInstancePtrs new_instances ;
2019-01-28 09:56:02 +00:00
# endif /* AUTOPLACEMENT_ON_LOAD */
2018-10-01 14:48:08 +00:00
for ( ModelObject * model_object : model_objects ) {
2018-09-17 10:15:11 +00:00
auto * object = model . add_object ( * model_object ) ;
std : : string object_name = object - > name . empty ( ) ? fs : : path ( object - > input_file ) . filename ( ) . string ( ) : object - > name ;
2018-10-17 07:30:07 +00:00
obj_idxs . push_back ( obj_count + + ) ;
2018-09-17 10:15:11 +00:00
2018-10-04 09:12:55 +00:00
if ( model_object - > instances . empty ( ) ) {
2019-01-28 09:56:02 +00:00
# ifdef AUTOPLACEMENT_ON_LOAD
2019-01-22 16:50:33 +00:00
object - > center_around_origin ( ) ;
new_instances . emplace_back ( object - > add_instance ( ) ) ;
2019-01-28 09:56:02 +00:00
# else /* AUTOPLACEMENT_ON_LOAD */
2019-03-25 11:07:43 +00:00
// if object has no defined position(s) we need to rearrange everything after loading
need_arrange = true ;
2019-08-06 16:16:02 +00:00
// add a default instance and center object around origin
object - > center_around_origin ( ) ; // also aligns object to Z = 0
ModelInstance * instance = object - > add_instance ( ) ;
2019-01-28 09:56:02 +00:00
instance - > set_offset ( Slic3r : : to_3d ( bed_shape . center ( ) . cast < double > ( ) , - object - > origin_translation ( 2 ) ) ) ;
# endif /* AUTOPLACEMENT_ON_LOAD */
2018-09-17 10:15:11 +00:00
}
2018-10-01 14:48:08 +00:00
const Vec3d size = object - > bounding_box ( ) . size ( ) ;
const Vec3d ratio = size . cwiseQuotient ( bed_size ) ;
const double max_ratio = std : : max ( ratio ( 0 ) , ratio ( 1 ) ) ;
if ( max_ratio > 10000 ) {
// the size of the object is too big -> this could lead to overflow when moving to clipper coordinates,
// so scale down the mesh
2019-08-06 16:16:02 +00:00
double inv = 1. / max_ratio ;
2019-07-02 14:42:23 +00:00
object - > scale_mesh_after_creation ( Vec3d ( inv , inv , inv ) ) ;
2018-12-19 08:54:15 +00:00
object - > origin_translation = Vec3d : : Zero ( ) ;
object - > center_around_origin ( ) ;
2018-10-01 14:48:08 +00:00
scaled_down = true ;
} else if ( max_ratio > 5 ) {
2019-01-25 12:30:01 +00:00
const Vec3d inverse = 1.0 / max_ratio * Vec3d : : Ones ( ) ;
for ( ModelInstance * instance : object - > instances ) {
2018-10-01 14:48:08 +00:00
instance - > set_scaling_factor ( inverse ) ;
}
2019-01-25 12:30:01 +00:00
scaled_down = true ;
2018-10-01 14:48:08 +00:00
}
2018-10-10 12:43:07 +00:00
2018-10-30 15:03:03 +00:00
object - > ensure_on_bed ( ) ;
2018-09-17 10:15:11 +00:00
}
2019-01-28 09:56:02 +00:00
# ifdef AUTOPLACEMENT_ON_LOAD
2019-01-23 12:12:44 +00:00
// FIXME distance should be a config value /////////////////////////////////
2019-01-22 16:50:33 +00:00
auto min_obj_distance = static_cast < coord_t > ( 6 / SCALING_FACTOR ) ;
const auto * bed_shape_opt = config - > opt < ConfigOptionPoints > ( " bed_shape " ) ;
assert ( bed_shape_opt ) ;
auto & bedpoints = bed_shape_opt - > values ;
Polyline bed ; bed . points . reserve ( bedpoints . size ( ) ) ;
for ( auto & v : bedpoints ) bed . append ( Point : : new_scale ( v ( 0 ) , v ( 1 ) ) ) ;
2019-08-06 16:16:02 +00:00
2019-06-27 19:13:44 +00:00
std : : pair < bool , GLCanvas3D : : WipeTowerInfo > wti = view3D - > get_canvas3d ( ) - > get_wipe_tower_info ( ) ;
2019-08-06 16:16:02 +00:00
2019-04-29 12:32:02 +00:00
arr : : find_new_position ( model , new_instances , min_obj_distance , bed , wti ) ;
// it remains to move the wipe tower:
view3D - > get_canvas3d ( ) - > arrange_wipe_tower ( wti ) ;
2019-01-28 09:56:02 +00:00
# endif /* AUTOPLACEMENT_ON_LOAD */
2019-01-22 16:50:33 +00:00
2018-10-01 14:48:08 +00:00
if ( scaled_down ) {
GUI : : show_info ( q ,
2020-04-01 07:48:56 +00:00
_L ( " Your object appears to be too large, so it was automatically scaled down to fit your print bed. " ) ,
_L ( " Object too large? " ) ) ;
2018-10-01 14:48:08 +00:00
}
2019-09-23 13:35:49 +00:00
for ( const size_t idx : obj_idxs ) {
wxGetApp ( ) . obj_list ( ) - > add_object_to_list ( idx ) ;
2018-10-01 14:48:08 +00:00
}
update ( ) ;
2018-10-11 11:22:36 +00:00
object_list_changed ( ) ;
2018-10-17 09:12:38 +00:00
this - > schedule_background_process ( ) ;
2018-10-01 14:48:08 +00:00
return obj_idxs ;
2018-09-17 10:15:11 +00:00
}
2019-04-04 09:31:26 +00:00
wxString Plater : : priv : : get_export_file ( GUI : : FileType file_type )
2018-10-04 09:12:55 +00:00
{
wxString wildcard ;
switch ( file_type ) {
case FT_STL :
case FT_AMF :
case FT_3MF :
2018-10-19 14:52:41 +00:00
case FT_GCODE :
2019-08-20 07:01:09 +00:00
case FT_OBJ :
2018-12-06 16:32:49 +00:00
wildcard = file_wildcards ( file_type ) ;
2018-10-04 09:12:55 +00:00
break ;
default :
2018-12-06 16:32:49 +00:00
wildcard = file_wildcards ( FT_MODEL ) ;
2018-10-04 09:12:55 +00:00
break ;
}
2018-12-03 12:14:28 +00:00
// Update printbility state of each of the ModelInstances.
this - > update_print_volume_state ( ) ;
2019-04-04 12:00:31 +00:00
const Selection & selection = get_selection ( ) ;
int obj_idx = selection . get_object_idx ( ) ;
fs : : path output_file ;
2019-05-14 13:00:24 +00:00
if ( file_type = = FT_3MF )
// for 3mf take the path from the project filename, if any
2019-05-15 12:09:16 +00:00
output_file = into_path ( get_project_filename ( " .3mf " ) ) ;
2019-04-04 12:00:31 +00:00
if ( output_file . empty ( ) )
2019-05-14 13:00:24 +00:00
{
// first try to get the file name from the current selection
if ( ( 0 < = obj_idx ) & & ( obj_idx < ( int ) this - > model . objects . size ( ) ) )
output_file = this - > model . objects [ obj_idx ] - > get_export_filename ( ) ;
if ( output_file . empty ( ) )
// Find the file name of the first printable object.
output_file = this - > model . propose_export_file_name_and_path ( ) ;
2019-09-19 12:01:17 +00:00
if ( output_file . empty ( ) & & ! model . objects . empty ( ) )
// Find the file name of the first object.
output_file = this - > model . objects [ 0 ] - > get_export_filename ( ) ;
2019-05-14 13:00:24 +00:00
}
2018-10-04 09:12:55 +00:00
2019-04-04 09:31:26 +00:00
wxString dlg_title ;
2018-10-04 09:12:55 +00:00
switch ( file_type ) {
2019-04-04 09:31:26 +00:00
case FT_STL :
{
output_file . replace_extension ( " stl " ) ;
2020-04-01 07:48:56 +00:00
dlg_title = _L ( " Export STL file: " ) ;
2019-04-04 09:31:26 +00:00
break ;
}
case FT_AMF :
{
// XXX: Problem on OS X with double extension?
output_file . replace_extension ( " zip.amf " ) ;
2020-04-01 07:48:56 +00:00
dlg_title = _L ( " Export AMF file: " ) ;
2019-04-04 09:31:26 +00:00
break ;
}
case FT_3MF :
{
output_file . replace_extension ( " 3mf " ) ;
2020-04-01 07:48:56 +00:00
dlg_title = _L ( " Save file as: " ) ;
2019-04-04 09:31:26 +00:00
break ;
}
2019-08-20 07:01:09 +00:00
case FT_OBJ :
{
output_file . replace_extension ( " obj " ) ;
2020-04-01 07:48:56 +00:00
dlg_title = _L ( " Export OBJ file: " ) ;
2019-08-20 07:01:09 +00:00
break ;
}
2018-10-04 09:12:55 +00:00
default : break ;
}
2019-08-15 10:52:56 +00:00
wxFileDialog dlg ( q , dlg_title ,
2019-04-04 09:31:26 +00:00
from_path ( output_file . parent_path ( ) ) , from_path ( output_file . filename ( ) ) ,
wildcard , wxFD_SAVE | wxFD_OVERWRITE_PROMPT ) ;
2018-10-04 09:12:55 +00:00
2019-08-15 10:52:56 +00:00
if ( dlg . ShowModal ( ) ! = wxID_OK )
2019-04-04 09:31:26 +00:00
return wxEmptyString ;
2018-10-04 09:12:55 +00:00
2019-08-15 10:52:56 +00:00
wxString out_path = dlg . GetPath ( ) ;
2019-04-04 09:31:26 +00:00
fs : : path path ( into_path ( out_path ) ) ;
2018-10-04 09:12:55 +00:00
wxGetApp ( ) . app_config - > update_last_output_dir ( path . parent_path ( ) . string ( ) ) ;
2019-04-04 09:31:26 +00:00
return out_path ;
2018-10-04 09:12:55 +00:00
}
2019-03-19 12:30:21 +00:00
const Selection & Plater : : priv : : get_selection ( ) const
2018-10-17 07:30:07 +00:00
{
2018-12-04 12:55:25 +00:00
return view3D - > get_canvas3d ( ) - > get_selection ( ) ;
2018-10-17 07:30:07 +00:00
}
2019-03-19 12:30:21 +00:00
Selection & Plater : : priv : : get_selection ( )
2018-10-17 07:30:07 +00:00
{
2018-12-04 12:55:25 +00:00
return view3D - > get_canvas3d ( ) - > get_selection ( ) ;
2018-10-17 07:30:07 +00:00
}
int Plater : : priv : : get_selected_object_idx ( ) const
{
int idx = get_selection ( ) . get_object_idx ( ) ;
return ( ( 0 < = idx ) & & ( idx < 1000 ) ) ? idx : - 1 ;
}
2018-10-04 09:12:55 +00:00
2018-12-06 13:49:14 +00:00
int Plater : : priv : : get_selected_volume_idx ( ) const
{
auto & selection = get_selection ( ) ;
int idx = selection . get_object_idx ( ) ;
2019-08-06 16:16:02 +00:00
if ( ( 0 > idx ) | | ( idx > 1000 ) )
2018-12-06 13:49:14 +00:00
return - 1 ;
const GLVolume * v = selection . get_volume ( * selection . get_volume_idxs ( ) . begin ( ) ) ;
if ( model . objects [ idx ] - > volumes . size ( ) > 1 )
return v - > volume_idx ( ) ;
return - 1 ;
}
2018-10-04 09:12:55 +00:00
void Plater : : priv : : selection_changed ( )
{
2019-01-24 14:50:06 +00:00
// if the selection is not valid to allow for layer editing, we need to turn off the tool if it is running
bool enable_layer_editing = layers_height_allowed ( ) ;
2019-01-25 07:37:06 +00:00
if ( ! enable_layer_editing & & view3D - > is_layers_editing_enabled ( ) ) {
SimpleEvent evt ( EVT_GLTOOLBAR_LAYERSEDITING ) ;
on_action_layersediting ( evt ) ;
}
2019-01-24 14:50:06 +00:00
2018-12-04 12:55:25 +00:00
// forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears)
view3D - > render ( ) ;
2018-10-04 09:12:55 +00:00
}
2018-10-08 17:14:55 +00:00
void Plater : : priv : : object_list_changed ( )
2018-10-04 09:12:55 +00:00
{
2018-10-23 13:27:31 +00:00
const bool export_in_progress = this - > background_process . is_export_scheduled ( ) ; // || ! send_gcode_file.empty());
2018-10-08 17:14:55 +00:00
// XXX: is this right?
2020-05-23 22:01:34 +00:00
const bool model_fits = view3D - > check_volumes_outside_state ( ) = = ModelInstancePVS_Inside ;
2018-10-08 17:14:55 +00:00
2018-10-18 13:09:41 +00:00
sidebar - > enable_buttons ( ! model . objects . empty ( ) & & ! export_in_progress & & model_fits ) ;
2018-10-04 09:12:55 +00:00
}
2018-11-21 14:28:35 +00:00
void Plater : : priv : : select_all ( )
{
2018-12-04 12:55:25 +00:00
view3D - > select_all ( ) ;
2018-12-03 12:29:07 +00:00
this - > sidebar - > obj_list ( ) - > update_selections ( ) ;
2018-11-21 14:28:35 +00:00
}
2019-05-14 09:57:39 +00:00
void Plater : : priv : : deselect_all ( )
{
view3D - > deselect_all ( ) ;
}
2018-10-08 17:14:55 +00:00
void Plater : : priv : : remove ( size_t obj_idx )
2018-10-04 09:12:55 +00:00
{
2018-10-08 17:14:55 +00:00
// Prevent toolpaths preview from rendering while we modify the Print object
preview - > set_enabled ( false ) ;
2018-12-04 12:55:25 +00:00
if ( view3D - > is_layers_editing_enabled ( ) )
view3D - > enable_layers_editing ( false ) ;
2018-10-22 13:18:56 +00:00
2018-10-08 17:14:55 +00:00
model . delete_object ( obj_idx ) ;
update ( ) ;
2019-05-14 14:37:32 +00:00
// Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
sidebar - > obj_list ( ) - > delete_object_from_list ( obj_idx ) ;
2019-05-08 08:37:45 +00:00
object_list_changed ( ) ;
2018-10-08 17:14:55 +00:00
}
2018-11-13 13:17:35 +00:00
void Plater : : priv : : delete_object_from_model ( size_t obj_idx )
{
2020-04-01 07:48:56 +00:00
wxString snapshot_label = _L ( " Delete Object " ) ;
2019-08-06 16:16:02 +00:00
if ( ! model . objects [ obj_idx ] - > name . empty ( ) )
snapshot_label + = " : " + wxString : : FromUTF8 ( model . objects [ obj_idx ] - > name . c_str ( ) ) ;
Plater : : TakeSnapshot snapshot ( q , snapshot_label ) ;
2018-11-13 13:17:35 +00:00
model . delete_object ( obj_idx ) ;
2018-11-14 10:22:13 +00:00
update ( ) ;
2019-05-08 08:37:45 +00:00
object_list_changed ( ) ;
2018-11-13 13:17:35 +00:00
}
2018-10-08 17:14:55 +00:00
void Plater : : priv : : reset ( )
{
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( q , _L ( " Reset Project " ) ) ;
2019-07-02 14:42:23 +00:00
2019-05-14 13:00:24 +00:00
set_project_filename ( wxEmptyString ) ;
2018-11-15 14:27:39 +00:00
2018-10-04 09:12:55 +00:00
// Prevent toolpaths preview from rendering while we modify the Print object
preview - > set_enabled ( false ) ;
2018-12-04 12:55:25 +00:00
if ( view3D - > is_layers_editing_enabled ( ) )
view3D - > enable_layers_editing ( false ) ;
2018-10-22 13:18:56 +00:00
2018-11-08 13:23:17 +00:00
// Stop and reset the Print content.
this - > background_process . reset ( ) ;
2018-10-04 09:12:55 +00:00
model . clear_objects ( ) ;
update ( ) ;
2019-05-14 14:37:32 +00:00
// Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
sidebar - > obj_list ( ) - > delete_all_objects_from_list ( ) ;
2019-05-08 08:37:45 +00:00
object_list_changed ( ) ;
2018-11-28 15:02:29 +00:00
2019-01-30 09:00:38 +00:00
// The hiding of the slicing results, if shown, is not taken care by the background process, so we do it here
this - > sidebar - > show_sliced_info_sizer ( false ) ;
2018-11-28 15:02:29 +00:00
2020-01-16 15:01:19 +00:00
model . custom_gcode_per_print_z . gcodes . clear ( ) ;
2018-10-04 09:12:55 +00:00
}
2018-10-18 13:09:41 +00:00
void Plater : : priv : : mirror ( Axis axis )
2018-10-09 07:35:19 +00:00
{
2018-12-04 12:55:25 +00:00
view3D - > mirror_selection ( axis ) ;
2018-10-09 07:35:19 +00:00
}
2020-04-23 16:47:51 +00:00
void Plater : : find_new_position ( const ModelInstancePtrs & instances ,
2019-07-16 16:33:42 +00:00
coord_t min_d )
2019-07-15 16:18:34 +00:00
{
arrangement : : ArrangePolygons movable , fixed ;
2020-04-23 16:47:51 +00:00
for ( const ModelObject * mo : p - > model . objects )
2019-07-15 16:18:34 +00:00
for ( const ModelInstance * inst : mo - > instances ) {
auto it = std : : find ( instances . begin ( ) , instances . end ( ) , inst ) ;
auto arrpoly = inst - > get_arrange_polygon ( ) ;
2019-08-06 16:16:02 +00:00
2019-07-15 16:18:34 +00:00
if ( it = = instances . end ( ) )
fixed . emplace_back ( std : : move ( arrpoly ) ) ;
else
movable . emplace_back ( std : : move ( arrpoly ) ) ;
}
2020-04-23 16:47:51 +00:00
if ( p - > view3D - > get_canvas3d ( ) - > get_wipe_tower_info ( ) )
fixed . emplace_back ( get_wipe_tower_arrangepoly ( * this ) ) ;
arrangement : : arrange ( movable , fixed , get_bed_shape ( * config ( ) ) ,
arrangement : : ArrangeParams { min_d } ) ;
2019-08-06 16:16:02 +00:00
2019-07-15 16:18:34 +00:00
for ( size_t i = 0 ; i < instances . size ( ) ; + + i )
if ( movable [ i ] . bed_idx = = 0 )
2020-03-30 11:26:24 +00:00
instances [ i ] - > apply_arrange_result ( movable [ i ] . translation . cast < double > ( ) ,
2019-07-17 11:32:31 +00:00
movable [ i ] . rotation ) ;
2019-07-15 16:18:34 +00:00
}
2018-11-12 13:52:52 +00:00
2018-10-09 07:35:19 +00:00
void Plater : : priv : : split_object ( )
{
2018-10-19 13:27:19 +00:00
int obj_idx = get_selected_object_idx ( ) ;
if ( obj_idx = = - 1 )
return ;
2019-11-11 15:10:46 +00:00
2018-10-19 13:27:19 +00:00
// we clone model object because split_object() adds the split volumes
// into the same model object, thus causing duplicates when we call load_model_objects()
Model new_model = model ;
ModelObject * current_model_object = new_model . objects [ obj_idx ] ;
if ( current_model_object - > volumes . size ( ) > 1 )
{
2020-04-01 07:48:56 +00:00
Slic3r : : GUI : : warning_catcher ( q , _L ( " The selected object can't be split because it contains more than one volume/material. " ) ) ;
2018-10-19 13:27:19 +00:00
return ;
}
2019-02-05 19:23:24 +00:00
wxBusyCursor wait ;
2018-10-19 13:27:19 +00:00
ModelObjectPtrs new_objects ;
current_model_object - > split ( & new_objects ) ;
if ( new_objects . size ( ) = = 1 )
2020-04-01 07:48:56 +00:00
Slic3r : : GUI : : warning_catcher ( q , _L ( " The selected object couldn't be split because it contains only one part. " ) ) ;
2018-10-19 13:27:19 +00:00
else
{
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( q , _L ( " Split to Objects " ) ) ;
2019-07-04 15:33:19 +00:00
2018-10-24 10:55:38 +00:00
unsigned int counter = 1 ;
2018-10-19 13:27:19 +00:00
for ( ModelObject * m : new_objects )
2018-10-24 10:55:38 +00:00
m - > name = current_model_object - > name + " _ " + std : : to_string ( counter + + ) ;
2018-10-19 13:27:19 +00:00
remove ( obj_idx ) ;
// load all model objects at once, otherwise the plate would be rearranged after each one
// causing original positions not to be kept
2018-10-31 10:24:56 +00:00
std : : vector < size_t > idxs = load_model_objects ( new_objects ) ;
// select newly added objects
for ( size_t idx : idxs )
{
get_selection ( ) . add_object ( ( unsigned int ) idx , false ) ;
}
2018-10-19 13:27:19 +00:00
}
2018-10-09 07:35:19 +00:00
}
2018-10-24 10:55:38 +00:00
void Plater : : priv : : split_volume ( )
{
2018-12-06 13:49:14 +00:00
wxGetApp ( ) . obj_list ( ) - > split ( ) ;
2018-10-24 10:55:38 +00:00
}
2019-05-22 12:42:38 +00:00
void Plater : : priv : : scale_selection_to_fit_print_volume ( )
{
this - > view3D - > get_canvas3d ( ) - > get_selection ( ) . scale_to_fit_print_volume ( * config ) ;
}
2018-10-09 07:35:19 +00:00
void Plater : : priv : : schedule_background_process ( )
{
2019-02-22 10:59:40 +00:00
delayed_error_message . clear ( ) ;
2018-10-17 09:12:38 +00:00
// Trigger the timer event after 0.5s
this - > background_process_timer . Start ( 500 , wxTIMER_ONE_SHOT ) ;
2019-01-21 16:02:16 +00:00
// Notify the Canvas3D that something has changed, so it may invalidate some of the layer editing stuff.
this - > view3D - > get_canvas3d ( ) - > set_config ( this - > config ) ;
2018-10-09 07:35:19 +00:00
}
2018-12-03 12:14:28 +00:00
void Plater : : priv : : update_print_volume_state ( )
{
BoundingBox bed_box_2D = get_extents ( Polygon : : new_scale ( this - > config - > opt < ConfigOptionPoints > ( " bed_shape " ) - > values ) ) ;
BoundingBoxf3 print_volume ( unscale ( bed_box_2D . min ( 0 ) , bed_box_2D . min ( 1 ) , 0.0 ) , unscale ( bed_box_2D . max ( 0 ) , bed_box_2D . max ( 1 ) , scale_ ( this - > config - > opt_float ( " max_print_height " ) ) ) ) ;
// Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
print_volume . min ( 2 ) = - 1e10 ;
this - > q - > model ( ) . update_print_volume_state ( print_volume ) ;
}
2018-11-13 16:45:44 +00:00
// Update background processing thread from the current config and Model.
// Returns a bitmask of UpdateBackgroundProcessReturnState.
2019-08-23 13:53:45 +00:00
unsigned int Plater : : priv : : update_background_process ( bool force_validation , bool postpone_error_messages )
2018-10-09 07:35:19 +00:00
{
2018-11-13 16:45:44 +00:00
// bitmap of enum UpdateBackgroundProcessReturnState
unsigned int return_state = 0 ;
2019-08-06 16:16:02 +00:00
// If the update_background_process() was not called by the timer, kill the timer,
2018-12-22 09:02:42 +00:00
// so the update_restart_background_process() will not be called again in vain.
2018-11-13 16:45:44 +00:00
this - > background_process_timer . Stop ( ) ;
2018-12-03 12:14:28 +00:00
// Update the "out of print bed" state of ModelInstances.
this - > update_print_volume_state ( ) ;
2018-10-17 09:12:38 +00:00
// Apply new config to the possibly running background task.
2018-12-22 09:02:42 +00:00
bool was_running = this - > background_process . running ( ) ;
2018-12-03 12:14:28 +00:00
Print : : ApplyStatus invalidated = this - > background_process . apply ( this - > q - > model ( ) , wxGetApp ( ) . preset_bundle - > full_config ( ) ) ;
2018-11-08 15:01:21 +00:00
2018-10-17 09:12:38 +00:00
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
2018-12-04 12:55:25 +00:00
if ( view3D - > is_layers_editing_enabled ( ) )
view3D - > get_wxglcanvas ( ) - > Refresh ( ) ;
2018-10-23 20:53:43 +00:00
if ( invalidated = = Print : : APPLY_STATUS_INVALIDATED ) {
// Some previously calculated data on the Print was invalidated.
// Hide the slicing results, as the current slicing status is no more valid.
2018-10-31 11:26:57 +00:00
this - > sidebar - > show_sliced_info_sizer ( false ) ;
2018-10-23 20:53:43 +00:00
// Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
// Otherwise they will be just refreshed.
2019-08-06 16:16:02 +00:00
if ( this - > preview ! = nullptr )
// If the preview is not visible, the following line just invalidates the preview,
// but the G-code paths or SLA preview are calculated first once the preview is made visible.
this - > preview - > reload_print ( ) ;
// In FDM mode, we need to reload the 3D scene because of the wipe tower preview box.
// In SLA mode, we need to reload the 3D scene every time to show the support structures.
if ( this - > printer_technology = = ptSLA | | ( this - > printer_technology = = ptFFF & & this - > config - > opt_bool ( " wipe_tower " ) ) )
return_state | = UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE ;
2018-10-17 09:12:38 +00:00
}
2018-11-13 16:45:44 +00:00
2019-01-10 15:06:24 +00:00
if ( ( invalidated ! = Print : : APPLY_STATUS_UNCHANGED | | force_validation ) & & ! this - > background_process . empty ( ) ) {
2019-08-23 13:53:45 +00:00
// The delayed error message is no more valid.
this - > delayed_error_message . clear ( ) ;
// The state of the Print changed, and it is non-zero. Let's validate it and give the user feedback on errors.
2018-11-13 16:45:44 +00:00
std : : string err = this - > background_process . validate ( ) ;
if ( err . empty ( ) ) {
2019-08-06 16:16:02 +00:00
if ( invalidated ! = Print : : APPLY_STATUS_UNCHANGED & & this - > background_processing_enabled ( ) )
2018-11-13 16:45:44 +00:00
return_state | = UPDATE_BACKGROUND_PROCESS_RESTART ;
} else {
// The print is not valid.
2019-02-19 13:57:59 +00:00
// Only show the error message immediately, if the top level parent of this window is active.
auto p = dynamic_cast < wxWindow * > ( this - > q ) ;
while ( p - > GetParent ( ) )
p = p - > GetParent ( ) ;
auto * top_level_wnd = dynamic_cast < wxTopLevelWindow * > ( p ) ;
2019-08-23 13:53:45 +00:00
if ( ! postpone_error_messages & & top_level_wnd & & top_level_wnd - > IsActive ( ) ) {
2019-02-19 13:57:59 +00:00
// The error returned from the Print needs to be translated into the local language.
2020-02-21 12:38:06 +00:00
GUI : : show_error ( this - > q , err ) ;
2019-02-19 13:57:59 +00:00
} else {
// Show the error message once the main window gets activated.
2020-02-21 12:38:06 +00:00
this - > delayed_error_message = err ;
2019-02-19 13:57:59 +00:00
}
2018-11-13 16:45:44 +00:00
return_state | = UPDATE_BACKGROUND_PROCESS_INVALID ;
}
2019-08-23 13:53:45 +00:00
} else if ( ! this - > delayed_error_message . empty ( ) ) {
// Reusing the old state.
return_state | = UPDATE_BACKGROUND_PROCESS_INVALID ;
2018-11-13 16:45:44 +00:00
}
2018-12-22 09:02:42 +00:00
2019-01-10 15:06:24 +00:00
if ( invalidated ! = Print : : APPLY_STATUS_UNCHANGED & & was_running & & ! this - > background_process . running ( ) & &
2018-12-22 09:02:42 +00:00
( return_state & UPDATE_BACKGROUND_PROCESS_RESTART ) = = 0 ) {
2019-08-06 16:16:02 +00:00
// The background processing was killed and it will not be restarted.
wxCommandEvent evt ( EVT_PROCESS_COMPLETED ) ;
evt . SetInt ( - 1 ) ;
// Post the "canceled" callback message, so that it will be processed after any possible pending status bar update messages.
wxQueueEvent ( GUI : : wxGetApp ( ) . mainframe - > m_plater , evt . Clone ( ) ) ;
}
2018-12-22 09:02:42 +00:00
2019-03-01 10:00:34 +00:00
if ( ( return_state & UPDATE_BACKGROUND_PROCESS_INVALID ) ! = 0 )
{
2019-03-12 08:41:57 +00:00
// Validation of the background data failed.
2020-04-01 07:48:56 +00:00
const wxString invalid_str = _L ( " Invalid data " ) ;
2019-03-01 10:00:34 +00:00
for ( auto btn : { ActionButtonType : : abReslice , ActionButtonType : : abSendGCode , ActionButtonType : : abExport } )
sidebar - > set_btn_label ( btn , invalid_str ) ;
}
else
{
2019-03-12 08:41:57 +00:00
// Background data is valid.
2019-03-01 10:00:34 +00:00
if ( ( return_state & UPDATE_BACKGROUND_PROCESS_RESTART ) ! = 0 | |
( return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE ) ! = 0 )
2020-04-01 07:48:56 +00:00
this - > statusbar ( ) - > set_status_text ( _L ( " Ready to slice " ) ) ;
2019-03-01 10:00:34 +00:00
sidebar - > set_btn_label ( ActionButtonType : : abExport , _ ( label_btn_export ) ) ;
2019-03-12 08:41:57 +00:00
sidebar - > set_btn_label ( ActionButtonType : : abSendGCode , _ ( label_btn_send ) ) ;
2019-08-06 16:16:02 +00:00
const wxString slice_string = background_process . running ( ) & & wxGetApp ( ) . get_mode ( ) = = comSimple ?
2020-04-01 07:48:56 +00:00
_L ( " Slicing " ) + dots : _L ( " Slice now " ) ;
2019-03-01 10:00:34 +00:00
sidebar - > set_btn_label ( ActionButtonType : : abReslice , slice_string ) ;
if ( background_process . finished ( ) )
show_action_buttons ( false ) ;
2019-08-06 16:16:02 +00:00
else if ( ! background_process . empty ( ) & &
2019-03-11 09:23:59 +00:00
! background_process . running ( ) ) /* Do not update buttons if background process is running
2019-08-06 16:16:02 +00:00
* This condition is important for SLA mode especially ,
* when this function is called several times during calculations
2019-03-11 09:23:59 +00:00
* */
2019-03-01 10:00:34 +00:00
show_action_buttons ( true ) ;
}
2018-11-13 16:45:44 +00:00
return return_state ;
2018-10-09 07:35:19 +00:00
}
2018-12-22 09:02:42 +00:00
// Restart background processing thread based on a bitmask of UpdateBackgroundProcessReturnState.
bool Plater : : priv : : restart_background_process ( unsigned int state )
{
2019-06-18 14:24:30 +00:00
if ( m_ui_jobs . is_any_running ( ) ) {
2019-04-17 12:56:00 +00:00
// Avoid a race condition
return false ;
}
2019-08-06 16:16:02 +00:00
if ( ! this - > background_process . empty ( ) & &
( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID ) = = 0 & &
( ( ( state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART ) ! = 0 & & ! this - > background_process . finished ( ) ) | |
2018-12-22 09:02:42 +00:00
( state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT ) ! = 0 | |
( state & UPDATE_BACKGROUND_PROCESS_RESTART ) ! = 0 ) ) {
// The print is valid and it can be started.
if ( this - > background_process . start ( ) ) {
this - > statusbar ( ) - > set_cancel_callback ( [ this ] ( ) {
2020-04-01 07:48:56 +00:00
this - > statusbar ( ) - > set_status_text ( _L ( " Cancelling " ) ) ;
2018-12-22 09:02:42 +00:00
this - > background_process . stop ( ) ;
} ) ;
return true ;
}
}
return false ;
}
2020-03-12 11:43:01 +00:00
void Plater : : priv : : export_gcode ( fs : : path output_path , bool output_path_on_removable_media , PrintHostJob upload_job )
2018-12-11 09:33:11 +00:00
{
wxCHECK_RET ( ! ( output_path . empty ( ) & & upload_job . empty ( ) ) , " export_gcode: output_path and upload_job empty " ) ;
if ( model . objects . empty ( ) )
return ;
if ( background_process . is_export_scheduled ( ) ) {
2020-04-01 07:48:56 +00:00
GUI : : show_error ( q , _L ( " Another export job is currently running. " ) ) ;
2018-12-11 09:33:11 +00:00
return ;
}
// bitmask of UpdateBackgroundProcessReturnState
2019-01-10 15:06:24 +00:00
unsigned int state = update_background_process ( true ) ;
2018-12-11 09:33:11 +00:00
if ( state & priv : : UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE )
view3D - > reload_scene ( false ) ;
2019-01-03 11:59:06 +00:00
2018-12-11 09:33:11 +00:00
if ( ( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID ) ! = 0 )
return ;
if ( ! output_path . empty ( ) ) {
2020-03-12 11:43:01 +00:00
background_process . schedule_export ( output_path . string ( ) , output_path_on_removable_media ) ;
2018-12-11 09:33:11 +00:00
} else {
background_process . schedule_upload ( std : : move ( upload_job ) ) ;
}
2019-02-25 09:21:12 +00:00
// If the SLA processing of just a single object's supports is running, restart slicing for the whole object.
this - > background_process . set_task ( PrintBase : : TaskParams ( ) ) ;
2018-12-22 09:02:42 +00:00
this - > restart_background_process ( priv : : UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT ) ;
2018-12-11 09:33:11 +00:00
}
2019-02-03 09:41:14 +00:00
unsigned int Plater : : priv : : update_restart_background_process ( bool force_update_scene , bool force_update_preview )
2018-10-09 07:35:19 +00:00
{
2018-11-13 16:45:44 +00:00
// bitmask of UpdateBackgroundProcessReturnState
2019-01-10 15:06:24 +00:00
unsigned int state = this - > update_background_process ( false ) ;
2018-12-22 09:02:42 +00:00
if ( force_update_scene | | ( state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE ) ! = 0 )
2018-12-04 12:55:25 +00:00
view3D - > reload_scene ( false ) ;
2019-01-03 11:59:06 +00:00
2018-12-22 09:02:42 +00:00
if ( force_update_preview )
this - > preview - > reload_print ( ) ;
this - > restart_background_process ( state ) ;
2019-08-06 16:16:02 +00:00
return state ;
2018-10-09 07:35:19 +00:00
}
2018-12-06 14:40:41 +00:00
void Plater : : priv : : update_fff_scene ( )
{
if ( this - > preview ! = nullptr )
this - > preview - > reload_print ( ) ;
// In case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth:
2019-08-06 16:16:02 +00:00
view3D - > reload_scene ( true ) ;
2019-12-12 14:43:14 +00:00
2018-12-06 14:40:41 +00:00
}
2018-11-23 11:47:32 +00:00
void Plater : : priv : : update_sla_scene ( )
{
// Update the SLAPrint from the current Model, so that the reload_scene()
// pulls the correct data.
delayed_scene_refresh = false ;
2018-12-22 09:02:42 +00:00
this - > update_restart_background_process ( true , true ) ;
2018-11-23 11:47:32 +00:00
}
2018-10-09 07:35:19 +00:00
void Plater : : priv : : reload_from_disk ( )
{
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( q , _L ( " Reload from disk " ) ) ;
2019-07-05 17:46:48 +00:00
2019-09-19 07:09:11 +00:00
const Selection & selection = get_selection ( ) ;
2018-10-09 07:35:19 +00:00
2019-09-19 07:09:11 +00:00
if ( selection . is_wipe_tower ( ) )
return ;
2018-12-05 14:22:03 +00:00
2019-09-19 07:09:11 +00:00
// struct to hold selected ModelVolumes by their indices
struct SelectedVolume
{
int object_idx ;
int volume_idx ;
2019-09-06 11:49:15 +00:00
2019-09-19 07:09:11 +00:00
// operators needed by std::algorithms
bool operator < ( const SelectedVolume & other ) const { return ( object_idx < other . object_idx ) | | ( ( object_idx = = other . object_idx ) & & ( volume_idx < other . volume_idx ) ) ; }
bool operator = = ( const SelectedVolume & other ) const { return ( object_idx = = other . object_idx ) & & ( volume_idx = = other . volume_idx ) ; }
} ;
std : : vector < SelectedVolume > selected_volumes ;
2019-09-11 13:31:30 +00:00
2019-09-19 07:09:11 +00:00
// collects selected ModelVolumes
const std : : set < unsigned int > & selected_volumes_idxs = selection . get_volume_idxs ( ) ;
for ( unsigned int idx : selected_volumes_idxs )
2019-09-06 12:36:47 +00:00
{
2019-09-19 07:09:11 +00:00
const GLVolume * v = selection . get_volume ( idx ) ;
int v_idx = v - > volume_idx ( ) ;
2019-11-25 13:42:36 +00:00
if ( v_idx > = 0 )
{
int o_idx = v - > object_idx ( ) ;
if ( ( 0 < = o_idx ) & & ( o_idx < ( int ) model . objects . size ( ) ) )
selected_volumes . push_back ( { o_idx , v_idx } ) ;
}
2019-09-06 12:36:47 +00:00
}
2019-09-19 07:09:11 +00:00
std : : sort ( selected_volumes . begin ( ) , selected_volumes . end ( ) ) ;
selected_volumes . erase ( std : : unique ( selected_volumes . begin ( ) , selected_volumes . end ( ) ) , selected_volumes . end ( ) ) ;
2018-12-05 14:22:03 +00:00
2019-09-19 07:09:11 +00:00
// collects paths of files to load
std : : vector < fs : : path > input_paths ;
2019-12-10 13:42:28 +00:00
std : : vector < fs : : path > missing_input_paths ;
2019-09-19 07:09:11 +00:00
for ( const SelectedVolume & v : selected_volumes )
2019-09-11 13:02:57 +00:00
{
2019-12-10 13:42:28 +00:00
const ModelObject * object = model . objects [ v . object_idx ] ;
const ModelVolume * volume = object - > volumes [ v . volume_idx ] ;
if ( ! volume - > source . input_file . empty ( ) )
{
if ( fs : : exists ( volume - > source . input_file ) )
input_paths . push_back ( volume - > source . input_file ) ;
else
missing_input_paths . push_back ( volume - > source . input_file ) ;
}
2020-02-26 07:56:05 +00:00
else if ( ! object - > input_file . empty ( ) & & volume - > is_model_part ( ) & & ! volume - > name . empty ( ) )
2020-01-21 13:07:13 +00:00
missing_input_paths . push_back ( volume - > name ) ;
2019-09-19 07:09:11 +00:00
}
2019-12-10 13:42:28 +00:00
std : : sort ( missing_input_paths . begin ( ) , missing_input_paths . end ( ) ) ;
missing_input_paths . erase ( std : : unique ( missing_input_paths . begin ( ) , missing_input_paths . end ( ) ) , missing_input_paths . end ( ) ) ;
while ( ! missing_input_paths . empty ( ) )
{
// ask user to select the missing file
2019-12-19 08:02:50 +00:00
fs : : path search = missing_input_paths . back ( ) ;
2020-04-01 07:48:56 +00:00
wxString title = _L ( " Please select the file to reload " ) ;
2019-12-18 14:32:25 +00:00
# if defined(__APPLE__)
2020-01-21 13:07:13 +00:00
title + = " ( " + from_u8 ( search . filename ( ) . string ( ) ) + " ) " ;
2019-12-18 14:32:25 +00:00
# endif // __APPLE__
2020-01-21 13:07:13 +00:00
title + = " : " ;
2019-12-19 08:02:50 +00:00
wxFileDialog dialog ( q , title , " " , from_u8 ( search . filename ( ) . string ( ) ) , file_wildcards ( FT_MODEL ) , wxFD_OPEN | wxFD_FILE_MUST_EXIST ) ;
2019-12-10 13:42:28 +00:00
if ( dialog . ShowModal ( ) ! = wxID_OK )
return ;
std : : string sel_filename_path = dialog . GetPath ( ) . ToUTF8 ( ) . data ( ) ;
std : : string sel_filename = fs : : path ( sel_filename_path ) . filename ( ) . string ( ) ;
2019-12-19 08:02:50 +00:00
if ( boost : : algorithm : : iequals ( search . filename ( ) . string ( ) , sel_filename ) )
2019-12-10 13:42:28 +00:00
{
input_paths . push_back ( sel_filename_path ) ;
missing_input_paths . pop_back ( ) ;
2019-12-16 09:24:08 +00:00
fs : : path sel_path = fs : : path ( sel_filename_path ) . remove_filename ( ) . string ( ) ;
2019-12-10 13:42:28 +00:00
std : : vector < fs : : path > : : iterator it = missing_input_paths . begin ( ) ;
while ( it ! = missing_input_paths . end ( ) )
{
// try to use the path of the selected file with all remaining missing files
2019-12-16 09:24:08 +00:00
fs : : path repathed_filename = sel_path ;
repathed_filename / = it - > filename ( ) ;
2019-12-10 13:42:28 +00:00
if ( fs : : exists ( repathed_filename ) )
{
2019-12-16 09:24:08 +00:00
input_paths . push_back ( repathed_filename . string ( ) ) ;
2019-12-10 13:42:28 +00:00
it = missing_input_paths . erase ( it ) ;
}
else
+ + it ;
}
}
2019-12-16 09:24:08 +00:00
else
{
2020-04-01 07:48:56 +00:00
wxString message = _L ( " It is not allowed to change the file to reload " ) + " ( " + from_u8 ( search . filename ( ) . string ( ) ) + " ). \n " + _L ( " Do you want to retry " ) + " ? " ;
2019-12-16 09:24:08 +00:00
wxMessageDialog dlg ( q , message , wxMessageBoxCaptionStr , wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION ) ;
if ( dlg . ShowModal ( ) ! = wxID_YES )
return ;
}
2019-09-19 07:09:11 +00:00
}
2019-12-10 13:42:28 +00:00
2019-09-19 07:09:11 +00:00
std : : sort ( input_paths . begin ( ) , input_paths . end ( ) ) ;
input_paths . erase ( std : : unique ( input_paths . begin ( ) , input_paths . end ( ) ) , input_paths . end ( ) ) ;
2019-09-10 09:16:59 +00:00
2020-01-21 13:07:13 +00:00
std : : vector < wxString > fail_list ;
2019-09-19 07:09:11 +00:00
// load one file at a time
for ( size_t i = 0 ; i < input_paths . size ( ) ; + + i )
{
const auto & path = input_paths [ i ] . string ( ) ;
2020-01-21 13:07:13 +00:00
wxBusyCursor wait ;
2020-04-01 07:48:56 +00:00
wxBusyInfo info ( _L ( " Reload from: " ) + " " + from_u8 ( path ) , q - > get_current_canvas3D ( ) - > get_wxglcanvas ( ) ) ;
2020-01-21 13:07:13 +00:00
2019-09-19 07:09:11 +00:00
Model new_model ;
try
2019-09-11 13:02:57 +00:00
{
2019-09-19 07:09:11 +00:00
new_model = Model : : read_from_file ( path , nullptr , true , false ) ;
for ( ModelObject * model_object : new_model . objects )
{
model_object - > center_around_origin ( ) ;
model_object - > ensure_on_bed ( ) ;
}
2018-12-05 14:22:03 +00:00
}
2019-09-19 07:09:11 +00:00
catch ( std : : exception & )
2019-09-11 13:02:57 +00:00
{
2019-09-19 07:09:11 +00:00
// error while loading
return ;
2018-12-05 14:22:03 +00:00
}
2019-09-19 07:09:11 +00:00
// update the selected volumes whose source is the current file
2020-01-21 13:07:13 +00:00
for ( const SelectedVolume & sel_v : selected_volumes )
2019-09-10 09:16:59 +00:00
{
2020-01-21 13:07:13 +00:00
ModelObject * old_model_object = model . objects [ sel_v . object_idx ] ;
ModelVolume * old_volume = old_model_object - > volumes [ sel_v . volume_idx ] ;
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 ( ) ) ;
bool has_name = ! old_volume - > name . empty ( ) & & boost : : algorithm : : iequals ( old_volume - > name , fs : : path ( path ) . filename ( ) . string ( ) ) ;
if ( has_source | | has_name )
2019-09-10 09:16:59 +00:00
{
2020-01-21 13:07:13 +00:00
int new_volume_idx = - 1 ;
int new_object_idx = - 1 ;
if ( has_source )
{
// take idxs from source
new_volume_idx = old_volume - > source . volume_idx ;
new_object_idx = old_volume - > source . object_idx ;
}
else
{
// take idxs from the 1st matching volume
for ( size_t o = 0 ; o < new_model . objects . size ( ) ; + + o )
{
ModelObject * obj = new_model . objects [ o ] ;
bool found = false ;
for ( size_t v = 0 ; v < obj - > volumes . size ( ) ; + + v )
{
if ( obj - > volumes [ v ] - > name = = old_volume - > name )
{
new_volume_idx = ( int ) v ;
new_object_idx = ( int ) o ;
found = true ;
break ;
}
}
if ( found )
break ;
}
}
if ( ( new_object_idx < 0 ) & & ( ( int ) new_model . objects . size ( ) < = new_object_idx ) )
{
fail_list . push_back ( from_u8 ( has_source ? old_volume - > source . input_file : old_volume - > name ) ) ;
continue ;
}
2019-12-10 13:42:28 +00:00
ModelObject * new_model_object = new_model . objects [ new_object_idx ] ;
2020-01-21 13:07:13 +00:00
if ( ( new_volume_idx < 0 ) & & ( ( int ) new_model . objects . size ( ) < = new_volume_idx ) )
{
fail_list . push_back ( from_u8 ( has_source ? old_volume - > source . input_file : old_volume - > name ) ) ;
continue ;
}
2019-12-10 13:42:28 +00:00
if ( new_volume_idx < ( int ) new_model_object - > volumes . size ( ) )
2019-09-19 07:09:11 +00:00
{
2019-12-10 13:42:28 +00:00
old_model_object - > add_volume ( * new_model_object - > volumes [ new_volume_idx ] ) ;
ModelVolume * new_volume = old_model_object - > volumes . back ( ) ;
new_volume - > set_new_unique_id ( ) ;
new_volume - > config . apply ( old_volume - > config ) ;
new_volume - > set_type ( old_volume - > type ( ) ) ;
new_volume - > set_material_id ( old_volume - > material_id ( ) ) ;
2019-12-20 11:11:58 +00:00
new_volume - > set_transformation ( old_volume - > get_transformation ( ) * old_volume - > source . transform ) ;
2019-12-10 13:42:28 +00:00
new_volume - > translate ( new_volume - > get_transformation ( ) . get_matrix ( true ) * ( new_volume - > source . mesh_offset - old_volume - > source . mesh_offset ) ) ;
2020-01-21 13:07:13 +00:00
std : : swap ( old_model_object - > volumes [ sel_v . volume_idx ] , old_model_object - > volumes . back ( ) ) ;
2019-12-10 13:42:28 +00:00
old_model_object - > delete_volume ( old_model_object - > volumes . size ( ) - 1 ) ;
2019-12-20 15:02:56 +00:00
old_model_object - > ensure_on_bed ( ) ;
2020-05-12 13:52:33 +00:00
2020-05-13 12:53:05 +00:00
sla : : reproject_points_and_holes ( old_model_object ) ;
2019-09-19 07:09:11 +00:00
}
2019-09-10 09:16:59 +00:00
}
}
2018-12-05 14:22:03 +00:00
}
2020-01-21 13:07:13 +00:00
if ( ! fail_list . empty ( ) )
{
2020-04-01 07:48:56 +00:00
wxString message = _L ( " Unable to reload: " ) + " \n " ;
2020-01-21 13:07:13 +00:00
for ( const wxString & s : fail_list )
{
message + = s + " \n " ;
}
2020-04-01 07:48:56 +00:00
wxMessageDialog dlg ( q , message , _L ( " Error during reload " ) , wxOK | wxOK_DEFAULT | wxICON_WARNING ) ;
2020-01-21 13:07:13 +00:00
dlg . ShowModal ( ) ;
}
2019-09-19 07:09:11 +00:00
// update 3D scene
update ( ) ;
2019-09-06 11:11:20 +00:00
2019-09-10 09:16:59 +00:00
// new GLVolumes have been created at this point, so update their printable state
for ( size_t i = 0 ; i < model . objects . size ( ) ; + + i )
{
view3D - > get_canvas3d ( ) - > update_instance_printable_state_for_object ( i ) ;
}
2018-10-09 07:35:19 +00:00
}
2020-01-31 11:15:04 +00:00
void Plater : : priv : : reload_all_from_disk ( )
{
2020-02-03 14:47:09 +00:00
if ( model . objects . empty ( ) )
return ;
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( q , _L ( " Reload all from disk " ) ) ;
2020-01-31 11:15:04 +00:00
Plater : : SuppressSnapshots suppress ( q ) ;
Selection & selection = get_selection ( ) ;
Selection : : IndicesList curr_idxs = selection . get_volume_idxs ( ) ;
// reload from disk uses selection
select_all ( ) ;
reload_from_disk ( ) ;
// restore previous selection
selection . clear ( ) ;
for ( unsigned int idx : curr_idxs )
{
selection . add ( idx , false ) ;
}
}
2019-01-30 15:27:07 +00:00
void Plater : : priv : : fix_through_netfabb ( const int obj_idx , const int vol_idx /* = -1*/ )
2018-10-09 07:35:19 +00:00
{
2018-11-07 12:40:24 +00:00
if ( obj_idx < 0 )
return ;
2019-07-04 15:33:19 +00:00
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( q , _L ( " Fix Throught NetFabb " ) ) ;
2019-07-04 15:33:19 +00:00
2019-02-03 21:14:34 +00:00
fix_model_by_win10_sdk_gui ( * model . objects [ obj_idx ] , vol_idx ) ;
2020-05-13 12:53:05 +00:00
sla : : reproject_points_and_holes ( model . objects [ obj_idx ] ) ;
2019-02-03 21:14:34 +00:00
this - > update ( ) ;
2019-05-08 08:37:45 +00:00
this - > object_list_changed ( ) ;
2019-02-03 21:14:34 +00:00
this - > schedule_background_process ( ) ;
2018-10-09 07:35:19 +00:00
}
2018-12-04 12:55:25 +00:00
void Plater : : priv : : set_current_panel ( wxPanel * panel )
{
if ( std : : find ( panels . begin ( ) , panels . end ( ) , panel ) = = panels . end ( ) )
return ;
2019-03-08 07:29:54 +00:00
# ifdef __WXMAC__
2019-03-07 14:44:25 +00:00
bool force_render = ( current_panel ! = nullptr ) ;
2019-03-08 07:29:54 +00:00
# endif // __WXMAC__
2019-03-07 14:44:25 +00:00
2018-12-04 12:55:25 +00:00
if ( current_panel = = panel )
return ;
current_panel = panel ;
2018-12-06 12:44:38 +00:00
// to reduce flickering when changing view, first set as visible the new current panel
2018-12-04 12:55:25 +00:00
for ( wxPanel * p : panels )
{
2018-12-06 12:44:38 +00:00
if ( p = = current_panel )
2019-03-07 14:44:25 +00:00
{
2019-03-08 07:29:54 +00:00
# ifdef __WXMAC__
// On Mac we need also to force a render to avoid flickering when changing view
2019-03-07 14:44:25 +00:00
if ( force_render )
{
if ( p = = view3D )
dynamic_cast < View3D * > ( p ) - > get_canvas3d ( ) - > render ( ) ;
else if ( p = = preview )
dynamic_cast < Preview * > ( p ) - > get_canvas3d ( ) - > render ( ) ;
}
2019-03-08 07:29:54 +00:00
# endif // __WXMAC__
2018-12-06 12:44:38 +00:00
p - > Show ( ) ;
2019-03-07 14:44:25 +00:00
}
2018-12-06 12:44:38 +00:00
}
// then set to invisible the other
for ( wxPanel * p : panels )
{
if ( p ! = current_panel )
p - > Hide ( ) ;
2018-12-04 12:55:25 +00:00
}
panel_sizer - > Layout ( ) ;
if ( current_panel = = view3D )
{
if ( view3D - > is_reload_delayed ( ) )
{
// Delayed loading of the 3D scene.
if ( this - > printer_technology = = ptSLA )
{
// Update the SLAPrint from the current Model, so that the reload_scene()
// pulls the correct data.
2018-12-22 09:02:42 +00:00
this - > update_restart_background_process ( true , false ) ;
} else
view3D - > reload_scene ( true ) ;
2018-12-04 12:55:25 +00:00
}
2019-09-27 12:52:19 +00:00
2018-12-04 12:55:25 +00:00
// sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
view3D - > set_as_dirty ( ) ;
2018-12-21 09:43:22 +00:00
view_toolbar . select_item ( " 3D " ) ;
2018-12-04 12:55:25 +00:00
}
else if ( current_panel = = preview )
{
2019-08-29 13:38:21 +00:00
// see: Plater::priv::object_list_changed()
// FIXME: it may be better to have a single function making this check and let it be called wherever needed
bool export_in_progress = this - > background_process . is_export_scheduled ( ) ;
2020-05-23 22:01:34 +00:00
bool model_fits = view3D - > check_volumes_outside_state ( ) ! = ModelInstancePVS_Partly_Outside ;
2019-08-29 13:38:21 +00:00
if ( ! model . objects . empty ( ) & & ! export_in_progress & & model_fits )
this - > q - > reslice ( ) ;
2019-02-28 14:27:03 +00:00
// keeps current gcode preview, if any
2019-03-18 13:07:55 +00:00
preview - > reload_print ( true ) ;
2019-09-27 12:52:19 +00:00
2020-01-03 10:41:29 +00:00
preview - > set_as_dirty ( ) ;
2018-12-21 09:43:22 +00:00
view_toolbar . select_item ( " Preview " ) ;
2018-12-04 12:55:25 +00:00
}
2018-12-21 10:39:37 +00:00
current_panel - > SetFocusFromKbd ( ) ;
2018-12-04 12:55:25 +00:00
}
2018-09-17 10:15:11 +00:00
void Plater : : priv : : on_select_preset ( wxCommandEvent & evt )
{
auto preset_type = static_cast < Preset : : Type > ( evt . GetInt ( ) ) ;
2020-06-16 10:57:49 +00:00
auto * combo = static_cast < PlaterPresetComboBox * > ( evt . GetEventObject ( ) ) ;
2018-09-17 10:15:11 +00:00
2020-03-23 21:47:35 +00:00
// see https://github.com/prusa3d/PrusaSlicer/issues/3889
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender"),
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
// So, use GetSelection() from event parameter
// But in this function we couldn't use evt.GetSelection(), because m_commandInt is used for preset_type
// Thus, get selection in this way:
int selection = combo - > FindString ( evt . GetString ( ) , true ) ;
2018-10-10 11:53:45 +00:00
auto idx = combo - > get_extruder_idx ( ) ;
2018-10-09 10:41:05 +00:00
2019-08-06 16:16:02 +00:00
//! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox,
2018-10-15 09:39:48 +00:00
//! but the OSX version derived from wxOwnerDrawnCombo.
2019-08-06 16:16:02 +00:00
//! So, to get selected string we do
//! combo->GetString(combo->GetSelection())
//! instead of
//! combo->GetStringSelection().ToUTF8().data());
2018-10-15 09:39:48 +00:00
2020-03-16 08:57:20 +00:00
const std : : string preset_name = wxGetApp ( ) . preset_bundle - > get_preset_name_by_alias ( preset_type ,
2020-03-23 21:47:35 +00:00
Preset : : remove_suffix_modified ( combo - > GetString ( selection ) . ToUTF8 ( ) . data ( ) ) ) ;
2018-10-15 09:39:48 +00:00
2018-09-17 10:15:11 +00:00
if ( preset_type = = Preset : : TYPE_FILAMENT ) {
2019-11-29 10:02:30 +00:00
wxGetApp ( ) . preset_bundle - > set_filament_preset ( idx , preset_name ) ;
2018-09-17 10:15:11 +00:00
}
// TODO: ?
2018-10-09 10:41:05 +00:00
if ( preset_type = = Preset : : TYPE_FILAMENT & & sidebar - > is_multifilament ( ) ) {
2019-12-03 03:48:01 +00:00
// Only update the plater UI for the 2nd and other filaments.
2020-06-16 10:57:49 +00:00
combo - > update ( ) ;
2019-08-06 16:16:02 +00:00
}
2018-10-10 11:53:45 +00:00
else {
2019-03-13 12:13:18 +00:00
wxWindowUpdateLocker noUpdates ( sidebar - > presets_panel ( ) ) ;
2019-11-29 10:02:30 +00:00
wxGetApp ( ) . get_tab ( preset_type ) - > select_preset ( preset_name ) ;
2018-09-17 10:15:11 +00:00
}
2018-10-15 09:39:48 +00:00
// update plater with new config
2020-04-23 16:47:51 +00:00
q - > on_config_change ( wxGetApp ( ) . preset_bundle - > full_config ( ) ) ;
2020-03-13 21:37:18 +00:00
if ( preset_type = = Preset : : TYPE_PRINTER ) {
2019-06-10 08:48:43 +00:00
/* Settings list can be changed after printer preset changing, so
* update all settings items for all item had it .
2019-08-06 16:16:02 +00:00
* Furthermore , Layers editing is implemented only for FFF printers
2019-06-10 08:48:43 +00:00
* and for SLA presets they should be deleted
*/
wxGetApp ( ) . obj_list ( ) - > update_object_list_by_printer_technology ( ) ;
2020-03-13 21:37:18 +00:00
}
2018-09-17 10:15:11 +00:00
}
2018-11-20 12:22:26 +00:00
void Plater : : priv : : on_slicing_update ( SlicingStatusEvent & evt )
2018-10-09 07:35:19 +00:00
{
2019-03-14 14:11:27 +00:00
if ( evt . status . percent > = - 1 ) {
2019-06-18 14:24:30 +00:00
if ( m_ui_jobs . is_any_running ( ) ) {
2019-04-17 12:56:00 +00:00
// Avoid a race condition
return ;
}
2019-03-14 14:11:27 +00:00
this - > statusbar ( ) - > set_progress ( evt . status . percent ) ;
2019-05-04 00:07:07 +00:00
this - > statusbar ( ) - > set_status_text ( _ ( evt . status . text ) + wxString : : FromUTF8 ( " … " ) ) ;
2019-03-14 14:11:27 +00:00
}
2019-09-25 10:06:38 +00:00
if ( evt . status . flags & ( PrintBase : : SlicingStatus : : RELOAD_SCENE | PrintBase : : SlicingStatus : : RELOAD_SLA_SUPPORT_POINTS ) ) {
2018-11-20 12:22:26 +00:00
switch ( this - > printer_technology ) {
case ptFFF :
2018-12-06 14:40:41 +00:00
this - > update_fff_scene ( ) ;
2018-11-20 12:22:26 +00:00
break ;
case ptSLA :
2019-04-10 11:36:15 +00:00
// If RELOAD_SLA_SUPPORT_POINTS, then the SLA gizmo is updated (reload_scene calls update_gizmos_data)
2018-12-04 12:55:25 +00:00
if ( view3D - > is_dragging ( ) )
2018-11-23 11:47:32 +00:00
delayed_scene_refresh = true ;
else
this - > update_sla_scene ( ) ;
2018-11-20 12:22:26 +00:00
break ;
2019-09-03 08:27:16 +00:00
default : break ;
2018-11-20 12:22:26 +00:00
}
2019-04-10 11:36:15 +00:00
} else if ( evt . status . flags & PrintBase : : SlicingStatus : : RELOAD_SLA_PREVIEW ) {
// Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
2019-03-14 14:11:27 +00:00
this - > preview - > reload_print ( ) ;
}
2018-10-09 07:35:19 +00:00
}
2018-11-20 12:22:26 +00:00
void Plater : : priv : : on_slicing_completed ( wxCommandEvent & )
2018-09-17 10:15:11 +00:00
{
2018-11-20 12:22:26 +00:00
switch ( this - > printer_technology ) {
case ptFFF :
2018-12-06 14:40:41 +00:00
this - > update_fff_scene ( ) ;
2018-11-20 12:22:26 +00:00
break ;
case ptSLA :
2018-12-04 12:55:25 +00:00
if ( view3D - > is_dragging ( ) )
2018-11-23 11:47:32 +00:00
delayed_scene_refresh = true ;
else
this - > update_sla_scene ( ) ;
2018-11-20 12:22:26 +00:00
break ;
2019-09-03 08:27:16 +00:00
default : break ;
2018-11-20 12:22:26 +00:00
}
2018-09-17 10:15:11 +00:00
}
2018-10-23 13:27:31 +00:00
void Plater : : priv : : on_process_completed ( wxCommandEvent & evt )
2018-09-17 10:15:11 +00:00
{
2018-10-18 16:06:40 +00:00
// Stop the background task, wait until the thread goes into the "Idle" state.
// At this point of time the thread should be either finished or canceled,
// so the following call just confirms, that the produced data were consumed.
this - > background_process . stop ( ) ;
2018-10-23 13:27:31 +00:00
this - > statusbar ( ) - > reset_cancel_callback ( ) ;
this - > statusbar ( ) - > stop_busy ( ) ;
2019-08-06 16:16:02 +00:00
2019-03-11 08:48:24 +00:00
const bool canceled = evt . GetInt ( ) < 0 ;
2019-08-06 16:16:02 +00:00
const bool error = evt . GetInt ( ) = = 0 ;
2019-03-11 08:48:24 +00:00
const bool success = evt . GetInt ( ) > 0 ;
2018-10-23 13:27:31 +00:00
// Reset the "export G-code path" name, so that the automatic background processing will be enabled again.
this - > background_process . reset_export ( ) ;
2019-03-11 08:48:24 +00:00
if ( error ) {
2018-10-23 13:27:31 +00:00
wxString message = evt . GetString ( ) ;
if ( message . IsEmpty ( ) )
2020-04-01 07:48:56 +00:00
message = _L ( " Export failed " ) ;
2020-03-12 15:05:39 +00:00
if ( q - > m_tracking_popup_menu )
// We don't want to pop-up a message box when tracking a pop-up menu.
// We postpone the error message instead.
q - > m_tracking_popup_menu_error_message = message ;
else
show_error ( q , message ) ;
2018-10-23 13:27:31 +00:00
this - > statusbar ( ) - > set_status_text ( message ) ;
2018-10-18 16:06:40 +00:00
}
2019-08-06 16:16:02 +00:00
if ( canceled )
2020-04-01 07:48:56 +00:00
this - > statusbar ( ) - > set_status_text ( _L ( " Cancelled " ) ) ;
2018-10-18 16:06:40 +00:00
2018-10-31 11:26:57 +00:00
this - > sidebar - > show_sliced_info_sizer ( success ) ;
2018-10-18 16:06:40 +00:00
2018-12-04 10:14:39 +00:00
// This updates the "Slice now", "Export G-code", "Arrange" buttons status.
// Namely, it refreshes the "Out of print bed" property of all the ModelObjects, and it enables
// the "Slice now" and "Export G-code" buttons based on their "out of bed" status.
this - > object_list_changed ( ) ;
2019-08-06 16:16:02 +00:00
2018-10-18 16:06:40 +00:00
// refresh preview
2018-11-13 16:45:44 +00:00
switch ( this - > printer_technology ) {
case ptFFF :
2018-12-06 14:40:41 +00:00
this - > update_fff_scene ( ) ;
2018-11-13 16:45:44 +00:00
break ;
case ptSLA :
2018-12-04 12:55:25 +00:00
if ( view3D - > is_dragging ( ) )
2018-11-23 11:47:32 +00:00
delayed_scene_refresh = true ;
else
this - > update_sla_scene ( ) ;
2018-11-13 16:45:44 +00:00
break ;
2019-09-03 08:27:16 +00:00
default : break ;
2018-11-12 16:35:57 +00:00
}
2019-12-13 17:02:25 +00:00
2019-03-01 10:00:34 +00:00
2019-03-08 14:40:28 +00:00
if ( canceled ) {
if ( wxGetApp ( ) . get_mode ( ) = = comSimple )
sidebar - > set_btn_label ( ActionButtonType : : abReslice , " Slice now " ) ;
show_action_buttons ( true ) ;
}
2020-03-06 14:10:58 +00:00
else if ( this - > writing_to_removable_device | | wxGetApp ( ) . get_mode ( ) = = comSimple )
show_action_buttons ( false ) ;
this - > writing_to_removable_device = false ;
2018-09-17 10:15:11 +00:00
}
void Plater : : priv : : on_layer_editing_toggled ( bool enable )
{
2018-12-04 12:55:25 +00:00
view3D - > enable_layers_editing ( enable ) ;
view3D - > set_as_dirty ( ) ;
2018-09-17 10:15:11 +00:00
}
2018-10-03 09:34:39 +00:00
void Plater : : priv : : on_action_add ( SimpleEvent & )
2018-09-17 10:15:11 +00:00
{
2018-10-17 10:17:25 +00:00
if ( q ! = nullptr )
2018-11-15 14:27:39 +00:00
q - > add_model ( ) ;
2018-09-17 10:15:11 +00:00
}
2018-10-24 10:55:38 +00:00
void Plater : : priv : : on_action_split_objects ( SimpleEvent & )
2018-10-04 09:12:55 +00:00
{
2018-10-19 13:27:19 +00:00
split_object ( ) ;
2018-10-04 09:12:55 +00:00
}
2018-10-24 10:55:38 +00:00
void Plater : : priv : : on_action_split_volumes ( SimpleEvent & )
{
split_volume ( ) ;
}
2018-10-04 09:12:55 +00:00
void Plater : : priv : : on_action_layersediting ( SimpleEvent & )
{
2019-03-14 12:54:05 +00:00
view3D - > enable_layers_editing ( ! view3D - > is_layers_editing_enabled ( ) ) ;
2018-10-04 09:12:55 +00:00
}
2018-10-16 14:04:19 +00:00
void Plater : : priv : : on_object_select ( SimpleEvent & evt )
{
wxGetApp ( ) . obj_list ( ) - > update_selections ( ) ;
2018-12-17 14:44:30 +00:00
selection_changed ( ) ;
2018-10-16 14:04:19 +00:00
}
2018-10-09 15:14:59 +00:00
2019-09-20 07:57:27 +00:00
void Plater : : priv : : on_right_click ( RBtnEvent & evt )
2018-10-08 17:55:30 +00:00
{
2018-10-17 10:17:25 +00:00
int obj_idx = get_selected_object_idx ( ) ;
2019-09-20 07:57:27 +00:00
wxMenu * menu = nullptr ;
2019-12-11 15:07:00 +00:00
if ( obj_idx = = - 1 ) // no one or several object are selected
{
if ( evt . data . second ) // right button was clicked on empty space
menu = & default_menu ;
else
2019-12-18 08:06:21 +00:00
{
sidebar - > obj_list ( ) - > show_multi_selection_menu ( ) ;
2019-12-11 15:07:00 +00:00
return ;
2019-12-18 08:06:21 +00:00
}
2019-12-11 15:07:00 +00:00
}
2019-09-20 07:57:27 +00:00
else
{
// If in 3DScene is(are) selected volume(s), but right button was clicked on empty space
if ( evt . data . second )
return ;
2018-10-17 10:17:25 +00:00
2019-12-11 15:07:00 +00:00
if ( printer_technology = = ptSLA )
menu = & sla_object_menu ;
else
{
// show "Object menu" for each one or several FullInstance instead of FullObject
const bool is_some_full_instances = get_selection ( ) . is_single_full_instance ( ) | |
get_selection ( ) . is_single_full_object ( ) | |
get_selection ( ) . is_multiple_full_instance ( ) ;
menu = is_some_full_instances ? & object_menu : & part_menu ;
}
2018-12-07 16:50:48 +00:00
2019-09-20 07:57:27 +00:00
sidebar - > obj_list ( ) - > append_menu_item_settings ( menu ) ;
2018-12-07 16:50:48 +00:00
2019-09-20 07:57:27 +00:00
if ( printer_technology ! = ptSLA )
sidebar - > obj_list ( ) - > append_menu_item_change_extruder ( menu ) ;
2019-03-28 15:28:34 +00:00
2019-09-20 07:57:27 +00:00
if ( menu ! = & part_menu )
{
/* Remove/Prepend "increase/decrease instances" menu items according to the view mode.
* Suppress to show those items for a Simple mode
*/
const MenuIdentifier id = printer_technology = = ptSLA ? miObjectSLA : miObjectFFF ;
if ( wxGetApp ( ) . get_mode ( ) = = comSimple ) {
2020-04-01 07:48:56 +00:00
if ( menu - > FindItem ( _L ( " Add instance " ) ) ! = wxNOT_FOUND )
2019-09-20 07:57:27 +00:00
{
/* Detach an items from the menu, but don't delete them
* so that they can be added back later
* ( after switching to the Advanced / Expert mode )
*/
menu - > Remove ( items_increase [ id ] ) ;
menu - > Remove ( items_decrease [ id ] ) ;
menu - > Remove ( items_set_number_of_copies [ id ] ) ;
}
2019-03-28 15:28:34 +00:00
}
2019-09-20 07:57:27 +00:00
else {
2020-04-01 07:48:56 +00:00
if ( menu - > FindItem ( _L ( " Add instance " ) ) = = wxNOT_FOUND )
2019-09-20 07:57:27 +00:00
{
// Prepend items to the menu, if those aren't not there
menu - > Prepend ( items_set_number_of_copies [ id ] ) ;
menu - > Prepend ( items_decrease [ id ] ) ;
menu - > Prepend ( items_increase [ id ] ) ;
}
2019-03-28 15:28:34 +00:00
}
2019-03-19 08:51:50 +00:00
}
}
2019-09-20 07:57:27 +00:00
if ( q ! = nullptr & & menu ) {
2019-02-25 09:35:16 +00:00
# ifdef __linux__
// For some reason on Linux the menu isn't displayed if position is specified
// (even though the position is sane).
q - > PopupMenu ( menu ) ;
# else
2019-09-20 07:57:27 +00:00
q - > PopupMenu ( menu , ( int ) evt . data . first . x ( ) , ( int ) evt . data . first . y ( ) ) ;
2019-02-25 09:35:16 +00:00
# endif
}
2018-10-08 17:55:30 +00:00
}
2018-10-09 15:14:59 +00:00
void Plater : : priv : : on_wipetower_moved ( Vec3dEvent & evt )
2018-10-08 17:55:30 +00:00
{
2018-10-09 15:14:59 +00:00
DynamicPrintConfig cfg ;
cfg . opt < ConfigOptionFloat > ( " wipe_tower_x " , true ) - > value = evt . data ( 0 ) ;
cfg . opt < ConfigOptionFloat > ( " wipe_tower_y " , true ) - > value = evt . data ( 1 ) ;
2018-11-19 12:17:14 +00:00
wxGetApp ( ) . get_tab ( Preset : : TYPE_PRINT ) - > load_config ( cfg ) ;
2018-10-08 17:55:30 +00:00
}
2019-04-26 13:34:26 +00:00
void Plater : : priv : : on_wipetower_rotated ( Vec3dEvent & evt )
{
DynamicPrintConfig cfg ;
cfg . opt < ConfigOptionFloat > ( " wipe_tower_x " , true ) - > value = evt . data ( 0 ) ;
cfg . opt < ConfigOptionFloat > ( " wipe_tower_y " , true ) - > value = evt . data ( 1 ) ;
cfg . opt < ConfigOptionFloat > ( " wipe_tower_rotation_angle " , true ) - > value = Geometry : : rad2deg ( evt . data ( 2 ) ) ;
wxGetApp ( ) . get_tab ( Preset : : TYPE_PRINT ) - > load_config ( cfg ) ;
}
2018-10-08 17:55:30 +00:00
void Plater : : priv : : on_update_geometry ( Vec3dsEvent < 2 > & )
{
// TODO
}
2019-08-06 16:16:02 +00:00
// Update the scene from the background processing,
2018-11-23 11:47:32 +00:00
// if the update message was received during mouse manipulation.
void Plater : : priv : : on_3dcanvas_mouse_dragging_finished ( SimpleEvent & )
{
if ( this - > delayed_scene_refresh ) {
this - > delayed_scene_refresh = false ;
this - > update_sla_scene ( ) ;
}
}
2018-10-17 10:17:25 +00:00
bool Plater : : priv : : init_object_menu ( )
{
2019-03-19 08:51:50 +00:00
items_increase . reserve ( 2 ) ;
items_decrease . reserve ( 2 ) ;
items_set_number_of_copies . reserve ( 2 ) ;
2018-12-07 16:50:48 +00:00
init_common_menu ( & object_menu ) ;
complit_init_object_menu ( ) ;
init_common_menu ( & sla_object_menu ) ;
complit_init_sla_object_menu ( ) ;
init_common_menu ( & part_menu , true ) ;
complit_init_part_menu ( ) ;
2019-09-20 07:57:27 +00:00
sidebar - > obj_list ( ) - > create_default_popupmenu ( & default_menu ) ;
2018-12-07 16:50:48 +00:00
return true ;
}
2019-11-28 13:18:24 +00:00
void Plater : : priv : : generate_thumbnail ( ThumbnailData & data , unsigned int w , unsigned int h , bool printable_only , bool parts_only , bool show_bed , bool transparent_background )
2019-10-23 11:31:24 +00:00
{
2019-11-28 13:18:24 +00:00
view3D - > get_canvas3d ( ) - > render_thumbnail ( data , w , h , printable_only , parts_only , show_bed , transparent_background ) ;
2019-10-23 11:31:24 +00:00
}
2019-11-22 11:39:03 +00:00
2019-11-28 13:18:24 +00:00
void Plater : : priv : : generate_thumbnails ( ThumbnailsList & thumbnails , const Vec2ds & sizes , bool printable_only , bool parts_only , bool show_bed , bool transparent_background )
2019-10-23 11:31:24 +00:00
{
2019-11-22 11:39:03 +00:00
thumbnails . clear ( ) ;
for ( const Vec2d & size : sizes )
{
thumbnails . push_back ( ThumbnailData ( ) ) ;
Point isize ( size ) ; // round to ints
2019-11-28 13:18:24 +00:00
generate_thumbnail ( thumbnails . back ( ) , isize . x ( ) , isize . y ( ) , printable_only , parts_only , show_bed , transparent_background ) ;
2019-11-22 11:39:03 +00:00
if ( ! thumbnails . back ( ) . is_valid ( ) )
thumbnails . pop_back ( ) ;
}
2019-10-23 11:31:24 +00:00
}
2019-05-03 07:44:19 +00:00
void Plater : : priv : : msw_rescale_object_menu ( )
{
2019-09-20 07:57:27 +00:00
for ( MenuWithSeparators * menu : { & object_menu , & sla_object_menu , & part_menu , & default_menu } )
2019-05-03 07:44:19 +00:00
msw_rescale_menu ( dynamic_cast < wxMenu * > ( menu ) ) ;
}
2019-05-15 12:09:16 +00:00
wxString Plater : : priv : : get_project_filename ( const wxString & extension ) const
2019-05-14 13:00:24 +00:00
{
2019-05-15 12:55:51 +00:00
return m_project_filename . empty ( ) ? " " : m_project_filename + extension ;
2019-05-14 13:00:24 +00:00
}
void Plater : : priv : : set_project_filename ( const wxString & filename )
{
2019-05-15 12:09:16 +00:00
boost : : filesystem : : path full_path = into_path ( filename ) ;
2019-05-17 14:27:00 +00:00
boost : : filesystem : : path ext = full_path . extension ( ) ;
if ( boost : : iequals ( ext . string ( ) , " .amf " ) ) {
// Remove the first extension.
full_path . replace_extension ( " " ) ;
// It may be ".zip.amf".
if ( boost : : iequals ( full_path . extension ( ) . string ( ) , " .zip " ) )
// Remove the 2nd extension.
full_path . replace_extension ( " " ) ;
} else {
// Remove just one extension.
2019-05-15 12:09:16 +00:00
full_path . replace_extension ( " " ) ;
}
2019-05-15 08:23:02 +00:00
m_project_filename = from_path ( full_path ) ;
2019-05-14 13:00:24 +00:00
wxGetApp ( ) . mainframe - > update_title ( ) ;
2019-07-12 13:36:01 +00:00
if ( ! filename . empty ( ) )
wxGetApp ( ) . mainframe - > add_to_recent_projects ( filename ) ;
2019-05-14 13:00:24 +00:00
}
2018-12-07 16:50:48 +00:00
bool Plater : : priv : : init_common_menu ( wxMenu * menu , const bool is_part /* = false*/ )
{
2019-03-08 16:00:56 +00:00
if ( is_part ) {
2020-04-01 07:48:56 +00:00
append_menu_item ( menu , wxID_ANY , _L ( " Delete " ) + " \t Del " , _L ( " Remove the selected object " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { q - > remove_selected ( ) ; } , " delete " , nullptr , [ this ] ( ) { return can_delete ( ) ; } , q ) ;
2019-04-04 13:13:43 +00:00
2020-04-01 07:48:56 +00:00
append_menu_item ( menu , wxID_ANY , _L ( " Reload from disk " ) , _L ( " Reload the selected volumes from disk " ) ,
2019-09-19 07:09:11 +00:00
[ this ] ( wxCommandEvent & ) { q - > reload_from_disk ( ) ; } , " " , menu , [ this ] ( ) { return can_reload_from_disk ( ) ; } , q ) ;
2019-04-04 13:13:43 +00:00
sidebar - > obj_list ( ) - > append_menu_item_export_stl ( menu ) ;
}
else {
2020-04-01 07:48:56 +00:00
wxMenuItem * item_increase = append_menu_item ( menu , wxID_ANY , _L ( " Add instance " ) + " \t + " , _L ( " Add one more instance of the selected object " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { q - > increase_instances ( ) ; } , " add_copies " , nullptr , [ this ] ( ) { return can_increase_instances ( ) ; } , q ) ;
2020-04-01 07:48:56 +00:00
wxMenuItem * item_decrease = append_menu_item ( menu , wxID_ANY , _L ( " Remove instance " ) + " \t - " , _L ( " Remove one instance of the selected object " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { q - > decrease_instances ( ) ; } , " remove_copies " , nullptr , [ this ] ( ) { return can_decrease_instances ( ) ; } , q ) ;
2020-04-01 07:48:56 +00:00
wxMenuItem * item_set_number_of_copies = append_menu_item ( menu , wxID_ANY , _L ( " Set number of instances " ) + dots , _L ( " Change the number of instances of the selected object " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { q - > set_number_of_copies ( ) ; } , " number_of_copies " , nullptr , [ this ] ( ) { return can_increase_instances ( ) ; } , q ) ;
2019-03-19 08:51:50 +00:00
items_increase . push_back ( item_increase ) ;
items_decrease . push_back ( item_decrease ) ;
items_set_number_of_copies . push_back ( item_set_number_of_copies ) ;
2019-03-08 16:00:56 +00:00
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
2020-04-01 07:48:56 +00:00
append_menu_item ( menu , wxID_ANY , _L ( " Delete " ) + " \t Del " , _L ( " Remove the selected object " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { q - > remove_selected ( ) ; } , " delete " , nullptr , [ this ] ( ) { return can_delete ( ) ; } , q ) ;
2019-01-22 15:40:10 +00:00
menu - > AppendSeparator ( ) ;
2019-05-13 12:27:51 +00:00
sidebar - > obj_list ( ) - > append_menu_item_instance_to_object ( menu , q ) ;
2018-12-07 17:20:22 +00:00
menu - > AppendSeparator ( ) ;
2019-07-31 08:12:13 +00:00
wxMenuItem * menu_item_printable = sidebar - > obj_list ( ) - > append_menu_item_printable ( menu , q ) ;
menu - > AppendSeparator ( ) ;
2020-04-01 07:48:56 +00:00
append_menu_item ( menu , wxID_ANY , _L ( " Reload from disk " ) , _L ( " Reload the selected object from disk " ) ,
2019-09-19 07:09:11 +00:00
[ this ] ( wxCommandEvent & ) { reload_from_disk ( ) ; } , " " , nullptr , [ this ] ( ) { return can_reload_from_disk ( ) ; } , q ) ;
2018-12-07 17:20:22 +00:00
2020-04-01 07:48:56 +00:00
append_menu_item ( menu , wxID_ANY , _L ( " Export as STL " ) + dots , _L ( " Export the selected object as STL file " ) ,
2019-12-11 15:07:00 +00:00
[ this ] ( wxCommandEvent & ) { q - > export_stl ( false , true ) ; } , " " , nullptr ,
[ this ] ( ) {
const Selection & selection = get_selection ( ) ;
return selection . is_single_full_instance ( ) | | selection . is_single_full_object ( ) ;
} , q ) ;
2019-04-04 13:13:43 +00:00
menu - > AppendSeparator ( ) ;
2019-07-31 08:12:13 +00:00
2020-05-20 18:07:31 +00:00
// "Scale to print volume" makes a sense just for whole object
sidebar - > obj_list ( ) - > append_menu_item_scale_selection_to_fit_print_volume ( menu ) ;
2019-07-31 08:12:13 +00:00
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) {
const Selection & selection = get_selection ( ) ;
int instance_idx = selection . get_instance_idx ( ) ;
2019-12-11 15:07:00 +00:00
evt . Enable ( selection . is_single_full_instance ( ) | | selection . is_single_full_object ( ) ) ;
2019-07-31 08:12:13 +00:00
if ( instance_idx ! = - 1 )
2019-07-31 09:01:50 +00:00
{
2019-07-31 08:12:13 +00:00
evt . Check ( model . objects [ selection . get_object_idx ( ) ] - > instances [ instance_idx ] - > printable ) ;
2019-07-31 09:01:50 +00:00
view3D - > set_as_dirty ( ) ;
}
2019-07-31 08:12:13 +00:00
} , menu_item_printable - > GetId ( ) ) ;
2018-12-07 16:50:48 +00:00
}
2018-10-17 12:26:13 +00:00
2020-05-20 18:07:31 +00:00
sidebar - > obj_list ( ) - > append_menu_items_convert_unit ( menu ) ;
2019-05-13 12:27:51 +00:00
sidebar - > obj_list ( ) - > append_menu_item_fix_through_netfabb ( menu ) ;
2019-01-30 15:27:07 +00:00
2018-10-18 12:42:21 +00:00
wxMenu * mirror_menu = new wxMenu ( ) ;
if ( mirror_menu = = nullptr )
return false ;
2020-04-01 07:48:56 +00:00
append_menu_item ( mirror_menu , wxID_ANY , _L ( " Along X axis " ) , _L ( " Mirror the selected object along the X axis " ) ,
2019-04-12 15:10:04 +00:00
[ this ] ( wxCommandEvent & ) { mirror ( X ) ; } , " mark_X " , menu ) ;
2020-04-01 07:48:56 +00:00
append_menu_item ( mirror_menu , wxID_ANY , _L ( " Along Y axis " ) , _L ( " Mirror the selected object along the Y axis " ) ,
2019-04-12 15:10:04 +00:00
[ this ] ( wxCommandEvent & ) { mirror ( Y ) ; } , " mark_Y " , menu ) ;
2020-04-01 07:48:56 +00:00
append_menu_item ( mirror_menu , wxID_ANY , _L ( " Along Z axis " ) , _L ( " Mirror the selected object along the Z axis " ) ,
2019-04-12 15:10:04 +00:00
[ this ] ( wxCommandEvent & ) { mirror ( Z ) ; } , " mark_Z " , menu ) ;
2018-10-18 12:42:21 +00:00
2020-04-01 07:48:56 +00:00
append_submenu ( menu , mirror_menu , wxID_ANY , _L ( " Mirror " ) , _L ( " Mirror the selected object " ) , " " ,
2019-05-13 12:27:51 +00:00
[ this ] ( ) { return can_mirror ( ) ; } , q ) ;
2018-12-07 16:50:48 +00:00
return true ;
}
bool Plater : : priv : : complit_init_object_menu ( )
{
2018-10-24 10:55:38 +00:00
wxMenu * split_menu = new wxMenu ( ) ;
if ( split_menu = = nullptr )
return false ;
2020-04-01 07:48:56 +00:00
append_menu_item ( split_menu , wxID_ANY , _L ( " To objects " ) , _L ( " Split the selected object into individual objects " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { split_object ( ) ; } , " split_object_SMALL " , & object_menu , [ this ] ( ) { return can_split ( ) ; } , q ) ;
2020-04-01 07:48:56 +00:00
append_menu_item ( split_menu , wxID_ANY , _L ( " To parts " ) , _L ( " Split the selected object into individual sub-parts " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { split_volume ( ) ; } , " split_parts_SMALL " , & object_menu , [ this ] ( ) { return can_split ( ) ; } , q ) ;
2018-10-24 10:55:38 +00:00
2020-04-01 07:48:56 +00:00
append_submenu ( & object_menu , split_menu , wxID_ANY , _L ( " Split " ) , _L ( " Split the selected object " ) , " " ,
2019-05-13 12:27:51 +00:00
[ this ] ( ) { return can_split ( ) & & wxGetApp ( ) . get_mode ( ) > comSimple ; } , q ) ;
2018-12-07 16:50:48 +00:00
object_menu . AppendSeparator ( ) ;
2018-11-22 15:04:21 +00:00
2019-05-27 11:07:37 +00:00
// Layers Editing for object
2019-12-11 15:07:00 +00:00
sidebar - > obj_list ( ) - > append_menu_item_layers_editing ( & object_menu , q ) ;
2019-05-27 11:07:37 +00:00
object_menu . AppendSeparator ( ) ;
2019-01-25 09:34:32 +00:00
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
2018-11-22 15:04:21 +00:00
2018-12-07 16:50:48 +00:00
return true ;
}
bool Plater : : priv : : complit_init_sla_object_menu ( )
{
2020-04-01 07:48:56 +00:00
append_menu_item ( & sla_object_menu , wxID_ANY , _L ( " Split " ) , _L ( " Split the selected object into individual objects " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { split_object ( ) ; } , " split_object_SMALL " , nullptr , [ this ] ( ) { return can_split ( ) ; } , q ) ;
2018-12-07 16:50:48 +00:00
2019-01-25 09:34:32 +00:00
sla_object_menu . AppendSeparator ( ) ;
2018-12-07 16:50:48 +00:00
// Add the automatic rotation sub-menu
2020-04-23 16:47:51 +00:00
append_menu_item (
& sla_object_menu , wxID_ANY , _ ( L ( " Optimize orientation " ) ) ,
_ ( L ( " Optimize the rotation of the object for better print results. " ) ) ,
[ this ] ( wxCommandEvent & ) {
m_ui_jobs . optimize_rotation ( ) ;
} ) ;
2018-12-07 16:50:48 +00:00
return true ;
}
bool Plater : : priv : : complit_init_part_menu ( )
{
2020-04-01 07:48:56 +00:00
append_menu_item ( & part_menu , wxID_ANY , _L ( " Split " ) , _L ( " Split the selected object into individual sub-parts " ) ,
2019-05-13 12:27:51 +00:00
[ this ] ( wxCommandEvent & ) { split_volume ( ) ; } , " split_parts_SMALL " , nullptr , [ this ] ( ) { return can_split ( ) ; } , q ) ;
2018-12-07 16:50:48 +00:00
2019-01-25 09:34:32 +00:00
part_menu . AppendSeparator ( ) ;
2018-12-07 16:50:48 +00:00
auto obj_list = sidebar - > obj_list ( ) ;
2020-02-14 12:27:01 +00:00
obj_list - > append_menu_item_change_type ( & part_menu , q ) ;
2018-12-07 16:50:48 +00:00
2018-10-17 10:17:25 +00:00
return true ;
}
2018-10-08 17:55:30 +00:00
2020-01-03 10:41:29 +00:00
void Plater : : priv : : set_current_canvas_as_dirty ( )
{
if ( current_panel = = view3D )
view3D - > set_as_dirty ( ) ;
else if ( current_panel = = preview )
preview - > set_as_dirty ( ) ;
}
2020-01-21 13:07:13 +00:00
GLCanvas3D * Plater : : priv : : get_current_canvas3D ( )
{
return ( current_panel = = view3D ) ? view3D - > get_canvas3d ( ) : ( ( current_panel = = preview ) ? preview - > get_canvas3d ( ) : nullptr ) ;
}
2020-03-04 14:19:48 +00:00
void Plater : : priv : : unbind_canvas_event_handlers ( )
{
if ( view3D ! = nullptr )
view3D - > get_canvas3d ( ) - > unbind_event_handlers ( ) ;
if ( preview ! = nullptr )
preview - > get_canvas3d ( ) - > unbind_event_handlers ( ) ;
}
2020-04-01 07:58:31 +00:00
void Plater : : priv : : reset_canvas_volumes ( )
{
if ( view3D ! = nullptr )
view3D - > get_canvas3d ( ) - > reset_volumes ( ) ;
if ( preview ! = nullptr )
preview - > get_canvas3d ( ) - > reset_volumes ( ) ;
}
2020-03-04 14:19:48 +00:00
2019-12-10 09:56:21 +00:00
bool Plater : : priv : : init_view_toolbar ( )
2018-12-06 09:38:19 +00:00
{
2019-12-10 09:56:21 +00:00
if ( view_toolbar . get_items_count ( ) > 0 )
// already initialized
return true ;
2018-12-17 09:55:14 +00:00
BackgroundTexture : : Metadata background_data ;
background_data . filename = " toolbar_background.png " ;
background_data . left = 16 ;
background_data . top = 16 ;
background_data . right = 16 ;
background_data . bottom = 16 ;
2019-02-26 08:56:23 +00:00
if ( ! view_toolbar . init ( background_data ) )
2019-12-10 09:56:21 +00:00
return false ;
2018-12-17 09:55:14 +00:00
2019-07-20 10:02:29 +00:00
view_toolbar . set_horizontal_orientation ( GLToolbar : : Layout : : HO_Left ) ;
view_toolbar . set_vertical_orientation ( GLToolbar : : Layout : : VO_Bottom ) ;
2018-12-17 09:55:14 +00:00
view_toolbar . set_border ( 5.0f ) ;
view_toolbar . set_gap_size ( 1.0f ) ;
GLToolbarItem : : Data item ;
item . name = " 3D " ;
2019-03-04 13:21:52 +00:00
item . icon_filename = " editor.svg " ;
2019-05-09 15:18:03 +00:00
item . tooltip = _utf8 ( L ( " 3D editor view " ) ) + " [ " + GUI : : shortkey_ctrl_prefix ( ) + " 5] " ;
2018-12-17 09:55:14 +00:00
item . sprite_id = 0 ;
2019-07-12 07:26:19 +00:00
item . left . action_callback = [ this ] ( ) { if ( this - > q ! = nullptr ) wxPostEvent ( this - > q , SimpleEvent ( EVT_GLVIEWTOOLBAR_3D ) ) ; } ;
2018-12-17 09:55:14 +00:00
if ( ! view_toolbar . add_item ( item ) )
2019-12-10 09:56:21 +00:00
return false ;
2018-12-06 09:38:19 +00:00
2018-12-17 09:55:14 +00:00
item . name = " Preview " ;
2019-03-04 13:21:52 +00:00
item . icon_filename = " preview.svg " ;
2019-05-09 15:18:03 +00:00
item . tooltip = _utf8 ( L ( " Preview " ) ) + " [ " + GUI : : shortkey_ctrl_prefix ( ) + " 6] " ;
2018-12-17 09:55:14 +00:00
item . sprite_id = 1 ;
2019-07-12 07:26:19 +00:00
item . left . action_callback = [ this ] ( ) { if ( this - > q ! = nullptr ) wxPostEvent ( this - > q , SimpleEvent ( EVT_GLVIEWTOOLBAR_PREVIEW ) ) ; } ;
2018-12-17 09:55:14 +00:00
if ( ! view_toolbar . add_item ( item ) )
2019-12-10 09:56:21 +00:00
return false ;
2018-12-17 09:55:14 +00:00
view_toolbar . select_item ( " 3D " ) ;
view_toolbar . set_enabled ( true ) ;
2019-12-10 09:56:21 +00:00
return true ;
2018-12-06 09:38:19 +00:00
}
2020-06-05 10:33:09 +00:00
bool Plater : : priv : : init_collapse_toolbar ( )
{
if ( collapse_toolbar . get_items_count ( ) > 0 )
// already initialized
return true ;
BackgroundTexture : : Metadata background_data ;
background_data . filename = " toolbar_background.png " ;
background_data . left = 16 ;
background_data . top = 16 ;
background_data . right = 16 ;
background_data . bottom = 16 ;
if ( ! collapse_toolbar . init ( background_data ) )
return false ;
collapse_toolbar . set_layout_type ( GLToolbar : : Layout : : Vertical ) ;
collapse_toolbar . set_horizontal_orientation ( GLToolbar : : Layout : : HO_Right ) ;
collapse_toolbar . set_vertical_orientation ( GLToolbar : : Layout : : VO_Top ) ;
collapse_toolbar . set_border ( 5.0f ) ;
collapse_toolbar . set_separator_size ( 5 ) ;
collapse_toolbar . set_gap_size ( 2 ) ;
GLToolbarItem : : Data item ;
item . name = " collapse_sidebar " ;
item . icon_filename = " collapse.svg " ;
item . tooltip = wxGetApp ( ) . plater ( ) - > is_sidebar_collapsed ( ) ? _utf8 ( L ( " Expand right panel " ) ) : _utf8 ( L ( " Collapse right panel " ) ) ;
item . sprite_id = 0 ;
item . left . action_callback = [ this , item ] ( ) {
std : : string new_tooltip = wxGetApp ( ) . plater ( ) - > is_sidebar_collapsed ( ) ?
_utf8 ( L ( " Collapse right panel " ) ) : _utf8 ( L ( " Expand right panel " ) ) ;
int id = collapse_toolbar . get_item_id ( " collapse_sidebar " ) ;
collapse_toolbar . set_tooltip ( id , new_tooltip ) ;
wxGetApp ( ) . plater ( ) - > collapse_sidebar ( ! wxGetApp ( ) . plater ( ) - > is_sidebar_collapsed ( ) ) ;
} ;
if ( ! collapse_toolbar . add_item ( item ) )
return false ;
return true ;
}
2019-01-22 15:40:10 +00:00
bool Plater : : priv : : can_set_instance_to_object ( ) const
{
const int obj_idx = get_selected_object_idx ( ) ;
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) & & ( model . objects [ obj_idx ] - > instances . size ( ) > 1 ) ;
}
2018-12-17 14:44:30 +00:00
bool Plater : : priv : : can_split ( ) const
2018-10-18 07:27:37 +00:00
{
2018-12-17 14:44:30 +00:00
return sidebar - > obj_list ( ) - > is_splittable ( ) ;
2018-10-18 07:27:37 +00:00
}
bool Plater : : priv : : layers_height_allowed ( ) const
{
2019-04-05 07:51:58 +00:00
if ( printer_technology ! = ptFFF )
return false ;
2018-10-18 07:27:37 +00:00
int obj_idx = get_selected_object_idx ( ) ;
2018-12-04 12:55:25 +00:00
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) & & config - > opt_bool ( " variable_layer_height " ) & & view3D - > is_layers_editing_allowed ( ) ;
2018-10-18 07:27:37 +00:00
}
2018-10-18 13:09:41 +00:00
bool Plater : : priv : : can_mirror ( ) const
2019-01-22 15:40:10 +00:00
{
2018-10-18 13:09:41 +00:00
return get_selection ( ) . is_from_single_instance ( ) ;
2019-01-22 15:40:10 +00:00
}
2019-09-19 07:09:11 +00:00
bool Plater : : priv : : can_reload_from_disk ( ) const
{
// struct to hold selected ModelVolumes by their indices
struct SelectedVolume
{
int object_idx ;
int volume_idx ;
// operators needed by std::algorithms
bool operator < ( const SelectedVolume & other ) const { return ( object_idx < other . object_idx ) | | ( ( object_idx = = other . object_idx ) & & ( volume_idx < other . volume_idx ) ) ; }
bool operator = = ( const SelectedVolume & other ) const { return ( object_idx = = other . object_idx ) & & ( volume_idx = = other . volume_idx ) ; }
} ;
std : : vector < SelectedVolume > selected_volumes ;
const Selection & selection = get_selection ( ) ;
// collects selected ModelVolumes
const std : : set < unsigned int > & selected_volumes_idxs = selection . get_volume_idxs ( ) ;
for ( unsigned int idx : selected_volumes_idxs )
{
const GLVolume * v = selection . get_volume ( idx ) ;
int v_idx = v - > volume_idx ( ) ;
2019-10-10 12:44:52 +00:00
if ( v_idx > = 0 )
2020-01-02 08:07:33 +00:00
{
int o_idx = v - > object_idx ( ) ;
if ( ( 0 < = o_idx ) & & ( o_idx < ( int ) model . objects . size ( ) ) )
selected_volumes . push_back ( { o_idx , v_idx } ) ;
}
2019-09-19 07:09:11 +00:00
}
std : : sort ( selected_volumes . begin ( ) , selected_volumes . end ( ) ) ;
selected_volumes . erase ( std : : unique ( selected_volumes . begin ( ) , selected_volumes . end ( ) ) , selected_volumes . end ( ) ) ;
// collects paths of files to load
std : : vector < fs : : path > paths ;
for ( const SelectedVolume & v : selected_volumes )
{
2020-02-07 08:49:48 +00:00
const ModelObject * object = model . objects [ v . object_idx ] ;
const ModelVolume * volume = object - > volumes [ v . volume_idx ] ;
2019-12-10 13:42:28 +00:00
if ( ! volume - > source . input_file . empty ( ) )
2019-09-19 07:09:11 +00:00
paths . push_back ( volume - > source . input_file ) ;
2020-02-07 08:49:48 +00:00
else if ( ! object - > input_file . empty ( ) & & ! volume - > name . empty ( ) )
paths . push_back ( volume - > name ) ;
2019-09-19 07:09:11 +00:00
}
std : : sort ( paths . begin ( ) , paths . end ( ) ) ;
paths . erase ( std : : unique ( paths . begin ( ) , paths . end ( ) ) , paths . end ( ) ) ;
return ! paths . empty ( ) ;
}
2019-07-24 12:02:36 +00:00
void Plater : : priv : : set_bed_shape ( const Pointfs & shape , const std : : string & custom_texture , const std : : string & custom_model )
2018-10-18 07:27:37 +00:00
{
2019-07-24 12:02:36 +00:00
bool new_shape = bed . set_shape ( shape , custom_texture , custom_model ) ;
2019-02-19 14:15:27 +00:00
if ( new_shape )
{
if ( view3D ) view3D - > bed_shape_changed ( ) ;
if ( preview ) preview - > bed_shape_changed ( ) ;
}
2018-10-18 07:27:37 +00:00
}
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_delete ( ) const
2018-10-24 10:55:38 +00:00
{
2019-06-28 15:03:50 +00:00
return ! get_selection ( ) . is_empty ( ) & & ! get_selection ( ) . is_wipe_tower ( ) & & ! m_ui_jobs . is_any_running ( ) ;
2018-10-24 10:55:38 +00:00
}
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_delete_all ( ) const
2018-10-18 07:27:37 +00:00
{
2019-03-14 12:54:05 +00:00
return ! model . objects . empty ( ) ;
2018-10-18 07:27:37 +00:00
}
2019-04-24 14:04:47 +00:00
bool Plater : : priv : : can_fix_through_netfabb ( ) const
{
int obj_idx = get_selected_object_idx ( ) ;
if ( obj_idx < 0 )
return false ;
return model . objects [ obj_idx ] - > get_mesh_errors_count ( ) > 0 ;
}
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_increase_instances ( ) const
2018-12-17 14:44:30 +00:00
{
2019-06-18 14:24:30 +00:00
if ( m_ui_jobs . is_any_running ( ) ) {
2019-04-17 12:56:00 +00:00
return false ;
}
2019-03-14 12:54:05 +00:00
int obj_idx = get_selected_object_idx ( ) ;
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) ;
2018-12-17 14:44:30 +00:00
}
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_decrease_instances ( ) const
2018-10-18 07:27:37 +00:00
{
2019-06-18 14:24:30 +00:00
if ( m_ui_jobs . is_any_running ( ) ) {
2019-04-17 12:56:00 +00:00
return false ;
}
2018-10-22 13:18:56 +00:00
int obj_idx = get_selected_object_idx ( ) ;
2019-03-14 12:54:05 +00:00
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) & & ( model . objects [ obj_idx ] - > instances . size ( ) > 1 ) ;
2018-10-18 07:27:37 +00:00
}
2018-10-18 13:09:41 +00:00
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_split_to_objects ( ) const
2018-10-18 13:09:41 +00:00
{
2019-03-14 12:54:05 +00:00
return can_split ( ) ;
2018-10-18 13:09:41 +00:00
}
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_split_to_volumes ( ) const
2018-10-18 13:09:41 +00:00
{
2019-03-14 12:54:05 +00:00
return ( printer_technology ! = ptSLA ) & & can_split ( ) ;
2018-10-18 13:09:41 +00:00
}
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_arrange ( ) const
2018-10-18 13:09:41 +00:00
{
2019-06-18 14:24:30 +00:00
return ! model . objects . empty ( ) & & ! m_ui_jobs . is_any_running ( ) ;
2018-10-18 07:27:37 +00:00
}
2018-10-08 17:55:30 +00:00
2019-03-14 12:54:05 +00:00
bool Plater : : priv : : can_layers_editing ( ) const
2019-02-19 14:15:27 +00:00
{
2019-03-14 12:54:05 +00:00
return layers_height_allowed ( ) ;
2019-02-19 14:15:27 +00:00
}
2018-12-07 16:50:48 +00:00
void Plater : : priv : : update_object_menu ( )
{
2019-01-25 12:16:32 +00:00
sidebar - > obj_list ( ) - > append_menu_items_add_volume ( & object_menu ) ;
2018-12-07 16:50:48 +00:00
}
2020-03-06 14:10:58 +00:00
void Plater : : priv : : show_action_buttons ( const bool ready_to_slice ) const
2019-03-01 10:00:34 +00:00
{
2020-03-06 14:10:58 +00:00
// Cache this value, so that the callbacks from the RemovableDriveManager may repeat that value when calling show_action_buttons().
this - > ready_to_slice = ready_to_slice ;
2019-03-01 10:00:34 +00:00
wxWindowUpdateLocker noUpdater ( sidebar ) ;
const auto prin_host_opt = config - > option < ConfigOptionString > ( " print_host " ) ;
const bool send_gcode_shown = prin_host_opt ! = nullptr & & ! prin_host_opt - > value . empty ( ) ;
2019-12-10 16:31:27 +00:00
2019-08-06 16:16:02 +00:00
// when a background processing is ON, export_btn and/or send_btn are showing
2019-03-01 10:00:34 +00:00
if ( wxGetApp ( ) . app_config - > get ( " background_processing " ) = = " 1 " )
{
2020-03-06 14:10:58 +00:00
RemovableDriveManager : : RemovableDrivesStatus removable_media_status = wxGetApp ( ) . removable_drive_manager ( ) - > status ( ) ;
2020-01-02 15:30:28 +00:00
if ( sidebar - > show_reslice ( false ) |
sidebar - > show_export ( true ) |
sidebar - > show_send ( send_gcode_shown ) |
2020-03-06 14:10:58 +00:00
sidebar - > show_export_removable ( removable_media_status . has_removable_drives ) |
sidebar - > show_disconnect ( removable_media_status . has_eject ) )
2019-08-06 16:16:02 +00:00
sidebar - > Layout ( ) ;
}
2019-03-01 10:00:34 +00:00
else
{
2020-03-06 14:10:58 +00:00
RemovableDriveManager : : RemovableDrivesStatus removable_media_status ;
if ( ! ready_to_slice )
removable_media_status = wxGetApp ( ) . removable_drive_manager ( ) - > status ( ) ;
if ( sidebar - > show_reslice ( ready_to_slice ) |
sidebar - > show_export ( ! ready_to_slice ) |
sidebar - > show_send ( send_gcode_shown & & ! ready_to_slice ) |
sidebar - > show_export_removable ( ! ready_to_slice & & removable_media_status . has_removable_drives ) |
sidebar - > show_disconnect ( ! ready_to_slice & & removable_media_status . has_eject ) )
2019-08-06 16:16:02 +00:00
sidebar - > Layout ( ) ;
}
2019-03-01 10:00:34 +00:00
}
2019-07-26 11:44:33 +00:00
void Plater : : priv : : enter_gizmos_stack ( )
{
2019-08-06 16:16:02 +00:00
assert ( m_undo_redo_stack_active = = & m_undo_redo_stack_main ) ;
if ( m_undo_redo_stack_active = = & m_undo_redo_stack_main ) {
m_undo_redo_stack_active = & m_undo_redo_stack_gizmos ;
assert ( m_undo_redo_stack_active - > empty ( ) ) ;
// Take the initial snapshot of the gizmos.
// Not localized on purpose, the text will never be shown to the user.
this - > take_snapshot ( std : : string ( " Gizmos-Initial " ) ) ;
}
2019-07-26 11:44:33 +00:00
}
void Plater : : priv : : leave_gizmos_stack ( )
{
2019-08-06 16:16:02 +00:00
assert ( m_undo_redo_stack_active = = & m_undo_redo_stack_gizmos ) ;
if ( m_undo_redo_stack_active = = & m_undo_redo_stack_gizmos ) {
assert ( ! m_undo_redo_stack_active - > empty ( ) ) ;
m_undo_redo_stack_active - > clear ( ) ;
m_undo_redo_stack_active = & m_undo_redo_stack_main ;
}
2019-07-26 11:44:33 +00:00
}
2019-07-09 18:45:00 +00:00
int Plater : : priv : : get_active_snapshot_index ( )
{
2019-07-26 11:44:33 +00:00
const size_t active_snapshot_time = this - > undo_redo_stack ( ) . active_snapshot_time ( ) ;
const std : : vector < UndoRedo : : Snapshot > & ss_stack = this - > undo_redo_stack ( ) . snapshots ( ) ;
2019-07-09 18:45:00 +00:00
const auto it = std : : lower_bound ( ss_stack . begin ( ) , ss_stack . end ( ) , UndoRedo : : Snapshot ( active_snapshot_time ) ) ;
return it - ss_stack . begin ( ) ;
}
2019-07-19 08:29:06 +00:00
void Plater : : priv : : take_snapshot ( const std : : string & snapshot_name )
{
2019-08-06 16:16:02 +00:00
if ( this - > m_prevent_snapshots > 0 )
2019-07-19 08:29:06 +00:00
return ;
assert ( this - > m_prevent_snapshots > = 0 ) ;
2019-07-22 14:52:47 +00:00
UndoRedo : : SnapshotData snapshot_data ;
snapshot_data . printer_technology = this - > printer_technology ;
2019-07-19 08:29:06 +00:00
if ( this - > view3D - > is_layers_editing_enabled ( ) )
2019-08-06 16:16:02 +00:00
snapshot_data . flags | = UndoRedo : : SnapshotData : : VARIABLE_LAYER_EDITING_ACTIVE ;
2019-07-23 16:17:57 +00:00
if ( this - > sidebar - > obj_list ( ) - > is_selected ( itSettings ) ) {
snapshot_data . flags | = UndoRedo : : SnapshotData : : SELECTED_SETTINGS_ON_SIDEBAR ;
2019-07-24 10:32:38 +00:00
snapshot_data . layer_range_idx = this - > sidebar - > obj_list ( ) - > get_selected_layers_range_idx ( ) ;
2019-07-23 16:17:57 +00:00
}
else if ( this - > sidebar - > obj_list ( ) - > is_selected ( itLayer ) ) {
snapshot_data . flags | = UndoRedo : : SnapshotData : : SELECTED_LAYER_ON_SIDEBAR ;
2019-07-24 10:32:38 +00:00
snapshot_data . layer_range_idx = this - > sidebar - > obj_list ( ) - > get_selected_layers_range_idx ( ) ;
2019-07-23 16:17:57 +00:00
}
else if ( this - > sidebar - > obj_list ( ) - > is_selected ( itLayerRoot ) )
snapshot_data . flags | = UndoRedo : : SnapshotData : : SELECTED_LAYERROOT_ON_SIDEBAR ;
2019-08-22 14:44:49 +00:00
// If SLA gizmo is active, ask it if it wants to trigger support generation
// on loading this snapshot.
if ( view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) . wants_reslice_supports_on_undo ( ) )
snapshot_data . flags | = UndoRedo : : SnapshotData : : RECALCULATE_SLA_SUPPORTS ;
2019-07-19 13:29:04 +00:00
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
if ( this - > printer_technology = = ptFFF ) {
2019-07-19 13:47:10 +00:00
const DynamicPrintConfig & config = wxGetApp ( ) . preset_bundle - > prints . get_edited_preset ( ) . config ;
model . wipe_tower . position = Vec2d ( config . opt_float ( " wipe_tower_x " ) , config . opt_float ( " wipe_tower_y " ) ) ;
model . wipe_tower . rotation = config . opt_float ( " wipe_tower_rotation_angle " ) ;
}
2019-07-26 11:44:33 +00:00
this - > undo_redo_stack ( ) . take_snapshot ( snapshot_name , model , view3D - > get_canvas3d ( ) - > get_selection ( ) , view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) , snapshot_data ) ;
this - > undo_redo_stack ( ) . release_least_recently_used ( ) ;
2019-07-19 08:29:06 +00:00
// Save the last active preset name of a particular printer technology.
( ( this - > printer_technology = = ptFFF ) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name ) = wxGetApp ( ) . preset_bundle - > printers . get_selected_preset_name ( ) ;
2019-08-06 16:16:02 +00:00
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 ( ) ;
2019-07-19 08:29:06 +00:00
}
2019-07-04 08:45:41 +00:00
void Plater : : priv : : undo ( )
{
2019-08-06 16:16:02 +00:00
const std : : vector < UndoRedo : : Snapshot > & snapshots = this - > undo_redo_stack ( ) . snapshots ( ) ;
auto it_current = std : : lower_bound ( snapshots . begin ( ) , snapshots . end ( ) , UndoRedo : : Snapshot ( this - > undo_redo_stack ( ) . active_snapshot_time ( ) ) ) ;
if ( - - it_current ! = snapshots . begin ( ) )
this - > undo_redo_to ( it_current ) ;
2019-07-04 08:45:41 +00:00
}
void Plater : : priv : : redo ( )
2019-08-06 16:16:02 +00:00
{
const std : : vector < UndoRedo : : Snapshot > & snapshots = this - > undo_redo_stack ( ) . snapshots ( ) ;
auto it_current = std : : lower_bound ( snapshots . begin ( ) , snapshots . end ( ) , UndoRedo : : Snapshot ( this - > undo_redo_stack ( ) . active_snapshot_time ( ) ) ) ;
if ( + + it_current ! = snapshots . end ( ) )
this - > undo_redo_to ( it_current ) ;
2019-07-04 12:35:04 +00:00
}
2019-07-18 15:41:47 +00:00
void Plater : : priv : : undo_redo_to ( size_t time_to_load )
2019-07-09 18:45:00 +00:00
{
2019-08-06 16:16:02 +00:00
const std : : vector < UndoRedo : : Snapshot > & snapshots = this - > undo_redo_stack ( ) . snapshots ( ) ;
auto it_current = std : : lower_bound ( snapshots . begin ( ) , snapshots . end ( ) , UndoRedo : : Snapshot ( time_to_load ) ) ;
assert ( it_current ! = snapshots . end ( ) ) ;
this - > undo_redo_to ( it_current ) ;
2019-07-09 18:45:00 +00:00
}
2019-07-18 15:41:47 +00:00
void Plater : : priv : : undo_redo_to ( std : : vector < UndoRedo : : Snapshot > : : const_iterator it_snapshot )
{
2019-08-22 23:36:56 +00:00
// Make sure that no updating function calls take_snapshot until we are done.
SuppressSnapshots snapshot_supressor ( q ) ;
2019-08-06 16:16:02 +00:00
bool temp_snapshot_was_taken = this - > undo_redo_stack ( ) . temp_snapshot_active ( ) ;
PrinterTechnology new_printer_technology = it_snapshot - > snapshot_data . printer_technology ;
bool printer_technology_changed = this - > printer_technology ! = new_printer_technology ;
if ( printer_technology_changed ) {
// Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type.
std : : string s_pt = ( it_snapshot - > snapshot_data . printer_technology = = ptFFF ) ? " FFF " : " SLA " ;
2020-04-01 07:48:56 +00:00
if ( ! wxGetApp ( ) . check_unsaved_changes ( format_wxstr ( _L (
" %1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets. " ) , s_pt ) ) )
2019-08-06 16:16:02 +00:00
// Don't switch the profiles.
return ;
}
2019-07-18 15:41:47 +00:00
// Save the last active preset name of a particular printer technology.
( ( this - > printer_technology = = ptFFF ) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name ) = wxGetApp ( ) . preset_bundle - > printers . get_selected_preset_name ( ) ;
2019-07-19 13:29:04 +00:00
//FIXME updating the Wipe tower config values at the ModelWipeTower from the Print config.
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
if ( this - > printer_technology = = ptFFF ) {
2019-07-19 13:47:10 +00:00
const DynamicPrintConfig & config = wxGetApp ( ) . preset_bundle - > prints . get_edited_preset ( ) . config ;
model . wipe_tower . position = Vec2d ( config . opt_float ( " wipe_tower_x " ) , config . opt_float ( " wipe_tower_y " ) ) ;
model . wipe_tower . rotation = config . opt_float ( " wipe_tower_rotation_angle " ) ;
}
2019-07-25 15:24:00 +00:00
const int layer_range_idx = it_snapshot - > snapshot_data . layer_range_idx ;
2019-07-19 08:29:06 +00:00
// Flags made of Snapshot::Flags enum values.
2019-07-22 14:52:47 +00:00
unsigned int new_flags = it_snapshot - > snapshot_data . flags ;
2019-08-06 16:16:02 +00:00
UndoRedo : : SnapshotData top_snapshot_data ;
2019-07-22 14:52:47 +00:00
top_snapshot_data . printer_technology = this - > printer_technology ;
2019-07-19 08:29:06 +00:00
if ( this - > view3D - > is_layers_editing_enabled ( ) )
2019-08-06 16:16:02 +00:00
top_snapshot_data . flags | = UndoRedo : : SnapshotData : : VARIABLE_LAYER_EDITING_ACTIVE ;
2019-07-23 16:17:57 +00:00
if ( this - > sidebar - > obj_list ( ) - > is_selected ( itSettings ) ) {
2019-08-06 16:16:02 +00:00
top_snapshot_data . flags | = UndoRedo : : SnapshotData : : SELECTED_SETTINGS_ON_SIDEBAR ;
2019-07-24 10:32:38 +00:00
top_snapshot_data . layer_range_idx = this - > sidebar - > obj_list ( ) - > get_selected_layers_range_idx ( ) ;
2019-07-23 16:17:57 +00:00
}
else if ( this - > sidebar - > obj_list ( ) - > is_selected ( itLayer ) ) {
top_snapshot_data . flags | = UndoRedo : : SnapshotData : : SELECTED_LAYER_ON_SIDEBAR ;
2019-07-24 10:32:38 +00:00
top_snapshot_data . layer_range_idx = this - > sidebar - > obj_list ( ) - > get_selected_layers_range_idx ( ) ;
2019-07-23 16:17:57 +00:00
}
else if ( this - > sidebar - > obj_list ( ) - > is_selected ( itLayerRoot ) )
top_snapshot_data . flags | = UndoRedo : : SnapshotData : : SELECTED_LAYERROOT_ON_SIDEBAR ;
2019-08-06 16:16:02 +00:00
bool new_variable_layer_editing_active = ( new_flags & UndoRedo : : SnapshotData : : VARIABLE_LAYER_EDITING_ACTIVE ) ! = 0 ;
2019-07-23 16:17:57 +00:00
bool new_selected_settings_on_sidebar = ( new_flags & UndoRedo : : SnapshotData : : SELECTED_SETTINGS_ON_SIDEBAR ) ! = 0 ;
bool new_selected_layer_on_sidebar = ( new_flags & UndoRedo : : SnapshotData : : SELECTED_LAYER_ON_SIDEBAR ) ! = 0 ;
bool new_selected_layerroot_on_sidebar = ( new_flags & UndoRedo : : SnapshotData : : SELECTED_LAYERROOT_ON_SIDEBAR ) ! = 0 ;
2019-08-22 14:44:49 +00:00
if ( this - > view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) . wants_reslice_supports_on_undo ( ) )
top_snapshot_data . flags | = UndoRedo : : SnapshotData : : RECALCULATE_SLA_SUPPORTS ;
2019-08-06 16:16:02 +00:00
// Disable layer editing before the Undo / Redo jump.
2019-07-19 13:36:55 +00:00
if ( ! new_variable_layer_editing_active & & view3D - > is_layers_editing_enabled ( ) )
view3D - > get_canvas3d ( ) - > force_main_toolbar_left_action ( view3D - > get_canvas3d ( ) - > get_main_toolbar_item_id ( " layersediting " ) ) ;
2019-11-27 10:08:10 +00:00
2019-08-22 14:44:49 +00:00
// Make a copy of the snapshot, undo/redo could invalidate the iterator
const UndoRedo : : Snapshot snapshot_copy = * it_snapshot ;
2019-07-18 15:41:47 +00:00
// Do the jump in time.
2019-07-26 11:44:33 +00:00
if ( it_snapshot - > timestamp < this - > undo_redo_stack ( ) . active_snapshot_time ( ) ?
2019-08-06 16:16:02 +00:00
this - > undo_redo_stack ( ) . undo ( model , this - > view3D - > get_canvas3d ( ) - > get_selection ( ) , this - > view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) , top_snapshot_data , it_snapshot - > timestamp ) :
this - > undo_redo_stack ( ) . redo ( model , this - > view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) , it_snapshot - > timestamp ) ) {
if ( printer_technology_changed ) {
// Switch to the other printer technology. Switch to the last printer active for that particular technology.
AppConfig * app_config = wxGetApp ( ) . app_config ;
app_config - > set ( " presets " , " printer " , ( new_printer_technology = = ptFFF ) ? m_last_fff_printer_profile_name : m_last_sla_printer_profile_name ) ;
wxGetApp ( ) . preset_bundle - > load_presets ( * app_config ) ;
2019-08-27 10:15:29 +00:00
// load_current_presets() calls Tab::load_current_preset() -> TabPrint::update() -> Object_list::update_and_show_object_settings_item(),
// but the Object list still keeps pointer to the old Model. Avoid a crash by removing selection first.
this - > sidebar - > obj_list ( ) - > unselect_objects ( ) ;
2019-08-06 16:16:02 +00:00
// Load the currently selected preset into the GUI, update the preset selection box.
// This also switches the printer technology based on the printer technology of the active printer profile.
wxGetApp ( ) . load_current_presets ( ) ;
2019-07-18 15:41:47 +00:00
}
2019-07-19 13:47:10 +00:00
//FIXME updating the Print config from the Wipe tower config values at the ModelWipeTower.
// This is a workaround until we refactor the Wipe Tower position / orientation to live solely inside the Model, not in the Print config.
if ( this - > printer_technology = = ptFFF ) {
const DynamicPrintConfig & current_config = wxGetApp ( ) . preset_bundle - > prints . get_edited_preset ( ) . config ;
Vec2d current_position ( current_config . opt_float ( " wipe_tower_x " ) , current_config . opt_float ( " wipe_tower_y " ) ) ;
double current_rotation = current_config . opt_float ( " wipe_tower_rotation_angle " ) ;
if ( current_position ! = model . wipe_tower . position | | current_rotation ! = model . wipe_tower . rotation ) {
DynamicPrintConfig new_config ;
new_config . set_key_value ( " wipe_tower_x " , new ConfigOptionFloat ( model . wipe_tower . position . x ( ) ) ) ;
new_config . set_key_value ( " wipe_tower_y " , new ConfigOptionFloat ( model . wipe_tower . position . y ( ) ) ) ;
new_config . set_key_value ( " wipe_tower_rotation_angle " , new ConfigOptionFloat ( model . wipe_tower . rotation ) ) ;
Tab * tab_print = wxGetApp ( ) . get_tab ( Preset : : TYPE_PRINT ) ;
tab_print - > load_config ( new_config ) ;
tab_print - > update_dirty ( ) ;
}
}
2019-07-23 16:17:57 +00:00
// set selection mode for ObjectList on sidebar
this - > sidebar - > obj_list ( ) - > set_selection_mode ( new_selected_settings_on_sidebar ? ObjectList : : SELECTION_MODE : : smSettings :
new_selected_layer_on_sidebar ? ObjectList : : SELECTION_MODE : : smLayer :
2019-08-06 16:16:02 +00:00
new_selected_layerroot_on_sidebar ? ObjectList : : SELECTION_MODE : : smLayerRoot :
2019-07-23 16:17:57 +00:00
ObjectList : : SELECTION_MODE : : smUndef ) ;
if ( new_selected_settings_on_sidebar | | new_selected_layer_on_sidebar )
2019-07-25 15:24:00 +00:00
this - > sidebar - > obj_list ( ) - > set_selected_layers_range_idx ( layer_range_idx ) ;
2019-07-23 16:17:57 +00:00
2019-08-22 14:44:49 +00:00
this - > update_after_undo_redo ( snapshot_copy , temp_snapshot_was_taken ) ;
2019-08-06 16:16:02 +00:00
// Enable layer editing after the Undo / Redo jump.
if ( ! view3D - > is_layers_editing_enabled ( ) & & this - > layers_height_allowed ( ) & & new_variable_layer_editing_active )
2019-07-19 13:36:55 +00:00
view3D - > get_canvas3d ( ) - > force_main_toolbar_left_action ( view3D - > get_canvas3d ( ) - > get_main_toolbar_item_id ( " layersediting " ) ) ;
}
2019-07-09 18:45:00 +00:00
}
2019-08-22 14:44:49 +00:00
void Plater : : priv : : update_after_undo_redo ( const UndoRedo : : Snapshot & snapshot , bool /* temp_snapshot_was_taken */ )
2019-07-04 12:35:04 +00:00
{
2019-08-06 16:16:02 +00:00
this - > view3D - > get_canvas3d ( ) - > get_selection ( ) . clear ( ) ;
// Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies).
2019-08-23 13:53:45 +00:00
this - > update ( ( unsigned int ) UpdateParams : : FORCE_BACKGROUND_PROCESSING_UPDATE | ( unsigned int ) UpdateParams : : POSTPONE_VALIDATION_ERROR_MESSAGE ) ;
2019-08-06 16:16:02 +00:00
// Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot.
//if (temp_snapshot_was_taken)
// Release the old snapshots always, as it may have happened, that some of the triangle meshes got deserialized from the snapshot, while some
// triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size.
this - > undo_redo_stack ( ) . release_least_recently_used ( ) ;
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
2019-07-26 11:44:33 +00:00
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 ) ;
2019-08-22 14:44:49 +00:00
this - > view3D - > get_canvas3d ( ) - > get_gizmos_manager ( ) . update_after_undo_redo ( snapshot ) ;
2019-07-04 15:33:19 +00:00
2019-07-11 16:42:02 +00:00
wxGetApp ( ) . obj_list ( ) - > update_after_undo_redo ( ) ;
2019-07-18 15:41:47 +00:00
if ( wxGetApp ( ) . get_mode ( ) = = comSimple & & model_has_advanced_features ( this - > model ) ) {
2019-08-06 16:16:02 +00:00
// If the user jumped to a snapshot that require user interface with advanced features, switch to the advanced mode without asking.
// There is a little risk of surprising the user, as he already must have had the advanced or expert mode active for such a snapshot to be taken.
2019-07-18 15:41:47 +00:00
Slic3r : : GUI : : wxGetApp ( ) . save_mode ( comAdvanced ) ;
view3D - > set_as_dirty ( ) ;
}
2019-08-23 13:53:45 +00:00
// 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,
// 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
// queue pump, which in turn executes the rendering function before a full update after the Undo / Redo jump.
this - > show_delayed_error_message ( ) ;
2019-08-06 16:16:02 +00:00
//FIXME what about the state of the manipulators?
//FIXME what about the focus? Cursor in the side panel?
2019-07-17 13:48:53 +00:00
2019-07-26 11:44:33 +00:00
BOOST_LOG_TRIVIAL ( info ) < < " Undo / Redo snapshot reloaded. Undo / Redo stack memory: " < < Slic3r : : format_memsize_MB ( this - > undo_redo_stack ( ) . memsize ( ) ) < < log_memory_info ( ) ;
2019-07-04 08:45:41 +00:00
}
2019-03-01 10:00:34 +00:00
void Sidebar : : set_btn_label ( const ActionButtonType btn_type , const wxString & label ) const
{
switch ( btn_type )
{
case ActionButtonType : : abReslice : p - > btn_reslice - > SetLabelText ( label ) ; break ;
case ActionButtonType : : abExport : p - > btn_export_gcode - > SetLabelText ( label ) ; break ;
2019-12-10 16:31:27 +00:00
case ActionButtonType : : abSendGCode : /*p->btn_send_gcode->SetLabelText(label);*/ break ;
2019-03-01 10:00:34 +00:00
}
}
2018-09-17 10:15:11 +00:00
// Plater / Public
Plater : : Plater ( wxWindow * parent , MainFrame * main_frame )
2020-05-22 13:23:05 +00:00
: wxPanel ( parent , wxID_ANY , wxDefaultPosition , wxGetApp ( ) . get_min_size ( ) )
2020-03-02 09:58:46 +00:00
, p ( new priv ( this , main_frame ) )
2018-09-17 10:15:11 +00:00
{
// Initialization performed in the private c-tor
}
Plater : : ~ Plater ( )
{
}
2018-12-03 12:14:28 +00:00
Sidebar & Plater : : sidebar ( ) { return * p - > sidebar ; }
Model & Plater : : model ( ) { return p - > model ; }
const Print & Plater : : fff_print ( ) const { return p - > fff_print ; }
Print & Plater : : fff_print ( ) { return p - > fff_print ; }
const SLAPrint & Plater : : sla_print ( ) const { return p - > sla_print ; }
SLAPrint & Plater : : sla_print ( ) { return p - > sla_print ; }
2018-09-17 10:15:11 +00:00
2019-05-14 08:30:14 +00:00
void Plater : : new_project ( )
{
2019-06-18 12:45:10 +00:00
p - > select_view_3D ( " 3D " ) ;
2019-05-14 13:00:24 +00:00
wxPostEvent ( p - > view3D - > get_wxglcanvas ( ) , SimpleEvent ( EVT_GLTOOLBAR_DELETE_ALL ) ) ;
2019-05-14 08:30:14 +00:00
}
2018-11-15 14:27:39 +00:00
void Plater : : load_project ( )
{
2019-07-17 13:48:53 +00:00
// Ask user for a project file name.
2018-11-15 14:27:39 +00:00
wxString input_file ;
wxGetApp ( ) . load_project ( this , input_file ) ;
2019-07-17 13:48:53 +00:00
// And finally load the new project.
2019-07-12 13:36:01 +00:00
load_project ( input_file ) ;
}
2018-11-15 14:27:39 +00:00
2019-07-12 13:36:01 +00:00
void Plater : : load_project ( const wxString & filename )
{
if ( filename . empty ( ) )
2018-11-15 14:27:39 +00:00
return ;
2019-07-23 10:57:58 +00:00
// Take the Undo / Redo snapshot.
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , _L ( " Load Project " ) + " : " + wxString : : FromUTF8 ( into_path ( filename ) . stem ( ) . string ( ) . c_str ( ) ) ) ;
2019-07-23 10:57:58 +00:00
2018-11-15 14:27:39 +00:00
p - > reset ( ) ;
std : : vector < fs : : path > input_paths ;
2019-07-12 13:36:01 +00:00
input_paths . push_back ( into_path ( filename ) ) ;
2019-09-02 13:15:28 +00:00
std : : vector < size_t > res = load_files ( input_paths ) ;
// if res is empty no data has been loaded
if ( ! res . empty ( ) )
p - > set_project_filename ( filename ) ;
2018-11-15 14:27:39 +00:00
}
2020-04-29 17:10:13 +00:00
void Plater : : add_model ( bool imperial_units /* = false*/ )
2018-10-17 10:17:25 +00:00
{
wxArrayString input_files ;
2018-11-15 14:27:39 +00:00
wxGetApp ( ) . import_model ( this , input_files ) ;
if ( input_files . empty ( ) )
return ;
2018-10-17 10:17:25 +00:00
2019-07-17 13:48:53 +00:00
std : : vector < fs : : path > paths ;
for ( const auto & file : input_files )
paths . push_back ( into_path ( file ) ) ;
2019-08-06 16:16:02 +00:00
wxString snapshot_label ;
assert ( ! paths . empty ( ) ) ;
if ( paths . size ( ) = = 1 ) {
2020-04-01 07:48:56 +00:00
snapshot_label = _L ( " Import Object " ) ;
2019-08-06 16:16:02 +00:00
snapshot_label + = " : " ;
snapshot_label + = wxString : : FromUTF8 ( paths . front ( ) . filename ( ) . string ( ) . c_str ( ) ) ;
} else {
2020-04-01 07:48:56 +00:00
snapshot_label = _L ( " Import Objects " ) ;
2019-08-06 16:16:02 +00:00
snapshot_label + = " : " ;
snapshot_label + = wxString : : FromUTF8 ( paths . front ( ) . filename ( ) . string ( ) . c_str ( ) ) ;
for ( size_t i = 1 ; i < paths . size ( ) ; + + i ) {
snapshot_label + = " , " ;
snapshot_label + = wxString : : FromUTF8 ( paths [ i ] . filename ( ) . string ( ) . c_str ( ) ) ;
}
}
Plater : : TakeSnapshot snapshot ( this , snapshot_label ) ;
2020-04-29 17:10:13 +00:00
load_files ( paths , true , false , imperial_units ) ;
2018-10-17 10:17:25 +00:00
}
2020-04-13 10:31:37 +00:00
void Plater : : import_sl1_archive ( )
{
2020-04-23 17:45:55 +00:00
p - > m_ui_jobs . import_sla_arch ( ) ;
2020-04-13 10:31:37 +00:00
}
2018-11-16 08:26:41 +00:00
void Plater : : extract_config_from_project ( )
{
wxString input_file ;
wxGetApp ( ) . load_project ( this , input_file ) ;
if ( input_file . empty ( ) )
return ;
std : : vector < fs : : path > input_paths ;
2019-01-02 14:11:05 +00:00
input_paths . push_back ( into_path ( input_file ) ) ;
2018-11-16 08:26:41 +00:00
load_files ( input_paths , false , true ) ;
}
2020-04-29 17:10:13 +00:00
std : : vector < size_t > Plater : : load_files ( const std : : vector < fs : : path > & input_files , bool load_model , bool load_config , bool imperial_units /*= false*/ ) { return p - > load_files ( input_files , load_model , load_config , imperial_units ) ; }
2018-09-17 10:15:11 +00:00
2019-01-09 09:43:17 +00:00
// To be called when providing a list of files to the GUI slic3r on command line.
2020-04-29 17:10:13 +00:00
std : : vector < size_t > Plater : : load_files ( const std : : vector < std : : string > & input_files , bool load_model , bool load_config , bool imperial_units /*= false*/ )
2019-08-06 16:16:02 +00:00
{
2019-01-09 09:43:17 +00:00
std : : vector < fs : : path > paths ;
paths . reserve ( input_files . size ( ) ) ;
2019-09-02 13:15:28 +00:00
for ( const std : : string & path : input_files )
2019-01-09 09:43:17 +00:00
paths . emplace_back ( path ) ;
2020-04-29 17:10:13 +00:00
return p - > load_files ( paths , load_model , load_config , imperial_units ) ;
2019-01-09 09:43:17 +00:00
}
2018-11-21 12:32:24 +00:00
void Plater : : update ( ) { p - > update ( ) ; }
2018-10-17 10:59:58 +00:00
2019-06-18 14:24:30 +00:00
void Plater : : stop_jobs ( ) { p - > m_ui_jobs . stop_all ( ) ; }
2019-05-13 16:58:56 +00:00
2018-12-04 10:14:39 +00:00
void Plater : : update_ui_from_settings ( ) { p - > update_ui_from_settings ( ) ; }
2018-10-17 10:59:58 +00:00
void Plater : : select_view ( const std : : string & direction ) { p - > select_view ( direction ) ; }
2018-12-04 12:55:25 +00:00
void Plater : : select_view_3D ( const std : : string & name ) { p - > select_view_3D ( name ) ; }
2019-08-20 07:01:09 +00:00
bool Plater : : is_preview_shown ( ) const { return p - > is_preview_shown ( ) ; }
bool Plater : : is_preview_loaded ( ) const { return p - > is_preview_loaded ( ) ; }
bool Plater : : is_view3D_shown ( ) const { return p - > is_view3D_shown ( ) ; }
2020-02-04 13:42:26 +00:00
bool Plater : : are_view3D_labels_shown ( ) const { return p - > are_view3D_labels_shown ( ) ; }
void Plater : : show_view3D_labels ( bool show ) { p - > show_view3D_labels ( show ) ; }
2020-03-16 11:49:39 +00:00
bool Plater : : is_sidebar_collapsed ( ) const { return p - > is_sidebar_collapsed ( ) ; }
2020-04-29 13:58:57 +00:00
void Plater : : collapse_sidebar ( bool show ) { p - > collapse_sidebar ( show ) ; }
2020-03-16 11:49:39 +00:00
2020-03-13 14:09:07 +00:00
# if ENABLE_SLOPE_RENDERING
bool Plater : : is_view3D_slope_shown ( ) const { return p - > is_view3D_slope_shown ( ) ; }
void Plater : : show_view3D_slope ( bool show ) { p - > show_view3D_slope ( show ) ; }
bool Plater : : is_view3D_layers_editing_enabled ( ) const { return p - > is_view3D_layers_editing_enabled ( ) ; }
# endif // ENABLE_SLOPE_RENDERING
2018-11-21 14:28:35 +00:00
void Plater : : select_all ( ) { p - > select_all ( ) ; }
2019-05-14 09:57:39 +00:00
void Plater : : deselect_all ( ) { p - > deselect_all ( ) ; }
2018-11-21 14:28:35 +00:00
2018-10-08 17:14:55 +00:00
void Plater : : remove ( size_t obj_idx ) { p - > remove ( obj_idx ) ; }
2018-11-22 10:31:53 +00:00
void Plater : : reset ( ) { p - > reset ( ) ; }
2019-05-02 11:52:13 +00:00
void Plater : : reset_with_confirm ( )
{
2020-04-01 07:48:56 +00:00
if ( wxMessageDialog ( ( wxWindow * ) this , _L ( " All objects will be removed, continue? " ) , wxString ( SLIC3R_APP_NAME ) + " - " + _L ( " Delete all " ) , wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE ) . ShowModal ( ) = = wxID_YES )
2019-05-02 11:52:13 +00:00
reset ( ) ;
}
2018-11-22 10:31:53 +00:00
2018-11-13 13:17:35 +00:00
void Plater : : delete_object_from_model ( size_t obj_idx ) { p - > delete_object_from_model ( obj_idx ) ; }
2018-10-04 09:12:55 +00:00
void Plater : : remove_selected ( )
{
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , _L ( " Delete Selected Objects " ) ) ;
2018-12-04 12:55:25 +00:00
this - > p - > view3D - > delete_selected ( ) ;
2018-10-04 09:12:55 +00:00
}
2018-10-18 13:09:41 +00:00
void Plater : : increase_instances ( size_t num )
2018-10-11 08:03:38 +00:00
{
2019-04-17 12:56:00 +00:00
if ( ! can_increase_instances ( ) ) { return ; }
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , _L ( " Increase Instances " ) ) ;
2019-07-02 14:42:23 +00:00
2018-10-17 07:30:07 +00:00
int obj_idx = p - > get_selected_object_idx ( ) ;
ModelObject * model_object = p - > model . objects [ obj_idx ] ;
ModelInstance * model_instance = model_object - > instances . back ( ) ;
2018-10-11 08:03:38 +00:00
2018-11-07 12:40:24 +00:00
bool was_one_instance = model_object - > instances . size ( ) = = 1 ;
2019-08-06 16:16:02 +00:00
2019-04-12 13:31:33 +00:00
double offset_base = canvas3D ( ) - > get_size_proportional_to_max_bed_size ( 0.05 ) ;
double offset = offset_base ;
for ( size_t i = 0 ; i < num ; i + + , offset + = offset_base ) {
2018-10-11 08:03:38 +00:00
Vec3d offset_vec = model_instance - > get_offset ( ) + Vec3d ( offset , offset , 0.0 ) ;
2019-01-03 14:04:29 +00:00
model_object - > add_instance ( offset_vec , model_instance - > get_scaling_factor ( ) , model_instance - > get_rotation ( ) , model_instance - > get_mirror ( ) ) ;
2018-10-23 13:27:31 +00:00
// p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec));
2018-10-11 08:03:38 +00:00
}
2019-09-24 07:11:27 +00:00
if ( p - > get_config ( " autocenter " ) = = " 1 " )
2020-04-23 16:47:51 +00:00
arrange ( ) ;
2019-09-24 07:11:27 +00:00
p - > update ( ) ;
2018-10-11 08:03:38 +00:00
2018-10-23 07:19:41 +00:00
p - > get_selection ( ) . add_instance ( obj_idx , ( int ) model_object - > instances . size ( ) - 1 ) ;
2020-04-29 11:35:35 +00:00
sidebar ( ) . obj_list ( ) - > increase_object_instances ( obj_idx , was_one_instance ? num + 1 : num ) ;
2018-10-11 08:03:38 +00:00
2020-04-29 11:35:35 +00:00
p - > selection_changed ( ) ;
2018-10-17 09:12:38 +00:00
this - > p - > schedule_background_process ( ) ;
2018-10-11 08:03:38 +00:00
}
2018-10-18 13:09:41 +00:00
void Plater : : decrease_instances ( size_t num )
2018-10-11 08:03:38 +00:00
{
2019-04-17 12:56:00 +00:00
if ( ! can_decrease_instances ( ) ) { return ; }
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , _L ( " Decrease Instances " ) ) ;
2019-07-02 14:42:23 +00:00
2018-10-17 07:30:07 +00:00
int obj_idx = p - > get_selected_object_idx ( ) ;
ModelObject * model_object = p - > model . objects [ obj_idx ] ;
2018-10-11 08:03:38 +00:00
if ( model_object - > instances . size ( ) > num ) {
2018-11-08 13:23:17 +00:00
for ( size_t i = 0 ; i < num ; + + i )
2018-10-11 08:03:38 +00:00
model_object - > delete_last_instance ( ) ;
2019-05-14 14:37:32 +00:00
p - > update ( ) ;
// Delete object from Sidebar list. Do it after update, so that the GLScene selection is updated with the modified model.
2018-10-18 09:41:29 +00:00
sidebar ( ) . obj_list ( ) - > decrease_object_instances ( obj_idx , num ) ;
2018-10-17 07:30:07 +00:00
}
else {
remove ( obj_idx ) ;
2018-10-11 08:03:38 +00:00
}
2018-10-23 07:19:41 +00:00
if ( ! model_object - > instances . empty ( ) )
p - > get_selection ( ) . add_instance ( obj_idx , ( int ) model_object - > instances . size ( ) - 1 ) ;
2018-10-17 07:40:04 +00:00
p - > selection_changed ( ) ;
2018-10-23 13:27:31 +00:00
this - > p - > schedule_background_process ( ) ;
2018-10-11 08:03:38 +00:00
}
2018-10-25 19:13:45 +00:00
void Plater : : set_number_of_copies ( /*size_t num*/ )
2018-10-11 08:03:38 +00:00
{
2018-10-17 07:30:07 +00:00
int obj_idx = p - > get_selected_object_idx ( ) ;
if ( obj_idx = = - 1 )
return ;
ModelObject * model_object = p - > model . objects [ obj_idx ] ;
2018-10-11 08:03:38 +00:00
2020-04-01 07:48:56 +00:00
const int num = wxGetNumberFromUser ( " " , _L ( " Enter the number of copies: " ) ,
_L ( " Copies of the selected object " ) , model_object - > instances . size ( ) , 0 , 1000 , this ) ;
2018-10-25 19:13:45 +00:00
if ( num < 0 )
return ;
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , wxString : : Format ( _L ( " Set numbers of copies to %d " ) , num ) ) ;
2019-07-04 15:33:19 +00:00
2019-09-20 14:45:43 +00:00
int diff = num - ( int ) model_object - > instances . size ( ) ;
2018-10-18 13:09:41 +00:00
if ( diff > 0 )
increase_instances ( diff ) ;
else if ( diff < 0 )
decrease_instances ( - diff ) ;
2018-10-11 08:03:38 +00:00
}
2018-10-04 09:12:55 +00:00
2018-11-21 14:47:41 +00:00
bool Plater : : is_selection_empty ( ) const
{
2019-04-10 10:16:17 +00:00
return p - > get_selection ( ) . is_empty ( ) | | p - > get_selection ( ) . is_wipe_tower ( ) ;
2018-11-21 14:47:41 +00:00
}
2019-05-22 12:42:38 +00:00
void Plater : : scale_selection_to_fit_print_volume ( )
{
p - > scale_selection_to_fit_print_volume ( ) ;
}
2020-05-20 18:07:31 +00:00
void Plater : : convert_unit ( bool from_imperial_unit )
{
std : : vector < int > obj_idxs , volume_idxs ;
wxGetApp ( ) . obj_list ( ) - > get_selection_indexes ( obj_idxs , volume_idxs ) ;
if ( obj_idxs . empty ( ) & & volume_idxs . empty ( ) )
return ;
TakeSnapshot snapshot ( this , from_imperial_unit ? _L ( " Convert from imperial units " ) : _L ( " Convert to imperial units " ) ) ;
wxBusyCursor wait ;
ModelObjectPtrs objects ;
for ( int obj_idx : obj_idxs ) {
ModelObject * object = p - > model . objects [ obj_idx ] ;
object - > convert_units ( objects , from_imperial_unit , volume_idxs ) ;
remove ( obj_idx ) ;
}
p - > load_model_objects ( objects ) ;
Selection & selection = p - > view3D - > get_canvas3d ( ) - > get_selection ( ) ;
size_t last_obj_idx = p - > model . objects . size ( ) - 1 ;
if ( volume_idxs . empty ( ) ) {
for ( size_t i = 0 ; i < objects . size ( ) ; + + i )
selection . add_object ( ( unsigned int ) ( last_obj_idx - i ) , i = = 0 ) ;
}
else {
for ( int vol_idx : volume_idxs )
selection . add_volume ( last_obj_idx , vol_idx , 0 , false ) ;
}
}
2018-11-26 09:56:07 +00:00
void Plater : : cut ( size_t obj_idx , size_t instance_idx , coordf_t z , bool keep_upper , bool keep_lower , bool rotate_lower )
2018-10-18 13:13:38 +00:00
{
wxCHECK_RET ( obj_idx < p - > model . objects . size ( ) , " obj_idx out of bounds " ) ;
auto * object = p - > model . objects [ obj_idx ] ;
wxCHECK_RET ( instance_idx < object - > instances . size ( ) , " instance_idx out of bounds " ) ;
2019-01-18 14:02:07 +00:00
if ( ! keep_upper & & ! keep_lower ) {
return ;
}
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , _L ( " Cut by Plane " ) ) ;
2019-07-04 15:33:19 +00:00
2019-02-05 19:23:24 +00:00
wxBusyCursor wait ;
2018-11-26 09:56:07 +00:00
const auto new_objects = object - > cut ( instance_idx , z , keep_upper , keep_lower , rotate_lower ) ;
2018-10-18 13:13:38 +00:00
remove ( obj_idx ) ;
p - > load_model_objects ( new_objects ) ;
2019-12-19 09:06:46 +00:00
Selection & selection = p - > get_selection ( ) ;
size_t last_id = p - > model . objects . size ( ) - 1 ;
for ( size_t i = 0 ; i < new_objects . size ( ) ; + + i )
{
selection . add_object ( ( unsigned int ) ( last_id - i ) , i = = 0 ) ;
}
2018-10-18 13:13:38 +00:00
}
2020-01-02 15:30:28 +00:00
void Plater : : export_gcode ( bool prefer_removable )
2018-10-04 09:12:55 +00:00
{
2018-10-23 13:27:31 +00:00
if ( p - > model . objects . empty ( ) )
return ;
2018-09-17 10:15:11 +00:00
2019-02-03 09:41:14 +00:00
// If possible, remove accents from accented latin characters.
// This function is useful for generating file names to be processed by legacy firmwares.
fs : : path default_output_file ;
try {
2019-08-06 16:16:02 +00:00
// Update the background processing, so that the placeholder parser will get the correct values for the ouput file template.
// Also if there is something wrong with the current configuration, a pop-up dialog will be shown and the export will not be performed.
unsigned int state = this - > p - > update_restart_background_process ( false , false ) ;
if ( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID )
return ;
2019-05-17 14:27:00 +00:00
default_output_file = this - > p - > background_process . output_filepath_for_project ( into_path ( get_project_filename ( " .3mf " ) ) ) ;
2019-05-15 12:09:16 +00:00
}
catch ( const std : : exception & ex ) {
2019-02-03 09:41:14 +00:00
show_error ( this , ex . what ( ) ) ;
return ;
2018-09-17 10:15:11 +00:00
}
2019-02-03 09:41:14 +00:00
default_output_file = fs : : path ( Slic3r : : fold_utf8_to_ascii ( default_output_file . string ( ) ) ) ;
2020-03-06 14:10:58 +00:00
AppConfig & appconfig = * wxGetApp ( ) . app_config ;
RemovableDriveManager & removable_drive_manager = * wxGetApp ( ) . removable_drive_manager ( ) ;
// Get a last save path, either to removable media or to an internal media.
std : : string start_dir = appconfig . get_last_output_dir ( default_output_file . parent_path ( ) . string ( ) , prefer_removable ) ;
if ( prefer_removable ) {
// Returns a path to a removable media if it exists, prefering start_dir. Update the internal removable drives database.
start_dir = removable_drive_manager . get_removable_drive_path ( start_dir ) ;
if ( start_dir . empty ( ) )
// Direct user to the last internal media.
start_dir = appconfig . get_last_output_dir ( default_output_file . parent_path ( ) . string ( ) , false ) ;
2019-11-27 12:30:45 +00:00
}
2019-02-03 09:41:14 +00:00
fs : : path output_path ;
2020-03-06 14:10:58 +00:00
{
2020-04-01 07:48:56 +00:00
wxFileDialog dlg ( this , ( printer_technology ( ) = = ptFFF ) ? _L ( " Save G-code file as: " ) : _L ( " Save SL1 file as: " ) ,
2020-03-06 14:10:58 +00:00
start_dir ,
from_path ( default_output_file . filename ( ) ) ,
GUI : : file_wildcards ( ( printer_technology ( ) = = ptFFF ) ? FT_GCODE : FT_PNGZIP , default_output_file . extension ( ) . string ( ) ) ,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
) ;
if ( dlg . ShowModal ( ) = = wxID_OK )
output_path = into_path ( dlg . GetPath ( ) ) ;
2018-10-23 13:27:31 +00:00
}
2020-03-06 14:10:58 +00:00
if ( ! output_path . empty ( ) ) {
bool path_on_removable_media = removable_drive_manager . set_and_verify_last_save_path ( output_path . string ( ) ) ;
2020-03-12 11:43:01 +00:00
p - > export_gcode ( output_path , path_on_removable_media , PrintHostJob ( ) ) ;
2020-03-06 14:10:58 +00:00
// Storing a path to AppConfig either as path to removable media or a path to internal media.
// is_path_on_removable_drive() is called with the "true" parameter to update its internal database as the user may have shuffled the external drives
// while the dialog was open.
appconfig . update_last_output_dir ( output_path . parent_path ( ) . string ( ) , path_on_removable_media ) ;
p - > writing_to_removable_device = path_on_removable_media ;
2019-12-12 09:48:33 +00:00
}
2018-09-17 10:15:11 +00:00
}
2019-05-02 11:46:39 +00:00
void Plater : : export_stl ( bool extended , bool selection_only )
2018-10-04 09:12:55 +00:00
{
2018-10-17 07:30:07 +00:00
if ( p - > model . objects . empty ( ) ) { return ; }
2018-10-04 09:12:55 +00:00
2019-04-04 09:31:26 +00:00
wxString path = p - > get_export_file ( FT_STL ) ;
if ( path . empty ( ) ) { return ; }
2019-01-02 14:11:05 +00:00
const std : : string path_u8 = into_u8 ( path ) ;
2018-12-05 14:22:03 +00:00
2019-02-22 09:11:57 +00:00
wxBusyCursor wait ;
2020-02-10 23:58:19 +00:00
const auto & selection = p - > get_selection ( ) ;
const auto obj_idx = selection . get_object_idx ( ) ;
if ( selection_only & & ( obj_idx = = - 1 | | selection . is_wipe_tower ( ) ) )
return ;
2019-04-04 13:13:43 +00:00
2020-02-10 23:58:19 +00:00
TriangleMesh mesh ;
if ( p - > printer_technology = = ptFFF ) {
if ( selection_only ) {
const ModelObject * model_object = p - > model . objects [ obj_idx ] ;
if ( selection . get_mode ( ) = = Selection : : Instance )
{
if ( selection . is_single_full_object ( ) )
mesh = model_object - > mesh ( ) ;
else
mesh = model_object - > full_raw_mesh ( ) ;
}
2019-04-05 09:30:49 +00:00
else
2020-02-10 23:58:19 +00:00
{
const GLVolume * volume = selection . get_volume ( * selection . get_volume_idxs ( ) . begin ( ) ) ;
mesh = model_object - > volumes [ volume - > volume_idx ( ) ] - > mesh ( ) ;
mesh . transform ( volume - > get_volume_transformation ( ) . get_matrix ( ) ) ;
mesh . translate ( - model_object - > origin_translation . cast < float > ( ) ) ;
}
2019-04-05 09:30:49 +00:00
}
2020-02-10 23:58:19 +00:00
else {
mesh = p - > model . mesh ( ) ;
2019-04-04 13:13:43 +00:00
}
}
2019-04-05 08:08:34 +00:00
else
2019-05-02 11:46:39 +00:00
{
2020-02-10 23:58:19 +00:00
// This is SLA mode, all objects have only one volume.
// However, we must have a look at the backend to load
// hollowed mesh and/or supports
2018-12-05 14:22:03 +00:00
2020-02-10 23:58:19 +00:00
const PrintObjects & objects = p - > sla_print . objects ( ) ;
for ( const SLAPrintObject * object : objects )
2019-05-02 11:46:39 +00:00
{
2020-02-10 23:58:19 +00:00
const ModelObject * model_object = object - > model_object ( ) ;
if ( selection_only ) {
if ( model_object - > id ( ) ! = p - > model . objects [ obj_idx ] - > id ( ) )
continue ;
}
Transform3d mesh_trafo_inv = object - > trafo ( ) . inverse ( ) ;
bool is_left_handed = object - > is_left_handed ( ) ;
TriangleMesh pad_mesh ;
bool has_pad_mesh = extended & & object - > has_mesh ( slaposPad ) ;
if ( has_pad_mesh )
2019-05-02 11:46:39 +00:00
{
2020-02-10 23:58:19 +00:00
pad_mesh = object - > get_mesh ( slaposPad ) ;
pad_mesh . transform ( mesh_trafo_inv ) ;
}
2019-05-02 11:46:39 +00:00
2020-02-10 23:58:19 +00:00
TriangleMesh supports_mesh ;
bool has_supports_mesh = extended & & object - > has_mesh ( slaposSupportTree ) ;
if ( has_supports_mesh )
{
supports_mesh = object - > get_mesh ( slaposSupportTree ) ;
supports_mesh . transform ( mesh_trafo_inv ) ;
}
const std : : vector < SLAPrintObject : : Instance > & obj_instances = object - > instances ( ) ;
for ( const SLAPrintObject : : Instance & obj_instance : obj_instances )
{
auto it = std : : find_if ( model_object - > instances . begin ( ) , model_object - > instances . end ( ) ,
[ & obj_instance ] ( const ModelInstance * mi ) { return mi - > id ( ) = = obj_instance . instance_id ; } ) ;
assert ( it ! = model_object - > instances . end ( ) ) ;
2019-05-02 11:46:39 +00:00
2020-02-10 23:58:19 +00:00
if ( it ! = model_object - > instances . end ( ) )
2019-05-02 11:46:39 +00:00
{
2020-02-10 23:58:19 +00:00
bool one_inst_only = selection_only & & ! selection . is_single_full_object ( ) ;
2019-05-02 11:46:39 +00:00
2020-02-10 23:58:19 +00:00
int instance_idx = it - model_object - > instances . begin ( ) ;
const Transform3d & inst_transform = one_inst_only
? Transform3d : : Identity ( )
: object - > model_object ( ) - > instances [ instance_idx ] - > get_transformation ( ) . get_matrix ( ) ;
2019-05-02 11:46:39 +00:00
2020-02-10 23:58:19 +00:00
if ( has_pad_mesh )
{
TriangleMesh inst_pad_mesh = pad_mesh ;
inst_pad_mesh . transform ( inst_transform , is_left_handed ) ;
mesh . merge ( inst_pad_mesh ) ;
}
2019-05-02 11:46:39 +00:00
2020-02-10 23:58:19 +00:00
if ( has_supports_mesh )
{
TriangleMesh inst_supports_mesh = supports_mesh ;
inst_supports_mesh . transform ( inst_transform , is_left_handed ) ;
mesh . merge ( inst_supports_mesh ) ;
2019-05-02 11:46:39 +00:00
}
2020-02-10 23:58:19 +00:00
TriangleMesh inst_object_mesh = object - > get_mesh_to_print ( ) ;
2020-02-13 12:49:13 +00:00
inst_object_mesh . transform ( mesh_trafo_inv ) ;
2020-02-10 23:58:19 +00:00
inst_object_mesh . transform ( inst_transform , is_left_handed ) ;
mesh . merge ( inst_object_mesh ) ;
if ( one_inst_only )
break ;
2019-05-02 11:46:39 +00:00
}
}
}
}
2019-01-02 14:11:05 +00:00
Slic3r : : store_stl ( path_u8 . c_str ( ) , & mesh , true ) ;
2020-04-01 07:48:56 +00:00
p - > statusbar ( ) - > set_status_text ( format_wxstr ( _L ( " STL file exported to %s " ) , path ) ) ;
2018-10-04 09:12:55 +00:00
}
void Plater : : export_amf ( )
{
2018-10-17 07:30:07 +00:00
if ( p - > model . objects . empty ( ) ) { return ; }
2018-10-08 17:55:30 +00:00
2019-04-04 09:31:26 +00:00
wxString path = p - > get_export_file ( FT_AMF ) ;
if ( path . empty ( ) ) { return ; }
2019-01-02 14:11:05 +00:00
const std : : string path_u8 = into_u8 ( path ) ;
2018-10-08 17:55:30 +00:00
2019-02-05 19:23:24 +00:00
wxBusyCursor wait ;
2019-04-04 09:31:26 +00:00
bool export_config = true ;
DynamicPrintConfig cfg = wxGetApp ( ) . preset_bundle - > full_config_secure ( ) ;
2020-01-08 10:11:38 +00:00
bool full_pathnames = wxGetApp ( ) . app_config - > get ( " export_sources_full_pathnames " ) = = " 1 " ;
if ( Slic3r : : store_amf ( path_u8 . c_str ( ) , & p - > model , export_config ? & cfg : nullptr , full_pathnames ) ) {
2018-10-08 17:55:30 +00:00
// Success
2020-04-01 07:48:56 +00:00
p - > statusbar ( ) - > set_status_text ( format_wxstr ( _L ( " AMF file exported to %s " ) , path ) ) ;
2018-10-08 17:55:30 +00:00
} else {
// Failure
2020-04-01 07:48:56 +00:00
p - > statusbar ( ) - > set_status_text ( format_wxstr ( _L ( " Error exporting AMF file %s " ) , path ) ) ;
2018-10-08 17:55:30 +00:00
}
2018-10-04 09:12:55 +00:00
}
2018-11-15 14:27:39 +00:00
void Plater : : export_3mf ( const boost : : filesystem : : path & output_path )
2018-10-04 09:12:55 +00:00
{
2018-10-17 07:30:07 +00:00
if ( p - > model . objects . empty ( ) ) { return ; }
2018-10-08 17:55:30 +00:00
2018-11-15 14:27:39 +00:00
wxString path ;
bool export_config = true ;
if ( output_path . empty ( ) )
{
2019-04-04 09:31:26 +00:00
path = p - > get_export_file ( FT_3MF ) ;
if ( path . empty ( ) ) { return ; }
2018-11-15 14:27:39 +00:00
}
else
2019-01-02 14:11:05 +00:00
path = from_path ( output_path ) ;
2018-10-08 17:55:30 +00:00
2018-11-15 14:27:39 +00:00
if ( ! path . Lower ( ) . EndsWith ( " .3mf " ) )
return ;
2018-10-08 17:55:30 +00:00
2019-06-18 14:24:30 +00:00
DynamicPrintConfig cfg = wxGetApp ( ) . preset_bundle - > full_config_secure ( ) ;
2019-01-02 14:11:05 +00:00
const std : : string path_u8 = into_u8 ( path ) ;
2019-02-05 19:23:24 +00:00
wxBusyCursor wait ;
2020-01-08 10:11:38 +00:00
bool full_pathnames = wxGetApp ( ) . app_config - > get ( " export_sources_full_pathnames " ) = = " 1 " ;
ThumbnailData thumbnail_data ;
p - > generate_thumbnail ( thumbnail_data , THUMBNAIL_SIZE_3MF . first , THUMBNAIL_SIZE_3MF . second , false , true , true , true ) ;
if ( Slic3r : : store_3mf ( path_u8 . c_str ( ) , & p - > model , export_config ? & cfg : nullptr , full_pathnames , & thumbnail_data ) ) {
2018-10-08 17:55:30 +00:00
// Success
2020-04-01 07:48:56 +00:00
p - > statusbar ( ) - > set_status_text ( format_wxstr ( _L ( " 3MF file exported to %s " ) , path ) ) ;
2019-05-14 13:00:24 +00:00
p - > set_project_filename ( path ) ;
}
else {
2018-10-08 17:55:30 +00:00
// Failure
2020-04-01 07:48:56 +00:00
p - > statusbar ( ) - > set_status_text ( format_wxstr ( _L ( " Error exporting 3MF file %s " ) , path ) ) ;
2018-10-08 17:55:30 +00:00
}
2018-10-04 09:12:55 +00:00
}
2019-09-19 07:09:11 +00:00
void Plater : : reload_from_disk ( )
{
p - > reload_from_disk ( ) ;
}
2020-01-31 11:15:04 +00:00
void Plater : : reload_all_from_disk ( )
{
p - > reload_all_from_disk ( ) ;
}
2019-08-20 09:33:58 +00:00
bool Plater : : has_toolpaths_to_export ( ) const
{
return p - > preview - > get_canvas3d ( ) - > has_toolpaths_to_export ( ) ;
}
void Plater : : export_toolpaths_to_obj ( ) const
2019-08-20 07:01:09 +00:00
{
if ( ( printer_technology ( ) ! = ptFFF ) | | ! is_preview_loaded ( ) )
return ;
wxString path = p - > get_export_file ( FT_OBJ ) ;
if ( path . empty ( ) )
return ;
2019-08-20 09:33:58 +00:00
2019-08-20 07:01:09 +00:00
wxBusyCursor wait ;
p - > preview - > get_canvas3d ( ) - > export_toolpaths_to_obj ( into_u8 ( path ) . c_str ( ) ) ;
}
2019-11-07 13:25:03 +00:00
2018-09-17 10:15:11 +00:00
void Plater : : reslice ( )
{
2019-05-14 08:34:11 +00:00
// Stop arrange and (or) optimize rotation tasks.
this - > stop_jobs ( ) ;
2019-07-31 11:00:35 +00:00
if ( printer_technology ( ) = = ptSLA ) {
for ( auto & object : model ( ) . objects )
if ( object - > sla_points_status = = sla : : PointsStatus : : NoPoints )
object - > sla_points_status = sla : : PointsStatus : : Generating ;
}
2019-08-06 16:16:02 +00:00
2018-11-13 16:45:44 +00:00
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
// bitmask of UpdateBackgroundProcessReturnState
2019-01-10 15:06:24 +00:00
unsigned int state = this - > p - > update_background_process ( true ) ;
2018-11-13 16:45:44 +00:00
if ( state & priv : : UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE )
2018-12-04 12:55:25 +00:00
this - > p - > view3D - > reload_scene ( false ) ;
2019-02-25 09:21:12 +00:00
// If the SLA processing of just a single object's supports is running, restart slicing for the whole object.
this - > p - > background_process . set_task ( PrintBase : : TaskParams ( ) ) ;
2018-12-22 09:02:42 +00:00
// Only restarts if the state is valid.
this - > p - > restart_background_process ( state | priv : : UPDATE_BACKGROUND_PROCESS_FORCE_RESTART ) ;
2019-03-01 10:00:34 +00:00
if ( ( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID ) ! = 0 )
return ;
if ( p - > background_process . running ( ) )
{
if ( wxGetApp ( ) . get_mode ( ) = = comSimple )
2020-04-01 07:48:56 +00:00
p - > sidebar - > set_btn_label ( ActionButtonType : : abReslice , _L ( " Slicing " ) + dots ) ;
2019-03-01 10:00:34 +00:00
else
{
2020-04-01 07:48:56 +00:00
p - > sidebar - > set_btn_label ( ActionButtonType : : abReslice , _L ( " Slice now " ) ) ;
2019-03-01 10:00:34 +00:00
p - > show_action_buttons ( false ) ;
}
}
else if ( ! p - > background_process . empty ( ) & & ! p - > background_process . idle ( ) )
p - > show_action_buttons ( true ) ;
2019-07-02 11:13:17 +00:00
// update type of preview
2019-10-16 07:45:11 +00:00
p - > preview - > update_view_type ( true ) ;
2018-09-17 10:15:11 +00:00
}
2019-08-23 13:53:45 +00:00
void Plater : : reslice_SLA_supports ( const ModelObject & object , bool postpone_error_messages )
2020-01-23 10:22:06 +00:00
{
reslice_SLA_until_step ( slaposPad , object , postpone_error_messages ) ;
}
void Plater : : reslice_SLA_hollowing ( const ModelObject & object , bool postpone_error_messages )
{
2020-02-03 14:42:54 +00:00
reslice_SLA_until_step ( slaposDrillHoles , object , postpone_error_messages ) ;
2020-01-23 10:22:06 +00:00
}
void Plater : : reslice_SLA_until_step ( SLAPrintObjectStep step , const ModelObject & object , bool postpone_error_messages )
2019-02-21 10:40:56 +00:00
{
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
// bitmask of UpdateBackgroundProcessReturnState
2019-08-23 13:53:45 +00:00
unsigned int state = this - > p - > update_background_process ( true , postpone_error_messages ) ;
2019-02-21 10:40:56 +00:00
if ( state & priv : : UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE )
this - > p - > view3D - > reload_scene ( false ) ;
2019-06-18 14:24:30 +00:00
if ( this - > p - > background_process . empty ( ) | | ( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID ) )
2019-02-21 10:40:56 +00:00
// Nothing to do on empty input or invalid configuration.
return ;
// Limit calculation to the single object only.
PrintBase : : TaskParams task ;
task . single_model_object = object . id ( ) ;
// If the background processing is not enabled, calculate supports just for the single instance.
// Otherwise calculate everything, but start with the provided object.
2019-08-06 16:16:02 +00:00
if ( ! this - > p - > background_processing_enabled ( ) ) {
task . single_model_instance_only = true ;
2020-01-23 10:22:06 +00:00
task . to_object_step = step ;
2019-08-06 16:16:02 +00:00
}
2019-02-21 10:40:56 +00:00
this - > p - > background_process . set_task ( task ) ;
// and let the background processing start.
this - > p - > restart_background_process ( state | priv : : UPDATE_BACKGROUND_PROCESS_FORCE_RESTART ) ;
}
2018-10-04 09:12:55 +00:00
void Plater : : send_gcode ( )
{
2018-12-11 09:33:11 +00:00
if ( p - > model . objects . empty ( ) ) { return ; }
PrintHostJob upload_job ( p - > config ) ;
if ( upload_job . empty ( ) ) { return ; }
// Obtain default output path
fs : : path default_output_file ;
try {
2019-08-06 16:16:02 +00:00
// Update the background processing, so that the placeholder parser will get the correct values for the ouput file template.
// Also if there is something wrong with the current configuration, a pop-up dialog will be shown and the export will not be performed.
unsigned int state = this - > p - > update_restart_background_process ( false , false ) ;
if ( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID )
return ;
2019-05-17 14:27:00 +00:00
default_output_file = this - > p - > background_process . output_filepath_for_project ( into_path ( get_project_filename ( " .3mf " ) ) ) ;
2019-05-15 12:09:16 +00:00
}
catch ( const std : : exception & ex ) {
2018-12-11 09:33:11 +00:00
show_error ( this , ex . what ( ) ) ;
return ;
}
default_output_file = fs : : path ( Slic3r : : fold_utf8_to_ascii ( default_output_file . string ( ) ) ) ;
2019-03-04 15:50:43 +00:00
PrintHostSendDialog dlg ( default_output_file , upload_job . printhost - > can_start_print ( ) ) ;
2018-12-11 09:33:11 +00:00
if ( dlg . ShowModal ( ) = = wxID_OK ) {
upload_job . upload_data . upload_path = dlg . filename ( ) ;
upload_job . upload_data . start_print = dlg . start_print ( ) ;
2020-03-12 11:43:01 +00:00
p - > export_gcode ( fs : : path ( ) , false , std : : move ( upload_job ) ) ;
2018-12-11 09:33:11 +00:00
}
2018-10-04 09:12:55 +00:00
}
2020-03-06 14:10:58 +00:00
// Called when the Eject button is pressed.
2019-12-11 11:28:51 +00:00
void Plater : : eject_drive ( )
{
2020-03-11 17:25:05 +00:00
wxBusyCursor wait ;
2020-03-06 14:10:58 +00:00
wxGetApp ( ) . removable_drive_manager ( ) - > eject_drive ( ) ;
2019-12-11 11:28:51 +00:00
}
2019-07-04 08:45:41 +00:00
void Plater : : take_snapshot ( const std : : string & snapshot_name ) { p - > take_snapshot ( snapshot_name ) ; }
void Plater : : take_snapshot ( const wxString & snapshot_name ) { p - > take_snapshot ( snapshot_name ) ; }
2019-07-11 14:00:01 +00:00
void Plater : : suppress_snapshots ( ) { p - > suppress_snapshots ( ) ; }
void Plater : : allow_snapshots ( ) { p - > allow_snapshots ( ) ; }
2019-07-04 08:45:41 +00:00
void Plater : : undo ( ) { p - > undo ( ) ; }
void Plater : : redo ( ) { p - > redo ( ) ; }
2019-07-09 18:45:00 +00:00
void Plater : : undo_to ( int selection )
{
if ( selection = = 0 ) {
p - > undo ( ) ;
return ;
}
2019-08-06 16:16:02 +00:00
2019-07-09 18:45:00 +00:00
const int idx = p - > get_active_snapshot_index ( ) - selection - 1 ;
2019-07-26 11:44:33 +00:00
p - > undo_redo_to ( p - > undo_redo_stack ( ) . snapshots ( ) [ idx ] . timestamp ) ;
2019-07-09 18:45:00 +00:00
}
void Plater : : redo_to ( int selection )
{
if ( selection = = 0 ) {
p - > redo ( ) ;
return ;
}
2019-08-06 16:16:02 +00:00
2019-07-10 08:15:07 +00:00
const int idx = p - > get_active_snapshot_index ( ) + selection + 1 ;
2019-07-26 11:44:33 +00:00
p - > undo_redo_to ( p - > undo_redo_stack ( ) . snapshots ( ) [ idx ] . timestamp ) ;
2019-07-09 18:45:00 +00:00
}
2019-07-09 13:27:28 +00:00
bool Plater : : undo_redo_string_getter ( const bool is_undo , int idx , const char * * out_text )
{
2019-07-26 11:44:33 +00:00
const std : : vector < UndoRedo : : Snapshot > & ss_stack = p - > undo_redo_stack ( ) . snapshots ( ) ;
2019-07-09 18:45:00 +00:00
const int idx_in_ss_stack = p - > get_active_snapshot_index ( ) + ( is_undo ? - ( + + idx ) : idx ) ;
2019-07-09 13:27:28 +00:00
2019-10-29 09:40:34 +00:00
if ( 0 < idx_in_ss_stack & & ( size_t ) idx_in_ss_stack < ss_stack . size ( ) - 1 ) {
2019-07-09 13:27:28 +00:00
* out_text = ss_stack [ idx_in_ss_stack ] . name . c_str ( ) ;
return true ;
}
return false ;
}
2019-07-02 14:42:23 +00:00
2019-07-20 12:03:34 +00:00
void Plater : : undo_redo_topmost_string_getter ( const bool is_undo , std : : string & out_text )
{
2019-07-26 11:44:33 +00:00
const std : : vector < UndoRedo : : Snapshot > & ss_stack = p - > undo_redo_stack ( ) . snapshots ( ) ;
2019-07-20 12:03:34 +00:00
const int idx_in_ss_stack = p - > get_active_snapshot_index ( ) + ( is_undo ? - 1 : 0 ) ;
2019-10-29 09:40:34 +00:00
if ( 0 < idx_in_ss_stack & & ( size_t ) idx_in_ss_stack < ss_stack . size ( ) - 1 ) {
2019-07-20 12:03:34 +00:00
out_text = ss_stack [ idx_in_ss_stack ] . name ;
return ;
}
2019-08-06 08:01:10 +00:00
out_text = " " ;
2019-07-20 12:03:34 +00:00
}
2020-04-20 19:46:16 +00:00
bool Plater : : search_string_getter ( int idx , const char * * label , const char * * tooltip )
2020-03-28 18:39:24 +00:00
{
2020-04-13 15:55:38 +00:00
const Search : : OptionsSearcher & search_list = p - > sidebar - > get_searcher ( ) ;
2020-03-28 18:39:24 +00:00
if ( 0 < = idx & & ( size_t ) idx < search_list . size ( ) ) {
2020-04-20 19:46:16 +00:00
search_list [ idx ] . get_marked_label_and_tooltip ( label , tooltip ) ;
2020-03-28 18:39:24 +00:00
return true ;
}
return false ;
}
2019-09-06 15:46:55 +00:00
void Plater : : on_extruders_change ( size_t num_extruders )
2018-10-10 11:53:45 +00:00
{
auto & choices = sidebar ( ) . combos_filament ( ) ;
2019-03-13 12:13:18 +00:00
if ( num_extruders = = choices . size ( ) )
return ;
2018-11-15 10:15:24 +00:00
wxWindowUpdateLocker noUpdates_scrolled_panel ( & sidebar ( ) /*.scrolled_panel()*/ ) ;
2018-11-09 17:39:07 +00:00
2019-09-06 15:46:55 +00:00
size_t i = choices . size ( ) ;
2018-10-10 11:53:45 +00:00
while ( i < num_extruders )
{
2020-06-16 10:57:49 +00:00
PlaterPresetComboBox * choice /*{ nullptr }*/ ;
2018-10-10 11:53:45 +00:00
sidebar ( ) . init_filament_combo ( & choice , i ) ;
choices . push_back ( choice ) ;
// initialize selection
2020-06-16 10:57:49 +00:00
choice - > update ( ) ;
2018-10-10 11:53:45 +00:00
+ + i ;
}
// remove unused choices if any
sidebar ( ) . remove_unused_filament_combos ( num_extruders ) ;
2018-11-15 10:15:24 +00:00
sidebar ( ) . Layout ( ) ;
sidebar ( ) . scrolled_panel ( ) - > Refresh ( ) ;
2018-10-10 11:53:45 +00:00
}
2018-10-17 09:12:38 +00:00
void Plater : : on_config_change ( const DynamicPrintConfig & config )
2018-10-10 11:53:45 +00:00
{
2018-10-15 08:53:47 +00:00
bool update_scheduled = false ;
2019-02-04 09:06:15 +00:00
bool bed_shape_changed = false ;
2018-10-17 09:12:38 +00:00
for ( auto opt_key : p - > config - > diff ( config ) ) {
2019-08-19 15:19:21 +00:00
if ( opt_key = = " filament_colour " )
{
update_scheduled = true ; // update should be scheduled (for update 3DScene) #2738
/* There is a case, when we use filament_color instead of extruder_color (when extruder_color == "").
* Thus plater config option " filament_colour " should be filled with filament_presets values .
* Otherwise , on 3 dScene will be used last edited filament color for all volumes with extruder_color = = " " .
*/
const std : : vector < std : : string > filament_presets = wxGetApp ( ) . preset_bundle - > filament_presets ;
if ( filament_presets . size ( ) > 1 & &
p - > config - > option < ConfigOptionStrings > ( opt_key ) - > values . size ( ) ! = config . option < ConfigOptionStrings > ( opt_key ) - > values . size ( ) )
{
const PresetCollection & filaments = wxGetApp ( ) . preset_bundle - > filaments ;
std : : vector < std : : string > filament_colors ;
filament_colors . reserve ( filament_presets . size ( ) ) ;
for ( const std : : string & filament_preset : filament_presets )
filament_colors . push_back ( filaments . find_preset ( filament_preset , true ) - > config . opt_string ( " filament_colour " , ( unsigned ) 0 ) ) ;
p - > config - > option < ConfigOptionStrings > ( opt_key ) - > values = filament_colors ;
2019-10-01 16:19:28 +00:00
p - > sidebar - > obj_list ( ) - > update_extruder_colors ( ) ;
2019-08-19 15:19:21 +00:00
continue ;
}
}
2018-10-17 09:12:38 +00:00
p - > config - > set_key_value ( opt_key , config . option ( opt_key ) - > clone ( ) ) ;
2020-04-23 19:32:12 +00:00
if ( opt_key = = " printer_technology " ) {
2018-12-03 12:14:28 +00:00
this - > set_printer_technology ( config . opt_enum < PrinterTechnology > ( opt_key ) ) ;
2020-04-23 19:32:12 +00:00
// print technology is changed, so we should to update a search list
p - > sidebar - > update_searcher ( ) ;
}
2019-07-24 12:02:36 +00:00
else if ( ( opt_key = = " bed_shape " ) | | ( opt_key = = " bed_custom_texture " ) | | ( opt_key = = " bed_custom_model " ) ) {
2019-02-04 09:06:15 +00:00
bed_shape_changed = true ;
2018-10-15 08:53:47 +00:00
update_scheduled = true ;
2019-08-06 16:16:02 +00:00
}
2018-12-06 14:40:41 +00:00
else if ( boost : : starts_with ( opt_key , " wipe_tower " ) | |
// opt_key == "filament_minimal_purge_on_wipe_tower" // ? #ys_FIXME
opt_key = = " single_extruder_multi_material " ) {
2018-10-15 08:53:47 +00:00
update_scheduled = true ;
2019-08-06 16:16:02 +00:00
}
2018-10-15 08:53:47 +00:00
else if ( opt_key = = " variable_layer_height " ) {
if ( p - > config - > opt_bool ( " variable_layer_height " ) ! = true ) {
2018-12-04 12:55:25 +00:00
p - > view3D - > enable_layers_editing ( false ) ;
p - > view3D - > set_as_dirty ( ) ;
2018-10-15 08:53:47 +00:00
}
2019-03-14 12:54:05 +00:00
}
2018-10-15 08:53:47 +00:00
else if ( opt_key = = " extruder_colour " ) {
update_scheduled = true ;
p - > preview - > set_number_extruders ( p - > config - > option < ConfigOptionStrings > ( opt_key ) - > values . size ( ) ) ;
2019-10-01 16:19:28 +00:00
p - > sidebar - > obj_list ( ) - > update_extruder_colors ( ) ;
2018-10-15 08:53:47 +00:00
} else if ( opt_key = = " max_print_height " ) {
update_scheduled = true ;
2019-01-17 12:21:33 +00:00
}
else if ( opt_key = = " printer_model " ) {
2018-10-15 08:53:47 +00:00
// update to force bed selection(for texturing)
2019-02-04 09:06:15 +00:00
bed_shape_changed = true ;
2018-10-15 08:53:47 +00:00
update_scheduled = true ;
2019-01-17 12:21:33 +00:00
}
2018-10-15 08:53:47 +00:00
}
2019-02-04 09:06:15 +00:00
if ( bed_shape_changed )
2019-07-18 12:39:19 +00:00
p - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ,
2019-07-24 12:02:36 +00:00
p - > config - > option < ConfigOptionString > ( " bed_custom_texture " ) - > value ,
p - > config - > option < ConfigOptionString > ( " bed_custom_model " ) - > value ) ;
2019-02-04 09:06:15 +00:00
2019-08-06 16:16:02 +00:00
if ( update_scheduled )
2018-10-15 08:53:47 +00:00
update ( ) ;
2018-10-17 09:12:38 +00:00
if ( p - > main_frame - > is_loaded ( ) )
this - > p - > schedule_background_process ( ) ;
2018-10-10 11:53:45 +00:00
}
2020-02-04 14:24:35 +00:00
void Plater : : set_bed_shape ( ) const
{
p - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ,
p - > config - > option < ConfigOptionString > ( " bed_custom_texture " ) - > value ,
p - > config - > option < ConfigOptionString > ( " bed_custom_model " ) - > value ) ;
}
2019-09-30 11:59:26 +00:00
void Plater : : force_filament_colors_update ( )
{
bool update_scheduled = false ;
DynamicPrintConfig * config = p - > config ;
const std : : vector < std : : string > filament_presets = wxGetApp ( ) . preset_bundle - > filament_presets ;
if ( filament_presets . size ( ) > 1 & &
p - > config - > option < ConfigOptionStrings > ( " filament_colour " ) - > values . size ( ) = = filament_presets . size ( ) )
{
const PresetCollection & filaments = wxGetApp ( ) . preset_bundle - > filaments ;
std : : vector < std : : string > filament_colors ;
filament_colors . reserve ( filament_presets . size ( ) ) ;
for ( const std : : string & filament_preset : filament_presets )
filament_colors . push_back ( filaments . find_preset ( filament_preset , true ) - > config . opt_string ( " filament_colour " , ( unsigned ) 0 ) ) ;
if ( config - > option < ConfigOptionStrings > ( " filament_colour " ) - > values ! = filament_colors ) {
config - > option < ConfigOptionStrings > ( " filament_colour " ) - > values = filament_colors ;
update_scheduled = true ;
}
}
2019-10-01 16:19:28 +00:00
if ( update_scheduled ) {
2019-09-30 11:59:26 +00:00
update ( ) ;
2019-10-01 16:19:28 +00:00
p - > sidebar - > obj_list ( ) - > update_extruder_colors ( ) ;
}
2019-09-30 11:59:26 +00:00
if ( p - > main_frame - > is_loaded ( ) )
this - > p - > schedule_background_process ( ) ;
}
2020-01-24 14:16:28 +00:00
void Plater : : force_print_bed_update ( )
{
// Fill in the printer model key with something which cannot possibly be valid, so that Plater::on_config_change() will update the print bed
// once a new Printer profile config is loaded.
p - > config - > opt_string ( " printer_model " , true ) = " \x01 \x00 \x01 " ;
}
2019-02-19 13:57:59 +00:00
void Plater : : on_activate ( )
{
2019-02-19 14:54:43 +00:00
# ifdef __linux__
2019-02-19 13:57:59 +00:00
wxWindow * focus_window = wxWindow : : FindFocus ( ) ;
2019-02-19 14:54:43 +00:00
// Activating the main frame, and no window has keyboard focus.
// Set the keyboard focus to the visible Canvas3D.
if ( this - > p - > view3D - > IsShown ( ) & & ( ! focus_window | | focus_window = = this - > p - > view3D - > get_wxglcanvas ( ) ) )
this - > p - > view3D - > get_wxglcanvas ( ) - > SetFocus ( ) ;
else if ( this - > p - > preview - > IsShown ( ) & & ( ! focus_window | | focus_window = = this - > p - > view3D - > get_wxglcanvas ( ) ) )
this - > p - > preview - > get_wxglcanvas ( ) - > SetFocus ( ) ;
# endif
2019-08-23 13:53:45 +00:00
this - > p - > show_delayed_error_message ( ) ;
2019-02-19 13:57:59 +00:00
}
2019-12-17 07:37:50 +00:00
// Get vector of extruder colors considering filament color, if extruder color is undefined.
2019-09-30 12:03:50 +00:00
std : : vector < std : : string > Plater : : get_extruder_colors_from_plater_config ( ) const
{
const Slic3r : : DynamicPrintConfig * config = & wxGetApp ( ) . preset_bundle - > printers . get_edited_preset ( ) . config ;
2019-10-07 10:36:16 +00:00
std : : vector < std : : string > extruder_colors ;
if ( ! config - > has ( " extruder_colour " ) ) // in case of a SLA print
return extruder_colors ;
extruder_colors = ( config - > option < ConfigOptionStrings > ( " extruder_colour " ) ) - > values ;
2019-10-18 10:35:35 +00:00
if ( ! wxGetApp ( ) . plater ( ) )
return extruder_colors ;
2019-09-30 12:03:50 +00:00
const std : : vector < std : : string > & filament_colours = ( p - > config - > option < ConfigOptionStrings > ( " filament_colour " ) ) - > values ;
for ( size_t i = 0 ; i < extruder_colors . size ( ) ; + + i )
if ( extruder_colors [ i ] = = " " & & i < filament_colours . size ( ) )
extruder_colors [ i ] = filament_colours [ i ] ;
return extruder_colors ;
}
2019-12-17 07:37:50 +00:00
/* Get vector of colors used for rendering of a Preview scene in "Color print" mode
* It consists of extruder colors and colors , saved in model . custom_gcode_per_print_z
*/
2019-11-07 12:51:54 +00:00
std : : vector < std : : string > Plater : : get_colors_for_color_print ( ) const
{
std : : vector < std : : string > colors = get_extruder_colors_from_plater_config ( ) ;
2020-01-16 15:01:19 +00:00
colors . reserve ( colors . size ( ) + p - > model . custom_gcode_per_print_z . gcodes . size ( ) ) ;
2019-11-07 12:51:54 +00:00
2020-01-23 11:49:39 +00:00
for ( const CustomGCode : : Item & code : p - > model . custom_gcode_per_print_z . gcodes )
2020-06-03 08:42:47 +00:00
if ( code . type = = CustomGCode : : ColorChange )
2019-12-17 07:37:50 +00:00
colors . emplace_back ( code . color ) ;
2019-11-07 12:51:54 +00:00
return colors ;
}
2019-05-15 12:09:16 +00:00
wxString Plater : : get_project_filename ( const wxString & extension ) const
{
return p - > get_project_filename ( extension ) ;
}
void Plater : : set_project_filename ( const wxString & filename )
2018-11-15 14:27:39 +00:00
{
2019-05-15 12:09:16 +00:00
return p - > set_project_filename ( filename ) ;
2018-11-15 14:27:39 +00:00
}
bool Plater : : is_export_gcode_scheduled ( ) const
{
return p - > background_process . is_export_scheduled ( ) ;
}
2020-04-23 16:47:51 +00:00
const Selection & Plater : : get_selection ( ) const
{
return p - > get_selection ( ) ;
}
2018-11-01 11:33:56 +00:00
int Plater : : get_selected_object_idx ( )
{
return p - > get_selected_object_idx ( ) ;
}
2018-11-13 14:24:05 +00:00
bool Plater : : is_single_full_object_selection ( ) const
2018-11-09 17:39:07 +00:00
{
return p - > get_selection ( ) . is_single_full_object ( ) ;
}
2018-11-23 11:47:32 +00:00
GLCanvas3D * Plater : : canvas3D ( )
2018-10-11 13:57:09 +00:00
{
2018-12-04 12:55:25 +00:00
return p - > view3D - > get_canvas3d ( ) ;
2018-10-11 13:57:09 +00:00
}
2020-01-21 13:07:13 +00:00
GLCanvas3D * Plater : : get_current_canvas3D ( )
{
return p - > get_current_canvas3D ( ) ;
}
2019-09-19 10:30:16 +00:00
BoundingBoxf Plater : : bed_shape_bb ( ) const
{
return p - > bed_shape_bb ( ) ;
}
2020-04-23 16:47:51 +00:00
void Plater : : arrange ( )
{
p - > m_ui_jobs . arrange ( ) ;
}
2020-01-03 10:41:29 +00:00
void Plater : : set_current_canvas_as_dirty ( )
{
p - > set_current_canvas_as_dirty ( ) ;
}
2020-03-04 14:19:48 +00:00
void Plater : : unbind_canvas_event_handlers ( )
{
p - > unbind_canvas_event_handlers ( ) ;
}
2020-04-01 07:58:31 +00:00
void Plater : : reset_canvas_volumes ( )
{
p - > reset_canvas_volumes ( ) ;
}
2020-03-04 14:19:48 +00:00
2018-11-12 16:35:57 +00:00
PrinterTechnology Plater : : printer_technology ( ) const
{
2018-11-13 16:45:44 +00:00
return p - > printer_technology ;
2018-11-12 16:35:57 +00:00
}
2020-04-23 16:47:51 +00:00
const DynamicPrintConfig * Plater : : config ( ) const { return p - > config ; }
2018-12-03 12:14:28 +00:00
void Plater : : set_printer_technology ( PrinterTechnology printer_technology )
{
p - > printer_technology = printer_technology ;
if ( p - > background_process . select_technology ( printer_technology ) ) {
// Update the active presets.
}
2019-08-06 16:16:02 +00:00
//FIXME for SLA synchronize
2018-12-03 12:14:28 +00:00
//p->background_process.apply(Model)!
2019-03-01 10:00:34 +00:00
2019-03-12 08:41:57 +00:00
p - > label_btn_export = printer_technology = = ptFFF ? L ( " Export G-code " ) : L ( " Export " ) ;
p - > label_btn_send = printer_technology = = ptFFF ? L ( " Send G-code " ) : L ( " Send to printer " ) ;
2019-04-30 11:51:36 +00:00
if ( wxGetApp ( ) . mainframe )
wxGetApp ( ) . mainframe - > update_menubar ( ) ;
2020-05-05 15:23:58 +00:00
p - > update_main_toolbar_tooltips ( ) ;
2020-05-06 18:45:57 +00:00
p - > sidebar - > get_searcher ( ) . set_printer_technology ( printer_technology ) ;
2018-12-03 12:14:28 +00:00
}
2018-10-31 14:41:27 +00:00
void Plater : : changed_object ( int obj_idx )
2018-10-08 14:27:38 +00:00
{
if ( obj_idx < 0 )
return ;
2019-04-21 23:51:10 +00:00
// recenter and re - align to Z = 0
auto model_object = p - > model . objects [ obj_idx ] ;
model_object - > ensure_on_bed ( ) ;
if ( this - > p - > printer_technology = = ptSLA ) {
// Update the SLAPrint from the current Model, so that the reload_scene()
// pulls the correct data, update the 3D scene.
this - > p - > update_restart_background_process ( true , false ) ;
2018-10-08 14:27:38 +00:00
}
2019-04-21 23:51:10 +00:00
else
p - > view3D - > reload_scene ( false ) ;
2018-10-08 14:27:38 +00:00
2018-11-07 14:29:13 +00:00
// update print
2018-12-03 12:14:28 +00:00
this - > p - > schedule_background_process ( ) ;
2018-10-08 14:27:38 +00:00
}
2019-04-15 13:40:40 +00:00
void Plater : : changed_objects ( const std : : vector < size_t > & object_idxs )
{
if ( object_idxs . empty ( ) )
return ;
2019-09-06 15:46:55 +00:00
for ( size_t obj_idx : object_idxs )
2019-04-21 23:51:10 +00:00
{
if ( obj_idx < p - > model . objects . size ( ) )
// recenter and re - align to Z = 0
p - > model . objects [ obj_idx ] - > ensure_on_bed ( ) ;
2019-04-15 13:40:40 +00:00
}
2019-04-21 23:51:10 +00:00
if ( this - > p - > printer_technology = = ptSLA ) {
// Update the SLAPrint from the current Model, so that the reload_scene()
// pulls the correct data, update the 3D scene.
this - > p - > update_restart_background_process ( true , false ) ;
}
else
p - > view3D - > reload_scene ( false ) ;
2019-04-15 13:40:40 +00:00
// update print
this - > p - > schedule_background_process ( ) ;
}
2019-06-26 07:48:52 +00:00
void Plater : : schedule_background_process ( bool schedule /* = true*/ )
2019-04-12 16:29:47 +00:00
{
2019-06-26 07:48:52 +00:00
if ( schedule )
this - > p - > schedule_background_process ( ) ;
this - > p - > suppressed_backround_processing_update = false ;
}
2020-03-12 15:11:25 +00:00
bool Plater : : is_background_process_update_scheduled ( ) const
2019-06-26 07:48:52 +00:00
{
return this - > p - > background_process_timer . IsRunning ( ) ;
}
void Plater : : suppress_background_process ( const bool stop_background_process )
{
if ( stop_background_process )
this - > p - > background_process_timer . Stop ( ) ;
this - > p - > suppressed_backround_processing_update = true ;
2019-04-12 16:29:47 +00:00
}
2019-01-30 15:27:07 +00:00
void Plater : : fix_through_netfabb ( const int obj_idx , const int vol_idx /* = -1*/ ) { p - > fix_through_netfabb ( obj_idx , vol_idx ) ; }
2018-09-17 10:15:11 +00:00
2018-12-07 16:50:48 +00:00
void Plater : : update_object_menu ( ) { p - > update_object_menu ( ) ; }
2020-03-06 14:10:58 +00:00
void Plater : : show_action_buttons ( const bool ready_to_slice ) const { p - > show_action_buttons ( ready_to_slice ) ; }
2018-12-07 16:50:48 +00:00
2019-04-10 06:40:58 +00:00
void Plater : : copy_selection_to_clipboard ( )
{
2020-06-01 09:11:38 +00:00
// At first try to copy selected values to the ObjectList's clipboard
// to check if Settings or Layers are selected in the list
// and then copy to 3DCanvas's clipboard if not
if ( can_copy_to_clipboard ( ) & & ! p - > sidebar - > obj_list ( ) - > copy_to_clipboard ( ) )
2019-06-24 11:21:05 +00:00
p - > view3D - > get_canvas3d ( ) - > get_selection ( ) . copy_to_clipboard ( ) ;
2019-04-10 06:40:58 +00:00
}
void Plater : : paste_from_clipboard ( )
{
2019-07-04 15:33:19 +00:00
if ( ! can_paste_from_clipboard ( ) )
return ;
2020-04-01 07:48:56 +00:00
Plater : : TakeSnapshot snapshot ( this , _L ( " Paste From Clipboard " ) ) ;
2020-06-01 09:11:38 +00:00
// At first try to paste values from the ObjectList's clipboard
// to check if Settings or Layers were copied
// and then paste from the 3DCanvas's clipboard if not
if ( ! p - > sidebar - > obj_list ( ) - > paste_from_clipboard ( ) )
p - > view3D - > get_canvas3d ( ) - > get_selection ( ) . paste_from_clipboard ( ) ;
2019-04-10 06:40:58 +00:00
}
2020-04-22 13:46:23 +00:00
void Plater : : search ( bool plater_is_active )
{
if ( plater_is_active ) {
2020-05-11 20:00:26 +00:00
// plater should be focused for correct navigation inside search window
this - > SetFocus ( ) ;
2020-04-22 13:46:23 +00:00
wxKeyEvent evt ;
# ifdef __APPLE__
evt . m_keyCode = ' f ' ;
# else /* __APPLE__ */
evt . m_keyCode = WXK_CONTROL_F ;
# endif /* __APPLE__ */
evt . SetControlDown ( true ) ;
canvas3D ( ) - > on_char ( evt ) ;
}
else
{
wxPoint pos = this - > ClientToScreen ( wxPoint ( 0 , 0 ) ) ;
pos . x + = em_unit ( this ) * 40 ;
pos . y + = em_unit ( this ) * 4 ;
p - > sidebar - > get_searcher ( ) . search_dialog - > Popup ( pos ) ;
}
}
2019-04-24 23:45:00 +00:00
void Plater : : msw_rescale ( )
2019-04-16 08:05:45 +00:00
{
2019-04-24 23:45:00 +00:00
p - > preview - > msw_rescale ( ) ;
2019-04-16 10:11:48 +00:00
2019-04-24 23:45:00 +00:00
p - > view3D - > get_canvas3d ( ) - > msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
2019-04-24 23:45:00 +00:00
p - > sidebar - > msw_rescale ( ) ;
2019-04-16 08:05:45 +00:00
2019-05-03 07:44:19 +00:00
p - > msw_rescale_object_menu ( ) ;
2019-04-16 08:05:45 +00:00
Layout ( ) ;
GetParent ( ) - > Layout ( ) ;
}
2020-05-21 15:29:00 +00:00
void Plater : : sys_color_changed ( )
{
p - > sidebar - > sys_color_changed ( ) ;
// msw_rescale_menu updates just icons, so use it
p - > msw_rescale_object_menu ( ) ;
Layout ( ) ;
GetParent ( ) - > Layout ( ) ;
}
2019-12-10 09:56:21 +00:00
bool Plater : : init_view_toolbar ( )
{
return p - > init_view_toolbar ( ) ;
}
2020-06-05 10:33:09 +00:00
bool Plater : : init_collapse_toolbar ( )
{
return p - > init_collapse_toolbar ( ) ;
}
2019-07-02 13:49:18 +00:00
const Camera & Plater : : get_camera ( ) const
{
return p - > camera ;
}
2020-03-02 09:58:46 +00:00
Camera & Plater : : get_camera ( )
{
return p - > camera ;
}
2020-05-28 13:27:29 +00:00
# if ENABLE_ENVIRONMENT_MAP
void Plater : : init_environment_texture ( )
{
if ( p - > environment_texture . get_id ( ) = = 0 )
p - > environment_texture . load_from_file ( resources_dir ( ) + " /icons/Pmetal_001.png " , false , GLTexture : : SingleThreaded , false ) ;
}
unsigned int Plater : : get_environment_texture_id ( ) const
{
return p - > environment_texture . get_id ( ) ;
}
# endif // ENABLE_ENVIRONMENT_MAP
2020-03-02 09:58:46 +00:00
const Bed3D & Plater : : get_bed ( ) const
{
return p - > bed ;
}
Bed3D & Plater : : get_bed ( )
{
return p - > bed ;
}
const GLToolbar & Plater : : get_view_toolbar ( ) const
{
return p - > view_toolbar ;
}
GLToolbar & Plater : : get_view_toolbar ( )
{
return p - > view_toolbar ;
}
2020-06-05 10:33:09 +00:00
const GLToolbar & Plater : : get_collapse_toolbar ( ) const
{
return p - > collapse_toolbar ;
}
GLToolbar & Plater : : get_collapse_toolbar ( )
{
return p - > collapse_toolbar ;
}
2019-09-27 12:52:19 +00:00
const Mouse3DController & Plater : : get_mouse3d_controller ( ) const
{
return p - > mouse3d_controller ;
}
Mouse3DController & Plater : : get_mouse3d_controller ( )
{
return p - > mouse3d_controller ;
}
2019-03-14 12:54:05 +00:00
bool Plater : : can_delete ( ) const { return p - > can_delete ( ) ; }
bool Plater : : can_delete_all ( ) const { return p - > can_delete_all ( ) ; }
bool Plater : : can_increase_instances ( ) const { return p - > can_increase_instances ( ) ; }
bool Plater : : can_decrease_instances ( ) const { return p - > can_decrease_instances ( ) ; }
2019-05-13 12:27:51 +00:00
bool Plater : : can_set_instance_to_object ( ) const { return p - > can_set_instance_to_object ( ) ; }
bool Plater : : can_fix_through_netfabb ( ) const { return p - > can_fix_through_netfabb ( ) ; }
2019-03-14 12:54:05 +00:00
bool Plater : : can_split_to_objects ( ) const { return p - > can_split_to_objects ( ) ; }
bool Plater : : can_split_to_volumes ( ) const { return p - > can_split_to_volumes ( ) ; }
bool Plater : : can_arrange ( ) const { return p - > can_arrange ( ) ; }
bool Plater : : can_layers_editing ( ) const { return p - > can_layers_editing ( ) ; }
2019-06-24 11:21:05 +00:00
bool Plater : : can_paste_from_clipboard ( ) const
{
const Selection & selection = p - > view3D - > get_canvas3d ( ) - > get_selection ( ) ;
const Selection : : Clipboard & clipboard = selection . get_clipboard ( ) ;
2020-06-01 09:11:38 +00:00
if ( clipboard . is_empty ( ) & & p - > sidebar - > obj_list ( ) - > clipboard_is_empty ( ) )
2019-06-24 11:21:05 +00:00
return false ;
if ( ( wxGetApp ( ) . preset_bundle - > printers . get_edited_preset ( ) . printer_technology ( ) = = ptSLA ) & & ! clipboard . is_sla_compliant ( ) )
return false ;
Selection : : EMode mode = clipboard . get_mode ( ) ;
if ( ( mode = = Selection : : Volume ) & & ! selection . is_from_single_instance ( ) )
return false ;
if ( ( mode = = Selection : : Instance ) & & ( selection . get_mode ( ) ! = Selection : : Instance ) )
return false ;
return true ;
}
bool Plater : : can_copy_to_clipboard ( ) const
{
if ( is_selection_empty ( ) )
return false ;
const Selection & selection = p - > view3D - > get_canvas3d ( ) - > get_selection ( ) ;
if ( ( wxGetApp ( ) . preset_bundle - > printers . get_edited_preset ( ) . printer_technology ( ) = = ptSLA ) & & ! selection . is_sla_compliant ( ) )
return false ;
return true ;
}
2019-03-14 12:54:05 +00:00
2019-07-26 11:44:33 +00:00
bool Plater : : can_undo ( ) const { return p - > undo_redo_stack ( ) . has_undo_snapshot ( ) ; }
bool Plater : : can_redo ( ) const { return p - > undo_redo_stack ( ) . has_redo_snapshot ( ) ; }
2019-09-19 07:09:11 +00:00
bool Plater : : can_reload_from_disk ( ) const { return p - > can_reload_from_disk ( ) ; }
2019-07-26 11:44:33 +00:00
const UndoRedo : : Stack & Plater : : undo_redo_stack_main ( ) const { return p - > undo_redo_stack_main ( ) ; }
void Plater : : enter_gizmos_stack ( ) { p - > enter_gizmos_stack ( ) ; }
void Plater : : leave_gizmos_stack ( ) { p - > leave_gizmos_stack ( ) ; }
2020-03-20 12:41:36 +00:00
bool Plater : : inside_snapshot_capture ( ) { return p - > inside_snapshot_capture ( ) ; }
2019-07-08 08:57:35 +00:00
2020-03-12 15:05:39 +00:00
// Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu.
bool Plater : : PopupMenu ( wxMenu * menu , const wxPoint & pos )
{
// Don't want to wake up and trigger reslicing while tracking the pop-up menu.
SuppressBackgroundProcessingUpdate sbpu ;
// When tracking a pop-up menu, postpone error messages from the slicing result.
m_tracking_popup_menu = true ;
bool out = this - > wxPanel : : PopupMenu ( menu , pos ) ;
m_tracking_popup_menu = false ;
if ( ! m_tracking_popup_menu_error_message . empty ( ) ) {
// Don't know whether the CallAfter is necessary, but it should not hurt.
// The menus likely sends out some commands, so we may be safer if the dialog is shown after the menu command is processed.
wxString message = std : : move ( m_tracking_popup_menu_error_message ) ;
wxTheApp - > CallAfter ( [ message , this ] ( ) { show_error ( this , message ) ; } ) ;
m_tracking_popup_menu_error_message . clear ( ) ;
}
return out ;
}
2019-07-08 08:57:35 +00:00
2019-06-26 07:48:52 +00:00
SuppressBackgroundProcessingUpdate : : SuppressBackgroundProcessingUpdate ( ) :
2020-03-12 15:11:25 +00:00
m_was_scheduled ( wxGetApp ( ) . plater ( ) - > is_background_process_update_scheduled ( ) )
2019-06-26 07:48:52 +00:00
{
2020-03-12 15:11:25 +00:00
wxGetApp ( ) . plater ( ) - > suppress_background_process ( m_was_scheduled ) ;
2019-06-26 07:48:52 +00:00
}
SuppressBackgroundProcessingUpdate : : ~ SuppressBackgroundProcessingUpdate ( )
{
2020-03-12 15:11:25 +00:00
wxGetApp ( ) . plater ( ) - > schedule_background_process ( m_was_scheduled ) ;
2019-06-26 07:48:52 +00:00
}
2018-09-17 10:15:11 +00:00
} } // namespace Slic3r::GUI