diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index ef60ab3fa..9d2531813 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -30,6 +30,9 @@ set(SLIC3R_GUI_SOURCES GUI/GLCanvas3DManager.cpp GUI/Selection.hpp GUI/Selection.cpp + GUI/Gizmos/GLGizmos.hpp + GUI/Gizmos/GLGizmosManager.cpp + GUI/Gizmos/GLGizmosManager.hpp GUI/Gizmos/GLGizmoBase.cpp GUI/Gizmos/GLGizmoBase.hpp GUI/Gizmos/GLGizmoMove.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7fb1ad25e..06a36866d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -124,62 +124,6 @@ void Size::set_scale_factor(int scale_factor) m_scale_factor = scale_factor; } -Rect::Rect() - : m_left(0.0f) - , m_top(0.0f) - , m_right(0.0f) - , m_bottom(0.0f) -{ -} - -Rect::Rect(float left, float top, float right, float bottom) - : m_left(left) - , m_top(top) - , m_right(right) - , m_bottom(bottom) -{ -} - -float Rect::get_left() const -{ - return m_left; -} - -void Rect::set_left(float left) -{ - m_left = left; -} - -float Rect::get_top() const -{ - return m_top; -} - -void Rect::set_top(float top) -{ - m_top = top; -} - -float Rect::get_right() const -{ - return m_right; -} - -void Rect::set_right(float right) -{ - m_right = right; -} - -float Rect::get_bottom() const -{ - return m_bottom; -} - -void Rect::set_bottom(float bottom) -{ - m_bottom = bottom; -} - #if !ENABLE_TEXTURES_FROM_SVG GLCanvas3D::Shader::Shader() : m_shader(nullptr) @@ -734,881 +678,6 @@ GLCanvas3D::Mouse::Mouse() { } -#if ENABLE_SVG_ICONS -const float GLCanvas3D::Gizmos::Default_Icons_Size = 64; -#endif // ENABLE_SVG_ICONS - -GLCanvas3D::Gizmos::Gizmos() - : m_enabled(false) -#if ENABLE_SVG_ICONS - , m_icons_texture_dirty(true) -#endif // ENABLE_SVG_ICONS - , m_current(Undefined) -#if ENABLE_SVG_ICONS - , m_overlay_icons_size(Default_Icons_Size) - , m_overlay_scale(1.0f) - , m_overlay_border(5.0f) - , m_overlay_gap_y(5.0f) -{ -} -#else -{ - set_overlay_scale(1.0); -} -#endif // ENABLE_SVG_ICONS - -GLCanvas3D::Gizmos::~Gizmos() -{ - reset(); -} - -bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) -{ -#if !ENABLE_SVG_ICONS - m_icons_texture.metadata.filename = "gizmos.png"; - m_icons_texture.metadata.icon_size = 64; - - if (!m_icons_texture.metadata.filename.empty()) - { - if (!m_icons_texture.texture.load_from_file(resources_dir() + "/icons/" + m_icons_texture.metadata.filename, false)) - { - reset(); - return false; - } - } -#endif // !ENABLE_SVG_ICONS - - m_background_texture.metadata.filename = "toolbar_background.png"; - m_background_texture.metadata.left = 16; - m_background_texture.metadata.top = 16; - m_background_texture.metadata.right = 16; - m_background_texture.metadata.bottom = 16; - - if (!m_background_texture.metadata.filename.empty()) - { - if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false)) - { - reset(); - return false; - } - } - -#if ENABLE_SVG_ICONS - GLGizmoBase* gizmo = new GLGizmoMove3D(parent, "move.svg", 0); -#else - GLGizmoBase* gizmo = new GLGizmoMove3D(parent, 0); -#endif // ENABLE_SVG_ICONS - if (gizmo == nullptr) - return false; - - if (!gizmo->init()) - return false; - - m_gizmos.insert(GizmosMap::value_type(Move, gizmo)); - -#if ENABLE_SVG_ICONS - gizmo = new GLGizmoScale3D(parent, "scale.svg", 1); -#else - gizmo = new GLGizmoScale3D(parent, 1); -#endif // ENABLE_SVG_ICONS - if (gizmo == nullptr) - return false; - - if (!gizmo->init()) - return false; - - m_gizmos.insert(GizmosMap::value_type(Scale, gizmo)); - -#if ENABLE_SVG_ICONS - gizmo = new GLGizmoRotate3D(parent, "rotate.svg", 2); -#else - gizmo = new GLGizmoRotate3D(parent, 2); -#endif // ENABLE_SVG_ICONS - if (gizmo == nullptr) - { - reset(); - return false; - } - - if (!gizmo->init()) - { - reset(); - return false; - } - - m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo)); - -#if ENABLE_SVG_ICONS - gizmo = new GLGizmoFlatten(parent, "place.svg", 3); -#else - gizmo = new GLGizmoFlatten(parent, 3); -#endif // ENABLE_SVG_ICONS - if (gizmo == nullptr) - return false; - - if (!gizmo->init()) { - reset(); - return false; - } - - m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo)); - -#if ENABLE_SVG_ICONS - gizmo = new GLGizmoCut(parent, "cut.svg", 4); -#else - gizmo = new GLGizmoCut(parent, 4); -#endif // ENABLE_SVG_ICONS - if (gizmo == nullptr) - return false; - - if (!gizmo->init()) { - reset(); - return false; - } - - m_gizmos.insert(GizmosMap::value_type(Cut, gizmo)); - -#if ENABLE_SVG_ICONS - gizmo = new GLGizmoSlaSupports(parent, "sla_supports.svg", 5); -#else - gizmo = new GLGizmoSlaSupports(parent, 5); -#endif // ENABLE_SVG_ICONS - if (gizmo == nullptr) - return false; - - if (!gizmo->init()) { - reset(); - return false; - } - - m_gizmos.insert(GizmosMap::value_type(SlaSupports, gizmo)); - - return true; -} - -bool GLCanvas3D::Gizmos::is_enabled() const -{ - return m_enabled; -} - -void GLCanvas3D::Gizmos::set_enabled(bool enable) -{ - m_enabled = enable; -} - -#if ENABLE_SVG_ICONS -void GLCanvas3D::Gizmos::set_overlay_icon_size(float size) -{ - if (m_overlay_icons_size != size) - { - m_overlay_icons_size = size; - m_icons_texture_dirty = true; - } -} -#endif // ENABLE_SVG_ICONS - -void GLCanvas3D::Gizmos::set_overlay_scale(float scale) -{ -#if ENABLE_SVG_ICONS - if (m_overlay_scale != scale) - { - m_overlay_scale = scale; - m_icons_texture_dirty = true; - } -#else - m_overlay_icons_scale = scale; - m_overlay_border = 5.0f * scale; - m_overlay_gap_y = 5.0f * scale; -#endif // ENABLE_SVG_ICONS -} - -std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection) -{ - std::string name = ""; - - if (!m_enabled) - return name; - - float cnv_h = (float)canvas.get_canvas_size().get_height(); - float height = get_total_overlay_height(); -#if ENABLE_SVG_ICONS - float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; - float scaled_border = m_overlay_border * m_overlay_scale; - float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; - float scaled_stride_y = scaled_icons_size + scaled_gap_y; - float top_y = 0.5f * (cnv_h - height) + scaled_border; -#else - float top_y = 0.5f * (cnv_h - height) + m_overlay_border; - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; -#endif // ENABLE_SVG_ICONS - - for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second == nullptr) || !it->second->is_selectable()) - continue; - -#if ENABLE_SVG_ICONS - bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); -#else - bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); -#endif // ENABLE_SVG_ICONS - if (inside) - name = it->second->get_name(); - - if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On)) - it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); - -#if ENABLE_SVG_ICONS - top_y += scaled_stride_y; -#else - top_y += (scaled_icons_size + m_overlay_gap_y); -#endif // ENABLE_SVG_ICONS - } - - return name; -} - -void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection) -{ - if (!m_enabled) - return; - - float cnv_h = (float)canvas.get_canvas_size().get_height(); - float height = get_total_overlay_height(); - -#if ENABLE_SVG_ICONS - float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; - float scaled_border = m_overlay_border * m_overlay_scale; - float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; - float scaled_stride_y = scaled_icons_size + scaled_gap_y; - float top_y = 0.5f * (cnv_h - height) + scaled_border; -#else - float top_y = 0.5f * (cnv_h - height) + m_overlay_border; - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; -#endif // ENABLE_SVG_ICONS - - for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second == nullptr) || !it->second->is_selectable()) - continue; - -#if ENABLE_SVG_ICONS - bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); -#else - bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); -#endif // ENABLE_SVG_ICONS - if (it->second->is_activable(selection) && inside) - { - if ((it->second->get_state() == GLGizmoBase::On)) - { - it->second->set_state(GLGizmoBase::Hover); - m_current = Undefined; - } - else if ((it->second->get_state() == GLGizmoBase::Hover)) - { - it->second->set_state(GLGizmoBase::On); - m_current = it->first; - } - } - else - it->second->set_state(GLGizmoBase::Off); - -#if ENABLE_SVG_ICONS - top_y += scaled_stride_y; -#else - top_y += (scaled_icons_size + m_overlay_gap_y); -#endif // ENABLE_SVG_ICONS - } - - GizmosMap::iterator it = m_gizmos.find(m_current); - if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On)) - it->second->set_state(GLGizmoBase::On); -} - -void GLCanvas3D::Gizmos::update_on_off_state(const Selection& selection) -{ - GizmosMap::iterator it = m_gizmos.find(m_current); - if ((it != m_gizmos.end()) && (it->second != nullptr)) - { - if (!it->second->is_activable(selection)) - { - it->second->set_state(GLGizmoBase::Off); - m_current = Undefined; - } - } -} - -void GLCanvas3D::Gizmos::reset_all_states() -{ - if (!m_enabled) - return; - - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if (it->second != nullptr) - { - it->second->set_state(GLGizmoBase::Off); - it->second->set_hover_id(-1); - } - } - - m_current = Undefined; -} - -void GLCanvas3D::Gizmos::set_hover_id(int id) -{ - if (!m_enabled) - return; - - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second != nullptr) && (it->second->get_state() == GLGizmoBase::On)) - it->second->set_hover_id(id); - } -} - -void GLCanvas3D::Gizmos::enable_grabber(EType type, unsigned int id, bool enable) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(type); - if (it != m_gizmos.end()) - { - if (enable) - it->second->enable_grabber(id); - else - it->second->disable_grabber(id); - } -} - -bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const -{ - if (!m_enabled) - return false; - - float cnv_h = (float)canvas.get_canvas_size().get_height(); - float height = get_total_overlay_height(); - -#if ENABLE_SVG_ICONS - float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; - float scaled_border = m_overlay_border * m_overlay_scale; - float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; - float scaled_stride_y = scaled_icons_size + scaled_gap_y; - float top_y = 0.5f * (cnv_h - height) + scaled_border; -#else - float top_y = 0.5f * (cnv_h - height) + m_overlay_border; - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; -#endif // ENABLE_SVG_ICONS - - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second == nullptr) || !it->second->is_selectable()) - continue; - -#if ENABLE_SVG_ICONS - if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size)) -#else - if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size)) -#endif // ENABLE_SVG_ICONS - return true; - -#if ENABLE_SVG_ICONS - top_y += scaled_stride_y; -#else - top_y += (scaled_icons_size + m_overlay_gap_y); -#endif // ENABLE_SVG_ICONS - } - - return false; -} - -bool GLCanvas3D::Gizmos::grabber_contains_mouse() const -{ - if (!m_enabled) - return false; - - GLGizmoBase* curr = get_current(); - return (curr != nullptr) ? (curr->get_hover_id() != -1) : false; -} - -void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos) -{ - if (!m_enabled) - return; - - GLGizmoBase* curr = get_current(); - if (curr != nullptr) - curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos, shift_down), selection); -} - -GLCanvas3D::Gizmos::EType GLCanvas3D::Gizmos::get_current_type() const -{ - return m_current; -} - -bool GLCanvas3D::Gizmos::is_running() const -{ - if (!m_enabled) - return false; - - GLGizmoBase* curr = get_current(); - return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false; -} - -bool GLCanvas3D::Gizmos::handle_shortcut(int key, const Selection& selection) -{ - if (!m_enabled || selection.is_empty()) - return false; - - EType old_current = m_current; - bool handled = false; - for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second == nullptr) || !it->second->is_selectable()) - continue; - - int it_key = it->second->get_shortcut_key(); - - if (it->second->is_activable(selection) && ((it_key == key - 64) || (it_key == key - 96))) - { - if ((it->second->get_state() == GLGizmoBase::On)) - { - it->second->set_state(GLGizmoBase::Off); - m_current = Undefined; - handled = true; - } - else if ((it->second->get_state() == GLGizmoBase::Off)) - { - it->second->set_state(GLGizmoBase::On); - m_current = it->first; - handled = true; - } - } - } - - if (handled && (old_current != Undefined) && (old_current != m_current)) - { - GizmosMap::const_iterator it = m_gizmos.find(old_current); - if (it != m_gizmos.end()) - it->second->set_state(GLGizmoBase::Off); - } - - return handled; -} - -bool GLCanvas3D::Gizmos::is_dragging() const -{ - if (!m_enabled) - return false; - - GLGizmoBase* curr = get_current(); - return (curr != nullptr) ? curr->is_dragging() : false; -} - -void GLCanvas3D::Gizmos::start_dragging(const Selection& selection) -{ - if (!m_enabled) - return; - - GLGizmoBase* curr = get_current(); - if (curr != nullptr) - curr->start_dragging(selection); -} - -void GLCanvas3D::Gizmos::stop_dragging() -{ - if (!m_enabled) - return; - - GLGizmoBase* curr = get_current(); - if (curr != nullptr) - curr->stop_dragging(); -} - -Vec3d GLCanvas3D::Gizmos::get_displacement() const -{ - if (!m_enabled) - return Vec3d::Zero(); - - GizmosMap::const_iterator it = m_gizmos.find(Move); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_displacement() : Vec3d::Zero(); -} - -Vec3d GLCanvas3D::Gizmos::get_scale() const -{ - if (!m_enabled) - return Vec3d::Ones(); - - GizmosMap::const_iterator it = m_gizmos.find(Scale); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_scale() : Vec3d::Ones(); -} - -void GLCanvas3D::Gizmos::set_scale(const Vec3d& scale) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(Scale); - if (it != m_gizmos.end()) - reinterpret_cast(it->second)->set_scale(scale); -} - -Vec3d GLCanvas3D::Gizmos::get_rotation() const -{ - if (!m_enabled) - return Vec3d::Zero(); - - GizmosMap::const_iterator it = m_gizmos.find(Rotate); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_rotation() : Vec3d::Zero(); -} - -void GLCanvas3D::Gizmos::set_rotation(const Vec3d& rotation) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(Rotate); - if (it != m_gizmos.end()) - reinterpret_cast(it->second)->set_rotation(rotation); -} - -Vec3d GLCanvas3D::Gizmos::get_flattening_normal() const -{ - if (!m_enabled) - return Vec3d::Zero(); - - GizmosMap::const_iterator it = m_gizmos.find(Flatten); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_flattening_normal() : Vec3d::Zero(); -} - -void GLCanvas3D::Gizmos::set_flattening_data(const ModelObject* model_object) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(Flatten); - if (it != m_gizmos.end()) - reinterpret_cast(it->second)->set_flattening_data(model_object); -} - -void GLCanvas3D::Gizmos::set_sla_support_data(ModelObject* model_object, const Selection& selection) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); - if (it != m_gizmos.end()) - reinterpret_cast(it->second)->set_sla_support_data(model_object, selection); -} - - -// Returns true if the gizmo used the event to do something, false otherwise. -bool GLCanvas3D::Gizmos::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down) -{ - if (!m_enabled) - return false; - - GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); - if (it != m_gizmos.end()) - return reinterpret_cast(it->second)->mouse_event(action, mouse_position, shift_down); - - return false; -} - -void GLCanvas3D::Gizmos::render_current_gizmo(const Selection& selection) const -{ - if (!m_enabled) - return; - - do_render_current_gizmo(selection); -} - -void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const Selection& selection) const -{ - if (!m_enabled) - return; - - GLGizmoBase* curr = get_current(); - if (curr != nullptr) - curr->render_for_picking(selection); -} - -void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const Selection& selection) const -{ - if (!m_enabled) - return; - -#if ENABLE_SVG_ICONS - if (m_icons_texture_dirty) - generate_icons_texture(); -#endif // ENABLE_SVG_ICONS - - ::glDisable(GL_DEPTH_TEST); - - ::glPushMatrix(); - ::glLoadIdentity(); - - do_render_overlay(canvas, selection); - - ::glPopMatrix(); -} - - -void GLCanvas3D::Gizmos::reset() -{ - for (GizmosMap::value_type& gizmo : m_gizmos) - { - delete gizmo.second; - gizmo.second = nullptr; - } - - m_gizmos.clear(); -} - -void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const -{ - if (m_gizmos.empty()) - return; - - float cnv_w = (float)canvas.get_canvas_size().get_width(); - float cnv_h = (float)canvas.get_canvas_size().get_height(); - float zoom = canvas.get_camera_zoom(); - float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - - float height = get_total_overlay_height(); - float width = get_total_overlay_width(); -#if ENABLE_SVG_ICONS - float scaled_border = m_overlay_border * m_overlay_scale * inv_zoom; -#else - float scaled_border = m_overlay_border * inv_zoom; -#endif // ENABLE_SVG_ICONS - - float top_x = (-0.5f * cnv_w) * inv_zoom; - float top_y = (0.5f * height) * inv_zoom; - - float left = top_x; - float top = top_y; - float right = left + width * inv_zoom; - float bottom = top - height * inv_zoom; - - // renders background - unsigned int bg_tex_id = m_background_texture.texture.get_id(); - float bg_tex_width = (float)m_background_texture.texture.get_width(); - float bg_tex_height = (float)m_background_texture.texture.get_height(); - if ((bg_tex_id != 0) && (bg_tex_width > 0) && (bg_tex_height > 0)) - { - float inv_bg_tex_width = (bg_tex_width != 0.0f) ? 1.0f / bg_tex_width : 0.0f; - float inv_bg_tex_height = (bg_tex_height != 0.0f) ? 1.0f / bg_tex_height : 0.0f; - - float bg_uv_left = 0.0f; - float bg_uv_right = 1.0f; - float bg_uv_top = 1.0f; - float bg_uv_bottom = 0.0f; - - float bg_left = left; - float bg_right = right; - float bg_top = top; - float bg_bottom = bottom; - float bg_width = right - left; - float bg_height = top - bottom; - float bg_min_size = std::min(bg_width, bg_height); - - float bg_uv_i_left = (float)m_background_texture.metadata.left * inv_bg_tex_width; - float bg_uv_i_right = 1.0f - (float)m_background_texture.metadata.right * inv_bg_tex_width; - float bg_uv_i_top = 1.0f - (float)m_background_texture.metadata.top * inv_bg_tex_height; - float bg_uv_i_bottom = (float)m_background_texture.metadata.bottom * inv_bg_tex_height; - - float bg_i_left = bg_left + scaled_border; - float bg_i_right = bg_right - scaled_border; - float bg_i_top = bg_top - scaled_border; - float bg_i_bottom = bg_bottom + scaled_border; - - bg_uv_left = bg_uv_i_left; - bg_i_left = bg_left; - - if ((m_overlay_border > 0) && (bg_uv_top != bg_uv_i_top)) - { - if (bg_uv_left != bg_uv_i_left) - GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_top, bg_top, { { bg_uv_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_top }, { bg_uv_left, bg_uv_top } }); - - GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_top, bg_top, { { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_top }, { bg_uv_i_left, bg_uv_top } }); - - if (bg_uv_right != bg_uv_i_right) - GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_top, bg_top, { { bg_uv_i_right, bg_uv_i_top }, { bg_uv_right, bg_uv_i_top }, { bg_uv_right, bg_uv_top }, { bg_uv_i_right, bg_uv_top } }); - } - - if ((m_overlay_border > 0) && (bg_uv_left != bg_uv_i_left)) - GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_bottom, bg_i_top, { { bg_uv_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_left, bg_uv_i_top } }); - - GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_bottom, bg_i_top, { { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top } }); - - if ((m_overlay_border > 0) && (bg_uv_right != bg_uv_i_right)) - GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_bottom, bg_i_top, { { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top } }); - - if ((m_overlay_border > 0) && (bg_uv_bottom != bg_uv_i_bottom)) - { - if (bg_uv_left != bg_uv_i_left) - GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_bottom, bg_i_bottom, { { bg_uv_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_left, bg_uv_i_bottom } }); - - GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_bottom, bg_i_bottom, { { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_right, bg_uv_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom } }); - - if (bg_uv_right != bg_uv_i_right) - GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_bottom, bg_i_bottom, { { bg_uv_i_right, bg_uv_bottom }, { bg_uv_right, bg_uv_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom } }); - } - } - -#if ENABLE_SVG_ICONS - top_x += scaled_border; - top_y -= scaled_border; - float scaled_gap_y = m_overlay_gap_y * m_overlay_scale * inv_zoom; - - float scaled_icons_size = m_overlay_icons_size * m_overlay_scale * inv_zoom; - float scaled_stride_y = scaled_icons_size + scaled_gap_y; - unsigned int icons_texture_id = m_icons_texture.get_id(); - unsigned int tex_width = m_icons_texture.get_width(); - unsigned int tex_height = m_icons_texture.get_height(); - float inv_tex_width = (tex_width != 0) ? 1.0f / (float)tex_width : 0.0f; - float inv_tex_height = (tex_height != 0) ? 1.0f / (float)tex_height : 0.0f; -#else - top_x += m_overlay_border * inv_zoom; - top_y -= m_overlay_border * inv_zoom; - float scaled_gap_y = m_overlay_gap_y * inv_zoom; - - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale * inv_zoom; - unsigned int icons_texture_id = m_icons_texture.texture.get_id(); - unsigned int texture_size = m_icons_texture.texture.get_width(); - float inv_texture_size = (texture_size != 0) ? 1.0f / (float)texture_size : 0.0f; -#endif // ENABLE_SVG_ICONS - -#if ENABLE_SVG_ICONS - if ((icons_texture_id == 0) || (tex_width <= 0) || (tex_height <= 0)) - return; -#endif // ENABLE_SVG_ICONS - - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second == nullptr) || !it->second->is_selectable()) - continue; - - unsigned int sprite_id = it->second->get_sprite_id(); - GLGizmoBase::EState state = it->second->get_state(); - -#if ENABLE_SVG_ICONS - float u_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_width; - float v_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_height; - float v_top = sprite_id * v_icon_size; - float u_left = state * u_icon_size; - float v_bottom = v_top + v_icon_size; - float u_right = u_left + u_icon_size; -#else - float uv_icon_size = (float)m_icons_texture.metadata.icon_size * inv_texture_size; - float v_top = sprite_id * uv_icon_size; - float u_left = state * uv_icon_size; - float v_bottom = v_top + uv_icon_size; - float u_right = u_left + uv_icon_size; -#endif // ENABLE_SVG_ICONS - - GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); - if (it->second->get_state() == GLGizmoBase::On) { - float toolbar_top = (float)cnv_h - canvas.m_view_toolbar.get_height(); -#if ENABLE_SVG_ICONS - it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); -#else - it->second->render_input_window(2.0f * m_overlay_border + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); -#endif // ENABLE_SVG_ICONS - } -#if ENABLE_SVG_ICONS - top_y -= scaled_stride_y; -#else - top_y -= (scaled_icons_size + scaled_gap_y); -#endif // ENABLE_SVG_ICONS - } -} - -void GLCanvas3D::Gizmos::do_render_current_gizmo(const Selection& selection) const -{ - GLGizmoBase* curr = get_current(); - if (curr != nullptr) - curr->render(selection); -} - -float GLCanvas3D::Gizmos::get_total_overlay_height() const -{ -#if ENABLE_SVG_ICONS - float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; - float scaled_border = m_overlay_border * m_overlay_scale; - float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; - float scaled_stride_y = scaled_icons_size + scaled_gap_y; - float height = 2.0f * scaled_border; -#else - float height = 2.0f * m_overlay_border; - - float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; -#endif // ENABLE_SVG_ICONS - - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if ((it->second == nullptr) || !it->second->is_selectable()) - continue; - -#if ENABLE_SVG_ICONS - height += scaled_stride_y; -#else - height += (scaled_icons_size + m_overlay_gap_y); -#endif // ENABLE_SVG_ICONS - } - -#if ENABLE_SVG_ICONS - return height - scaled_gap_y; -#else - return height - m_overlay_gap_y; -#endif // ENABLE_SVG_ICONS -} - -float GLCanvas3D::Gizmos::get_total_overlay_width() const -{ -#if ENABLE_SVG_ICONS - return (2.0f * m_overlay_border + m_overlay_icons_size) * m_overlay_scale; -#else - return (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale + 2.0f * m_overlay_border; -#endif // ENABLE_SVG_ICONS -} - -GLGizmoBase* GLCanvas3D::Gizmos::get_current() const -{ - GizmosMap::const_iterator it = m_gizmos.find(m_current); - return (it != m_gizmos.end()) ? it->second : nullptr; -} - -#if ENABLE_SVG_ICONS -bool GLCanvas3D::Gizmos::generate_icons_texture() const -{ - std::string path = resources_dir() + "/icons/"; - std::vector filenames; - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) - { - if (it->second != nullptr) - { - const std::string& icon_filename = it->second->get_icon_filename(); - if (!icon_filename.empty()) - filenames.push_back(path + icon_filename); - } - } - - std::vector> states; - states.push_back(std::make_pair(1, false)); - states.push_back(std::make_pair(0, false)); - states.push_back(std::make_pair(0, true)); - - bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, (unsigned int)(m_overlay_icons_size * m_overlay_scale)); - if (res) - m_icons_texture_dirty = false; - - return res; -} -#endif // ENABLE_SVG_ICONS - const unsigned char GLCanvas3D::WarningTexture::Background_Color[3] = { 120, 120, 120 };//{ 9, 91, 134 }; const unsigned char GLCanvas3D::WarningTexture::Opacity = 255; @@ -3100,7 +2169,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'a': case 'A': case WXK_CONTROL_A: - if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::SelectAll)) // Sla gizmo selects all support points + if (m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::SelectAll)) // Sla gizmo selects all support points m_dirty = true; else post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL)); @@ -3120,14 +2189,14 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) { // key ESC case WXK_ESCAPE: { - if (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::DiscardChanges)) + if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::DiscardChanges)) m_gizmos.reset_all_states(); m_dirty = true; break; } case WXK_RETURN: { - if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ApplyChanges)) + if (m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ApplyChanges)) m_dirty = true; break; } @@ -3137,8 +2206,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) #else /* __APPLE__ */ case WXK_DELETE: #endif /* __APPLE__ */ - if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::Delete)) - m_dirty = true; + if (m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::Delete)) + m_dirty = true; else post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); break; @@ -3155,7 +2224,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case '?': { post_event(SimpleEvent(EVT_GLCANVAS_QUESTION_MARK)); break; } case 'A': case 'a': { - if (m_gizmos.get_current_type() == Gizmos::SlaSupports) { + if (m_gizmos.get_current_type() == GLGizmosManager::SlaSupports) { if (m_gizmos.mouse_event(SLAGizmoEventType::AutomaticGeneration)) m_dirty = true; } @@ -3173,7 +2242,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 'z': { m_selection.is_empty() ? zoom_to_volumes() : zoom_to_selection(); break; } case 'M': case 'm': { - if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ManualEditing)) { + if (m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ManualEditing)) { m_dirty = true; break; } @@ -3207,7 +2276,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) // Enable switching between 3D and Preview with Tab // m_canvas->HandleAsNavigationKey(evt); // XXX: Doesn't work in some cases / on Linux post_event(SimpleEvent(EVT_GLCANVAS_TAB)); - } else if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp)) { + } else if (m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp)) { // shift has been just released - SLA gizmo might want to close rectangular selection. m_dirty = true; } @@ -3409,7 +2478,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.position = Vec2d(-1.0, -1.0); m_dirty = true; } - else if (evt.LeftDClick() && (m_gizmos.get_current_type() != Gizmos::Undefined)) + else if (evt.LeftDClick() && (m_gizmos.get_current_type() != GLGizmosManager::Undefined)) { m_mouse.ignore_up_event = true; } @@ -3443,7 +2512,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) _update_gizmos_data(); m_dirty = true; } - else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown())) + else if (evt.LeftDown() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown())) { // the gizmo got the event and took some action, there is no need to do anything more } @@ -3453,7 +2522,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_selection.start_dragging(); m_gizmos.start_dragging(m_selection); - if (m_gizmos.get_current_type() == Gizmos::Flatten) { + if (m_gizmos.get_current_type() == GLGizmosManager::Flatten) { // Rotate the object so the normal points downward: m_selection.flattening_rotate(m_gizmos.get_flattening_normal()); do_flatten(); @@ -3462,7 +2531,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } - else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::RightDown)) + else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::RightDown)) { // event was taken care of by the SlaSupports gizmo } @@ -3526,7 +2595,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } } else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown) - && (m_mouse.drag.move_volume_idx != -1) && m_gizmos.get_current_type() != Gizmos::SlaSupports /* don't allow dragging objects with the Sla gizmo on */) + && (m_mouse.drag.move_volume_idx != -1) && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports /* don't allow dragging objects with the Sla gizmo on */) { if (!m_mouse.drag.move_requires_threshold) { @@ -3589,21 +2658,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) switch (m_gizmos.get_current_type()) { - case Gizmos::Move: + case GLGizmosManager::Move: { // Apply new temporary offset m_selection.translate(m_gizmos.get_displacement()); wxGetApp().obj_manipul()->update_settings_value(m_selection); break; } - case Gizmos::Scale: + case GLGizmosManager::Scale: { // Apply new temporary scale factors m_selection.scale(m_gizmos.get_scale(), evt.AltDown()); wxGetApp().obj_manipul()->update_settings_value(m_selection); break; } - case Gizmos::Rotate: + case GLGizmosManager::Rotate: { // Apply new temporary rotations TransformationType transformation_type(TransformationType::World_Relative_Joint); @@ -3619,7 +2688,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } - else if (evt.Dragging() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::Dragging, Vec2d(pos(0), pos(1)), evt.ShiftDown())) + else if (evt.Dragging() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::Dragging, Vec2d(pos(0), pos(1)), evt.ShiftDown())) { // the gizmo got the event and took some action, no need to do anything more here m_dirty = true; @@ -3671,12 +2740,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) _stop_timer(); m_layers_editing.accept_changes(*this); } - else if (evt.LeftUp() && m_gizmos.get_current_type() == Gizmos::SlaSupports && !m_gizmos.is_dragging() - && !m_mouse.dragging && m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown())) + else if (evt.LeftUp() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && !m_gizmos.is_dragging() + && !m_mouse.dragging && m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown())) { // the gizmo got the event and took some action, no need to do anything more } - else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging && m_gizmos.get_current_type() != Gizmos::SlaSupports) + else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports) { m_regenerate_volumes = false; do_move(); @@ -3686,7 +2755,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); } else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() - && !is_layers_editing_enabled() && (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown()))) + && !is_layers_editing_enabled() && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown()))) { // SLA gizmo cannot be deselected by clicking in canvas area to avoid inadvertent unselection and losing manual changes // that's why the mouse_event function was called so that the gizmo can refuse the deselection in manual editing mode @@ -3707,18 +2776,18 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { switch (m_gizmos.get_current_type()) { - case Gizmos::Move: + case GLGizmosManager::Move: { m_regenerate_volumes = false; do_move(); break; } - case Gizmos::Scale: + case GLGizmosManager::Scale: { do_scale(); break; } - case Gizmos::Rotate: + case GLGizmosManager::Rotate: { do_rotate(); break; @@ -3746,7 +2815,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // if right clicking on volume, propagate event through callback (shows context menu) if (m_volumes.volumes[m_hover_volume_id]->hover && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower // no context menu for the wipe tower - && m_gizmos.get_current_type() != Gizmos::SlaSupports) // disable context menu when the gizmo is open + && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports) // disable context menu when the gizmo is open { // forces the selection of the volume m_selection.add(m_hover_volume_id); @@ -5058,11 +4127,11 @@ void GLCanvas3D::_update_gizmos_data() return; bool enable_move_z = !m_selection.is_wipe_tower(); - m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); + m_gizmos.enable_grabber(GLGizmosManager::Move, 2, enable_move_z); bool enable_scale_xyz = m_selection.is_single_full_instance() || m_selection.is_single_volume() || m_selection.is_single_modifier(); for (int i = 0; i < 6; ++i) { - m_gizmos.enable_grabber(Gizmos::Scale, i, enable_scale_xyz); + m_gizmos.enable_grabber(GLGizmosManager::Scale, i, enable_scale_xyz); } if (m_selection.is_single_full_instance()) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 4cbabc438..bc9932e75 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -10,6 +10,7 @@ #include "3DBed.hpp" #include "Camera.hpp" #include "Selection.hpp" +#include "Gizmos/GLGizmosManager.hpp" #include @@ -64,33 +65,6 @@ public: void set_scale_factor(int height); }; -class Rect -{ - float m_left; - float m_top; - float m_right; - float m_bottom; - -public: - Rect(); - Rect(float left, float top, float right, float bottom); - - float get_left() const; - void set_left(float left); - - float get_top() const; - void set_top(float top); - - float get_right() const; - void set_right(float right); - - float get_bottom() const; - void set_bottom(float bottom); - - float get_width() const { return m_right - m_left; } - float get_height() const { return m_top - m_bottom; } -}; - wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); using Vec2dEvent = Event; @@ -117,22 +91,6 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent); -// this describes events being passed from GLCanvas3D to SlaSupport gizmo -enum class SLAGizmoEventType { - LeftDown = 1, - LeftUp, - RightDown, - Dragging, - Delete, - SelectAll, - ShiftUp, - ApplyChanges, - DiscardChanges, - AutomaticGeneration, - ManualEditing -}; - - class GLCanvas3D { struct GCodePreviewVolumeIndex @@ -357,119 +315,6 @@ public: }; private: - class Gizmos - { - public: -#if ENABLE_SVG_ICONS - static const float Default_Icons_Size; -#endif // ENABLE_SVG_ICONS - - enum EType : unsigned char - { - Undefined, - Move, - Scale, - Rotate, - Flatten, - Cut, - SlaSupports, - Num_Types - }; - - private: - bool m_enabled; - typedef std::map GizmosMap; - GizmosMap m_gizmos; -#if ENABLE_SVG_ICONS - mutable GLTexture m_icons_texture; - mutable bool m_icons_texture_dirty; -#else - ItemsIconsTexture m_icons_texture; -#endif // ENABLE_SVG_ICONS - BackgroundTexture m_background_texture; - EType m_current; - -#if ENABLE_SVG_ICONS - float m_overlay_icons_size; - float m_overlay_scale; -#else - float m_overlay_icons_scale; -#endif // ENABLE_SVG_ICONS - float m_overlay_border; - float m_overlay_gap_y; - - public: - Gizmos(); - ~Gizmos(); - - bool init(GLCanvas3D& parent); - - bool is_enabled() const; - void set_enabled(bool enable); - -#if ENABLE_SVG_ICONS - void set_overlay_icon_size(float size); -#endif // ENABLE_SVG_ICONS - void set_overlay_scale(float scale); - - std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); - void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); - void update_on_off_state(const Selection& selection); - void reset_all_states(); - - void set_hover_id(int id); - void enable_grabber(EType type, unsigned int id, bool enable); - - bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; - bool grabber_contains_mouse() const; - void update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos = nullptr); - Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const; - EType get_current_type() const; - - bool is_running() const; - bool handle_shortcut(int key, const Selection& selection); - - bool is_dragging() const; - void start_dragging(const Selection& selection); - void stop_dragging(); - - Vec3d get_displacement() const; - - Vec3d get_scale() const; - void set_scale(const Vec3d& scale); - - Vec3d get_rotation() const; - void set_rotation(const Vec3d& rotation); - - Vec3d get_flattening_normal() const; - - void set_flattening_data(const ModelObject* model_object); - - void set_sla_support_data(ModelObject* model_object, const Selection& selection); - bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false); - void delete_current_grabber(bool delete_all = false); - - void render_current_gizmo(const Selection& selection) const; - void render_current_gizmo_for_picking_pass(const Selection& selection) const; - - void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; - - private: - void reset(); - - void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; - void do_render_current_gizmo(const Selection& selection) const; - - float get_total_overlay_height() const; - float get_total_overlay_width() const; - - GLGizmoBase* get_current() const; - -#if ENABLE_SVG_ICONS - bool generate_icons_texture() const; -#endif // ENABLE_SVG_ICONS - }; - struct SlaCap { struct Triangles @@ -557,7 +402,7 @@ private: LayersEditing m_layers_editing; Shader m_shader; Mouse m_mouse; - mutable Gizmos m_gizmos; + mutable GLGizmosManager m_gizmos; mutable GLToolbar m_toolbar; ClippingPlane m_clipping_planes[2]; bool m_use_clipping_planes; @@ -715,6 +560,8 @@ public: void update_ui_from_settings(); + float get_view_toolbar_height() const { return m_view_toolbar.get_height(); } + private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 1e12674ec..ee22b994f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -1,4 +1,5 @@ #include "GLGizmoBase.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" #include diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index b70c1f8df..461f65570 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -3,7 +3,6 @@ #include "libslic3r/Point.hpp" -#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/Selection.hpp" diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index e228706c0..30cc1527f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -1,5 +1,6 @@ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. #include "GLGizmoCut.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" #include diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index cd7e3b985..8ac2405ec 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -1,5 +1,6 @@ // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. #include "GLGizmoSlaSupports.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" #include diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index c27ff0b6d..8edfbe2cb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -2,6 +2,7 @@ #define slic3r_GLGizmoSlaSupports_hpp_ #include "GLGizmoBase.hpp" +#include "GLGizmos.hpp" // There is an L function in igl that would be overridden by our localization macro - let's undefine it... #undef L diff --git a/src/slic3r/GUI/Gizmos/GLGizmos.hpp b/src/slic3r/GUI/Gizmos/GLGizmos.hpp index 8c5e25669..c45b7648d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmos.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmos.hpp @@ -1,6 +1,21 @@ #ifndef slic3r_GLGizmos_hpp_ #define slic3r_GLGizmos_hpp_ +// this describes events being passed from GLCanvas3D to SlaSupport gizmo +enum class SLAGizmoEventType { + LeftDown = 1, + LeftUp, + RightDown, + Dragging, + Delete, + SelectAll, + ShiftUp, + ApplyChanges, + DiscardChanges, + AutomaticGeneration, + ManualEditing +}; + #include "slic3r/GUI/Gizmos/GLGizmoMove.hpp" #include "slic3r/GUI/Gizmos/GLGizmoScale.hpp" #include "slic3r/GUI/Gizmos/GLGizmoRotate.hpp" diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp new file mode 100644 index 000000000..0a7cacd30 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -0,0 +1,865 @@ +#include "libslic3r/libslic3r.h" +#include "GLGizmosManager.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" +#include "slic3r/GUI/3DScene.hpp" + +#include + +namespace Slic3r { +namespace GUI { + +#if ENABLE_SVG_ICONS + const float GLGizmosManager::Default_Icons_Size = 64; +#endif // ENABLE_SVG_ICONS + +GLGizmosManager::GLGizmosManager() + : m_enabled(false) +#if ENABLE_SVG_ICONS + , m_icons_texture_dirty(true) +#endif // ENABLE_SVG_ICONS + , m_current(Undefined) +#if ENABLE_SVG_ICONS + , m_overlay_icons_size(Default_Icons_Size) + , m_overlay_scale(1.0f) + , m_overlay_border(5.0f) + , m_overlay_gap_y(5.0f) +{ +} +#else +{ + set_overlay_scale(1.0); +} +#endif // ENABLE_SVG_ICONS + +GLGizmosManager::~GLGizmosManager() +{ + reset(); +} + +bool GLGizmosManager::init(GLCanvas3D& parent) +{ +#if !ENABLE_SVG_ICONS + m_icons_texture.metadata.filename = "gizmos.png"; + m_icons_texture.metadata.icon_size = 64; + + if (!m_icons_texture.metadata.filename.empty()) + { + if (!m_icons_texture.texture.load_from_file(resources_dir() + "/icons/" + m_icons_texture.metadata.filename, false)) + { + reset(); + return false; + } + } +#endif // !ENABLE_SVG_ICONS + + m_background_texture.metadata.filename = "toolbar_background.png"; + m_background_texture.metadata.left = 16; + m_background_texture.metadata.top = 16; + m_background_texture.metadata.right = 16; + m_background_texture.metadata.bottom = 16; + + if (!m_background_texture.metadata.filename.empty()) + { + if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false)) + { + reset(); + return false; + } + } + +#if ENABLE_SVG_ICONS + GLGizmoBase* gizmo = new GLGizmoMove3D(parent, "move.svg", 0); +#else + GLGizmoBase* gizmo = new GLGizmoMove3D(parent, 0); +#endif // ENABLE_SVG_ICONS + if (gizmo == nullptr) + return false; + + if (!gizmo->init()) + return false; + + m_gizmos.insert(GizmosMap::value_type(Move, gizmo)); + +#if ENABLE_SVG_ICONS + gizmo = new GLGizmoScale3D(parent, "scale.svg", 1); +#else + gizmo = new GLGizmoScale3D(parent, 1); +#endif // ENABLE_SVG_ICONS + if (gizmo == nullptr) + return false; + + if (!gizmo->init()) + return false; + + m_gizmos.insert(GizmosMap::value_type(Scale, gizmo)); + +#if ENABLE_SVG_ICONS + gizmo = new GLGizmoRotate3D(parent, "rotate.svg", 2); +#else + gizmo = new GLGizmoRotate3D(parent, 2); +#endif // ENABLE_SVG_ICONS + if (gizmo == nullptr) + { + reset(); + return false; + } + + if (!gizmo->init()) + { + reset(); + return false; + } + + m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo)); + +#if ENABLE_SVG_ICONS + gizmo = new GLGizmoFlatten(parent, "place.svg", 3); +#else + gizmo = new GLGizmoFlatten(parent, 3); +#endif // ENABLE_SVG_ICONS + if (gizmo == nullptr) + return false; + + if (!gizmo->init()) { + reset(); + return false; + } + + m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo)); + +#if ENABLE_SVG_ICONS + gizmo = new GLGizmoCut(parent, "cut.svg", 4); +#else + gizmo = new GLGizmoCut(parent, 4); +#endif // ENABLE_SVG_ICONS + if (gizmo == nullptr) + return false; + + if (!gizmo->init()) { + reset(); + return false; + } + + m_gizmos.insert(GizmosMap::value_type(Cut, gizmo)); + +#if ENABLE_SVG_ICONS + gizmo = new GLGizmoSlaSupports(parent, "sla_supports.svg", 5); +#else + gizmo = new GLGizmoSlaSupports(parent, 5); +#endif // ENABLE_SVG_ICONS + if (gizmo == nullptr) + return false; + + if (!gizmo->init()) { + reset(); + return false; + } + + m_gizmos.insert(GizmosMap::value_type(SlaSupports, gizmo)); + + return true; +} + +#if ENABLE_SVG_ICONS +void GLGizmosManager::set_overlay_icon_size(float size) +{ + if (m_overlay_icons_size != size) + { + m_overlay_icons_size = size; + m_icons_texture_dirty = true; + } +} +#endif // ENABLE_SVG_ICONS + +void GLGizmosManager::set_overlay_scale(float scale) +{ +#if ENABLE_SVG_ICONS + if (m_overlay_scale != scale) + { + m_overlay_scale = scale; + m_icons_texture_dirty = true; + } +#else + m_overlay_icons_scale = scale; + m_overlay_border = 5.0f * scale; + m_overlay_gap_y = 5.0f * scale; +#endif // ENABLE_SVG_ICONS +} + +std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection) +{ + std::string name = ""; + + if (!m_enabled) + return name; + + float cnv_h = (float)canvas.get_canvas_size().get_height(); + float height = get_total_overlay_height(); +#if ENABLE_SVG_ICONS + float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; + float scaled_border = m_overlay_border * m_overlay_scale; + float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; + float scaled_stride_y = scaled_icons_size + scaled_gap_y; + float top_y = 0.5f * (cnv_h - height) + scaled_border; +#else + float top_y = 0.5f * (cnv_h - height) + m_overlay_border; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; +#endif // ENABLE_SVG_ICONS + + for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second == nullptr) || !it->second->is_selectable()) + continue; + +#if ENABLE_SVG_ICONS + bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); +#else + bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); +#endif // ENABLE_SVG_ICONS + if (inside) + name = it->second->get_name(); + + if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On)) + it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); + +#if ENABLE_SVG_ICONS + top_y += scaled_stride_y; +#else + top_y += (scaled_icons_size + m_overlay_gap_y); +#endif // ENABLE_SVG_ICONS + } + + return name; +} + +void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection) +{ + if (!m_enabled) + return; + + float cnv_h = (float)canvas.get_canvas_size().get_height(); + float height = get_total_overlay_height(); + +#if ENABLE_SVG_ICONS + float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; + float scaled_border = m_overlay_border * m_overlay_scale; + float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; + float scaled_stride_y = scaled_icons_size + scaled_gap_y; + float top_y = 0.5f * (cnv_h - height) + scaled_border; +#else + float top_y = 0.5f * (cnv_h - height) + m_overlay_border; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; +#endif // ENABLE_SVG_ICONS + + for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second == nullptr) || !it->second->is_selectable()) + continue; + +#if ENABLE_SVG_ICONS + bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); +#else + bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size); +#endif // ENABLE_SVG_ICONS + if (it->second->is_activable(selection) && inside) + { + if ((it->second->get_state() == GLGizmoBase::On)) + { + it->second->set_state(GLGizmoBase::Hover); + m_current = Undefined; + } + else if ((it->second->get_state() == GLGizmoBase::Hover)) + { + it->second->set_state(GLGizmoBase::On); + m_current = it->first; + } + } + else + it->second->set_state(GLGizmoBase::Off); + +#if ENABLE_SVG_ICONS + top_y += scaled_stride_y; +#else + top_y += (scaled_icons_size + m_overlay_gap_y); +#endif // ENABLE_SVG_ICONS + } + + GizmosMap::iterator it = m_gizmos.find(m_current); + if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On)) + it->second->set_state(GLGizmoBase::On); +} + +void GLGizmosManager::update_on_off_state(const Selection& selection) +{ + GizmosMap::iterator it = m_gizmos.find(m_current); + if ((it != m_gizmos.end()) && (it->second != nullptr)) + { + if (!it->second->is_activable(selection)) + { + it->second->set_state(GLGizmoBase::Off); + m_current = Undefined; + } + } +} + +void GLGizmosManager::reset_all_states() +{ + if (!m_enabled) + return; + + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if (it->second != nullptr) + { + it->second->set_state(GLGizmoBase::Off); + it->second->set_hover_id(-1); + } + } + + m_current = Undefined; +} + +void GLGizmosManager::set_hover_id(int id) +{ + if (!m_enabled) + return; + + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second != nullptr) && (it->second->get_state() == GLGizmoBase::On)) + it->second->set_hover_id(id); + } +} + +void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(type); + if (it != m_gizmos.end()) + { + if (enable) + it->second->enable_grabber(id); + else + it->second->disable_grabber(id); + } +} + +bool GLGizmosManager::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const +{ + if (!m_enabled) + return false; + + float cnv_h = (float)canvas.get_canvas_size().get_height(); + float height = get_total_overlay_height(); + +#if ENABLE_SVG_ICONS + float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; + float scaled_border = m_overlay_border * m_overlay_scale; + float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; + float scaled_stride_y = scaled_icons_size + scaled_gap_y; + float top_y = 0.5f * (cnv_h - height) + scaled_border; +#else + float top_y = 0.5f * (cnv_h - height) + m_overlay_border; + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; +#endif // ENABLE_SVG_ICONS + + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second == nullptr) || !it->second->is_selectable()) + continue; + +#if ENABLE_SVG_ICONS + if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size)) +#else + if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size)) +#endif // ENABLE_SVG_ICONS + return true; + +#if ENABLE_SVG_ICONS + top_y += scaled_stride_y; +#else + top_y += (scaled_icons_size + m_overlay_gap_y); +#endif // ENABLE_SVG_ICONS + } + + return false; +} + +bool GLGizmosManager::grabber_contains_mouse() const +{ + if (!m_enabled) + return false; + + GLGizmoBase* curr = get_current(); + return (curr != nullptr) ? (curr->get_hover_id() != -1) : false; +} + +void GLGizmosManager::update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos) +{ + if (!m_enabled) + return; + + GLGizmoBase* curr = get_current(); + if (curr != nullptr) + curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos, shift_down), selection); +} + +bool GLGizmosManager::is_running() const +{ + if (!m_enabled) + return false; + + GLGizmoBase* curr = get_current(); + return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false; +} + +bool GLGizmosManager::handle_shortcut(int key, const Selection& selection) +{ + if (!m_enabled || selection.is_empty()) + return false; + + EType old_current = m_current; + bool handled = false; + for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second == nullptr) || !it->second->is_selectable()) + continue; + + int it_key = it->second->get_shortcut_key(); + + if (it->second->is_activable(selection) && ((it_key == key - 64) || (it_key == key - 96))) + { + if ((it->second->get_state() == GLGizmoBase::On)) + { + it->second->set_state(GLGizmoBase::Off); + m_current = Undefined; + handled = true; + } + else if ((it->second->get_state() == GLGizmoBase::Off)) + { + it->second->set_state(GLGizmoBase::On); + m_current = it->first; + handled = true; + } + } + } + + if (handled && (old_current != Undefined) && (old_current != m_current)) + { + GizmosMap::const_iterator it = m_gizmos.find(old_current); + if (it != m_gizmos.end()) + it->second->set_state(GLGizmoBase::Off); + } + + return handled; +} + +bool GLGizmosManager::is_dragging() const +{ + if (!m_enabled) + return false; + + GLGizmoBase* curr = get_current(); + return (curr != nullptr) ? curr->is_dragging() : false; +} + +void GLGizmosManager::start_dragging(const Selection& selection) +{ + if (!m_enabled) + return; + + GLGizmoBase* curr = get_current(); + if (curr != nullptr) + curr->start_dragging(selection); +} + +void GLGizmosManager::stop_dragging() +{ + if (!m_enabled) + return; + + GLGizmoBase* curr = get_current(); + if (curr != nullptr) + curr->stop_dragging(); +} + +Vec3d GLGizmosManager::get_displacement() const +{ + if (!m_enabled) + return Vec3d::Zero(); + + GizmosMap::const_iterator it = m_gizmos.find(Move); + return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_displacement() : Vec3d::Zero(); +} + +Vec3d GLGizmosManager::get_scale() const +{ + if (!m_enabled) + return Vec3d::Ones(); + + GizmosMap::const_iterator it = m_gizmos.find(Scale); + return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_scale() : Vec3d::Ones(); +} + +void GLGizmosManager::set_scale(const Vec3d& scale) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(Scale); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->set_scale(scale); +} + +Vec3d GLGizmosManager::get_rotation() const +{ + if (!m_enabled) + return Vec3d::Zero(); + + GizmosMap::const_iterator it = m_gizmos.find(Rotate); + return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_rotation() : Vec3d::Zero(); +} + +void GLGizmosManager::set_rotation(const Vec3d& rotation) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(Rotate); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->set_rotation(rotation); +} + +Vec3d GLGizmosManager::get_flattening_normal() const +{ + if (!m_enabled) + return Vec3d::Zero(); + + GizmosMap::const_iterator it = m_gizmos.find(Flatten); + return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_flattening_normal() : Vec3d::Zero(); +} + +void GLGizmosManager::set_flattening_data(const ModelObject* model_object) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(Flatten); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->set_flattening_data(model_object); +} + +void GLGizmosManager::set_sla_support_data(ModelObject* model_object, const Selection& selection) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->set_sla_support_data(model_object, selection); +} + +// Returns true if the gizmo used the event to do something, false otherwise. +bool GLGizmosManager::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down) +{ + if (!m_enabled) + return false; + + GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); + if (it != m_gizmos.end()) + return reinterpret_cast(it->second)->mouse_event(action, mouse_position, shift_down); + + return false; +} + +void GLGizmosManager::render_current_gizmo(const Selection& selection) const +{ + if (!m_enabled) + return; + + GLGizmoBase* curr = get_current(); + if (curr != nullptr) + curr->render(selection); +} + +void GLGizmosManager::render_current_gizmo_for_picking_pass(const Selection& selection) const +{ + if (!m_enabled) + return; + + GLGizmoBase* curr = get_current(); + if (curr != nullptr) + curr->render_for_picking(selection); +} + +void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection& selection) const +{ + if (!m_enabled) + return; + +#if ENABLE_SVG_ICONS + if (m_icons_texture_dirty) + generate_icons_texture(); +#endif // ENABLE_SVG_ICONS + + glsafe(::glDisable(GL_DEPTH_TEST)); + + glsafe(::glPushMatrix()); + glsafe(::glLoadIdentity()); + + do_render_overlay(canvas, selection); + + glsafe(::glPopMatrix()); +} + +void GLGizmosManager::reset() +{ + for (GizmosMap::value_type& gizmo : m_gizmos) + { + delete gizmo.second; + gizmo.second = nullptr; + } + + m_gizmos.clear(); +} + +void GLGizmosManager::do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const +{ + if (m_gizmos.empty()) + return; + + float cnv_w = (float)canvas.get_canvas_size().get_width(); + float cnv_h = (float)canvas.get_canvas_size().get_height(); + float zoom = canvas.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + + float height = get_total_overlay_height(); + float width = get_total_overlay_width(); +#if ENABLE_SVG_ICONS + float scaled_border = m_overlay_border * m_overlay_scale * inv_zoom; +#else + float scaled_border = m_overlay_border * inv_zoom; +#endif // ENABLE_SVG_ICONS + + float top_x = (-0.5f * cnv_w) * inv_zoom; + float top_y = (0.5f * height) * inv_zoom; + + float left = top_x; + float top = top_y; + float right = left + width * inv_zoom; + float bottom = top - height * inv_zoom; + + // renders background + unsigned int bg_tex_id = m_background_texture.texture.get_id(); + float bg_tex_width = (float)m_background_texture.texture.get_width(); + float bg_tex_height = (float)m_background_texture.texture.get_height(); + if ((bg_tex_id != 0) && (bg_tex_width > 0) && (bg_tex_height > 0)) + { + float inv_bg_tex_width = (bg_tex_width != 0.0f) ? 1.0f / bg_tex_width : 0.0f; + float inv_bg_tex_height = (bg_tex_height != 0.0f) ? 1.0f / bg_tex_height : 0.0f; + + float bg_uv_left = 0.0f; + float bg_uv_right = 1.0f; + float bg_uv_top = 1.0f; + float bg_uv_bottom = 0.0f; + + float bg_left = left; + float bg_right = right; + float bg_top = top; + float bg_bottom = bottom; + float bg_width = right - left; + float bg_height = top - bottom; + float bg_min_size = std::min(bg_width, bg_height); + + float bg_uv_i_left = (float)m_background_texture.metadata.left * inv_bg_tex_width; + float bg_uv_i_right = 1.0f - (float)m_background_texture.metadata.right * inv_bg_tex_width; + float bg_uv_i_top = 1.0f - (float)m_background_texture.metadata.top * inv_bg_tex_height; + float bg_uv_i_bottom = (float)m_background_texture.metadata.bottom * inv_bg_tex_height; + + float bg_i_left = bg_left + scaled_border; + float bg_i_right = bg_right - scaled_border; + float bg_i_top = bg_top - scaled_border; + float bg_i_bottom = bg_bottom + scaled_border; + + bg_uv_left = bg_uv_i_left; + bg_i_left = bg_left; + + if ((m_overlay_border > 0) && (bg_uv_top != bg_uv_i_top)) + { + if (bg_uv_left != bg_uv_i_left) + GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_top, bg_top, { { bg_uv_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_left, bg_uv_top }, { bg_uv_left, bg_uv_top } }); + + GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_top, bg_top, { { bg_uv_i_left, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_top }, { bg_uv_i_left, bg_uv_top } }); + + if (bg_uv_right != bg_uv_i_right) + GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_top, bg_top, { { bg_uv_i_right, bg_uv_i_top }, { bg_uv_right, bg_uv_i_top }, { bg_uv_right, bg_uv_top }, { bg_uv_i_right, bg_uv_top } }); + } + + if ((m_overlay_border > 0) && (bg_uv_left != bg_uv_i_left)) + GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_i_bottom, bg_i_top, { { bg_uv_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_top }, { bg_uv_left, bg_uv_i_top } }); + + GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_i_bottom, bg_i_top, { { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_top }, { bg_uv_i_left, bg_uv_i_top } }); + + if ((m_overlay_border > 0) && (bg_uv_right != bg_uv_i_right)) + GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_i_bottom, bg_i_top, { { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_right, bg_uv_i_top }, { bg_uv_i_right, bg_uv_i_top } }); + + if ((m_overlay_border > 0) && (bg_uv_bottom != bg_uv_i_bottom)) + { + if (bg_uv_left != bg_uv_i_left) + GLTexture::render_sub_texture(bg_tex_id, bg_left, bg_i_left, bg_bottom, bg_i_bottom, { { bg_uv_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_left, bg_uv_i_bottom }, { bg_uv_left, bg_uv_i_bottom } }); + + GLTexture::render_sub_texture(bg_tex_id, bg_i_left, bg_i_right, bg_bottom, bg_i_bottom, { { bg_uv_i_left, bg_uv_bottom }, { bg_uv_i_right, bg_uv_bottom }, { bg_uv_i_right, bg_uv_i_bottom }, { bg_uv_i_left, bg_uv_i_bottom } }); + + if (bg_uv_right != bg_uv_i_right) + GLTexture::render_sub_texture(bg_tex_id, bg_i_right, bg_right, bg_bottom, bg_i_bottom, { { bg_uv_i_right, bg_uv_bottom }, { bg_uv_right, bg_uv_bottom }, { bg_uv_right, bg_uv_i_bottom }, { bg_uv_i_right, bg_uv_i_bottom } }); + } + } + +#if ENABLE_SVG_ICONS + top_x += scaled_border; + top_y -= scaled_border; + float scaled_gap_y = m_overlay_gap_y * m_overlay_scale * inv_zoom; + + float scaled_icons_size = m_overlay_icons_size * m_overlay_scale * inv_zoom; + float scaled_stride_y = scaled_icons_size + scaled_gap_y; + unsigned int icons_texture_id = m_icons_texture.get_id(); + unsigned int tex_width = m_icons_texture.get_width(); + unsigned int tex_height = m_icons_texture.get_height(); + float inv_tex_width = (tex_width != 0) ? 1.0f / (float)tex_width : 0.0f; + float inv_tex_height = (tex_height != 0) ? 1.0f / (float)tex_height : 0.0f; +#else + top_x += m_overlay_border * inv_zoom; + top_y -= m_overlay_border * inv_zoom; + float scaled_gap_y = m_overlay_gap_y * inv_zoom; + + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale * inv_zoom; + unsigned int icons_texture_id = m_icons_texture.texture.get_id(); + unsigned int texture_size = m_icons_texture.texture.get_width(); + float inv_texture_size = (texture_size != 0) ? 1.0f / (float)texture_size : 0.0f; +#endif // ENABLE_SVG_ICONS + +#if ENABLE_SVG_ICONS + if ((icons_texture_id == 0) || (tex_width <= 0) || (tex_height <= 0)) + return; +#endif // ENABLE_SVG_ICONS + + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second == nullptr) || !it->second->is_selectable()) + continue; + + unsigned int sprite_id = it->second->get_sprite_id(); + GLGizmoBase::EState state = it->second->get_state(); + +#if ENABLE_SVG_ICONS + float u_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_width; + float v_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_height; + float v_top = sprite_id * v_icon_size; + float u_left = state * u_icon_size; + float v_bottom = v_top + v_icon_size; + float u_right = u_left + u_icon_size; +#else + float uv_icon_size = (float)m_icons_texture.metadata.icon_size * inv_texture_size; + float v_top = sprite_id * uv_icon_size; + float u_left = state * uv_icon_size; + float v_bottom = v_top + uv_icon_size; + float u_right = u_left + uv_icon_size; +#endif // ENABLE_SVG_ICONS + + GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); + if (it->second->get_state() == GLGizmoBase::On) { + float toolbar_top = (float)cnv_h - canvas.get_view_toolbar_height(); +#if ENABLE_SVG_ICONS + it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); +#else + it->second->render_input_window(2.0f * m_overlay_border + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); +#endif // ENABLE_SVG_ICONS + } +#if ENABLE_SVG_ICONS + top_y -= scaled_stride_y; +#else + top_y -= (scaled_icons_size + scaled_gap_y); +#endif // ENABLE_SVG_ICONS + } +} + +float GLGizmosManager::get_total_overlay_height() const +{ +#if ENABLE_SVG_ICONS + float scaled_icons_size = m_overlay_icons_size * m_overlay_scale; + float scaled_border = m_overlay_border * m_overlay_scale; + float scaled_gap_y = m_overlay_gap_y * m_overlay_scale; + float scaled_stride_y = scaled_icons_size + scaled_gap_y; + float height = 2.0f * scaled_border; +#else + float height = 2.0f * m_overlay_border; + + float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale; +#endif // ENABLE_SVG_ICONS + + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if ((it->second == nullptr) || !it->second->is_selectable()) + continue; + +#if ENABLE_SVG_ICONS + height += scaled_stride_y; +#else + height += (scaled_icons_size + m_overlay_gap_y); +#endif // ENABLE_SVG_ICONS + } + +#if ENABLE_SVG_ICONS + return height - scaled_gap_y; +#else + return height - m_overlay_gap_y; +#endif // ENABLE_SVG_ICONS +} + +float GLGizmosManager::get_total_overlay_width() const +{ +#if ENABLE_SVG_ICONS + return (2.0f * m_overlay_border + m_overlay_icons_size) * m_overlay_scale; +#else + return (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale + 2.0f * m_overlay_border; +#endif // ENABLE_SVG_ICONS +} + +GLGizmoBase* GLGizmosManager::get_current() const +{ + GizmosMap::const_iterator it = m_gizmos.find(m_current); + return (it != m_gizmos.end()) ? it->second : nullptr; +} + +#if ENABLE_SVG_ICONS +bool GLGizmosManager::generate_icons_texture() const +{ + std::string path = resources_dir() + "/icons/"; + std::vector filenames; + for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + { + if (it->second != nullptr) + { + const std::string& icon_filename = it->second->get_icon_filename(); + if (!icon_filename.empty()) + filenames.push_back(path + icon_filename); + } + } + + std::vector> states; + states.push_back(std::make_pair(1, false)); + states.push_back(std::make_pair(0, false)); + states.push_back(std::make_pair(0, true)); + + bool res = m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, (unsigned int)(m_overlay_icons_size * m_overlay_scale)); + if (res) + m_icons_texture_dirty = false; + + return res; +} +#endif // ENABLE_SVG_ICONS + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp new file mode 100644 index 000000000..0dcb9c774 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -0,0 +1,160 @@ +#ifndef slic3r_GUI_GLGizmosManager_hpp_ +#define slic3r_GUI_GLGizmosManager_hpp_ + +#include "slic3r/GUI/GLTexture.hpp" +#include "slic3r/GUI/GLToolbar.hpp" +#include "slic3r/GUI/Gizmos/GLGizmos.hpp" + +#include + +namespace Slic3r { +namespace GUI { + +class Selection; +class GLGizmoBase; +class GLCanvas3D; + +class Rect +{ + float m_left; + float m_top; + float m_right; + float m_bottom; + +public: + Rect() : m_left(0.0f) , m_top(0.0f) , m_right(0.0f) , m_bottom(0.0f) {} + + Rect::Rect(float left, float top, float right, float bottom) : m_left(left) , m_top(top) , m_right(right) , m_bottom(bottom) {} + + float get_left() const { return m_left; } + void set_left(float left) { m_left = left; } + + float get_top() const { return m_top; } + void set_top(float top) { m_top = top; } + + float get_right() const { return m_right; } + void set_right(float right) { m_right = right; } + + float get_bottom() const { return m_bottom; } + void set_bottom(float bottom) { m_bottom = bottom; } + + float get_width() const { return m_right - m_left; } + float get_height() const { return m_top - m_bottom; } +}; + +class GLGizmosManager +{ +public: +#if ENABLE_SVG_ICONS + static const float Default_Icons_Size; +#endif // ENABLE_SVG_ICONS + + enum EType : unsigned char + { + Undefined, + Move, + Scale, + Rotate, + Flatten, + Cut, + SlaSupports, + Num_Types + }; + +private: + bool m_enabled; + typedef std::map GizmosMap; + GizmosMap m_gizmos; +#if ENABLE_SVG_ICONS + mutable GLTexture m_icons_texture; + mutable bool m_icons_texture_dirty; +#else + ItemsIconsTexture m_icons_texture; +#endif // ENABLE_SVG_ICONS + BackgroundTexture m_background_texture; + EType m_current; + +#if ENABLE_SVG_ICONS + float m_overlay_icons_size; + float m_overlay_scale; +#else + float m_overlay_icons_scale; +#endif // ENABLE_SVG_ICONS + float m_overlay_border; + float m_overlay_gap_y; + +public: + GLGizmosManager(); + ~GLGizmosManager(); + + bool init(GLCanvas3D& parent); + + bool is_enabled() const { return m_enabled; } + void set_enabled(bool enable) { m_enabled = enable; } + +#if ENABLE_SVG_ICONS + void set_overlay_icon_size(float size); +#endif // ENABLE_SVG_ICONS + void set_overlay_scale(float scale); + + std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); + void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); + void update_on_off_state(const Selection& selection); + void reset_all_states(); + + void set_hover_id(int id); + void enable_grabber(EType type, unsigned int id, bool enable); + + bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; + bool grabber_contains_mouse() const; + void update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos = nullptr); + Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const; + EType get_current_type() const { return m_current; } + + bool is_running() const; + bool handle_shortcut(int key, const Selection& selection); + + bool is_dragging() const; + void start_dragging(const Selection& selection); + void stop_dragging(); + + Vec3d get_displacement() const; + + Vec3d get_scale() const; + void set_scale(const Vec3d& scale); + + Vec3d get_rotation() const; + void set_rotation(const Vec3d& rotation); + + Vec3d get_flattening_normal() const; + + void set_flattening_data(const ModelObject* model_object); + + void set_sla_support_data(ModelObject* model_object, const Selection& selection); + bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false); + void delete_current_grabber(bool delete_all = false); + + void render_current_gizmo(const Selection& selection) const; + void render_current_gizmo_for_picking_pass(const Selection& selection) const; + + void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; + +private: + void reset(); + + void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; + + float get_total_overlay_height() const; + float get_total_overlay_width() const; + + GLGizmoBase* get_current() const; + +#if ENABLE_SVG_ICONS + bool generate_icons_texture() const; +#endif // ENABLE_SVG_ICONS +}; + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GUI_GLGizmosManager_hpp_