From 143c0f3750ee6dd29d492fdd26cc7964b715bfce Mon Sep 17 00:00:00 2001 From: "liz.li" Date: Tue, 27 Sep 2022 15:56:08 +0800 Subject: [PATCH] NEW:add section view at assemble_view Change-Id: I05b77e96e0d382b34ef80f622c71deca1eeb93b8 --- src/slic3r/GUI/GLCanvas3D.cpp | 72 +++++++--- src/slic3r/GUI/GLCanvas3D.hpp | 2 +- src/slic3r/GUI/GUI_Preview.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 167 ++++++++++++++++++++++ src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp | 117 +++++++++++++++ src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 36 ++++- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 4 + 7 files changed, 377 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c948b351d..a0cf1f345 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1978,6 +1978,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re m_selection.volumes_changed(map_glvolume_old_to_new); m_gizmos.update_data(); + m_gizmos.update_assemble_view_data(); m_gizmos.refresh_on_off_state(); // Update the toolbar @@ -2694,7 +2695,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) } else if (keyCode == WXK_CONTROL) m_dirty = true; - else if (m_gizmos.is_enabled() && !m_selection.is_empty()) { + else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) { translationProcessor.process(evt); //switch (keyCode) @@ -2774,7 +2775,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) } else if (keyCode == WXK_CONTROL) m_dirty = true; - else if (m_gizmos.is_enabled() && !m_selection.is_empty()) { + else if (m_gizmos.is_enabled() && !m_selection.is_empty() && m_canvas_type != CanvasAssembleView) { // auto do_rotate = [this](double angle_z_rad) { // m_selection.start_dragging(); // m_selection.rotate(Vec3d(0.0, 0.0, angle_z_rad), TransformationType(TransformationType::World_Relative_Joint)); @@ -3351,6 +3352,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) //BBS do not limit rotate in assemble view camera.rotate_local_with_target(Vec3d(rot.y(), rot.x(), 0.), rotate_target); //camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, rotate_target); + auto clp_dist = m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position(); + m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true); } else { #ifdef SUPPORT_FEEE_CAMERA @@ -5725,7 +5728,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with else m_volumes.set_z_range(-FLT_MAX, FLT_MAX); - m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); + if (m_canvas_type == CanvasAssembleView) { + m_volumes.set_clipping_plane(m_gizmos.get_assemble_view_clipping_plane().get_data()); + } + else { + m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); + } //BBS: remove sinking logic //m_volumes.set_show_sinking_contours(! m_gizmos.is_hiding_instances()); @@ -5766,6 +5774,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with shader->start_using(); } } + break; } case GLVolumeCollection::ERenderType::Transparent: @@ -5779,6 +5788,12 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with return true; } }, with_outline); + if (m_canvas_type == CanvasAssembleView) { + const GLGizmosManager& gm = get_gizmos_manager(); + shader->stop_using(); + gm.render_painter_assemble_view(); + shader->start_using(); + } break; } } @@ -5964,7 +5979,7 @@ void GLCanvas3D::_render_overlays() _check_and_update_toolbar_icon_scale(); - _render_explosion_control(); + _render_assemble_control(); _render_assemble_info(); // main toolbar and undoredo toolbar need to be both updated before rendering because both their sizes are needed @@ -6172,6 +6187,8 @@ void GLCanvas3D::_render_gizmos_overlay() const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale()); m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment #endif /* __WXMSW__ */ + if (m_canvas_type == CanvasAssembleView) + return; m_gizmos.render_overlay(); @@ -6669,7 +6686,7 @@ void GLCanvas3D::_render_paint_toolbar() const } //BBS -void GLCanvas3D::_render_explosion_control() const +void GLCanvas3D::_render_assemble_control() const { if (m_canvas_type != ECanvasType::CanvasAssembleView) { GLVolume::explosion_ratio = m_explosion_ratio = 1.0; @@ -6684,26 +6701,45 @@ void GLCanvas3D::_render_explosion_control() const auto canvas_h = float(get_canvas_size().get_height()); const float text_padding = 7.0f; - ImVec2 text_size = imgui->calc_text_size(_L("Explosion Ratio")); - const float slider_width = 130.0f; + const float text_size_x = std::max(imgui->calc_text_size(_L("Explosion Ratio")).x, imgui->calc_text_size(_L("Section View")).x); + const float slider_width = 75.0f; const float value_size = imgui->calc_text_size("3.00").x + text_padding * 2; const float item_spacing = imgui->get_item_spacing().x; ImVec2 window_padding = ImGui::GetStyle().WindowPadding; - ImVec2 window_size = ImVec2(text_size.x + slider_width + value_size + item_spacing * 2 + window_padding.x * 2, window_padding.y * 2 + text_size.y); - // 13.0f is bottom margin - imgui->set_next_window_pos(canvas_w * 0.5 - window_size.x * 0.5, canvas_h - window_size.y - 13.0f, ImGuiCond_Always, 0.0f, 0.0f); - imgui->begin(_L("Explosion Ratio"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); + imgui->set_next_window_pos(canvas_w / 2, canvas_h - 13.0f * get_scale(), ImGuiCond_Always, 0.5f, 1.0f); + imgui->begin(_L("Assemble Control"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); ImGui::AlignTextToFramePadding(); - imgui->text(_L("Explosion Ratio")); - ImGui::SameLine(window_padding.x + text_size.x + item_spacing); - ImGui::PushItemWidth(slider_width); - bool slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f"); - ImGui::SameLine(window_padding.x + text_size.x + slider_width + item_spacing * 2); - ImGui::PushItemWidth(value_size); - bool input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f"); + { + imgui->text(_L("Section View")); + + ImGui::SameLine(window_padding.x + text_size_x + item_spacing); + ImGui::PushItemWidth(slider_width); + static float clp_dist = 0.f; + bool view_slider_changed = imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true); + + ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 2); + ImGui::PushItemWidth(value_size); + bool view_input_changed = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f"); + + if (view_slider_changed || view_input_changed) + m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(clp_dist, true); + } + + { + ImGui::SameLine(window_padding.x + text_size_x + slider_width + item_spacing * 6 + value_size); + imgui->text(_L("Explosion Ratio")); + + ImGui::SameLine(window_padding.x + 2 * text_size_x + slider_width + item_spacing * 7 + value_size); + ImGui::PushItemWidth(slider_width); + bool explosion_slider_changed = imgui->bbl_slider_float_style("##ratio_slider", &m_explosion_ratio, 1.0f, 3.0f, "%1.2f"); + + ImGui::SameLine(window_padding.x + 2 * text_size_x + 2 * slider_width + item_spacing * 8 + value_size); + ImGui::PushItemWidth(value_size); + bool explosion_input_changed = ImGui::BBLDragFloat("##ratio_input", &m_explosion_ratio, 0.1f, 1.0f, 3.0f, "%1.2f"); + } imgui->end(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 933f698c1..452cd0add 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -978,7 +978,7 @@ private: // BBS //void _render_view_toolbar() const; void _render_paint_toolbar() const; - void _render_explosion_control() const; + void _render_assemble_control() const; void _render_assemble_info() const; #if ENABLE_SHOW_CAMERA_TARGET void _render_camera_target() const; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 26b9f5104..2d10cd50e 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -767,7 +767,7 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint m_canvas->set_process(process); m_canvas->set_type(GLCanvas3D::ECanvasType::CanvasAssembleView); m_canvas->set_config(config); - m_canvas->enable_gizmos(false); + m_canvas->enable_gizmos(true); m_canvas->enable_selection(true); m_canvas->enable_main_toolbar(false); m_canvas->enable_labels(false); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index b7583977f..2bc950fe3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -541,5 +541,172 @@ void SupportsClipper::render_cut() const } + +using namespace AssembleViewDataObjects; +AssembleViewDataPool::AssembleViewDataPool(GLCanvas3D* canvas) + : m_canvas(canvas) +{ + using c = AssembleViewDataID; + m_data[c::ModelObjectsInfo].reset(new ModelObjectsInfo(this)); + m_data[c::ModelObjectsClipper].reset(new ModelObjectsClipper(this)); +} + +void AssembleViewDataPool::update(AssembleViewDataID required) +{ + assert(check_dependencies(required)); + for (auto& [id, data] : m_data) { + if (int(required) & int(AssembleViewDataID(id))) + data->update(); + else + if (data->is_valid()) + data->release(); + } +} + + +ModelObjectsInfo* AssembleViewDataPool::model_objects_info() const +{ + ModelObjectsInfo* sel_info = dynamic_cast(m_data.at(AssembleViewDataID::ModelObjectsInfo).get()); + assert(sel_info); + return sel_info->is_valid() ? sel_info : nullptr; +} + + +ModelObjectsClipper* AssembleViewDataPool::model_objects_clipper() const +{ + ModelObjectsClipper* oc = dynamic_cast(m_data.at(AssembleViewDataID::ModelObjectsClipper).get()); + // ObjectClipper is used from outside the gizmos to report current clipping plane. + // This function can be called when oc is nullptr. + return (oc && oc->is_valid()) ? oc : nullptr; +} + +#ifndef NDEBUG +// Check the required resources one by one and return true if all +// dependencies are met. +bool AssembleViewDataPool::check_dependencies(AssembleViewDataID required) const +{ + // This should iterate over currently required data. Each of them should + // be asked about its dependencies and it must check that all dependencies + // are also in required and before the current one. + for (auto& [id, data] : m_data) { + // in case we don't use this, the deps are irrelevant + if (!(int(required) & int(AssembleViewDataID(id)))) + continue; + + + AssembleViewDataID deps = data->get_dependencies(); + assert(int(deps) == (int(deps) & int(required))); + } + + +return true; +} +#endif // NDEBUG + + + + +void ModelObjectsInfo::on_update() +{ + if (!get_pool()->get_canvas()->get_model()->objects.empty()) { + m_model_objects = get_pool()->get_canvas()->get_model()->objects; + } +} + +void ModelObjectsInfo::on_release() +{ + m_model_objects.clear(); +} + +//int ModelObjectsInfo::get_active_instance() const +//{ +// const Selection& selection = get_pool()->get_canvas()->get_selection(); +// return selection.get_instance_idx(); +//} + + +void ModelObjectsClipper::on_update() +{ + const ModelObjectPtrs model_objects = get_pool()->model_objects_info()->model_objects(); + if (model_objects.empty()) + return; + + // which mesh should be cut? + std::vector meshes; + + if (meshes.empty()) + for (auto mo : model_objects) { + for (const ModelVolume* mv : mo->volumes) + meshes.push_back(&mv->mesh()); + } + + if (meshes != m_old_meshes) { + m_clippers.clear(); + for (const TriangleMesh* mesh : meshes) { + m_clippers.emplace_back(new MeshClipper); + m_clippers.back()->set_mesh(*mesh); + } + m_old_meshes = meshes; + + m_active_inst_bb_radius = get_pool()->get_canvas()->volumes_bounding_box().radius(); + } +} + + +void ModelObjectsClipper::on_release() +{ + m_clippers.clear(); + m_old_meshes.clear(); + m_clp.reset(); + m_clp_ratio = 0.; + +} + +void ModelObjectsClipper::render_cut() const +{ + if (m_clp_ratio == 0.) + return; + const ModelObjectPtrs model_objects = get_pool()->model_objects_info()->model_objects(); + + size_t clipper_id = 0; + for (const ModelObject* mo : model_objects) { + Geometry::Transformation assemble_objects_trafo = mo->instances[0]->get_assemble_transformation(); + auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly(); + for (const ModelVolume* mv : mo->volumes) { + Geometry::Transformation vol_trafo = mv->get_transformation(); + Geometry::Transformation trafo = assemble_objects_trafo * vol_trafo; + trafo.set_offset(trafo.get_offset() + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0) + offset_to_assembly * (GLVolume::explosion_ratio - 1.0)); + + auto& clipper = m_clippers[clipper_id]; + clipper->set_plane(*m_clp); + clipper->set_transformation(trafo); + glsafe(::glPushMatrix()); + // BBS + glsafe(::glColor3f(0.25f, 0.25f, 0.25f)); + clipper->render_cut(); + glsafe(::glPopMatrix()); + + ++clipper_id; + } + } +} + + +void ModelObjectsClipper::set_position(double pos, bool keep_normal) +{ + Vec3d camera_dir = wxGetApp().plater()->get_camera().get_dir_forward(); + Vec3d normal = -camera_dir; + const Vec3d& center = get_pool()->get_canvas()->volumes_bounding_box().center(); + float dist = normal.dot(center); + + if (pos < 0.) + pos = m_clp_ratio; + + m_clp_ratio = pos; + m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius * GLVolume::explosion_ratio) - m_clp_ratio * 2 * m_active_inst_bb_radius * GLVolume::explosion_ratio))); + get_pool()->get_canvas()->set_as_dirty(); +} + + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp index 228f5b58c..91c1bde44 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp @@ -39,6 +39,7 @@ enum class SLAGizmoEventType : unsigned char { class CommonGizmosDataBase; +class AssembleViewDataBase; namespace CommonGizmosDataObjects { class SelectionInfo; class InstancesHider; @@ -48,6 +49,11 @@ namespace CommonGizmosDataObjects { class SupportsClipper; } +namespace AssembleViewDataObjects { + class ModelObjectsInfo; + class ModelObjectsClipper; +} + // Some of the gizmos use the same data that need to be updated ocassionally. // It is also desirable that the data are not recalculated when the gizmos // are just switched, but on the other hand, they should be released when @@ -306,9 +312,120 @@ private: } // namespace CommonGizmosDataObjects +enum class AssembleViewDataID { + None = 0, + ModelObjectsInfo = 1 << 0, + ModelObjectsClipper = 1 << 4, +}; + +class AssembleViewDataPool { +public: + AssembleViewDataPool(GLCanvas3D* canvas); + + // Update all resources and release what is not used. + // Accepts a bitmask of currently required resources. + void update(AssembleViewDataID required); + + // Getters for the data that need to be accessed from the gizmos directly. + AssembleViewDataObjects::ModelObjectsInfo* model_objects_info() const; + AssembleViewDataObjects::ModelObjectsClipper* model_objects_clipper() const; + + GLCanvas3D* get_canvas() const { return m_canvas; } + +private: + std::map> m_data; + GLCanvas3D* m_canvas; + +#ifndef NDEBUG + bool check_dependencies(AssembleViewDataID required) const; +#endif +}; + +// Base class for a wrapper object managing a single resource. +// Each of the enum values above (safe None) will have an object of this kind. +class AssembleViewDataBase { +public: + // Pass a backpointer to the pool, so the individual + // objects can communicate with one another. + explicit AssembleViewDataBase(AssembleViewDataPool* cgdp) + : m_common{ cgdp } {} + virtual ~AssembleViewDataBase() {} + + // Update the resource. + void update() { on_update(); m_is_valid = true; } + + // Release any data that are stored internally. + void release() { on_release(); m_is_valid = false; } + + // Returns whether the resource is currently maintained. + bool is_valid() const { return m_is_valid; } + +#ifndef NDEBUG + // Return a bitmask of all resources that this one relies on. + // The dependent resource must have higher ID than the one + // it depends on. + virtual AssembleViewDataID get_dependencies() const { return AssembleViewDataID::None; } +#endif // NDEBUG + +protected: + virtual void on_release() = 0; + virtual void on_update() = 0; + AssembleViewDataPool* get_pool() const { return m_common; } +private: + bool m_is_valid = false; + AssembleViewDataPool* m_common = nullptr; +}; +namespace AssembleViewDataObjects +{ +class ModelObjectsInfo : public AssembleViewDataBase +{ +public: + explicit ModelObjectsInfo(AssembleViewDataPool* cgdp) + : AssembleViewDataBase(cgdp) {} + + ModelObjectPtrs model_objects() const { return m_model_objects; } + //int get_active_instance() const; + float get_sla_shift() const { return m_z_shift; } + +protected: + void on_update() override; + void on_release() override; + +private: + ModelObjectPtrs m_model_objects; + float m_z_shift = 0.f; +}; + +class ModelObjectsClipper : public AssembleViewDataBase +{ +public: + explicit ModelObjectsClipper(AssembleViewDataPool* cgdp) + : AssembleViewDataBase(cgdp) {} +#ifndef NDEBUG + AssembleViewDataID get_dependencies() const override { return AssembleViewDataID::ModelObjectsInfo; } +#endif // NDEBUG + + void set_position(double pos, bool keep_normal); + double get_position() const { return m_clp_ratio; } + ClippingPlane* get_clipping_plane() const { return m_clp.get(); } + void render_cut() const; + + +protected: + void on_update() override; + void on_release() override; + +private: + std::vector m_old_meshes; + std::vector> m_clippers; + std::unique_ptr m_clp; + double m_clp_ratio = 0.; + double m_active_inst_bb_radius = 0.; +}; +} } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index b8b3ddef9..eabdd1a4a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -155,6 +155,7 @@ bool GLGizmosManager::init() //m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++)); m_common_gizmos_data.reset(new CommonGizmosDataPool(&m_parent)); + m_assemble_view_data.reset(new AssembleViewDataPool(&m_parent)); for (auto& gizmo : m_gizmos) { if (! gizmo->init()) { @@ -341,6 +342,16 @@ void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos) curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos)); } +void GLGizmosManager::update_assemble_view_data() +{ + if (m_assemble_view_data) { + if (m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView) + m_assemble_view_data->update(AssembleViewDataID(0)); + else + m_assemble_view_data->update(AssembleViewDataID((int)AssembleViewDataID::ModelObjectsInfo | (int)AssembleViewDataID::ModelObjectsClipper)); + } +} + void GLGizmosManager::update_data() { if (!m_enabled) @@ -359,10 +370,11 @@ void GLGizmosManager::update_data() enable_grabber(Scale, i, enable_scale_xyz); } - if (m_common_gizmos_data) + if (m_common_gizmos_data) { m_common_gizmos_data->update(get_current() - ? get_current()->get_requirements() - : CommonGizmosDataID(0)); + ? get_current()->get_requirements() + : CommonGizmosDataID(0)); + } if (selection.is_single_full_instance()) { @@ -587,6 +599,18 @@ ClippingPlane GLGizmosManager::get_clipping_plane() const } } +ClippingPlane GLGizmosManager::get_assemble_view_clipping_plane() const +{ + if (!m_assemble_view_data + || !m_assemble_view_data->model_objects_clipper() + || m_assemble_view_data->model_objects_clipper()->get_position() == 0.) + return ClippingPlane::ClipsNothing(); + else { + const ClippingPlane& clp = *m_assemble_view_data->model_objects_clipper()->get_clipping_plane(); + return ClippingPlane(-clp.get_normal(), clp.get_data()[3]); + } +} + bool GLGizmosManager::wants_reslice_supports_on_undo() const { return (m_current == SlaSupports @@ -614,6 +638,12 @@ void GLGizmosManager::render_painter_gizmo() const gizmo->render_painter_gizmo(); } +void GLGizmosManager::render_painter_assemble_view() const +{ + if (m_assemble_view_data) + m_assemble_view_data->model_objects_clipper()->render_cut(); +} + void GLGizmosManager::render_current_gizmo_for_picking_pass() const { if (! m_enabled || m_current == Undefined) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index c1338fdf3..c47aed6ba 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -146,6 +146,7 @@ private: std::map icon_list; public: + std::unique_ptr m_assemble_view_data; enum MENU_ICON_NAME { IC_TOOLBAR_RESET = 0, IC_TOOLBAR_RESET_HOVER, @@ -222,6 +223,7 @@ public: void update(const Linef3& mouse_ray, const Point& mouse_pos); void update_data(); + void update_assemble_view_data(); EType get_current_type() const { return m_current; } GLGizmoBase* get_current() const; @@ -265,6 +267,7 @@ public: bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); ClippingPlane get_clipping_plane() const; + ClippingPlane get_assemble_view_clipping_plane() const; bool wants_reslice_supports_on_undo() const; bool is_in_editing_mode(bool error_notification = false) const; @@ -273,6 +276,7 @@ public: void render_current_gizmo() const; void render_current_gizmo_for_picking_pass() const; void render_painter_gizmo() const; + void render_painter_assemble_view() const; void render_overlay() const;