From ddda5062c2647040a42d153014700eeaefa3285e Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 27 Jul 2018 12:08:33 +0200 Subject: [PATCH] 3D scene toolbar actions --- lib/Slic3r/GUI/Plater.pm | 110 +++++++++++++++- xs/src/slic3r/GUI/3DScene.cpp | 72 ++++++++++ xs/src/slic3r/GUI/3DScene.hpp | 17 +++ xs/src/slic3r/GUI/GLCanvas3D.cpp | 168 +++++++++++++++++++++++- xs/src/slic3r/GUI/GLCanvas3D.hpp | 36 +++++ xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 99 ++++++++++++++ xs/src/slic3r/GUI/GLCanvas3DManager.hpp | 17 +++ xs/src/slic3r/GUI/GLToolbar.cpp | 128 ++++++++++++++++-- xs/src/slic3r/GUI/GLToolbar.hpp | 20 ++- xs/xsp/GUI_3DScene.xsp | 102 +++++++++++++- 10 files changed, 749 insertions(+), 20 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 9e070f66b..fbe9dc3b0 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -159,7 +159,63 @@ sub new { } } }; + +#====================================================================================================================================================== + # callbacks for toolbar + my $on_action_add = sub { + $self->add; + }; + + my $on_action_delete = sub { + $self->remove(); + }; + + my $on_action_deleteall = sub { + $self->reset; + }; + + my $on_action_arrange = sub { + $self->arrange; + }; + + my $on_action_more = sub { + $self->increase; + }; + + my $on_action_fewer = sub { + $self->decrease; + }; + + my $on_action_ccw45 = sub { + $self->rotate(45, Z, 'relative'); + }; + + my $on_action_cw45 = sub { + $self->rotate(-45, Z, 'relative'); + }; + + my $on_action_scale = sub { + $self->changescale(undef); + }; + + my $on_action_split = sub { + $self->split_object; + }; + my $on_action_cut = sub { + $self->object_cut_dialog; + }; + + my $on_action_settings = sub { + $self->object_settings_dialog; + }; + + my $on_action_layersediting = sub { + my $state = Slic3r::GUI::_3DScene::is_toolbar_item_pressed($self->{canvas3D}, "layersediting"); + $self->on_layer_editing_toggled($state); + }; +#====================================================================================================================================================== + # Initialize 3D plater if ($Slic3r::GUI::have_OpenGL) { $self->{canvas3D} = Slic3r::GUI::Plater::3D->new($self->{preview_notebook}, $self->{objects}, $self->{model}, $self->{print}, $self->{config}); @@ -179,6 +235,21 @@ sub new { Slic3r::GUI::_3DScene::register_on_gizmo_scale_uniformly_callback($self->{canvas3D}, $on_gizmo_scale_uniformly); Slic3r::GUI::_3DScene::register_on_gizmo_rotate_callback($self->{canvas3D}, $on_gizmo_rotate); Slic3r::GUI::_3DScene::register_on_update_geometry_info_callback($self->{canvas3D}, $on_update_geometry_info); +#====================================================================================================================================================== + Slic3r::GUI::_3DScene::register_action_add_callback($self->{canvas3D}, $on_action_add); + Slic3r::GUI::_3DScene::register_action_delete_callback($self->{canvas3D}, $on_action_delete); + Slic3r::GUI::_3DScene::register_action_deleteall_callback($self->{canvas3D}, $on_action_deleteall); + Slic3r::GUI::_3DScene::register_action_arrange_callback($self->{canvas3D}, $on_action_arrange); + Slic3r::GUI::_3DScene::register_action_more_callback($self->{canvas3D}, $on_action_more); + Slic3r::GUI::_3DScene::register_action_fewer_callback($self->{canvas3D}, $on_action_fewer); + Slic3r::GUI::_3DScene::register_action_ccw45_callback($self->{canvas3D}, $on_action_ccw45); + Slic3r::GUI::_3DScene::register_action_cw45_callback($self->{canvas3D}, $on_action_cw45); + Slic3r::GUI::_3DScene::register_action_scale_callback($self->{canvas3D}, $on_action_scale); + Slic3r::GUI::_3DScene::register_action_split_callback($self->{canvas3D}, $on_action_split); + Slic3r::GUI::_3DScene::register_action_cut_callback($self->{canvas3D}, $on_action_cut); + Slic3r::GUI::_3DScene::register_action_settings_callback($self->{canvas3D}, $on_action_settings); + Slic3r::GUI::_3DScene::register_action_layersediting_callback($self->{canvas3D}, $on_action_layersediting); +#====================================================================================================================================================== Slic3r::GUI::_3DScene::enable_gizmos($self->{canvas3D}, 1); #====================================================================================================================================================== Slic3r::GUI::_3DScene::enable_toolbar($self->{canvas3D}, 1); @@ -2098,25 +2169,32 @@ sub object_list_changed { # Enable/disable buttons depending on whether there are any objects on the platter. my $have_objects = @{$self->{objects}} ? 1 : 0; - my $variable_layer_height_allowed = $self->{config}->variable_layer_height && Slic3r::GUI::_3DScene::is_layers_editing_allowed($self->{canvas3D}); +#=================================================================================================================================================== +# my $variable_layer_height_allowed = $self->{config}->variable_layer_height && Slic3r::GUI::_3DScene::is_layers_editing_allowed($self->{canvas3D}); +#=================================================================================================================================================== if ($self->{htoolbar}) { # On OSX or Linux $self->{htoolbar}->EnableTool($_, $have_objects) - for (TB_RESET, TB_ARRANGE, TB_LAYER_EDITING); - $self->{htoolbar}->EnableTool(TB_LAYER_EDITING, 0) if (! $variable_layer_height_allowed); +#=================================================================================================================================================== + for (TB_RESET, TB_ARRANGE); +# for (TB_RESET, TB_ARRANGE, TB_LAYER_EDITING); +# $self->{htoolbar}->EnableTool(TB_LAYER_EDITING, 0) if (! $variable_layer_height_allowed); +#=================================================================================================================================================== } else { # On MSW my $method = $have_objects ? 'Enable' : 'Disable'; $self->{"btn_$_"}->$method - for grep $self->{"btn_$_"}, qw(reset arrange reslice export_gcode export_stl print send_gcode layer_editing); - $self->{"btn_layer_editing"}->Disable if (! $variable_layer_height_allowed); +#=================================================================================================================================================== + for grep $self->{"btn_$_"}, qw(reset arrange reslice export_gcode export_stl print send_gcode); +# for grep $self->{"btn_$_"}, qw(reset arrange reslice export_gcode export_stl print send_gcode layer_editing); +# $self->{"btn_layer_editing"}->Disable if (! $variable_layer_height_allowed); +#=================================================================================================================================================== } #=================================================================================================================================================== - for my $toolbar_item (qw(deleteall arrange layersediting)) { + for my $toolbar_item (qw(deleteall arrange)) { Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, $toolbar_item, $have_objects); } - Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "layersediting", 0) if (! $variable_layer_height_allowed); #=================================================================================================================================================== my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file}; @@ -2132,23 +2210,41 @@ sub selection_changed { my ($self) = @_; my ($obj_idx, $object) = $self->selected_object; my $have_sel = defined $obj_idx; +#=================================================================================================================================================== + my $layers_height_allowed = $self->{config}->variable_layer_height && Slic3r::GUI::_3DScene::is_layers_editing_allowed($self->{canvas3D}) && $have_sel; +#=================================================================================================================================================== $self->{right_panel}->Freeze; if ($self->{htoolbar}) { # On OSX or Linux $self->{htoolbar}->EnableTool($_, $have_sel) for (TB_REMOVE, TB_MORE, TB_FEWER, TB_45CW, TB_45CCW, TB_SCALE, TB_SPLIT, TB_CUT, TB_SETTINGS); + +#=================================================================================================================================================== + $self->{htoolbar}->EnableTool(TB_LAYER_EDITING, $layers_height_allowed); +#=================================================================================================================================================== + } else { # On MSW my $method = $have_sel ? 'Enable' : 'Disable'; $self->{"btn_$_"}->$method for grep $self->{"btn_$_"}, qw(remove increase decrease rotate45cw rotate45ccw changescale split cut settings); + +#=================================================================================================================================================== + if ($layers_height_allowed) { + $self->{"btn_layer_editing"}->Enable; + } else { + $self->{"btn_layer_editing"}->Disable; + } +#=================================================================================================================================================== } #=================================================================================================================================================== for my $toolbar_item (qw(delete more fewer ccw45 cw45 scale split cut settings)) { Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, $toolbar_item, $have_sel); } + + Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "layersediting", $layers_height_allowed); #=================================================================================================================================================== if ($self->{object_info_size}) { # have we already loaded the info pane? diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index c00a9a08e..78a44f1f0 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -1803,6 +1803,11 @@ void _3DScene::enable_toolbar_item(wxGLCanvas* canvas, const std::string& name, { s_canvas_mgr.enable_toolbar_item(canvas, name, enable); } + +bool _3DScene::is_toolbar_item_pressed(wxGLCanvas* canvas, const std::string& name) +{ + return s_canvas_mgr.is_toolbar_item_pressed(canvas, name); +} //################################################################################################################################### void _3DScene::zoom_to_bed(wxGLCanvas* canvas) @@ -1940,6 +1945,73 @@ void _3DScene::register_on_update_geometry_info_callback(wxGLCanvas* canvas, voi s_canvas_mgr.register_on_update_geometry_info_callback(canvas, callback); } +//################################################################################################################################### +void _3DScene::register_action_add_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_add_callback(canvas, callback); +} + +void _3DScene::register_action_delete_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_delete_callback(canvas, callback); +} + +void _3DScene::register_action_deleteall_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_deleteall_callback(canvas, callback); +} + +void _3DScene::register_action_arrange_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_arrange_callback(canvas, callback); +} + +void _3DScene::register_action_more_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_more_callback(canvas, callback); +} + +void _3DScene::register_action_fewer_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_fewer_callback(canvas, callback); +} + +void _3DScene::register_action_ccw45_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_ccw45_callback(canvas, callback); +} + +void _3DScene::register_action_cw45_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_cw45_callback(canvas, callback); +} + +void _3DScene::register_action_scale_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_scale_callback(canvas, callback); +} + +void _3DScene::register_action_split_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_split_callback(canvas, callback); +} + +void _3DScene::register_action_cut_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_cut_callback(canvas, callback); +} + +void _3DScene::register_action_settings_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_settings_callback(canvas, callback); +} + +void _3DScene::register_action_layersediting_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_layersediting_callback(canvas, callback); +} +//################################################################################################################################### + static inline int hex_digit_to_int(const char c) { return diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 9028a1760..cb53b48ba 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -504,6 +504,7 @@ public: //################################################################################################################################### static void enable_toolbar_item(wxGLCanvas* canvas, const std::string& name, bool enable); + static bool is_toolbar_item_pressed(wxGLCanvas* canvas, const std::string& name); //################################################################################################################################### static void zoom_to_bed(wxGLCanvas* canvas); @@ -538,6 +539,22 @@ public: static void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback); static void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback); +//################################################################################################################################### + static void register_action_add_callback(wxGLCanvas* canvas, void* callback); + static void register_action_delete_callback(wxGLCanvas* canvas, void* callback); + static void register_action_deleteall_callback(wxGLCanvas* canvas, void* callback); + static void register_action_arrange_callback(wxGLCanvas* canvas, void* callback); + static void register_action_more_callback(wxGLCanvas* canvas, void* callback); + static void register_action_fewer_callback(wxGLCanvas* canvas, void* callback); + static void register_action_ccw45_callback(wxGLCanvas* canvas, void* callback); + static void register_action_cw45_callback(wxGLCanvas* canvas, void* callback); + static void register_action_scale_callback(wxGLCanvas* canvas, void* callback); + static void register_action_split_callback(wxGLCanvas* canvas, void* callback); + static void register_action_cut_callback(wxGLCanvas* canvas, void* callback); + static void register_action_settings_callback(wxGLCanvas* canvas, void* callback); + static void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback); +//################################################################################################################################### + static std::vector load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector instance_idxs); static std::vector load_object(wxGLCanvas* canvas, const Model* model, int obj_idx); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 07020bdb7..e1657fd74 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1698,6 +1698,9 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) , m_force_zoom_to_bed_enabled(false) , m_apply_zoom_to_volumes_filter(false) , m_hover_volume_id(-1) +//################################################################################################################################### + , m_toolbar_action_running(false) +//################################################################################################################################### , m_warning_texture_enabled(false) , m_legend_texture_enabled(false) , m_picking_enabled(false) @@ -2090,6 +2093,11 @@ void GLCanvas3D::enable_toolbar_item(const std::string& name, bool enable) else m_toolbar.disable_item(name); } + +bool GLCanvas3D::is_toolbar_item_pressed(const std::string& name) const +{ + return m_toolbar.is_item_pressed(name); +} //################################################################################################################################### void GLCanvas3D::zoom_to_bed() @@ -2862,6 +2870,86 @@ void GLCanvas3D::register_on_update_geometry_info_callback(void* callback) m_on_update_geometry_info_callback.register_callback(callback); } +//################################################################################################################################### +void GLCanvas3D::register_action_add_callback(void* callback) +{ + if (callback != nullptr) + m_action_add_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_delete_callback(void* callback) +{ + if (callback != nullptr) + m_action_delete_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_deleteall_callback(void* callback) +{ + if (callback != nullptr) + m_action_deleteall_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_arrange_callback(void* callback) +{ + if (callback != nullptr) + m_action_arrange_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_more_callback(void* callback) +{ + if (callback != nullptr) + m_action_more_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_fewer_callback(void* callback) +{ + if (callback != nullptr) + m_action_fewer_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_ccw45_callback(void* callback) +{ + if (callback != nullptr) + m_action_ccw45_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_cw45_callback(void* callback) +{ + if (callback != nullptr) + m_action_cw45_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_scale_callback(void* callback) +{ + if (callback != nullptr) + m_action_scale_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_split_callback(void* callback) +{ + if (callback != nullptr) + m_action_split_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_cut_callback(void* callback) +{ + if (callback != nullptr) + m_action_cut_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_settings_callback(void* callback) +{ + if (callback != nullptr) + m_action_settings_callback.register_callback(callback); +} + +void GLCanvas3D::register_action_layersediting_callback(void* callback) +{ + if (callback != nullptr) + m_action_layersediting_callback.register_callback(callback); +} +//################################################################################################################################### + void GLCanvas3D::bind_event_handlers() { if (m_canvas != nullptr) @@ -3039,6 +3127,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; m_layers_editing.last_object_id = layer_editing_object_idx; bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position); +//################################################################################################################################### + int toolbar_contains_mouse = m_toolbar.contains_mouse(*this, m_mouse.position); +//################################################################################################################################### if (evt.Entering()) { @@ -3052,6 +3143,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } else if (evt.LeftDClick() && (m_hover_volume_id != -1)) m_on_double_click_callback.call(); +//################################################################################################################################### + else if (evt.LeftDClick() && (toolbar_contains_mouse != -1)) + { + m_toolbar_action_running = true; + m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this); + } +//################################################################################################################################### else if (evt.LeftDown() || evt.RightDown()) { // If user pressed left or right button we first check whether this happened @@ -3090,6 +3188,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(); m_dirty = true; } +//################################################################################################################################### + else if (toolbar_contains_mouse != -1) + { + m_toolbar_action_running = true; + m_toolbar.do_action((unsigned int)toolbar_contains_mouse, *this); + } +//################################################################################################################################### else { // Select volume in this 3D canvas. @@ -3346,7 +3451,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if (!m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled()) { // deselect and propagate event through callback - if (m_picking_enabled) +//################################################################################################################################### + if (m_picking_enabled && !m_toolbar_action_running) +// if (m_picking_enabled) +//################################################################################################################################### { deselect_volumes(); _on_select(-1); @@ -3378,6 +3486,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.set_start_position_3D_as_invalid(); m_mouse.set_start_position_2D_as_invalid(); m_mouse.dragging = false; +//################################################################################################################################### + m_toolbar_action_running = false; +//################################################################################################################################### m_dirty = true; } else if (evt.Moving()) @@ -3467,36 +3578,48 @@ bool GLCanvas3D::_init_toolbar() item.name = "add"; item.tooltip = GUI::L_str("Add..."); + item.is_toggable = false; + item.action_callback = &m_action_add_callback; item.textures[GLToolbarItem::Normal] = "brick_add_normal_36.png"; item.textures[GLToolbarItem::Hover] = "brick_add_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "brick_add_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "brick_add_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "brick_add_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "delete"; item.tooltip = GUI::L_str("Delete"); + item.is_toggable = false; + item.action_callback = &m_action_delete_callback; item.textures[GLToolbarItem::Normal] = "brick_delete_normal_36.png"; item.textures[GLToolbarItem::Hover] = "brick_delete_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "brick_delete_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "brick_delete_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "brick_delete_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "deleteall"; item.tooltip = GUI::L_str("Delete all"); + item.is_toggable = false; + item.action_callback = &m_action_deleteall_callback; item.textures[GLToolbarItem::Normal] = "cross_normal_36.png"; item.textures[GLToolbarItem::Hover] = "cross_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "cross_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "cross_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "cross_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "arrange"; item.tooltip = GUI::L_str("Arrange"); + item.is_toggable = false; + item.action_callback = &m_action_arrange_callback; item.textures[GLToolbarItem::Normal] = "bricks_normal_36.png"; item.textures[GLToolbarItem::Hover] = "bricks_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "bricks_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "bricks_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "bricks_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3506,18 +3629,24 @@ bool GLCanvas3D::_init_toolbar() item.name = "more"; item.tooltip = GUI::L_str("Add instance"); + item.is_toggable = false; + item.action_callback = &m_action_more_callback; item.textures[GLToolbarItem::Normal] = "add_normal_36.png"; item.textures[GLToolbarItem::Hover] = "add_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "add_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "add_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "add_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "fewer"; item.tooltip = GUI::L_str("Remove instance"); + item.is_toggable = false; + item.action_callback = &m_action_fewer_callback; item.textures[GLToolbarItem::Normal] = "delete_normal_36.png"; item.textures[GLToolbarItem::Hover] = "delete_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "delete_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "delete_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "delete_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3527,45 +3656,60 @@ bool GLCanvas3D::_init_toolbar() item.name = "ccw45"; item.tooltip = GUI::L_str("Rotate CCW 45 degrees"); + item.is_toggable = false; + item.action_callback = &m_action_ccw45_callback; item.textures[GLToolbarItem::Normal] = "arrow_rotate_anticlockwise_normal_36.png"; item.textures[GLToolbarItem::Hover] = "arrow_rotate_anticlockwise_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "arrow_rotate_anticlockwise_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "arrow_rotate_anticlockwise_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "arrow_rotate_anticlockwise_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "cw45"; item.tooltip = GUI::L_str("Rotate CW 45 degrees"); + item.is_toggable = false; + item.action_callback = &m_action_cw45_callback; item.textures[GLToolbarItem::Normal] = "arrow_rotate_clockwise_normal_36.png"; item.textures[GLToolbarItem::Hover] = "arrow_rotate_clockwise_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "arrow_rotate_clockwise_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "arrow_rotate_clockwise_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "arrow_rotate_clockwise_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "scale"; item.tooltip = GUI::L_str("Scale..."); + item.is_toggable = false; + item.action_callback = &m_action_scale_callback; item.textures[GLToolbarItem::Normal] = "arrow_out_normal_36.png"; item.textures[GLToolbarItem::Hover] = "arrow_out_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "arrow_out_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "arrow_out_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "arrow_out_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "split"; item.tooltip = GUI::L_str("Split"); + item.is_toggable = false; + item.action_callback = &m_action_split_callback; item.textures[GLToolbarItem::Normal] = "shape_ungroup_normal_36.png"; item.textures[GLToolbarItem::Hover] = "shape_ungroup_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "shape_ungroup_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "shape_ungroup_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "shape_ungroup_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "cut"; item.tooltip = GUI::L_str("Cut..."); + item.is_toggable = false; + item.action_callback = &m_action_cut_callback; item.textures[GLToolbarItem::Normal] = "package_normal_36.png"; item.textures[GLToolbarItem::Hover] = "package_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "package_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "package_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "package_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3575,18 +3719,24 @@ bool GLCanvas3D::_init_toolbar() item.name = "settings"; item.tooltip = GUI::L_str("Settings..."); + item.is_toggable = false; + item.action_callback = &m_action_settings_callback; item.textures[GLToolbarItem::Normal] = "cog_normal_36.png"; item.textures[GLToolbarItem::Hover] = "cog_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "cog_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "cog_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "cog_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; item.name = "layersediting"; item.tooltip = GUI::L_str("Layers editing"); + item.is_toggable = true; + item.action_callback = &m_action_layersediting_callback; item.textures[GLToolbarItem::Normal] = "variable_layer_height_normal_36.png"; item.textures[GLToolbarItem::Hover] = "variable_layer_height_hover_36.png"; item.textures[GLToolbarItem::Pressed] = "variable_layer_height_pressed_36.png"; + item.textures[GLToolbarItem::HoverPressed] = "variable_layer_height_hover_pressed_36.png"; item.textures[GLToolbarItem::Disabled] = "variable_layer_height_disabled_36.png"; if (!m_toolbar.add_item(item)) return false; @@ -3786,6 +3936,22 @@ void GLCanvas3D::_deregister_callbacks() m_on_gizmo_scale_uniformly_callback.deregister_callback(); m_on_gizmo_rotate_callback.deregister_callback(); m_on_update_geometry_info_callback.deregister_callback(); + +//################################################################################################################################### + m_action_add_callback.deregister_callback(); + m_action_delete_callback.deregister_callback(); + m_action_deleteall_callback.deregister_callback(); + m_action_arrange_callback.deregister_callback(); + m_action_more_callback.deregister_callback(); + m_action_fewer_callback.deregister_callback(); + m_action_ccw45_callback.deregister_callback(); + m_action_cw45_callback.deregister_callback(); + m_action_scale_callback.deregister_callback(); + m_action_split_callback.deregister_callback(); + m_action_cut_callback.deregister_callback(); + m_action_settings_callback.deregister_callback(); + m_action_layersediting_callback.deregister_callback(); +//################################################################################################################################### } void GLCanvas3D::_mark_volumes_for_layer_height() const diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 24b848d6c..a35538969 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -450,6 +450,9 @@ private: bool m_force_zoom_to_bed_enabled; bool m_apply_zoom_to_volumes_filter; mutable int m_hover_volume_id; +//################################################################################################################################### + bool m_toolbar_action_running; +//################################################################################################################################### bool m_warning_texture_enabled; bool m_legend_texture_enabled; bool m_picking_enabled; @@ -486,6 +489,22 @@ private: PerlCallback m_on_gizmo_rotate_callback; PerlCallback m_on_update_geometry_info_callback; +//################################################################################################################################### + PerlCallback m_action_add_callback; + PerlCallback m_action_delete_callback; + PerlCallback m_action_deleteall_callback; + PerlCallback m_action_arrange_callback; + PerlCallback m_action_more_callback; + PerlCallback m_action_fewer_callback; + PerlCallback m_action_ccw45_callback; + PerlCallback m_action_cw45_callback; + PerlCallback m_action_scale_callback; + PerlCallback m_action_split_callback; + PerlCallback m_action_cut_callback; + PerlCallback m_action_settings_callback; + PerlCallback m_action_layersediting_callback; +//################################################################################################################################### + public: GLCanvas3D(wxGLCanvas* canvas); ~GLCanvas3D(); @@ -552,6 +571,7 @@ public: //################################################################################################################################### void enable_toolbar_item(const std::string& name, bool enable); + bool is_toolbar_item_pressed(const std::string& name) const; //################################################################################################################################### void zoom_to_bed(); @@ -602,6 +622,22 @@ public: void register_on_gizmo_rotate_callback(void* callback); void register_on_update_geometry_info_callback(void* callback); +//################################################################################################################################### + void register_action_add_callback(void* callback); + void register_action_delete_callback(void* callback); + void register_action_deleteall_callback(void* callback); + void register_action_arrange_callback(void* callback); + void register_action_more_callback(void* callback); + void register_action_fewer_callback(void* callback); + void register_action_ccw45_callback(void* callback); + void register_action_cw45_callback(void* callback); + void register_action_scale_callback(void* callback); + void register_action_split_callback(void* callback); + void register_action_cut_callback(void* callback); + void register_action_settings_callback(void* callback); + void register_action_layersediting_callback(void* callback); +//################################################################################################################################### + void bind_event_handlers(); void unbind_event_handlers(); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index 75cf78bdc..f9b10e1d7 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -441,6 +441,12 @@ void GLCanvas3DManager::enable_toolbar_item(wxGLCanvas* canvas, const std::strin if (it != m_canvases.end()) it->second->enable_toolbar_item(name, enable); } + +bool GLCanvas3DManager::is_toolbar_item_pressed(wxGLCanvas* canvas, const std::string& name) const +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->is_toolbar_item_pressed(name) : false; +} //################################################################################################################################### void GLCanvas3DManager::zoom_to_bed(wxGLCanvas* canvas) @@ -703,6 +709,99 @@ void GLCanvas3DManager::register_on_update_geometry_info_callback(wxGLCanvas* ca it->second->register_on_update_geometry_info_callback(callback); } +//################################################################################################################################### +void GLCanvas3DManager::register_action_add_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_add_callback(callback); +} + +void GLCanvas3DManager::register_action_delete_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_delete_callback(callback); +} + +void GLCanvas3DManager::register_action_deleteall_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_deleteall_callback(callback); +} + +void GLCanvas3DManager::register_action_arrange_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_arrange_callback(callback); +} + +void GLCanvas3DManager::register_action_more_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_more_callback(callback); +} + +void GLCanvas3DManager::register_action_fewer_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_fewer_callback(callback); +} + +void GLCanvas3DManager::register_action_ccw45_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_ccw45_callback(callback); +} + +void GLCanvas3DManager::register_action_cw45_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_cw45_callback(callback); +} + +void GLCanvas3DManager::register_action_scale_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_scale_callback(callback); +} + +void GLCanvas3DManager::register_action_split_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_split_callback(callback); +} + +void GLCanvas3DManager::register_action_cut_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_cut_callback(callback); +} + +void GLCanvas3DManager::register_action_settings_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_settings_callback(callback); +} + +void GLCanvas3DManager::register_action_layersediting_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_layersediting_callback(callback); +} +//################################################################################################################################### + GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) { return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp index ace6515d2..b4deb72b6 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -119,6 +119,7 @@ public: //################################################################################################################################### void enable_toolbar_item(wxGLCanvas* canvas, const std::string& name, bool enable); + bool is_toolbar_item_pressed(wxGLCanvas* canvas, const std::string& name) const; //################################################################################################################################### void zoom_to_bed(wxGLCanvas* canvas); @@ -165,6 +166,22 @@ public: void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback); void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback); +//################################################################################################################################### + void register_action_add_callback(wxGLCanvas* canvas, void* callback); + void register_action_delete_callback(wxGLCanvas* canvas, void* callback); + void register_action_deleteall_callback(wxGLCanvas* canvas, void* callback); + void register_action_arrange_callback(wxGLCanvas* canvas, void* callback); + void register_action_more_callback(wxGLCanvas* canvas, void* callback); + void register_action_fewer_callback(wxGLCanvas* canvas, void* callback); + void register_action_ccw45_callback(wxGLCanvas* canvas, void* callback); + void register_action_cw45_callback(wxGLCanvas* canvas, void* callback); + void register_action_scale_callback(wxGLCanvas* canvas, void* callback); + void register_action_split_callback(wxGLCanvas* canvas, void* callback); + void register_action_cut_callback(wxGLCanvas* canvas, void* callback); + void register_action_settings_callback(wxGLCanvas* canvas, void* callback); + void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback); +//################################################################################################################################### + private: CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); CanvasesMap::const_iterator _get_canvas(wxGLCanvas* canvas) const; diff --git a/xs/src/slic3r/GUI/GLToolbar.cpp b/xs/src/slic3r/GUI/GLToolbar.cpp index fe861a45d..e6e9eeac8 100644 --- a/xs/src/slic3r/GUI/GLToolbar.cpp +++ b/xs/src/slic3r/GUI/GLToolbar.cpp @@ -1,6 +1,5 @@ #include "GLToolbar.hpp" -#include "../../libslic3r/Utils.hpp" #include "../../slic3r/GUI/GLCanvas3D.hpp" #include @@ -12,11 +11,13 @@ namespace Slic3r { namespace GUI { -GLToolbarItem::GLToolbarItem(EType type, const std::string& name, const std::string& tooltip) + GLToolbarItem::GLToolbarItem(EType type, const std::string& name, const std::string& tooltip, bool is_toggable, PerlCallback* action_callback) : m_type(type) , m_state(Disabled) , m_name(name) , m_tooltip(tooltip) + , m_is_toggable(is_toggable) + , m_action_callback(action_callback) { } @@ -29,9 +30,12 @@ bool GLToolbarItem::load_textures(const std::string* filenames) for (unsigned int i = (unsigned int)Normal; i < (unsigned int)Num_States; ++i) { - std::string filename = path + filenames[i]; - if (!m_icon_textures[i].load_from_file(filename, false)) - return false; + if (!filenames[i].empty()) + { + std::string filename = path + filenames[i]; + if (!m_icon_textures[i].load_from_file(filename, false)) + return false; + } } return true; @@ -67,6 +71,22 @@ int GLToolbarItem::get_icon_textures_size() const return m_icon_textures[Normal].get_width(); } +void GLToolbarItem::do_action() +{ + if (m_action_callback != nullptr) + m_action_callback->call(); +} + +bool GLToolbarItem::is_enabled() const +{ + return m_state != Disabled; +} + +bool GLToolbarItem::is_toggable() const +{ + return m_is_toggable; +} + bool GLToolbarItem::is_separator() const { return m_type == Separator; @@ -113,7 +133,7 @@ void GLToolbar::set_separator_x(float separator) bool GLToolbar::add_item(const GLToolbar::ItemCreationData& data) { - GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Action, data.name, data.tooltip); + GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Action, data.name, data.tooltip, data.is_toggable, data.action_callback); if ((item == nullptr) || !item->load_textures(data.textures)) return false; @@ -124,7 +144,7 @@ bool GLToolbar::add_item(const GLToolbar::ItemCreationData& data) bool GLToolbar::add_separator() { - GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Separator, "", ""); + GLToolbarItem* item = new GLToolbarItem(GLToolbarItem::Separator, "", "", false, nullptr); if (item == nullptr) return false; @@ -156,6 +176,17 @@ void GLToolbar::disable_item(const std::string& name) } } +bool GLToolbar::is_item_pressed(const std::string& name) const +{ + for (GLToolbarItem* item : m_items) + { + if (item->get_name() == name) + return (item->get_state() == GLToolbarItem::Pressed) || (item->get_state() == GLToolbarItem::HoverPressed); + } + + return false; +} + void GLToolbar::update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos) { if (!m_enabled) @@ -201,8 +232,17 @@ void GLToolbar::update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos) } case GLToolbarItem::Pressed: { - if (!inside) - item->set_state(GLToolbarItem::Normal); + if (inside) + item->set_state(GLToolbarItem::HoverPressed); + + break; + } + case GLToolbarItem::HoverPressed: + { + if (inside) + tooltip = item->get_tooltip(); + else + item->set_state(GLToolbarItem::Pressed); break; } @@ -219,9 +259,77 @@ void GLToolbar::update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos) canvas.set_tooltip(tooltip); } +int GLToolbar::contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const +{ + if (!m_enabled) + return -1; + + float cnv_w = (float)canvas.get_canvas_size().get_width(); + float width = _get_total_width(); + float left = 0.5f * (cnv_w - width); + float top = m_offset_y; + + int id = -1; + + for (GLToolbarItem* item : m_items) + { + ++id; + + if (item->is_separator()) + left += (m_separator_x + m_gap_x); + else + { + float tex_size = (float)item->get_icon_textures_size() * m_textures_scale; + float right = left + tex_size; + float bottom = top + tex_size; + + if ((left <= mouse_pos.x) && (mouse_pos.x <= right) && (top <= mouse_pos.y) && (mouse_pos.y <= bottom)) + return id; + + left += (tex_size + m_gap_x); + } + } + + return -1; +} + +void GLToolbar::do_action(unsigned int item_id, GLCanvas3D& canvas) +{ + if (item_id < (unsigned int)m_items.size()) + { + GLToolbarItem* item = m_items[item_id]; + if ((item != nullptr) && !item->is_separator() && item->is_enabled()) + { + if (item->is_toggable()) + { + GLToolbarItem::EState state = item->get_state(); + if (state == GLToolbarItem::Hover) + item->set_state(GLToolbarItem::HoverPressed); + else if (state == GLToolbarItem::HoverPressed) + item->set_state(GLToolbarItem::Hover); + + canvas.render(); + item->do_action(); + } + else + { + item->set_state(GLToolbarItem::HoverPressed); + canvas.render(); + item->do_action(); + if (item->get_state() != GLToolbarItem::Disabled) + { + // the item may get disabled during the action, if not, set it to normal state + item->set_state(GLToolbarItem::Hover); + canvas.render(); + } + } + } + } +} + void GLToolbar::render(const GLCanvas3D& canvas, const Pointf& mouse_pos) const { - if (m_items.empty()) + if (!m_enabled || m_items.empty()) return; ::glDisable(GL_DEPTH_TEST); diff --git a/xs/src/slic3r/GUI/GLToolbar.hpp b/xs/src/slic3r/GUI/GLToolbar.hpp index 5a1af5b37..e5c8f9fb8 100644 --- a/xs/src/slic3r/GUI/GLToolbar.hpp +++ b/xs/src/slic3r/GUI/GLToolbar.hpp @@ -2,6 +2,7 @@ #define slic3r_GLToolbar_hpp_ #include "../../slic3r/GUI/GLTexture.hpp" +#include "../../libslic3r/Utils.hpp" #include #include @@ -29,6 +30,7 @@ public: Normal, Hover, Pressed, + HoverPressed, Disabled, Num_States }; @@ -43,8 +45,11 @@ private: std::string m_name; std::string m_tooltip; + bool m_is_toggable; + PerlCallback* m_action_callback; + public: - GLToolbarItem(EType type, const std::string& name, const std::string& tooltip); + GLToolbarItem(EType type, const std::string& name, const std::string& tooltip, bool is_toggable, PerlCallback* action_callback); bool load_textures(const std::string* filenames); @@ -58,6 +63,10 @@ public: unsigned int get_icon_texture_id() const; int get_icon_textures_size() const; + void do_action(); + + bool is_enabled() const; + bool is_toggable() const; bool is_separator() const; }; @@ -68,6 +77,8 @@ public: { std::string name; std::string tooltip; + bool is_toggable; + PerlCallback* action_callback; std::string textures[GLToolbarItem::Num_States]; }; @@ -99,8 +110,15 @@ public: void enable_item(const std::string& name); void disable_item(const std::string& name); + bool is_item_pressed(const std::string& name) const; + void update_hover_state(GLCanvas3D& canvas, const Pointf& mouse_pos); + // returns the id of the item under the given mouse position or -1 if none + int contains_mouse(const GLCanvas3D& canvas, const Pointf& mouse_pos) const; + + void do_action(unsigned int item_id, GLCanvas3D& canvas); + void render(const GLCanvas3D& canvas, const Pointf& mouse_pos) const; private: diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index b906a3ce9..1999b2ce3 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -452,6 +452,15 @@ enable_toolbar_item(canvas, item, enable) CODE: _3DScene::enable_toolbar_item((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), item, enable); +bool +is_toolbar_item_pressed(canvas, item) + SV *canvas; + std::string item; + CODE: + RETVAL = _3DScene::is_toolbar_item_pressed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), item); + OUTPUT: + RETVAL + void zoom_to_bed(canvas) SV *canvas; @@ -638,7 +647,98 @@ register_on_update_geometry_info_callback(canvas, callback) SV *callback; CODE: _3DScene::register_on_update_geometry_info_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); - + +void +register_action_add_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_add_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_delete_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_delete_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_deleteall_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_deleteall_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_arrange_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_arrange_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_more_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_more_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_fewer_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_fewer_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_ccw45_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_ccw45_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_cw45_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_cw45_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_scale_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_scale_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_split_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_split_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_cut_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_cut_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_settings_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_settings_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + +void +register_action_layersediting_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_layersediting_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + void reset_legend_texture() CODE: