Tech ENABLE_GIZMO_GRABBER_REFACTOR - Refactoring of GLGizmoBase::Grabber to have a single static instance of the cube and cone models to be shared by all grabbers

This commit is contained in:
enricoturri1966 2022-04-14 15:15:14 +02:00
parent 09512c086b
commit f504236734
7 changed files with 2203 additions and 2019 deletions

View File

@ -79,6 +79,8 @@
#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1) #define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1)
// Enable fix of used filament data exported to gcode file // Enable fix of used filament data exported to gcode file
#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1) #define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1)
// Enable gizmo grabbers to share common models
#define ENABLE_GIZMO_GRABBER_REFACTOR (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_ #endif // _prusaslicer_technologies_h_

View File

@ -1,277 +1,398 @@
#include "GLGizmoBase.hpp" #include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#if ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_GL_SHADERS_ATTRIBUTES
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
// TODO: Display tooltips quicker on Linux // TODO: Display tooltips quicker on Linux
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
const float GLGizmoBase::Grabber::SizeFactor = 0.05f; const float GLGizmoBase::Grabber::SizeFactor = 0.05f;
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
void GLGizmoBase::Grabber::render(bool hover, float size) #if ENABLE_GIZMO_GRABBER_REFACTOR
{ GLModel GLGizmoBase::Grabber::s_cube;
render(size, hover ? complementary(color) : color, false); GLModel GLGizmoBase::Grabber::s_cone;
}
GLGizmoBase::Grabber::~Grabber()
float GLGizmoBase::Grabber::get_half_size(float size) const {
{ if (s_cube.is_initialized())
return std::max(size * SizeFactor, MinHalfSize); s_cube.reset();
}
if (s_cone.is_initialized())
float GLGizmoBase::Grabber::get_dragging_half_size(float size) const s_cone.reset();
{ }
return get_half_size(size) * DraggingScaleFactor; #endif // ENABLE_GIZMO_GRABBER_REFACTOR
}
float GLGizmoBase::Grabber::get_half_size(float size) const
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) {
{ return std::max(size * SizeFactor, MinHalfSize);
#if ENABLE_GL_SHADERS_ATTRIBUTES }
GLShaderProgram* shader = wxGetApp().get_current_shader();
if (shader == nullptr) float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
return; {
#endif // ENABLE_GL_SHADERS_ATTRIBUTES return get_half_size(size) * DraggingScaleFactor;
}
if (!m_cube.is_initialized()) {
// This cannot be done in constructor, OpenGL is not yet void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking)
// initialized at that point (on Linux at least). {
indexed_triangle_set its = its_make_cube(1., 1., 1.); #if ENABLE_GL_SHADERS_ATTRIBUTES
its_translate(its, -0.5f * Vec3f::Ones()); GLShaderProgram* shader = wxGetApp().get_current_shader();
#if ENABLE_LEGACY_OPENGL_REMOVAL if (shader == nullptr)
m_cube.init_from(its); return;
#else #endif // ENABLE_GL_SHADERS_ATTRIBUTES
m_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GIZMO_GRABBER_REFACTOR
} if (!s_cube.is_initialized()) {
#else
const float fullsize = 2.0f * (dragging ? get_dragging_half_size(size) : get_half_size(size)); if (!m_cube.is_initialized()) {
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
#if ENABLE_LEGACY_OPENGL_REMOVAL // This cannot be done in constructor, OpenGL is not yet
m_cube.set_color(render_color); // initialized at that point (on Linux at least).
#else indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0);
m_cube.set_color(-1, render_color); its_translate(its, -0.5f * Vec3f::Ones());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GIZMO_GRABBER_REFACTOR
#if ENABLE_GL_SHADERS_ATTRIBUTES s_cube.init_from(its);
const Camera& camera = wxGetApp().plater()->get_camera(); #else
const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, fullsize * Vec3d::Ones()); m_cube.init_from(its);
const Transform3d& projection_matrix = camera.get_projection_matrix(); #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#else
shader->set_uniform("view_model_matrix", view_model_matrix); #if ENABLE_GIZMO_GRABBER_REFACTOR
shader->set_uniform("projection_matrix", projection_matrix); s_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); #else
#else m_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
glsafe(::glPushMatrix()); #endif // ENABLE_GIZMO_GRABBER_REFACTOR
glsafe(::glTranslated(center.x(), center.y(), center.z())); #endif // ENABLE_LEGACY_OPENGL_REMOVAL
glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0)); }
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); #if ENABLE_GIZMO_GRABBER_REFACTOR
glsafe(::glScaled(fullsize, fullsize, fullsize)); if (!s_cone.is_initialized())
#endif // ENABLE_GL_SHADERS_ATTRIBUTES s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0));
m_cube.render(); #endif // ENABLE_GIZMO_GRABBER_REFACTOR
#if !ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glPopMatrix()); #if ENABLE_GIZMO_GRABBER_REFACTOR
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size);
} #else
const float fullsize = 2.0f * (dragging ? get_dragging_half_size(size) : get_half_size(size));
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) #endif // ENABLE_GIZMO_GRABBER_REFACTOR
: m_parent(parent)
, m_group_id(-1) #if ENABLE_LEGACY_OPENGL_REMOVAL
, m_state(Off) #if ENABLE_GIZMO_GRABBER_REFACTOR
, m_shortcut_key(0) s_cube.set_color(render_color);
, m_icon_filename(icon_filename) s_cone.set_color(render_color);
, m_sprite_id(sprite_id) #else
, m_hover_id(-1) m_cube.set_color(render_color);
, m_dragging(false) #endif // ENABLE_GIZMO_GRABBER_REFACTOR
, m_imgui(wxGetApp().imgui()) #else
, m_first_input_window_render(true) #if ENABLE_GIZMO_GRABBER_REFACTOR
, m_dirty(false) s_cube.set_color(-1, render_color);
{ s_cone.set_color(-1, render_color);
} #else
m_cube.set_color(-1, render_color);
void GLGizmoBase::set_hover_id(int id) #endif // ENABLE_GIZMO_GRABBER_REFACTOR
{ #endif // ENABLE_LEGACY_OPENGL_REMOVAL
// do not change hover id during dragging
assert(!m_dragging); #if ENABLE_GL_SHADERS_ATTRIBUTES
const Camera& camera = wxGetApp().plater()->get_camera();
// allow empty grabbers when not using grabbers but use hover_id - flatten, rotate #if ENABLE_GIZMO_GRABBER_REFACTOR
if (!m_grabbers.empty() && id >= (int) m_grabbers.size()) const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
return; #else
const Transform3d view_model_matrix = camera.get_view_matrix() * matrix * Geometry::assemble_transform(center, angles, fullsize * Vec3d::Ones());
m_hover_id = id; #endif // ENABLE_GIZMO_GRABBER_REFACTOR
on_set_hover_id(); const Transform3d& projection_matrix = camera.get_projection_matrix();
}
shader->set_uniform("view_model_matrix", view_model_matrix);
bool GLGizmoBase::update_items_state() shader->set_uniform("projection_matrix", projection_matrix);
{ shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
bool res = m_dirty; #else
m_dirty = false; glsafe(::glPushMatrix());
return res; glsafe(::glTranslated(center.x(), center.y(), center.z()));
} glsafe(::glRotated(Geometry::rad2deg(angles.z()), 0.0, 0.0, 1.0));
glsafe(::glRotated(Geometry::rad2deg(angles.y()), 0.0, 1.0, 0.0));
ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
{ #if ENABLE_GIZMO_GRABBER_REFACTOR
id = BASE_ID - id; glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size));
if (m_group_id > -1) #else
id -= m_group_id; glsafe(::glScaled(fullsize, fullsize, fullsize));
#endif // ENABLE_GIZMO_GRABBER_REFACTOR
return picking_decode(id); #endif // ENABLE_GL_SHADERS_ATTRIBUTES
} #if ENABLE_GIZMO_GRABBER_REFACTOR
s_cube.render();
void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
{ #if ENABLE_GL_SHADERS_ATTRIBUTES
render_grabbers((float)((box.size().x() + box.size().y() + box.size().z()) / 3.0)); if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
} shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0)));
s_cone.render();
void GLGizmoBase::render_grabbers(float size) const }
{ if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) {
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0)));
if (shader == nullptr) s_cone.render();
return; }
shader->start_using(); if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) {
shader->set_uniform("emission_factor", 0.1f); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0)));
for (int i = 0; i < (int)m_grabbers.size(); ++i) { s_cone.render();
if (m_grabbers[i].enabled) }
m_grabbers[i].render(m_hover_id == i, size); if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) {
} shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0)));
shader->stop_using(); s_cone.render();
} }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) {
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitZ()));
{ s_cone.render();
#if ENABLE_LEGACY_OPENGL_REMOVAL }
GLShaderProgram* shader = wxGetApp().get_shader("flat"); if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) {
if (shader != nullptr) { shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0)));
shader->start_using(); s_cone.render();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL }
const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); #else
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { glsafe(::glPushMatrix());
if (m_grabbers[i].enabled) { glsafe(::glTranslated(1.0, 0.0, 0.0));
m_grabbers[i].color = picking_color_component(i); glsafe(::glRotated(0.5 * Geometry::rad2deg(double(PI)), 0.0, 1.0, 0.0));
m_grabbers[i].render_for_picking(mean_size); s_cone.render();
} glsafe(::glPopMatrix());
} }
#if ENABLE_LEGACY_OPENGL_REMOVAL if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) {
shader->stop_using(); glsafe(::glPushMatrix());
} glsafe(::glTranslated(-1.0, 0.0, 0.0));
#endif // ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glRotated(-0.5 * Geometry::rad2deg(double(PI)), 0.0, 1.0, 0.0));
} s_cone.render();
glsafe(::glPopMatrix());
// help function to process grabbers }
// call start_dragging, stop_dragging, on_dragging if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) {
bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) { glsafe(::glPushMatrix());
bool is_dragging_finished = false; glsafe(::glTranslated(0.0, 1.0, 0.0));
if (mouse_event.Moving()) { glsafe(::glRotated(-0.5 * Geometry::rad2deg(double(PI)), 1.0, 0.0, 0.0));
// it should not happen but for sure s_cone.render();
assert(!m_dragging); glsafe(::glPopMatrix());
if (m_dragging) is_dragging_finished = true; }
else return false; if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) {
} glsafe(::glPushMatrix());
glsafe(::glTranslated(0.0, -1.0, 0.0));
if (mouse_event.LeftDown()) { glsafe(::glRotated(0.5 * Geometry::rad2deg(double(PI)), 1.0, 0.0, 0.0));
Selection &selection = m_parent.get_selection(); s_cone.render();
if (!selection.is_empty() && m_hover_id != -1 && glsafe(::glPopMatrix());
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))) { }
selection.setup_cache(); if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) {
glsafe(::glPushMatrix());
m_dragging = true; glsafe(::glTranslated(0.0, 0.0, 1.0));
for (auto &grabber : m_grabbers) grabber.dragging = false; s_cone.render();
if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size())) glsafe(::glPopMatrix());
m_grabbers[m_hover_id].dragging = true; }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) {
// prevent change of hover_id during dragging glsafe(::glPushMatrix());
m_parent.set_mouse_as_dragging(); glsafe(::glTranslated(0.0, 0.0, -1.0));
on_start_dragging(); glsafe(::glRotated(Geometry::rad2deg(double(PI)), 1.0, 0.0, 0.0));
s_cone.render();
// Let the plater know that the dragging started glsafe(::glPopMatrix());
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED)); }
m_parent.set_as_dirty(); #endif // ENABLE_GL_SHADERS_ATTRIBUTES
return true; #else
} m_cube.render();
} else if (m_dragging) { #endif // ENABLE_GIZMO_GRABBER_REFACTOR
// when mouse cursor leave window than finish actual dragging operation #if !ENABLE_GL_SHADERS_ATTRIBUTES
bool is_leaving = mouse_event.Leaving(); glsafe(::glPopMatrix());
if (mouse_event.Dragging()) { #endif // !ENABLE_GL_SHADERS_ATTRIBUTES
m_parent.set_mouse_as_dragging(); }
Point mouse_coord(mouse_event.GetX(), mouse_event.GetY());
auto ray = m_parent.mouse_ray(mouse_coord); GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
UpdateData data(ray, mouse_coord); : m_parent(parent)
, m_group_id(-1)
on_dragging(data); , m_state(Off)
, m_shortcut_key(0)
wxGetApp().obj_manipul()->set_dirty(); , m_icon_filename(icon_filename)
m_parent.set_as_dirty(); , m_sprite_id(sprite_id)
return true; , m_hover_id(-1)
} else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) { , m_dragging(false)
for (auto &grabber : m_grabbers) grabber.dragging = false; , m_imgui(wxGetApp().imgui())
m_dragging = false; , m_first_input_window_render(true)
, m_dirty(false)
// NOTE: This should be part of GLCanvas3D {
// Reset hover_id when leave window }
if (is_leaving) m_parent.mouse_up_cleanup();
void GLGizmoBase::set_hover_id(int id)
on_stop_dragging(); {
// do not change hover id during dragging
// There is prediction that after draggign, data are changed assert(!m_dragging);
// Data are updated twice also by canvas3D::reload_scene.
// Should be fixed. // allow empty grabbers when not using grabbers but use hover_id - flatten, rotate
m_parent.get_gizmos_manager().update_data(); if (!m_grabbers.empty() && id >= (int) m_grabbers.size())
return;
wxGetApp().obj_manipul()->set_dirty();
m_hover_id = id;
// Let the plater know that the dragging finished, so a delayed on_set_hover_id();
// refresh of the scene with the background processing data should }
// be performed.
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); bool GLGizmoBase::update_items_state()
// updates camera target constraints {
m_parent.refresh_camera_scene_box(); bool res = m_dirty;
return true; m_dirty = false;
} return res;
} }
return false;
} ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const
{
std::string GLGizmoBase::format(float value, unsigned int decimals) const id = BASE_ID - id;
{ if (m_group_id > -1)
return Slic3r::string_printf("%.*f", decimals, value); id -= m_group_id;
}
return picking_decode(id);
void GLGizmoBase::set_dirty() { }
m_dirty = true;
} void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
{
void GLGizmoBase::render_input_window(float x, float y, float bottom_limit) render_grabbers((float)((box.size().x() + box.size().y() + box.size().z()) / 3.0));
{ }
on_render_input_window(x, y, bottom_limit);
if (m_first_input_window_render) { void GLGizmoBase::render_grabbers(float size) const
// for some reason, the imgui dialogs are not shown on screen in the 1st frame where they are rendered, but show up only with the 2nd rendered frame {
// so, we forces another frame rendering the first time the imgui window is shown GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
m_parent.set_as_dirty(); if (shader == nullptr)
m_first_input_window_render = false; return;
} shader->start_using();
} shader->set_uniform("emission_factor", 0.1f);
for (int i = 0; i < (int)m_grabbers.size(); ++i) {
if (m_grabbers[i].enabled)
m_grabbers[i].render(m_hover_id == i, size);
std::string GLGizmoBase::get_name(bool include_shortcut) const }
{ shader->stop_using();
int key = get_shortcut_key(); }
std::string out = on_get_name();
if (include_shortcut && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z) void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
out += std::string(" [") + char(int('A') + key - int(WXK_CONTROL_A)) + "]"; {
return out; #if ENABLE_LEGACY_OPENGL_REMOVAL
} GLShaderProgram* shader = wxGetApp().get_shader("flat");
if (shader != nullptr) {
shader->start_using();
} // namespace GUI #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} // namespace Slic3r const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0);
for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) {
if (m_grabbers[i].enabled) {
m_grabbers[i].color = picking_color_component(i);
m_grabbers[i].render_for_picking(mean_size);
}
}
#if ENABLE_LEGACY_OPENGL_REMOVAL
shader->stop_using();
}
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
}
// help function to process grabbers
// call start_dragging, stop_dragging, on_dragging
bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
bool is_dragging_finished = false;
if (mouse_event.Moving()) {
// it should not happen but for sure
assert(!m_dragging);
if (m_dragging) is_dragging_finished = true;
else return false;
}
if (mouse_event.LeftDown()) {
Selection &selection = m_parent.get_selection();
if (!selection.is_empty() && m_hover_id != -1 &&
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))) {
selection.setup_cache();
m_dragging = true;
for (auto &grabber : m_grabbers) grabber.dragging = false;
if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size()))
m_grabbers[m_hover_id].dragging = true;
// prevent change of hover_id during dragging
m_parent.set_mouse_as_dragging();
on_start_dragging();
// Let the plater know that the dragging started
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_STARTED));
m_parent.set_as_dirty();
return true;
}
} else if (m_dragging) {
// when mouse cursor leave window than finish actual dragging operation
bool is_leaving = mouse_event.Leaving();
if (mouse_event.Dragging()) {
m_parent.set_mouse_as_dragging();
Point mouse_coord(mouse_event.GetX(), mouse_event.GetY());
auto ray = m_parent.mouse_ray(mouse_coord);
UpdateData data(ray, mouse_coord);
on_dragging(data);
wxGetApp().obj_manipul()->set_dirty();
m_parent.set_as_dirty();
return true;
} else if (mouse_event.LeftUp() || is_leaving || is_dragging_finished) {
for (auto &grabber : m_grabbers) grabber.dragging = false;
m_dragging = false;
// NOTE: This should be part of GLCanvas3D
// Reset hover_id when leave window
if (is_leaving) m_parent.mouse_up_cleanup();
on_stop_dragging();
// There is prediction that after draggign, data are changed
// Data are updated twice also by canvas3D::reload_scene.
// Should be fixed.
m_parent.get_gizmos_manager().update_data();
wxGetApp().obj_manipul()->set_dirty();
// Let the plater know that the dragging finished, so a delayed
// refresh of the scene with the background processing data should
// be performed.
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
// updates camera target constraints
m_parent.refresh_camera_scene_box();
return true;
}
}
return false;
}
std::string GLGizmoBase::format(float value, unsigned int decimals) const
{
return Slic3r::string_printf("%.*f", decimals, value);
}
void GLGizmoBase::set_dirty() {
m_dirty = true;
}
void GLGizmoBase::render_input_window(float x, float y, float bottom_limit)
{
on_render_input_window(x, y, bottom_limit);
if (m_first_input_window_render) {
// for some reason, the imgui dialogs are not shown on screen in the 1st frame where they are rendered, but show up only with the 2nd rendered frame
// so, we forces another frame rendering the first time the imgui window is shown
m_parent.set_as_dirty();
m_first_input_window_render = false;
}
}
std::string GLGizmoBase::get_name(bool include_shortcut) const
{
int key = get_shortcut_key();
std::string out = on_get_name();
if (include_shortcut && key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z)
out += std::string(" [") + char(int('A') + key - int(WXK_CONTROL_A)) + "]";
return out;
}
} // namespace GUI
} // namespace Slic3r

View File

@ -1,215 +1,239 @@
#ifndef slic3r_GLGizmoBase_hpp_ #ifndef slic3r_GLGizmoBase_hpp_
#define slic3r_GLGizmoBase_hpp_ #define slic3r_GLGizmoBase_hpp_
#include "libslic3r/Point.hpp" #include "libslic3r/Point.hpp"
#include "libslic3r/Color.hpp" #include "libslic3r/Color.hpp"
#include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GLModel.hpp" #include "slic3r/GUI/GLModel.hpp"
#include <cereal/archives/binary.hpp> #include <cereal/archives/binary.hpp>
class wxWindow; class wxWindow;
class wxMouseEvent; class wxMouseEvent;
namespace Slic3r { namespace Slic3r {
class BoundingBoxf3; class BoundingBoxf3;
class Linef3; class Linef3;
class ModelObject; class ModelObject;
namespace GUI { namespace GUI {
static const ColorRGBA DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f }; static const ColorRGBA DEFAULT_BASE_COLOR = { 0.625f, 0.625f, 0.625f, 1.0f };
static const ColorRGBA DEFAULT_DRAG_COLOR = ColorRGBA::WHITE(); static const ColorRGBA DEFAULT_DRAG_COLOR = ColorRGBA::WHITE();
static const ColorRGBA DEFAULT_HIGHLIGHT_COLOR = ColorRGBA::ORANGE(); static const ColorRGBA DEFAULT_HIGHLIGHT_COLOR = ColorRGBA::ORANGE();
static const std::array<ColorRGBA, 3> AXES_COLOR = {{ ColorRGBA::X(), ColorRGBA::Y(), ColorRGBA::Z() }}; static const std::array<ColorRGBA, 3> AXES_COLOR = {{ ColorRGBA::X(), ColorRGBA::Y(), ColorRGBA::Z() }};
static const ColorRGBA CONSTRAINED_COLOR = ColorRGBA::GRAY(); static const ColorRGBA CONSTRAINED_COLOR = ColorRGBA::GRAY();
class ImGuiWrapper; class ImGuiWrapper;
class GLCanvas3D; class GLCanvas3D;
enum class CommonGizmosDataID; enum class CommonGizmosDataID;
class CommonGizmosDataPool; class CommonGizmosDataPool;
class GLGizmoBase class GLGizmoBase
{ {
public: public:
// Starting value for ids to avoid clashing with ids used by GLVolumes // Starting value for ids to avoid clashing with ids used by GLVolumes
// (254 is choosen to leave some space for forward compatibility) // (254 is choosen to leave some space for forward compatibility)
static const unsigned int BASE_ID = 255 * 255 * 254; static const unsigned int BASE_ID = 255 * 255 * 254;
protected: #if ENABLE_GIZMO_GRABBER_REFACTOR
struct Grabber enum class EGrabberExtension
{ {
static const float SizeFactor; None = 0,
static const float MinHalfSize; PosX = 1 << 0,
static const float DraggingScaleFactor; NegX = 1 << 1,
PosY = 1 << 2,
bool enabled{ true }; NegY = 1 << 3,
bool dragging{ false }; PosZ = 1 << 4,
Vec3d center{ Vec3d::Zero() }; NegZ = 1 << 5,
Vec3d angles{ Vec3d::Zero() }; };
#if ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GIZMO_GRABBER_REFACTOR
Transform3d matrix{ Transform3d::Identity() };
#endif // ENABLE_GL_SHADERS_ATTRIBUTES protected:
ColorRGBA color{ ColorRGBA::WHITE() }; struct Grabber
{
Grabber() = default; static const float SizeFactor;
static const float MinHalfSize;
void render(bool hover, float size); static const float DraggingScaleFactor;
void render_for_picking(float size) { render(size, color, true); }
bool enabled{ true };
float get_half_size(float size) const; bool dragging{ false };
float get_dragging_half_size(float size) const; Vec3d center{ Vec3d::Zero() };
Vec3d angles{ Vec3d::Zero() };
private: #if ENABLE_GL_SHADERS_ATTRIBUTES
void render(float size, const ColorRGBA& render_color, bool picking); Transform3d matrix{ Transform3d::Identity() };
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
GLModel m_cube; ColorRGBA color{ ColorRGBA::WHITE() };
}; #if ENABLE_GIZMO_GRABBER_REFACTOR
EGrabberExtension extensions{ EGrabberExtension::None };
public: #endif // ENABLE_GIZMO_GRABBER_REFACTOR
enum EState
{ Grabber() = default;
Off, #if ENABLE_GIZMO_GRABBER_REFACTOR
On, ~Grabber();
Num_States #endif // ENABLE_GIZMO_GRABBER_REFACTOR
};
void render(bool hover, float size) { render(size, hover ? complementary(color) : color, false); }
struct UpdateData void render_for_picking(float size) { render(size, color, true); }
{
const Linef3& mouse_ray; float get_half_size(float size) const;
const Point& mouse_pos; float get_dragging_half_size(float size) const;
UpdateData(const Linef3& mouse_ray, const Point& mouse_pos) private:
: mouse_ray(mouse_ray), mouse_pos(mouse_pos) void render(float size, const ColorRGBA& render_color, bool picking);
{}
}; #if ENABLE_GIZMO_GRABBER_REFACTOR
static GLModel s_cube;
protected: static GLModel s_cone;
GLCanvas3D& m_parent; #else
int m_group_id; // TODO: remove only for rotate GLModel m_cube;
EState m_state; #endif // ENABLE_GIZMO_GRABBER_REFACTOR
int m_shortcut_key; };
std::string m_icon_filename;
unsigned int m_sprite_id; public:
int m_hover_id; enum EState
bool m_dragging; {
mutable std::vector<Grabber> m_grabbers; Off,
ImGuiWrapper* m_imgui; On,
bool m_first_input_window_render; Num_States
CommonGizmosDataPool* m_c; };
public:
GLGizmoBase(GLCanvas3D& parent, struct UpdateData
const std::string& icon_filename, {
unsigned int sprite_id); const Linef3& mouse_ray;
virtual ~GLGizmoBase() = default; const Point& mouse_pos;
bool init() { return on_init(); } UpdateData(const Linef3& mouse_ray, const Point& mouse_pos)
: mouse_ray(mouse_ray), mouse_pos(mouse_pos)
void load(cereal::BinaryInputArchive& ar) { m_state = On; on_load(ar); } {}
void save(cereal::BinaryOutputArchive& ar) const { on_save(ar); } };
std::string get_name(bool include_shortcut = true) const; protected:
GLCanvas3D& m_parent;
EState get_state() const { return m_state; } int m_group_id; // TODO: remove only for rotate
void set_state(EState state) { m_state = state; on_set_state(); } EState m_state;
int m_shortcut_key;
int get_shortcut_key() const { return m_shortcut_key; } std::string m_icon_filename;
unsigned int m_sprite_id;
const std::string& get_icon_filename() const { return m_icon_filename; } int m_hover_id;
bool m_dragging;
bool is_activable() const { return on_is_activable(); } mutable std::vector<Grabber> m_grabbers;
bool is_selectable() const { return on_is_selectable(); } ImGuiWrapper* m_imgui;
CommonGizmosDataID get_requirements() const { return on_get_requirements(); } bool m_first_input_window_render;
virtual bool wants_enter_leave_snapshots() const { return false; } CommonGizmosDataPool* m_c;
virtual std::string get_gizmo_entering_text() const { assert(false); return ""; } public:
virtual std::string get_gizmo_leaving_text() const { assert(false); return ""; } GLGizmoBase(GLCanvas3D& parent,
virtual std::string get_action_snapshot_name() { return _u8L("Gizmo action"); } const std::string& icon_filename,
void set_common_data_pool(CommonGizmosDataPool* ptr) { m_c = ptr; } unsigned int sprite_id);
virtual ~GLGizmoBase() = default;
unsigned int get_sprite_id() const { return m_sprite_id; }
bool init() { return on_init(); }
int get_hover_id() const { return m_hover_id; }
void set_hover_id(int id); void load(cereal::BinaryInputArchive& ar) { m_state = On; on_load(ar); }
void save(cereal::BinaryOutputArchive& ar) const { on_save(ar); }
bool is_dragging() const { return m_dragging; }
std::string get_name(bool include_shortcut = true) const;
// returns True when Gizmo changed its state
bool update_items_state(); EState get_state() const { return m_state; }
void set_state(EState state) { m_state = state; on_set_state(); }
void render() { on_render(); }
void render_for_picking() { on_render_for_picking(); } int get_shortcut_key() const { return m_shortcut_key; }
void render_input_window(float x, float y, float bottom_limit);
const std::string& get_icon_filename() const { return m_icon_filename; }
/// <summary>
/// Mouse tooltip text bool is_activable() const { return on_is_activable(); }
/// </summary> bool is_selectable() const { return on_is_selectable(); }
/// <returns>Text to be visible in mouse tooltip</returns> CommonGizmosDataID get_requirements() const { return on_get_requirements(); }
virtual std::string get_tooltip() const { return ""; } virtual bool wants_enter_leave_snapshots() const { return false; }
virtual std::string get_gizmo_entering_text() const { assert(false); return ""; }
/// <summary> virtual std::string get_gizmo_leaving_text() const { assert(false); return ""; }
/// Is called when data (Selection) is changed virtual std::string get_action_snapshot_name() { return _u8L("Gizmo action"); }
/// </summary> void set_common_data_pool(CommonGizmosDataPool* ptr) { m_c = ptr; }
virtual void data_changed(){};
unsigned int get_sprite_id() const { return m_sprite_id; }
/// <summary>
/// Implement when want to process mouse events in gizmo int get_hover_id() const { return m_hover_id; }
/// Click, Right click, move, drag, ... void set_hover_id(int id);
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param> bool is_dragging() const { return m_dragging; }
/// <returns>Return True when use the information and don't want to propagate it otherwise False.</returns>
virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; } // returns True when Gizmo changed its state
protected: bool update_items_state();
virtual bool on_init() = 0;
virtual void on_load(cereal::BinaryInputArchive& ar) {} void render() { on_render(); }
virtual void on_save(cereal::BinaryOutputArchive& ar) const {} void render_for_picking() { on_render_for_picking(); }
virtual std::string on_get_name() const = 0; void render_input_window(float x, float y, float bottom_limit);
virtual void on_set_state() {}
virtual void on_set_hover_id() {} /// <summary>
virtual bool on_is_activable() const { return true; } /// Mouse tooltip text
virtual bool on_is_selectable() const { return true; } /// </summary>
virtual CommonGizmosDataID on_get_requirements() const { return CommonGizmosDataID(0); } /// <returns>Text to be visible in mouse tooltip</returns>
virtual void on_enable_grabber(unsigned int id) {} virtual std::string get_tooltip() const { return ""; }
virtual void on_disable_grabber(unsigned int id) {}
/// <summary>
// called inside use_grabbers /// Is called when data (Selection) is changed
virtual void on_start_dragging() {} /// </summary>
virtual void on_stop_dragging() {} virtual void data_changed(){};
virtual void on_dragging(const UpdateData& data) {}
/// <summary>
virtual void on_render() = 0; /// Implement when want to process mouse events in gizmo
virtual void on_render_for_picking() = 0; /// Click, Right click, move, drag, ...
virtual void on_render_input_window(float x, float y, float bottom_limit) {} /// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
// Returns the picking color for the given id, based on the BASE_ID constant /// <returns>Return True when use the information and don't want to propagate it otherwise False.</returns>
// No check is made for clashing with other picking color (i.e. GLVolumes) virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; }
ColorRGBA picking_color_component(unsigned int id) const; protected:
virtual bool on_init() = 0;
void render_grabbers(const BoundingBoxf3& box) const; virtual void on_load(cereal::BinaryInputArchive& ar) {}
void render_grabbers(float size) const; virtual void on_save(cereal::BinaryOutputArchive& ar) const {}
void render_grabbers_for_picking(const BoundingBoxf3& box) const; virtual std::string on_get_name() const = 0;
virtual void on_set_state() {}
std::string format(float value, unsigned int decimals) const; virtual void on_set_hover_id() {}
virtual bool on_is_activable() const { return true; }
// Mark gizmo as dirty to Re-Render when idle() virtual bool on_is_selectable() const { return true; }
void set_dirty(); virtual CommonGizmosDataID on_get_requirements() const { return CommonGizmosDataID(0); }
virtual void on_enable_grabber(unsigned int id) {}
/// <summary> virtual void on_disable_grabber(unsigned int id) {}
/// function which
/// Set up m_dragging and call functions // called inside use_grabbers
/// on_start_dragging / on_dragging / on_stop_dragging virtual void on_start_dragging() {}
/// </summary> virtual void on_stop_dragging() {}
/// <param name="mouse_event">Keep information about mouse click</param> virtual void on_dragging(const UpdateData& data) {}
/// <returns>same as on_mouse</returns>
bool use_grabbers(const wxMouseEvent &mouse_event); virtual void on_render() = 0;
private: virtual void on_render_for_picking() = 0;
// Flag for dirty visible state of Gizmo virtual void on_render_input_window(float x, float y, float bottom_limit) {}
// When True then need new rendering
bool m_dirty; // Returns the picking color for the given id, based on the BASE_ID constant
}; // No check is made for clashing with other picking color (i.e. GLVolumes)
ColorRGBA picking_color_component(unsigned int id) const;
} // namespace GUI
} // namespace Slic3r void render_grabbers(const BoundingBoxf3& box) const;
void render_grabbers(float size) const;
#endif // slic3r_GLGizmoBase_hpp_ void render_grabbers_for_picking(const BoundingBoxf3& box) const;
std::string format(float value, unsigned int decimals) const;
// Mark gizmo as dirty to Re-Render when idle()
void set_dirty();
/// <summary>
/// function which
/// Set up m_dragging and call functions
/// on_start_dragging / on_dragging / on_stop_dragging
/// </summary>
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>same as on_mouse</returns>
bool use_grabbers(const wxMouseEvent &mouse_event);
private:
// Flag for dirty visible state of Gizmo
// When True then need new rendering
bool m_dirty;
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoBase_hpp_

View File

@ -1,331 +1,349 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. // Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoMove.hpp" #include "GLGizmoMove.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#if ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_GL_SHADERS_ATTRIBUTES
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_GL_SHADERS_ATTRIBUTES
#include <GL/glew.h> #include <GL/glew.h>
#include <wx/utils.h> #include <wx/utils.h>
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
const double GLGizmoMove3D::Offset = 10.0; const double GLGizmoMove3D::Offset = 10.0;
GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id)
{} {}
std::string GLGizmoMove3D::get_tooltip() const std::string GLGizmoMove3D::get_tooltip() const
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
bool show_position = selection.is_single_full_instance(); bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center(); const Vec3d& position = selection.get_bounding_box().center();
if (m_hover_id == 0 || m_grabbers[0].dragging) if (m_hover_id == 0 || m_grabbers[0].dragging)
return "X: " + format(show_position ? position(0) : m_displacement(0), 2); return "X: " + format(show_position ? position(0) : m_displacement(0), 2);
else if (m_hover_id == 1 || m_grabbers[1].dragging) else if (m_hover_id == 1 || m_grabbers[1].dragging)
return "Y: " + format(show_position ? position(1) : m_displacement(1), 2); return "Y: " + format(show_position ? position(1) : m_displacement(1), 2);
else if (m_hover_id == 2 || m_grabbers[2].dragging) else if (m_hover_id == 2 || m_grabbers[2].dragging)
return "Z: " + format(show_position ? position(2) : m_displacement(2), 2); return "Z: " + format(show_position ? position(2) : m_displacement(2), 2);
else else
return ""; return "";
} }
bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) { bool GLGizmoMove3D::on_mouse(const wxMouseEvent &mouse_event) {
return use_grabbers(mouse_event); return use_grabbers(mouse_event);
} }
void GLGizmoMove3D::data_changed() { void GLGizmoMove3D::data_changed() {
const Selection &selection = m_parent.get_selection(); const Selection &selection = m_parent.get_selection();
bool is_wipe_tower = selection.is_wipe_tower(); bool is_wipe_tower = selection.is_wipe_tower();
m_grabbers[2].enabled = !is_wipe_tower; m_grabbers[2].enabled = !is_wipe_tower;
} }
bool GLGizmoMove3D::on_init() bool GLGizmoMove3D::on_init()
{ {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
m_grabbers.push_back(Grabber()); m_grabbers.push_back(Grabber());
} #if ENABLE_GIZMO_GRABBER_REFACTOR
m_grabbers.back().extensions = GLGizmoBase::EGrabberExtension::PosZ;
m_shortcut_key = WXK_CONTROL_M; #endif // ENABLE_GIZMO_GRABBER_REFACTOR
}
return true;
} #if ENABLE_GIZMO_GRABBER_REFACTOR
m_grabbers[0].angles = { 0.0, 0.5 * double(PI), 0.0 };
std::string GLGizmoMove3D::on_get_name() const m_grabbers[1].angles = { -0.5 * double(PI), 0.0, 0.0 };
{ #endif // ENABLE_GIZMO_GRABBER_REFACTOR
return _u8L("Move");
} m_shortcut_key = WXK_CONTROL_M;
bool GLGizmoMove3D::on_is_activable() const return true;
{ }
return !m_parent.get_selection().is_empty();
} std::string GLGizmoMove3D::on_get_name() const
{
void GLGizmoMove3D::on_start_dragging() return _u8L("Move");
{ }
assert(m_hover_id != -1);
bool GLGizmoMove3D::on_is_activable() const
m_displacement = Vec3d::Zero(); {
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); return !m_parent.get_selection().is_empty();
m_starting_drag_position = m_grabbers[m_hover_id].center; }
m_starting_box_center = box.center();
m_starting_box_bottom_center = box.center(); void GLGizmoMove3D::on_start_dragging()
m_starting_box_bottom_center(2) = box.min(2); {
} assert(m_hover_id != -1);
void GLGizmoMove3D::on_stop_dragging() m_displacement = Vec3d::Zero();
{ const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
m_parent.do_move(L("Gizmo-Move")); m_starting_drag_position = m_grabbers[m_hover_id].center;
m_displacement = Vec3d::Zero(); m_starting_box_center = box.center();
} m_starting_box_bottom_center = box.center();
m_starting_box_bottom_center(2) = box.min(2);
void GLGizmoMove3D::on_dragging(const UpdateData& data) }
{
if (m_hover_id == 0) void GLGizmoMove3D::on_stop_dragging()
m_displacement.x() = calc_projection(data); {
else if (m_hover_id == 1) m_parent.do_move(L("Gizmo-Move"));
m_displacement.y() = calc_projection(data); m_displacement = Vec3d::Zero();
else if (m_hover_id == 2) }
m_displacement.z() = calc_projection(data);
void GLGizmoMove3D::on_dragging(const UpdateData& data)
Selection &selection = m_parent.get_selection(); {
selection.translate(m_displacement); if (m_hover_id == 0)
} m_displacement.x() = calc_projection(data);
else if (m_hover_id == 1)
void GLGizmoMove3D::on_render() m_displacement.y() = calc_projection(data);
{ else if (m_hover_id == 2)
if (!m_cone.is_initialized()) m_displacement.z() = calc_projection(data);
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0));
Selection &selection = m_parent.get_selection();
const Selection& selection = m_parent.get_selection(); selection.translate(m_displacement);
}
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST)); void GLGizmoMove3D::on_render()
{
const BoundingBoxf3& box = selection.get_bounding_box(); #if !ENABLE_GIZMO_GRABBER_REFACTOR
const Vec3d& center = box.center(); if (!m_cone.is_initialized())
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 18.0));
// x axis #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
m_grabbers[0].center = { box.max.x() + Offset, center.y(), center.z() };
m_grabbers[0].color = AXES_COLOR[0]; const Selection& selection = m_parent.get_selection();
// y axis glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
m_grabbers[1].center = { center.x(), box.max.y() + Offset, center.z() }; glsafe(::glEnable(GL_DEPTH_TEST));
m_grabbers[1].color = AXES_COLOR[1];
const BoundingBoxf3& box = selection.get_bounding_box();
// z axis const Vec3d& center = box.center();
m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
m_grabbers[2].color = AXES_COLOR[2]; // x axis
m_grabbers[0].center = { box.max.x() + Offset, center.y(), center.z() };
glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); m_grabbers[0].color = AXES_COLOR[0];
#if ENABLE_LEGACY_OPENGL_REMOVAL // y axis
auto render_grabber_connection = [this, &center](unsigned int id) { m_grabbers[1].center = { center.x(), box.max.y() + Offset, center.z() };
if (m_grabbers[id].enabled) { m_grabbers[1].color = AXES_COLOR[1];
if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
m_grabber_connections[id].old_center = center; // z axis
m_grabber_connections[id].model.reset(); m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset };
m_grabbers[2].color = AXES_COLOR[2];
GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
init_data.color = AXES_COLOR[id];
init_data.reserve_vertices(2); #if ENABLE_LEGACY_OPENGL_REMOVAL
init_data.reserve_indices(2); auto render_grabber_connection = [this, &center](unsigned int id) {
if (m_grabbers[id].enabled) {
// vertices if (!m_grabber_connections[id].model.is_initialized() || !m_grabber_connections[id].old_center.isApprox(center)) {
init_data.add_vertex((Vec3f)center.cast<float>()); m_grabber_connections[id].old_center = center;
init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>()); m_grabber_connections[id].model.reset();
// indices GLModel::Geometry init_data;
init_data.add_line(0, 1); init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
init_data.color = AXES_COLOR[id];
m_grabber_connections[id].model.init_from(std::move(init_data)); init_data.reserve_vertices(2);
} init_data.reserve_indices(2);
m_grabber_connections[id].model.render(); // vertices
} init_data.add_vertex((Vec3f)center.cast<float>());
}; init_data.add_vertex((Vec3f)m_grabbers[id].center.cast<float>());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
// indices
if (m_hover_id == -1) { init_data.add_line(0, 1);
#if ENABLE_LEGACY_OPENGL_REMOVAL
GLShaderProgram* shader = wxGetApp().get_shader("flat"); m_grabber_connections[id].model.init_from(std::move(init_data));
if (shader != nullptr) { }
shader->start_using();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL m_grabber_connections[id].model.render();
}
#if ENABLE_GL_SHADERS_ATTRIBUTES };
const Camera& camera = wxGetApp().plater()->get_camera(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); if (m_hover_id == -1) {
#endif // ENABLE_GL_SHADERS_ATTRIBUTES #if ENABLE_LEGACY_OPENGL_REMOVAL
GLShaderProgram* shader = wxGetApp().get_shader("flat");
// draw axes if (shader != nullptr) {
for (unsigned int i = 0; i < 3; ++i) { shader->start_using();
#if ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
render_grabber_connection(i);
#else #if ENABLE_GL_SHADERS_ATTRIBUTES
if (m_grabbers[i].enabled) { const Camera& camera = wxGetApp().plater()->get_camera();
glsafe(::glColor4fv(AXES_COLOR[i].data())); shader->set_uniform("view_model_matrix", camera.get_view_matrix());
::glBegin(GL_LINES); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
::glVertex3dv(center.data()); #endif // ENABLE_GL_SHADERS_ATTRIBUTES
::glVertex3dv(m_grabbers[i].center.data());
glsafe(::glEnd()); // draw axes
} for (unsigned int i = 0; i < 3; ++i) {
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
} render_grabber_connection(i);
#else
#if ENABLE_LEGACY_OPENGL_REMOVAL if (m_grabbers[i].enabled) {
shader->stop_using(); glsafe(::glColor4fv(AXES_COLOR[i].data()));
} ::glBegin(GL_LINES);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL ::glVertex3dv(center.data());
::glVertex3dv(m_grabbers[i].center.data());
// draw grabbers glsafe(::glEnd());
render_grabbers(box); }
for (unsigned int i = 0; i < 3; ++i) { #endif // ENABLE_LEGACY_OPENGL_REMOVAL
if (m_grabbers[i].enabled) }
render_grabber_extension((Axis)i, box, false);
} #if ENABLE_LEGACY_OPENGL_REMOVAL
} shader->stop_using();
else { }
// draw axis #endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_LEGACY_OPENGL_REMOVAL
GLShaderProgram* shader = wxGetApp().get_shader("flat"); // draw grabbers
if (shader != nullptr) { render_grabbers(box);
shader->start_using(); #if !ENABLE_GIZMO_GRABBER_REFACTOR
for (unsigned int i = 0; i < 3; ++i) {
#if ENABLE_GL_SHADERS_ATTRIBUTES if (m_grabbers[i].enabled)
const Camera& camera = wxGetApp().plater()->get_camera(); render_grabber_extension((Axis)i, box, false);
shader->set_uniform("view_model_matrix", camera.get_view_matrix()); }
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
#endif // ENABLE_GL_SHADERS_ATTRIBUTES }
else {
render_grabber_connection(m_hover_id); // draw axis
shader->stop_using(); #if ENABLE_LEGACY_OPENGL_REMOVAL
} GLShaderProgram* shader = wxGetApp().get_shader("flat");
if (shader != nullptr) {
shader = wxGetApp().get_shader("gouraud_light"); shader->start_using();
#else
glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data())); #if ENABLE_GL_SHADERS_ATTRIBUTES
::glBegin(GL_LINES); const Camera& camera = wxGetApp().plater()->get_camera();
::glVertex3dv(center.data()); shader->set_uniform("view_model_matrix", camera.get_view_matrix());
::glVertex3dv(m_grabbers[m_hover_id].center.data()); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
glsafe(::glEnd()); #endif // ENABLE_GL_SHADERS_ATTRIBUTES
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); render_grabber_connection(m_hover_id);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL shader->stop_using();
if (shader != nullptr) { }
shader->start_using();
shader->set_uniform("emission_factor", 0.1f); shader = wxGetApp().get_shader("gouraud_light");
// draw grabber #else
const float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data()));
m_grabbers[m_hover_id].render(true, mean_size); ::glBegin(GL_LINES);
shader->stop_using(); ::glVertex3dv(center.data());
} ::glVertex3dv(m_grabbers[m_hover_id].center.data());
render_grabber_extension((Axis)m_hover_id, box, false); glsafe(::glEnd());
}
} GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
void GLGizmoMove3D::on_render_for_picking() if (shader != nullptr) {
{ shader->start_using();
glsafe(::glDisable(GL_DEPTH_TEST)); shader->set_uniform("emission_factor", 0.1f);
// draw grabber
const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); const float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0);
render_grabbers_for_picking(box); m_grabbers[m_hover_id].render(true, mean_size);
render_grabber_extension(X, box, true); shader->stop_using();
render_grabber_extension(Y, box, true); }
render_grabber_extension(Z, box, true); #if !ENABLE_GIZMO_GRABBER_REFACTOR
} render_grabber_extension((Axis)m_hover_id, box, false);
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
double GLGizmoMove3D::calc_projection(const UpdateData& data) const }
{ }
double projection = 0.0;
void GLGizmoMove3D::on_render_for_picking()
Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; {
double len_starting_vec = starting_vec.norm(); glsafe(::glDisable(GL_DEPTH_TEST));
if (len_starting_vec != 0.0) {
Vec3d mouse_dir = data.mouse_ray.unit_vector(); const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position render_grabbers_for_picking(box);
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form #if !ENABLE_GIZMO_GRABBER_REFACTOR
// in our case plane normal and ray direction are the same (orthogonal view) render_grabber_extension(X, box, true);
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal render_grabber_extension(Y, box, true);
Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; render_grabber_extension(Z, box, true);
// vector from the starting position to the found intersection #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
Vec3d inters_vec = inters - m_starting_drag_position; }
// finds projection of the vector along the staring direction double GLGizmoMove3D::calc_projection(const UpdateData& data) const
projection = inters_vec.dot(starting_vec.normalized()); {
} double projection = 0.0;
if (wxGetKeyState(WXK_SHIFT)) Vec3d starting_vec = m_starting_drag_position - m_starting_box_center;
projection = m_snap_step * (double)std::round(projection / m_snap_step); double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0) {
return projection; Vec3d mouse_dir = data.mouse_ray.unit_vector();
} // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) // in our case plane normal and ray direction are the same (orthogonal view)
{ // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size)); // vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting_drag_position;
#if ENABLE_LEGACY_OPENGL_REMOVAL
GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); // finds projection of the vector along the staring direction
#else projection = inters_vec.dot(starting_vec.normalized());
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); }
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
if (shader == nullptr) if (wxGetKeyState(WXK_SHIFT))
return; projection = m_snap_step * (double)std::round(projection / m_snap_step);
#if ENABLE_LEGACY_OPENGL_REMOVAL return projection;
m_cone.set_color((!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color); }
shader->start_using();
shader->set_uniform("emission_factor", 0.1f); #if !ENABLE_GIZMO_GRABBER_REFACTOR
#else void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking)
m_cone.set_color(-1, (!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color); {
if (!picking) { const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0);
shader->start_using(); const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size));
shader->set_uniform("emission_factor", 0.1f);
} #if ENABLE_LEGACY_OPENGL_REMOVAL
#endif // ENABLE_LEGACY_OPENGL_REMOVAL GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
#else
#if ENABLE_GL_SHADERS_ATTRIBUTES GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
const Camera& camera = wxGetApp().plater()->get_camera(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL
Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_grabbers[axis].center); if (shader == nullptr)
if (axis == X) return;
view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY());
else if (axis == Y) #if ENABLE_LEGACY_OPENGL_REMOVAL
view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX()); m_cone.set_color((!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color);
view_model_matrix = view_model_matrix * Geometry::assemble_transform(2.0 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size)); shader->start_using();
shader->set_uniform("emission_factor", 0.1f);
shader->set_uniform("view_model_matrix", view_model_matrix); #else
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); m_cone.set_color(-1, (!picking && m_hover_id != -1) ? complementary(m_grabbers[axis].color) : m_grabbers[axis].color);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); if (!picking) {
#else shader->start_using();
glsafe(::glPushMatrix()); shader->set_uniform("emission_factor", 0.1f);
glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z())); }
if (axis == X) #endif // ENABLE_LEGACY_OPENGL_REMOVAL
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
else if (axis == Y) #if ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0)); const Camera& camera = wxGetApp().plater()->get_camera();
Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(m_grabbers[axis].center);
glsafe(::glTranslated(0.0, 0.0, 2.0 * size)); if (axis == X)
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size)); view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), 0.5 * PI * Vec3d::UnitY());
#endif // ENABLE_GL_SHADERS_ATTRIBUTES else if (axis == Y)
m_cone.render(); view_model_matrix = view_model_matrix * Geometry::assemble_transform(Vec3d::Zero(), -0.5 * PI * Vec3d::UnitX());
#if !ENABLE_GL_SHADERS_ATTRIBUTES view_model_matrix = view_model_matrix * Geometry::assemble_transform(2.0 * size * Vec3d::UnitZ(), Vec3d::Zero(), Vec3d(0.75 * size, 0.75 * size, 3.0 * size));
glsafe(::glPopMatrix());
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
#if !ENABLE_LEGACY_OPENGL_REMOVAL shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
if (! picking) #else
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPushMatrix());
shader->stop_using(); glsafe(::glTranslated(m_grabbers[axis].center.x(), m_grabbers[axis].center.y(), m_grabbers[axis].center.z()));
} if (axis == X)
glsafe(::glRotated(90.0, 0.0, 1.0, 0.0));
} // namespace GUI else if (axis == Y)
} // namespace Slic3r glsafe(::glRotated(-90.0, 1.0, 0.0, 0.0));
glsafe(::glTranslated(0.0, 0.0, 2.0 * size));
glsafe(::glScaled(0.75 * size, 0.75 * size, 3.0 * size));
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
m_cone.render();
#if !ENABLE_GL_SHADERS_ATTRIBUTES
glsafe(::glPopMatrix());
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
#if !ENABLE_LEGACY_OPENGL_REMOVAL
if (! picking)
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
shader->stop_using();
}
#endif // !ENABLE_GIZMO_GRABBER_REFACTOR
} // namespace GUI
} // namespace Slic3r

View File

@ -1,70 +1,73 @@
#ifndef slic3r_GLGizmoMove_hpp_ #ifndef slic3r_GLGizmoMove_hpp_
#define slic3r_GLGizmoMove_hpp_ #define slic3r_GLGizmoMove_hpp_
#include "GLGizmoBase.hpp" #include "GLGizmoBase.hpp"
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
class GLGizmoMove3D : public GLGizmoBase class GLGizmoMove3D : public GLGizmoBase
{ {
static const double Offset; static const double Offset;
Vec3d m_displacement{ Vec3d::Zero() }; Vec3d m_displacement{ Vec3d::Zero() };
double m_snap_step{ 1.0 }; double m_snap_step{ 1.0 };
Vec3d m_starting_drag_position{ Vec3d::Zero() }; Vec3d m_starting_drag_position{ Vec3d::Zero() };
Vec3d m_starting_box_center{ Vec3d::Zero() }; Vec3d m_starting_box_center{ Vec3d::Zero() };
Vec3d m_starting_box_bottom_center{ Vec3d::Zero() }; Vec3d m_starting_box_bottom_center{ Vec3d::Zero() };
GLModel m_cone; #if !ENABLE_GIZMO_GRABBER_REFACTOR
#if ENABLE_LEGACY_OPENGL_REMOVAL GLModel m_cone;
struct GrabberConnection #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
{ #if ENABLE_LEGACY_OPENGL_REMOVAL
GLModel model; struct GrabberConnection
Vec3d old_center{ Vec3d::Zero() }; {
}; GLModel model;
std::array<GrabberConnection, 3> m_grabber_connections; Vec3d old_center{ Vec3d::Zero() };
#endif // ENABLE_LEGACY_OPENGL_REMOVAL };
std::array<GrabberConnection, 3> m_grabber_connections;
public: #endif // ENABLE_LEGACY_OPENGL_REMOVAL
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
virtual ~GLGizmoMove3D() = default; public:
GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
double get_snap_step(double step) const { return m_snap_step; } virtual ~GLGizmoMove3D() = default;
void set_snap_step(double step) { m_snap_step = step; }
double get_snap_step(double step) const { return m_snap_step; }
std::string get_tooltip() const override; void set_snap_step(double step) { m_snap_step = step; }
/// <summary> std::string get_tooltip() const override;
/// Postpone to Grabber for move
/// </summary> /// <summary>
/// <param name="mouse_event">Keep information about mouse click</param> /// Postpone to Grabber for move
/// <returns>Return True when use the information otherwise False.</returns> /// </summary>
bool on_mouse(const wxMouseEvent &mouse_event) override; /// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
/// <summary> bool on_mouse(const wxMouseEvent &mouse_event) override;
/// Detect reduction of move for wipetover on selection change
/// </summary> /// <summary>
void data_changed() override; /// Detect reduction of move for wipetover on selection change
protected: /// </summary>
bool on_init() override; void data_changed() override;
std::string on_get_name() const override;
bool on_is_activable() const override; protected:
void on_start_dragging() override; bool on_init() override;
void on_stop_dragging() override; std::string on_get_name() const override;
void on_dragging(const UpdateData& data) override; bool on_is_activable() const override;
void on_render() override; void on_start_dragging() override;
void on_render_for_picking() override; void on_stop_dragging() override;
void on_dragging(const UpdateData& data) override;
private: void on_render() override;
double calc_projection(const UpdateData& data) const; void on_render_for_picking() override;
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking);
}; private:
double calc_projection(const UpdateData& data) const;
#if !ENABLE_GIZMO_GRABBER_REFACTOR
void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking);
} // namespace GUI #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
} // namespace Slic3r };
#endif // slic3r_GLGizmoMove_hpp_ } // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoMove_hpp_

File diff suppressed because it is too large Load Diff

View File

@ -1,213 +1,218 @@
#ifndef slic3r_GLGizmoRotate_hpp_ #ifndef slic3r_GLGizmoRotate_hpp_
#define slic3r_GLGizmoRotate_hpp_ #define slic3r_GLGizmoRotate_hpp_
#include "GLGizmoBase.hpp" #include "GLGizmoBase.hpp"
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
class Selection; class Selection;
class GLGizmoRotate : public GLGizmoBase class GLGizmoRotate : public GLGizmoBase
{ {
static const float Offset; static const float Offset;
static const unsigned int AngleResolution; static const unsigned int AngleResolution;
static const unsigned int ScaleStepsCount; static const unsigned int ScaleStepsCount;
static const float ScaleStepRad; static const float ScaleStepRad;
static const unsigned int ScaleLongEvery; static const unsigned int ScaleLongEvery;
static const float ScaleLongTooth; static const float ScaleLongTooth;
static const unsigned int SnapRegionsCount; static const unsigned int SnapRegionsCount;
static const float GrabberOffset; static const float GrabberOffset;
public: public:
enum Axis : unsigned char enum Axis : unsigned char
{ {
X=0, X=0,
Y=1, Y=1,
Z=2 Z=2
}; };
private: private:
Axis m_axis; Axis m_axis;
double m_angle{ 0.0 }; double m_angle{ 0.0 };
Vec3d m_center{ Vec3d::Zero() }; Vec3d m_center{ Vec3d::Zero() };
float m_radius{ 0.0f }; float m_radius{ 0.0f };
float m_snap_coarse_in_radius{ 0.0f }; float m_snap_coarse_in_radius{ 0.0f };
float m_snap_coarse_out_radius{ 0.0f }; float m_snap_coarse_out_radius{ 0.0f };
float m_snap_fine_in_radius{ 0.0f }; float m_snap_fine_in_radius{ 0.0f };
float m_snap_fine_out_radius{ 0.0f }; float m_snap_fine_out_radius{ 0.0f };
GLModel m_cone; #if !ENABLE_GIZMO_GRABBER_REFACTOR
#if ENABLE_LEGACY_OPENGL_REMOVAL GLModel m_cone;
GLModel m_circle; #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
GLModel m_scale; #if ENABLE_LEGACY_OPENGL_REMOVAL
GLModel m_snap_radii; GLModel m_circle;
GLModel m_reference_radius; GLModel m_scale;
GLModel m_angle_arc; GLModel m_snap_radii;
struct GrabberConnection GLModel m_reference_radius;
{ GLModel m_angle_arc;
GLModel model; struct GrabberConnection
Vec3d old_center{ Vec3d::Zero() }; {
}; GLModel model;
GrabberConnection m_grabber_connection; Vec3d old_center{ Vec3d::Zero() };
float m_old_radius{ 0.0f }; };
float m_old_hover_radius{ 0.0f }; GrabberConnection m_grabber_connection;
float m_old_angle{ 0.0f }; float m_old_radius{ 0.0f };
#endif // ENABLE_LEGACY_OPENGL_REMOVAL float m_old_hover_radius{ 0.0f };
float m_old_angle{ 0.0f };
ColorRGBA m_drag_color; #endif // ENABLE_LEGACY_OPENGL_REMOVAL
ColorRGBA m_highlight_color;
public: ColorRGBA m_drag_color;
GLGizmoRotate(GLCanvas3D& parent, Axis axis); ColorRGBA m_highlight_color;
virtual ~GLGizmoRotate() = default;
public:
double get_angle() const { return m_angle; } GLGizmoRotate(GLCanvas3D& parent, Axis axis);
void set_angle(double angle); virtual ~GLGizmoRotate() = default;
std::string get_tooltip() const override; double get_angle() const { return m_angle; }
void set_angle(double angle);
void start_dragging();
void stop_dragging(); std::string get_tooltip() const override;
void enable_grabber(); void start_dragging();
void disable_grabber(); void stop_dragging();
void set_highlight_color(const ColorRGBA &color); void enable_grabber();
void disable_grabber();
/// <summary>
/// Postpone to Grabber for move void set_highlight_color(const ColorRGBA &color);
/// Detect move of object by dragging
/// </summary> /// <summary>
/// <param name="mouse_event">Keep information about mouse click</param> /// Postpone to Grabber for move
/// <returns>Return True when use the information otherwise False.</returns> /// Detect move of object by dragging
bool on_mouse(const wxMouseEvent &mouse_event) override; /// </summary>
void dragging(const UpdateData &data); /// <param name="mouse_event">Keep information about mouse click</param>
protected: /// <returns>Return True when use the information otherwise False.</returns>
bool on_init() override; bool on_mouse(const wxMouseEvent &mouse_event) override;
std::string on_get_name() const override { return ""; } void dragging(const UpdateData &data);
void on_start_dragging() override; protected:
void on_dragging(const UpdateData &data) override; bool on_init() override;
void on_render() override; std::string on_get_name() const override { return ""; }
void on_render_for_picking() override; void on_start_dragging() override;
void on_dragging(const UpdateData &data) override;
private: void on_render() override;
#if ENABLE_LEGACY_OPENGL_REMOVAL void on_render_for_picking() override;
void render_circle(const ColorRGBA& color, bool radius_changed);
void render_scale(const ColorRGBA& color, bool radius_changed); private:
void render_snap_radii(const ColorRGBA& color, bool radius_changed); #if ENABLE_LEGACY_OPENGL_REMOVAL
void render_reference_radius(const ColorRGBA& color, bool radius_changed); void render_circle(const ColorRGBA& color, bool radius_changed);
void render_angle_arc(const ColorRGBA& color, bool radius_changed); void render_scale(const ColorRGBA& color, bool radius_changed);
void render_grabber_connection(const ColorRGBA& color, bool radius_changed); void render_snap_radii(const ColorRGBA& color, bool radius_changed);
#else void render_reference_radius(const ColorRGBA& color, bool radius_changed);
void render_circle() const; void render_angle_arc(const ColorRGBA& color, bool radius_changed);
void render_scale() const; void render_grabber_connection(const ColorRGBA& color, bool radius_changed);
void render_snap_radii() const; #else
void render_reference_radius() const; void render_circle() const;
void render_angle() const; void render_scale() const;
#endif // ENABLE_LEGACY_OPENGL_REMOVAL void render_snap_radii() const;
void render_grabber(const BoundingBoxf3& box); void render_reference_radius() const;
void render_grabber_extension(const BoundingBoxf3& box, bool picking); void render_angle() const;
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_GL_SHADERS_ATTRIBUTES void render_grabber(const BoundingBoxf3& box);
Transform3d local_transform(const Selection& selection) const; #if !ENABLE_GIZMO_GRABBER_REFACTOR
#else void render_grabber_extension(const BoundingBoxf3& box, bool picking);
void transform_to_local(const Selection& selection) const; #endif // !ENABLE_GIZMO_GRABBER_REFACTOR
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
#if ENABLE_GL_SHADERS_ATTRIBUTES
// returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate Transform3d local_transform(const Selection& selection) const;
Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const; #else
}; void transform_to_local(const Selection& selection) const;
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
class GLGizmoRotate3D : public GLGizmoBase
{ // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
std::array<GLGizmoRotate, 3> m_gizmos; Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
};
public:
GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); class GLGizmoRotate3D : public GLGizmoBase
{
Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); } std::array<GLGizmoRotate, 3> m_gizmos;
void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
public:
std::string get_tooltip() const override { GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
std::string tooltip = m_gizmos[X].get_tooltip();
if (tooltip.empty()) Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
tooltip = m_gizmos[Y].get_tooltip(); void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
if (tooltip.empty())
tooltip = m_gizmos[Z].get_tooltip(); std::string get_tooltip() const override {
return tooltip; std::string tooltip = m_gizmos[X].get_tooltip();
} if (tooltip.empty())
tooltip = m_gizmos[Y].get_tooltip();
/// <summary> if (tooltip.empty())
/// Postpone to Rotation tooltip = m_gizmos[Z].get_tooltip();
/// </summary> return tooltip;
/// <param name="mouse_event">Keep information about mouse click</param> }
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override; /// <summary>
/// Postpone to Rotation
void data_changed() override; /// </summary>
protected: /// <param name="mouse_event">Keep information about mouse click</param>
bool on_init() override; /// <returns>Return True when use the information otherwise False.</returns>
std::string on_get_name() const override; bool on_mouse(const wxMouseEvent &mouse_event) override;
void on_set_state() override {
for (GLGizmoRotate& g : m_gizmos) void data_changed() override;
g.set_state(m_state); protected:
} bool on_init() override;
void on_set_hover_id() override { std::string on_get_name() const override;
for (int i = 0; i < 3; ++i) void on_set_state() override {
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); for (GLGizmoRotate& g : m_gizmos)
} g.set_state(m_state);
void on_enable_grabber(unsigned int id) override { }
if (id < 3) void on_set_hover_id() override {
m_gizmos[id].enable_grabber(); for (int i = 0; i < 3; ++i)
} m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
void on_disable_grabber(unsigned int id) override { }
if (id < 3) void on_enable_grabber(unsigned int id) override {
m_gizmos[id].disable_grabber(); if (id < 3)
} m_gizmos[id].enable_grabber();
bool on_is_activable() const override; }
void on_start_dragging() override; void on_disable_grabber(unsigned int id) override {
void on_stop_dragging() override; if (id < 3)
void on_dragging(const UpdateData &data) override; m_gizmos[id].disable_grabber();
}
void on_render() override; bool on_is_activable() const override;
void on_render_for_picking() override { void on_start_dragging() override;
for (GLGizmoRotate& g : m_gizmos) { void on_stop_dragging() override;
g.render_for_picking(); void on_dragging(const UpdateData &data) override;
}
} void on_render() override;
void on_render_for_picking() override {
void on_render_input_window(float x, float y, float bottom_limit) override; for (GLGizmoRotate& g : m_gizmos) {
g.render_for_picking();
private: }
}
class RotoptimzeWindow
{ void on_render_input_window(float x, float y, float bottom_limit) override;
ImGuiWrapper *m_imgui = nullptr;
private:
public:
struct State { class RotoptimzeWindow
float accuracy = 1.f; {
int method_id = 0; ImGuiWrapper *m_imgui = nullptr;
};
public:
struct Alignment { float x, y, bottom_limit; }; struct State {
float accuracy = 1.f;
RotoptimzeWindow(ImGuiWrapper * imgui, int method_id = 0;
State & state, };
const Alignment &bottom_limit);
struct Alignment { float x, y, bottom_limit; };
~RotoptimzeWindow();
RotoptimzeWindow(ImGuiWrapper * imgui,
RotoptimzeWindow(const RotoptimzeWindow&) = delete; State & state,
RotoptimzeWindow(RotoptimzeWindow &&) = delete; const Alignment &bottom_limit);
RotoptimzeWindow& operator=(const RotoptimzeWindow &) = delete;
RotoptimzeWindow& operator=(RotoptimzeWindow &&) = delete; ~RotoptimzeWindow();
};
RotoptimzeWindow(const RotoptimzeWindow&) = delete;
RotoptimzeWindow::State m_rotoptimizewin_state = {}; RotoptimzeWindow(RotoptimzeWindow &&) = delete;
RotoptimzeWindow& operator=(const RotoptimzeWindow &) = delete;
void load_rotoptimize_state(); RotoptimzeWindow& operator=(RotoptimzeWindow &&) = delete;
}; };
} // namespace GUI RotoptimzeWindow::State m_rotoptimizewin_state = {};
} // namespace Slic3r
void load_rotoptimize_state();
#endif // slic3r_GLGizmoRotate_hpp_ };
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoRotate_hpp_