From f2bb070ab94b01bd2a0c6b63bd37a8ff800ad4b4 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Wed, 1 May 2019 11:33:41 +0200
Subject: [PATCH] Implemented scaling of instances through the object
 manipulation box for rotated, but still axis aligned coordinate systems.

---
 src/slic3r/GUI/GUI_ObjectManipulation.cpp | 24 +++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index 010291156..174879adc 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -420,8 +420,6 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
 		transformation_type.set_local();
 	}
 
-    //FIXME if anisotropic scaling is required, and is_single_full_instance && m_world_coordinates, apply 90 degrees rotation of the rotation vector.
-
     selection.start_dragging();
 	selection.rotate(
 		(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation), 
@@ -482,17 +480,27 @@ void ObjectManipulation::do_scale(const Vec3d &scale) const
     Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
     Vec3d scaling_factor = scale;
 
-    if (m_uniform_scale || selection.requires_uniform_scale())
-    {
+    TransformationType transformation_type(TransformationType::World_Relative_Joint);
+    if (selection.is_single_full_instance()) {
+        if (m_world_coordinates) {
+            // Only a 90 degree rotation is allowed, therefore an axis aligned scaling will
+            // be still axis aligned after the instance rotation is applied.
+            const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
+            scaling_factor = (volume->get_instance_transformation().get_matrix(true, false, true, true) * scale).cwiseAbs();
+            // Absolute scaling shall not change.
+            assert(std::abs(scale.maxCoeff() - scaling_factor.maxCoeff()) < EPSILON);
+			assert(std::abs(scale.minCoeff() - scaling_factor.minCoeff()) < EPSILON);
+			assert(std::abs(scale.squaredNorm() - scaling_factor.squaredNorm()) < EPSILON);
+		} else
+            transformation_type.set_local();
+    }
+
+    if (m_uniform_scale || selection.requires_uniform_scale()) {
         int max_diff_axis;
         (scale - m_cache.scale).cwiseAbs().maxCoeff(&max_diff_axis);
         scaling_factor = scale(max_diff_axis) * Vec3d::Ones();
     }
 
-    TransformationType transformation_type(TransformationType::World_Relative_Joint);
-    if (selection.is_single_full_instance() && ! m_world_coordinates)
-        transformation_type.set_local();
-    //FIXME if anisotropic scaling is required, and is_single_full_instance && m_world_coordinates, apply 90 degrees rotation of the scaling vector.
     selection.start_dragging();
     selection.scale(scaling_factor * 0.01, transformation_type);
     wxGetApp().plater()->canvas3D()->do_scale();