2018-09-17 10:15:11 +00:00
# include "Plater.hpp"
# include <cstddef>
# include <algorithm>
# include <vector>
# include <string>
# include <regex>
2018-12-06 16:32:49 +00:00
# include <boost/algorithm/string/predicate.hpp>
# include <boost/algorithm/string/trim.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>
# 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-10 11:53:45 +00:00
# include <wx/colordlg.h>
2018-10-18 13:13:38 +00:00
# include <wx/numdlg.h>
# include <wx/debug.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"
2018-09-17 10:15:11 +00:00
# include "libslic3r/Model.hpp"
2018-11-12 13:52:52 +00:00
# include "libslic3r/ModelArrange.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-11-26 13:41:58 +00:00
# include "libslic3r/SLA/SLARotfinder.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"
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"
# include "3DScene.hpp"
2018-10-03 09:34:39 +00:00
# include "GLCanvas3D.hpp"
2018-09-17 10:15:11 +00:00
# include "GLToolbar.hpp"
# include "GUI_Preview.hpp"
# include "Tab.hpp"
# include "PresetBundle.hpp"
# include "BackgroundSlicingProcess.hpp"
# include "ProgressStatusBar.hpp"
2018-12-11 09:33:11 +00:00
# include "PrintHostDialogs.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"
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"
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 ;
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 ;
2018-11-01 11:33:56 +00:00
bool showing_manifold_warning_icon ;
void show_sizer ( bool show ) ;
2018-09-17 10:15:11 +00:00
} ;
ObjectInfo : : ObjectInfo ( wxWindow * parent ) :
wxStaticBoxSizer ( new wxStaticBox ( parent , wxID_ANY , _ ( L ( " Info " ) ) ) , wxVERTICAL )
{
2018-10-01 13:09:31 +00:00
GetStaticBox ( ) - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
2018-09-17 10:15:11 +00:00
auto * grid_sizer = new wxFlexGridSizer ( 4 , 5 , 5 ) ;
grid_sizer - > SetFlexibleDirection ( wxHORIZONTAL ) ;
grid_sizer - > AddGrowableCol ( 1 , 1 ) ;
grid_sizer - > AddGrowableCol ( 3 , 1 ) ;
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-01-21 11:34:28 +00:00
init_info_label ( & info_size , _ ( L ( " Size " ) ) ) ;
init_info_label ( & info_volume , _ ( L ( " Volume " ) ) ) ;
init_info_label ( & info_facets , _ ( L ( " Facets " ) ) ) ;
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
2019-01-21 11:34:28 +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 ( ) ) ;
2018-09-17 10:15:11 +00:00
wxBitmap bitmap ( GUI : : from_u8 ( Slic3r : : var ( " error.png " ) ) , wxBITMAP_TYPE_PNG ) ;
manifold_warning_icon = new wxStaticBitmap ( parent , wxID_ANY , bitmap ) ;
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 ) ;
}
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
}
2018-10-31 11:26:57 +00:00
enum SlisedInfoIdx
{
siFilament_m ,
siFilament_mm3 ,
siFilament_g ,
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 ) ;
2018-11-20 09:33:54 +00:00
void SetTextAndShow ( SlisedInfoIdx 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 ) :
wxStaticBoxSizer ( new wxStaticBox ( parent , wxID_ANY , _ ( L ( " Sliced Info " ) ) ) , wxVERTICAL )
{
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
} ;
2018-10-31 11:26:57 +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 ( " Cost " ) ) ) ;
2018-11-20 09:33:54 +00:00
init_info_label ( _ ( L ( " Estimated printing time " ) ) ) ;
2018-10-31 11:26:57 +00:00
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 ) ;
}
2018-11-20 09:33:54 +00:00
void SlicedInfo : : SetTextAndShow ( SlisedInfoIdx 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
}
PresetComboBox : : PresetComboBox ( wxWindow * parent , Preset : : Type preset_type ) :
2019-02-04 09:35:16 +00:00
wxBitmapComboBox ( parent , wxID_ANY , wxEmptyString , wxDefaultPosition , wxSize ( 15 * wxGetApp ( ) . em_unit ( ) , - 1 ) , 0 , nullptr , wxCB_READONLY ) ,
2018-09-17 10:15:11 +00:00
preset_type ( preset_type ) ,
last_selected ( wxNOT_FOUND )
{
Bind ( wxEVT_COMBOBOX , [ this ] ( wxCommandEvent & evt ) {
auto selected_item = this - > GetSelection ( ) ;
auto marker = reinterpret_cast < Marker > ( this - > GetClientData ( selected_item ) ) ;
if ( marker = = LABEL_ITEM_MARKER ) {
this - > SetSelection ( this - > last_selected ) ;
evt . StopPropagation ( ) ;
2018-12-21 09:58:00 +00:00
} else if ( this - > last_selected ! = selected_item | |
wxGetApp ( ) . get_tab ( this - > preset_type ) - > get_presets ( ) - > current_is_dirty ( ) ) {
2018-09-17 10:15:11 +00:00
this - > last_selected = selected_item ;
evt . SetInt ( this - > preset_type ) ;
2018-10-09 10:41:05 +00:00
evt . Skip ( ) ;
2018-09-17 10:15:11 +00:00
} else {
evt . StopPropagation ( ) ;
}
} ) ;
2018-10-10 11:53:45 +00:00
if ( preset_type = = Slic3r : : Preset : : TYPE_FILAMENT )
{
Bind ( wxEVT_LEFT_DOWN , [ this ] ( wxMouseEvent & event ) {
if ( extruder_idx < 0 | | event . GetLogicalPosition ( wxClientDC ( this ) ) . x > 24 ) {
// Let the combo box process the mouse click.
event . Skip ( ) ;
return ;
}
// Swallow the mouse click and open the color picker.
auto data = new wxColourData ( ) ;
data - > SetChooseFull ( 1 ) ;
2019-01-02 16:54:54 +00:00
auto dialog = new wxColourDialog ( /* wxGetApp().mainframe */ this , data ) ;
dialog - > CenterOnParent ( ) ;
2018-10-10 11:53:45 +00:00
if ( dialog - > ShowModal ( ) = = wxID_OK ) {
DynamicPrintConfig cfg = * wxGetApp ( ) . get_tab ( Preset : : TYPE_PRINTER ) - > get_config ( ) ;
2018-10-17 09:12:38 +00:00
//FIXME this is too expensive to call full_config to get just the extruder color!
2018-10-10 11:53:45 +00:00
auto colors = static_cast < ConfigOptionStrings * > ( wxGetApp ( ) . preset_bundle - > full_config ( ) . option ( " extruder_colour " ) - > clone ( ) ) ;
colors - > values [ extruder_idx ] = dialog - > GetColourData ( ) . GetColour ( ) . GetAsString ( wxC2S_HTML_SYNTAX ) ;
cfg . set_key_value ( " extruder_colour " , colors ) ;
wxGetApp ( ) . get_tab ( Preset : : TYPE_PRINTER ) - > load_config ( cfg ) ;
wxGetApp ( ) . preset_bundle - > update_platter_filament_ui ( extruder_idx , this ) ;
2018-10-17 09:12:38 +00:00
wxGetApp ( ) . plater ( ) - > on_config_change ( cfg ) ;
2018-10-10 11:53:45 +00:00
}
dialog - > Destroy ( ) ;
} ) ;
}
2018-09-17 10:15:11 +00:00
}
PresetComboBox : : ~ PresetComboBox ( ) { }
2018-10-09 10:41:05 +00:00
void PresetComboBox : : set_label_marker ( int item )
{
this - > SetClientData ( item , ( void * ) LABEL_ITEM_MARKER ) ;
}
2018-12-03 14:16:33 +00:00
void PresetComboBox : : check_selection ( )
{
if ( this - > last_selected ! = GetSelection ( ) )
this - > last_selected = GetSelection ( ) ;
}
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 ;
2018-10-04 14:43:10 +00:00
public :
FreqChangedParams ( wxWindow * parent , const int label_width ) ;
~ 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 ) ;
2018-10-04 14:43:10 +00:00
} ;
FreqChangedParams : : FreqChangedParams ( wxWindow * parent , const int label_width ) :
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-02-07 13:44:05 +00:00
m_og - > label_width = label_width = = 0 ? 1 : label_width ;
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 ) ) ;
}
2018-12-11 15:33:43 +00:00
else { //(opt_key == "support")
2018-10-04 14:43:10 +00:00
const wxString & selection = boost : : any_cast < wxString > ( value ) ;
auto support_material = selection = = _ ( " None " ) ? false : true ;
new_conf . set_key_value ( " support_material " , new ConfigOptionBool ( support_material ) ) ;
if ( selection = = _ ( " Everywhere " ) )
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( false ) ) ;
else if ( selection = = _ ( " Support on build plate only " ) )
new_conf . set_key_value ( " support_material_buildplate_only " , new ConfigOptionBool ( true ) ) ;
}
tab_print - > load_config ( new_conf ) ;
}
tab_print - > update_dirty ( ) ;
} ;
2019-02-07 13:44:05 +00:00
Line line = Line { " " , " " } ;
2018-10-04 14:43:10 +00:00
ConfigOptionDef def ;
2019-02-07 13:44:05 +00:00
def . label = L ( " Supports " ) ;
2018-10-04 14:43:10 +00:00
def . type = coStrings ;
def . gui_type = " select_open " ;
def . tooltip = L ( " Select what kind of support do you need " ) ;
def . enum_labels . push_back ( L ( " None " ) ) ;
def . enum_labels . push_back ( L ( " Support on build plate only " ) ) ;
def . enum_labels . push_back ( L ( " Everywhere " ) ) ;
2019-02-07 13:44:05 +00:00
const std : : string selection = ! config - > opt_bool ( " support_material " ) ?
" None " : config - > opt_bool ( " support_material_buildplate_only " ) ?
" Support on build plate only " :
" Everywhere " ;
2018-10-04 14:43:10 +00:00
def . default_value = new ConfigOptionStrings { selection } ;
2019-02-07 13:44:05 +00:00
Option option = Option ( 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 ) ;
m_og - > append_line ( line ) ;
line = Line { " " , " " } ;
option = m_og - > get_option ( " fill_density " ) ;
option . opt . label = L ( " Infill " ) ;
option . opt . width = 7 * wxGetApp ( ) . em_unit ( ) ;
option . opt . sidetext = " " ;
line . append_option ( option ) ;
2018-10-04 14:43:10 +00:00
m_brim_width = config - > opt_float ( " brim_width " ) ;
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 = " " ;
def . default_value = new ConfigOptionBool { m_brim_width > 0.0 ? true : false } ;
option = Option ( def , " brim " ) ;
2019-02-07 13:44:05 +00:00
option . opt . sidetext = " " ;
line . append_option ( option ) ;
2018-10-04 14:43:10 +00:00
2019-02-07 13:44:05 +00:00
auto wiping_dialog_btn = [ config , this ] ( wxWindow * parent ) {
2018-10-04 14:43:10 +00:00
m_wiping_dialog_button = new wxButton ( parent , wxID_ANY , _ ( L ( " Purging volumes " ) ) + dots , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT ) ;
auto sizer = new wxBoxSizer ( wxHORIZONTAL ) ;
sizer - > Add ( m_wiping_dialog_button ) ;
m_wiping_dialog_button - > Bind ( wxEVT_BUTTON , ( [ parent ] ( wxCommandEvent & e )
{
auto & config = wxGetApp ( ) . preset_bundle - > project_config ;
const std : : vector < double > & init_matrix = ( config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) ) - > values ;
const std : : vector < double > & init_extruders = ( config . option < ConfigOptionFloats > ( " wiping_volumes_extruders " ) ) - > values ;
WipingDialog dlg ( parent , cast < float > ( init_matrix ) , cast < float > ( init_extruders ) ) ;
if ( dlg . ShowModal ( ) = = wxID_OK ) {
std : : vector < float > matrix = dlg . get_matrix ( ) ;
std : : vector < float > extruders = dlg . get_extruders ( ) ;
( config . option < ConfigOptionFloats > ( " wiping_volumes_matrix " ) ) - > values = std : : vector < double > ( matrix . begin ( ) , matrix . end ( ) ) ;
( 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
}
} ) ) ;
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
// Frequently changed parameters for SLA_technology
m_og_sla = std : : make_shared < ConfigOptionsGroup > ( parent , " " ) ;
DynamicPrintConfig * config_sla = & wxGetApp ( ) . preset_bundle - > sla_prints . get_edited_preset ( ) . config ;
m_og_sla - > set_config ( config_sla ) ;
2019-02-07 13:44:05 +00:00
m_og_sla - > label_width = label_width = = 0 ? 1 : label_width ;
2019-01-15 08:31:53 +00:00
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 ;
tab - > set_value ( opt_key , value ) ;
DynamicPrintConfig new_conf = * config_sla ;
new_conf . set_key_value ( opt_key , new ConfigOptionBool ( boost : : any_cast < bool > ( value ) ) ) ;
tab - > load_config ( new_conf ) ;
tab - > update_dirty ( ) ;
} ;
2019-02-07 13:44:05 +00:00
line = Line { " " , " " } ;
option = m_og_sla - > get_option ( " supports_enable " ) ;
option . opt . sidetext = " " ;
line . append_option ( option ) ;
option = m_og_sla - > get_option ( " pad_enable " ) ;
option . opt . sidetext = " " ;
line . append_option ( option ) ;
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
// 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
struct Sidebar : : priv
{
2018-10-04 09:12:55 +00:00
Plater * plater ;
2018-09-17 10:15:11 +00:00
wxScrolledWindow * scrolled ;
2019-01-10 10:05:58 +00:00
PrusaModeSizer * mode_sizer ;
2018-09-17 10:15:11 +00:00
wxFlexGridSizer * sizer_presets ;
PresetComboBox * combo_print ;
std : : vector < PresetComboBox * > combos_filament ;
wxBoxSizer * sizer_filaments ;
2018-11-16 16:36:23 +00:00
PresetComboBox * combo_sla_print ;
2018-09-17 10:15:11 +00:00
PresetComboBox * combo_sla_material ;
PresetComboBox * combo_printer ;
wxBoxSizer * sizer_params ;
2018-10-04 14:43:10 +00:00
FreqChangedParams * frequently_changed_parameters ;
ObjectList * object_list ;
ObjectManipulation * object_manipulation ;
2018-11-09 17:39:07 +00:00
ObjectSettings * object_settings ;
2018-09-17 10:15:11 +00:00
ObjectInfo * object_info ;
SlicedInfo * sliced_info ;
wxButton * btn_export_gcode ;
wxButton * btn_reslice ;
wxButton * btn_send_gcode ;
2018-10-04 09:12:55 +00:00
priv ( Plater * plater ) : plater ( plater ) { }
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
} ;
2018-10-10 11:53:45 +00:00
void Sidebar : : priv : : show_preset_comboboxes ( )
{
2018-11-13 16:45:44 +00:00
const bool showSLA = plater - > printer_technology ( ) = = ptSLA ;
2018-10-10 11:53:45 +00:00
2018-11-15 10:15:24 +00:00
wxWindowUpdateLocker noUpdates_scrolled ( scrolled - > GetParent ( ) ) ;
2018-11-09 17:39:07 +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 )
: wxPanel ( parent ) , p ( new priv ( parent ) )
2018-09-17 10:15:11 +00:00
{
2019-02-06 08:49:32 +00:00
p - > scrolled = new wxScrolledWindow ( this , wxID_ANY , wxDefaultPosition , wxSize ( 40 * wxGetApp ( ) . em_unit ( ) , - 1 ) ) ;
2018-12-18 12:22:22 +00:00
p - > scrolled - > SetScrollbars ( 0 , 20 , 1 , 2 ) ;
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-02-11 14:36:05 +00:00
p - > mode_sizer = new PrusaModeSizer ( p - > scrolled , 2 * wxGetApp ( ) . em_unit ( ) ) ;
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 ) ;
2018-09-17 10:15:11 +00:00
p - > sizer_filaments = new wxBoxSizer ( wxVERTICAL ) ;
auto init_combo = [ this ] ( PresetComboBox * * combo , wxString label , Preset : : Type preset_type , bool filament ) {
2019-02-07 13:44:05 +00:00
auto * text = new wxStaticText ( p - > scrolled , wxID_ANY , label + " : " ) ;
2018-10-01 13:09:31 +00:00
text - > SetFont ( wxGetApp ( ) . small_font ( ) ) ;
* combo = new PresetComboBox ( p - > scrolled , preset_type ) ;
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-02-07 13:44:05 +00:00
sizer_presets - > Add ( * combo , 0 , wxEXPAND | wxBOTTOM , 1 ) ;
2018-09-17 10:15:11 +00:00
} else {
2019-02-07 13:44:05 +00:00
sizer_filaments - > Add ( * combo , 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 ) ;
2018-11-16 16:36:23 +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 " ) ) , 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
2018-10-04 14:43:10 +00:00
// calculate width of the preset labels
2019-02-07 13:44:05 +00:00
// p->sizer_presets->Layout();
// const wxArrayInt& ar = p->sizer_presets->GetColWidths();
// const int label_width = ar.IsEmpty() ? 10*wxGetApp().em_unit() : ar.front()-4;
const int margin_5 = int ( 0.5 * wxGetApp ( ) . em_unit ( ) ) ; // 5;
const int margin_10 = int ( 1.5 * wxGetApp ( ) . em_unit ( ) ) ; // 15;
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-02-07 13:44:05 +00:00
p - > frequently_changed_parameters = new FreqChangedParams ( p - > scrolled , 0 /*label_width*/ ) ;
p - > sizer_params - > Add ( p - > frequently_changed_parameters - > get_sizer ( ) , 0 , wxEXPAND | wxTOP | wxBOTTOM , margin_10 ) ;
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 ) ;
2018-10-04 14:43:10 +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 ) ;
2018-11-09 17:39:07 +00:00
2018-09-17 10:15:11 +00:00
wxBitmap arrow_up ( GUI : : from_u8 ( Slic3r : : var ( " brick_go.png " ) ) , wxBITMAP_TYPE_PNG ) ;
2018-12-11 09:33:11 +00:00
p - > btn_send_gcode = new wxButton ( this , wxID_ANY , _ ( L ( " Send to printer " ) ) ) ;
2018-09-17 10:15:11 +00:00
p - > btn_send_gcode - > SetBitmap ( arrow_up ) ;
2018-12-11 09:33:11 +00:00
p - > btn_send_gcode - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
2018-09-17 10:15:11 +00:00
p - > btn_send_gcode - > Hide ( ) ;
// 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*/ ) ;
scrolled_sizer - > Add ( p - > sizer_presets , 0 , wxEXPAND | wxLEFT , margin_5 ) ;
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-01-21 11:34:28 +00:00
p - > btn_export_gcode = new wxButton ( this , wxID_ANY , _ ( L ( " Export G-code " ) ) + dots ) ;
2018-10-01 13:09:31 +00:00
p - > btn_export_gcode - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
2018-09-17 10:15:11 +00:00
p - > btn_reslice = new wxButton ( this , wxID_ANY , _ ( L ( " Slice now " ) ) ) ;
2018-10-01 13:09:31 +00:00
p - > btn_reslice - > SetFont ( wxGetApp ( ) . bold_font ( ) ) ;
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-02-07 13:44:05 +00:00
btns_sizer - > Add ( p - > btn_reslice , 0 , wxEXPAND | wxTOP , margin_5 ) ;
btns_sizer - > Add ( p - > btn_send_gcode , 0 , wxEXPAND | wxTOP , margin_5 ) ;
btns_sizer - > Add ( p - > btn_export_gcode , 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
p - > btn_export_gcode - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > export_gcode ( ) ; } ) ;
p - > btn_reslice - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > reslice ( ) ; } ) ;
p - > btn_send_gcode - > Bind ( wxEVT_BUTTON , [ this ] ( wxCommandEvent & ) { p - > plater - > send_gcode ( ) ; } ) ;
2018-09-17 10:15:11 +00:00
}
Sidebar : : ~ Sidebar ( ) { }
2018-10-10 11:53:45 +00:00
void Sidebar : : init_filament_combo ( PresetComboBox * * combo , const int extr_idx ) {
* combo = new PresetComboBox ( p - > scrolled , Slic3r : : Preset : : TYPE_FILAMENT ) ;
// # copy icons from first choice
// $choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets;
( * combo ) - > set_extruder_idx ( extr_idx ) ;
auto /***/ sizer_filaments = this - > p - > sizer_filaments ;
sizer_filaments - > Add ( * combo , 1 , wxEXPAND | wxBOTTOM , 1 ) ;
}
void Sidebar : : remove_unused_filament_combos ( const int current_extruder_count )
{
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 ( ) ;
}
}
2018-09-17 10:15:11 +00:00
void Sidebar : : update_presets ( Preset : : Type preset_type )
{
2018-10-31 15:22:36 +00:00
PresetBundle & preset_bundle = * wxGetApp ( ) . preset_bundle ;
2018-09-17 10:15:11 +00:00
switch ( preset_type ) {
2019-01-15 14:54:20 +00:00
case Preset : : TYPE_FILAMENT :
{
const int extruder_cnt = p - > plater - > printer_technology ( ) ! = ptFFF ? 1 :
dynamic_cast < ConfigOptionFloats * > ( preset_bundle . printers . get_edited_preset ( ) . config . option ( " nozzle_diameter " ) ) - > values . size ( ) ;
const int filament_cnt = p - > combos_filament . size ( ) > extruder_cnt ? extruder_cnt : p - > combos_filament . size ( ) ;
if ( filament_cnt = = 1 ) {
2018-09-17 10:15:11 +00:00
// Single filament printer, synchronize the filament presets.
2019-01-15 14:54:20 +00:00
const std : : string & name = preset_bundle . filaments . get_selected_preset ( ) . name ;
preset_bundle . set_filament_preset ( 0 , name ) ;
2018-09-17 10:15:11 +00:00
}
2019-01-15 14:54:20 +00:00
for ( size_t i = 0 ; i < filament_cnt ; i + + ) {
preset_bundle . update_platter_filament_ui ( i , p - > combos_filament [ i ] ) ;
2018-09-17 10:15:11 +00:00
}
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 :
2018-10-31 15:22:36 +00:00
preset_bundle . prints . update_platter_ui ( p - > combo_print ) ;
2018-09-17 10:15:11 +00:00
break ;
2018-11-16 16:36:23 +00:00
case Preset : : TYPE_SLA_PRINT :
preset_bundle . sla_prints . update_platter_ui ( p - > combo_sla_print ) ;
break ;
2018-09-17 10:15:11 +00:00
case Preset : : TYPE_SLA_MATERIAL :
2018-10-31 15:22:36 +00:00
preset_bundle . sla_materials . update_platter_ui ( p - > combo_sla_material ) ;
2018-09-17 10:15:11 +00:00
break ;
2018-10-31 15:22:36 +00:00
case Preset : : TYPE_PRINTER :
{
// Update the print choosers to only contain the compatible presets, update the dirty flags.
2018-11-13 16:45:44 +00:00
if ( p - > plater - > printer_technology ( ) = = ptFFF )
2018-10-31 15:22:36 +00:00
preset_bundle . prints . update_platter_ui ( p - > combo_print ) ;
2018-11-16 16:36:23 +00:00
else {
preset_bundle . sla_prints . update_platter_ui ( p - > combo_sla_print ) ;
preset_bundle . sla_materials . update_platter_ui ( p - > combo_sla_material ) ;
}
2018-10-31 15:22:36 +00:00
// Update the printer choosers, update the dirty flags.
2018-12-03 14:16:33 +00:00
auto prev_selection = p - > combo_printer - > GetSelection ( ) ;
2018-10-31 15:22:36 +00:00
preset_bundle . printers . update_platter_ui ( p - > combo_printer ) ;
2018-12-03 14:16:33 +00:00
if ( prev_selection ! = p - > combo_printer - > GetSelection ( ) )
p - > combo_printer - > check_selection ( ) ;
2018-10-31 15:22:36 +00:00
// Update the filament choosers to only contain the compatible presets, update the color preview,
// update the dirty flags.
2018-11-13 16:45:44 +00:00
if ( p - > plater - > printer_technology ( ) = = ptFFF ) {
2018-10-31 15:22:36 +00:00
for ( size_t i = 0 ; i < p - > combos_filament . size ( ) ; + + i )
preset_bundle . update_platter_filament_ui ( i , p - > combos_filament [ i ] ) ;
}
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-01-10 10:05:58 +00:00
void Sidebar : : update_mode_sizer ( const Slic3r : : ConfigOptionMode & mode )
{
p - > mode_sizer - > SetMode ( mode ) ;
}
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 ;
}
wxScrolledWindow * Sidebar : : scrolled_panel ( )
{
return p - > scrolled ;
}
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 ( ) ;
}
void Sidebar : : update_objects_list_extruder_column ( int extruders_count )
{
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 ;
}
2018-11-01 11:33:56 +00:00
const ModelInstance * model_instance = ! model_object - > instances . empty ( ) ? model_object - > instances . front ( ) : nullptr ;
2018-11-01 13:02:38 +00:00
2018-11-15 10:15:24 +00:00
auto size = model_object - > bounding_box ( ) . size ( ) ;
2018-11-01 11:33:56 +00:00
p - > object_info - > info_size - > SetLabel ( wxString : : Format ( " %.2f x %.2f x %.2f " , size ( 0 ) , size ( 1 ) , size ( 2 ) ) ) ;
p - > object_info - > info_materials - > SetLabel ( wxString : : Format ( " %d " , static_cast < int > ( model_object - > materials_count ( ) ) ) ) ;
2018-11-13 14:24:05 +00:00
auto & stats = model_object - > volumes . front ( ) - > mesh . stl . stats ;
2018-12-17 14:45:20 +00:00
p - > object_info - > info_volume - > SetLabel ( wxString : : Format ( " %.2f " , size ( 0 ) * size ( 1 ) * size ( 2 ) ) ) ;
2018-11-01 11:33: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 ) ) ;
int errors = stats . degenerate_facets + stats . edges_fixed + stats . facets_removed +
stats . facets_added + stats . facets_reversed + stats . backwards_edges ;
if ( errors > 0 ) {
wxString tooltip = wxString : : Format ( _ ( L ( " Auto-repaired (%d errors) " ) ) , errors ) ;
p - > object_info - > info_manifold - > SetLabel ( tooltip ) ;
2019-01-21 11:34:28 +00:00
tooltip + = " : \n " + wxString : : Format ( _ ( L ( " %d degenerate facets, %d edges fixed, %d facets removed, "
2018-11-01 11:33:56 +00:00
" %d facets added, %d facets reversed, %d backwards edges " ) ) ,
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 ) ;
}
else {
p - > object_info - > info_manifold - > SetLabel ( L ( " Yes " ) ) ;
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 ) ;
2018-10-31 11:26:57 +00:00
}
void Sidebar : : show_sliced_info_sizer ( const bool show )
{
2018-11-13 11:19:56 +00:00
wxWindowUpdateLocker freeze_guard ( this ) ;
2018-11-01 11:33:56 +00:00
2018-10-31 11:26:57 +00:00
p - > sliced_info - > Show ( show ) ;
if ( show ) {
2018-12-03 12:14:28 +00:00
const PrintStatistics & ps = p - > plater - > fff_print ( ) . print_statistics ( ) ;
2018-10-31 11:26:57 +00:00
const bool is_wipe_tower = ps . total_wipe_tower_filament > 0 ;
2018-11-20 09:33:54 +00:00
wxString new_label = _ ( L ( " Used Filament (m) " ) ) ;
if ( is_wipe_tower )
new_label + = wxString : : Format ( " : \n - %s \n - %s " , _ ( L ( " objects " ) ) , _ ( L ( " wipe tower " ) ) ) ;
2018-10-31 11:26:57 +00:00
wxString info_text = is_wipe_tower ?
2018-11-20 09:33:54 +00:00
wxString : : Format ( " %.2f \n %.2f \n %.2f " , ps . total_used_filament / 1000 ,
( ps . total_used_filament - ps . total_wipe_tower_filament ) / 1000 ,
ps . total_wipe_tower_filament / 1000 ) :
2018-10-31 11:26:57 +00:00
wxString : : Format ( " %.2f " , ps . total_used_filament / 1000 ) ;
2018-11-20 09:33:54 +00:00
p - > sliced_info - > SetTextAndShow ( siFilament_m , info_text , new_label ) ;
2018-10-31 11:26:57 +00:00
p - > sliced_info - > SetTextAndShow ( siFilament_mm3 , wxString : : Format ( " %.2f " , ps . total_extruded_volume ) ) ;
p - > sliced_info - > SetTextAndShow ( siFilament_g , wxString : : Format ( " %.2f " , ps . total_weight ) ) ;
2018-11-20 09:33:54 +00:00
new_label = _ ( L ( " Cost " ) ) ;
if ( is_wipe_tower )
new_label + = wxString : : Format ( " : \n - %s \n - %s " , _ ( L ( " objects " ) ) , _ ( L ( " wipe tower " ) ) ) ;
2018-10-31 11:26:57 +00:00
info_text = is_wipe_tower ?
2018-11-20 09:33:54 +00:00
wxString : : Format ( " %.2f \n %.2f \n %.2f " , ps . total_cost ,
( ps . total_cost - ps . total_wipe_tower_cost ) ,
ps . total_wipe_tower_cost ) :
2018-10-31 11:26:57 +00:00
wxString : : Format ( " %.2f " , ps . total_cost ) ;
2018-11-20 09:33:54 +00:00
p - > sliced_info - > SetTextAndShow ( siCost , info_text , new_label ) ;
if ( ps . estimated_normal_print_time = = " N/A " & & ps . estimated_silent_print_time = = " N/A " )
p - > sliced_info - > SetTextAndShow ( siEstimatedTime , " N/A " ) ;
else {
2019-01-21 11:34:28 +00:00
new_label = _ ( L ( " Estimated printing time " ) ) + " : " ;
2018-11-20 09:33:54 +00:00
info_text = " " ;
if ( ps . estimated_normal_print_time ! = " N/A " ) {
new_label + = wxString : : Format ( " \n - %s " , _ ( L ( " normal mode " ) ) ) ;
info_text + = wxString : : Format ( " \n %s " , ps . estimated_normal_print_time ) ;
}
if ( ps . estimated_silent_print_time ! = " N/A " ) {
new_label + = wxString : : Format ( " \n - %s " , _ ( L ( " silent mode " ) ) ) ;
info_text + = wxString : : Format ( " \n %s " , ps . estimated_silent_print_time ) ;
}
p - > sliced_info - > SetTextAndShow ( siEstimatedTime , info_text , new_label ) ;
}
2018-10-31 11:26:57 +00:00
// if there is a wipe tower, insert number of toolchanges info into the array:
2018-12-03 12:14:28 +00:00
p - > sliced_info - > SetTextAndShow ( siWTNumbetOfToolchanges , is_wipe_tower ? wxString : : Format ( " %.d " , p - > plater - > fff_print ( ) . wipe_tower_data ( ) . number_of_toolchanges ) : " N/A " ) ;
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 ) ;
}
2018-12-11 09:33:11 +00:00
void Sidebar : : show_reslice ( bool show ) { p - > btn_reslice - > Show ( show ) ; }
void Sidebar : : show_send ( bool show ) { p - > btn_send_gcode - > 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
}
2018-10-10 11:53:45 +00:00
std : : vector < PresetComboBox * > & Sidebar : : combos_filament ( )
{
return p - > combos_filament ;
}
2018-09-17 10:15:11 +00:00
// Plater::DropTarget
class PlaterDropTarget : public wxFileDropTarget
{
public :
2019-02-01 07:53:29 +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 ;
}
}
plater - > load_files ( paths ) ;
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-01-25 12:16:32 +00:00
PrusaMenu object_menu ;
2018-12-07 16:50:48 +00:00
// Part popup menu
2019-01-25 12:16:32 +00:00
PrusaMenu part_menu ;
2018-12-07 16:50:48 +00:00
// SLA-Object popup menu
2019-01-25 12:16:32 +00:00
PrusaMenu sla_object_menu ;
2019-01-25 09:34:32 +00:00
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 ;
2018-11-13 16:45:44 +00:00
Slic3r : : SLAPrint sla_print ;
Slic3r : : Model model ;
PrinterTechnology printer_technology = ptFFF ;
Slic3r : : GCodePreviewData gcode_preview_data ;
2018-09-17 10:15:11 +00:00
// GUI elements
2018-12-04 12:55:25 +00:00
wxSizer * panel_sizer ;
wxPanel * current_panel ;
std : : vector < wxPanel * > panels ;
2018-09-17 10:15:11 +00:00
Sidebar * sidebar ;
2018-12-04 12:55:25 +00:00
View3D * view3D ;
2018-12-17 09:55:14 +00:00
GLToolbar view_toolbar ;
2018-10-04 14:43:10 +00:00
Preview * preview ;
2018-11-15 14:27:39 +00:00
wxString project_filename ;
2018-10-17 09:12:38 +00:00
BackgroundSlicingProcess background_process ;
2018-11-12 13:52:52 +00:00
std : : atomic < bool > arranging ;
2018-11-22 15:04:21 +00:00
std : : atomic < bool > rotoptimizing ;
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
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
# if ENABLE_VOLUMES_CENTERING_FIXES
static const std : : regex pattern_prusa ;
# endif // ENABLE_VOLUMES_CENTERING_FIXES
2018-09-17 10:15:11 +00:00
priv ( Plater * q , MainFrame * main_frame ) ;
2018-11-21 12:52:46 +00:00
void update ( bool force_full_scene_refresh = false ) ;
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 ( ) ;
2018-09-17 10:15:11 +00:00
void update_ui_from_settings ( ) ;
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 ;
2018-11-16 08:26:41 +00:00
std : : vector < size_t > load_files ( const std : : vector < fs : : path > & input_files , bool load_model , bool load_config ) ;
2018-10-01 14:48:08 +00:00
std : : vector < size_t > load_model_objects ( const ModelObjectPtrs & model_objects ) ;
2018-10-04 09:12:55 +00:00
std : : unique_ptr < CheckboxFileDialog > get_export_file ( GUI : : FileType file_type ) ;
2018-10-17 07:30:07 +00:00
const GLCanvas3D : : Selection & get_selection ( ) const ;
GLCanvas3D : : Selection & get_selection ( ) ;
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 ( ) ;
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 arrange ( ) ;
2018-11-22 15:04:21 +00:00
void sla_optimize_rotation ( ) ;
2018-10-09 07:35:19 +00:00
void split_object ( ) ;
2018-10-24 10:55:38 +00:00
void split_volume ( ) ;
2018-12-03 12:14:28 +00:00
bool background_processing_enabled ( ) const { return this - > get_config ( " background_processing " ) = = " 1 " ; }
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))
2018-11-13 16:45:44 +00:00
UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE = 2 ,
// 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-01-10 15:06:24 +00:00
unsigned int update_background_process ( bool force_validation = 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-02-03 09:41:14 +00:00
// returns bit mask of UpdateBackgroundProcessReturnState
unsigned int update_restart_background_process ( bool force_scene_update , bool force_preview_update ) ;
2018-12-11 09:33:11 +00:00
void export_gcode ( fs : : path output_path , PrintHostJob upload_job ) ;
2018-10-09 07:35:19 +00:00
void reload_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 & ) ;
2018-10-08 17:55:30 +00:00
void on_viewport_changed ( SimpleEvent & ) ;
void on_right_click ( Vec2dEvent & ) ;
void on_wipetower_moved ( Vec3dEvent & ) ;
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 ( ) ;
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-12-06 09:38:19 +00:00
void init_view_toolbar ( ) ;
2018-10-18 07:27:37 +00:00
bool can_delete_object ( ) const ;
bool can_increase_instances ( ) const ;
bool can_decrease_instances ( ) const ;
2019-01-22 15:40:10 +00:00
bool can_set_instance_to_object ( ) const ;
2018-10-24 10:55:38 +00:00
bool can_split_to_objects ( ) const ;
bool can_split_to_volumes ( ) const ;
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-10-18 13:09:41 +00:00
bool can_delete_all ( ) const ;
bool can_arrange ( ) const ;
bool can_mirror ( ) 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 ( ) ;
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
# if ENABLE_VOLUMES_CENTERING_FIXES
const std : : regex Plater : : priv : : pattern_prusa ( " .*prusa " , std : : regex : : icase ) ;
# endif // ENABLE_VOLUMES_CENTERING_FIXES
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-02-08 11:30:10 +00:00
" bed_shape " , " 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 " ,
" brim_width " , " perimeters " , " perimeter_extruder " , " fill_density " , " infill_extruder " , " top_solid_layers " , " bottom_solid_layers " , " solid_infill_extruder " ,
" 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 ) )
2018-11-23 11:47:32 +00:00
, delayed_scene_refresh ( false )
2018-11-15 14:27:39 +00:00
, project_filename ( wxEmptyString )
2018-12-17 09:55:14 +00:00
, view_toolbar ( GLToolbar : : Radio )
2018-09-17 10:15:11 +00:00
{
2018-11-15 08:46:55 +00:00
arranging . store ( false ) ;
2018-11-30 14:41:45 +00:00
rotoptimizing . store ( false ) ;
2018-12-03 12:14:28 +00:00
background_process . set_fff_print ( & fff_print ) ;
2018-11-08 19:18:40 +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 ) ;
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 ) ;
2018-11-08 19:18:40 +00:00
// Default printer technology for default config.
2018-11-13 16:45:44 +00:00
background_process . select_technology ( this - > printer_technology ) ;
2018-10-23 13:27:31 +00:00
// Register progress callback from the Print class to the Platter.
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
2018-12-04 12:55:25 +00:00
view3D = new View3D ( q , & model , config , & background_process ) ;
preview = new Preview ( q , config , & background_process , & gcode_preview_data , [ this ] ( ) { schedule_background_process ( ) ; } ) ;
2018-12-20 21:30:42 +00:00
// Let the Tab key switch between the 3D view and the layer preview.
2018-12-21 10:39:37 +00:00
view3D - > Bind ( wxEVT_NAVIGATION_KEY , [ this ] ( wxNavigationKeyEvent & evt ) { if ( evt . IsFromTab ( ) ) this - > select_next_view_3D ( ) ; } ) ;
preview - > Bind ( wxEVT_NAVIGATION_KEY , [ this ] ( wxNavigationKeyEvent & evt ) { if ( evt . IsFromTab ( ) ) this - > select_next_view_3D ( ) ; } ) ;
2018-11-26 09:56:07 +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 ) ;
2018-12-22 09:02:42 +00:00
this - > q - > Bind ( wxEVT_TIMER , [ this ] ( wxTimerEvent & evt ) { this - > update_restart_background_process ( false , false ) ; } ) ;
2018-09-17 10:15:11 +00:00
2019-01-17 12:21:33 +00:00
# if !ENABLE_REWORKED_BED_SHAPE_CHANGE
2018-09-17 10:15:11 +00:00
auto * bed_shape = config - > opt < ConfigOptionPoints > ( " bed_shape " ) ;
2018-12-04 12:55:25 +00:00
view3D - > set_bed_shape ( bed_shape - > values ) ;
2018-09-17 10:15:11 +00:00
preview - > set_bed_shape ( bed_shape - > values ) ;
2019-01-17 12:21:33 +00:00
# endif // !ENABLE_REWORKED_BED_SHAPE_CHANGE
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 ( ) ;
// 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_VIEWPORT_CHANGED , & priv : : on_viewport_changed , 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 ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_ARRANGE , [ this ] ( SimpleEvent & ) { arrange ( ) ; } ) ;
2019-02-03 13:06:13 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_SELECT_ALL , [ this ] ( SimpleEvent & ) { this - > q - > select_all ( ) ; } ) ;
2018-12-19 13:01:13 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_QUESTION_MARK , [ this ] ( SimpleEvent & ) { wxGetApp ( ) . keyboard_shortcuts ( ) ; } ) ;
2018-12-19 11:07:45 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_INCREASE_INSTANCES , [ this ] ( Event < int > & evt )
{ 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 ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLCANVAS_WIPETOWER_MOVED , & priv : : on_wipetower_moved , 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 ) ;
// 3DScene/Toolbar:
view3D_canvas - > Bind ( EVT_GLTOOLBAR_ADD , & priv : : on_action_add , this ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_DELETE , [ q ] ( SimpleEvent & ) { q - > remove_selected ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_DELETE_ALL , [ this ] ( SimpleEvent & ) { reset ( ) ; } ) ;
view3D_canvas - > Bind ( EVT_GLTOOLBAR_ARRANGE , [ this ] ( SimpleEvent & ) { arrange ( ) ; } ) ;
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 ) ;
2018-12-06 09:38:19 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_INIT , [ this ] ( SimpleEvent & ) { init_view_toolbar ( ) ; } ) ;
2018-10-04 09:12:55 +00:00
2018-10-08 17:55:30 +00:00
// Preview events:
2018-10-04 08:41:11 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_VIEWPORT_CHANGED , & priv : : on_viewport_changed , this ) ;
2018-12-22 09:02:42 +00:00
preview - > get_wxglcanvas ( ) - > Bind ( EVT_GLCANVAS_QUESTION_MARK , [ this ] ( SimpleEvent & ) { wxGetApp ( ) . keyboard_shortcuts ( ) ; } ) ;
2019-01-03 11:59:06 +00:00
2018-12-06 09:38:19 +00:00
view3D_canvas - > Bind ( EVT_GLCANVAS_INIT , [ this ] ( SimpleEvent & ) { init_view_toolbar ( ) ; } ) ;
2018-09-17 10:15:11 +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
update_ui_from_settings ( ) ;
q - > Layout ( ) ;
2018-12-20 11:51:42 +00:00
set_current_panel ( view3D ) ;
2018-09-17 10:15:11 +00:00
}
2018-11-21 12:52:46 +00:00
void Plater : : priv : : update ( bool force_full_scene_refresh )
2018-09-17 10:15:11 +00:00
{
2018-10-01 14:48:08 +00:00
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 ;
if ( this - > printer_technology = = ptSLA )
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-01-10 15:06:24 +00:00
update_status = this - > update_background_process ( false ) ;
2018-12-22 09:02:42 +00:00
this - > view3D - > reload_scene ( false , force_full_scene_refresh ) ;
this - > preview - > reload_print ( ) ;
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
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 ( )
{
// TODO: (?)
// my ($self) = @_;
// if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! wxTheApp->{app_config}->get("background_processing"))) {
// $self->{buttons_sizer}->Show($self->{btn_reslice}, ! wxTheApp->{app_config}->get("background_processing"));
// $self->{buttons_sizer}->Layout;
// }
2019-01-24 12:16:46 +00:00
# if ENABLE_RETINA_GL
view3D - > get_canvas3d ( ) - > update_ui_from_settings ( ) ;
preview - > get_canvas3d ( ) - > update_ui_from_settings ( ) ;
# endif
2018-09-17 10:15:11 +00:00
}
2018-10-23 13:27:31 +00:00
ProgressStatusBar * Plater : : priv : : statusbar ( )
2018-09-17 10:15:11 +00:00
{
return main_frame - > m_statusbar ;
}
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 ( ) ;
}
2018-11-16 08:26:41 +00:00
std : : vector < size_t > Plater : : priv : : load_files ( const std : : vector < fs : : path > & input_files , bool load_model , bool load_config )
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 " ) ;
bool one_by_one = input_files . size ( ) = = 1 | | nozzle_dmrs - > values . size ( ) < = 1 ;
if ( ! one_by_one ) {
for ( const auto & path : input_files ) {
if ( std : : regex_match ( path . string ( ) , pattern_bundle ) ) {
one_by_one = true ;
break ;
}
}
}
2019-01-21 11:34:28 +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 ( ) ;
2019-01-02 14:11:05 +00:00
const auto dlg_info = wxString : : Format ( _ ( L ( " Processing input file %s \n " ) ) , from_path ( filename ) ) ;
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
# if ENABLE_VOLUMES_CENTERING_FIXES
const bool type_prusa = std : : regex_match ( path . string ( ) , pattern_prusa ) ;
# endif // ENABLE_VOLUMES_CENTERING_FIXES
2018-09-17 10:15:11 +00:00
Slic3r : : Model model ;
try {
if ( type_3mf | | type_zip_amf ) {
DynamicPrintConfig config ;
2018-11-06 18:09:54 +00:00
{
DynamicPrintConfig config_loaded ;
model = Slic3r : : Model : : read_from_archive ( path . string ( ) , & config_loaded , false ) ;
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,
PrinterTechnology printer_technology = Preset : : printer_technology ( config_loaded ) ;
config . apply ( printer_technology = = ptFFF ?
2018-11-06 18:09:54 +00:00
static_cast < const ConfigBase & > ( FullPrintConfig : : defaults ( ) ) :
static_cast < const ConfigBase & > ( SLAFullPrintConfig : : defaults ( ) ) ) ;
// and place the loaded config over the base.
config + = std : : move ( config_loaded ) ;
}
}
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 ( ) ;
}
wxGetApp ( ) . app_config - > update_config_dir ( path . parent_path ( ) . string ( ) ) ;
}
}
else {
2018-09-17 10:15:11 +00:00
model = Slic3r : : Model : : read_from_file ( path . string ( ) , nullptr , false ) ;
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
2019-01-18 11:52:09 +00:00
# if ENABLE_VOLUMES_CENTERING_FIXES
2019-01-18 15:01:43 +00:00
if ( ! type_3mf & & ! type_any_amf & & ! type_prusa ) {
2019-01-18 11:52:09 +00:00
# endif // ENABLE_VOLUMES_CENTERING_FIXES
if ( model . looks_like_multipart_object ( ) ) {
2019-01-21 13:43:57 +00:00
wxMessageDialog dlg ( q , _ ( L (
2019-01-21 11:34:28 +00:00
" This file contains several objects positioned at multiple heights. "
" Instead of considering them as multiple objects, should I consider \n "
" this file as a single object having multiple parts? \n "
2019-01-21 13:43:57 +00:00
) ) , _ ( L ( " Multi-part object detected " ) ) , wxICON_WARNING | wxYES | wxNO ) ;
if ( dlg . ShowModal ( ) = = wxID_YES ) {
model . convert_multipart_object ( nozzle_dmrs - > values . size ( ) ) ;
}
2019-01-18 11:52:09 +00:00
}
# if ENABLE_VOLUMES_CENTERING_FIXES
2018-09-17 10:15:11 +00:00
}
2019-01-18 11:52:09 +00:00
# endif // ENABLE_VOLUMES_CENTERING_FIXES
2018-09-17 10:15:11 +00:00
2019-01-18 11:52:09 +00:00
# if !ENABLE_VOLUMES_CENTERING_FIXES
2019-01-03 11:04:14 +00:00
if ( type_3mf | | type_any_amf ) {
2019-01-18 11:52:09 +00:00
# endif // !ENABLE_VOLUMES_CENTERING_FIXES
2018-11-16 08:26:41 +00:00
for ( ModelObject * model_object : model . objects ) {
model_object - > center_around_origin ( ) ;
model_object - > ensure_on_bed ( ) ;
}
2019-01-18 11:52:09 +00:00
# if !ENABLE_VOLUMES_CENTERING_FIXES
2018-09-17 10:15:11 +00:00
}
2019-01-18 11:52:09 +00:00
# endif // !ENABLE_VOLUMES_CENTERING_FIXES
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 ) {
Slic3r : : GUI : : show_error ( nullptr ,
wxString : : Format ( _ ( L ( " You can't to add the object(s) from %s because of one or some of them is(are) multi-part " ) ) ,
2019-01-02 14:11:05 +00:00
from_path ( filename ) ) ) ;
2018-12-10 12:39:56 +00:00
return std : : vector < size_t > ( ) ;
}
}
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
}
}
}
if ( new_model ! = nullptr ) {
wxMessageDialog dlg ( q , _ ( L (
" Multiple objects were loaded for a multi-material printer. \n "
" Instead of considering them as multiple objects, should I consider \n "
" these files to represent a single object having multiple parts? \n "
) ) , _ ( L ( " Multi-part object detected " ) ) , wxICON_WARNING | wxYES | wxNO ) ;
if ( dlg . ShowModal ( ) = = wxID_YES ) {
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...
statusbar ( ) - > set_status_text ( _ ( L ( " Loaded " ) ) ) ;
}
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 ) )
{
GLCanvas3D : : Selection & selection = view3D - > get_canvas3d ( ) - > get_selection ( ) ;
selection . clear ( ) ;
for ( size_t idx : obj_idxs )
{
selection . add_object ( ( unsigned int ) idx , false ) ;
}
}
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 */
// if object has no defined position(s) we need to rearrange everything after loading object->center_around_origin();
need_arrange = true ;
// add a default instance and center object around origin
object - > center_around_origin ( ) ; // also aligns object to Z = 0
ModelInstance * instance = object - > add_instance ( ) ;
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
2018-12-18 17:41:20 +00:00
double inv = 1. / max_ratio ;
2018-12-19 08:54:15 +00:00
object - > scale_mesh ( Vec3d ( inv , inv , inv ) ) ;
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-10-18 16:06:40 +00:00
// print.auto_assign_extruders(object);
// print.add_model_object(object);
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-01-23 12:12:44 +00:00
arr : : find_new_position ( model , new_instances , min_obj_distance , bed ) ;
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 ,
_ ( L ( " Your object appears to be too large, so it was automatically scaled down to fit your print bed. " ) ) ,
_ ( L ( " Object too large? " ) ) ) ;
}
for ( const size_t idx : obj_idxs ) {
2018-10-08 14:27:38 +00:00
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
}
2018-10-04 09:12:55 +00:00
std : : unique_ptr < CheckboxFileDialog > Plater : : priv : : get_export_file ( GUI : : FileType file_type )
{
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 :
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 ( ) ;
// Find the file name of the first printable object.
2019-02-03 09:41:14 +00:00
fs : : path output_file = this - > model . propose_export_file_name_and_path ( ) ;
2018-10-04 09:12:55 +00:00
switch ( file_type ) {
case FT_STL : output_file . replace_extension ( " stl " ) ; break ;
case FT_AMF : output_file . replace_extension ( " zip.amf " ) ; break ; // XXX: Problem on OS X with double extension?
case FT_3MF : output_file . replace_extension ( " 3mf " ) ; break ;
default : break ;
}
auto dlg = Slic3r : : make_unique < CheckboxFileDialog > ( q ,
2018-11-16 09:14:52 +00:00
( ( file_type = = FT_AMF ) | | ( file_type = = FT_3MF ) ) ? _ ( L ( " Export print config " ) ) : " " ,
2018-10-04 09:12:55 +00:00
true ,
_ ( L ( " Save file as: " ) ) ,
2019-01-02 14:11:05 +00:00
from_path ( output_file . parent_path ( ) ) ,
from_path ( output_file . filename ( ) ) ,
2018-10-04 09:12:55 +00:00
wildcard ,
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
) ;
if ( dlg - > ShowModal ( ) ! = wxID_OK ) {
return nullptr ;
}
2019-01-02 14:11:05 +00:00
fs : : path path ( into_path ( dlg - > GetPath ( ) ) ) ;
2018-10-04 09:12:55 +00:00
wxGetApp ( ) . app_config - > update_last_output_dir ( path . parent_path ( ) . string ( ) ) ;
return dlg ;
}
2018-10-17 07:30:07 +00:00
const GLCanvas3D : : Selection & Plater : : priv : : get_selection ( ) const
{
2018-12-04 12:55:25 +00:00
return view3D - > get_canvas3d ( ) - > get_selection ( ) ;
2018-10-17 07:30:07 +00:00
}
GLCanvas3D : : Selection & Plater : : priv : : get_selection ( )
{
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 ( ) ;
if ( ( 0 > idx ) | | ( idx > 1000 ) )
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 ( )
{
2018-12-04 12:55:25 +00:00
view3D - > enable_toolbar_item ( " delete " , can_delete_object ( ) ) ;
view3D - > enable_toolbar_item ( " more " , can_increase_instances ( ) ) ;
view3D - > enable_toolbar_item ( " fewer " , can_decrease_instances ( ) ) ;
2018-12-17 14:44:30 +00:00
view3D - > enable_toolbar_item ( " splitobjects " , can_split /*_to_objects*/ ( ) ) ;
view3D - > enable_toolbar_item ( " splitvolumes " , can_split /*_to_volumes*/ ( ) ) ;
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
view3D - > enable_toolbar_item ( " layersediting " , enable_layer_editing ) ;
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-12-04 12:55:25 +00:00
// Enable/disable buttons depending on whether there are any objects on the platter.
view3D - > enable_toolbar_item ( " deleteall " , can_delete_all ( ) ) ;
view3D - > enable_toolbar_item ( " arrange " , can_arrange ( ) ) ;
2018-10-08 17:14: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?
2018-12-04 12:55:25 +00:00
const bool model_fits = view3D - > check_volumes_outside_state ( ) = = ModelInstance : : PVS_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
}
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 ) ;
// Delete object from Sidebar list
2018-10-12 10:00:37 +00:00
sidebar - > obj_list ( ) - > delete_object_from_list ( obj_idx ) ;
2018-10-08 17:14:55 +00:00
object_list_changed ( ) ;
update ( ) ;
}
2018-11-13 13:17:35 +00:00
void Plater : : priv : : delete_object_from_model ( size_t obj_idx )
{
model . delete_object ( obj_idx ) ;
2018-11-14 10:22:13 +00:00
object_list_changed ( ) ;
update ( ) ;
2018-11-13 13:17:35 +00:00
}
2018-10-08 17:14:55 +00:00
void Plater : : priv : : reset ( )
{
2018-11-15 14:27:39 +00:00
project_filename . Clear ( ) ;
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 ( ) ;
// Delete all objects from list on c++ side
sidebar - > obj_list ( ) - > delete_all_objects_from_list ( ) ;
2018-10-08 17:14:55 +00:00
object_list_changed ( ) ;
2018-10-04 09:12:55 +00:00
update ( ) ;
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
auto & config = wxGetApp ( ) . preset_bundle - > project_config ;
config . option < ConfigOptionFloats > ( " colorprint_heights " ) - > values . 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
}
void Plater : : priv : : arrange ( )
{
2018-11-12 13:52:52 +00:00
// don't do anything if currently arranging. Then this is a re-entrance
if ( arranging . load ( ) ) return ;
// Guard the arrange process
arranging . store ( true ) ;
2019-02-03 13:06:13 +00:00
wxBusyCursor wait ;
2018-11-21 10:07:08 +00:00
// Disable the arrange button (to prevent reentrancies, we will call wxYied)
2018-12-04 12:55:25 +00:00
view3D - > enable_toolbar_item ( " arrange " , can_arrange ( ) ) ;
2018-11-12 13:52:52 +00:00
this - > background_process . stop ( ) ;
unsigned count = 0 ;
for ( auto obj : model . objects ) count + = obj - > instances . size ( ) ;
auto prev_range = statusbar ( ) - > get_range ( ) ;
statusbar ( ) - > set_range ( count ) ;
auto statusfn = [ this , count ] ( unsigned st , const std : : string & msg ) {
/* // In case we would run the arrange asynchronously
wxCommandEvent event ( EVT_PROGRESS_BAR ) ;
event . SetInt ( st ) ;
event . SetString ( msg ) ;
wxQueueEvent ( this - > q , event . Clone ( ) ) ; */
statusbar ( ) - > set_progress ( count - st ) ;
statusbar ( ) - > set_status_text ( msg ) ;
// ok, this is dangerous, but we are protected by the atomic flag
2018-11-21 10:07:08 +00:00
// 'arranging' and the arrange button is also disabled.
// This call is needed for the cancel button to work.
2018-11-12 13:52:52 +00:00
wxYieldIfNeeded ( ) ;
} ;
statusbar ( ) - > set_cancel_callback ( [ this , statusfn ] ( ) {
arranging . store ( false ) ;
statusfn ( 0 , L ( " Arranging canceled " ) ) ;
} ) ;
static const std : : string arrangestr = L ( " Arranging " ) ;
// FIXME: I don't know how to obtain the minimum distance, it depends
// on printer technology. I guess the following should work but it crashes.
double dist = 6 ; //PrintConfig::min_object_distance(config);
2019-02-08 11:30:10 +00:00
if ( printer_technology = = ptFFF ) {
dist = PrintConfig : : min_object_distance ( config ) ;
}
2018-11-12 13:52:52 +00:00
2019-02-08 11:30:10 +00:00
auto min_obj_distance = coord_t ( dist / SCALING_FACTOR ) ;
2018-11-12 13:52:52 +00:00
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 ) ) ) ;
statusfn ( 0 , arrangestr ) ;
try {
arr : : BedShapeHint hint ;
// TODO: from Sasha from GUI or
hint . type = arr : : BedShapeType : : WHO_KNOWS ;
arr : : arrange ( model ,
min_obj_distance ,
bed ,
hint ,
false , // create many piles not just one pile
[ statusfn ] ( unsigned st ) { statusfn ( st , arrangestr ) ; } ,
[ this ] ( ) { return ! arranging . load ( ) ; } ) ;
} catch ( std : : exception & /*e*/ ) {
GUI : : show_error ( this - > q , L ( " Could not arrange model objects! "
" Some geometries may be invalid. " ) ) ;
}
statusfn ( 0 , L ( " Arranging done. " ) ) ;
statusbar ( ) - > set_range ( prev_range ) ;
statusbar ( ) - > set_cancel_callback ( ) ; // remove cancel button
arranging . store ( false ) ;
2018-11-21 10:07:08 +00:00
// We enable back the arrange button
2018-12-04 12:55:25 +00:00
view3D - > enable_toolbar_item ( " arrange " , can_arrange ( ) ) ;
2018-11-21 10:07:08 +00:00
2018-11-21 12:52:46 +00:00
// Do a full refresh of scene tree, including regenerating all the GLVolumes.
//FIXME The update function shall just reload the modified matrices.
update ( true ) ;
2018-10-09 07:35:19 +00:00
}
2018-11-22 15:04:21 +00:00
// This method will find an optimal orientation for the currently selected item
// Very similar in nature to the arrange method above...
void Plater : : priv : : sla_optimize_rotation ( ) {
// TODO: we should decide whether to allow arrange when the search is
// running we should probably disable explicit slicing and background
// processing
if ( rotoptimizing . load ( ) ) return ;
rotoptimizing . store ( true ) ;
int obj_idx = get_selected_object_idx ( ) ;
ModelObject * o = model . objects [ obj_idx ] ;
background_process . stop ( ) ;
auto prev_range = statusbar ( ) - > get_range ( ) ;
statusbar ( ) - > set_range ( 100 ) ;
auto stfn = [ this ] ( unsigned st , const std : : string & msg ) {
statusbar ( ) - > set_progress ( st ) ;
statusbar ( ) - > set_status_text ( msg ) ;
// could be problematic, but we need the cancel button.
wxYieldIfNeeded ( ) ;
} ;
statusbar ( ) - > set_cancel_callback ( [ this , stfn ] ( ) {
rotoptimizing . store ( false ) ;
stfn ( 0 , L ( " Orientation search canceled " ) ) ;
} ) ;
auto r = sla : : find_best_rotation (
2018-11-27 10:09:25 +00:00
* o , .005f ,
2018-11-22 15:04:21 +00:00
[ stfn ] ( unsigned s ) { stfn ( s , L ( " Searching for optimal orientation " ) ) ; } ,
[ this ] ( ) { return ! rotoptimizing . load ( ) ; }
) ;
if ( rotoptimizing . load ( ) ) // wasn't canceled
for ( ModelInstance * oi : o - > instances ) oi - > set_rotation ( { r [ X ] , r [ Y ] , r [ Z ] } ) ;
2018-11-29 10:45:02 +00:00
// Correct the z offset of the object which was corrupted be the rotation
o - > ensure_on_bed ( ) ;
2018-11-22 15:04:21 +00:00
stfn ( 0 , L ( " Orientation found. " ) ) ;
statusbar ( ) - > set_range ( prev_range ) ;
statusbar ( ) - > set_cancel_callback ( ) ;
rotoptimizing . store ( false ) ;
update ( true ) ;
}
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 ;
// 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 )
{
Slic3r : : GUI : : warning_catcher ( q , _ ( L ( " The selected object can't be split because it contains more than one volume/material. " ) ) ) ;
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 )
Slic3r : : GUI : : warning_catcher ( q , _ ( L ( " The selected object couldn't be split because it contains only one part. " ) ) ) ;
else
{
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
}
2018-10-09 07:35:19 +00:00
void Plater : : priv : : schedule_background_process ( )
{
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-01-10 15:06:24 +00:00
unsigned int Plater : : priv : : update_background_process ( bool force_validation )
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 ;
2018-12-22 09:02:42 +00:00
// If the update_background_process() was not called by the timer, kill the timer,
// 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 ( ) ;
2019-02-19 13:57:59 +00:00
// The delayed error message is no more valid.
this - > delayed_error_message . clear ( ) ;
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.
2018-11-13 16:45:44 +00:00
switch ( this - > printer_technology ) {
case ptFFF :
2018-11-08 19:18:40 +00:00
if ( this - > preview ! = nullptr )
2018-11-13 16:45:44 +00:00
// If the preview is not visible, the following line just invalidates the preview,
// but the G-code paths are calculated first once the preview is made visible.
2018-11-08 19:18:40 +00:00
this - > preview - > reload_print ( ) ;
// We also need to reload 3D scene because of the wipe tower preview box
2018-12-06 14:40:41 +00:00
if ( this - > config - > opt_bool ( " wipe_tower " ) )
2018-11-13 16:45:44 +00:00
return_state | = UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE ;
break ;
case ptSLA :
2018-11-22 11:42:17 +00:00
return_state | = UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE ;
2018-11-13 16:45:44 +00:00
break ;
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 ( ) ) {
// 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 ( ) ) {
2018-12-22 09:02:42 +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 ) ;
if ( top_level_wnd & & top_level_wnd - > IsActive ( ) ) {
// The error returned from the Print needs to be translated into the local language.
GUI : : show_error ( this - > q , _ ( err ) ) ;
} else {
// Show the error message once the main window gets activated.
this - > delayed_error_message = _ ( err ) ;
}
2018-11-13 16:45:44 +00:00
return_state | = UPDATE_BACKGROUND_PROCESS_INVALID ;
}
}
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 ) {
// 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 ( ) ) ;
}
2019-02-21 10:40:56 +00:00
//FIXME update "Slice Now / Schedule background process"
//background_process.is_export_scheduled() - byl zavolan "Export G-code", background processing ma jmeno export souboru
//background_process.is_upload_scheduled() - byl zavolan "Send to OctoPrint", jeste nebylo doslajsovano (pak se preda upload fronte a background process zapomene)
//background_process.empty() - prazdna plocha
2019-02-21 11:39:38 +00:00
// pokud (return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0 -> doslo k chybe (gray out "Slice now") mozna "Invalid data"???
// jinak background_process.running() -> Zobraz "Slicing ..."
// jinak pokud ! background_process.empty() && ! background_process.finished() -> je neco ke slajsovani (povol tlacitko) "Slice Now"
2019-02-21 10:40:56 +00:00
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 )
{
if ( ! this - > background_process . empty ( ) & &
( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID ) = = 0 & &
( ( ( state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART ) ! = 0 & & ! this - > background_process . finished ( ) ) | |
( 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 ] ( ) {
this - > statusbar ( ) - > set_status_text ( L ( " Cancelling " ) ) ;
this - > background_process . stop ( ) ;
} ) ;
return true ;
}
}
return false ;
}
2018-12-11 09:33:11 +00:00
void Plater : : priv : : export_gcode ( fs : : path output_path , PrintHostJob upload_job )
{
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 ( ) ) {
GUI : : show_error ( q , _ ( L ( " Another export job is currently running. " ) ) ) ;
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 ( ) ) {
background_process . schedule_export ( output_path . string ( ) ) ;
} else {
background_process . schedule_upload ( std : : move ( upload_job ) ) ;
}
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-02-03 09:41:14 +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:
view3D - > reload_scene ( true ) ;
}
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 ( )
{
2018-12-05 14:22:03 +00:00
const auto & selection = get_selection ( ) ;
const auto obj_orig_idx = selection . get_object_idx ( ) ;
if ( selection . is_wipe_tower ( ) | | obj_orig_idx = = - 1 ) { return ; }
2018-10-09 07:35:19 +00:00
2018-12-05 14:22:03 +00:00
auto * object_orig = model . objects [ obj_orig_idx ] ;
std : : vector < fs : : path > input_paths ( 1 , object_orig - > input_file ) ;
const auto new_idxs = load_files ( input_paths , true , false ) ;
for ( const auto idx : new_idxs ) {
ModelObject * object = model . objects [ idx ] ;
object - > clear_instances ( ) ;
for ( const ModelInstance * instance : object_orig - > instances ) {
object - > add_instance ( * instance ) ;
}
if ( object - > volumes . size ( ) = = object_orig - > volumes . size ( ) ) {
for ( size_t i = 0 ; i < object - > volumes . size ( ) ; i + + ) {
object - > volumes [ i ] - > config . apply ( object_orig - > volumes [ i ] - > config ) ;
}
}
2019-01-21 09:06:51 +00:00
// XXX: Restore more: layer_height_ranges, layer_height_profile (?)
2018-12-05 14:22:03 +00:00
}
remove ( obj_orig_idx ) ;
2018-10-09 07:35:19 +00:00
}
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-02-03 21:14:34 +00:00
fix_model_by_win10_sdk_gui ( * model . objects [ obj_idx ] , vol_idx ) ;
this - > object_list_changed ( ) ;
this - > update ( ) ;
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 ;
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 )
p - > Show ( ) ;
}
// 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
}
// 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 )
{
2018-12-11 16:49:31 +00:00
this - > q - > reslice ( ) ;
2018-12-04 12:55:25 +00:00
preview - > reload_print ( ) ;
preview - > set_canvas_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 ( ) ) ;
2018-10-10 11:53:45 +00:00
auto * combo = static_cast < PresetComboBox * > ( evt . GetEventObject ( ) ) ;
2018-09-17 10:15:11 +00:00
2018-10-10 11:53:45 +00:00
auto idx = combo - > get_extruder_idx ( ) ;
2018-10-09 10:41:05 +00:00
2018-10-15 09:39:48 +00:00
//! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox,
//! but the OSX version derived from wxOwnerDrawnCombo.
//! So, to get selected string we do
//! combo->GetString(combo->GetSelection())
//! instead of
2019-01-03 13:34:53 +00:00
//! combo->GetStringSelection().ToUTF8().data());
2018-10-15 09:39:48 +00:00
std : : string selected_string = combo - > GetString ( combo - > GetSelection ( ) ) . ToUTF8 ( ) . data ( ) ;
2018-09-17 10:15:11 +00:00
if ( preset_type = = Preset : : TYPE_FILAMENT ) {
2018-10-15 09:39:48 +00:00
wxGetApp ( ) . preset_bundle - > set_filament_preset ( idx , selected_string ) ;
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 ( ) ) {
2018-10-10 11:53:45 +00:00
// Only update the platter UI for the 2nd and other filaments.
2018-10-09 10:41:05 +00:00
wxGetApp ( ) . preset_bundle - > update_platter_filament_ui ( idx , combo ) ;
2018-10-10 11:53:45 +00:00
}
else {
2018-10-09 10:41:05 +00:00
for ( Tab * tab : wxGetApp ( ) . tabs_list ) {
if ( tab - > type ( ) = = preset_type ) {
2018-10-15 09:39:48 +00:00
tab - > select_preset ( selected_string ) ;
2018-10-09 10:41:05 +00:00
break ;
}
}
2018-09-17 10:15:11 +00:00
}
2018-10-15 09:39:48 +00:00
// update plater with new config
2018-10-17 09:12:38 +00:00
wxGetApp ( ) . plater ( ) - > on_config_change ( wxGetApp ( ) . preset_bundle - > full_config ( ) ) ;
2018-11-29 14:00:23 +00:00
if ( preset_type = = Preset : : TYPE_PRINTER )
wxGetApp ( ) . obj_list ( ) - > update_settings_items ( ) ;
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
{
2018-11-20 12:22:26 +00:00
this - > statusbar ( ) - > set_progress ( evt . status . percent ) ;
this - > statusbar ( ) - > set_status_text ( _ ( L ( evt . status . text ) ) + wxString : : FromUTF8 ( " … " ) ) ;
2018-11-20 15:27:30 +00:00
if ( evt . status . flags & PrintBase : : SlicingStatus : : RELOAD_SCENE ) {
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-02-06 13:18:04 +00:00
if ( evt . status . flags & PrintBase : : SlicingStatus : : RELOAD_SLA_SUPPORT_POINTS ) {
2019-02-19 12:47:28 +00:00
// Update SLA gizmo (reload_scene calls update_gizmos_data)
2019-02-06 14:16:25 +00:00
q - > canvas3D ( ) - > reload_scene ( true ) ;
2019-02-06 13:18:04 +00:00
}
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 ;
}
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 ( ) ;
2018-10-25 08:07:11 +00:00
bool canceled = evt . GetInt ( ) < 0 ;
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 ( ) ;
if ( ! success ) {
wxString message = evt . GetString ( ) ;
if ( message . IsEmpty ( ) )
message = _ ( L ( " Export failed " ) ) ;
this - > statusbar ( ) - > set_status_text ( message ) ;
2018-10-18 16:06:40 +00:00
}
2018-10-25 08:07:11 +00:00
if ( canceled )
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 ( ) ;
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 ;
2018-11-12 16:35:57 +00:00
}
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 ) ;
if ( enable & & ! view3D - > is_layers_editing_enabled ( ) ) {
// Initialization of the OpenGL shaders failed. Disable the tool.
view3D - > enable_toolbar_item ( " layersediting " , false ) ;
}
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 & )
{
2018-12-04 12:55:25 +00:00
bool enable = ! view3D - > is_layers_editing_enabled ( ) ;
view3D - > enable_layers_editing ( enable ) ;
if ( enable & & ! view3D - > is_layers_editing_enabled ( ) )
view3D - > enable_toolbar_item ( " layersediting " , false ) ;
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
2018-10-03 12:25:35 +00:00
void Plater : : priv : : on_viewport_changed ( SimpleEvent & evt )
{
wxObject * o = evt . GetEventObject ( ) ;
2018-12-04 12:55:25 +00:00
if ( o = = preview - > get_wxglcanvas ( ) )
preview - > set_viewport_into_scene ( view3D - > get_canvas3d ( ) ) ;
else if ( o = = view3D - > get_wxglcanvas ( ) )
preview - > set_viewport_from_scene ( view3D - > get_canvas3d ( ) ) ;
2018-10-03 12:25:35 +00:00
}
2018-10-17 10:17:25 +00:00
void Plater : : priv : : on_right_click ( Vec2dEvent & evt )
2018-10-08 17:55:30 +00:00
{
2018-10-17 10:17:25 +00:00
int obj_idx = get_selected_object_idx ( ) ;
if ( obj_idx = = - 1 )
return ;
2018-12-07 16:50:48 +00:00
wxMenu * menu = printer_technology = = ptSLA ? & sla_object_menu :
2019-01-25 09:34:32 +00:00
get_selection ( ) . is_single_full_instance ( ) ? // show "Object menu" for each FullInstance instead of FullObject
2018-12-13 12:19:11 +00:00
& object_menu : & part_menu ;
2018-12-07 16:50:48 +00:00
sidebar - > obj_list ( ) - > append_menu_item_settings ( menu ) ;
2018-10-17 12:26:13 +00:00
if ( q ! = nullptr )
2018-12-07 16:50:48 +00:00
q - > PopupMenu ( menu , ( int ) evt . data . x ( ) , ( int ) evt . data . y ( ) ) ;
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
}
void Plater : : priv : : on_update_geometry ( Vec3dsEvent < 2 > & )
{
// TODO
}
2018-11-23 11:47:32 +00:00
// Update the scene from the background processing,
// 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 ( )
{
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 ( ) ;
return true ;
}
bool Plater : : priv : : init_common_menu ( wxMenu * menu , const bool is_part /* = false*/ )
{
2019-01-21 11:34:28 +00:00
wxMenuItem * item_delete = append_menu_item ( menu , wxID_ANY , _ ( L ( " Delete " ) ) + " \t Del " , _ ( L ( " Remove the selected object " ) ) ,
2018-10-31 11:56:08 +00:00
[ this ] ( wxCommandEvent & ) { q - > remove_selected ( ) ; } , " brick_delete.png " ) ;
2018-12-07 16:50:48 +00:00
if ( ! is_part ) {
2019-01-21 11:34:28 +00:00
wxMenuItem * item_increase = append_menu_item ( menu , wxID_ANY , _ ( L ( " Increase copies " ) ) + " \t + " , _ ( L ( " Place one more copy of the selected object " ) ) ,
2018-12-07 16:50:48 +00:00
[ this ] ( wxCommandEvent & ) { q - > increase_instances ( ) ; } , " add.png " ) ;
2019-01-21 11:34:28 +00:00
wxMenuItem * item_decrease = append_menu_item ( menu , wxID_ANY , _ ( L ( " Decrease copies " ) ) + " \t - " , _ ( L ( " Remove one copy of the selected object " ) ) ,
2018-12-07 16:50:48 +00:00
[ this ] ( wxCommandEvent & ) { q - > decrease_instances ( ) ; } , " delete.png " ) ;
2019-01-21 11:34:28 +00:00
wxMenuItem * item_set_number_of_copies = append_menu_item ( menu , wxID_ANY , _ ( L ( " Set number of copies " ) ) + dots , _ ( L ( " Change the number of copies of the selected object " ) ) ,
2018-12-07 16:50:48 +00:00
[ this ] ( wxCommandEvent & ) { q - > set_number_of_copies ( ) ; } , " textfield.png " ) ;
2019-01-22 15:40:10 +00:00
menu - > AppendSeparator ( ) ;
2019-01-23 15:01:37 +00:00
wxMenuItem * item_instance_to_object = sidebar - > obj_list ( ) - > append_menu_item_instance_to_object ( menu ) ;
2019-01-22 15:40:10 +00:00
2018-12-07 16:50:48 +00:00
if ( q ! = nullptr )
{
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_increase_instances ( ) ) ; } , item_increase - > GetId ( ) ) ;
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_decrease_instances ( ) ) ; } , item_decrease - > GetId ( ) ) ;
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_increase_instances ( ) ) ; } , item_set_number_of_copies - > GetId ( ) ) ;
2019-01-22 15:40:10 +00:00
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_set_instance_to_object ( ) ) ; } , item_instance_to_object - > GetId ( ) ) ;
2018-12-07 16:50:48 +00:00
}
2018-12-07 17:20:22 +00:00
menu - > AppendSeparator ( ) ;
append_menu_item ( menu , wxID_ANY , _ ( L ( " Reload from Disk " ) ) , _ ( L ( " Reload the selected file from Disk " ) ) ,
[ this ] ( wxCommandEvent & ) { reload_from_disk ( ) ; } ) ;
2019-01-21 11:34:28 +00:00
append_menu_item ( menu , wxID_ANY , _ ( L ( " Export object as STL " ) ) + dots , _ ( L ( " Export this single object as STL file " ) ) ,
2018-12-07 17:20:22 +00:00
[ this ] ( wxCommandEvent & ) { q - > export_stl ( true ) ; } ) ;
2018-12-07 16:50:48 +00:00
}
menu - > AppendSeparator ( ) ;
2018-10-17 12:26:13 +00:00
2019-01-30 15:27:07 +00:00
sidebar - > obj_list ( ) - > append_menu_item_fix_through_netfabb ( menu ) ;
2018-10-18 12:42:21 +00:00
wxMenu * mirror_menu = new wxMenu ( ) ;
if ( mirror_menu = = nullptr )
return false ;
append_menu_item ( mirror_menu , wxID_ANY , _ ( L ( " Along X axis " ) ) , _ ( L ( " Mirror the selected object along the X axis " ) ) ,
2018-12-07 16:50:48 +00:00
[ this ] ( wxCommandEvent & ) { mirror ( X ) ; } , " bullet_red.png " , menu ) ;
2018-10-18 12:42:21 +00:00
append_menu_item ( mirror_menu , wxID_ANY , _ ( L ( " Along Y axis " ) ) , _ ( L ( " Mirror the selected object along the Y axis " ) ) ,
2018-12-07 16:50:48 +00:00
[ this ] ( wxCommandEvent & ) { mirror ( Y ) ; } , " bullet_green.png " , menu ) ;
2018-10-18 12:42:21 +00:00
append_menu_item ( mirror_menu , wxID_ANY , _ ( L ( " Along Z axis " ) ) , _ ( L ( " Mirror the selected object along the Z axis " ) ) ,
2018-12-07 16:50:48 +00:00
[ this ] ( wxCommandEvent & ) { mirror ( Z ) ; } , " bullet_blue.png " , menu ) ;
2018-10-18 12:42:21 +00:00
2018-12-07 16:50:48 +00:00
wxMenuItem * item_mirror = append_submenu ( menu , mirror_menu , wxID_ANY , _ ( L ( " Mirror " ) ) , _ ( L ( " Mirror the selected object " ) ) ) ;
2018-10-18 12:42:21 +00:00
2018-12-07 16:50:48 +00:00
// ui updates needs to be binded to the parent panel
if ( q ! = nullptr )
{
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_mirror ( ) ) ; } , item_mirror - > GetId ( ) ) ;
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_delete_object ( ) ) ; } , item_delete - > GetId ( ) ) ;
}
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 ;
wxMenuItem * item_split_objects = append_menu_item ( split_menu , wxID_ANY , _ ( L ( " To objects " ) ) , _ ( L ( " Split the selected object into individual objects " ) ) ,
2018-11-08 15:43:25 +00:00
[ this ] ( wxCommandEvent & ) { split_object ( ) ; } , " shape_ungroup_o.png " , & object_menu ) ;
2018-10-24 10:55:38 +00:00
wxMenuItem * item_split_volumes = append_menu_item ( split_menu , wxID_ANY , _ ( L ( " To parts " ) ) , _ ( L ( " Split the selected object into individual sub-parts " ) ) ,
2018-11-08 15:43:25 +00:00
[ this ] ( wxCommandEvent & ) { split_volume ( ) ; } , " shape_ungroup_p.png " , & object_menu ) ;
2018-10-24 10:55:38 +00:00
wxMenuItem * item_split = append_submenu ( & object_menu , split_menu , wxID_ANY , _ ( L ( " Split " ) ) , _ ( L ( " Split the selected object " ) ) , " shape_ungroup.png " ) ;
2018-12-07 16:50:48 +00:00
object_menu . AppendSeparator ( ) ;
2018-11-22 15:04:21 +00:00
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-10-17 12:26:13 +00:00
// ui updates needs to be binded to the parent panel
if ( q ! = nullptr )
{
2019-01-22 15:40:10 +00:00
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_split ( ) ) ; } , item_split - > GetId ( ) ) ;
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_split ( ) ) ; } , item_split_objects - > GetId ( ) ) ;
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_split ( ) ) ; } , item_split_volumes - > GetId ( ) ) ;
2018-10-17 12:26:13 +00:00
}
2018-12-07 16:50:48 +00:00
return true ;
}
bool Plater : : priv : : complit_init_sla_object_menu ( )
{
wxMenuItem * item_split = append_menu_item ( & sla_object_menu , wxID_ANY , _ ( L ( " Split " ) ) , _ ( L ( " Split the selected object into individual objects " ) ) ,
[ this ] ( wxCommandEvent & ) { split_object ( ) ; } , " shape_ungroup_o.png " ) ;
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
append_menu_item ( & sla_object_menu , wxID_ANY , _ ( L ( " Optimize orientation " ) ) , _ ( L ( " Optimize the rotation of the object for better print results. " ) ) ,
[ this ] ( wxCommandEvent & ) { sla_optimize_rotation ( ) ; } ) ;
// ui updates needs to be binded to the parent panel
if ( q ! = nullptr )
{
2019-01-22 15:40:10 +00:00
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_split ( ) ) ; } , item_split - > GetId ( ) ) ;
2018-12-07 16:50:48 +00:00
}
return true ;
}
bool Plater : : priv : : complit_init_part_menu ( )
{
wxMenuItem * item_split = append_menu_item ( & part_menu , wxID_ANY , _ ( L ( " Split " ) ) , _ ( L ( " Split the selected object into individual sub-parts " ) ) ,
[ this ] ( wxCommandEvent & ) { split_volume ( ) ; } , " shape_ungroup_p.png " ) ;
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 ( ) ;
obj_list - > append_menu_item_change_type ( & part_menu ) ;
// ui updates needs to be binded to the parent panel
if ( q ! = nullptr )
{
2019-01-22 15:40:10 +00:00
q - > Bind ( wxEVT_UPDATE_UI , [ this ] ( wxUpdateUIEvent & evt ) { evt . Enable ( can_split ( ) ) ; } , item_split - > GetId ( ) ) ;
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
2018-12-06 09:38:19 +00:00
void Plater : : priv : : init_view_toolbar ( )
{
2018-12-17 09:55:14 +00:00
ItemsIconsTexture : : Metadata icons_data ;
icons_data . filename = " view_toolbar.png " ;
icons_data . icon_size = 64 ;
icons_data . icon_border_size = 0 ;
icons_data . icon_gap_size = 0 ;
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 ( ! view_toolbar . init ( icons_data , background_data ) )
return ;
view_toolbar . set_layout_orientation ( GLToolbar : : Layout : : Bottom ) ;
view_toolbar . set_border ( 5.0f ) ;
view_toolbar . set_gap_size ( 1.0f ) ;
GLToolbarItem : : Data item ;
item . name = " 3D " ;
2019-02-03 10:10:25 +00:00
item . tooltip = GUI : : L_str ( " 3D editor view " ) + " [ " + GUI : : shortkey_ctrl_prefix ( ) + " 5] " ;
2018-12-17 09:55:14 +00:00
item . sprite_id = 0 ;
item . action_event = EVT_GLVIEWTOOLBAR_3D ;
item . is_toggable = false ;
if ( ! view_toolbar . add_item ( item ) )
2018-12-06 09:38:19 +00:00
return ;
2018-12-17 09:55:14 +00:00
item . name = " Preview " ;
2019-02-03 10:10:25 +00:00
item . tooltip = GUI : : L_str ( " Preview " ) + " [ " + GUI : : shortkey_ctrl_prefix ( ) + " 6] " ;
2018-12-17 09:55:14 +00:00
item . sprite_id = 1 ;
item . action_event = EVT_GLVIEWTOOLBAR_PREVIEW ;
item . is_toggable = false ;
if ( ! view_toolbar . add_item ( item ) )
return ;
view_toolbar . enable_item ( " 3D " ) ;
view_toolbar . enable_item ( " Preview " ) ;
view_toolbar . select_item ( " 3D " ) ;
view_toolbar . set_enabled ( true ) ;
view3D - > set_view_toolbar ( & view_toolbar ) ;
preview - > set_view_toolbar ( & view_toolbar ) ;
2018-12-06 09:38:19 +00:00
}
2018-10-18 07:27:37 +00:00
bool Plater : : priv : : can_delete_object ( ) const
{
int obj_idx = get_selected_object_idx ( ) ;
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) ;
}
bool Plater : : priv : : can_increase_instances ( ) const
{
int obj_idx = get_selected_object_idx ( ) ;
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) ;
}
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-10-18 07:27:37 +00:00
bool Plater : : priv : : can_decrease_instances ( ) 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-10-24 10:55:38 +00:00
bool Plater : : priv : : can_split_to_objects ( ) const
{
int obj_idx = get_selected_object_idx ( ) ;
return ( 0 < = obj_idx ) & & ( obj_idx < ( int ) model . objects . size ( ) ) & & ! model . objects [ obj_idx ] - > is_multiparts ( ) ;
}
bool Plater : : priv : : can_split_to_volumes ( ) const
2018-10-18 07:27:37 +00:00
{
2018-12-07 16:50:48 +00:00
if ( printer_technology = = ptSLA )
return false ;
// int obj_idx = get_selected_object_idx();
// return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts();
return sidebar - > obj_list ( ) - > is_splittable ( ) ;
2018-10-18 07:27:37 +00:00
}
2018-12-17 14:44:30 +00:00
bool Plater : : priv : : can_split ( ) const
{
return sidebar - > obj_list ( ) - > is_splittable ( ) ;
}
2018-10-18 07:27:37 +00:00
bool Plater : : priv : : layers_height_allowed ( ) const
{
2018-10-22 13:18:56 +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_delete_all ( ) const
{
return ! model . objects . empty ( ) ;
}
bool Plater : : priv : : can_arrange ( ) const
{
2018-11-12 13:52:52 +00:00
return ! model . objects . empty ( ) & & ! arranging . load ( ) ;
2018-10-18 13:09:41 +00:00
}
bool Plater : : priv : : can_mirror ( ) const
{
return get_selection ( ) . is_from_single_instance ( ) ;
2018-10-18 07:27:37 +00:00
}
2018-10-08 17:55:30 +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 ) ;
2019-01-31 12:19:26 +00:00
# if ENABLE_MODE_AWARE_TOOLBAR_ITEMS
if ( view3D ! = nullptr )
view3D - > update_toolbar_items_visibility ( ) ;
# endif // ENABLE_MODE_AWARE_TOOLBAR_ITEMS
2018-12-07 16:50:48 +00:00
}
2018-09-17 10:15:11 +00:00
// Plater / Public
Plater : : Plater ( wxWindow * parent , MainFrame * main_frame )
: wxPanel ( parent ) , p ( new priv ( this , main_frame ) )
{
// 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
2018-11-15 14:27:39 +00:00
void Plater : : load_project ( )
{
wxString input_file ;
wxGetApp ( ) . load_project ( this , input_file ) ;
if ( input_file . empty ( ) )
return ;
p - > reset ( ) ;
p - > project_filename = input_file ;
std : : vector < fs : : path > input_paths ;
2019-01-02 14:11:05 +00:00
input_paths . push_back ( into_path ( input_file ) ) ;
2018-11-15 14:27:39 +00:00
load_files ( input_paths ) ;
}
void Plater : : add_model ( )
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
std : : vector < fs : : path > input_paths ;
for ( const auto & file : input_files ) {
2019-01-02 14:11:05 +00:00
input_paths . push_back ( into_path ( file ) ) ;
2018-10-17 10:17:25 +00:00
}
2018-11-16 08:26:41 +00:00
load_files ( input_paths , true , false ) ;
2018-10-17 10:17:25 +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 ) ;
}
void Plater : : load_files ( const std : : vector < fs : : path > & input_files , bool load_model , bool load_config ) { p - > load_files ( input_files , load_model , load_config ) ; }
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.
void Plater : : load_files ( const std : : vector < std : : string > & input_files , bool load_model , bool load_config )
{
std : : vector < fs : : path > paths ;
paths . reserve ( input_files . size ( ) ) ;
for ( const std : : string & path : input_files )
paths . emplace_back ( path ) ;
p - > load_files ( paths , load_model , load_config ) ;
}
2018-11-21 12:32:24 +00:00
void Plater : : update ( ) { p - > update ( ) ; }
2018-10-17 10:59:58 +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 ) ; }
2018-11-21 14:28:35 +00:00
void Plater : : select_all ( ) { p - > select_all ( ) ; }
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 ( ) ; }
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 ( )
{
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
{
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 ] ;
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 ;
2018-10-11 08:03:38 +00:00
float offset = 10.0 ;
for ( size_t i = 0 ; i < num ; i + + , offset + = 10.0 ) {
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
}
2018-11-07 12:40:24 +00:00
sidebar ( ) . obj_list ( ) - > increase_object_instances ( obj_idx , was_one_instance ? num + 1 : num ) ;
2018-10-11 08:03:38 +00:00
if ( p - > get_config ( " autocenter " ) = = " 1 " ) {
p - > arrange ( ) ;
} else {
p - > update ( ) ;
}
2018-10-23 07:19:41 +00:00
p - > get_selection ( ) . add_instance ( obj_idx , ( int ) model_object - > instances . size ( ) - 1 ) ;
2018-10-11 08:03:38 +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
{
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
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 ( ) ;
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
}
p - > update ( ) ;
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
2018-10-25 19:13:45 +00:00
const auto num = wxGetNumberFromUser ( " " , _ ( " Enter the number of copies: " ) ,
_ ( " Copies of the selected object " ) , model_object - > instances . size ( ) , 0 , 1000 , this ) ;
if ( num < 0 )
return ;
2018-10-17 07:30:07 +00:00
int diff = ( int ) 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
{
return p - > get_selection ( ) . is_empty ( ) ;
}
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 ;
}
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-02-03 09:41:14 +00:00
void Plater : : export_gcode ( )
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 {
// 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 ;
default_output_file = this - > p - > background_process . current_print ( ) - > output_filepath ( " " ) ;
} catch ( const std : : exception & ex ) {
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 ( ) ) ) ;
auto start_dir = wxGetApp ( ) . app_config - > get_last_output_dir ( default_output_file . parent_path ( ) . string ( ) ) ;
2018-09-17 10:15:11 +00:00
2019-02-03 09:41:14 +00:00
wxFileDialog dlg ( this , ( printer_technology ( ) = = ptFFF ) ? _ ( L ( " Save G-code file as: " ) ) : _ ( L ( " Save Zip file as: " ) ) ,
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
) ;
fs : : path output_path ;
if ( dlg . ShowModal ( ) = = wxID_OK ) {
fs : : path path = into_path ( dlg . GetPath ( ) ) ;
wxGetApp ( ) . app_config - > update_last_output_dir ( path . parent_path ( ) . string ( ) ) ;
output_path = std : : move ( path ) ;
2018-10-23 13:27:31 +00:00
}
2019-02-03 09:41:14 +00:00
if ( ! output_path . empty ( ) )
p - > export_gcode ( std : : move ( output_path ) , PrintHostJob ( ) ) ;
2018-09-17 10:15:11 +00:00
}
2018-12-05 14:22:03 +00:00
void Plater : : export_stl ( 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
auto dialog = p - > get_export_file ( FT_STL ) ;
if ( ! dialog ) { return ; }
// Store a binary STL
2019-01-02 14:11:05 +00:00
const wxString path = dialog - > GetPath ( ) ;
const std : : string path_u8 = into_u8 ( path ) ;
2018-12-05 14:22:03 +00:00
TriangleMesh mesh ;
if ( selection_only ) {
const auto & selection = p - > get_selection ( ) ;
if ( selection . is_wipe_tower ( ) ) { return ; }
const auto obj_idx = selection . get_object_idx ( ) ;
if ( obj_idx = = - 1 ) { return ; }
mesh = p - > model . objects [ obj_idx ] - > mesh ( ) ;
} else {
2019-01-02 17:36:48 +00:00
mesh = p - > model . mesh ( ) ;
2018-12-05 14:22:03 +00:00
}
2019-01-02 14:11:05 +00:00
Slic3r : : store_stl ( path_u8 . c_str ( ) , & mesh , true ) ;
2018-10-04 09:12:55 +00:00
p - > statusbar ( ) - > set_status_text ( wxString : : Format ( _ ( L ( " STL file exported to %s " ) ) , path ) ) ;
}
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
auto dialog = p - > get_export_file ( FT_AMF ) ;
if ( ! dialog ) { return ; }
2019-01-02 14:11:05 +00:00
const wxString path = dialog - > GetPath ( ) ;
const std : : string path_u8 = into_u8 ( path ) ;
2018-10-08 17:55:30 +00:00
2018-12-06 13:47:53 +00:00
DynamicPrintConfig cfg = wxGetApp ( ) . preset_bundle - > full_config_secure ( ) ;
2019-02-05 19:23:24 +00:00
wxBusyCursor wait ;
2019-01-02 14:11:05 +00:00
if ( Slic3r : : store_amf ( path_u8 . c_str ( ) , & p - > model , dialog - > get_checkbox_value ( ) ? & cfg : nullptr ) ) {
2018-10-08 17:55:30 +00:00
// Success
p - > statusbar ( ) - > set_status_text ( wxString : : Format ( _ ( L ( " AMF file exported to %s " ) ) , path ) ) ;
} else {
// Failure
p - > statusbar ( ) - > set_status_text ( wxString : : Format ( _ ( L ( " Error exporting AMF file %s " ) ) , path ) ) ;
}
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 ( ) )
{
auto dialog = p - > get_export_file ( FT_3MF ) ;
if ( ! dialog ) { return ; }
path = dialog - > GetPath ( ) ;
export_config = dialog - > get_checkbox_value ( ) ;
}
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
2018-12-06 13:47:53 +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 ;
2019-01-02 14:11:05 +00:00
if ( Slic3r : : store_3mf ( path_u8 . c_str ( ) , & p - > model , export_config ? & cfg : nullptr ) ) {
2018-10-08 17:55:30 +00:00
// Success
p - > statusbar ( ) - > set_status_text ( wxString : : Format ( _ ( L ( " 3MF file exported to %s " ) ) , path ) ) ;
} else {
// Failure
p - > statusbar ( ) - > set_status_text ( wxString : : Format ( _ ( L ( " Error exporting 3MF file %s " ) ) , path ) ) ;
}
2018-10-04 09:12:55 +00:00
}
2018-09-17 10:15:11 +00:00
void Plater : : reslice ( )
{
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 ) ;
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 ) ;
2018-09-17 10:15:11 +00:00
}
2019-02-21 10:40:56 +00:00
void Plater : : reslice_SLA_supports ( const ModelObject & object )
{
//FIXME Don't reslice if export of G-code or sending to OctoPrint is running.
// bitmask of UpdateBackgroundProcessReturnState
unsigned int state = this - > p - > update_background_process ( true ) ;
if ( state & priv : : UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE )
this - > p - > view3D - > reload_scene ( false ) ;
if ( this - > p - > background_process . empty ( ) | | ( state & priv : : UPDATE_BACKGROUND_PROCESS_INVALID ) )
// 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.
if ( ! this - > p - > background_processing_enabled ( ) ) {
task . single_model_instance_only = true ;
task . to_object_step = slaposBasePool ;
}
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-02-03 09:41:14 +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 ;
default_output_file = this - > p - > background_process . current_print ( ) - > output_filepath ( " " ) ;
2018-12-11 09:33:11 +00:00
} catch ( const std : : exception & ex ) {
show_error ( this , ex . what ( ) ) ;
return ;
}
default_output_file = fs : : path ( Slic3r : : fold_utf8_to_ascii ( default_output_file . string ( ) ) ) ;
2018-12-14 14:27:34 +00:00
PrintHostSendDialog dlg ( default_output_file ) ;
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 ( ) ;
p - > export_gcode ( fs : : path ( ) , std : : move ( upload_job ) ) ;
}
2018-10-04 09:12:55 +00:00
}
2018-10-10 11:53:45 +00:00
void Plater : : on_extruders_change ( int num_extruders )
{
auto & choices = sidebar ( ) . combos_filament ( ) ;
2018-11-15 10:15:24 +00:00
wxWindowUpdateLocker noUpdates_scrolled_panel ( & sidebar ( ) /*.scrolled_panel()*/ ) ;
2018-11-09 17:39:07 +00:00
// sidebar().scrolled_panel()->Freeze();
2018-10-10 11:53:45 +00:00
int i = choices . size ( ) ;
while ( i < num_extruders )
{
PresetComboBox * choice /*{ nullptr }*/ ;
sidebar ( ) . init_filament_combo ( & choice , i ) ;
choices . push_back ( choice ) ;
// initialize selection
wxGetApp ( ) . preset_bundle - > update_platter_filament_ui ( i , choice ) ;
+ + 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
# if ENABLE_REWORKED_BED_SHAPE_CHANGE
bool bed_shape_changed = false ;
# endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
2018-10-17 09:12:38 +00:00
for ( auto opt_key : p - > config - > diff ( config ) ) {
p - > config - > set_key_value ( opt_key , config . option ( opt_key ) - > clone ( ) ) ;
2018-12-03 12:14:28 +00:00
if ( opt_key = = " printer_technology " )
this - > set_printer_technology ( config . opt_enum < PrinterTechnology > ( opt_key ) ) ;
2019-01-17 12:21:33 +00:00
else if ( opt_key = = " bed_shape " ) {
2019-02-04 09:06:15 +00:00
# if ENABLE_REWORKED_BED_SHAPE_CHANGE
bed_shape_changed = true ;
# else
2018-12-04 12:55:25 +00:00
if ( p - > view3D ) p - > view3D - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( opt_key ) - > values ) ;
2018-10-15 08:53:47 +00:00
if ( p - > preview ) p - > preview - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( opt_key ) - > values ) ;
2019-02-04 09:06:15 +00:00
# endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
2018-10-15 08:53:47 +00:00
update_scheduled = true ;
}
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 ;
}
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_toolbar_item ( " layersediting " , false ) ;
p - > view3D - > enable_layers_editing ( false ) ;
p - > view3D - > set_as_dirty ( ) ;
2018-10-15 08:53:47 +00:00
}
2018-12-04 12:55:25 +00:00
else if ( p - > view3D - > is_layers_editing_allowed ( ) ) {
p - > view3D - > enable_toolbar_item ( " layersediting " , true ) ;
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 ( ) ) ;
} 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
# if ENABLE_REWORKED_BED_SHAPE_CHANGE
bed_shape_changed = true ;
# else
2018-12-04 12:55:25 +00:00
if ( p - > view3D ) p - > view3D - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ) ;
2018-10-15 08:53:47 +00:00
if ( p - > preview ) p - > preview - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ) ;
2019-02-04 09:06:15 +00:00
# endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
2018-10-15 08:53:47 +00:00
update_scheduled = true ;
2019-01-17 12:21:33 +00:00
}
else if ( opt_key = = " host_type " & & this - > p - > printer_technology = = ptSLA ) {
2018-12-18 13:34:16 +00:00
p - > config - > option < ConfigOptionEnum < PrintHostType > > ( opt_key ) - > value = htSL1 ;
2018-10-15 08:53:47 +00:00
}
}
2018-12-11 09:33:11 +00:00
{
const auto prin_host_opt = p - > config - > option < ConfigOptionString > ( " print_host " ) ;
p - > sidebar - > show_send ( prin_host_opt ! = nullptr & & ! prin_host_opt - > value . empty ( ) ) ;
}
2019-02-04 09:06:15 +00:00
# if ENABLE_REWORKED_BED_SHAPE_CHANGE
if ( bed_shape_changed )
{
if ( p - > view3D ) p - > view3D - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ) ;
if ( p - > preview ) p - > preview - > set_bed_shape ( p - > config - > option < ConfigOptionPoints > ( " bed_shape " ) - > values ) ;
}
# endif // ENABLE_REWORKED_BED_SHAPE_CHANGE
2018-10-15 08:53:47 +00:00
if ( update_scheduled )
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
}
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-02-19 13:57:59 +00:00
if ( ! this - > p - > delayed_error_message . empty ( ) ) {
std : : string msg = std : : move ( this - > p - > delayed_error_message ) ;
this - > p - > delayed_error_message . clear ( ) ;
GUI : : show_error ( this , msg ) ;
}
}
2018-11-15 14:27:39 +00:00
const wxString & Plater : : get_project_filename ( ) const
{
return p - > project_filename ;
}
bool Plater : : is_export_gcode_scheduled ( ) const
{
return p - > background_process . is_export_scheduled ( ) ;
}
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
}
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
}
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.
}
//FIXME for SLA synchronize
//p->background_process.apply(Model)!
}
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 ;
auto list = wxGetApp ( ) . obj_list ( ) ;
wxASSERT ( list ! = nullptr ) ;
if ( list = = nullptr )
return ;
if ( list - > is_parts_changed ( ) ) {
// recenter and re - align to Z = 0
2018-10-12 10:00:37 +00:00
auto model_object = p - > model . objects [ obj_idx ] ;
2018-10-30 15:03:03 +00:00
model_object - > ensure_on_bed ( ) ;
2018-12-03 12:14:28 +00:00
if ( this - > p - > printer_technology = = ptSLA ) {
// Update the SLAPrint from the current Model, so that the reload_scene()
2018-12-22 09:02:42 +00:00
// pulls the correct data, update the 3D scene.
this - > p - > update_restart_background_process ( true , false ) ;
} 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-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 ( ) ; }
2018-09-17 10:15:11 +00:00
} } // namespace Slic3r::GUI