diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp
index 420ab473f..9b8014917 100644
--- a/src/libslic3r/Geometry.cpp
+++ b/src/libslic3r/Geometry.cpp
@@ -1529,17 +1529,17 @@ Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot
 {
     return
         // From the current coordinate system to world.
-        Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
+        Eigen::AngleAxisd(rot_xyz_to.z(), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to.x(), Vec3d::UnitX()) *
         // From world to the initial coordinate system.
-        Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
+        Eigen::AngleAxisd(-rot_xyz_from.x(), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from.z(), Vec3d::UnitZ());
 }
 
 // This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
 double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
 {
-    Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
-    Vec3d  axis  = angle_axis.axis();
-    double angle = angle_axis.angle();
+    const Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
+    const Vec3d& axis  = angle_axis.axis();
+    const double angle = angle_axis.angle();
 #ifndef NDEBUG
     if (std::abs(angle) > 1e-8) {
         assert(std::abs(axis.x()) < 1e-8);
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index 564bba5db..1c07c5c42 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -278,7 +278,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
                 return;
 
             // Update mirroring at the GLVolumes.
-            selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
+            selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
             selection.synchronize_unselected_volumes();
             // Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
             canvas->do_mirror(L("Set Mirror"));
@@ -379,7 +379,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
             return;
 
         // Update rotation at the GLVolumes.
-        selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
+        selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
         selection.synchronize_unselected_volumes();
         // Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
         canvas->do_rotate(L("Reset Rotation"));
@@ -551,17 +551,23 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
             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();
+#if ENABLE_WORLD_COORDINATE
+            m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
+#else
+            m_new_rotation = Vec3d::Zero();
+#endif // ENABLE_WORLD_COORDINATE
+            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.0;
 		} 
         else {
 #if ENABLE_WORLD_COORDINATE
             m_new_position = Vec3d::Zero();
-#endif // ENABLE_WORLD_COORDINATE
+            m_new_rotation = Vec3d::Zero();
+#else
             m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
+#endif // ENABLE_WORLD_COORDINATE
             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.;
+            m_new_scale    = volume->get_instance_scaling_factor() * 100.0;
 		}
 
         m_new_enabled  = true;
@@ -570,7 +576,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
         const BoundingBoxf3& box = selection.get_bounding_box();
         m_new_position = box.center();
         m_new_rotation = Vec3d::Zero();
-        m_new_scale    = Vec3d(100., 100., 100.);
+        m_new_scale    = Vec3d(100.0, 100.0, 100.0);
         m_new_size     = box.size();
         m_new_rotate_label_string = L("Rotate");
 		m_new_scale_label_string  = L("Scale");
@@ -586,7 +592,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
             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();
+//            const Vec3d& mirror = trafo.get_mirror();
 
             m_new_position = offset;
             m_new_rotation = rotation * (180.0 / M_PI);
@@ -596,8 +602,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
         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_rotation = volume->get_volume_rotation() * (180.0 / M_PI);
+        m_new_scale    = volume->get_volume_scaling_factor() * 100.0;
         m_new_size     = volume->get_instance_scaling_factor().cwiseProduct(volume->get_volume_scaling_factor().cwiseProduct(volume->bounding_box().size()));
 #if ENABLE_WORLD_COORDINATE
         }
@@ -711,11 +717,20 @@ void ObjectManipulation::update_reset_buttons_visibility()
 
     if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
         const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
+#if ENABLE_WORLD_COORDINATE
+        Vec3d rotation = Vec3d::Zero();
+        Vec3d scale = Vec3d::Ones();
+#else
         Vec3d rotation;
         Vec3d scale;
-        double min_z = 0.;
+#endif // ENABLE_WORLD_COORDINATE
+        double min_z = 0.0;
 
+#if ENABLE_WORLD_COORDINATE
+        if (selection.is_single_full_instance() && m_world_coordinates) {
+#else
         if (selection.is_single_full_instance()) {
+#endif // ENABLE_WORLD_COORDINATE
             rotation = volume->get_instance_rotation();
             scale = volume->get_instance_scaling_factor();
             min_z = wxGetApp().model().objects[volume->composite_id.object_id]->bounding_box().min.z();
@@ -727,7 +742,11 @@ void ObjectManipulation::update_reset_buttons_visibility()
         }
         show_rotation = !rotation.isApprox(Vec3d::Zero());
         show_scale = !scale.isApprox(Vec3d::Ones());
+#if ENABLE_WORLD_COORDINATE
+        show_drop_to_bed = min_z > EPSILON;
+#else
         show_drop_to_bed = std::abs(min_z) > SINKING_Z_THRESHOLD;
+#endif // ENABLE_WORLD_COORDINATE
     }
 
     wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
@@ -1019,6 +1038,13 @@ void ObjectManipulation::set_world_coordinates(const bool world_coordinates)
     canvas->set_as_dirty();
     canvas->request_extra_frame();
 }
+
+bool ObjectManipulation::get_world_coordinates() const
+{
+    const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
+    return wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier()) ? 
+        m_world_coordinates : true;
+}
 #endif // ENABLE_WORLD_COORDINATE
 
 void ObjectManipulation::msw_rescale()
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
index 6d0383038..a4f826fea 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
@@ -185,10 +185,11 @@ public:
     // Does the object manipulation panel work in World or Local coordinates?
 #if ENABLE_WORLD_COORDINATE
     void        set_world_coordinates(const bool world_coordinates);
+    bool        get_world_coordinates() const;
 #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; }
+#endif // ENABLE_WORLD_COORDINATE
 
     void reset_cache() { m_cache.reset(); }
 #ifndef __APPLE__
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
index bc40476c4..a8df103fc 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
@@ -23,27 +23,18 @@ GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filenam
 
 std::string GLGizmoMove3D::get_tooltip() const
 {
-    const Selection& selection = m_parent.get_selection();
-    const bool show_position = selection.is_single_full_instance();
 #if ENABLE_WORLD_COORDINATE
-    const bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates();
-    Vec3d position = Vec3d::Zero();
-    if (!world_coordinates) {
-        if (selection.is_single_modifier() || selection.is_single_volume() || selection.is_wipe_tower())
-            position = selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_offset();
-    }
-    else
-        position = selection.get_bounding_box().center();
-
     if (m_hover_id == 0)
-        return m_grabbers[0].dragging ? "DX: " + format(m_displacement.x(), 2) : "X: " + format(position.x(), 2);
+        return "X: " + format(m_displacement.x(), 2);
     else if (m_hover_id == 1)
-        return m_grabbers[1].dragging ? "DY: " + format(m_displacement.y(), 2) : "Y: " + format(position.y(), 2);
+        return "Y: " + format(m_displacement.y(), 2);
     else if (m_hover_id == 2)
-        return m_grabbers[2].dragging ? "DZ: " + format(m_displacement.z(), 2) : "Z: " + format(position.z(), 2);
+        return "Z: " + format(m_displacement.z(), 2);
     else
         return "";
 #else
+    const Selection& selection = m_parent.get_selection();
+    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)
@@ -98,12 +89,10 @@ void GLGizmoMove3D::on_start_dragging()
     }
 }
 
-#if !ENABLE_WORLD_COORDINATE
 void GLGizmoMove3D::on_stop_dragging()
 {
     m_displacement = Vec3d::Zero();
 }
-#endif // !ENABLE_WORLD_COORDINATE
 
 void GLGizmoMove3D::on_update(const UpdateData& data)
 {
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
index 514c0df2c..4a44b3c95 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp
@@ -34,9 +34,7 @@ protected:
     virtual std::string on_get_name() const override;
     virtual bool on_is_activable() const override;
     virtual void on_start_dragging() override;
-#if !ENABLE_WORLD_COORDINATE
     virtual void on_stop_dragging() override;
-#endif // !ENABLE_WORLD_COORDINATE
     virtual void on_update(const UpdateData& data) override;
     virtual void on_render() override;
     virtual void on_render_for_picking() override;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
index 37ca01b3a..5bafc573b 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
@@ -2,15 +2,18 @@
 #include "GLGizmoRotate.hpp"
 #include "slic3r/GUI/GLCanvas3D.hpp"
 #include "slic3r/GUI/ImGuiWrapper.hpp"
-
-#include <GL/glew.h>
+#if ENABLE_WORLD_COORDINATE
+#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
+#endif // ENABLE_WORLD_COORDINATE
 
 #include "slic3r/GUI/GUI_App.hpp"
 #include "slic3r/GUI/GUI.hpp"
 #include "slic3r/GUI/Plater.hpp"
+#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
+
 #include "libslic3r/PresetBundle.hpp"
 
-#include "slic3r/GUI/Jobs/RotoptimizeJob.hpp"
+#include <GL/glew.h>
 
 namespace Slic3r {
 namespace GUI {
@@ -29,13 +32,6 @@ const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius
 GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis)
     : GLGizmoBase(parent, "", -1)
     , m_axis(axis)
-    , m_angle(0.0)
-    , m_center(0.0, 0.0, 0.0)
-    , m_radius(0.0f)
-    , m_snap_coarse_in_radius(0.0f)
-    , m_snap_coarse_out_radius(0.0f)
-    , m_snap_fine_in_radius(0.0f)
-    , m_snap_fine_out_radius(0.0f)
 {
 }
 
@@ -81,6 +77,9 @@ bool GLGizmoRotate::on_init()
 
 void GLGizmoRotate::on_start_dragging()
 {
+#if ENABLE_WORLD_COORDINATE
+    init_data_from_selection(m_parent.get_selection());
+#else
     const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box();
     m_center = box.center();
     m_radius = Offset + box.radius();
@@ -88,33 +87,31 @@ void GLGizmoRotate::on_start_dragging()
     m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
     m_snap_fine_in_radius = m_radius;
     m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
+#endif // ENABLE_WORLD_COORDINATE
 }
 
 void GLGizmoRotate::on_update(const UpdateData& data)
 {
-    Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection()));
+    const Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, m_parent.get_selection()));
 
-    Vec2d orig_dir = Vec2d::UnitX();
-    Vec2d new_dir = mouse_pos.normalized();
+    const Vec2d orig_dir = Vec2d::UnitX();
+    const Vec2d new_dir = mouse_pos.normalized();
 
     double theta = ::acos(std::clamp(new_dir.dot(orig_dir), -1.0, 1.0));
     if (cross2(orig_dir, new_dir) < 0.0)
         theta = 2.0 * (double)PI - theta;
 
-    double len = mouse_pos.norm();
+    const double len = mouse_pos.norm();
 
     // snap to coarse snap region
-    if ((m_snap_coarse_in_radius <= len) && (len <= m_snap_coarse_out_radius))
-    {
-        double step = 2.0 * (double)PI / (double)SnapRegionsCount;
+    if (m_snap_coarse_in_radius <= len && len <= m_snap_coarse_out_radius) {
+        const double step = 2.0 * (double)PI / (double)SnapRegionsCount;
         theta = step * (double)std::round(theta / step);
     }
-    else
-    {
+    else {
         // snap to fine snap region (scale)
-        if ((m_snap_fine_in_radius <= len) && (len <= m_snap_fine_out_radius))
-        {
-            double step = 2.0 * (double)PI / (double)ScaleStepsCount;
+        if (m_snap_fine_in_radius <= len && len <= m_snap_fine_out_radius) {
+            const double step = 2.0 * (double)PI / (double)ScaleStepsCount;
             theta = step * (double)std::round(theta / step);
         }
     }
@@ -134,12 +131,16 @@ void GLGizmoRotate::on_render()
     const BoundingBoxf3& box = selection.get_bounding_box();
 
     if (m_hover_id != 0 && !m_grabbers[0].dragging) {
+#if ENABLE_WORLD_COORDINATE
+        init_data_from_selection(selection);
+#else
         m_center = box.center();
         m_radius = Offset + box.radius();
         m_snap_coarse_in_radius = m_radius / 3.0f;
         m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
         m_snap_fine_in_radius = m_radius;
         m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth);
+#endif // ENABLE_WORLD_COORDINATE
     }
 
     glsafe(::glEnable(GL_DEPTH_TEST));
@@ -186,6 +187,24 @@ void GLGizmoRotate::on_render_for_picking()
     glsafe(::glPopMatrix());
 }
 
+#if ENABLE_WORLD_COORDINATE
+void GLGizmoRotate::init_data_from_selection(const Selection& selection)
+{
+    const BoundingBoxf3& box = selection.get_bounding_box();
+    m_center = box.center();
+    m_radius = Offset + box.radius();
+    m_snap_coarse_in_radius = m_radius / 3.0f;
+    m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
+    m_snap_fine_in_radius = m_radius;
+    m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
+
+    if (wxGetApp().obj_manipul()->get_world_coordinates())
+        m_orient_matrix = Transform3d::Identity();
+    else
+        m_orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
+}
+#endif // ENABLE_WORLD_COORDINATE
+
 void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit)
 {
     if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
@@ -219,12 +238,11 @@ void GLGizmoRotate3D::load_rotoptimize_state()
 void GLGizmoRotate::render_circle() const
 {
     ::glBegin(GL_LINE_LOOP);
-    for (unsigned int i = 0; i < ScaleStepsCount; ++i)
-    {
-        float angle = (float)i * ScaleStepRad;
-        float x = ::cos(angle) * m_radius;
-        float y = ::sin(angle) * m_radius;
-        float z = 0.0f;
+    for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
+        const float angle = (float)i * ScaleStepRad;
+        const float x = ::cos(angle) * m_radius;
+        const float y = ::sin(angle) * m_radius;
+        const float z = 0.0f;
         ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
     }
     glsafe(::glEnd());
@@ -232,21 +250,20 @@ void GLGizmoRotate::render_circle() const
 
 void GLGizmoRotate::render_scale() const
 {
-    float out_radius_long = m_snap_fine_out_radius;
-    float out_radius_short = m_radius * (1.0f + 0.5f * ScaleLongTooth);
+    const float out_radius_long = m_snap_fine_out_radius;
+    const float out_radius_short = m_radius * (1.0f + 0.5f * ScaleLongTooth);
 
     ::glBegin(GL_LINES);
-    for (unsigned int i = 0; i < ScaleStepsCount; ++i)
-    {
-        float angle = (float)i * ScaleStepRad;
-        float cosa = ::cos(angle);
-        float sina = ::sin(angle);
-        float in_x = cosa * m_radius;
-        float in_y = sina * m_radius;
-        float in_z = 0.0f;
-        float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short;
-        float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short;
-        float out_z = 0.0f;
+    for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
+        const float angle = (float)i * ScaleStepRad;
+        const float cosa = ::cos(angle);
+        const float sina = ::sin(angle);
+        const float in_x = cosa * m_radius;
+        const float in_y = sina * m_radius;
+        const float in_z = 0.0f;
+        const float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short;
+        const float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short;
+        const float out_z = 0.0f;
         ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z);
         ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z);
     }
@@ -255,23 +272,22 @@ void GLGizmoRotate::render_scale() const
 
 void GLGizmoRotate::render_snap_radii() const
 {
-    float step = 2.0f * (float)PI / (float)SnapRegionsCount;
+    const float step = 2.0f * (float)PI / (float)SnapRegionsCount;
 
-    float in_radius = m_radius / 3.0f;
-    float out_radius = 2.0f * in_radius;
+    const float in_radius = m_radius / 3.0f;
+    const float out_radius = 2.0f * in_radius;
 
     ::glBegin(GL_LINES);
-    for (unsigned int i = 0; i < SnapRegionsCount; ++i)
-    {
-        float angle = (float)i * step;
-        float cosa = ::cos(angle);
-        float sina = ::sin(angle);
-        float in_x = cosa * in_radius;
-        float in_y = sina * in_radius;
-        float in_z = 0.0f;
-        float out_x = cosa * out_radius;
-        float out_y = sina * out_radius;
-        float out_z = 0.0f;
+    for (unsigned int i = 0; i < SnapRegionsCount; ++i) {
+        const float angle = (float)i * step;
+        const float cosa = ::cos(angle);
+        const float sina = ::sin(angle);
+        const float in_x = cosa * in_radius;
+        const float in_y = sina * in_radius;
+        const float in_z = 0.0f;
+        const float out_x = cosa * out_radius;
+        const float out_y = sina * out_radius;
+        const float out_z = 0.0f;
         ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z);
         ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z);
     }
@@ -288,16 +304,15 @@ void GLGizmoRotate::render_reference_radius() const
 
 void GLGizmoRotate::render_angle() const
 {
-    float step_angle = (float)m_angle / AngleResolution;
-    float ex_radius = m_radius * (1.0f + GrabberOffset);
+    const float step_angle = (float)m_angle / AngleResolution;
+    const float ex_radius = m_radius * (1.0f + GrabberOffset);
 
     ::glBegin(GL_LINE_STRIP);
-    for (unsigned int i = 0; i <= AngleResolution; ++i)
-    {
-        float angle = (float)i * step_angle;
-        float x = ::cos(angle) * ex_radius;
-        float y = ::sin(angle) * ex_radius;
-        float z = 0.0f;
+    for (unsigned int i = 0; i <= AngleResolution; ++i) {
+        const float angle = (float)i * step_angle;
+        const float x = ::cos(angle) * ex_radius;
+        const float y = ::sin(angle) * ex_radius;
+        const float z = 0.0f;
         ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z);
     }
     glsafe(::glEnd());
@@ -305,9 +320,9 @@ void GLGizmoRotate::render_angle() const
 
 void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
 {
-    double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
+    const double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset);
     m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0);
-    m_grabbers[0].angles(2) = m_angle;
+    m_grabbers[0].angles.z() = m_angle;
 
     glsafe(::glColor4fv((m_hover_id != -1) ? m_drag_color.data() : m_highlight_color.data()));
 
@@ -322,8 +337,8 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const
 
 void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) const
 {
-    float mean_size = (float)((box.size()(0) + box.size()(1) + box.size()(2)) / 3.0);
-    double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_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[0].get_dragging_half_size(mean_size) : (double)m_grabbers[0].get_half_size(mean_size);
 
     std::array<float, 4> color = m_grabbers[0].color;
     if (!picking && m_hover_id != -1) {
@@ -367,10 +382,14 @@ void GLGizmoRotate::transform_to_local(const Selection& selection) const
 {
     glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
 
+#if ENABLE_WORLD_COORDINATE
+    glsafe(::glMultMatrixd(m_orient_matrix.data()));
+#else
     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);
+        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
 
     switch (m_axis)
     {
@@ -423,8 +442,12 @@ Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, cons
     }
     }
 
+#if ENABLE_WORLD_COORDINATE
+    m = m * m_orient_matrix.inverse();
+#else
     if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes())
         m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse();
+#endif // ENABLE_WORLD_COORDINATE
 
     m.translate(-m_center);
 
@@ -473,13 +496,13 @@ bool GLGizmoRotate3D::on_is_activable() const
 
 void GLGizmoRotate3D::on_start_dragging()
 {
-    if ((0 <= m_hover_id) && (m_hover_id < 3))
+    if (0 <= m_hover_id && m_hover_id < 3)
         m_gizmos[m_hover_id].start_dragging();
 }
 
 void GLGizmoRotate3D::on_stop_dragging()
 {
-    if ((0 <= m_hover_id) && (m_hover_id < 3))
+    if (0 <= m_hover_id && m_hover_id < 3)
         m_gizmos[m_hover_id].stop_dragging();
 }
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index 3245c4dbe..1ef4f8c23 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -30,15 +30,16 @@ public:
 
 private:
     Axis m_axis;
-    double m_angle;
-
-    mutable Vec3d m_center;
-    mutable float m_radius;
-
-    mutable float m_snap_coarse_in_radius;
-    mutable float m_snap_coarse_out_radius;
-    mutable float m_snap_fine_in_radius;
-    mutable float m_snap_fine_out_radius;
+    double m_angle{ 0.0 };
+    Vec3d m_center{ Vec3d::Zero() };
+    float m_radius{ 0.0 };
+    float m_snap_coarse_in_radius{ 0.0 };
+    float m_snap_coarse_out_radius{ 0.0 };
+    float m_snap_fine_in_radius{ 0.0 };
+    float m_snap_fine_out_radius{ 0.0 };
+#if ENABLE_WORLD_COORDINATE
+    Transform3d m_orient_matrix{ Transform3d::Identity() };
+#endif // ENABLE_WORLD_COORDINATE
 
 public:
     GLGizmoRotate(GLCanvas3D& parent, Axis axis);
@@ -70,6 +71,10 @@ private:
     void transform_to_local(const Selection& selection) const;
     // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate
     Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const Selection& selection) const;
+
+#if ENABLE_WORLD_COORDINATE
+    void init_data_from_selection(const Selection& selection);
+#endif // ENABLE_WORLD_COORDINATE
 };
 
 class GLGizmoRotate3D : public GLGizmoBase
@@ -80,7 +85,7 @@ public:
     GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
 
     Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); }
-    void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); }
+    void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation.x()); m_gizmos[Y].set_angle(rotation.y()); m_gizmos[Z].set_angle(rotation.z()); }
 
     std::string get_tooltip() const override
     {
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index fa90809b9..2e5d864e9 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -640,7 +640,11 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
         case Rotate:
         {
             // Apply new temporary rotations
+#if ENABLE_WORLD_COORDINATE
+            TransformationType transformation_type(wxGetApp().obj_manipul()->get_world_coordinates() ? TransformationType::World_Relative_Joint : TransformationType::Local_Relative_Joint);
+#else
             TransformationType transformation_type(TransformationType::World_Relative_Joint);
+#endif // ENABLE_WORLD_COORDINATE
             if (evt.AltDown())
                 transformation_type.set_independent();
             selection.rotate(get_rotation(), transformation_type);
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index cace70491..8dd169a62 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -741,7 +741,7 @@ void Selection::translate(const Vec3d& displacement, bool local)
 
 #if !DISABLE_INSTANCES_SYNCH
     if (translation_type == Instance)
-        synchronize_unselected_instances(SYNC_ROTATION_NONE);
+        synchronize_unselected_instances(SyncRotationType::NONE);
     else if (translation_type == Volume)
         synchronize_unselected_volumes();
 #endif // !DISABLE_INSTANCES_SYNCH
@@ -793,11 +793,22 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
                     const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
                     const Vec3d    &rotation = first_volume.get_instance_rotation();
                     const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
-                    volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
+                    volume.set_instance_rotation(Vec3d(rotation.x(), rotation.y(), rotation.z() + z_diff));
                 }
                 else {
                     // extracts rotations from the composed transformation
-                    Vec3d new_rotation = transformation_type.world() ?
+#if ENABLE_WORLD_COORDINATE
+                    const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+                    const Vec3d new_rotation = transformation_type.world() ?
+                        Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
+                        transformation_type.absolute() ? rotation : Geometry::extract_euler_angles(m_cache.volumes_data[i].get_instance_rotation_matrix() * m);
+                    if (rot_axis_max == 2 && transformation_type.world() && transformation_type.joint()) {
+                        // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
+                        const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation);
+                        volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
+                    }
+#else
+                    const Vec3d new_rotation = transformation_type.world() ?
                         Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
                         transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
                     if (rot_axis_max == 2 && transformation_type.joint()) {
@@ -805,6 +816,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
                         const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), new_rotation);
                         volume.set_instance_offset(m_cache.dragging_center + Eigen::AngleAxisd(z_diff, Vec3d::UnitZ()) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
                     }
+#endif // ENABLE_WORLD_COORDINATE
                     volume.set_instance_rotation(new_rotation);
                     object_instance_first[volume.object_idx()] = i;
                 }
@@ -823,14 +835,13 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
                         v.set_volume_rotation(new_rotation);
                     }
                 }
-                else
-                {
+                else {
                     if (m_mode == Instance)
                         rotate_instance(v, i);
                     else if (m_mode == Volume) {
                         // extracts rotations from the composed transformation
-                        Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
-                        Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
+                        const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+                        const Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
                         if (transformation_type.joint()) {
                             const Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
                             const Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
@@ -842,12 +853,25 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
             }
         }
 
-    #if !DISABLE_INSTANCES_SYNCH
+#if !DISABLE_INSTANCES_SYNCH
+#if ENABLE_WORLD_COORDINATE
+        if (m_mode == Instance) {
+            SyncRotationType synch;
+            if (transformation_type.world() && rot_axis_max == 2)
+                synch = SyncRotationType::NONE;
+            else if (transformation_type.local())
+                synch = SyncRotationType::FULL;
+            else
+                synch = SyncRotationType::GENERAL;
+            synchronize_unselected_instances(synch);
+        }
+#else
         if (m_mode == Instance)
             synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
+#endif // ENABLE_WORLD_COORDINATE
         else if (m_mode == Volume)
             synchronize_unselected_volumes();
-    #endif // !DISABLE_INSTANCES_SYNCH
+#endif // !DISABLE_INSTANCES_SYNCH
     }
     else { // it's the wipe tower that's selected and being rotated
         GLVolume& volume = *((*m_volumes)[*m_list.begin()]); // the wipe tower is always alone in the selection
@@ -855,7 +879,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
         // make sure the wipe tower rotates around its center, not origin
         // we can assume that only Z rotation changes
         const Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset();
-        const Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0.0, 0.0, 1.0)) * center_local;
+        const Vec3d center_local_new = Eigen::AngleAxisd(rotation.z()-volume.get_volume_rotation().z(), Vec3d::UnitZ()) * center_local;
         volume.set_volume_rotation(rotation);
         volume.set_volume_offset(volume.get_volume_offset() + center_local - center_local_new);
     }
@@ -889,7 +913,7 @@ void Selection::flattening_rotate(const Vec3d& normal)
     // Apply the same transformation also to other instances,
     // but respect their possibly diffrent z-rotation.
     if (m_mode == Instance)
-        synchronize_unselected_instances(SYNC_ROTATION_GENERAL);
+        synchronize_unselected_instances(SyncRotationType::GENERAL);
 #endif // !DISABLE_INSTANCES_SYNCH
 
     this->set_bounding_boxes_dirty();
@@ -952,7 +976,7 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
 
 #if !DISABLE_INSTANCES_SYNCH
     if (m_mode == Instance)
-        synchronize_unselected_instances(SYNC_ROTATION_NONE);
+        synchronize_unselected_instances(SyncRotationType::NONE);
     else if (m_mode == Volume)
         synchronize_unselected_volumes();
 #endif // !DISABLE_INSTANCES_SYNCH
@@ -1019,7 +1043,7 @@ void Selection::mirror(Axis axis)
 
 #if !DISABLE_INSTANCES_SYNCH
     if (m_mode == Instance)
-        synchronize_unselected_instances(SYNC_ROTATION_NONE);
+        synchronize_unselected_instances(SyncRotationType::NONE);
     else if (m_mode == Volume)
         synchronize_unselected_volumes();
 #endif // !DISABLE_INSTANCES_SYNCH
@@ -1359,8 +1383,7 @@ void Selection::copy_to_clipboard()
 
     m_clipboard.reset();
 
-    for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content)
-    {
+    for (const ObjectIdxsToInstanceIdxsMap::value_type& object : m_cache.content) {
         ModelObject* src_object = m_model->objects[object.first];
         ModelObject* dst_object = m_clipboard.add_object();
         dst_object->name                 = src_object->name;
@@ -1373,26 +1396,22 @@ void Selection::copy_to_clipboard()
         dst_object->layer_height_profile.assign(src_object->layer_height_profile);
         dst_object->origin_translation   = src_object->origin_translation;
 
-        for (int i : object.second)
-        {
+        for (int i : object.second) {
             dst_object->add_instance(*src_object->instances[i]);
         }
 
-        for (unsigned int i : m_list)
-        {
+        for (unsigned int i : m_list) {
             // Copy the ModelVolumes only for the selected GLVolumes of the 1st selected instance.
             const GLVolume* volume = (*m_volumes)[i];
-            if ((volume->object_idx() == object.first) && (volume->instance_idx() == *object.second.begin()))
-            {
+            if (volume->object_idx() == object.first && volume->instance_idx() == *object.second.begin()) {
                 int volume_idx = volume->volume_idx();
-                if ((0 <= volume_idx) && (volume_idx < (int)src_object->volumes.size()))
-                {
+                if (0 <= volume_idx && volume_idx < (int)src_object->volumes.size()) {
                     ModelVolume* src_volume = src_object->volumes[volume_idx];
                     ModelVolume* dst_volume = dst_object->add_volume(*src_volume);
                     dst_volume->set_new_unique_id();
-                } else {
-                    assert(false);
                 }
+                else
+                    assert(false);
             }
         }
     }
@@ -1428,8 +1447,7 @@ std::vector<unsigned int> Selection::get_volume_idxs_from_object(unsigned int ob
 {
     std::vector<unsigned int> idxs;
 
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
         if ((*m_volumes)[i]->object_idx() == (int)object_idx)
             idxs.push_back(i);
     }
@@ -1441,10 +1459,9 @@ std::vector<unsigned int> Selection::get_volume_idxs_from_instance(unsigned int
 {
     std::vector<unsigned int> idxs;
 
-    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
-    {
+    for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) {
         const GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == (int)object_idx) && (v->instance_idx() == (int)instance_idx))
+        if (v->object_idx() == (int)object_idx && v->instance_idx() == (int)instance_idx)
             idxs.push_back(i);
     }
 
@@ -1458,9 +1475,8 @@ std::vector<unsigned int> Selection::get_volume_idxs_from_volume(unsigned int ob
     for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
     {
         const GLVolume* v = (*m_volumes)[i];
-        if ((v->object_idx() == (int)object_idx) && (v->volume_idx() == (int)volume_idx))
-        {
-            if (((int)instance_idx != -1) && (v->instance_idx() == (int)instance_idx))
+        if (v->object_idx() == (int)object_idx && v->volume_idx() == (int)volume_idx) {
+            if ((int)instance_idx != -1 && v->instance_idx() == (int)instance_idx)
                 idxs.push_back(i);
         }
     }
@@ -1472,8 +1488,7 @@ std::vector<unsigned int> Selection::get_missing_volume_idxs_from(const std::vec
 {
     std::vector<unsigned int> idxs;
 
-    for (unsigned int i : m_list)
-    {
+    for (unsigned int i : m_list) {
         std::vector<unsigned int>::const_iterator it = std::find(volume_idxs.begin(), volume_idxs.end(), i);
         if (it == volume_idxs.end())
             idxs.push_back(i);
@@ -1486,8 +1501,7 @@ std::vector<unsigned int> Selection::get_unselected_volume_idxs_from(const std::
 {
     std::vector<unsigned int> idxs;
 
-    for (unsigned int i : volume_idxs)
-    {
+    for (unsigned int i : volume_idxs) {
         if (m_list.find(i) == m_list.end())
             idxs.push_back(i);
     }
@@ -1505,8 +1519,7 @@ void Selection::update_type()
     m_cache.content.clear();
     m_type = Mixed;
 
-    for (unsigned int i : m_list)
-    {
+    for (unsigned int i : m_list) {
         const GLVolume* volume = (*m_volumes)[i];
         int obj_idx = volume->object_idx();
         int inst_idx = volume->instance_idx();
@@ -1525,23 +1538,19 @@ void Selection::update_type()
     {
         if (m_list.empty())
             m_type = Empty;
-        else if (m_list.size() == 1)
-        {
+        else if (m_list.size() == 1) {
             const GLVolume* first = (*m_volumes)[*m_list.begin()];
             if (first->is_wipe_tower)
                 m_type = WipeTower;
-            else if (first->is_modifier)
-            {
+            else if (first->is_modifier) {
                 m_type = SingleModifier;
                 requires_disable = true;
             }
-            else
-            {
+            else {
                 const ModelObject* model_object = m_model->objects[first->object_idx()];
                 unsigned int volumes_count = (unsigned int)model_object->volumes.size();
                 unsigned int instances_count = (unsigned int)model_object->instances.size();
-                if (volumes_count * instances_count == 1)
-                {
+                if (volumes_count * instances_count == 1) {
                     m_type = SingleFullObject;
                     // ensures the correct mode is selected
                     m_mode = Instance;
@@ -1552,15 +1561,13 @@ void Selection::update_type()
                     // ensures the correct mode is selected
                     m_mode = Instance;
                 }
-                else
-                {
+                else {
                     m_type = SingleVolume;
                     requires_disable = true;
                 }
             }
         }
-        else
-        {
+        else {
             unsigned int sla_volumes_count = 0;
             // Note: sla_volumes_count is a count of the selected sla_volumes per object instead of per instance, like a model_volumes_count is
             for (unsigned int i : m_list) {
@@ -1575,25 +1582,20 @@ void Selection::update_type()
 
                 unsigned int instances_count = (unsigned int)model_object->instances.size();
                 unsigned int selected_instances_count = (unsigned int)m_cache.content.begin()->second.size();
-                if (model_volumes_count * instances_count + sla_volumes_count == (unsigned int)m_list.size())
-                {
+                if (model_volumes_count * instances_count + sla_volumes_count == (unsigned int)m_list.size()) {
                     m_type = SingleFullObject;
                     // ensures the correct mode is selected
                     m_mode = Instance;
                 }
-                else if (selected_instances_count == 1)
-                {
-                    if (model_volumes_count + sla_volumes_count == (unsigned int)m_list.size())
-                    {
+                else if (selected_instances_count == 1) {
+                    if (model_volumes_count + sla_volumes_count == (unsigned int)m_list.size()) {
                         m_type = SingleFullInstance;
                         // ensures the correct mode is selected
                         m_mode = Instance;
                     }
-                    else
-                    {
+                    else {
                         unsigned int modifiers_count = 0;
-                        for (unsigned int i : m_list)
-                        {
+                        for (unsigned int i : m_list) {
                             if ((*m_volumes)[i]->is_modifier)
                                 ++modifiers_count;
                         }
@@ -1606,25 +1608,21 @@ void Selection::update_type()
                         requires_disable = true;
                     }
                 }
-                else if ((selected_instances_count > 1) && (selected_instances_count * model_volumes_count + sla_volumes_count == (unsigned int)m_list.size()))
-                {
+                else if (selected_instances_count > 1 && selected_instances_count * model_volumes_count + sla_volumes_count == (unsigned int)m_list.size()) {
                     m_type = MultipleFullInstance;
                     // ensures the correct mode is selected
                     m_mode = Instance;
                 }
             }
-            else
-            {
+            else {
                 unsigned int sels_cntr = 0;
-                for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
-                {
+                for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it) {
                     const ModelObject* model_object = m_model->objects[it->first];
                     unsigned int volumes_count = (unsigned int)model_object->volumes.size();
                     unsigned int instances_count = (unsigned int)model_object->instances.size();
                     sels_cntr += volumes_count * instances_count;
                 }
-                if (sels_cntr + sla_volumes_count == (unsigned int)m_list.size())
-                {
+                if (sels_cntr + sla_volumes_count == (unsigned int)m_list.size()) {
                     m_type = MultipleFullObject;
                     // ensures the correct mode is selected
                     m_mode = Instance;
@@ -1635,8 +1633,7 @@ void Selection::update_type()
 
     int object_idx = get_object_idx();
     int instance_idx = get_instance_idx();
-    for (GLVolume* v : *m_volumes)
-    {
+    for (GLVolume* v : *m_volumes) {
         v->disabled = requires_disable ? (v->object_idx() != object_idx) || (v->instance_idx() != instance_idx) : false;
     }
 
@@ -2091,7 +2088,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
 
             assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
             switch (sync_rotation_type) {
-            case SYNC_ROTATION_NONE: {
+            case SyncRotationType::NONE: {
                 // z only rotation -> synch instance z
                 // The X,Y rotations should be synchronized from start to end of the rotation.
                 assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation()));
@@ -2099,12 +2096,25 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
                     v->set_instance_offset(Z, volume->get_instance_offset().z());
                 break;
             }
-            case SYNC_ROTATION_GENERAL:
+            case SyncRotationType::GENERAL: {
                 // generic rotation -> update instance z with the delta of the rotation.
                 const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
                 v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
                 break;
             }
+#if ENABLE_WORLD_COORDINATE
+            case SyncRotationType::FULL: {
+                // generic rotation -> update instance z with the delta of the rotation.
+                const Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rotation, m_cache.volumes_data[j].get_instance_rotation()));
+                const Vec3d& axis = angle_axis.axis();
+                const double z_diff = (std::abs(axis.x()) > EPSILON || std::abs(axis.y()) > EPSILON) ?
+                    angle_axis.angle() * axis.z() : Geometry::rotation_diff_z(rotation, m_cache.volumes_data[j].get_instance_rotation());
+
+                v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
+                break;
+            }
+#endif // ENABLE_WORLD_COORDINATE
+            }
 
             v->set_instance_scaling_factor(scaling_factor);
             v->set_instance_mirror(mirror);
diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp
index dea507511..94ca35eab 100644
--- a/src/slic3r/GUI/Selection.hpp
+++ b/src/slic3r/GUI/Selection.hpp
@@ -368,11 +368,15 @@ private:
     void render_sidebar_layers_hints(const std::string& sidebar_field) const;
 
 public:
-    enum SyncRotationType {
+    enum class SyncRotationType {
         // Do not synchronize rotation. Either not rotating at all, or rotating by world Z axis.
-        SYNC_ROTATION_NONE = 0,
+        NONE = 0,
         // Synchronize after rotation by an axis not parallel with Z.
-        SYNC_ROTATION_GENERAL = 1,
+        GENERAL = 1,
+#if ENABLE_WORLD_COORDINATE
+        // Fully synchronize rotation.
+        FULL = 2,
+#endif // ENABLE_WORLD_COORDINATE
     };
     void synchronize_unselected_instances(SyncRotationType sync_rotation_type);
     void synchronize_unselected_volumes();