2018-06-13 14:39:33 +00:00
# include "GUI.hpp"
2018-06-15 23:21:25 +00:00
# include "OptionsGroup.hpp"
# include "PresetBundle.hpp"
2018-06-13 14:39:33 +00:00
# include "GUI_ObjectParts.hpp"
2018-06-14 13:33:42 +00:00
# include "Model.hpp"
# include "wxExtensions.hpp"
2018-06-15 20:42:51 +00:00
# include "LambdaObjectDialog.hpp"
# include "../../libslic3r/Utils.hpp"
2018-06-13 14:39:33 +00:00
# include <wx/msgdlg.h>
2018-06-14 13:33:42 +00:00
# include <boost/filesystem.hpp>
2018-06-15 23:21:25 +00:00
# include <boost/algorithm/string.hpp>
2018-07-29 10:19:08 +00:00
# include "Geometry.hpp"
2018-08-09 13:55:08 +00:00
# include "slic3r/Utils/FixModelByWin10.hpp"
2018-06-13 14:39:33 +00:00
namespace Slic3r
{
namespace GUI
{
2018-06-15 23:21:25 +00:00
wxSizer * m_sizer_object_buttons = nullptr ;
wxSizer * m_sizer_part_buttons = nullptr ;
wxSizer * m_sizer_object_movers = nullptr ;
wxDataViewCtrl * m_objects_ctrl = nullptr ;
PrusaObjectDataViewModel * m_objects_model = nullptr ;
wxCollapsiblePane * m_collpane_settings = nullptr ;
2018-06-18 12:20:29 +00:00
wxIcon m_icon_modifiermesh ;
wxIcon m_icon_solidmesh ;
2018-07-04 14:32:01 +00:00
wxIcon m_icon_manifold_warning ;
2018-07-23 15:35:50 +00:00
wxBitmap m_bmp_cog ;
2018-07-30 15:03:14 +00:00
wxBitmap m_bmp_split ;
2018-06-18 12:20:29 +00:00
wxSlider * m_mover_x = nullptr ;
wxSlider * m_mover_y = nullptr ;
wxSlider * m_mover_z = nullptr ;
wxButton * m_btn_move_up = nullptr ;
wxButton * m_btn_move_down = nullptr ;
Point3 m_move_options ;
Point3 m_last_coords ;
int m_selected_object_id = - 1 ;
2018-06-16 01:04:59 +00:00
2018-06-15 23:21:25 +00:00
bool g_prevent_list_events = false ; // We use this flag to avoid circular event handling Select()
// happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler
// calls this method again and again and again
2018-07-29 10:19:08 +00:00
bool g_is_percent_scale = false ; // It indicates if scale unit is percentage
int g_rotation_x = 0 ; // Last value of the rotation around the X axis
int g_rotation_y = 0 ; // Last value of the rotation around the Y axis
2018-07-24 16:39:40 +00:00
ModelObjectPtrs * m_objects ;
2018-07-25 14:13:20 +00:00
std : : shared_ptr < DynamicPrintConfig * > m_config ;
2018-07-24 16:39:40 +00:00
std : : shared_ptr < DynamicPrintConfig > m_default_config ;
wxBoxSizer * m_option_sizer = nullptr ;
2018-06-15 23:21:25 +00:00
2018-07-25 14:13:20 +00:00
// option groups for settings
std : : vector < std : : shared_ptr < ConfigOptionsGroup > > m_og_settings ;
2018-06-15 23:21:25 +00:00
int m_event_object_selection_changed = 0 ;
int m_event_object_settings_changed = 0 ;
2018-07-04 06:54:30 +00:00
int m_event_remove_object = 0 ;
2018-07-26 08:59:03 +00:00
int m_event_update_scene = 0 ;
2018-06-15 23:21:25 +00:00
2018-06-14 13:33:42 +00:00
bool m_parts_changed = false ;
bool m_part_settings_changed = false ;
2018-07-27 10:26:14 +00:00
# ifdef __WXOSX__
wxString g_selected_extruder = " " ;
# endif //__WXOSX__
2018-07-09 14:42:31 +00:00
// typedef std::map<std::string, std::string> t_category_icon;
typedef std : : map < std : : string , wxBitmap > t_category_icon ;
inline t_category_icon & get_category_icon ( ) {
static t_category_icon CATEGORY_ICON ;
if ( CATEGORY_ICON . empty ( ) ) {
CATEGORY_ICON [ L ( " Layers and Perimeters " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " layers.png " ) ) , wxBITMAP_TYPE_PNG ) ;
CATEGORY_ICON [ L ( " Infill " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " infill.png " ) ) , wxBITMAP_TYPE_PNG ) ;
CATEGORY_ICON [ L ( " Support material " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " building.png " ) ) , wxBITMAP_TYPE_PNG ) ;
CATEGORY_ICON [ L ( " Speed " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " time.png " ) ) , wxBITMAP_TYPE_PNG ) ;
CATEGORY_ICON [ L ( " Extruders " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " funnel.png " ) ) , wxBITMAP_TYPE_PNG ) ;
CATEGORY_ICON [ L ( " Extrusion Width " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " funnel.png " ) ) , wxBITMAP_TYPE_PNG ) ;
// CATEGORY_ICON[L("Skirt and brim")] = wxBitmap(from_u8(Slic3r::var("box.png")), wxBITMAP_TYPE_PNG);
// CATEGORY_ICON[L("Speed > Acceleration")] = wxBitmap(from_u8(Slic3r::var("time.png")), wxBITMAP_TYPE_PNG);
CATEGORY_ICON [ L ( " Advanced " ) ] = wxBitmap ( from_u8 ( Slic3r : : var ( " wand.png " ) ) , wxBITMAP_TYPE_PNG ) ;
}
return CATEGORY_ICON ;
}
2018-07-24 16:39:40 +00:00
std : : vector < std : : string > get_options ( const bool is_part )
2018-07-23 15:35:50 +00:00
{
PrintRegionConfig reg_config ;
auto options = reg_config . keys ( ) ;
if ( ! is_part ) {
PrintObjectConfig obj_config ;
std : : vector < std : : string > obj_options = obj_config . keys ( ) ;
options . insert ( options . end ( ) , obj_options . begin ( ) , obj_options . end ( ) ) ;
}
2018-07-24 16:39:40 +00:00
return options ;
}
// category -> vector ( option ; label )
typedef std : : map < std : : string , std : : vector < std : : pair < std : : string , std : : string > > > settings_menu_hierarchy ;
void get_options_menu ( settings_menu_hierarchy & settings_menu , bool is_part )
{
auto options = get_options ( is_part ) ;
2018-07-23 15:35:50 +00:00
2018-08-01 10:49:39 +00:00
auto extruders_cnt = get_preset_bundle ( ) - > printers . get_edited_preset ( ) . config . option < ConfigOptionFloats > ( " nozzle_diameter " ) - > values . size ( ) ;
2018-07-23 15:35:50 +00:00
DynamicPrintConfig config ;
for ( auto & option : options )
{
auto const opt = config . def ( ) - > get ( option ) ;
auto category = opt - > category ;
2018-08-01 10:49:39 +00:00
if ( category . empty ( ) | |
( category = = " Extruders " & & extruders_cnt = = 1 ) ) continue ;
2018-07-23 15:35:50 +00:00
std : : pair < std : : string , std : : string > option_label ( option , opt - > label ) ;
std : : vector < std : : pair < std : : string , std : : string > > new_category ;
auto & cat_opt_label = settings_menu . find ( category ) = = settings_menu . end ( ) ? new_category : settings_menu . at ( category ) ;
cat_opt_label . push_back ( option_label ) ;
if ( cat_opt_label . size ( ) = = 1 )
settings_menu [ category ] = cat_opt_label ;
}
}
2018-06-15 23:21:25 +00:00
void set_event_object_selection_changed ( const int & event ) {
m_event_object_selection_changed = event ;
}
void set_event_object_settings_changed ( const int & event ) {
m_event_object_settings_changed = event ;
}
2018-07-04 06:54:30 +00:00
void set_event_remove_object ( const int & event ) {
m_event_remove_object = event ;
}
2018-07-26 08:59:03 +00:00
void set_event_update_scene ( const int & event ) {
m_event_update_scene = event ;
}
2018-06-15 23:21:25 +00:00
2018-07-24 10:15:36 +00:00
void set_objects_from_model ( Model & model ) {
m_objects = & ( model . objects ) ;
}
2018-06-18 12:20:29 +00:00
void init_mesh_icons ( ) {
2018-08-01 10:49:39 +00:00
m_icon_modifiermesh = wxIcon ( Slic3r : : GUI : : from_u8 ( Slic3r : : var ( " lambda.png " ) ) , wxBITMAP_TYPE_PNG ) ; //(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG);
2018-07-25 14:13:20 +00:00
m_icon_solidmesh = wxIcon ( Slic3r : : GUI : : from_u8 ( Slic3r : : var ( " object.png " ) ) , wxBITMAP_TYPE_PNG ) ; //(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG);
2018-07-23 15:35:50 +00:00
// init icon for manifold warning
2018-07-26 08:59:03 +00:00
m_icon_manifold_warning = wxIcon ( Slic3r : : GUI : : from_u8 ( Slic3r : : var ( " exclamation_mark_.png " ) ) , wxBITMAP_TYPE_PNG ) ; //(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG);
2018-07-23 15:35:50 +00:00
2018-07-30 15:03:14 +00:00
// init bitmap for "Split to sub-objects" context menu
m_bmp_split = wxBitmap ( Slic3r : : GUI : : from_u8 ( Slic3r : : var ( " split.png " ) ) , wxBITMAP_TYPE_PNG ) ;
2018-07-23 15:35:50 +00:00
// init bitmap for "Add Settings" context menu
m_bmp_cog = wxBitmap ( Slic3r : : GUI : : from_u8 ( Slic3r : : var ( " cog.png " ) ) , wxBITMAP_TYPE_PNG ) ;
2018-06-18 12:20:29 +00:00
}
2018-06-14 13:33:42 +00:00
bool is_parts_changed ( ) { return m_parts_changed ; }
bool is_part_settings_changed ( ) { return m_part_settings_changed ; }
2018-07-04 12:52:36 +00:00
static wxString dots ( " … " , wxConvUTF8 ) ;
2018-06-15 23:21:25 +00:00
2018-08-10 10:19:35 +00:00
void set_tooltip_for_item ( const wxPoint & pt )
{
wxDataViewItem item ;
wxDataViewColumn * col ;
m_objects_ctrl - > HitTest ( pt , item , col ) ;
if ( ! item ) return ;
if ( col - > GetTitle ( ) = = " " )
m_objects_ctrl - > GetMainWindow ( ) - > SetToolTip ( _ ( L ( " Right button click the icon to change the object settings " ) ) ) ;
else if ( col - > GetTitle ( ) = = _ ( " Name " ) & &
m_objects_model - > GetIcon ( item ) . GetRefData ( ) = = m_icon_manifold_warning . GetRefData ( ) ) {
int obj_idx = m_objects_model - > GetIdByItem ( item ) ;
auto & stats = ( * m_objects ) [ obj_idx ] - > volumes [ 0 ] - > mesh . stl . stats ;
int errors = stats . degenerate_facets + stats . edges_fixed + stats . facets_removed +
stats . facets_added + stats . facets_reversed + stats . backwards_edges ;
wxString tooltip = wxString : : Format ( _ ( L ( " Auto-repaired (%d errors): \n " ) ) , errors ) ;
std : : map < std : : string , int > error_msg ;
error_msg [ L ( " degenerate facets " ) ] = stats . degenerate_facets ;
error_msg [ L ( " edges fixed " ) ] = stats . edges_fixed ;
error_msg [ L ( " facets removed " ) ] = stats . facets_removed ;
error_msg [ L ( " facets added " ) ] = stats . facets_added ;
error_msg [ L ( " facets reversed " ) ] = stats . facets_reversed ;
error_msg [ L ( " backwards edges " ) ] = stats . backwards_edges ;
for ( auto error : error_msg )
{
if ( error . second > 0 )
tooltip + = wxString : : Format ( _ ( " \t %d %s \n " ) , error . second , error . first ) ;
}
// OR
// tooltip += wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, "
// "%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);
if ( is_windows10 ( ) )
tooltip + = _ ( L ( " Right button click the icon to fix STL through Netfabb " ) ) ;
m_objects_ctrl - > GetMainWindow ( ) - > SetToolTip ( tooltip ) ;
}
else
m_objects_ctrl - > GetMainWindow ( ) - > SetToolTip ( " " ) ; // hide tooltip
}
wxPoint get_mouse_position_in_control ( ) {
const wxPoint & pt = wxGetMousePosition ( ) ;
wxWindow * win = m_objects_ctrl - > GetMainWindow ( ) ;
return wxPoint ( pt . x - win - > GetScreenPosition ( ) . x ,
pt . y - win - > GetScreenPosition ( ) . y ) ;
}
2018-08-15 09:18:20 +00:00
wxDataViewColumn * object_ctrl_create_extruder_column ( int extruders_count )
{
wxArrayString choices ;
choices . Add ( " default " ) ;
for ( int i = 1 ; i < = extruders_count ; + + i )
choices . Add ( wxString : : Format ( " %d " , i ) ) ;
wxDataViewChoiceRenderer * c =
new wxDataViewChoiceRenderer ( choices , wxDATAVIEW_CELL_EDITABLE , wxALIGN_CENTER_HORIZONTAL ) ;
wxDataViewColumn * column = new wxDataViewColumn ( _ ( L ( " Extruder " ) ) , c , 3 , 60 , wxALIGN_CENTER_HORIZONTAL , wxDATAVIEW_COL_RESIZABLE ) ;
return column ;
}
2018-08-15 08:09:05 +00:00
void create_objects_ctrl ( wxWindow * win , wxBoxSizer * & objects_sz )
2018-06-15 23:21:25 +00:00
{
m_objects_ctrl = new wxDataViewCtrl ( win , wxID_ANY , wxDefaultPosition , wxDefaultSize ) ;
m_objects_ctrl - > SetInitialSize ( wxSize ( - 1 , 150 ) ) ; // TODO - Set correct height according to the opened/closed objects
2018-08-15 08:09:05 +00:00
objects_sz = new wxBoxSizer ( wxVERTICAL ) ;
2018-06-15 23:21:25 +00:00
objects_sz - > Add ( m_objects_ctrl , 1 , wxGROW | wxLEFT , 20 ) ;
m_objects_model = new PrusaObjectDataViewModel ;
m_objects_ctrl - > AssociateModel ( m_objects_model ) ;
# if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
m_objects_ctrl - > EnableDragSource ( wxDF_UNICODETEXT ) ;
m_objects_ctrl - > EnableDropTarget ( wxDF_UNICODETEXT ) ;
# endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
// column 0(Icon+Text) of the view control:
2018-07-04 06:54:30 +00:00
m_objects_ctrl - > AppendIconTextColumn ( _ ( L ( " Name " ) ) , 0 , wxDATAVIEW_CELL_INERT , 120 ,
2018-08-15 08:09:05 +00:00
wxALIGN_LEFT , wxDATAVIEW_COL_RESIZABLE ) ;
2018-06-15 23:21:25 +00:00
// column 1 of the view control:
2018-07-04 06:54:30 +00:00
m_objects_ctrl - > AppendTextColumn ( _ ( L ( " Copy " ) ) , 1 , wxDATAVIEW_CELL_INERT , 45 ,
2018-06-19 10:24:16 +00:00
wxALIGN_CENTER_HORIZONTAL , wxDATAVIEW_COL_RESIZABLE ) ;
2018-06-15 23:21:25 +00:00
// column 2 of the view control:
2018-07-04 06:54:30 +00:00
m_objects_ctrl - > AppendTextColumn ( _ ( L ( " Scale " ) ) , 2 , wxDATAVIEW_CELL_INERT , 55 ,
wxALIGN_CENTER_HORIZONTAL , wxDATAVIEW_COL_RESIZABLE ) ;
2018-07-25 15:48:15 +00:00
// column 3 of the view control:
2018-08-15 09:18:20 +00:00
m_objects_ctrl - > AppendColumn ( object_ctrl_create_extruder_column ( 4 ) ) ;
2018-07-04 06:54:30 +00:00
2018-07-25 15:48:15 +00:00
// column 4 of the view control:
2018-08-01 10:49:39 +00:00
m_objects_ctrl - > AppendBitmapColumn ( " " , 4 , wxDATAVIEW_CELL_INERT , 25 ,
2018-06-19 10:24:16 +00:00
wxALIGN_CENTER_HORIZONTAL , wxDATAVIEW_COL_RESIZABLE ) ;
2018-08-15 08:09:05 +00:00
}
2018-06-15 23:21:25 +00:00
2018-08-15 08:09:05 +00:00
// ****** from GUI.cpp
wxBoxSizer * create_objects_list ( wxWindow * win )
{
wxBoxSizer * objects_sz ;
create_objects_ctrl ( win , objects_sz ) ;
m_objects_ctrl - > Bind ( wxEVT_DATAVIEW_SELECTION_CHANGED , [ ] ( wxEvent & event ) {
2018-07-27 10:26:14 +00:00
object_ctrl_selection_changed ( ) ;
2018-08-10 10:19:35 +00:00
# ifndef __WXMSW__
set_tooltip_for_item ( get_mouse_position_in_control ( ) ) ;
# endif //__WXMSW__
2018-06-15 23:21:25 +00:00
} ) ;
2018-08-10 10:19:35 +00:00
m_objects_ctrl - > Bind ( wxEVT_DATAVIEW_ITEM_CONTEXT_MENU , [ ] ( wxDataViewEvent & event ) {
2018-08-15 08:09:05 +00:00
object_ctrl_context_menu ( ) ;
2018-07-04 06:54:30 +00:00
event . Skip ( ) ;
} ) ;
2018-08-15 08:09:05 +00:00
m_objects_ctrl - > Bind ( wxEVT_CHAR , [ ] ( wxKeyEvent & event ) { object_ctrl_key_event ( event ) ; } ) ;
2018-06-15 23:21:25 +00:00
2018-07-27 08:52:16 +00:00
# ifdef __WXMSW__
2018-08-15 08:09:05 +00:00
m_objects_ctrl - > Bind ( wxEVT_CHOICE , [ ] ( wxCommandEvent & event ) { update_extruder_in_config ( event . GetString ( ) ) ; } ) ;
2018-08-10 10:19:35 +00:00
m_objects_ctrl - > GetMainWindow ( ) - > Bind ( wxEVT_MOTION , [ ] ( wxMouseEvent & event ) {
set_tooltip_for_item ( event . GetPosition ( ) ) ;
2018-08-13 12:15:43 +00:00
event . Skip ( ) ;
2018-08-10 10:19:35 +00:00
} ) ;
2018-07-27 08:52:16 +00:00
# else
2018-08-15 08:09:05 +00:00
m_objects_ctrl - > Bind ( wxEVT_DATAVIEW_ITEM_VALUE_CHANGED , [ ] ( wxDataViewEvent & event ) { object_ctrl_item_value_change ( event ) ; } ) ;
2018-07-26 14:51:18 +00:00
# endif //__WXMSW__
2018-08-13 08:30:36 +00:00
m_objects_ctrl - > Bind ( wxEVT_DATAVIEW_ITEM_BEGIN_DRAG , [ ] ( wxDataViewEvent & e ) { on_begin_drag ( e ) ; } ) ;
m_objects_ctrl - > Bind ( wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE , [ ] ( wxDataViewEvent & e ) { on_drop_possible ( e ) ; } ) ;
m_objects_ctrl - > Bind ( wxEVT_DATAVIEW_ITEM_DROP , [ ] ( wxDataViewEvent & e ) { on_drop ( e ) ; } ) ;
2018-06-15 23:21:25 +00:00
return objects_sz ;
}
2018-08-15 08:09:05 +00:00
wxBoxSizer * create_edit_object_buttons ( wxWindow * win )
2018-06-15 23:21:25 +00:00
{
auto sizer = new wxBoxSizer ( wxVERTICAL ) ;
auto btn_load_part = new wxButton ( win , wxID_ANY , /*Load */ " part " + dots , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT | wxNO_BORDER /*wxBU_LEFT*/ ) ;
auto btn_load_modifier = new wxButton ( win , wxID_ANY , /*Load */ " modifier " + dots , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT | wxNO_BORDER /*wxBU_LEFT*/ ) ;
auto btn_load_lambda_modifier = new wxButton ( win , wxID_ANY , /*Load */ " generic " + dots , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT | wxNO_BORDER /*wxBU_LEFT*/ ) ;
auto btn_delete = new wxButton ( win , wxID_ANY , " Delete " /*" part"*/ , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT | wxNO_BORDER /*wxBU_LEFT*/ ) ;
auto btn_split = new wxButton ( win , wxID_ANY , " Split " /*" part"*/ , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT | wxNO_BORDER /*wxBU_LEFT*/ ) ;
2018-06-18 12:20:29 +00:00
m_btn_move_up = new wxButton ( win , wxID_ANY , " " , wxDefaultPosition , wxDefaultSize /*wxSize(30, -1)*/ , wxBU_LEFT ) ;
m_btn_move_down = new wxButton ( win , wxID_ANY , " " , wxDefaultPosition , wxDefaultSize /*wxSize(30, -1)*/ , wxBU_LEFT ) ;
2018-06-15 23:21:25 +00:00
//*** button's functions
2018-06-18 13:26:09 +00:00
btn_load_part - > Bind ( wxEVT_BUTTON , [ win ] ( wxEvent & ) {
2018-06-15 23:21:25 +00:00
on_btn_load ( win ) ;
} ) ;
2018-06-18 13:26:09 +00:00
btn_load_modifier - > Bind ( wxEVT_BUTTON , [ win ] ( wxEvent & ) {
2018-06-15 23:21:25 +00:00
on_btn_load ( win , true ) ;
} ) ;
2018-06-18 13:26:09 +00:00
btn_load_lambda_modifier - > Bind ( wxEVT_BUTTON , [ win ] ( wxEvent & ) {
2018-06-15 23:21:25 +00:00
on_btn_load ( win , true , true ) ;
} ) ;
2018-06-18 13:26:09 +00:00
btn_delete - > Bind ( wxEVT_BUTTON , [ ] ( wxEvent & ) { on_btn_del ( ) ; } ) ;
2018-07-31 13:31:12 +00:00
btn_split - > Bind ( wxEVT_BUTTON , [ ] ( wxEvent & ) { on_btn_split ( true ) ; } ) ;
2018-06-18 13:26:09 +00:00
m_btn_move_up - > Bind ( wxEVT_BUTTON , [ ] ( wxEvent & ) { on_btn_move_up ( ) ; } ) ;
m_btn_move_down - > Bind ( wxEVT_BUTTON , [ ] ( wxEvent & ) { on_btn_move_down ( ) ; } ) ;
2018-06-15 23:21:25 +00:00
//***
2018-06-18 12:20:29 +00:00
m_btn_move_up - > SetMinSize ( wxSize ( 20 , - 1 ) ) ;
m_btn_move_down - > SetMinSize ( wxSize ( 20 , - 1 ) ) ;
2018-06-15 23:21:25 +00:00
btn_load_part - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " brick_add.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
btn_load_modifier - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " brick_add.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
btn_load_lambda_modifier - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " brick_add.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
btn_delete - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " brick_delete.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
btn_split - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " shape_ungroup.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
2018-06-18 12:20:29 +00:00
m_btn_move_up - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " bullet_arrow_up.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
m_btn_move_down - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " bullet_arrow_down.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
2018-06-15 23:21:25 +00:00
m_sizer_object_buttons = new wxGridSizer ( 1 , 3 , 0 , 0 ) ;
m_sizer_object_buttons - > Add ( btn_load_part , 0 , wxEXPAND ) ;
m_sizer_object_buttons - > Add ( btn_load_modifier , 0 , wxEXPAND ) ;
m_sizer_object_buttons - > Add ( btn_load_lambda_modifier , 0 , wxEXPAND ) ;
m_sizer_object_buttons - > Show ( false ) ;
m_sizer_part_buttons = new wxGridSizer ( 1 , 3 , 0 , 0 ) ;
m_sizer_part_buttons - > Add ( btn_delete , 0 , wxEXPAND ) ;
m_sizer_part_buttons - > Add ( btn_split , 0 , wxEXPAND ) ;
{
auto up_down_sizer = new wxGridSizer ( 1 , 2 , 0 , 0 ) ;
2018-06-18 12:20:29 +00:00
up_down_sizer - > Add ( m_btn_move_up , 1 , wxEXPAND ) ;
up_down_sizer - > Add ( m_btn_move_down , 1 , wxEXPAND ) ;
2018-06-15 23:21:25 +00:00
m_sizer_part_buttons - > Add ( up_down_sizer , 0 , wxEXPAND ) ;
}
m_sizer_part_buttons - > Show ( false ) ;
btn_load_part - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
btn_load_modifier - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
btn_load_lambda_modifier - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
btn_delete - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
btn_split - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
2018-06-18 12:20:29 +00:00
m_btn_move_up - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
m_btn_move_down - > SetFont ( Slic3r : : GUI : : small_font ( ) ) ;
2018-06-15 23:21:25 +00:00
sizer - > Add ( m_sizer_object_buttons , 0 , wxEXPAND | wxLEFT , 20 ) ;
sizer - > Add ( m_sizer_part_buttons , 0 , wxEXPAND | wxLEFT , 20 ) ;
return sizer ;
}
2018-06-18 12:20:29 +00:00
void update_after_moving ( )
{
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( ! item | | m_selected_object_id < 0 )
return ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
if ( volume_id < 0 )
return ;
Point3 m = m_move_options ;
Point3 l = m_last_coords ;
auto d = Pointf3 ( m . x - l . x , m . y - l . y , m . z - l . z ) ;
2018-07-24 10:15:36 +00:00
auto volume = ( * m_objects ) [ m_selected_object_id ] - > volumes [ volume_id ] ;
2018-06-18 12:20:29 +00:00
volume - > mesh . translate ( d . x , d . y , d . z ) ;
m_last_coords = m ;
m_parts_changed = true ;
parts_changed ( m_selected_object_id ) ;
}
2018-06-15 23:21:25 +00:00
wxSizer * object_movers ( wxWindow * win )
{
2018-06-16 01:04:59 +00:00
// DynamicPrintConfig* config = &get_preset_bundle()->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume
std : : shared_ptr < ConfigOptionsGroup > optgroup = std : : make_shared < ConfigOptionsGroup > ( win , " Move " /*, config*/ ) ;
2018-06-15 23:21:25 +00:00
optgroup - > label_width = 20 ;
2018-06-18 12:20:29 +00:00
optgroup - > m_on_change = [ ] ( t_config_option_key opt_key , boost : : any value ) {
int val = boost : : any_cast < int > ( value ) ;
bool update = false ;
if ( opt_key = = " x " & & m_move_options . x ! = val ) {
update = true ;
m_move_options . x = val ;
}
else if ( opt_key = = " y " & & m_move_options . y ! = val ) {
update = true ;
m_move_options . y = val ;
}
else if ( opt_key = = " z " & & m_move_options . z ! = val ) {
update = true ;
m_move_options . z = val ;
}
if ( update ) update_after_moving ( ) ;
} ;
2018-06-15 23:21:25 +00:00
ConfigOptionDef def ;
def . label = L ( " X " ) ;
def . type = coInt ;
def . gui_type = " slider " ;
def . default_value = new ConfigOptionInt ( 0 ) ;
Option option = Option ( def , " x " ) ;
option . opt . full_width = true ;
optgroup - > append_single_option_line ( option ) ;
2018-06-18 12:20:29 +00:00
m_mover_x = dynamic_cast < wxSlider * > ( optgroup - > get_field ( " x " ) - > getWindow ( ) ) ;
2018-06-15 23:21:25 +00:00
def . label = L ( " Y " ) ;
option = Option ( def , " y " ) ;
optgroup - > append_single_option_line ( option ) ;
2018-06-18 12:20:29 +00:00
m_mover_y = dynamic_cast < wxSlider * > ( optgroup - > get_field ( " y " ) - > getWindow ( ) ) ;
2018-06-15 23:21:25 +00:00
def . label = L ( " Z " ) ;
option = Option ( def , " z " ) ;
optgroup - > append_single_option_line ( option ) ;
2018-06-18 12:20:29 +00:00
m_mover_z = dynamic_cast < wxSlider * > ( optgroup - > get_field ( " z " ) - > getWindow ( ) ) ;
2018-06-15 23:21:25 +00:00
get_optgroups ( ) . push_back ( optgroup ) ; // ogObjectMovers
2018-06-18 12:20:29 +00:00
2018-06-15 23:21:25 +00:00
m_sizer_object_movers = optgroup - > sizer ;
m_sizer_object_movers - > Show ( false ) ;
2018-06-18 12:20:29 +00:00
m_move_options = Point3 ( 0 , 0 , 0 ) ;
m_last_coords = Point3 ( 0 , 0 , 0 ) ;
2018-06-15 23:21:25 +00:00
return optgroup - > sizer ;
}
wxBoxSizer * content_settings ( wxWindow * win )
{
DynamicPrintConfig * config = & get_preset_bundle ( ) - > /*full_config();//*/ printers . get_edited_preset ( ) . config ; // TODO get config from Model_volume
std : : shared_ptr < ConfigOptionsGroup > optgroup = std : : make_shared < ConfigOptionsGroup > ( win , " Extruders " , config ) ;
optgroup - > label_width = label_width ( ) ;
Option option = optgroup - > get_option ( " extruder " ) ;
option . opt . default_value = new ConfigOptionInt ( 1 ) ;
optgroup - > append_single_option_line ( option ) ;
get_optgroups ( ) . push_back ( optgroup ) ; // ogObjectSettings
auto sizer = new wxBoxSizer ( wxVERTICAL ) ;
2018-08-15 08:09:05 +00:00
sizer - > Add ( create_edit_object_buttons ( win ) , 0 , wxEXPAND , 0 ) ; // *** Edit Object Buttons***
2018-06-15 23:21:25 +00:00
sizer - > Add ( optgroup - > sizer , 1 , wxEXPAND | wxLEFT , 20 ) ;
auto add_btn = new wxButton ( win , wxID_ANY , " " , wxDefaultPosition , wxDefaultSize , wxBU_EXACTFIT | wxNO_BORDER ) ;
if ( wxMSW ) add_btn - > SetBackgroundColour ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_WINDOW ) ) ;
add_btn - > SetBitmap ( wxBitmap ( from_u8 ( Slic3r : : var ( " add.png " ) ) , wxBITMAP_TYPE_PNG ) ) ;
sizer - > Add ( add_btn , 0 , wxALIGN_LEFT | wxLEFT , 20 ) ;
sizer - > Add ( object_movers ( win ) , 0 , wxEXPAND | wxLEFT , 20 ) ;
return sizer ;
}
2018-07-04 12:52:36 +00:00
void add_objects_list ( wxWindow * parent , wxBoxSizer * sizer )
{
2018-08-15 08:09:05 +00:00
const auto ol_sizer = create_objects_list ( parent ) ;
2018-07-04 12:52:36 +00:00
sizer - > Add ( ol_sizer , 1 , wxEXPAND | wxTOP , 20 ) ;
set_objects_list_sizer ( ol_sizer ) ;
}
Line add_og_to_object_settings ( const std : : string & option_name , const std : : string & sidetext , int def_value = 0 )
{
Line line = { _ ( option_name ) , " " } ;
ConfigOptionDef def ;
def . type = coInt ;
def . default_value = new ConfigOptionInt ( def_value ) ;
def . sidetext = sidetext ;
def . width = 70 ;
2018-07-29 10:19:08 +00:00
if ( option_name = = " Rotation " )
def . min = - 360 ;
2018-07-04 12:52:36 +00:00
const std : : string lower_name = boost : : algorithm : : to_lower_copy ( option_name ) ;
std : : vector < std : : string > axes { " x " , " y " , " z " } ;
for ( auto axis : axes ) {
def . label = boost : : algorithm : : to_upper_copy ( axis ) ;
Option option = Option ( def , lower_name + " _ " + axis ) ;
option . opt . full_width = true ;
line . append_option ( option ) ;
}
if ( option_name = = " Scale " )
{
def . label = L ( " Units " ) ;
def . type = coStrings ;
def . gui_type = " select_open " ;
def . enum_labels . push_back ( L ( " % " ) ) ;
def . enum_labels . push_back ( L ( " mm " ) ) ;
def . default_value = new ConfigOptionStrings { " % " } ;
def . sidetext = " " ;
Option option = Option ( def , lower_name + " _unit " ) ;
line . append_option ( option ) ;
}
2018-07-29 10:19:08 +00:00
2018-07-04 12:52:36 +00:00
return line ;
}
void add_object_settings ( wxWindow * parent , wxBoxSizer * sizer )
{
auto optgroup = std : : make_shared < ConfigOptionsGroup > ( parent , _ ( L ( " Object Settings " ) ) ) ;
optgroup - > label_width = 100 ;
optgroup - > set_grid_vgap ( 5 ) ;
optgroup - > m_on_change = [ ] ( t_config_option_key opt_key , boost : : any value ) {
if ( opt_key = = " scale_unit " ) {
const wxString & selection = boost : : any_cast < wxString > ( value ) ;
std : : vector < std : : string > axes { " x " , " y " , " z " } ;
for ( auto axis : axes ) {
std : : string key = " scale_ " + axis ;
get_optgroup ( ogFrequentlyObjectSettings ) - > set_side_text ( key , selection ) ;
}
2018-07-29 10:19:08 +00:00
g_is_percent_scale = selection = = _ ( " % " ) ;
update_scale_values ( ) ;
2018-07-04 12:52:36 +00:00
}
} ;
// def.label = L("Name");
// def.type = coString;
// def.tooltip = L("Object name");
// def.full_width = true;
// def.default_value = new ConfigOptionString{ "BlaBla_object.stl" };
// optgroup->append_single_option_line(Option(def, "object_name"));
2018-07-29 10:19:08 +00:00
ConfigOptionDef def ;
def . label = L ( " Name " ) ;
// def.type = coString;
def . gui_type = " legend " ;
def . tooltip = L ( " Object name " ) ;
def . full_width = true ;
2018-07-30 08:48:40 +00:00
def . default_value = new ConfigOptionString { " " } ;
2018-07-29 10:19:08 +00:00
optgroup - > append_single_option_line ( Option ( def , " object_name " ) ) ;
2018-07-04 12:52:36 +00:00
optgroup - > set_flag ( ogSIDE_OPTIONS_VERTICAL ) ;
optgroup - > sidetext_width = 25 ;
optgroup - > append_line ( add_og_to_object_settings ( L ( " Position " ) , L ( " mm " ) ) ) ;
2018-07-29 10:19:08 +00:00
optgroup - > append_line ( add_og_to_object_settings ( L ( " Rotation " ) , " ° " ) ) ;
optgroup - > append_line ( add_og_to_object_settings ( L ( " Scale " ) , " % " ) ) ;
2018-07-04 12:52:36 +00:00
optgroup - > set_flag ( ogDEFAULT ) ;
def . label = L ( " Place on bed " ) ;
def . type = coBool ;
def . tooltip = L ( " Automatic placing of models on printing bed in Y axis " ) ;
def . gui_type = " " ;
def . sidetext = " " ;
def . default_value = new ConfigOptionBool { false } ;
optgroup - > append_single_option_line ( Option ( def , " place_on_bed " ) ) ;
2018-07-24 16:39:40 +00:00
m_option_sizer = new wxBoxSizer ( wxVERTICAL ) ;
optgroup - > sizer - > Add ( m_option_sizer , 1 , wxEXPAND | wxLEFT , 5 ) ;
2018-07-04 12:52:36 +00:00
sizer - > Add ( optgroup - > sizer , 0 , wxEXPAND | wxLEFT | wxTOP , 20 ) ;
optgroup - > disable ( ) ;
get_optgroups ( ) . push_back ( optgroup ) ; // ogFrequentlyObjectSettings
2018-07-23 15:35:50 +00:00
// add_current_settings();
2018-07-04 12:52:36 +00:00
}
2018-06-15 23:21:25 +00:00
// add Collapsible Pane to sizer
wxCollapsiblePane * add_collapsible_pane ( wxWindow * parent , wxBoxSizer * sizer_parent , const wxString & name , std : : function < wxSizer * ( wxWindow * ) > content_function )
{
# ifdef __WXMSW__
auto * collpane = new PrusaCollapsiblePaneMSW ( parent , wxID_ANY , name ) ;
# else
auto * collpane = new PrusaCollapsiblePane /*wxCollapsiblePane*/ ( parent , wxID_ANY , name ) ;
# endif // __WXMSW__
// add the pane with a zero proportion value to the sizer which contains it
sizer_parent - > Add ( collpane , 0 , wxGROW | wxALL , 0 ) ;
wxWindow * win = collpane - > GetPane ( ) ;
wxSizer * sizer = content_function ( win ) ;
wxSizer * sizer_pane = new wxBoxSizer ( wxVERTICAL ) ;
sizer_pane - > Add ( sizer , 1 , wxGROW | wxEXPAND | wxBOTTOM , 2 ) ;
win - > SetSizer ( sizer_pane ) ;
// sizer_pane->SetSizeHints(win);
return collpane ;
}
void add_collapsible_panes ( wxWindow * parent , wxBoxSizer * sizer )
{
// *** Objects List ***
2018-08-15 08:09:05 +00:00
auto collpane = add_collapsible_pane ( parent , sizer , " Objects List: " , create_objects_list ) ;
2018-06-15 23:21:25 +00:00
collpane - > Bind ( wxEVT_COLLAPSIBLEPANE_CHANGED , ( [ collpane ] ( wxCommandEvent & e ) {
// wxWindowUpdateLocker noUpdates(g_right_panel);
if ( collpane - > IsCollapsed ( ) ) {
m_sizer_object_buttons - > Show ( false ) ;
m_sizer_part_buttons - > Show ( false ) ;
m_sizer_object_movers - > Show ( false ) ;
2018-06-19 14:24:49 +00:00
if ( ! m_objects_ctrl - > HasSelection ( ) )
m_collpane_settings - > Show ( false ) ;
2018-06-15 23:21:25 +00:00
}
} ) ) ;
// *** Object/Part Settings ***
m_collpane_settings = add_collapsible_pane ( parent , sizer , " Object Settings " , content_settings ) ;
}
void show_collpane_settings ( bool expert_mode )
{
m_collpane_settings - > Show ( expert_mode & & ! m_objects_model - > IsEmpty ( ) ) ;
}
void add_object_to_list ( const std : : string & name , ModelObject * model_object )
{
2018-07-04 14:32:01 +00:00
wxString item_name = name ;
2018-06-15 23:21:25 +00:00
int scale = model_object - > instances [ 0 ] - > scaling_factor * 100 ;
2018-07-04 14:32:01 +00:00
auto item = m_objects_model - > Add ( item_name , model_object - > instances . size ( ) , scale ) ;
m_objects_ctrl - > Select ( item ) ;
// Add error icon if detected auto-repaire
auto stats = model_object - > volumes [ 0 ] - > mesh . stl . stats ;
int errors = stats . degenerate_facets + stats . edges_fixed + stats . facets_removed +
stats . facets_added + stats . facets_reversed + stats . backwards_edges ;
if ( errors > 0 ) {
const wxDataViewIconText data ( item_name , m_icon_manifold_warning ) ;
wxVariant variant ;
variant < < data ;
m_objects_model - > SetValue ( variant , item , 0 ) ;
}
2018-08-01 10:49:39 +00:00
if ( model_object - > volumes . size ( ) > 1 ) {
2018-07-30 15:03:14 +00:00
for ( auto id = 0 ; id < model_object - > volumes . size ( ) ; id + + )
m_objects_model - > AddChild ( item , model_object - > volumes [ id ] - > name , m_icon_solidmesh , false ) ;
2018-08-01 10:49:39 +00:00
m_objects_ctrl - > Expand ( item ) ;
}
2018-07-30 15:03:14 +00:00
2018-06-19 14:24:49 +00:00
// part_selection_changed();
2018-08-14 11:04:11 +00:00
# ifndef __WXOSX__ //#ifdef __WXMSW__
2018-06-19 14:24:49 +00:00
object_ctrl_selection_changed ( ) ;
# endif //__WXMSW__
2018-06-15 23:21:25 +00:00
}
void delete_object_from_list ( )
{
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( ! item | | m_objects_model - > GetParent ( item ) ! = wxDataViewItem ( 0 ) )
return ;
// m_objects_ctrl->Select(m_objects_model->Delete(item));
m_objects_model - > Delete ( item ) ;
2018-07-04 06:54:30 +00:00
// if (m_objects_model->IsEmpty())
// m_collpane_settings->Show(false);
2018-06-15 23:21:25 +00:00
}
void delete_all_objects_from_list ( )
{
m_objects_model - > DeleteAll ( ) ;
2018-07-04 06:54:30 +00:00
// m_collpane_settings->Show(false);
2018-06-15 23:21:25 +00:00
}
void set_object_count ( int idx , int count )
{
m_objects_model - > SetValue ( wxString : : Format ( " %d " , count ) , idx , 1 ) ;
m_objects_ctrl - > Refresh ( ) ;
}
void set_object_scale ( int idx , int scale )
{
m_objects_model - > SetValue ( wxString : : Format ( " %d%% " , scale ) , idx , 2 ) ;
m_objects_ctrl - > Refresh ( ) ;
}
void unselect_objects ( )
{
2018-08-15 10:47:46 +00:00
if ( ! m_objects_ctrl - > GetSelection ( ) )
return ;
2018-08-10 12:02:47 +00:00
g_prevent_list_events = true ;
2018-08-15 10:47:46 +00:00
m_objects_ctrl - > UnselectAll ( ) ;
part_selection_changed ( ) ;
2018-08-10 12:02:47 +00:00
g_prevent_list_events = false ;
2018-06-15 23:21:25 +00:00
}
void select_current_object ( int idx )
{
g_prevent_list_events = true ;
m_objects_ctrl - > UnselectAll ( ) ;
if ( idx < 0 ) {
g_prevent_list_events = false ;
return ;
}
m_objects_ctrl - > Select ( m_objects_model - > GetItemById ( idx ) ) ;
2018-06-19 14:24:49 +00:00
part_selection_changed ( ) ;
2018-06-15 23:21:25 +00:00
g_prevent_list_events = false ;
2018-07-04 06:54:30 +00:00
}
void remove ( )
{
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( ! item )
return ;
if ( m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) ) {
if ( m_event_remove_object > 0 ) {
wxCommandEvent event ( m_event_remove_object ) ;
get_main_frame ( ) - > ProcessWindowEvent ( event ) ;
}
// delete_object_from_list();
}
else
on_btn_del ( ) ;
2018-06-19 14:24:49 +00:00
}
void object_ctrl_selection_changed ( )
{
if ( g_prevent_list_events ) return ;
2018-06-15 23:21:25 +00:00
2018-06-19 14:24:49 +00:00
part_selection_changed ( ) ;
if ( m_event_object_selection_changed > 0 ) {
wxCommandEvent event ( m_event_object_selection_changed ) ;
2018-08-14 12:13:07 +00:00
event . SetInt ( int ( m_objects_model - > GetParent ( m_objects_ctrl - > GetSelection ( ) ) ! = wxDataViewItem ( 0 ) ) ) ;
2018-06-19 14:24:49 +00:00
event . SetId ( m_selected_object_id ) ;
get_main_frame ( ) - > ProcessWindowEvent ( event ) ;
2018-06-15 23:21:25 +00:00
}
2018-08-01 13:54:56 +00:00
# ifdef __WXOSX__
update_extruder_in_config ( g_selected_extruder ) ;
# endif //__WXOSX__
2018-06-15 23:21:25 +00:00
}
2018-06-19 14:24:49 +00:00
2018-08-15 08:09:05 +00:00
void object_ctrl_context_menu ( )
{
wxDataViewItem item ;
wxDataViewColumn * col ;
m_objects_ctrl - > HitTest ( get_mouse_position_in_control ( ) , item , col ) ;
wxString title = col - > GetTitle ( ) ;
if ( ! item ) return ;
if ( title = = " " )
show_context_menu ( ) ;
// ys_FIXME
// else if (title == _("Name") && pt.x >15 &&
// m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData())
// {
// if (is_windows10())
// fix_through_netfabb();
// }
# ifndef __WXMSW__
m_objects_ctrl - > GetMainWindow ( ) - > SetToolTip ( " " ) ; // hide tooltip
# endif //__WXMSW__
}
void object_ctrl_key_event ( wxKeyEvent & event )
{
if ( event . GetKeyCode ( ) = = WXK_TAB )
m_objects_ctrl - > Navigate ( event . ShiftDown ( ) ? wxNavigationKeyEvent : : IsBackward : wxNavigationKeyEvent : : IsForward ) ;
else if ( event . GetKeyCode ( ) = = WXK_DELETE
# ifdef __WXOSX__
| | event . GetKeyCode ( ) = = WXK_BACK
# endif //__WXOSX__
) {
printf ( " WXK_BACK \n " ) ;
remove ( ) ;
}
else
event . Skip ( ) ;
}
void object_ctrl_item_value_change ( wxDataViewEvent & event )
{
if ( event . GetColumn ( ) = = 3 )
{
wxVariant variant ;
m_objects_model - > GetValue ( variant , event . GetItem ( ) , 3 ) ;
# ifdef __WXOSX__
g_selected_extruder = variant . GetString ( ) ;
# else // --> for Linux
update_extruder_in_config ( variant . GetString ( ) ) ;
# endif //__WXOSX__
}
}
2018-07-25 14:13:20 +00:00
//update_optgroup
void update_settings_list ( )
{
2018-07-27 08:42:54 +00:00
# ifdef __WXGTK__
auto parent = get_optgroup ( ogFrequentlyObjectSettings ) - > get_parent ( ) ;
# else
auto parent = get_optgroup ( ogFrequentlyObjectSettings ) - > parent ( ) ;
# endif /* __WXGTK__ */
2018-07-25 14:13:20 +00:00
// There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/Slic3r/issues/898 and https://github.com/prusa3d/Slic3r/issues/952.
// The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason,
// we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely.
2018-07-27 08:42:54 +00:00
# ifdef __linux__
2018-07-26 08:59:03 +00:00
std : : unique_ptr < wxWindowUpdateLocker > no_updates ( new wxWindowUpdateLocker ( parent ) ) ;
2018-07-25 14:13:20 +00:00
# else
wxWindowUpdateLocker noUpdates ( parent ) ;
# endif
m_option_sizer - > Clear ( true ) ;
if ( m_config )
{
2018-07-31 13:31:12 +00:00
auto extra_column = [ ] ( wxWindow * parent , const Line & line )
2018-07-25 14:13:20 +00:00
{
auto opt_key = ( line . get_options ( ) ) [ 0 ] . opt_id ; //we assume that we have one option per line
auto btn = new wxBitmapButton ( parent , wxID_ANY , wxBitmap ( Slic3r : : GUI : : from_u8 ( Slic3r : : var ( " erase.png " ) ) , wxBITMAP_TYPE_PNG ) ,
wxDefaultPosition , wxDefaultSize , wxBORDER_NONE ) ;
btn - > Bind ( wxEVT_BUTTON , [ opt_key ] ( wxEvent & event ) {
( * m_config ) - > erase ( opt_key ) ;
wxTheApp - > CallAfter ( [ ] ( ) { update_settings_list ( ) ; } ) ;
} ) ;
return btn ;
} ;
std : : map < std : : string , std : : vector < std : : string > > cat_options ;
auto opt_keys = ( * m_config ) - > keys ( ) ;
if ( opt_keys . size ( ) = = 1 & & opt_keys [ 0 ] = = " extruder " )
return ;
2018-08-01 10:49:39 +00:00
auto extruders_cnt = get_preset_bundle ( ) - > printers . get_edited_preset ( ) . config . option < ConfigOptionFloats > ( " nozzle_diameter " ) - > values . size ( ) ;
2018-07-25 14:13:20 +00:00
for ( auto & opt_key : opt_keys ) {
auto category = ( * m_config ) - > def ( ) - > get ( opt_key ) - > category ;
2018-08-01 10:49:39 +00:00
if ( category . empty ( ) | |
( category = = " Extruders " & & extruders_cnt = = 1 ) ) continue ;
2018-07-25 14:13:20 +00:00
std : : vector < std : : string > new_category ;
auto & cat_opt = cat_options . find ( category ) = = cat_options . end ( ) ? new_category : cat_options . at ( category ) ;
cat_opt . push_back ( opt_key ) ;
if ( cat_opt . size ( ) = = 1 )
cat_options [ category ] = cat_opt ;
}
m_og_settings . resize ( 0 ) ;
for ( auto & cat : cat_options ) {
if ( cat . second . size ( ) = = 1 & & cat . second [ 0 ] = = " extruder " )
continue ;
auto optgroup = std : : make_shared < ConfigOptionsGroup > ( parent , cat . first , * m_config , false , ogDEFAULT , extra_column ) ;
optgroup - > label_width = 100 ;
optgroup - > sidetext_width = 70 ;
for ( auto & opt : cat . second )
{
if ( opt = = " extruder " )
continue ;
Option option = optgroup - > get_option ( opt ) ;
option . opt . width = 70 ;
optgroup - > append_single_option_line ( option ) ;
}
optgroup - > reload_config ( ) ;
m_option_sizer - > Add ( optgroup - > sizer , 0 , wxEXPAND | wxALL , 0 ) ;
m_og_settings . push_back ( optgroup ) ;
}
}
# ifdef __linux__
no_updates . reset ( nullptr ) ;
# endif
2018-07-27 08:42:54 +00:00
get_right_panel ( ) - > Layout ( ) ;
get_right_panel ( ) - > GetParent ( ) - > Layout ( ) ;
2018-07-25 14:13:20 +00:00
}
2018-07-23 15:35:50 +00:00
void get_settings_choice ( wxMenu * menu , int id , bool is_part )
{
auto category_name = menu - > GetLabel ( id ) ;
wxArrayString names ;
2018-07-25 14:13:20 +00:00
wxArrayInt selections ;
2018-07-23 15:35:50 +00:00
settings_menu_hierarchy settings_menu ;
get_options_menu ( settings_menu , is_part ) ;
2018-07-24 16:39:40 +00:00
std : : vector < std : : pair < std : : string , std : : string > > * settings_list = nullptr ;
2018-07-25 14:13:20 +00:00
auto opt_keys = ( * m_config ) - > keys ( ) ;
2018-07-24 16:39:40 +00:00
for ( auto & cat : settings_menu )
2018-07-23 15:35:50 +00:00
{
2018-07-24 16:39:40 +00:00
if ( _ ( cat . first ) = = category_name ) {
2018-07-25 14:13:20 +00:00
int sel = 0 ;
for ( auto & pair : cat . second ) {
2018-07-23 15:35:50 +00:00
names . Add ( _ ( pair . second ) ) ;
2018-07-25 14:13:20 +00:00
if ( find ( opt_keys . begin ( ) , opt_keys . end ( ) , pair . first ) ! = opt_keys . end ( ) )
selections . Add ( sel ) ;
sel + + ;
}
2018-07-24 16:39:40 +00:00
settings_list = & cat . second ;
2018-07-23 15:35:50 +00:00
break ;
}
2018-07-25 14:13:20 +00:00
}
2018-07-24 16:39:40 +00:00
if ( ! settings_list )
return ;
2018-07-23 15:35:50 +00:00
2018-07-25 14:13:20 +00:00
if ( wxGetMultipleChoices ( selections , _ ( L ( " Select showing settings " ) ) , category_name , names ) = = 0 )
return ;
2018-07-24 16:39:40 +00:00
2018-07-25 14:13:20 +00:00
std : : vector < std : : string > selected_options ;
2018-07-24 16:39:40 +00:00
for ( auto sel : selections )
2018-07-25 14:13:20 +00:00
selected_options . push_back ( ( * settings_list ) [ sel ] . first ) ;
for ( auto & setting : ( * settings_list ) )
2018-07-24 16:39:40 +00:00
{
2018-07-25 14:13:20 +00:00
auto & opt_key = setting . first ;
if ( find ( opt_keys . begin ( ) , opt_keys . end ( ) , opt_key ) ! = opt_keys . end ( ) & &
find ( selected_options . begin ( ) , selected_options . end ( ) , opt_key ) = = selected_options . end ( ) )
( * m_config ) - > erase ( opt_key ) ;
if ( find ( opt_keys . begin ( ) , opt_keys . end ( ) , opt_key ) = = opt_keys . end ( ) & &
find ( selected_options . begin ( ) , selected_options . end ( ) , opt_key ) ! = selected_options . end ( ) )
( * m_config ) - > set_key_value ( opt_key , m_default_config . get ( ) - > option ( opt_key ) - > clone ( ) ) ;
2018-07-24 16:39:40 +00:00
}
2018-07-25 14:13:20 +00:00
update_settings_list ( ) ;
2018-07-23 15:35:50 +00:00
}
2018-07-31 10:04:01 +00:00
bool cur_item_hase_children ( )
{
wxDataViewItemArray children ;
if ( m_objects_model - > GetChildren ( m_objects_ctrl - > GetSelection ( ) , children ) > 0 )
return true ;
return false ;
}
2018-07-31 13:31:12 +00:00
wxMenuItem * menu_item_split ( wxMenu * menu , int id ) {
auto menu_item = new wxMenuItem ( menu , id , _ ( L ( " Split to parts " ) ) ) ;
menu_item - > SetBitmap ( m_bmp_split ) ;
return menu_item ;
}
wxMenuItem * menu_item_settings ( wxMenu * menu , int id ) {
auto menu_item = new wxMenuItem ( menu , id , _ ( L ( " Add settings " ) ) ) ;
menu_item - > SetBitmap ( m_bmp_cog ) ;
auto sub_menu = create_add_settings_popupmenu ( false ) ;
menu_item - > SetSubMenu ( sub_menu ) ;
return menu_item ;
}
2018-07-23 15:35:50 +00:00
wxMenu * create_add_part_popupmenu ( )
{
2018-07-04 06:54:30 +00:00
wxMenu * menu = new wxMenu ;
2018-07-25 14:13:20 +00:00
std : : vector < std : : string > menu_items = { L ( " Add part " ) , L ( " Add modifier " ) , L ( " Add generic " ) } ;
2018-07-30 15:03:14 +00:00
wxWindowID config_id_base = wxWindow : : NewControlId ( menu_items . size ( ) + 2 ) ;
2018-07-25 14:13:20 +00:00
int i = 0 ;
for ( auto & item : menu_items ) {
auto menu_item = new wxMenuItem ( menu , config_id_base + i , _ ( item ) ) ;
menu_item - > SetBitmap ( i = = 0 ? m_icon_solidmesh : m_icon_modifiermesh ) ;
menu - > Append ( menu_item ) ;
i + + ;
2018-07-30 15:03:14 +00:00
}
menu - > AppendSeparator ( ) ;
2018-07-31 13:31:12 +00:00
auto menu_item = menu_item_split ( menu , config_id_base + i ) ;
2018-07-30 15:03:14 +00:00
menu - > Append ( menu_item ) ;
2018-07-31 10:04:01 +00:00
menu_item - > Enable ( ! cur_item_hase_children ( ) ) ;
2018-07-04 06:54:30 +00:00
2018-07-31 13:31:12 +00:00
menu - > AppendSeparator ( ) ;
// Append settings popupmenu
menu - > Append ( menu_item_settings ( menu , config_id_base + i + 1 ) ) ;
2018-07-04 06:54:30 +00:00
wxWindow * win = get_tab_panel ( ) - > GetPage ( 0 ) ;
2018-07-23 15:35:50 +00:00
menu - > Bind ( wxEVT_MENU , [ config_id_base , win , menu ] ( wxEvent & event ) {
2018-07-04 06:54:30 +00:00
switch ( event . GetId ( ) - config_id_base ) {
case 0 :
on_btn_load ( win ) ;
break ;
case 1 :
on_btn_load ( win , true ) ;
break ;
case 2 :
on_btn_load ( win , true , true ) ;
break ;
2018-07-30 15:03:14 +00:00
case 3 :
2018-07-31 13:31:12 +00:00
on_btn_split ( false ) ;
2018-07-30 15:03:14 +00:00
break ;
2018-07-23 15:35:50 +00:00
default : {
get_settings_choice ( menu , event . GetId ( ) , false ) ;
break ; }
2018-07-04 06:54:30 +00:00
}
} ) ;
2018-07-23 15:35:50 +00:00
2018-07-31 13:31:12 +00:00
return menu ;
}
2018-07-23 15:35:50 +00:00
2018-07-31 13:31:12 +00:00
wxMenu * create_part_settings_popupmenu ( )
{
wxMenu * menu = new wxMenu ;
wxWindowID config_id_base = wxWindow : : NewControlId ( 2 ) ;
2018-07-23 15:35:50 +00:00
2018-07-31 13:31:12 +00:00
menu - > Append ( menu_item_split ( menu , config_id_base ) ) ;
2018-07-23 15:35:50 +00:00
2018-07-31 13:31:12 +00:00
menu - > AppendSeparator ( ) ;
// Append settings popupmenu
menu - > Append ( menu_item_settings ( menu , config_id_base + 1 ) ) ;
menu - > Bind ( wxEVT_MENU , [ config_id_base , menu ] ( wxEvent & event ) {
switch ( event . GetId ( ) - config_id_base ) {
case 0 :
on_btn_split ( true ) ;
break ;
default : {
get_settings_choice ( menu , event . GetId ( ) , true ) ;
break ; }
}
} ) ;
return menu ;
2018-07-04 06:54:30 +00:00
}
2018-07-23 15:35:50 +00:00
wxMenu * create_add_settings_popupmenu ( bool is_part )
2018-07-09 14:42:31 +00:00
{
wxMenu * menu = new wxMenu ;
2018-07-23 15:35:50 +00:00
auto categories = get_category_icon ( ) ;
2018-07-09 14:42:31 +00:00
2018-07-23 15:35:50 +00:00
settings_menu_hierarchy settings_menu ;
get_options_menu ( settings_menu , is_part ) ;
2018-07-09 14:42:31 +00:00
2018-07-23 15:35:50 +00:00
for ( auto cat : settings_menu )
{
2018-07-31 13:31:12 +00:00
auto menu_item = new wxMenuItem ( menu , wxID_ANY , _ ( cat . first ) ) ;
2018-07-23 15:35:50 +00:00
menu_item - > SetBitmap ( categories . find ( cat . first ) = = categories . end ( ) ?
wxNullBitmap : categories . at ( cat . first ) ) ;
2018-07-09 14:42:31 +00:00
menu - > Append ( menu_item ) ;
}
2018-07-23 15:35:50 +00:00
menu - > Bind ( wxEVT_MENU , [ menu ] ( wxEvent & event ) {
get_settings_choice ( menu , event . GetId ( ) , true ) ;
} ) ;
2018-07-09 14:42:31 +00:00
return menu ;
}
2018-08-15 08:09:05 +00:00
void show_context_menu ( )
2018-07-04 06:54:30 +00:00
{
2018-08-15 08:09:05 +00:00
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( item )
{
if ( m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) ) {
auto menu = create_add_part_popupmenu ( ) ;
get_tab_panel ( ) - > GetPage ( 0 ) - > PopupMenu ( menu ) ;
}
else {
auto menu = create_part_settings_popupmenu ( ) ;
get_tab_panel ( ) - > GetPage ( 0 ) - > PopupMenu ( menu ) ;
}
}
2018-07-04 06:54:30 +00:00
}
2018-06-15 23:21:25 +00:00
// ******
2018-06-14 21:31:15 +00:00
void load_part ( wxWindow * parent , ModelObject * model_object ,
wxArrayString & part_names , const bool is_modifier )
2018-06-13 14:39:33 +00:00
{
2018-06-14 13:33:42 +00:00
wxArrayString input_files ;
open_model ( parent , input_files ) ;
for ( int i = 0 ; i < input_files . size ( ) ; + + i ) {
std : : string input_file = input_files . Item ( i ) . ToStdString ( ) ;
Model model ;
try {
model = Model : : read_from_file ( input_file ) ;
}
catch ( std : : exception & e ) {
auto msg = _ ( L ( " Error! " ) ) + input_file + " : " + e . what ( ) + " . " ;
show_error ( parent , msg ) ;
exit ( 1 ) ;
}
for ( auto object : model . objects ) {
for ( auto volume : object - > volumes ) {
auto new_volume = model_object - > add_volume ( * volume ) ;
new_volume - > modifier = is_modifier ;
boost : : filesystem : : path ( input_file ) . filename ( ) . string ( ) ;
new_volume - > name = boost : : filesystem : : path ( input_file ) . filename ( ) . string ( ) ;
part_names . Add ( new_volume - > name ) ;
// apply the same translation we applied to the object
new_volume - > mesh . translate ( model_object - > origin_translation . x ,
model_object - > origin_translation . y ,
model_object - > origin_translation . y ) ;
// set a default extruder value, since user can't add it manually
new_volume - > config . set_key_value ( " extruder " , new ConfigOptionInt ( 0 ) ) ;
m_parts_changed = true ;
}
}
}
2018-06-13 14:39:33 +00:00
}
2018-06-14 21:31:15 +00:00
void load_lambda ( wxWindow * parent , ModelObject * model_object ,
wxArrayString & part_names , const bool is_modifier )
{
auto dlg = new LambdaObjectDialog ( parent ) ;
if ( dlg - > ShowModal ( ) = = wxID_CANCEL ) {
return ;
}
std : : string name = " lambda- " ;
TriangleMesh mesh ;
auto params = dlg - > ObjectParameters ( ) ;
switch ( params . type )
{
case LambdaTypeBox : {
mesh = make_cube ( params . dim [ 0 ] , params . dim [ 1 ] , params . dim [ 2 ] ) ;
name + = " Box " ;
break ; }
case LambdaTypeCylinder : {
mesh = make_cylinder ( params . cyl_r , params . cyl_h ) ;
name + = " Cylinder " ;
break ; }
case LambdaTypeSphere : {
mesh = make_sphere ( params . sph_rho ) ;
name + = " Sphere " ;
break ; }
case LambdaTypeSlab : {
const auto & size = model_object - > bounding_box ( ) . size ( ) ;
mesh = make_cube ( size . x * 1.5 , size . y * 1.5 , params . slab_h ) ;
// box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z
mesh . translate ( - size . x * 1.5 / 2.0 , - size . y * 1.5 / 2.0 , params . slab_z ) ;
name + = " Slab " ;
break ; }
default :
break ;
}
mesh . repair ( ) ;
auto new_volume = model_object - > add_volume ( mesh ) ;
new_volume - > modifier = is_modifier ;
new_volume - > name = name ;
// set a default extruder value, since user can't add it manually
new_volume - > config . set_key_value ( " extruder " , new ConfigOptionInt ( 0 ) ) ;
part_names . Add ( name ) ;
m_parts_changed = true ;
}
void on_btn_load ( wxWindow * parent , bool is_modifier /*= false*/ , bool is_lambda /* = false*/ )
2018-06-14 13:33:42 +00:00
{
2018-06-15 23:21:25 +00:00
auto item = m_objects_ctrl - > GetSelection ( ) ;
2018-06-14 13:33:42 +00:00
if ( ! item )
return ;
int obj_idx = - 1 ;
2018-06-15 23:21:25 +00:00
if ( m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) )
obj_idx = m_objects_model - > GetIdByItem ( item ) ;
2018-06-14 13:33:42 +00:00
else
return ;
if ( obj_idx < 0 ) return ;
wxArrayString part_names ;
2018-06-14 21:31:15 +00:00
if ( is_lambda )
2018-07-24 10:15:36 +00:00
load_lambda ( parent , ( * m_objects ) [ obj_idx ] , part_names , is_modifier ) ;
2018-06-14 21:31:15 +00:00
else
2018-07-24 10:15:36 +00:00
load_part ( parent , ( * m_objects ) [ obj_idx ] , part_names , is_modifier ) ;
2018-06-14 13:33:42 +00:00
2018-06-14 19:48:06 +00:00
parts_changed ( obj_idx ) ;
2018-06-14 13:33:42 +00:00
for ( int i = 0 ; i < part_names . size ( ) ; + + i )
2018-06-18 12:20:29 +00:00
m_objects_ctrl - > Select ( m_objects_model - > AddChild ( item , part_names . Item ( i ) ,
is_modifier ? m_icon_modifiermesh : m_icon_solidmesh ) ) ;
2018-06-19 14:24:49 +00:00
// part_selection_changed();
# ifdef __WXMSW__
object_ctrl_selection_changed ( ) ;
# endif //__WXMSW__
2018-06-14 13:33:42 +00:00
}
2018-06-18 13:26:09 +00:00
void on_btn_del ( )
{
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( ! item ) return ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
if ( volume_id < 0 )
return ;
2018-07-24 10:15:36 +00:00
auto volume = ( * m_objects ) [ m_selected_object_id ] - > volumes [ volume_id ] ;
2018-06-18 13:26:09 +00:00
// if user is deleting the last solid part, throw error
int solid_cnt = 0 ;
2018-07-24 10:15:36 +00:00
for ( auto vol : ( * m_objects ) [ m_selected_object_id ] - > volumes )
2018-06-18 13:26:09 +00:00
if ( ! vol - > modifier )
+ + solid_cnt ;
if ( ! volume - > modifier & & solid_cnt = = 1 ) {
Slic3r : : GUI : : show_error ( nullptr , _ ( L ( " You can't delete the last solid part from this object. " ) ) ) ;
return ;
}
2018-07-24 10:15:36 +00:00
( * m_objects ) [ m_selected_object_id ] - > delete_volume ( volume_id ) ;
2018-06-18 13:26:09 +00:00
m_parts_changed = true ;
parts_changed ( m_selected_object_id ) ;
2018-06-19 14:24:49 +00:00
m_objects_ctrl - > Select ( m_objects_model - > Delete ( item ) ) ;
part_selection_changed ( ) ;
// #ifdef __WXMSW__
// object_ctrl_selection_changed();
// #endif //__WXMSW__
2018-06-18 13:26:09 +00:00
}
2018-07-31 13:31:12 +00:00
void on_btn_split ( const bool split_part )
2018-06-18 13:26:09 +00:00
{
auto item = m_objects_ctrl - > GetSelection ( ) ;
2018-08-14 11:04:11 +00:00
if ( ! item | | m_selected_object_id < 0 )
2018-06-18 13:26:09 +00:00
return ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
2018-07-30 15:03:14 +00:00
ModelVolume * volume ;
2018-07-31 13:31:12 +00:00
if ( volume_id < 0 ) {
if ( split_part ) return ;
else
volume = ( * m_objects ) [ m_selected_object_id ] - > volumes [ 0 ] ; }
2018-07-30 15:03:14 +00:00
else
volume = ( * m_objects ) [ m_selected_object_id ] - > volumes [ volume_id ] ;
DynamicPrintConfig & config = get_preset_bundle ( ) - > printers . get_edited_preset ( ) . config ;
auto nozzle_dmrs_cnt = config . option < ConfigOptionFloats > ( " nozzle_diameter " ) - > values . size ( ) ;
2018-07-31 10:04:01 +00:00
auto split_rez = volume - > split ( nozzle_dmrs_cnt ) ;
if ( split_rez = = 1 ) {
wxMessageBox ( _ ( L ( " The selected object couldn't be split because it contains only one part. " ) ) ) ;
return ;
}
auto model_object = ( * m_objects ) [ m_selected_object_id ] ;
2018-07-31 13:31:12 +00:00
if ( split_part ) {
auto parent = m_objects_model - > GetParent ( item ) ;
m_objects_model - > DeleteChildren ( parent ) ;
for ( auto id = 0 ; id < model_object - > volumes . size ( ) ; id + + )
m_objects_model - > AddChild ( parent , model_object - > volumes [ id ] - > name ,
model_object - > volumes [ id ] - > modifier ? m_icon_modifiermesh : m_icon_solidmesh , false ) ;
m_objects_ctrl - > Expand ( parent ) ;
}
else {
for ( auto id = 0 ; id < model_object - > volumes . size ( ) ; id + + )
m_objects_model - > AddChild ( item , model_object - > volumes [ id ] - > name , m_icon_solidmesh , false ) ;
m_objects_ctrl - > Expand ( item ) ;
}
2018-06-18 13:26:09 +00:00
}
void on_btn_move_up ( ) {
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( ! item )
return ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
if ( volume_id < 0 )
return ;
2018-07-24 10:15:36 +00:00
auto & volumes = ( * m_objects ) [ m_selected_object_id ] - > volumes ;
2018-06-18 13:26:09 +00:00
if ( 0 < volume_id & & volume_id < volumes . size ( ) ) {
std : : swap ( volumes [ volume_id - 1 ] , volumes [ volume_id ] ) ;
m_parts_changed = true ;
2018-06-19 10:24:16 +00:00
m_objects_ctrl - > Select ( m_objects_model - > MoveChildUp ( item ) ) ;
2018-06-19 14:24:49 +00:00
part_selection_changed ( ) ;
// #ifdef __WXMSW__
// object_ctrl_selection_changed();
// #endif //__WXMSW__
2018-06-18 13:26:09 +00:00
}
}
void on_btn_move_down ( ) {
auto item = m_objects_ctrl - > GetSelection ( ) ;
if ( ! item )
return ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
if ( volume_id < 0 )
return ;
2018-07-24 10:15:36 +00:00
auto & volumes = ( * m_objects ) [ m_selected_object_id ] - > volumes ;
2018-06-18 13:26:09 +00:00
if ( 0 < = volume_id & & volume_id + 1 < volumes . size ( ) ) {
2018-06-19 10:24:16 +00:00
std : : swap ( volumes [ volume_id + 1 ] , volumes [ volume_id ] ) ;
2018-06-18 13:26:09 +00:00
m_parts_changed = true ;
2018-06-19 10:24:16 +00:00
m_objects_ctrl - > Select ( m_objects_model - > MoveChildDown ( item ) ) ;
2018-06-19 14:24:49 +00:00
part_selection_changed ( ) ;
// #ifdef __WXMSW__
// object_ctrl_selection_changed();
// #endif //__WXMSW__
2018-06-18 13:26:09 +00:00
}
}
2018-06-14 19:48:06 +00:00
void parts_changed ( int obj_idx )
{
2018-06-15 23:21:25 +00:00
if ( m_event_object_settings_changed < = 0 ) return ;
2018-06-14 19:48:06 +00:00
2018-06-15 23:21:25 +00:00
wxCommandEvent e ( m_event_object_settings_changed ) ;
2018-06-14 19:48:06 +00:00
auto event_str = wxString : : Format ( " %d %d %d " , obj_idx ,
is_parts_changed ( ) ? 1 : 0 ,
is_part_settings_changed ( ) ? 1 : 0 ) ;
e . SetString ( event_str ) ;
get_main_frame ( ) - > ProcessWindowEvent ( e ) ;
}
2018-07-04 14:32:01 +00:00
void update_settings_value ( )
{
auto og = get_optgroup ( ogFrequentlyObjectSettings ) ;
2018-07-27 14:55:42 +00:00
if ( m_selected_object_id < 0 | | m_objects - > size ( ) < = m_selected_object_id ) {
2018-07-04 14:32:01 +00:00
og - > set_value ( " scale_x " , 0 ) ;
og - > set_value ( " scale_y " , 0 ) ;
og - > set_value ( " scale_z " , 0 ) ;
2018-08-14 14:10:58 +00:00
og - > disable ( ) ;
2018-07-04 14:32:01 +00:00
return ;
}
2018-07-29 10:19:08 +00:00
g_is_percent_scale = boost : : any_cast < wxString > ( og - > get_value ( " scale_unit " ) ) = = _ ( " % " ) ;
update_scale_values ( ) ;
2018-07-30 08:48:40 +00:00
update_rotation_values ( ) ;
2018-08-14 14:10:58 +00:00
og - > enable ( ) ;
2018-07-04 14:32:01 +00:00
}
2018-06-13 14:39:33 +00:00
2018-06-18 12:20:29 +00:00
void part_selection_changed ( )
{
2018-06-19 14:24:49 +00:00
auto item = m_objects_ctrl - > GetSelection ( ) ;
int obj_idx = - 1 ;
2018-07-29 10:19:08 +00:00
auto og = get_optgroup ( ogFrequentlyObjectSettings ) ;
2018-06-19 14:24:49 +00:00
if ( item )
{
2018-07-24 16:39:40 +00:00
bool is_part = false ;
if ( m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) ) {
2018-06-19 14:24:49 +00:00
obj_idx = m_objects_model - > GetIdByItem ( item ) ;
2018-07-25 14:13:20 +00:00
og - > set_name ( " " + _ ( L ( " Object Settings " ) ) + " " ) ;
m_config = std : : make_shared < DynamicPrintConfig * > ( & ( * m_objects ) [ obj_idx ] - > config ) ;
2018-07-24 16:39:40 +00:00
}
2018-06-19 14:24:49 +00:00
else {
auto parent = m_objects_model - > GetParent ( item ) ;
// Take ID of the parent object to "inform" perl-side which object have to be selected on the scene
obj_idx = m_objects_model - > GetIdByItem ( parent ) ;
2018-07-25 14:13:20 +00:00
og - > set_name ( " " + _ ( L ( " Part Settings " ) ) + " " ) ;
2018-07-24 16:39:40 +00:00
is_part = true ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
2018-07-25 14:13:20 +00:00
m_config = std : : make_shared < DynamicPrintConfig * > ( & ( * m_objects ) [ obj_idx ] - > volumes [ volume_id ] - > config ) ;
2018-06-19 14:24:49 +00:00
}
2018-07-24 16:39:40 +00:00
auto config = m_config ;
2018-07-29 10:19:08 +00:00
og - > set_value ( " object_name " , m_objects_model - > GetName ( item ) ) ;
2018-07-24 16:39:40 +00:00
m_default_config = std : : make_shared < DynamicPrintConfig > ( * DynamicPrintConfig : : new_from_defaults_keys ( get_options ( is_part ) ) ) ;
2018-06-19 14:24:49 +00:00
}
2018-07-29 10:19:08 +00:00
else {
wxString empty_str = wxEmptyString ;
og - > set_value ( " object_name " , empty_str ) ;
m_config = nullptr ;
}
2018-07-25 14:13:20 +00:00
update_settings_list ( ) ;
2018-06-19 14:24:49 +00:00
m_selected_object_id = obj_idx ;
2018-07-04 14:32:01 +00:00
update_settings_value ( ) ;
2018-07-04 06:54:30 +00:00
/* wxWindowUpdateLocker noUpdates(get_right_panel());
2018-06-19 14:24:49 +00:00
2018-06-18 12:20:29 +00:00
m_move_options = Point3 ( 0 , 0 , 0 ) ;
m_last_coords = Point3 ( 0 , 0 , 0 ) ;
// reset move sliders
std : : vector < std : : string > opt_keys = { " x " , " y " , " z " } ;
auto og = get_optgroup ( ogObjectMovers ) ;
for ( auto opt_key : opt_keys )
og - > set_value ( opt_key , int ( 0 ) ) ;
2018-07-04 06:54:30 +00:00
// if (!item || m_selected_object_id < 0){
if ( m_selected_object_id < 0 ) {
2018-06-18 12:20:29 +00:00
m_sizer_object_buttons - > Show ( false ) ;
m_sizer_part_buttons - > Show ( false ) ;
m_sizer_object_movers - > Show ( false ) ;
m_collpane_settings - > Show ( false ) ;
return ;
}
m_collpane_settings - > Show ( true ) ;
auto volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
if ( volume_id < 0 ) {
m_sizer_object_buttons - > Show ( true ) ;
m_sizer_part_buttons - > Show ( false ) ;
m_sizer_object_movers - > Show ( false ) ;
m_collpane_settings - > SetLabelText ( _ ( L ( " Object Settings " ) ) + " : " ) ;
// elsif($itemData->{type} eq 'object') {
// # select nothing in 3D preview
//
// # attach object config to settings panel
// $self->{optgroup_movers}->disable;
// $self->{staticbox}->SetLabel('Object Settings');
// @opt_keys = (map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new);
// $config = $self->{model_object}->config;
// }
return ;
}
m_collpane_settings - > SetLabelText ( _ ( L ( " Part Settings " ) ) + " : " ) ;
m_sizer_object_buttons - > Show ( false ) ;
m_sizer_part_buttons - > Show ( true ) ;
m_sizer_object_movers - > Show ( true ) ;
auto bb_size = m_objects [ m_selected_object_id ] - > bounding_box ( ) . size ( ) ;
int scale = 10 ; //??
m_mover_x - > SetMin ( - bb_size . x * 4 * scale ) ;
m_mover_x - > SetMax ( bb_size . x * 4 * scale ) ;
m_mover_y - > SetMin ( - bb_size . y * 4 * scale ) ;
m_mover_y - > SetMax ( bb_size . y * 4 * scale ) ;
m_mover_z - > SetMin ( - bb_size . z * 4 * scale ) ;
m_mover_z - > SetMax ( bb_size . z * 4 * scale ) ;
// my ($config, @opt_keys);
m_btn_move_up - > Enable ( volume_id > 0 ) ;
m_btn_move_down - > Enable ( volume_id + 1 < m_objects [ m_selected_object_id ] - > volumes . size ( ) ) ;
// attach volume config to settings panel
auto volume = m_objects [ m_selected_object_id ] - > volumes [ volume_id ] ;
if ( volume - > modifier )
og - > enable ( ) ;
else
og - > disable ( ) ;
// auto config = volume->config;
// get default values
// @opt_keys = @{Slic3r::Config::PrintRegion->new->get_keys};
// }
/*
# get default values
my $ default_config = Slic3r : : Config : : new_from_defaults_keys ( \ @ opt_keys ) ;
# append default extruder
push @ opt_keys , ' extruder ' ;
$ default_config - > set ( ' extruder ' , 0 ) ;
$ config - > set_ifndef ( ' extruder ' , 0 ) ;
$ self - > { settings_panel } - > set_default_config ( $ default_config ) ;
$ self - > { settings_panel } - > set_config ( $ config ) ;
$ self - > { settings_panel } - > set_opt_keys ( \ @ opt_keys ) ;
$ self - > { settings_panel } - > set_fixed_options ( [ qw ( extruder ) ] ) ;
$ self - > { settings_panel } - > enable ;
}
*/
}
2018-07-04 06:54:30 +00:00
void set_extruder_column_hidden ( bool hide )
{
m_objects_ctrl - > GetColumn ( 3 ) - > SetHidden ( hide ) ;
}
2018-07-27 10:26:14 +00:00
void update_extruder_in_config ( const wxString & selection )
{
2018-08-14 14:16:26 +00:00
if ( ! m_config | | selection . empty ( ) )
2018-07-27 10:26:14 +00:00
return ;
int extruder = selection . size ( ) > 1 ? 0 : atoi ( selection . c_str ( ) ) ;
( * m_config ) - > set_key_value ( " extruder " , new ConfigOptionInt ( extruder ) ) ;
if ( m_event_update_scene > 0 ) {
wxCommandEvent e ( m_event_update_scene ) ;
get_main_frame ( ) - > ProcessWindowEvent ( e ) ;
}
}
2018-07-29 10:19:08 +00:00
void update_scale_values ( )
{
update_scale_values ( ( * m_objects ) [ m_selected_object_id ] - > instance_bounding_box ( 0 ) . size ( ) ,
( * m_objects ) [ m_selected_object_id ] - > instances [ 0 ] - > scaling_factor ) ;
}
void update_scale_values ( const Pointf3 & size , float scaling_factor )
{
auto og = get_optgroup ( ogFrequentlyObjectSettings ) ;
if ( g_is_percent_scale ) {
auto scale = scaling_factor * 100 ;
og - > set_value ( " scale_x " , int ( scale ) ) ;
og - > set_value ( " scale_y " , int ( scale ) ) ;
og - > set_value ( " scale_z " , int ( scale ) ) ;
}
else {
og - > set_value ( " scale_x " , int ( size . x + 0.5 ) ) ;
og - > set_value ( " scale_y " , int ( size . y + 0.5 ) ) ;
og - > set_value ( " scale_z " , int ( size . z + 0.5 ) ) ;
}
}
2018-07-30 08:48:40 +00:00
void update_rotation_values ( )
2018-07-29 10:19:08 +00:00
{
2018-07-30 08:48:40 +00:00
auto og = get_optgroup ( ogFrequentlyObjectSettings ) ;
og - > set_value ( " rotation_x " , 0 ) ;
og - > set_value ( " rotation_y " , 0 ) ;
auto rotation_z = ( * m_objects ) [ m_selected_object_id ] - > instances [ 0 ] - > rotation ;
auto deg = int ( Geometry : : rad2deg ( rotation_z ) ) ;
if ( deg > 180 ) deg - = 360 ;
og - > set_value ( " rotation_z " , deg ) ;
2018-07-29 10:19:08 +00:00
}
void update_rotation_value ( const double angle , const std : : string & axis )
{
auto og = get_optgroup ( ogFrequentlyObjectSettings ) ;
int deg = int ( Geometry : : rad2deg ( angle ) ) ;
if ( deg > 180 ) deg - = 360 ;
og - > set_value ( " rotation_ " + axis , deg ) ;
}
2018-08-13 08:30:36 +00:00
void on_begin_drag ( wxDataViewEvent & event )
{
wxDataViewItem item ( event . GetItem ( ) ) ;
// only allow drags for item, not containers
2018-08-13 12:15:43 +00:00
if ( m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) ) {
2018-08-13 08:30:36 +00:00
event . Veto ( ) ;
return ;
}
2018-08-14 11:04:11 +00:00
/* Under MSW or OSX, DnD moves an item to the place of another selected item
* But under GTK , DnD moves an item between another two items .
* And as a result - call EVT_CHANGE_SELECTION to unselect all items .
* To prevent such behavior use g_prevent_list_events
* */
g_prevent_list_events = true ; //it's needed for GTK
2018-08-13 08:30:36 +00:00
wxTextDataObject * obj = new wxTextDataObject ;
2018-08-13 12:15:43 +00:00
obj - > SetText ( wxString : : Format ( " %d " , m_objects_model - > GetVolumeIdByItem ( item ) ) ) ;
2018-08-13 08:30:36 +00:00
event . SetDataObject ( obj ) ;
2018-08-13 12:15:43 +00:00
event . SetDragFlags ( /*wxDrag_AllowMove*/ wxDrag_DefaultMove ) ; // allows both copy and move;
2018-08-13 08:30:36 +00:00
}
void on_drop_possible ( wxDataViewEvent & event )
{
wxDataViewItem item ( event . GetItem ( ) ) ;
// only allow drags for item or background, not containers
2018-08-13 12:15:43 +00:00
if ( item . IsOk ( ) & & m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) | |
event . GetDataFormat ( ) ! = wxDF_UNICODETEXT )
2018-08-13 08:30:36 +00:00
event . Veto ( ) ;
}
void on_drop ( wxDataViewEvent & event )
{
wxDataViewItem item ( event . GetItem ( ) ) ;
// only allow drops for item, not containers
2018-08-13 12:15:43 +00:00
if ( item . IsOk ( ) & & m_objects_model - > GetParent ( item ) = = wxDataViewItem ( 0 ) | |
event . GetDataFormat ( ) ! = wxDF_UNICODETEXT ) {
2018-08-13 08:30:36 +00:00
event . Veto ( ) ;
return ;
2018-08-13 12:15:43 +00:00
}
2018-08-13 08:30:36 +00:00
wxTextDataObject obj ;
obj . SetData ( wxDF_UNICODETEXT , event . GetDataSize ( ) , event . GetDataBuffer ( ) ) ;
2018-08-13 12:15:43 +00:00
int from_volume_id = std : : stoi ( obj . GetText ( ) . ToStdString ( ) ) ;
int to_volume_id = m_objects_model - > GetVolumeIdByItem ( item ) ;
2018-08-14 11:04:11 +00:00
# ifdef __WXGTK__
/* Under GTK, DnD moves an item between another two items.
* And event . GetItem ( ) return item , which is under " insertion line "
* So , if we move item down we should to decrease the to_volume_id value
* */
if ( to_volume_id > from_volume_id ) to_volume_id - - ;
# endif // __WXGTK__
2018-08-13 12:15:43 +00:00
m_objects_ctrl - > Select ( m_objects_model - > ReorganizeChildren ( from_volume_id , to_volume_id ,
m_objects_model - > GetParent ( item ) ) ) ;
auto & volumes = ( * m_objects ) [ m_selected_object_id ] - > volumes ;
auto delta = to_volume_id < from_volume_id ? - 1 : 1 ;
int cnt = 0 ;
for ( int id = from_volume_id ; cnt < abs ( from_volume_id - to_volume_id ) ; id + = delta , cnt + + )
std : : swap ( volumes [ id ] , volumes [ id + delta ] ) ;
2018-08-14 11:04:11 +00:00
g_prevent_list_events = false ;
2018-08-13 08:30:36 +00:00
}
2018-08-15 09:18:20 +00:00
void update_objects_list_extruder_column ( const int extruders_count )
{
// delete old 3rd column
2018-08-15 10:47:46 +00:00
m_objects_ctrl - > DeleteColumn ( m_objects_ctrl - > GetColumn ( 3 ) ) ;
2018-08-15 09:18:20 +00:00
// insert new created 3rd column
m_objects_ctrl - > InsertColumn ( 3 , object_ctrl_create_extruder_column ( extruders_count ) ) ;
// set show/hide for this column
set_extruder_column_hidden ( extruders_count < = 1 ) ;
}
2018-06-13 14:39:33 +00:00
} //namespace GUI
} //namespace Slic3r