diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index acbb4731d3..d8cdb515b3 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -80,6 +80,8 @@ // Enable rendering modifiers and similar objects always as transparent #define ENABLE_MODIFIERS_ALWAYS_TRANSPARENT (1 && ENABLE_2_4_0_ALPHA4) +// Enable editing volumes transformation in world coordinates and instances in local coordinates +#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_4_0_ALPHA4) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index d5a1a5659f..564bba5db7 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -444,8 +444,13 @@ void ObjectManipulation::Show(const bool show) if (show) { // Show the "World Coordinates" / "Local Coordintes" Combo in Advanced / Expert mode only. - bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple; - m_word_local_combo->Show(show_world_local_combo); +#if ENABLE_WORLD_COORDINATE + const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); + bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier()); +#else + bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple; +#endif // ENABLE_WORLD_COORDINATE + m_word_local_combo->Show(show_world_local_combo); m_empty_str->Show(!show_world_local_combo); } } @@ -529,7 +534,9 @@ void ObjectManipulation::update_settings_value(const Selection& selection) if (selection.is_single_full_instance()) { // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); +#if !ENABLE_WORLD_COORDINATE m_new_position = volume->get_instance_offset(); +#endif // !ENABLE_WORLD_COORDINATE // Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible. if (m_world_coordinates && ! m_uniform_scale && @@ -540,14 +547,20 @@ void ObjectManipulation::update_settings_value(const Selection& selection) } if (m_world_coordinates) { - m_new_rotate_label_string = L("Rotate"); +#if ENABLE_WORLD_COORDINATE + m_new_position = volume->get_instance_offset(); +#endif // ENABLE_WORLD_COORDINATE + m_new_rotate_label_string = L("Rotate"); m_new_rotation = Vec3d::Zero(); m_new_size = selection.get_scaled_instance_bounding_box().size(); - m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.; + m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.0; } else { - m_new_rotation = volume->get_instance_rotation() * (180. / M_PI); - m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); +#if ENABLE_WORLD_COORDINATE + m_new_position = Vec3d::Zero(); +#endif // ENABLE_WORLD_COORDINATE + m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI); + m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size()); m_new_scale = volume->get_instance_scaling_factor() * 100.; } @@ -566,10 +579,29 @@ void ObjectManipulation::update_settings_value(const Selection& selection) else if (selection.is_single_modifier() || selection.is_single_volume()) { // the selection contains a single volume const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); +#if ENABLE_WORLD_COORDINATE + if (m_world_coordinates) { + const Geometry::Transformation trafo(volume->world_matrix()); + + const Vec3d& offset = trafo.get_offset(); + const Vec3d& rotation = trafo.get_rotation(); + const Vec3d& scaling_factor = trafo.get_scaling_factor(); + const Vec3d& m = trafo.get_mirror(); + + m_new_position = offset; + m_new_rotation = rotation * (180.0 / M_PI); + m_new_scale = scaling_factor * 100.0; + m_new_size = volume->bounding_box().size().cwiseProduct(scaling_factor); + } + else { +#endif // ENABLE_WORLD_COORDINATE m_new_position = volume->get_volume_offset(); m_new_rotation = volume->get_volume_rotation() * (180. / M_PI); m_new_scale = volume->get_volume_scaling_factor() * 100.; - m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size())); + m_new_size = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size())); +#if ENABLE_WORLD_COORDINATE + } +#endif // ENABLE_WORLD_COORDINATE m_new_enabled = true; } else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) { @@ -814,7 +846,11 @@ void ObjectManipulation::change_position_value(int axis, double value) auto canvas = wxGetApp().plater()->canvas3D(); Selection& selection = canvas->get_selection(); selection.start_dragging(); +#if ENABLE_WORLD_COORDINATE + selection.translate(position - m_cache.position, !m_world_coordinates); +#else selection.translate(position - m_cache.position, selection.requires_local_axes()); +#endif // ENABLE_WORLD_COORDINATE canvas->do_move(L("Set Position")); m_cache.position = position; @@ -974,6 +1010,17 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value) m_uniform_scale = new_value; } +#if ENABLE_WORLD_COORDINATE +void ObjectManipulation::set_world_coordinates(const bool world_coordinates) +{ + m_world_coordinates = world_coordinates; + this->UpdateAndShow(true); + GLCanvas3D* canvas = wxGetApp().plater()->canvas3D(); + canvas->set_as_dirty(); + canvas->request_extra_frame(); +} +#endif // ENABLE_WORLD_COORDINATE + void ObjectManipulation::msw_rescale() { const int em = wxGetApp().em_unit(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index a15c72fb8e..6d0383038e 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -183,7 +183,11 @@ public: void set_uniform_scaling(const bool uniform_scale); bool get_uniform_scaling() const { return m_uniform_scale; } // Does the object manipulation panel work in World or Local coordinates? +#if ENABLE_WORLD_COORDINATE + void set_world_coordinates(const bool world_coordinates); +#else void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); } +#endif // ENABLE_WORLD_COORDINATE bool get_world_coordinates() const { return m_world_coordinates; } void reset_cache() { m_cache.reset(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index e73a85647e..13071cb469 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -2,6 +2,9 @@ #include "GLGizmoMove.hpp" #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GUI_App.hpp" +#if ENABLE_WORLD_COORDINATE +#include "slic3r/GUI/GUI_ObjectManipulation.hpp" +#endif // ENABLE_WORLD_COORDINATE #include @@ -14,11 +17,6 @@ const double GLGizmoMove3D::Offset = 10.0; GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoBase(parent, icon_filename, sprite_id) - , m_displacement(Vec3d::Zero()) - , m_snap_step(1.0) - , m_starting_drag_position(Vec3d::Zero()) - , m_starting_box_center(Vec3d::Zero()) - , m_starting_box_bottom_center(Vec3d::Zero()) { m_vbo_cone.init_from(its_make_cone(1., 1., 2*PI/36)); } @@ -26,15 +24,15 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam std::string GLGizmoMove3D::get_tooltip() const { const Selection& selection = m_parent.get_selection(); - bool show_position = selection.is_single_full_instance(); + const bool show_position = selection.is_single_full_instance(); const Vec3d& position = selection.get_bounding_box().center(); 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.x() : m_displacement.x(), 2); 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.y() : m_displacement.y(), 2); 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.z() : m_displacement.z(), 2); else return ""; } @@ -65,17 +63,27 @@ void GLGizmoMove3D::on_start_dragging() if (m_hover_id != -1) { m_displacement = Vec3d::Zero(); const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); +#if ENABLE_WORLD_COORDINATE + const Vec3d center = box.center(); + m_starting_drag_position = center + m_grabbers[m_hover_id].center; + m_starting_box_center = center; + m_starting_box_bottom_center = center; + m_starting_box_bottom_center.z() = box.min.z(); +#else m_starting_drag_position = m_grabbers[m_hover_id].center; m_starting_box_center = box.center(); m_starting_box_bottom_center = box.center(); - m_starting_box_bottom_center(2) = box.min(2); + m_starting_box_bottom_center.z() = box.min.z(); +#endif // ENABLE_WORLD_COORDINATE } } +#if !ENABLE_WORLD_COORDINATE void GLGizmoMove3D::on_stop_dragging() { m_displacement = Vec3d::Zero(); } +#endif // !ENABLE_WORLD_COORDINATE void GLGizmoMove3D::on_update(const UpdateData& data) { @@ -89,12 +97,30 @@ void GLGizmoMove3D::on_update(const UpdateData& data) void GLGizmoMove3D::on_render() { - const Selection& selection = m_parent.get_selection(); - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glEnable(GL_DEPTH_TEST)); + const Selection& selection = m_parent.get_selection(); const BoundingBoxf3& box = selection.get_bounding_box(); +#if ENABLE_WORLD_COORDINATE + glsafe(::glPushMatrix()); + transform_to_local(selection); + + const Vec3d zero = Vec3d::Zero(); + const Vec3d half_box_size = 0.5 * box.size(); + + // x axis + m_grabbers[0].center = { half_box_size.x() + Offset, 0.0, 0.0 }; + m_grabbers[0].color = AXES_COLOR[0]; + + // y axis + m_grabbers[1].center = { 0.0, half_box_size.y() + Offset, 0.0 }; + m_grabbers[1].color = AXES_COLOR[1]; + + // z axis + m_grabbers[2].center = { 0.0, 0.0, half_box_size.z() + Offset }; + m_grabbers[2].color = AXES_COLOR[2]; +#else const Vec3d& center = box.center(); // x axis @@ -108,6 +134,7 @@ void GLGizmoMove3D::on_render() // z axis m_grabbers[2].center = { center.x(), center.y(), box.max.z() + Offset }; m_grabbers[2].color = AXES_COLOR[2]; +#endif // ENABLE_WORLD_COORDINATE glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); @@ -117,7 +144,11 @@ void GLGizmoMove3D::on_render() if (m_grabbers[i].enabled) { glsafe(::glColor4fv(AXES_COLOR[i].data())); ::glBegin(GL_LINES); +#if ENABLE_WORLD_COORDINATE + ::glVertex3dv(zero.data()); +#else ::glVertex3dv(center.data()); +#endif // ENABLE_WORLD_COORDINATE ::glVertex3dv(m_grabbers[i].center.data()); glsafe(::glEnd()); } @@ -134,7 +165,11 @@ void GLGizmoMove3D::on_render() // draw axis glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data())); ::glBegin(GL_LINES); +#if ENABLE_WORLD_COORDINATE + ::glVertex3dv(zero.data()); +#else ::glVertex3dv(center.data()); +#endif // ENABLE_WORLD_COORDINATE ::glVertex3dv(m_grabbers[m_hover_id].center.data()); glsafe(::glEnd()); @@ -143,40 +178,57 @@ void GLGizmoMove3D::on_render() shader->start_using(); shader->set_uniform("emission_factor", 0.1f); // draw grabber - float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); + const Vec3d box_size = box.size(); + const float mean_size = (float)((box_size.x() + box_size.y() + box_size.z()) / 3.0); m_grabbers[m_hover_id].render(true, mean_size); shader->stop_using(); } render_grabber_extension((Axis)m_hover_id, box, false); } + +#if ENABLE_WORLD_COORDINATE + glsafe(::glPopMatrix()); +#endif // ENABLE_WORLD_COORDINATE } void GLGizmoMove3D::on_render_for_picking() { glsafe(::glDisable(GL_DEPTH_TEST)); +#if ENABLE_WORLD_COORDINATE + const Selection& selection = m_parent.get_selection(); + const BoundingBoxf3& box = selection.get_bounding_box(); + glsafe(::glPushMatrix()); + transform_to_local(selection); +#else const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); +#endif // ENABLE_WORLD_COORDINATE + render_grabbers_for_picking(box); render_grabber_extension(X, box, true); render_grabber_extension(Y, box, true); render_grabber_extension(Z, box, true); + +#if ENABLE_WORLD_COORDINATE + glsafe(::glPopMatrix()); +#endif // ENABLE_WORLD_COORDINATE } double GLGizmoMove3D::calc_projection(const UpdateData& data) const { double projection = 0.0; - Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; - double len_starting_vec = starting_vec.norm(); + const Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; + const double len_starting_vec = starting_vec.norm(); if (len_starting_vec != 0.0) { 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 // 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 - Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + const Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_starting_drag_position; + const Vec3d inters_vec = inters - m_starting_drag_position; // finds projection of the vector along the staring direction projection = inters_vec.dot(starting_vec.normalized()); @@ -190,8 +242,9 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const { - float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); - double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size); + const Vec3d box_size = box.size(); + const float mean_size = (float)((box_size.x() + box_size.y() + box_size.z()) / 3.0); + const double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size(mean_size) : (double)m_grabbers[axis].get_half_size(mean_size); std::array color = m_grabbers[axis].color; if (!picking && m_hover_id != -1) { @@ -227,6 +280,18 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box shader->stop_using(); } +#if ENABLE_WORLD_COORDINATE +void GLGizmoMove3D::transform_to_local(const Selection& selection) const +{ + const Vec3d center = selection.get_bounding_box().center(); + glsafe(::glTranslated(center.x(), center.y(), center.z())); + + if (!wxGetApp().obj_manipul()->get_world_coordinates()) { + const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } +} +#endif // ENABLE_WORLD_COORDINATE } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index baa2df7391..67d9390f10 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -11,14 +11,11 @@ class GLGizmoMove3D : public GLGizmoBase { static const double Offset; - Vec3d m_displacement; - - double m_snap_step; - - Vec3d m_starting_drag_position; - Vec3d m_starting_box_center; - Vec3d m_starting_box_bottom_center; - + Vec3d m_displacement{ Vec3d::Zero() }; + double m_snap_step{ 1.0 }; + Vec3d m_starting_drag_position{ Vec3d::Zero() }; + Vec3d m_starting_box_center{ Vec3d::Zero() }; + Vec3d m_starting_box_bottom_center{ Vec3d::Zero() }; GLModel m_vbo_cone; public: @@ -36,7 +33,9 @@ protected: virtual bool on_init() override; virtual std::string on_get_name() const override; virtual bool on_is_activable() const override; +#if !ENABLE_WORLD_COORDINATE virtual void on_start_dragging() override; +#endif // !ENABLE_WORLD_COORDINATE virtual void on_stop_dragging() override; virtual void on_update(const UpdateData& data) override; virtual void on_render() override; @@ -45,6 +44,9 @@ protected: private: double calc_projection(const UpdateData& data) const; void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const; +#if ENABLE_WORLD_COORDINATE + void transform_to_local(const Selection& selection) const; +#endif // ENABLE_WORLD_COORDINATE }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 54fcfc2c7c..37ca01b3aa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -365,7 +365,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick void GLGizmoRotate::transform_to_local(const Selection& selection) const { - glsafe(::glTranslated(m_center(0), m_center(1), m_center(2))); + glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z())); if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) { Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 08a94a97d7..fa90809b91 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -617,7 +617,11 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt) case Move: { // Apply new temporary offset +#if ENABLE_WORLD_COORDINATE + selection.translate(get_displacement(), !wxGetApp().obj_manipul()->get_world_coordinates()); +#else selection.translate(get_displacement()); +#endif // ENABLE_WORLD_COORDINATE wxGetApp().obj_manipul()->set_dirty(); break; } diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 6a82ca8d3e..cace704914 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -706,13 +706,31 @@ void Selection::translate(const Vec3d& displacement, bool local) if (local) v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement); else { +#if ENABLE_WORLD_COORDINATE + const VolumeCache& volume_data = m_cache.volumes_data[i]; + const Vec3d local_displacement = (volume_data.get_instance_rotation_matrix() * volume_data.get_instance_scale_matrix() * volume_data.get_instance_mirror_matrix()).inverse() * displacement; + v.set_volume_offset(volume_data.get_volume_position() + local_displacement); +#else const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); +#endif // ENABLE_WORLD_COORDINATE } } else if (m_mode == Instance) { +#if ENABLE_WORLD_COORDINATE + if (is_from_fully_selected_instance(i)) { + if (local) { + const VolumeCache& volume_data = m_cache.volumes_data[i]; + const Vec3d world_displacement = (volume_data.get_instance_rotation_matrix() * volume_data.get_instance_scale_matrix() * volume_data.get_instance_mirror_matrix()) * displacement; + v.set_instance_offset(volume_data.get_instance_position() + world_displacement); + } + else + v.set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); + } +#else if (is_from_fully_selected_instance(i)) v.set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement); +#endif // ENABLE_WORLD_COORDINATE else { const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement; v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement); @@ -1249,10 +1267,28 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const glsafe(::glPushMatrix()); if (!boost::starts_with(sidebar_field, "layer")) { - const Vec3d& center = get_bounding_box().center(); + const Vec3d center = get_bounding_box().center(); if (is_single_full_instance() && !wxGetApp().obj_manipul()->get_world_coordinates()) { - glsafe(::glTranslated(center(0), center(1), center(2))); + glsafe(::glTranslated(center.x(), center.y(), center.z())); +#if ENABLE_WORLD_COORDINATE + Transform3d orient_matrix = Transform3d::Identity(); + if (boost::starts_with(sidebar_field, "position") || boost::starts_with(sidebar_field, "scale")) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else if (boost::starts_with(sidebar_field, "rotation")) { + if (boost::ends_with(sidebar_field, "x")) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else if (boost::ends_with(sidebar_field, "y")) { + const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation(); + if (rotation.x() == 0.0) + orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + else + orient_matrix.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ())); + } + } + + glsafe(::glMultMatrixd(orient_matrix.data())); +#else if (!boost::starts_with(sidebar_field, "position")) { Transform3d orient_matrix = Transform3d::Identity(); if (boost::starts_with(sidebar_field, "scale")) @@ -1271,15 +1307,24 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) const glsafe(::glMultMatrixd(orient_matrix.data())); } - } else if (is_single_volume() || is_single_modifier()) { - glsafe(::glTranslated(center(0), center(1), center(2))); +#endif // ENABLE_WORLD_COORDINATE + } + else if (is_single_volume() || is_single_modifier()) { + glsafe(::glTranslated(center.x(), center.y(), center.z())); +#if ENABLE_WORLD_COORDINATE + if (!wxGetApp().obj_manipul()->get_world_coordinates()) { + const Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); + glsafe(::glMultMatrixd(orient_matrix.data())); + } +#else Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); if (!boost::starts_with(sidebar_field, "position")) orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true); - glsafe(::glMultMatrixd(orient_matrix.data())); - } else { - glsafe(::glTranslated(center(0), center(1), center(2))); +#endif // ENABLE_WORLD_COORDINATE + } + else { + glsafe(::glTranslated(center.x(), center.y(), center.z())); if (requires_local_axes()) { const Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true); glsafe(::glMultMatrixd(orient_matrix.data()));