From 62894d3f7b841436c1fb849336b4e0dd15726fad Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 7 Sep 2018 16:05:10 +0200 Subject: [PATCH 1/9] Export the first M73 line to gcode before custom gcode --- xs/src/libslic3r/GCode.cpp | 9 ++++++++- xs/src/libslic3r/GCodeTimeEstimator.cpp | 13 ++++++++++++- xs/src/libslic3r/GCodeTimeEstimator.hpp | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b34ba5441..67a682d18 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -665,6 +665,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) _write_format(file, "\n"); } + // adds tags for time estimators + if (print.config.remaining_times.value) + { + _writeln(file, GCodeTimeEstimator::Normal_First_M73_Output_Placeholder_Tag); + if (m_silent_time_estimator_enabled) + _writeln(file, GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag); + } + // Prepare the helper object for replacing placeholders in custom G-code and output filename. m_placeholder_parser = print.placeholder_parser; m_placeholder_parser.update_timestamp(); @@ -724,7 +732,6 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) m_placeholder_parser.set("has_wipe_tower", has_wipe_tower); m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config.single_extruder_multi_material_priming); std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config.start_gcode.value, initial_extruder_id); - // Set bed temperature if the start G-code does not contain any bed temp control G-codes. this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true); // Set extruder(s) temperature before and after start G-code. diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp index c4ffb572a..f4f6472e5 100644 --- a/xs/src/libslic3r/GCodeTimeEstimator.cpp +++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp @@ -168,6 +168,9 @@ namespace Slic3r { } #endif // ENABLE_MOVE_STATS + const std::string GCodeTimeEstimator::Normal_First_M73_Output_Placeholder_Tag = "; NORMAL_FIRST_M73_OUTPUT_PLACEHOLDER"; + const std::string GCodeTimeEstimator::Silent_First_M73_Output_Placeholder_Tag = "; SILENT_FIRST_M73_OUTPUT_PLACEHOLDER"; + GCodeTimeEstimator::GCodeTimeEstimator(EMode mode) : _mode(mode) { @@ -294,7 +297,15 @@ namespace Slic3r { throw std::runtime_error(std::string("Remaining times export failed.\nError while reading from file.\n")); } - gcode_line += "\n"; + // replaces placeholders for initial line M73 with the real lines + if (((_mode == Normal) && (gcode_line == Normal_First_M73_Output_Placeholder_Tag)) || + ((_mode == Silent) && (gcode_line == Silent_First_M73_Output_Placeholder_Tag))) + { + sprintf(time_line, time_mask.c_str(), std::to_string(0), _get_time_minutes(_time).c_str()); + gcode_line = time_line; + } + else + gcode_line += "\n"; // add remaining time lines where needed _parser.parse_line(gcode_line, diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/xs/src/libslic3r/GCodeTimeEstimator.hpp index 1fa74e304..e9da584c3 100644 --- a/xs/src/libslic3r/GCodeTimeEstimator.hpp +++ b/xs/src/libslic3r/GCodeTimeEstimator.hpp @@ -17,6 +17,9 @@ namespace Slic3r { class GCodeTimeEstimator { public: + static const std::string Normal_First_M73_Output_Placeholder_Tag; + static const std::string Silent_First_M73_Output_Placeholder_Tag; + enum EMode : unsigned char { Normal, From 5e8bd4798834d0d5f22afb58acb13dd081585742 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 10 Sep 2018 10:01:49 +0200 Subject: [PATCH 2/9] Partial refactoring of 3d gizmos --- xs/src/slic3r/GUI/GLCanvas3D.cpp | 23 +----- xs/src/slic3r/GUI/GLCanvas3D.hpp | 3 +- xs/src/slic3r/GUI/GLGizmo.cpp | 129 +++++++++++++------------------ xs/src/slic3r/GUI/GLGizmo.hpp | 74 +++++++++--------- 4 files changed, 91 insertions(+), 138 deletions(-) diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index edc5bc78e..161ce89da 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1320,16 +1320,6 @@ void GLCanvas3D::Gizmos::update(const Linef3& mouse_ray) curr->update(mouse_ray); } -void GLCanvas3D::Gizmos::refresh() -{ - if (!m_enabled) - return; - - GLGizmoBase* curr = _get_current(); - if (curr != nullptr) - curr->refresh(); -} - GLCanvas3D::Gizmos::EType GLCanvas3D::Gizmos::get_current_type() const { return m_current; @@ -1349,12 +1339,12 @@ bool GLCanvas3D::Gizmos::is_dragging() const return m_dragging; } -void GLCanvas3D::Gizmos::start_dragging() +void GLCanvas3D::Gizmos::start_dragging(const BoundingBoxf3& box) { m_dragging = true; GLGizmoBase* curr = _get_current(); if (curr != nullptr) - curr->start_dragging(); + curr->start_dragging(box); } void GLCanvas3D::Gizmos::stop_dragging() @@ -2487,8 +2477,6 @@ void GLCanvas3D::reload_scene(bool force) if (!m_objects_selections.empty()) update_gizmos_data(); - m_gizmos.refresh(); - if (m_config->has("nozzle_diameter")) { // Should the wipe tower be visualized ? @@ -3019,7 +3007,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse()) { update_gizmos_data(); - m_gizmos.start_dragging(); + m_gizmos.start_dragging(_selected_volumes_bounding_box()); m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx); if (m_gizmos.get_current_type() == Gizmos::Flatten) { @@ -3062,7 +3050,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } update_gizmos_data(); - m_gizmos.refresh(); m_dirty = true; } } @@ -3158,7 +3145,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) update_position_values(volume->get_offset()); m_mouse.drag.start_position_3D = cur_pos; - m_gizmos.refresh(); m_dirty = true; } @@ -3226,9 +3212,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale()); } - if ((m_gizmos.get_current_type() != Gizmos::Rotate) && (volumes.size() > 1)) - m_gizmos.refresh(); - m_dirty = true; } else if (evt.Dragging() && !gizmos_overlay_contains_mouse) diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 541495eec..c5b4581fa 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -367,14 +367,13 @@ public: bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; bool grabber_contains_mouse() const; void update(const Linef3& mouse_ray); - void refresh(); EType get_current_type() const; bool is_running() const; bool is_dragging() const; - void start_dragging(); + void start_dragging(const BoundingBoxf3& box); void stop_dragging(); float get_scale() const; diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 4e8a6d3d5..ff0adac62 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -129,6 +129,7 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent) , m_group_id(-1) , m_state(Off) , m_hover_id(-1) + , m_dragging(false) { ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float)); ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float)); @@ -150,18 +151,21 @@ void GLGizmoBase::set_highlight_color(const float* color) ::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float)); } -void GLGizmoBase::start_dragging() +void GLGizmoBase::start_dragging(const BoundingBoxf3& box) { + m_dragging = true; + for (int i = 0; i < (int)m_grabbers.size(); ++i) { m_grabbers[i].dragging = (m_hover_id == i); } - on_start_dragging(); + on_start_dragging(box); } void GLGizmoBase::stop_dragging() { + m_dragging = false; set_tooltip(""); for (int i = 0; i < (int)m_grabbers.size(); ++i) @@ -235,7 +239,6 @@ GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) , m_angle(0.0) , m_center(0.0, 0.0, 0.0) , m_radius(0.0f) - , m_keep_initial_values(false) { } @@ -253,6 +256,12 @@ bool GLGizmoRotate::on_init() return true; } +void GLGizmoRotate::on_start_dragging(const BoundingBoxf3& box) +{ + m_center = box.center(); + m_radius = Offset + box.radius(); +} + void GLGizmoRotate::on_update(const Linef3& mouse_ray) { Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(mouse_ray)); @@ -294,18 +303,16 @@ void GLGizmoRotate::on_update(const Linef3& mouse_ray) void GLGizmoRotate::on_render(const BoundingBoxf3& box) const { - if (m_grabbers[0].dragging) + if (m_dragging) set_tooltip(format(m_angle * 180.0f / (float)PI, 4)); - - ::glEnable(GL_DEPTH_TEST); - - if (!m_keep_initial_values) + else { m_center = box.center(); m_radius = Offset + box.radius(); - m_keep_initial_values = true; } + ::glEnable(GL_DEPTH_TEST); + ::glPushMatrix(); transform_to_local(); @@ -509,23 +516,29 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray) cons GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent) : GLGizmoBase(parent) - , m_x(parent, GLGizmoRotate::X) - , m_y(parent, GLGizmoRotate::Y) - , m_z(parent, GLGizmoRotate::Z) { - m_x.set_group_id(0); - m_y.set_group_id(1); - m_z.set_group_id(2); + m_gizmos.emplace_back(parent, GLGizmoRotate::X); + m_gizmos.emplace_back(parent, GLGizmoRotate::Y); + m_gizmos.emplace_back(parent, GLGizmoRotate::Z); + + for (unsigned int i = 0; i < 3; ++i) + { + m_gizmos[i].set_group_id(i); + } } bool GLGizmoRotate3D::on_init() { - if (!m_x.init() || !m_y.init() || !m_z.init()) - return false; + for (GLGizmoRotate& g : m_gizmos) + { + if (!g.init()) + return false; + } - m_x.set_highlight_color(AXES_COLOR[0]); - m_y.set_highlight_color(AXES_COLOR[1]); - m_z.set_highlight_color(AXES_COLOR[2]); + for (unsigned int i = 0; i < 3; ++i) + { + m_gizmos[i].set_highlight_color(AXES_COLOR[i]); + } std::string path = resources_dir() + "/icons/overlay/"; @@ -544,68 +557,28 @@ bool GLGizmoRotate3D::on_init() return true; } -void GLGizmoRotate3D::on_start_dragging() +void GLGizmoRotate3D::on_start_dragging(const BoundingBoxf3& box) { - switch (m_hover_id) - { - case 0: - { - m_x.start_dragging(); - break; - } - case 1: - { - m_y.start_dragging(); - break; - } - case 2: - { - m_z.start_dragging(); - break; - } - default: - { - break; - } - } + if ((0 <= m_hover_id) && (m_hover_id < 3)) + m_gizmos[m_hover_id].start_dragging(box); } void GLGizmoRotate3D::on_stop_dragging() { - switch (m_hover_id) - { - case 0: - { - m_x.stop_dragging(); - break; - } - case 1: - { - m_y.stop_dragging(); - break; - } - case 2: - { - m_z.stop_dragging(); - break; - } - default: - { - break; - } - } + if ((0 <= m_hover_id) && (m_hover_id < 3)) + m_gizmos[m_hover_id].stop_dragging(); } void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const { if ((m_hover_id == -1) || (m_hover_id == 0)) - m_x.render(box); + m_gizmos[X].render(box); if ((m_hover_id == -1) || (m_hover_id == 1)) - m_y.render(box); + m_gizmos[Y].render(box); if ((m_hover_id == -1) || (m_hover_id == 2)) - m_z.render(box); + m_gizmos[Z].render(box); } const float GLGizmoScale3D::Offset = 5.0f; @@ -652,13 +625,13 @@ bool GLGizmoScale3D::on_init() return true; } -void GLGizmoScale3D::on_start_dragging() +void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box) { if (m_hover_id != -1) { m_starting_drag_position = m_grabbers[m_hover_id].center; m_show_starting_box = true; - m_starting_box = m_box; + m_starting_box = box; } } @@ -989,7 +962,8 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent) : GLGizmoBase(parent) - , m_normal(0.0, 0.0, 0.0) + , m_normal(Vec3d::Zero()) + , m_center(Vec3d::Zero()) { } @@ -1012,10 +986,13 @@ bool GLGizmoFlatten::on_init() return true; } -void GLGizmoFlatten::on_start_dragging() +void GLGizmoFlatten::on_start_dragging(const BoundingBoxf3& box) { if (m_hover_id != -1) + { m_normal = m_planes[m_hover_id].normal; + m_center = box.center(); + } } void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const @@ -1023,10 +1000,9 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const // the dragged_offset is a vector measuring where was the object moved // with the gizmo being on. This is reset in set_flattening_data and // does not work correctly when there are multiple copies. - if (!m_center) // this is the first bounding box that we see - m_center.reset(new Vec3d(box.center())); - - Vec3d dragged_offset = box.center() - *m_center; + Vec3d dragged_offset(Vec3d::Zero()); + if (m_dragging) + dragged_offset = box.center() - m_center; ::glEnable(GL_BLEND); ::glEnable(GL_DEPTH_TEST); @@ -1073,7 +1049,6 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { - m_center.release(); // object is not being dragged (this would not be called otherwise) - we must forget about the bounding box position... m_model_object = model_object; // ...and save the updated positions of the object instances: diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 3041f2adf..82a004b5b 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -57,6 +57,7 @@ protected: // textures are assumed to be square and all with the same size in pixels, no internal check is done GLTexture m_textures[Num_States]; int m_hover_id; + bool m_dragging; float m_base_color[3]; float m_drag_color[3]; float m_highlight_color[3]; @@ -82,10 +83,11 @@ public: void set_highlight_color(const float* color); - void start_dragging(); + void start_dragging(const BoundingBoxf3& box); void stop_dragging(); + bool is_dragging() const { return m_dragging; } + void update(const Linef3& mouse_ray); - void refresh() { on_refresh(); } void render(const BoundingBoxf3& box) const { on_render(box); } void render_for_picking(const BoundingBoxf3& box) const { on_render_for_picking(box); } @@ -94,10 +96,9 @@ protected: virtual bool on_init() = 0; virtual void on_set_state() {} virtual void on_set_hover_id() {} - virtual void on_start_dragging() {} + virtual void on_start_dragging(const BoundingBoxf3& box) {} virtual void on_stop_dragging() {} virtual void on_update(const Linef3& mouse_ray) = 0; - virtual void on_refresh() {} virtual void on_render(const BoundingBoxf3& box) const = 0; virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0; @@ -136,7 +137,6 @@ private: mutable Vec3d m_center; mutable float m_radius; - mutable bool m_keep_initial_values; public: GLGizmoRotate(GLCanvas3D& parent, Axis axis); @@ -146,9 +146,8 @@ public: protected: virtual bool on_init(); - virtual void on_set_state() { m_keep_initial_values = (m_state == On) ? false : true; } + virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_update(const Linef3& mouse_ray); - virtual void on_refresh() { m_keep_initial_values = false; } virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; @@ -167,56 +166,52 @@ private: class GLGizmoRotate3D : public GLGizmoBase { - GLGizmoRotate m_x; - GLGizmoRotate m_y; - GLGizmoRotate m_z; + std::vector m_gizmos; public: explicit GLGizmoRotate3D(GLCanvas3D& parent); - double get_angle_x() const { return m_x.get_angle(); } - void set_angle_x(double angle) { m_x.set_angle(angle); } + double get_angle_x() const { return m_gizmos[X].get_angle(); } + void set_angle_x(double angle) { m_gizmos[X].set_angle(angle); } - double get_angle_y() const { return m_y.get_angle(); } - void set_angle_y(double angle) { m_y.set_angle(angle); } + double get_angle_y() const { return m_gizmos[Y].get_angle(); } + void set_angle_y(double angle) { m_gizmos[Y].set_angle(angle); } - double get_angle_z() const { return m_z.get_angle(); } - void set_angle_z(double angle) { m_z.set_angle(angle); } + double get_angle_z() const { return m_gizmos[Z].get_angle(); } + void set_angle_z(double angle) { m_gizmos[Z].set_angle(angle); } protected: virtual bool on_init(); virtual void on_set_state() { - m_x.set_state(m_state); - m_y.set_state(m_state); - m_z.set_state(m_state); + for (GLGizmoRotate& g : m_gizmos) + { + g.set_state(m_state); + } } virtual void on_set_hover_id() { - m_x.set_hover_id(m_hover_id == 0 ? 0 : -1); - m_y.set_hover_id(m_hover_id == 1 ? 0 : -1); - m_z.set_hover_id(m_hover_id == 2 ? 0 : -1); + for (unsigned int i = 0; i < 3; ++i) + { + m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); + } } - virtual void on_start_dragging(); + virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_stop_dragging(); virtual void on_update(const Linef3& mouse_ray) { - m_x.update(mouse_ray); - m_y.update(mouse_ray); - m_z.update(mouse_ray); - } - virtual void on_refresh() - { - m_x.refresh(); - m_y.refresh(); - m_z.refresh(); + for (GLGizmoRotate& g : m_gizmos) + { + g.update(mouse_ray); + } } virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const { - m_x.render_for_picking(box); - m_y.render_for_picking(box); - m_z.render_for_picking(box); + for (const GLGizmoRotate& g : m_gizmos) + { + g.render_for_picking(box); + } } }; @@ -249,7 +244,7 @@ public: protected: virtual bool on_init(); - virtual void on_start_dragging(); + virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_stop_dragging() { m_show_starting_box = false; } virtual void on_update(const Linef3& mouse_ray); virtual void on_render(const BoundingBoxf3& box) const; @@ -291,7 +286,7 @@ private: std::vector m_planes; std::vector m_instances_positions; - mutable std::unique_ptr m_center = nullptr; + Vec3d m_center; const ModelObject* m_model_object = nullptr; void update_planes(); @@ -305,11 +300,12 @@ public: protected: virtual bool on_init(); - virtual void on_start_dragging(); + virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_update(const Linef3& mouse_ray) {} virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; - virtual void on_set_state() { + virtual void on_set_state() + { if (m_state == On && is_plane_update_necessary()) update_planes(); } From d8936b1ad8e14372e911c7a7ebb7f1adc30ceae3 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 10 Sep 2018 11:58:24 +0200 Subject: [PATCH 3/9] Another partial refactoring of 3d gizmos --- xs/src/slic3r/GUI/GLGizmo.cpp | 154 ++++++++++++++++++++-------------- xs/src/slic3r/GUI/GLGizmo.hpp | 2 +- 2 files changed, 93 insertions(+), 63 deletions(-) diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index ff0adac62..1d02e1752 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -20,7 +20,90 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f namespace Slic3r { namespace GUI { -const float GLGizmoBase::Grabber::HalfSize = 2.0f; + // returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center + // coordinates are local to the plane + Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center) + { + Transform3d m = Transform3d::Identity(); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0); + } + + // returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center + // coordinates are local to the plane + Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center) + { + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1)); + } + + // returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center + // coordinates are local to the plane + Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center) + { + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + + return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0)); + } + + // return an index: + // 0 for plane XY + // 1 for plane XZ + // 2 for plane YZ + // which indicates which plane is best suited for intersecting the given unit vector + // giving precedence to the plane with the given index + unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane) + { + unsigned int ret = preferred_plane; + + // 1st checks if the given vector is not parallel to the given preferred plane + double dot_to_normal = 0.0; + switch (ret) + { + case 0: // plane xy + { + dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ())); + break; + } + case 1: // plane xz + { + dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY())); + break; + } + case 2: // plane yz + { + dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX())); + break; + } + default: + { + break; + } + } + + // if almost parallel, select the plane whose normal direction is closest to the given vector direction, + // otherwise return the given preferred plane index + if (dot_to_normal < 0.1) + { + typedef std::map ProjsMap; + ProjsMap projs_map; + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz + ret = projs_map.rbegin()->second; + } + + return ret; + } + + const float GLGizmoBase::Grabber::HalfSize = 2.0f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; GLGizmoBase::Grabber::Grabber() @@ -881,77 +964,24 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& Vec3d starting_vec_dir = starting_vec.normalized(); Vec3d mouse_dir = mouse_ray.unit_vector(); - unsigned int plane_id = preferred_plane_id; - // 1st try to see if the mouse direction is close enough to the preferred plane normal - double dot_to_normal = 0.0; + unsigned int plane_id = select_best_plane(mouse_dir, preferred_plane_id); + // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length switch (plane_id) { case 0: { - dot_to_normal = std::abs(mouse_dir.dot(Vec3d::UnitZ())); + ratio = starting_vec_dir.dot(intersection_on_plane_xy(mouse_ray, center)) / len_starting_vec; break; } case 1: { - dot_to_normal = std::abs(mouse_dir.dot(-Vec3d::UnitY())); + ratio = starting_vec_dir.dot(intersection_on_plane_xz(mouse_ray, center)) / len_starting_vec; break; } case 2: { - dot_to_normal = std::abs(mouse_dir.dot(Vec3d::UnitX())); - break; - } - } - - if (dot_to_normal < 0.1) - { - // if not, select the plane who's normal is closest to the mouse direction - - typedef std::map ProjsMap; - ProjsMap projs_map; - - projs_map.insert(ProjsMap::value_type(std::abs(mouse_dir.dot(Vec3d::UnitZ())), 0)); // plane xy - projs_map.insert(ProjsMap::value_type(std::abs(mouse_dir.dot(-Vec3d::UnitY())), 1)); // plane xz - projs_map.insert(ProjsMap::value_type(std::abs(mouse_dir.dot(Vec3d::UnitX())), 2)); // plane yz - plane_id = projs_map.rbegin()->second; - } - - switch (plane_id) - { - case 0: - { - // calculates the intersection of the mouse ray with the plane parallel to plane XY and passing through the given center - Transform3d m = Transform3d::Identity(); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(mouse_ray, m).intersect_plane(0.0)); - - // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length - ratio = starting_vec_dir.dot(Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0)) / len_starting_vec; - break; - } - case 1: - { - // calculates the intersection of the mouse ray with the plane parallel to plane XZ and passing through the given center - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(mouse_ray, m).intersect_plane(0.0)); - - // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length - ratio = starting_vec_dir.dot(Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1))) / len_starting_vec; - break; - } - case 2: - { - // calculates the intersection of the mouse ray with the plane parallel to plane YZ and passing through the given center - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(mouse_ray, m).intersect_plane(0.0)); - - // ratio is given by the projection of the calculated intersection on the starting vector divided by the starting vector length - ratio = starting_vec_dir.dot(Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0))) / len_starting_vec; + ratio = starting_vec_dir.dot(intersection_on_plane_yz(mouse_ray, center)) / len_starting_vec; break; } } @@ -963,7 +993,7 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent) : GLGizmoBase(parent) , m_normal(Vec3d::Zero()) - , m_center(Vec3d::Zero()) + , m_starting_center(Vec3d::Zero()) { } @@ -991,7 +1021,7 @@ void GLGizmoFlatten::on_start_dragging(const BoundingBoxf3& box) if (m_hover_id != -1) { m_normal = m_planes[m_hover_id].normal; - m_center = box.center(); + m_starting_center = box.center(); } } @@ -1002,7 +1032,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const // does not work correctly when there are multiple copies. Vec3d dragged_offset(Vec3d::Zero()); if (m_dragging) - dragged_offset = box.center() - m_center; + dragged_offset = box.center() - m_starting_center; ::glEnable(GL_BLEND); ::glEnable(GL_DEPTH_TEST); diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 82a004b5b..0599955ed 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -286,7 +286,7 @@ private: std::vector m_planes; std::vector m_instances_positions; - Vec3d m_center; + Vec3d m_starting_center; const ModelObject* m_model_object = nullptr; void update_planes(); From be508b003a5348aaf3c79a7eeb14b3b90f197b41 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 10 Sep 2018 13:15:12 +0200 Subject: [PATCH 4/9] Fixed #1211 --- lib/Slic3r/GUI/Plater.pm | 9 +++++++++ xs/src/libslic3r/Format/3mf.cpp | 2 -- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ee2689d16..e2c95859f 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -767,6 +767,15 @@ sub load_files { $model->convert_multipart_object(scalar(@$nozzle_dmrs)) if $dialog->ShowModal() == wxID_YES; } + # objects imported from 3mf require a call to center_around_origin to have gizmos working properly and this call + # need to be done after looks_like_multipart_object detection + if ($input_file =~ /.3[mM][fF]$/) + { + foreach my $model_object (@{$model->objects}) { + $model_object->center_around_origin; # also aligns object to Z = 0 + } + } + if ($one_by_one) { push @obj_idx, $self->load_model_objects(@{$model->objects}); } else { diff --git a/xs/src/libslic3r/Format/3mf.cpp b/xs/src/libslic3r/Format/3mf.cpp index 945bb1f86..5de1d26c5 100644 --- a/xs/src/libslic3r/Format/3mf.cpp +++ b/xs/src/libslic3r/Format/3mf.cpp @@ -603,8 +603,6 @@ namespace Slic3r { if (!_generate_volumes(*object.second, obj_geometry->second, *volumes_ptr)) return false; - - object.second->center_around_origin(); } // fixes the min z of the model if negative From 78bc688a7fa601900502cf1821bd396e2a946af8 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 10 Sep 2018 13:48:35 +0200 Subject: [PATCH 5/9] Fixed compile on Linux --- xs/src/libslic3r/GCodeTimeEstimator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp index f4f6472e5..7471367fe 100644 --- a/xs/src/libslic3r/GCodeTimeEstimator.cpp +++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp @@ -301,7 +301,7 @@ namespace Slic3r { if (((_mode == Normal) && (gcode_line == Normal_First_M73_Output_Placeholder_Tag)) || ((_mode == Silent) && (gcode_line == Silent_First_M73_Output_Placeholder_Tag))) { - sprintf(time_line, time_mask.c_str(), std::to_string(0), _get_time_minutes(_time).c_str()); + sprintf(time_line, time_mask.c_str(), "0", _get_time_minutes(_time).c_str()); gcode_line = time_line; } else From 781df150a13a4ae3b55109fb728ef469cfbc8f7a Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 10 Sep 2018 14:10:08 +0200 Subject: [PATCH 6/9] Added perl callback for gizmo flatten --- lib/Slic3r/GUI/Plater.pm | 16 ++++++++-------- xs/src/slic3r/GUI/3DScene.cpp | 5 +++++ xs/src/slic3r/GUI/3DScene.hpp | 1 + xs/src/slic3r/GUI/GLCanvas3D.cpp | 9 ++++++++- xs/src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 7 +++++++ xs/src/slic3r/GUI/GLCanvas3DManager.hpp | 1 + xs/xsp/GUI_3DScene.xsp | 7 +++++++ 8 files changed, 39 insertions(+), 9 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 9b3457ef4..951f3bd0f 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -153,16 +153,15 @@ sub new { }; # callback to react to gizmo rotate - # omitting last three parameters means rotation around Z - # otherwise they are the components of the rotation axis vector my $on_gizmo_rotate = sub { + my ($angle) = @_; + $self->rotate(rad2deg($angle), Z, 'absolute'); + }; + + # callback to react to gizmo flatten + my $on_gizmo_flatten = sub { my ($angle, $axis_x, $axis_y, $axis_z) = @_; - if (!defined $axis_x) { - $self->rotate(rad2deg($angle), Z, 'absolute'); - } - else { - $self->rotate(rad2deg($angle), undef, 'absolute', $axis_x, $axis_y, $axis_z) if $angle != 0; - } + $self->rotate(rad2deg($angle), undef, 'absolute', $axis_x, $axis_y, $axis_z) if $angle != 0; }; # callback to update object's geometry info while using gizmos @@ -263,6 +262,7 @@ sub new { Slic3r::GUI::_3DScene::register_on_enable_action_buttons_callback($self->{canvas3D}, $enable_action_buttons); Slic3r::GUI::_3DScene::register_on_gizmo_scale_uniformly_callback($self->{canvas3D}, $on_gizmo_scale_uniformly); Slic3r::GUI::_3DScene::register_on_gizmo_rotate_callback($self->{canvas3D}, $on_gizmo_rotate); + Slic3r::GUI::_3DScene::register_on_gizmo_flatten_callback($self->{canvas3D}, $on_gizmo_flatten); Slic3r::GUI::_3DScene::register_on_update_geometry_info_callback($self->{canvas3D}, $on_update_geometry_info); Slic3r::GUI::_3DScene::register_action_add_callback($self->{canvas3D}, $on_action_add); Slic3r::GUI::_3DScene::register_action_delete_callback($self->{canvas3D}, $on_action_delete); diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 57639fed0..dc2f5dd5a 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -2044,6 +2044,11 @@ void _3DScene::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callb s_canvas_mgr.register_on_gizmo_rotate_callback(canvas, callback); } +void _3DScene::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback) +{ + s_canvas_mgr.register_on_gizmo_flatten_callback(canvas, callback); +} + void _3DScene::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback) { s_canvas_mgr.register_on_update_geometry_info_callback(canvas, callback); diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index ec9d1a501..df749d1bb 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -556,6 +556,7 @@ public: static void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback); static void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback); static void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback); + static void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback); static void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback); static void register_action_add_callback(wxGLCanvas* canvas, void* callback); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 161ce89da..94de895b4 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -2699,6 +2699,12 @@ void GLCanvas3D::register_on_gizmo_rotate_callback(void* callback) m_on_gizmo_rotate_callback.register_callback(callback); } +void GLCanvas3D::register_on_gizmo_flatten_callback(void* callback) +{ + if (callback != nullptr) + m_on_gizmo_flatten_callback.register_callback(callback); +} + void GLCanvas3D::register_on_update_geometry_info_callback(void* callback) { if (callback != nullptr) @@ -3016,7 +3022,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (normal(0) != 0.0 || normal(1) != 0.0 || normal(2) != 0.0) { Vec3d axis = normal(2) > 0.999 ? Vec3d::UnitX() : normal.cross(-Vec3d::UnitZ()).normalized(); float angle = acos(clamp(-1.0, 1.0, -normal(2))); - m_on_gizmo_rotate_callback.call(angle, (float)axis(0), (float)axis(1), (float)axis(2)); + m_on_gizmo_flatten_callback.call(angle, (float)axis(0), (float)axis(1), (float)axis(2)); } } @@ -3759,6 +3765,7 @@ void GLCanvas3D::_deregister_callbacks() m_on_enable_action_buttons_callback.deregister_callback(); m_on_gizmo_scale_uniformly_callback.deregister_callback(); m_on_gizmo_rotate_callback.deregister_callback(); + m_on_gizmo_flatten_callback.deregister_callback(); m_on_update_geometry_info_callback.deregister_callback(); m_action_add_callback.deregister_callback(); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index c5b4581fa..55a3075ce 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -501,6 +501,7 @@ private: PerlCallback m_on_enable_action_buttons_callback; PerlCallback m_on_gizmo_scale_uniformly_callback; PerlCallback m_on_gizmo_rotate_callback; + PerlCallback m_on_gizmo_flatten_callback; PerlCallback m_on_update_geometry_info_callback; PerlCallback m_action_add_callback; @@ -623,6 +624,7 @@ public: void register_on_enable_action_buttons_callback(void* callback); void register_on_gizmo_scale_uniformly_callback(void* callback); void register_on_gizmo_rotate_callback(void* callback); + void register_on_gizmo_flatten_callback(void* callback); void register_on_update_geometry_info_callback(void* callback); void register_action_add_callback(void* callback); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index a09d83b89..3445d4b65 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -700,6 +700,13 @@ void GLCanvas3DManager::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, vo it->second->register_on_gizmo_rotate_callback(callback); } +void GLCanvas3DManager::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->register_on_gizmo_flatten_callback(callback); +} + void GLCanvas3DManager::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback) { CanvasesMap::iterator it = _get_canvas(canvas); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp index 1c715a9a3..b808c022e 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -163,6 +163,7 @@ public: void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback); void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback); void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback); + void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback); void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback); void register_action_add_callback(wxGLCanvas* canvas, void* callback); diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 756f9e547..4c3c5501e 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -651,6 +651,13 @@ register_on_gizmo_rotate_callback(canvas, callback) CODE: _3DScene::register_on_gizmo_rotate_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); +void +register_on_gizmo_flatten_callback(canvas, callback) + SV *canvas; + SV *callback; + CODE: + _3DScene::register_on_gizmo_flatten_callback((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), (void*)callback); + void register_on_update_geometry_info_callback(canvas, callback) SV *canvas; From 4479c5444a26f5ad77a16b26ed18bd61e24db592 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 11 Sep 2018 09:00:28 +0200 Subject: [PATCH 7/9] 1st installment of gizmo move 3D --- resources/icons/overlay/move_hover.png | Bin 0 -> 2812 bytes resources/icons/overlay/move_off.png | Bin 0 -> 2769 bytes resources/icons/overlay/move_on.png | Bin 0 -> 2447 bytes xs/src/slic3r/GUI/3DScene.cpp | 23 +++- xs/src/slic3r/GUI/3DScene.hpp | 2 + xs/src/slic3r/GUI/GLCanvas3D.cpp | 81 +++++++++++-- xs/src/slic3r/GUI/GLCanvas3D.hpp | 6 +- xs/src/slic3r/GUI/GLGizmo.cpp | 151 +++++++++++++++++++++++++ xs/src/slic3r/GUI/GLGizmo.hpp | 25 ++++ 9 files changed, 275 insertions(+), 13 deletions(-) create mode 100644 resources/icons/overlay/move_hover.png create mode 100644 resources/icons/overlay/move_off.png create mode 100644 resources/icons/overlay/move_on.png diff --git a/resources/icons/overlay/move_hover.png b/resources/icons/overlay/move_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..99dc4cf8dbef9bf88bc6fa0a903705c400a815ed GIT binary patch literal 2812 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 X`3>!?!WdHJ00000NkvXXu0mjffwVm9 literal 0 HcmV?d00001 diff --git a/resources/icons/overlay/move_on.png b/resources/icons/overlay/move_on.png new file mode 100644 index 0000000000000000000000000000000000000000..7e78e0e6a3a0f36ce2a8a85e4ebdfa9ab6ec62c1 GIT binary patch literal 2447 zcmV;A32^p_P)j8 zK~#9!<(qqORP`0dKX-TYCXj@X1QLQkc*gQjM&8p1SPSxyN(Yd~tPfB-L_5%_V<|Xb ztL^w|r641qcWgjvsYTHU1qxOkQkjChMBWI27!qCy33=`9ALqAhmSnS+us3^WI5RhQ zbNB4M_k4fncb>nWhQ(yK=?)A4vVqR(NCo17SjAQjlmbP-8Q>VO7uc!k9JccPGz$cF z03(41fx$pqAPR^CA^;cQ4Dj<>phg{)>NpQ<2Q~ofHJw^p0${l520R7~2U36}phbvo zUj|%M8nPL9Pt*C%762G-?gnN81A%TzwXLL5;5%R^@Q$W)AS?hFZc>0Lz<6MY71Jr$ zD*)SowLqSxQ`Bq#7;Z)Y(|`$e3|Y9S9QX)$U(?xWDFB9>cwijx0?-qC(YL_Mz$co{ z)sO>VxJd(^@W6bBSads5HLws^uIUtp3;@GT2Vjl?xt2|IhZ8&|J)A2NGI~LLGE|jA z!67IsuFJ6qcwN&ueOmw+ZZx31QmrXrAK#X#F!XU4I0e$Peb=v-!k6#Dzu$(!8{Tmx z@EhQareib}fHXDVpAEb4?RrA)N08P{{y*|1Ts#8~7uSy+WUJpU>DOf!l3{PO*f`jnkujTXT7eLccGR#*p z1qZ-zlMXzo!dmZ5!bhF@%R6jZ1QjOS`@Vd*d>*XW%`N1P7v&rgUH57t zFxha^qcIJb3H0%w6Q1w_P^@B^xJ2{6=`vX5jTdhIrjL@bJ^+TBOdtn{_6NWSGXN*$ ze9yz?_)|JV=K*2|O6moIQ9zE0Z0l*j(?BQNMfZolkdYiX6?%^j&Odg(Oq*RFK=t*8 zI65j>eE=A4T&j}Ou-nrd;RB$o7(RSnK0m3$-48a*7ZnGS--N-_W#m77InW(j0mGEc z@&~wIm9YYZg-x&n4i|W8LIc9K_aG?)#xI09>m?feCSL@Nh?ZDkh#OM7z@@XW=x0z? z(&$7{GH>((FdAqRvQg6xIoh&J_TANL0oGY(bxp|<}lN=P=0Z zD+Vp09VBH+9v>Aa>9Ln~uYtusZ`yOr36GLF+XZwn4Z!Wth*>c4HFLaa-9$UA4Z>VN zmIKJB;|{H(y0JuUHC(#{r}x0F)o}F(f8N*xh={TJjUs@KF69!OmIJV95uDvG#f#D+ z@zYm}#G>~d>(ARF8Cs>mg%ei3krPOE0WF)w@Ks-j{p;(i`ZKG2hU@5d$bLXdT&Y=B z0{{@`AXsO|sxUY*1|DA_dAm2z+4$!=0c*2(`|V)08(ON}2Oy;(YMzp>U1AWdR_VK3V3^x zPd53u${IJMjNeN82lUzX4D$yUEjEl}(L z<@vtWRQQ=1Iy5uuX^0U#-vg@d7x!6+V5%>NlzePP%}jz)-AefOzTN@#5k@0-%)v zx@~(tmcx3g0ggFCUESi)vR~g_B=5RD|@W ztbuU#0u&vyO*-7Pf=GI{6e*M13jo(j;QV3O^*1R=*`IC{M7&ARcBFk2*XYj@GvJZm z!=PymH%!L8DAC;71)(pAg?K_LnQvr)>yd77U;xs(Lhf2=Rb4y-Tb9D{uSES5)1i9~ z{CEb8`K|cyrIW+oR0&KaN@l!MAOhF{^lLbCj)eLDh4#J0eXXADAGUg_ZFhKT6?Ete zoBslNxpoC$H!w)ksdfNpI@Q3IfKlO(MvCwU{sr$o(Xj9!c3|lwxKaqiXGw>~epCu< zQ8N2=hTeeyi;8+bBj9u>DY8u6AArbMS)pMzc)5H|3LMe#;wtS!dzFkd z2!N*ZEwBpkO>&P%YIrS@#Tc5Zw#9(cC0fvMgEAa+30S3MB#;IGtO4?UAww;cUy_kb zOgHza4t=Eze(n$)+hG>~K3B5QC;*yH0k9m@dVIrxle=Xq7~G^)8jiV6nB~$u zFyK*`z64@gK}{8$*d-;bR;fOBcj1HtONY1GVf5dksY_)Q09uvd$SkUfdNa*cIo_pt zq?SKomMmUu)6vI#?ht&n3cgq-4Uh2C?Jt)0Qo+=itkPQNybh7&)1x&N2}VRqS{#=o zYj_F{-rDk4YiTj?nx=CqXlcXj9Zyb)%dGG?b2D7!&&4}yBCscUH%zS1bk3Wq?c7oo z!A;BKRV^M(abABe-dWS#X2M&$W#%Rz9zZrtJ;I%|Y3e2rQh=$z!`x}x=57KaoEs;X zX*&CF=Vn%HogIO!!%HM|TW7D~+d8`mJ8hk900<|t-2NxPAk1%`HUJOOvZ}_ndAd-Q z>ox%Sw%t742p~O>?ejf>EZ{C68CjU&T?bR4V)jeGIiy>)hi2G5|9_-S+Q`YQ$SVK< N002ovPDHLkV1hbhW7_}# literal 0 HcmV?d00001 diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index dc2f5dd5a..ed2f8690d 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -313,6 +313,14 @@ void GLVolume::set_select_group_id(const std::string& select_by) select_group_id = composite_id; } +void GLVolume::set_drag_group_id(const std::string& drag_by) +{ + if (drag_by == "object") + drag_group_id = object_idx() * 1000; + else if (drag_by == "instance") + drag_group_id = object_idx() * 1000 + instance_idx(); +} + const Transform3f& GLVolume::world_matrix() const { if (m_world_matrix_dirty) @@ -666,11 +674,7 @@ std::vector GLVolumeCollection::load_object( v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx; v.set_select_group_id(select_by); - if (drag_by == "object") - v.drag_group_id = obj_idx * 1000; - else if (drag_by == "instance") - v.drag_group_id = obj_idx * 1000 + instance_idx; - + v.set_drag_group_id(drag_by); if (!model_volume->modifier) { v.set_convex_hull(model_volume->get_convex_hull()); @@ -963,6 +967,15 @@ void GLVolumeCollection::set_select_by(const std::string& select_by) } } +void GLVolumeCollection::set_drag_by(const std::string& drag_by) +{ + for (GLVolume *vol : this->volumes) + { + if (vol != nullptr) + vol->set_drag_group_id(drag_by); + } +} + std::vector GLVolumeCollection::get_current_print_zs(bool active_only) const { // Collect layer top positions of all volumes. diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index df749d1bb..6db58aa16 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -338,6 +338,7 @@ public: void set_convex_hull(const TriangleMesh& convex_hull); void set_select_group_id(const std::string& select_by); + void set_drag_group_id(const std::string& drag_by); int object_idx() const { return this->composite_id / 1000000; } int volume_idx() const { return (this->composite_id / 1000) % 1000; } @@ -449,6 +450,7 @@ public: void update_colors_by_extruder(const DynamicPrintConfig* config); void set_select_by(const std::string& select_by); + void set_drag_by(const std::string& drag_by); // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection std::vector get_current_print_zs(bool active_only) const; diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 94de895b4..b98826a80 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1123,7 +1123,6 @@ const float GLCanvas3D::Gizmos::OverlayGapY = 5.0f * OverlayTexturesScale; GLCanvas3D::Gizmos::Gizmos() : m_enabled(false) , m_current(Undefined) - , m_dragging(false) { } @@ -1134,7 +1133,16 @@ GLCanvas3D::Gizmos::~Gizmos() bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) { - GLGizmoBase* gizmo = new GLGizmoScale3D(parent); + GLGizmoBase* gizmo = new GLGizmoMove3D(parent); + if (gizmo == nullptr) + return false; + + if (!gizmo->init()) + return false; + + m_gizmos.insert(GizmosMap::value_type(Move, gizmo)); + + gizmo = new GLGizmoScale3D(parent); if (gizmo == nullptr) return false; @@ -1336,12 +1344,12 @@ bool GLCanvas3D::Gizmos::is_running() const bool GLCanvas3D::Gizmos::is_dragging() const { - return m_dragging; + GLGizmoBase* curr = _get_current(); + return (curr != nullptr) ? curr->is_dragging() : false; } void GLCanvas3D::Gizmos::start_dragging(const BoundingBoxf3& box) { - m_dragging = true; GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->start_dragging(box); @@ -1349,12 +1357,30 @@ void GLCanvas3D::Gizmos::start_dragging(const BoundingBoxf3& box) void GLCanvas3D::Gizmos::stop_dragging() { - m_dragging = false; GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->stop_dragging(); } +Vec3d GLCanvas3D::Gizmos::get_position() 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_position() : Vec3d::Zero(); +} + +void GLCanvas3D::Gizmos::set_position(const Vec3d& position) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(Move); + if (it != m_gizmos.end()) + reinterpret_cast(it->second)->set_position(position); +} + float GLCanvas3D::Gizmos::get_scale() const { if (!m_enabled) @@ -2143,6 +2169,7 @@ void GLCanvas3D::set_select_by(const std::string& value) void GLCanvas3D::set_drag_by(const std::string& value) { m_drag_by = value; + m_volumes.set_drag_by(value); } const std::string& GLCanvas3D::get_select_by() const @@ -2150,6 +2177,11 @@ const std::string& GLCanvas3D::get_select_by() const return m_select_by; } +const std::string& GLCanvas3D::get_drag_by() const +{ + return m_drag_by; +} + float GLCanvas3D::get_camera_zoom() const { return m_camera.zoom; @@ -2326,6 +2358,7 @@ void GLCanvas3D::update_gizmos_data() ModelInstance* model_instance = model_object->instances[0]; if (model_instance != nullptr) { + m_gizmos.set_position(Vec3d(model_instance->offset(0), model_instance->offset(1), 0.0)); m_gizmos.set_scale(model_instance->scaling_factor); m_gizmos.set_angle_z(model_instance->rotation); m_gizmos.set_flattening_data(model_object); @@ -2334,6 +2367,7 @@ void GLCanvas3D::update_gizmos_data() } else { + m_gizmos.set_position(Vec3d::Zero()); m_gizmos.set_scale(1.0f); m_gizmos.set_angle_z(0.0f); m_gizmos.set_flattening_data(nullptr); @@ -3181,6 +3215,18 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) switch (m_gizmos.get_current_type()) { + case Gizmos::Move: + { + // Apply new temporary offset + GLVolume* volume = m_volumes.volumes[m_mouse.drag.gizmo_volume_idx]; + Vec3d offset = m_gizmos.get_position() - volume->get_offset(); + for (GLVolume* v : volumes) + { + v->set_offset(v->get_offset() + offset); + } + update_position_values(volume->get_offset()); + break; + } case Gizmos::Scale: { // Apply new temporary scale factor @@ -3188,8 +3234,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) for (GLVolume* v : volumes) { v->set_scaling_factor((double)scale_factor); - update_scale_values((double)scale_factor); } + update_scale_values((double)scale_factor); break; } case Gizmos::Rotate: @@ -3199,8 +3245,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) for (GLVolume* v : volumes) { v->set_rotation((double)angle_z); - update_rotation_value((double)angle_z, Z); } + update_rotation_value((double)angle_z, Z); break; } default: @@ -3310,6 +3356,27 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { switch (m_gizmos.get_current_type()) { + case Gizmos::Move: + { + // get all volumes belonging to the same group, if any + std::vector volume_idxs; + int vol_id = m_mouse.drag.gizmo_volume_idx; + int group_id = m_volumes.volumes[vol_id]->select_group_id; + if (group_id == -1) + volume_idxs.push_back(vol_id); + else + { + for (int i = 0; i < (int)m_volumes.volumes.size(); ++i) + { + if (m_volumes.volumes[i]->select_group_id == group_id) + volume_idxs.push_back(i); + } + } + + _on_move(volume_idxs); + + break; + } case Gizmos::Scale: { m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index 55a3075ce..a200e7fdb 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -336,6 +336,7 @@ public: enum EType : unsigned char { Undefined, + Move, Scale, Rotate, Flatten, @@ -347,7 +348,6 @@ public: typedef std::map GizmosMap; GizmosMap m_gizmos; EType m_current; - bool m_dragging; public: Gizmos(); @@ -376,6 +376,9 @@ public: void start_dragging(const BoundingBoxf3& box); void stop_dragging(); + Vec3d get_position() const; + void set_position(const Vec3d& position); + float get_scale() const; void set_scale(float scale); @@ -558,6 +561,7 @@ public: void set_drag_by(const std::string& value); const std::string& get_select_by() const; + const std::string& get_drag_by() const; float get_camera_zoom() const; diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 1d02e1752..17c69749b 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -989,6 +989,157 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& return ratio; } +const double GLGizmoMove3D::Offset = 10.0; + +GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent) + : GLGizmoBase(parent) + , m_position(Vec3d::Zero()) + , m_starting_drag_position(Vec3d::Zero()) + , m_starting_box_center(Vec3d::Zero()) +{ +} + +bool GLGizmoMove3D::on_init() +{ + std::string path = resources_dir() + "/icons/overlay/"; + + std::string filename = path + "move_off.png"; + if (!m_textures[Off].load_from_file(filename, false)) + return false; + + filename = path + "move_hover.png"; + if (!m_textures[Hover].load_from_file(filename, false)) + return false; + + filename = path + "move_on.png"; + if (!m_textures[On].load_from_file(filename, false)) + return false; + + for (int i = 0; i < 3; ++i) + { + m_grabbers.push_back(Grabber()); + } + + return true; +} + +void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) +{ + if (m_hover_id != -1) + { + m_starting_drag_position = m_grabbers[m_hover_id].center; + m_starting_box_center = box.center(); + } +} + +void GLGizmoMove3D::on_update(const Linef3& mouse_ray) +{ + if (m_hover_id == 0) + m_position(0) = 2.0 * m_starting_box_center(0) + calc_displacement(1, mouse_ray) - m_starting_drag_position(0); + else if (m_hover_id == 1) + m_position(1) = 2.0 * m_starting_box_center(1) + calc_displacement(2, mouse_ray) - m_starting_drag_position(1); + else if (m_hover_id == 2) + m_position(2) = 2.0 * m_starting_box_center(2) + calc_displacement(1, mouse_ray) - m_starting_drag_position(2); +} + +void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const +{ + if (m_grabbers[0].dragging) + set_tooltip("X: " + format(m_position(0), 2)); + else if (m_grabbers[1].dragging) + set_tooltip("Y: " + format(m_position(1), 2)); + else if (m_grabbers[2].dragging) + set_tooltip("Z: " + format(m_position(2), 2)); + + ::glEnable(GL_DEPTH_TEST); + + const Vec3d& center = box.center(); + + // x axis + m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2)); + ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); + + // y axis + m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2)); + ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); + + // z axis + m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset); + ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); + + ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); + + if (m_hover_id == -1) + { + // draw axes + for (unsigned int i = 0; i < 3; ++i) + { + ::glColor3fv(AXES_COLOR[i]); + ::glBegin(GL_LINES); + ::glVertex3f(center(0), center(1), center(2)); + ::glVertex3f((GLfloat)m_grabbers[i].center(0), (GLfloat)m_grabbers[i].center(1), (GLfloat)m_grabbers[i].center(2)); + ::glEnd(); + } + + // draw grabbers + render_grabbers(); + } + else + { + // draw axis + ::glColor3fv(AXES_COLOR[m_hover_id]); + ::glBegin(GL_LINES); + ::glVertex3f(center(0), center(1), center(2)); + ::glVertex3f((GLfloat)m_grabbers[m_hover_id].center(0), (GLfloat)m_grabbers[m_hover_id].center(1), (GLfloat)m_grabbers[m_hover_id].center(2)); + ::glEnd(); + + // draw grabber + m_grabbers[m_hover_id].render(true); + } +} + +void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const +{ + ::glDisable(GL_DEPTH_TEST); + + render_grabbers_for_picking(); +} + +double GLGizmoMove3D::calc_displacement(unsigned int preferred_plane_id, const Linef3& mouse_ray) const +{ + double displacement = 0.0; + + Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; + double len_starting_vec = starting_vec.norm(); + if (len_starting_vec == 0.0) + return displacement; + + Vec3d starting_vec_dir = starting_vec.normalized(); + Vec3d mouse_dir = mouse_ray.unit_vector(); + + unsigned int plane_id = select_best_plane(mouse_dir, preferred_plane_id); + + switch (plane_id) + { + case 0: + { + displacement = starting_vec_dir.dot(intersection_on_plane_xy(mouse_ray, m_starting_box_center)); + break; + } + case 1: + { + displacement = starting_vec_dir.dot(intersection_on_plane_xz(mouse_ray, m_starting_box_center)); + break; + } + case 2: + { + displacement = starting_vec_dir.dot(intersection_on_plane_yz(mouse_ray, m_starting_box_center)); + break; + } + } + + return displacement; +} GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent) : GLGizmoBase(parent) diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 0599955ed..a7c688531 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -262,6 +262,31 @@ private: double calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const; }; +class GLGizmoMove3D : public GLGizmoBase +{ + static const double Offset; + + Vec3d m_position; + Vec3d m_starting_drag_position; + Vec3d m_starting_box_center; + +public: + explicit GLGizmoMove3D(GLCanvas3D& parent); + + const Vec3d& get_position() const { return m_position; } + void set_position(const Vec3d& position) { m_position = position; } + +protected: + virtual bool on_init(); + virtual void on_start_dragging(const BoundingBoxf3& box); + virtual void on_update(const Linef3& mouse_ray); + virtual void on_render(const BoundingBoxf3& box) const; + virtual void on_render_for_picking(const BoundingBoxf3& box) const; + +private: + double calc_displacement(unsigned int preferred_plane_id, const Linef3& mouse_ray) const; +}; + class GLGizmoFlatten : public GLGizmoBase { // This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself. From a97df55592f524eb73bd7d04ef8b7c1b3525d27d Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 11 Sep 2018 12:40:42 +0200 Subject: [PATCH 8/9] Temporary remove not yet supported transformations from 3D gizmos --- xs/src/slic3r/GUI/GLCanvas3D.cpp | 17 ++++++++ xs/src/slic3r/GUI/GLGizmo.cpp | 68 ++++++++++++++++++++++++-------- xs/src/slic3r/GUI/GLGizmo.hpp | 18 ++++++++- 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index b98826a80..fdee693ee 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -1140,6 +1140,9 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) if (!gizmo->init()) return false; + // temporary disable z grabber + gizmo->disable_grabber(2); + m_gizmos.insert(GizmosMap::value_type(Move, gizmo)); gizmo = new GLGizmoScale3D(parent); @@ -1149,6 +1152,16 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) if (!gizmo->init()) return false; + // temporary disable x grabbers + gizmo->disable_grabber(0); + gizmo->disable_grabber(1); + // temporary disable y grabbers + gizmo->disable_grabber(2); + gizmo->disable_grabber(3); + // temporary disable z grabbers + gizmo->disable_grabber(4); + gizmo->disable_grabber(5); + m_gizmos.insert(GizmosMap::value_type(Scale, gizmo)); gizmo = new GLGizmoRotate3D(parent); @@ -1164,6 +1177,10 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) return false; } + // temporary disable x and y grabbers + gizmo->disable_grabber(0); + gizmo->disable_grabber(1); + m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo)); gizmo = new GLGizmoFlatten(parent); diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 17c69749b..4aa5ab32f 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -110,6 +110,7 @@ GLGizmoBase::Grabber::Grabber() : center(Vec3d::Zero()) , angles(Vec3d::Zero()) , dragging(false) + , enabled(true) { color[0] = 1.0f; color[1] = 1.0f; @@ -234,6 +235,22 @@ void GLGizmoBase::set_highlight_color(const float* color) ::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float)); } +void GLGizmoBase::enable_grabber(unsigned int id) +{ + if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) + m_grabbers[id].enabled = true; + + on_enable_grabber(id); +} + +void GLGizmoBase::disable_grabber(unsigned int id) +{ + if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) + m_grabbers[id].enabled = false; + + on_disable_grabber(id); +} + void GLGizmoBase::start_dragging(const BoundingBoxf3& box) { m_dragging = true; @@ -278,7 +295,8 @@ void GLGizmoBase::render_grabbers() const { for (int i = 0; i < (int)m_grabbers.size(); ++i) { - m_grabbers[i].render(m_hover_id == i); + if (m_grabbers[i].enabled) + m_grabbers[i].render(m_hover_id == i); } } @@ -286,10 +304,13 @@ void GLGizmoBase::render_grabbers_for_picking() const { for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { - m_grabbers[i].color[0] = 1.0f; - m_grabbers[i].color[1] = 1.0f; - m_grabbers[i].color[2] = picking_color_component(i); - m_grabbers[i].render_for_picking(); + if (m_grabbers[i].enabled) + { + m_grabbers[i].color[0] = 1.0f; + m_grabbers[i].color[1] = 1.0f; + m_grabbers[i].color[2] = picking_color_component(i); + m_grabbers[i].render_for_picking(); + } } } @@ -386,6 +407,9 @@ void GLGizmoRotate::on_update(const Linef3& mouse_ray) void GLGizmoRotate::on_render(const BoundingBoxf3& box) const { + if (!m_grabbers[0].enabled) + return; + if (m_dragging) set_tooltip(format(m_angle * 180.0f / (float)PI, 4)); else @@ -789,12 +813,21 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_base_color); render_box(m_box); // draw connections - ::glColor3fv(m_grabbers[0].color); - render_grabbers_connection(0, 1); - ::glColor3fv(m_grabbers[2].color); - render_grabbers_connection(2, 3); - ::glColor3fv(m_grabbers[4].color); - render_grabbers_connection(4, 5); + if (m_grabbers[0].enabled && m_grabbers[1].enabled) + { + ::glColor3fv(m_grabbers[0].color); + render_grabbers_connection(0, 1); + } + if (m_grabbers[2].enabled && m_grabbers[3].enabled) + { + ::glColor3fv(m_grabbers[2].color); + render_grabbers_connection(2, 3); + } + if (m_grabbers[4].enabled && m_grabbers[5].enabled) + { + ::glColor3fv(m_grabbers[4].color); + render_grabbers_connection(4, 5); + } // draw grabbers render_grabbers(); } @@ -1074,11 +1107,14 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const // draw axes for (unsigned int i = 0; i < 3; ++i) { - ::glColor3fv(AXES_COLOR[i]); - ::glBegin(GL_LINES); - ::glVertex3f(center(0), center(1), center(2)); - ::glVertex3f((GLfloat)m_grabbers[i].center(0), (GLfloat)m_grabbers[i].center(1), (GLfloat)m_grabbers[i].center(2)); - ::glEnd(); + if (m_grabbers[i].enabled) + { + ::glColor3fv(AXES_COLOR[i]); + ::glBegin(GL_LINES); + ::glVertex3f(center(0), center(1), center(2)); + ::glVertex3f((GLfloat)m_grabbers[i].center(0), (GLfloat)m_grabbers[i].center(1), (GLfloat)m_grabbers[i].center(2)); + ::glEnd(); + } } // draw grabbers diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index a7c688531..8760b1c7d 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -28,6 +28,7 @@ protected: Vec3d center; Vec3d angles; float color[3]; + bool enabled; bool dragging; Grabber(); @@ -80,9 +81,12 @@ public: int get_hover_id() const { return m_hover_id; } void set_hover_id(int id); - + void set_highlight_color(const float* color); + void enable_grabber(unsigned int id); + void disable_grabber(unsigned int id); + void start_dragging(const BoundingBoxf3& box); void stop_dragging(); bool is_dragging() const { return m_dragging; } @@ -96,6 +100,8 @@ protected: virtual bool on_init() = 0; virtual void on_set_state() {} virtual void on_set_hover_id() {} + virtual void on_enable_grabber(unsigned int id) {} + virtual void on_disable_grabber(unsigned int id) {} virtual void on_start_dragging(const BoundingBoxf3& box) {} virtual void on_stop_dragging() {} virtual void on_update(const Linef3& mouse_ray) = 0; @@ -196,6 +202,16 @@ protected: m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); } } + virtual void on_enable_grabber(unsigned int id) + { + if ((0 <= id) && (id < 3)) + m_gizmos[id].enable_grabber(0); + } + virtual void on_disable_grabber(unsigned int id) + { + if ((0 <= id) && (id < 3)) + m_gizmos[id].disable_grabber(0); + } virtual void on_start_dragging(const BoundingBoxf3& box); virtual void on_stop_dragging(); virtual void on_update(const Linef3& mouse_ray) From 00b10c7f9d99976929d9c67d1abfc8f90f6ed055 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 11 Sep 2018 14:48:17 +0200 Subject: [PATCH 9/9] 3D gizmos' grabber size as a function of selected objects size --- xs/src/slic3r/GUI/GLGizmo.cpp | 206 +++++++++++++++++----------------- xs/src/slic3r/GUI/GLGizmo.hpp | 15 +-- 2 files changed, 113 insertions(+), 108 deletions(-) diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/xs/src/slic3r/GUI/GLGizmo.cpp index 4aa5ab32f..50c93d72c 100644 --- a/xs/src/slic3r/GUI/GLGizmo.cpp +++ b/xs/src/slic3r/GUI/GLGizmo.cpp @@ -20,90 +20,91 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f namespace Slic3r { namespace GUI { - // returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center - // coordinates are local to the plane - Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center) +// returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center +// coordinates are local to the plane +Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center) +{ + Transform3d m = Transform3d::Identity(); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0); +} + +// returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center +// coordinates are local to the plane +Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center) +{ + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1)); +} + +// returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center +// coordinates are local to the plane +Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center) +{ + Transform3d m = Transform3d::Identity(); + m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); + m.translate(-center); + Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); + + return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0)); +} + +// return an index: +// 0 for plane XY +// 1 for plane XZ +// 2 for plane YZ +// which indicates which plane is best suited for intersecting the given unit vector +// giving precedence to the plane with the given index +unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane) +{ + unsigned int ret = preferred_plane; + + // 1st checks if the given vector is not parallel to the given preferred plane + double dot_to_normal = 0.0; + switch (ret) { - Transform3d m = Transform3d::Identity(); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); - return Vec3d(mouse_pos_2d(0), mouse_pos_2d(1), 0.0); + case 0: // plane xy + { + dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ())); + break; + } + case 1: // plane xz + { + dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY())); + break; + } + case 2: // plane yz + { + dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX())); + break; + } + default: + { + break; + } } - // returns the intersection of the given ray with the plane parallel to plane XZ and passing through the given center - // coordinates are local to the plane - Vec3d intersection_on_plane_xz(const Linef3& ray, const Vec3d& center) + // if almost parallel, select the plane whose normal direction is closest to the given vector direction, + // otherwise return the given preferred plane index + if (dot_to_normal < 0.1) { - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-0.5 * (double)PI, Vec3d::UnitX())); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); - return Vec3d(mouse_pos_2d(0), 0.0, mouse_pos_2d(1)); + typedef std::map ProjsMap; + ProjsMap projs_map; + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz + projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz + ret = projs_map.rbegin()->second; } - // returns the intersection of the given ray with the plane parallel to plane YZ and passing through the given center - // coordinates are local to the plane - Vec3d intersection_on_plane_yz(const Linef3& ray, const Vec3d& center) - { - Transform3d m = Transform3d::Identity(); - m.rotate(Eigen::AngleAxisd(-0.5f * (double)PI, Vec3d::UnitY())); - m.translate(-center); - Vec2d mouse_pos_2d = to_2d(transform(ray, m).intersect_plane(0.0)); - - return Vec3d(0.0, mouse_pos_2d(1), -mouse_pos_2d(0)); - } - - // return an index: - // 0 for plane XY - // 1 for plane XZ - // 2 for plane YZ - // which indicates which plane is best suited for intersecting the given unit vector - // giving precedence to the plane with the given index - unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_plane) - { - unsigned int ret = preferred_plane; - - // 1st checks if the given vector is not parallel to the given preferred plane - double dot_to_normal = 0.0; - switch (ret) - { - case 0: // plane xy - { - dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitZ())); - break; - } - case 1: // plane xz - { - dot_to_normal = std::abs(unit_vector.dot(-Vec3d::UnitY())); - break; - } - case 2: // plane yz - { - dot_to_normal = std::abs(unit_vector.dot(Vec3d::UnitX())); - break; - } - default: - { - break; - } - } - - // if almost parallel, select the plane whose normal direction is closest to the given vector direction, - // otherwise return the given preferred plane index - if (dot_to_normal < 0.1) - { - typedef std::map ProjsMap; - ProjsMap projs_map; - projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitZ())), 0)); // plane xy - projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(-Vec3d::UnitY())), 1)); // plane xz - projs_map.insert(ProjsMap::value_type(std::abs(unit_vector.dot(Vec3d::UnitX())), 2)); // plane yz - ret = projs_map.rbegin()->second; - } - - return ret; - } + return ret; +} - const float GLGizmoBase::Grabber::HalfSize = 2.0f; +const float GLGizmoBase::Grabber::SizeFactor = 0.025f; +const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; GLGizmoBase::Grabber::Grabber() @@ -117,7 +118,7 @@ GLGizmoBase::Grabber::Grabber() color[2] = 1.0f; } -void GLGizmoBase::Grabber::render(bool hover) const +void GLGizmoBase::Grabber::render(bool hover, const BoundingBoxf3& box) const { float render_color[3]; if (hover) @@ -129,12 +130,15 @@ void GLGizmoBase::Grabber::render(bool hover) const else ::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); - render(render_color, true); + render(box, render_color, true); } -void GLGizmoBase::Grabber::render(const float* render_color, bool use_lighting) const +void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const { - float half_size = dragging ? HalfSize * DraggingScaleFactor : HalfSize; + float max_size = (float)box.max_size(); + float half_size = dragging ? max_size * SizeFactor * DraggingScaleFactor : max_size * SizeFactor; + half_size = std::max(half_size, MinHalfSize); + if (use_lighting) ::glEnable(GL_LIGHTING); @@ -291,16 +295,16 @@ float GLGizmoBase::picking_color_component(unsigned int id) const return (float)color / 255.0f; } -void GLGizmoBase::render_grabbers() const +void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const { for (int i = 0; i < (int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) - m_grabbers[i].render(m_hover_id == i); + m_grabbers[i].render((m_hover_id == i), box); } } -void GLGizmoBase::render_grabbers_for_picking() const +void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { @@ -309,7 +313,7 @@ void GLGizmoBase::render_grabbers_for_picking() const m_grabbers[i].color[0] = 1.0f; m_grabbers[i].color[1] = 1.0f; m_grabbers[i].color[2] = picking_color_component(i); - m_grabbers[i].render_for_picking(); + m_grabbers[i].render_for_picking(box); } } } @@ -440,7 +444,7 @@ void GLGizmoRotate::on_render(const BoundingBoxf3& box) const if (m_hover_id != -1) render_angle(); - render_grabber(); + render_grabber(box); ::glPopMatrix(); } @@ -452,7 +456,7 @@ void GLGizmoRotate::on_render_for_picking(const BoundingBoxf3& box) const ::glPushMatrix(); transform_to_local(); - render_grabbers_for_picking(); + render_grabbers_for_picking(box); ::glPopMatrix(); } @@ -544,7 +548,7 @@ void GLGizmoRotate::render_angle() const ::glEnd(); } -void GLGizmoRotate::render_grabber() const +void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const { double grabber_radius = (double)(m_radius + GrabberOffset); m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); @@ -558,7 +562,7 @@ void GLGizmoRotate::render_grabber() const ::glEnd(); ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); - render_grabbers(); + render_grabbers(box); } void GLGizmoRotate::transform_to_local() const @@ -829,7 +833,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const render_grabbers_connection(4, 5); } // draw grabbers - render_grabbers(); + render_grabbers(m_box); } else if ((m_hover_id == 0) || (m_hover_id == 1)) { @@ -846,8 +850,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[0].color); render_grabbers_connection(0, 1); // draw grabbers - m_grabbers[0].render(true); - m_grabbers[1].render(true); + m_grabbers[0].render(true, m_box); + m_grabbers[1].render(true, m_box); } else if ((m_hover_id == 2) || (m_hover_id == 3)) { @@ -864,8 +868,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[2].color); render_grabbers_connection(2, 3); // draw grabbers - m_grabbers[2].render(true); - m_grabbers[3].render(true); + m_grabbers[2].render(true, m_box); + m_grabbers[3].render(true, m_box); } else if ((m_hover_id == 4) || (m_hover_id == 5)) { @@ -882,8 +886,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[4].color); render_grabbers_connection(4, 5); // draw grabbers - m_grabbers[4].render(true); - m_grabbers[5].render(true); + m_grabbers[4].render(true, m_box); + m_grabbers[5].render(true, m_box); } else if (m_hover_id >= 6) { @@ -899,7 +903,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // draw grabbers for (int i = 6; i < 10; ++i) { - m_grabbers[i].render(true); + m_grabbers[i].render(true, m_box); } } } @@ -908,7 +912,7 @@ void GLGizmoScale3D::on_render_for_picking(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); - render_grabbers_for_picking(); + render_grabbers_for_picking(box); } void GLGizmoScale3D::render_box(const BoundingBoxf3& box) const @@ -1118,7 +1122,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const } // draw grabbers - render_grabbers(); + render_grabbers(box); } else { @@ -1130,7 +1134,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const ::glEnd(); // draw grabber - m_grabbers[m_hover_id].render(true); + m_grabbers[m_hover_id].render(true, box); } } @@ -1138,7 +1142,7 @@ void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); - render_grabbers_for_picking(); + render_grabbers_for_picking(box); } double GLGizmoMove3D::calc_displacement(unsigned int preferred_plane_id, const Linef3& mouse_ray) const diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/xs/src/slic3r/GUI/GLGizmo.hpp index 8760b1c7d..d3cad05c6 100644 --- a/xs/src/slic3r/GUI/GLGizmo.hpp +++ b/xs/src/slic3r/GUI/GLGizmo.hpp @@ -22,7 +22,8 @@ class GLGizmoBase protected: struct Grabber { - static const float HalfSize; + static const float SizeFactor; + static const float MinHalfSize; static const float DraggingScaleFactor; Vec3d center; @@ -33,11 +34,11 @@ protected: Grabber(); - void render(bool hover) const; - void render_for_picking() const { render(color, false); } + void render(bool hover, const BoundingBoxf3& box) const; + void render_for_picking(const BoundingBoxf3& box) const { render(box, color, false); } private: - void render(const float* render_color, bool use_lighting) const; + void render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const; void render_face(float half_size) const; }; @@ -109,8 +110,8 @@ protected: virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0; float picking_color_component(unsigned int id) const; - void render_grabbers() const; - void render_grabbers_for_picking() const; + void render_grabbers(const BoundingBoxf3& box) const; + void render_grabbers_for_picking(const BoundingBoxf3& box) const; void set_tooltip(const std::string& tooltip) const; std::string format(float value, unsigned int decimals) const; @@ -163,7 +164,7 @@ private: void render_snap_radii() const; void render_reference_radius() const; void render_angle() const; - void render_grabber() const; + void render_grabber(const BoundingBoxf3& box) const; void transform_to_local() const; // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate