From 8460926d36f777282e0cfc47a86341a6b1991fc2 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 6 Sep 2018 16:10:31 +0200 Subject: [PATCH] Added select by part tool to toolbar --- lib/Slic3r/GUI/Plater.pm | 46 +++++++++++++++- resources/icons/toolbar.png | Bin 20451 -> 21874 bytes xs/src/slic3r/GUI/3DScene.cpp | 53 ++++++++++++++---- xs/src/slic3r/GUI/3DScene.hpp | 9 +++ xs/src/slic3r/GUI/GLCanvas3D.cpp | 70 +++++++++++++++++++++--- xs/src/slic3r/GUI/GLCanvas3D.hpp | 8 ++- xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 19 +++++++ xs/src/slic3r/GUI/GLCanvas3DManager.hpp | 5 ++ xs/src/slic3r/GUI/GUI_ObjectParts.cpp | 1 - xs/xsp/GUI_3DScene.xsp | 24 ++++++++ 10 files changed, 211 insertions(+), 24 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index b48ab0f97..8a9d13aae 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -85,9 +85,13 @@ sub new { # Initialize handlers for canvases my $on_select_object = sub { - my ($obj_idx) = @_; - # Ignore the special objects (the wipe tower proxy and such). - $self->select_object((defined($obj_idx) && $obj_idx >= 0 && $obj_idx < 1000) ? $obj_idx : undef); + my ($obj_idx, $vol_idx) = @_; + + if (($obj_idx != -1) && ($vol_idx == -1)) { + # Ignore the special objects (the wipe tower proxy and such). + $self->select_object((defined($obj_idx) && $obj_idx >= 0 && $obj_idx < 1000) ? $obj_idx : undef); + $self->item_changed_selection($obj_idx) if (defined($obj_idx)); + } }; my $on_double_click = sub { $self->object_settings_dialog if $self->selected_object; @@ -217,6 +221,29 @@ sub new { my $state = Slic3r::GUI::_3DScene::is_toolbar_item_pressed($self->{canvas3D}, "layersediting"); $self->on_layer_editing_toggled($state); }; + + my $on_action_selectbyparts = sub { + my $curr = Slic3r::GUI::_3DScene::get_select_by($self->{canvas3D}); + if ($curr eq 'volume') { + Slic3r::GUI::_3DScene::set_select_by($self->{canvas3D}, 'object'); + my $selections = $self->collect_selections; + Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections); + Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1); + } + elsif ($curr eq 'object') { + Slic3r::GUI::_3DScene::set_select_by($self->{canvas3D}, 'volume'); + my $selections = []; + Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections); + Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D}); + Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1); + + my ($obj_idx, $object) = $self->selected_object; + if (defined $obj_idx) { + my $vol_idx = Slic3r::GUI::_3DScene::get_first_volume_id($self->{canvas3D}, $obj_idx); + Slic3r::GUI::_3DScene::select_volume($self->{canvas3D}, $vol_idx) if ($vol_idx != -1); + } + } + }; # Initialize 3D plater if ($Slic3r::GUI::have_OpenGL) { @@ -247,6 +274,7 @@ sub new { 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::register_action_selectbyparts_callback($self->{canvas3D}, $on_action_selectbyparts); Slic3r::GUI::_3DScene::enable_gizmos($self->{canvas3D}, 1); Slic3r::GUI::_3DScene::enable_toolbar($self->{canvas3D}, 1); Slic3r::GUI::_3DScene::enable_shader($self->{canvas3D}, 1); @@ -2331,12 +2359,24 @@ sub selection_changed { } Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "layersediting", $layers_height_allowed); + + my $can_select_by_parts = 0; if ($have_sel) { my $model_object = $self->{model}->objects->[$obj_idx]; + $can_select_by_parts = ($obj_idx >= 0) && ($obj_idx < 1000) && ($model_object->volumes_count > 1); Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "fewer", $model_object->instances_count > 1); } + if ($can_select_by_parts) { + # first disable to let the item in the toolbar to switch to the unpressed state + Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "selectbyparts", 0); + Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "selectbyparts", 1); + } else { + Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "selectbyparts", 0); + Slic3r::GUI::_3DScene::set_select_by($self->{canvas3D}, 'object'); + } + if ($self->{object_info_size}) { # have we already loaded the info pane? if ($have_sel) { my $model_object = $self->{model}->objects->[$obj_idx]; diff --git a/resources/icons/toolbar.png b/resources/icons/toolbar.png index ce954143dbe98cc25d31ea8831332e402ee395cb..79246bcf91761ca4d6c89393cbfd9a5f6a28e6ea 100644 GIT binary patch delta 5304 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 GLVolumeCollection::load_object( v.bounding_box = v.indexed_vertex_array.bounding_box(); v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx; - if (select_by == "object") - v.select_group_id = obj_idx * 1000000; - else if (select_by == "volume") - v.select_group_id = obj_idx * 1000000 + volume_idx * 1000; - else if (select_by == "instance") - v.select_group_id = v.composite_id; + v.set_select_group_id(select_by); if (drag_by == "object") v.drag_group_id = obj_idx * 1000; else if (drag_by == "instance") @@ -949,6 +954,15 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con } } +void GLVolumeCollection::set_select_by(const std::string& select_by) +{ + for (GLVolume *vol : this->volumes) + { + if (vol != nullptr) + vol->set_select_group_id(select_by); + } +} + std::vector GLVolumeCollection::get_current_print_zs(bool active_only) const { // Collect layer top positions of all volumes. @@ -1772,12 +1786,12 @@ void _3DScene::set_model(wxGLCanvas* canvas, Model* model) void _3DScene::set_bed_shape(wxGLCanvas* canvas, const Pointfs& shape) { - return s_canvas_mgr.set_bed_shape(canvas, shape); + s_canvas_mgr.set_bed_shape(canvas, shape); } void _3DScene::set_auto_bed_shape(wxGLCanvas* canvas) { - return s_canvas_mgr.set_auto_bed_shape(canvas); + s_canvas_mgr.set_auto_bed_shape(canvas); } BoundingBoxf3 _3DScene::get_volumes_bounding_box(wxGLCanvas* canvas) @@ -1792,22 +1806,27 @@ void _3DScene::set_axes_length(wxGLCanvas* canvas, float length) void _3DScene::set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons) { - return s_canvas_mgr.set_cutting_plane(canvas, z, polygons); + s_canvas_mgr.set_cutting_plane(canvas, z, polygons); } void _3DScene::set_color_by(wxGLCanvas* canvas, const std::string& value) { - return s_canvas_mgr.set_color_by(canvas, value); + s_canvas_mgr.set_color_by(canvas, value); } void _3DScene::set_select_by(wxGLCanvas* canvas, const std::string& value) { - return s_canvas_mgr.set_select_by(canvas, value); + s_canvas_mgr.set_select_by(canvas, value); } void _3DScene::set_drag_by(wxGLCanvas* canvas, const std::string& value) { - return s_canvas_mgr.set_drag_by(canvas, value); + s_canvas_mgr.set_drag_by(canvas, value); +} + +std::string _3DScene::get_select_by(wxGLCanvas* canvas) +{ + return s_canvas_mgr.get_select_by(canvas); } bool _3DScene::is_layers_editing_enabled(wxGLCanvas* canvas) @@ -2080,6 +2099,11 @@ void _3DScene::register_action_layersediting_callback(wxGLCanvas* canvas, void* s_canvas_mgr.register_action_layersediting_callback(canvas, callback); } +void _3DScene::register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_action_selectbyparts_callback(canvas, callback); +} + static inline int hex_digit_to_int(const char c) { return @@ -2117,6 +2141,11 @@ std::vector _3DScene::load_object(wxGLCanvas* canvas, const Model* model, i return s_canvas_mgr.load_object(canvas, model, obj_idx); } +int _3DScene::get_first_volume_id(wxGLCanvas* canvas, int obj_idx) +{ + return s_canvas_mgr.get_first_volume_id(canvas, obj_idx); +} + void _3DScene::reload_scene(wxGLCanvas* canvas, bool force) { s_canvas_mgr.reload_scene(canvas, force); diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 1785ecf4a..ec9d1a501 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -337,6 +337,8 @@ public: void set_convex_hull(const TriangleMesh& convex_hull); + void set_select_group_id(const std::string& select_by); + int object_idx() const { return this->composite_id / 1000000; } int volume_idx() const { return (this->composite_id / 1000) % 1000; } int instance_idx() const { return this->composite_id % 1000; } @@ -446,6 +448,8 @@ public: void update_colors_by_extruder(const DynamicPrintConfig* config); + void set_select_by(const std::string& select_by); + // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection std::vector get_current_print_zs(bool active_only) const; @@ -499,6 +503,8 @@ public: static void set_select_by(wxGLCanvas* canvas, const std::string& value); static void set_drag_by(wxGLCanvas* canvas, const std::string& value); + static std::string get_select_by(wxGLCanvas* canvas); + static bool is_layers_editing_enabled(wxGLCanvas* canvas); static bool is_layers_editing_allowed(wxGLCanvas* canvas); static bool is_shader_enabled(wxGLCanvas* canvas); @@ -562,10 +568,13 @@ public: 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 void register_action_selectbyparts_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); + static int get_first_volume_id(wxGLCanvas* canvas, int obj_idx); + static void reload_scene(wxGLCanvas* canvas, bool force); static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 2bec6b66b..56bfb8f37 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -2018,6 +2018,9 @@ void GLCanvas3D::update_volumes_selection(const std::vector& selections) if (m_model == nullptr) return; + if (selections.empty()) + return; + for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++obj_idx) { if ((selections[obj_idx] == 1) && (obj_idx < (unsigned int)m_objects_volumes_idxs.size())) @@ -2144,6 +2147,7 @@ void GLCanvas3D::set_color_by(const std::string& value) void GLCanvas3D::set_select_by(const std::string& value) { m_select_by = value; + m_volumes.set_select_by(value); } void GLCanvas3D::set_drag_by(const std::string& value) @@ -2151,6 +2155,11 @@ void GLCanvas3D::set_drag_by(const std::string& value) m_drag_by = value; } +const std::string& GLCanvas3D::get_select_by() const +{ + return m_select_by; +} + float GLCanvas3D::get_camera_zoom() const { return m_camera.zoom; @@ -2432,6 +2441,17 @@ std::vector GLCanvas3D::load_object(const Model& model, int obj_idx) return std::vector(); } +int GLCanvas3D::get_first_volume_id(int obj_idx) const +{ + for (int i = 0; i < (int)m_volumes.volumes.size(); ++i) + { + if ((m_volumes.volumes[i] != nullptr) && (m_volumes.volumes[i]->object_idx() == obj_idx)) + return i; + } + + return -1; +} + void GLCanvas3D::reload_scene(bool force) { if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) @@ -2757,6 +2777,12 @@ void GLCanvas3D::register_action_layersediting_callback(void* callback) m_action_layersediting_callback.register_callback(callback); } +void GLCanvas3D::register_action_selectbyparts_callback(void* callback) +{ + if (callback != nullptr) + m_action_selectbyparts_callback.register_callback(callback); +} + void GLCanvas3D::bind_event_handlers() { if (m_canvas != nullptr) @@ -3043,7 +3069,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // propagate event through callback if (m_picking_enabled && (volume_idx != -1)) - _on_select(volume_idx); + _on_select(volume_idx, selected_object_idx); if (volume_idx != -1) { @@ -3287,7 +3313,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_picking_enabled && !m_toolbar_action_running) { deselect_volumes(); - _on_select(-1); + _on_select(-1, -1); update_gizmos_data(); } } @@ -3512,6 +3538,17 @@ bool GLCanvas3D::_init_toolbar() if (!m_toolbar.add_item(item)) return false; + if (!m_toolbar.add_separator()) + return false; + + item.name = "selectbyparts"; + item.tooltip = GUI::L_str("Select by parts"); + item.sprite_id = 10; + item.is_toggable = true; + item.action_callback = &m_action_selectbyparts_callback; + if (!m_toolbar.add_item(item)) + return false; + enable_toolbar_item("add", true); return true; @@ -3751,6 +3788,7 @@ void GLCanvas3D::_deregister_callbacks() m_action_cut_callback.deregister_callback(); m_action_settings_callback.deregister_callback(); m_action_layersediting_callback.deregister_callback(); + m_action_selectbyparts_callback.deregister_callback(); } void GLCanvas3D::_mark_volumes_for_layer_height() const @@ -5262,17 +5300,35 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) m_on_wipe_tower_moved_callback.call(wipe_tower_origin(0), wipe_tower_origin(1)); } -void GLCanvas3D::_on_select(int volume_idx) +void GLCanvas3D::_on_select(int volume_idx, int object_idx) { - int id = -1; + int vol_id = -1; + int obj_id = -1; + if ((volume_idx != -1) && (volume_idx < (int)m_volumes.volumes.size())) { if (m_select_by == "volume") - id = m_volumes.volumes[volume_idx]->volume_idx(); + { + if (m_volumes.volumes[volume_idx]->object_idx() != object_idx) + { + set_select_by("object"); + obj_id = m_volumes.volumes[volume_idx]->object_idx(); + vol_id = -1; + } + else + { + obj_id = object_idx; + vol_id = m_volumes.volumes[volume_idx]->volume_idx(); + } + } else if (m_select_by == "object") - id = m_volumes.volumes[volume_idx]->object_idx(); + { + obj_id = m_volumes.volumes[volume_idx]->object_idx(); + vol_id = -1; + } } - m_on_select_object_callback.call(id); + + m_on_select_object_callback.call(obj_id, vol_id); } std::vector GLCanvas3D::_parse_colors(const std::vector& colors) diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 2969d12c6..541495eec 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -514,6 +514,7 @@ private: PerlCallback m_action_cut_callback; PerlCallback m_action_settings_callback; PerlCallback m_action_layersediting_callback; + PerlCallback m_action_selectbyparts_callback; public: GLCanvas3D(wxGLCanvas* canvas); @@ -556,6 +557,8 @@ public: void set_select_by(const std::string& value); void set_drag_by(const std::string& value); + const std::string& get_select_by() const; + float get_camera_zoom() const; BoundingBoxf3 volumes_bounding_box() const; @@ -597,6 +600,8 @@ public: std::vector load_object(const ModelObject& model_object, int obj_idx, std::vector instance_idxs); std::vector load_object(const Model& model, int obj_idx); + int get_first_volume_id(int obj_idx) const; + void reload_scene(bool force); void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); @@ -631,6 +636,7 @@ public: void register_action_cut_callback(void* callback); void register_action_settings_callback(void* callback); void register_action_layersediting_callback(void* callback); + void register_action_selectbyparts_callback(void* callback); void bind_event_handlers(); void unbind_event_handlers(); @@ -733,7 +739,7 @@ private: void _show_warning_texture_if_needed(); void _on_move(const std::vector& volume_idxs); - void _on_select(int volume_idx); + void _on_select(int volume_idx, int object_idx); // generates the legend texture in dependence of the current shown view type void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index 57a49d7ab..a09d83b89 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -338,6 +338,12 @@ void GLCanvas3DManager::set_drag_by(wxGLCanvas* canvas, const std::string& value it->second->set_drag_by(value); } +std::string GLCanvas3DManager::get_select_by(wxGLCanvas* canvas) const +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->get_select_by() : ""; +} + bool GLCanvas3DManager::is_layers_editing_enabled(wxGLCanvas* canvas) const { CanvasesMap::const_iterator it = _get_canvas(canvas); @@ -536,6 +542,12 @@ std::vector GLCanvas3DManager::load_object(wxGLCanvas* canvas, const Model* return (it != m_canvases.end()) ? it->second->load_object(*model, obj_idx) : std::vector(); } +int GLCanvas3DManager::get_first_volume_id(wxGLCanvas* canvas, int obj_idx) const +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second->get_first_volume_id(obj_idx) : -1; +} + void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force) { CanvasesMap::iterator it = _get_canvas(canvas); @@ -765,6 +777,13 @@ void GLCanvas3DManager::register_action_layersediting_callback(wxGLCanvas* canva it->second->register_action_layersediting_callback(callback); } +void GLCanvas3DManager::register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_action_selectbyparts_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 f7705a56c..1c715a9a3 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -98,6 +98,8 @@ public: void set_select_by(wxGLCanvas* canvas, const std::string& value); void set_drag_by(wxGLCanvas* canvas, const std::string& value); + std::string get_select_by(wxGLCanvas* canvas) const; + bool is_layers_editing_enabled(wxGLCanvas* canvas) const; bool is_layers_editing_allowed(wxGLCanvas* canvas) const; bool is_shader_enabled(wxGLCanvas* canvas) const; @@ -135,6 +137,8 @@ public: std::vector load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector instance_idxs); std::vector load_object(wxGLCanvas* canvas, const Model* model, int obj_idx); + int get_first_volume_id(wxGLCanvas* canvas, int obj_idx) const; + void reload_scene(wxGLCanvas* canvas, bool force); void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); @@ -171,6 +175,7 @@ public: 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); + void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback); private: CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp index 9ec39b976..af57db8ed 100644 --- a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/xs/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -1572,7 +1572,6 @@ void update_position_values() void update_position_values(const Vec3d& position) { auto og = get_optgroup(ogFrequentlyObjectSettings); - auto instance = (*m_objects)[m_selected_object_id]->instances.front(); og->set_value("position_x", int(position(0))); og->set_value("position_y", int(position(1))); diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 6c199aacb..756f9e547 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -337,6 +337,14 @@ set_drag_by(canvas, value) CODE: _3DScene::set_drag_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), value); +std::string +get_select_by(canvas) + SV *canvas; + CODE: + RETVAL = _3DScene::get_select_by((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas")); + OUTPUT: + RETVAL + bool is_layers_editing_enabled(canvas) SV *canvas; @@ -720,6 +728,13 @@ register_action_layersediting_callback(canvas, callback) CODE: _3DScene::register_action_layersediting_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); +void +register_action_selectbyparts_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_action_selectbyparts_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + void reset_legend_texture() CODE: @@ -736,6 +751,15 @@ load_model_object(canvas, model_object, obj_idx, instance_idxs) OUTPUT: RETVAL +int +get_first_volume_id(canvas, obj_idx) + SV *canvas; + int obj_idx; + CODE: + RETVAL = _3DScene::get_first_volume_id((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), obj_idx); + OUTPUT: + RETVAL + std::vector load_model(canvas, model, obj_idx) SV *canvas;