diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 0f0ae974b..797272223 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -42,6 +42,8 @@ #define ENABLE_TOOLBAR_BACKGROUND_TEXTURE (1 && ENABLE_1_42_0) // Renders a small sphere in the center of the bounding box of the current selection when no gizmo is active #define ENABLE_RENDER_SELECTION_CENTER (0 && ENABLE_1_42_0) +// Show visual hints in the 3D scene when sidebar matrix fields have focus +#define ENABLE_SIDEBAR_VISUAL_HINTS (0 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 09c3443c3..012203450 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1868,6 +1868,130 @@ void _3DScene::point3_to_verts(const Vec3crd& point, double width, double height GUI::GLCanvas3DManager _3DScene::s_canvas_mgr; +#if ENABLE_SIDEBAR_VISUAL_HINTS +GLModel::GLModel() + : m_useVBOs(false) +{ +} + +GLModel::~GLModel() +{ + m_volume.release_geometry(); +} + +void GLModel::set_color(float* color, unsigned int size) +{ + m_volume.set_render_color(color, size); +} + +void GLModel::set_scale(const Vec3d& scale) +{ + m_volume.set_volume_scaling_factor(scale); +} + +void GLModel::render() const +{ + if (m_useVBOs) + render_VBOs(); + else + { + } +} + +void GLModel::render_VBOs() const +{ + ::glEnable(GL_BLEND); + ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + ::glCullFace(GL_BACK); + ::glEnableClientState(GL_VERTEX_ARRAY); + ::glEnableClientState(GL_NORMAL_ARRAY); + + GLint current_program_id; + ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); + GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; + + m_volume.render_VBOs(color_id, -1, -1); + + ::glBindBuffer(GL_ARRAY_BUFFER, 0); + ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + ::glDisableClientState(GL_VERTEX_ARRAY); + ::glDisableClientState(GL_NORMAL_ARRAY); + + ::glDisable(GL_BLEND); +} + +GLArrow::GLArrow() + : GLModel() +{ +} + +bool GLArrow::on_init(bool useVBOs) +{ + Pointf3s vertices; + std::vector triangles; + + // top face + vertices.emplace_back(0.5, 0.0, -0.1); + vertices.emplace_back(0.5, 2.0, -0.1); + vertices.emplace_back(1.0, 2.0, -0.1); + vertices.emplace_back(0.0, 3.0, -0.1); + vertices.emplace_back(-1.0, 2.0, -0.1); + vertices.emplace_back(-0.5, 2.0, -0.1); + vertices.emplace_back(-0.5, 0.0, -0.1); + + // bottom face + vertices.emplace_back(0.5, 0.0, 0.1); + vertices.emplace_back(0.5, 2.0, 0.1); + vertices.emplace_back(1.0, 2.0, 0.1); + vertices.emplace_back(0.0, 3.0, 0.1); + vertices.emplace_back(-1.0, 2.0, 0.1); + vertices.emplace_back(-0.5, 2.0, 0.1); + vertices.emplace_back(-0.5, 0.0, 0.1); + + // bottom face + triangles.emplace_back(0, 6, 1); + triangles.emplace_back(6, 5, 1); + triangles.emplace_back(5, 4, 3); + triangles.emplace_back(5, 3, 1); + triangles.emplace_back(1, 3, 2); + + // top face + triangles.emplace_back(7, 8, 13); + triangles.emplace_back(13, 8, 12); + triangles.emplace_back(12, 10, 11); + triangles.emplace_back(8, 10, 12); + triangles.emplace_back(8, 9, 10); + + // side face + triangles.emplace_back(0, 1, 8); + triangles.emplace_back(8, 7, 0); + triangles.emplace_back(1, 2, 9); + triangles.emplace_back(9, 8, 1); + triangles.emplace_back(2, 3, 10); + triangles.emplace_back(10, 9, 2); + triangles.emplace_back(3, 4, 11); + triangles.emplace_back(11, 10, 3); + triangles.emplace_back(4, 5, 12); + triangles.emplace_back(12, 11, 4); + triangles.emplace_back(5, 6, 13); + triangles.emplace_back(13, 12, 5); + triangles.emplace_back(6, 0, 7); + triangles.emplace_back(7, 13, 6); + + m_useVBOs = useVBOs; + + if (m_useVBOs) + m_volume.indexed_vertex_array.load_mesh_full_shading(TriangleMesh(vertices, triangles)); + else + m_volume.indexed_vertex_array.load_mesh_flat_shading(TriangleMesh(vertices, triangles)); + + m_volume.finalize_geometry(m_useVBOs); + return true; +} +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + std::string _3DScene::get_gl_info(bool format_as_html, bool extensions) { return s_canvas_mgr.get_gl_info(format_as_html, extensions); diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 97b0310e5..169b0c740 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -583,6 +583,41 @@ private: GLVolumeCollection& operator=(const GLVolumeCollection &); }; +#if ENABLE_SIDEBAR_VISUAL_HINTS +class GLModel +{ +protected: + GLVolume m_volume; + bool m_useVBOs; + +public: + GLModel(); + virtual ~GLModel(); + + bool init(bool useVBOs) { return on_init(useVBOs); } + + void set_color(float* color, unsigned int size); + void set_scale(const Vec3d& scale); + + void render() const; + +protected: + virtual bool on_init(bool useVBOs) = 0; + +private: + void render_VBOs() const; +}; + +class GLArrow : public GLModel +{ +public: + GLArrow(); + +protected: + virtual bool on_init(bool useVBOs); +}; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + class _3DScene { static GUI::GLCanvas3DManager s_canvas_mgr; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c266c41d0..7facc3623 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1154,6 +1154,12 @@ GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec } #endif // ENABLE_MODELVOLUME_TRANSFORM +#if ENABLE_SIDEBAR_VISUAL_HINTS +const float GLCanvas3D::Selection::RED[3] = { 1.0f, 0.0f, 0.0f }; +const float GLCanvas3D::Selection::GREEN[3] = { 0.0f, 1.0f, 0.0f }; +const float GLCanvas3D::Selection::BLUE[3] = { 0.0f, 0.0f, 1.0f }; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + GLCanvas3D::Selection::Selection() : m_volumes(nullptr) , m_model(nullptr) @@ -1183,6 +1189,19 @@ void GLCanvas3D::Selection::set_volumes(GLVolumePtrs* volumes) _update_valid(); } +#if ENABLE_SIDEBAR_VISUAL_HINTS +bool GLCanvas3D::Selection::init(bool useVBOs) +{ + if (m_arrow.init(useVBOs)) + { + m_arrow.set_scale(5.0 * Vec3d::Ones()); + return true; + } + + return false; +} +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + void GLCanvas3D::Selection::set_model(Model* model) { m_model = model; @@ -2055,6 +2074,50 @@ void GLCanvas3D::Selection::render_center() const } #endif // ENABLE_RENDER_SELECTION_CENTER +#if ENABLE_SIDEBAR_VISUAL_HINTS +void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_field) const +{ + if (sidebar_field.empty()) + return; + + ::glClear(GL_DEPTH_BUFFER_BIT); + ::glEnable(GL_DEPTH_TEST); + + ::glEnable(GL_LIGHTING); + + ::glPushMatrix(); + + const Vec3d& center = get_bounding_box().center(); + + if (is_single_full_instance()) + ::glTranslated(center(0), center(1), center(2)); + else if (is_single_volume() || is_single_modifier()) + { + const GLVolume* volume = (*m_volumes)[*m_list.begin()]; + Transform3d orient_matrix = volume->get_instance_transformation().get_matrix(true, false, true, true) * volume->get_volume_transformation().get_matrix(true, false, true, true); + const Vec3d& offset = get_bounding_box().center(); + + ::glTranslated(offset(0), offset(1), offset(2)); + ::glMultMatrixd(orient_matrix.data()); + } + else + ::glTranslated(center(0), center(1), center(2)); + + if (boost::starts_with(sidebar_field, "position")) + _render_sidebar_position_hints(sidebar_field); + else if (boost::starts_with(sidebar_field, "rotation")) + _render_sidebar_rotation_hints(sidebar_field); + else if (boost::starts_with(sidebar_field, "scale")) + _render_sidebar_scale_hints(sidebar_field); + else if (boost::starts_with(sidebar_field, "size")) + _render_sidebar_size_hints(sidebar_field); + + ::glPopMatrix(); + + ::glDisable(GL_LIGHTING); +} +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + void GLCanvas3D::Selection::_update_valid() { m_valid = (m_volumes != nullptr) && (m_model != nullptr); @@ -2457,6 +2520,101 @@ void GLCanvas3D::Selection::_render_bounding_box(const BoundingBoxf3& box, float ::glEnd(); } +#if ENABLE_SIDEBAR_VISUAL_HINTS +void GLCanvas3D::Selection::_render_sidebar_position_hints(const std::string& sidebar_field) const +{ + if (boost::ends_with(sidebar_field, "x")) + { + ::glRotated(-90.0, 0.0, 0.0, 1.0); + _render_sidebar_position_hint(X); + } + else if (boost::ends_with(sidebar_field, "y")) + _render_sidebar_position_hint(Y); + else if (boost::ends_with(sidebar_field, "z")) + { + ::glRotated(90.0, 1.0, 0.0, 0.0); + _render_sidebar_position_hint(Z); + } +} + +void GLCanvas3D::Selection::_render_sidebar_rotation_hints(const std::string& sidebar_field) const +{ +} + +void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const +{ + if (boost::ends_with(sidebar_field, "x") || requires_uniform_scale()) + { + ::glPushMatrix(); + ::glRotated(-90.0, 0.0, 0.0, 1.0); + _render_sidebar_scale_hint(X); + ::glPopMatrix(); + } + + if (boost::ends_with(sidebar_field, "y") || requires_uniform_scale()) + { + ::glPushMatrix(); + _render_sidebar_scale_hint(Y); + ::glPopMatrix(); + } + + if (boost::ends_with(sidebar_field, "z") || requires_uniform_scale()) + { + ::glPushMatrix(); + ::glRotated(90.0, 1.0, 0.0, 0.0); + _render_sidebar_scale_hint(Z); + ::glPopMatrix(); + } +} + +void GLCanvas3D::Selection::_render_sidebar_size_hints(const std::string& sidebar_field) const +{ + _render_sidebar_scale_hints(sidebar_field); +} + +void GLCanvas3D::Selection::_render_sidebar_position_hint(Axis axis) const +{ + float color[3]; + switch (axis) + { + case X: { ::memcpy((void*)color, (const void*)RED, 3 * sizeof(float)); break; } + case Y: { ::memcpy((void*)color, (const void*)GREEN, 3 * sizeof(float)); break; } + case Z: { ::memcpy((void*)color, (const void*)BLUE, 3 * sizeof(float)); break; } + } + + m_arrow.set_color(color, 3); + m_arrow.render(); +} + +void GLCanvas3D::Selection::_render_sidebar_rotation_hint(Axis axis, double length) const +{ +} + +void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const +{ + float color[3]; + switch (axis) + { + case X: { ::memcpy((void*)color, (const void*)RED, 3 * sizeof(float)); break; } + case Y: { ::memcpy((void*)color, (const void*)GREEN, 3 * sizeof(float)); break; } + case Z: { ::memcpy((void*)color, (const void*)BLUE, 3 * sizeof(float)); break; } + } + + m_arrow.set_color(color, 3); + + ::glTranslated(0.0, 5.0, 0.0); + m_arrow.render(); + + ::glTranslated(0.0, -10.0, 0.0); + ::glRotated(180.0, 0.0, 0.0, 1.0); + m_arrow.render(); +} + +void GLCanvas3D::Selection::_render_sidebar_size_hint(Axis axis, double length) const +{ +} +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + void GLCanvas3D::Selection::_synchronize_unselected_instances() { std::set done; // prevent processing volumes twice @@ -3788,6 +3946,11 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) if (!_init_toolbar()) return false; +#if ENABLE_SIDEBAR_VISUAL_HINTS + if (!m_selection.init(m_use_VBOs)) + return false; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + #if ENABLE_REMOVE_TABS_FROM_PLATER post_event(SimpleEvent(EVT_GLCANVAS_INIT)); #endif // ENABLE_REMOVE_TABS_FROM_PLATER @@ -4165,6 +4328,10 @@ void GLCanvas3D::render() // this position is used later into on_mouse() to drag the objects m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast()); +#if ENABLE_SIDEBAR_VISUAL_HINTS + _render_selection_sidebar_hints(); +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + _render_current_gizmo(); #if ENABLE_SHOW_CAMERA_TARGET _render_camera_target(); @@ -5671,6 +5838,11 @@ bool GLCanvas3D::_init_toolbar() icons_data.icon_border_size = 1; icons_data.icon_gap_size = 1; +// icons_data.filename = "toolbar141.png"; +// icons_data.icon_size = 52; +// icons_data.icon_border_size = 0; +// icons_data.icon_gap_size = 0; + BackgroundTexture::Metadata background_data; background_data.filename = "toolbar_background.png"; background_data.left = 16; @@ -6577,6 +6749,19 @@ void GLCanvas3D::_render_sla_slices() const } } +#if ENABLE_SIDEBAR_VISUAL_HINTS +void GLCanvas3D::_render_selection_sidebar_hints() const +{ + if (m_use_VBOs) + m_shader.start_using(); + + m_selection.render_sidebar_hints(m_sidebar_field); + + if (m_use_VBOs) + m_shader.stop_using(); +} +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + void GLCanvas3D::_update_volumes_hover_state() const { for (GLVolume* v : m_volumes.volumes) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d4449aa7a..e73e1d835 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -368,6 +368,12 @@ class GLCanvas3D public: class Selection { +#if ENABLE_SIDEBAR_VISUAL_HINTS + static const float RED[3]; + static const float GREEN[3]; + static const float BLUE[3]; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS + public: typedef std::set IndicesList; @@ -495,6 +501,9 @@ public: #if ENABLE_RENDER_SELECTION_CENTER GLUquadricObj* m_quadric; #endif // ENABLE_RENDER_SELECTION_CENTER +#if ENABLE_SIDEBAR_VISUAL_HINTS + mutable GLArrow m_arrow; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS public: Selection(); @@ -503,6 +512,9 @@ public: #endif // ENABLE_RENDER_SELECTION_CENTER void set_volumes(GLVolumePtrs* volumes); +#if ENABLE_SIDEBAR_VISUAL_HINTS + bool init(bool useVBOs); +#endif // ENABLE_SIDEBAR_VISUAL_HINTS Model* get_model() const { return m_model; } void set_model(Model* model); @@ -580,6 +592,9 @@ public: #if ENABLE_RENDER_SELECTION_CENTER void render_center() const; #endif // ENABLE_RENDER_SELECTION_CENTER +#if ENABLE_SIDEBAR_VISUAL_HINTS + void render_sidebar_hints(const std::string& sidebar_field) const; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS private: void _update_valid(); @@ -595,6 +610,16 @@ public: void _render_selected_volumes() const; void _render_synchronized_volumes() const; void _render_bounding_box(const BoundingBoxf3& box, float* color) const; +#if ENABLE_SIDEBAR_VISUAL_HINTS + void _render_sidebar_position_hints(const std::string& sidebar_field) const; + void _render_sidebar_rotation_hints(const std::string& sidebar_field) const; + void _render_sidebar_scale_hints(const std::string& sidebar_field) const; + void _render_sidebar_size_hints(const std::string& sidebar_field) const; + void _render_sidebar_position_hint(Axis axis) const; + void _render_sidebar_rotation_hint(Axis axis, double length) const; + void _render_sidebar_scale_hint(Axis axis) const; + void _render_sidebar_size_hint(Axis axis, double length) const; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS void _synchronize_unselected_instances(); void _synchronize_unselected_volumes(); #if ENABLE_ENSURE_ON_BED_WHILE_SCALING @@ -1055,6 +1080,9 @@ private: void _render_camera_target() const; #endif // ENABLE_SHOW_CAMERA_TARGET void _render_sla_slices() const; +#if ENABLE_SIDEBAR_VISUAL_HINTS + void _render_selection_sidebar_hints() const; +#endif // ENABLE_SIDEBAR_VISUAL_HINTS void _update_volumes_hover_state() const; void _update_gizmos_data();