Browse Source

GDK SceneComposer :
- add a new file : PickManager that provide severals informations for tools.
- modified the MoveTool, RotateTool and ScaleTool according with the pickManager
- now local/global choice for transformations is just a step away

Maselbas 10 years ago
parent
commit
2158a4bffe

+ 90 - 22
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java

@@ -5,8 +5,11 @@
 package com.jme3.gde.scenecomposer.tools;
 
 import com.jme3.asset.AssetManager;
+import com.jme3.bullet.control.CharacterControl;
+import com.jme3.bullet.control.RigidBodyControl;
 import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
 import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
+import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
 import com.jme3.gde.scenecomposer.SceneComposerToolController;
 import com.jme3.gde.scenecomposer.SceneEditTool;
 import com.jme3.math.Vector2f;
@@ -17,12 +20,11 @@ import org.openide.loaders.DataObject;
 import org.openide.util.Lookup;
 
 /**
- * Move an object.
- * When created, it generates a quad that will lie along a plane
- * that the user selects for moving on. When the mouse is over
- * the axisMarker, it will highlight the plane that it is over: XY,XZ,YZ.
- * When clicked and then dragged, the selected object will move along that 
- * plane.
+ * Move an object. When created, it generates a quad that will lie along a plane
+ * that the user selects for moving on. When the mouse is over the axisMarker,
+ * it will highlight the plane that it is over: XY,XZ,YZ. When clicked and then
+ * dragged, the selected object will move along that plane.
+ *
  * @author Brent Owens
  */
 public class MoveTool extends SceneEditTool {
@@ -30,7 +32,9 @@ public class MoveTool extends SceneEditTool {
     private Vector3f pickedMarker;
     private Vector3f constraintAxis; //used for one axis move
     private boolean wasDragging = false;
-    private MoveManager moveManager;
+    private Vector3f startPosition;
+    private Vector3f lastPosition;
+    private PickManager pickManager;
 
     public MoveTool() {
         axisPickType = AxisMarkerPickType.axisAndPlane;
@@ -41,7 +45,7 @@ public class MoveTool extends SceneEditTool {
     @Override
     public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
         super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController);
-        moveManager = Lookup.getDefault().lookup(MoveManager.class);
+        pickManager = Lookup.getDefault().lookup(PickManager.class);
         displayPlanes();
     }
 
@@ -52,10 +56,10 @@ public class MoveTool extends SceneEditTool {
             pickedMarker = null; // mouse released, reset selection
             constraintAxis = Vector3f.UNIT_XYZ; // no constraint
             if (wasDragging) {
-                actionPerformed(moveManager.makeUndo());
+                actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startPosition, lastPosition));
                 wasDragging = false;
-    }
-            moveManager.reset();
+            }
+            pickManager.reset();
         }
     }
 
@@ -70,21 +74,21 @@ public class MoveTool extends SceneEditTool {
             highlightAxisMarker(camera, screenCoord, axisPickType);
         } else {
             pickedMarker = null;
-            moveManager.reset();
+            pickManager.reset();
         }
     }
 
     @Override
     public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
-    if (!pressed) {
+        if (!pressed) {
             setDefaultAxisMarkerColors();
             pickedMarker = null; // mouse released, reset selection
             constraintAxis = Vector3f.UNIT_XYZ; // no constraint
             if (wasDragging) {
-                actionPerformed(moveManager.makeUndo());
+                actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startPosition, lastPosition));
                 wasDragging = false;
             }
-            moveManager.reset();
+            pickManager.reset();
             return;
         }
 
@@ -99,25 +103,43 @@ public class MoveTool extends SceneEditTool {
             }
 
             if (pickedMarker.equals(QUAD_XY)) {
-                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.XY, true);
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY,
+                        PickManager.TransformationType.local, camera, screenCoord);
             } else if (pickedMarker.equals(QUAD_XZ)) {
-                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.XZ, true);
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ,
+                        PickManager.TransformationType.local, camera, screenCoord);
             } else if (pickedMarker.equals(QUAD_YZ)) {
-                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.YZ, true);
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ,
+                        PickManager.TransformationType.local, camera, screenCoord);
             } else if (pickedMarker.equals(ARROW_X)) {
-                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.XY, true);
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY,
+                        PickManager.TransformationType.local, camera, screenCoord);
                 constraintAxis = Vector3f.UNIT_X; // move only X
             } else if (pickedMarker.equals(ARROW_Y)) {
-                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.YZ, true);
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ,
+                        PickManager.TransformationType.local, camera, screenCoord);
                 constraintAxis = Vector3f.UNIT_Y; // move only Y
             } else if (pickedMarker.equals(ARROW_Z)) {
-                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.XZ, true);
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ,
+                        PickManager.TransformationType.local, camera, screenCoord);
                 constraintAxis = Vector3f.UNIT_Z; // move only Z
             }
+            startPosition = toolController.getSelectedSpatial().getLocalTranslation().clone();
+
         }
-        if (!moveManager.move(camera, screenCoord, constraintAxis, false)) {
+        if (!pickManager.updatePick(camera, screenCoord)) {
             return;
         }
+        Vector3f diff = Vector3f.ZERO;
+        if (pickedMarker.equals(QUAD_XY) || pickedMarker.equals(QUAD_XZ) || pickedMarker.equals(QUAD_YZ)) {
+            diff = pickManager.getTranslation();
+
+        } else if (pickedMarker.equals(ARROW_X) || pickedMarker.equals(ARROW_Y) || pickedMarker.equals(ARROW_Z)) {
+            diff = pickManager.getTranslation(constraintAxis);
+        }
+        Vector3f position = startPosition.add(diff);
+        lastPosition = position;
+        toolController.getSelectedSpatial().setLocalTranslation(position);
         updateToolsTransformation();
 
         wasDragging = true;
@@ -126,4 +148,50 @@ public class MoveTool extends SceneEditTool {
     @Override
     public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
     }
+
+    protected class MoveUndo extends AbstractUndoableSceneEdit {
+
+        private Spatial spatial;
+        private Vector3f before = new Vector3f(), after = new Vector3f();
+
+        MoveUndo(Spatial spatial, Vector3f before, Vector3f after) {
+            this.spatial = spatial;
+            this.before.set(before);
+            if (after != null) {
+                this.after.set(after);
+            }
+        }
+
+        @Override
+        public void sceneUndo() {
+            spatial.setLocalTranslation(before);
+            RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
+            if (control != null) {
+                control.setPhysicsLocation(spatial.getWorldTranslation());
+            }
+            CharacterControl character = spatial.getControl(CharacterControl.class);
+            if (character != null) {
+                character.setPhysicsLocation(spatial.getWorldTranslation());
+            }
+            //     toolController.selectedSpatialTransformed();
+        }
+
+        @Override
+        public void sceneRedo() {
+            spatial.setLocalTranslation(after);
+            RigidBodyControl control = spatial.getControl(RigidBodyControl.class);
+            if (control != null) {
+                control.setPhysicsLocation(spatial.getWorldTranslation());
+            }
+            CharacterControl character = spatial.getControl(CharacterControl.class);
+            if (character != null) {
+                character.setPhysicsLocation(spatial.getWorldTranslation());
+            }
+            //toolController.selectedSpatialTransformed();
+        }
+
+        public void setAfter(Vector3f after) {
+            this.after.set(after);
+        }
+    }
 }

+ 182 - 0
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java

@@ -0,0 +1,182 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.scenecomposer.tools;
+
+import com.jme3.gde.scenecomposer.SceneEditTool;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.Camera;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Quad;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ *
+ * @author dokthar
+ */
+@ServiceProvider(service = PickManager.class)
+public class PickManager {
+
+    private Vector3f startPickLoc;
+    private Vector3f finalPickLoc;
+    private Vector3f startSpatialLocation;
+    private Quaternion origineRotation;
+    private final Node plane;
+    private Spatial spatial;
+
+    protected static final Quaternion PLANE_XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
+    protected static final Quaternion PLANE_YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));//YAW090
+    protected static final Quaternion PLANE_XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0)); //PITCH090
+
+    public enum TransformationType {
+
+        local, global, camera
+    }
+
+    public PickManager() {
+        float size = 1000;
+        Geometry g = new Geometry("plane", new Quad(size, size));
+        g.setLocalTranslation(-size / 2, -size / 2, 0);
+        plane = new Node();
+        plane.attachChild(g);
+    }
+
+    public void reset() {
+        startPickLoc = null;
+        finalPickLoc = null;
+        startSpatialLocation = null;
+        spatial = null;
+    }
+
+    public void initiatePick(Spatial selectedSpatial, Quaternion planeRotation, TransformationType type, Camera camera, Vector2f screenCoord) {
+        spatial = selectedSpatial;
+        startSpatialLocation = selectedSpatial.getWorldTranslation().clone();
+
+        setTransformation(planeRotation, type);
+        plane.setLocalTranslation(startSpatialLocation);
+
+        startPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null);
+    }
+
+    public void setTransformation(Quaternion planeRotation, TransformationType type) {
+        Quaternion rot = new Quaternion();
+        if (type == TransformationType.local) {
+            rot.set(spatial.getWorldRotation());
+            rot.multLocal(planeRotation);
+            origineRotation = spatial.getWorldRotation().clone();
+        } else if (type == TransformationType.global) {
+            rot.set(planeRotation);
+            origineRotation = new Quaternion(Quaternion.IDENTITY);
+        } else if (type == TransformationType.camera) {
+            rot.set(planeRotation);
+            origineRotation = planeRotation.clone();
+        }
+        plane.setLocalRotation(rot);
+    }
+
+    public boolean updatePick(Camera camera, Vector2f screenCoord) {
+        finalPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null);
+        return finalPickLoc != null;
+    }
+
+    /**
+     *
+     * @return the start location in WorldSpace
+     */
+    public Vector3f getStartLocation() {
+        return startSpatialLocation;
+    }
+
+    /**
+     *
+     * @return the vector from the tool origin to the start location, in
+     * WorldSpace
+     */
+    public Vector3f getStartOffset() {
+        return startPickLoc.subtract(startSpatialLocation);
+    }
+
+    /**
+     *
+     * @return the vector from the tool origin to the final location, in
+     * WorldSpace
+     */
+    public Vector3f getFinalOffset() {
+        return finalPickLoc.subtract(startSpatialLocation);
+    }
+
+    /**
+     *
+     * @return the angle between the start location and the final location
+     */
+    public float getAngle() {
+        Vector3f v1, v2;
+        v1 = startPickLoc.subtract(startSpatialLocation);
+        v2 = finalPickLoc.subtract(startSpatialLocation);
+        return v1.angleBetween(v2);
+    }
+
+    /**
+     *
+     * @return the Quaternion rotation in the WorldSpace
+     */
+    public Quaternion getRotation() {
+        Vector3f v1, v2;
+        v1 = startPickLoc.subtract(startSpatialLocation).normalize();
+        v2 = finalPickLoc.subtract(startSpatialLocation).normalize();
+        Vector3f axis = v1.cross(v2);
+        float angle = v1.angleBetween(v2);
+        return new Quaternion().fromAngleAxis(angle, axis);
+    }
+
+    /**
+     * 
+     * @return the Quaternion rotation in the ToolSpace
+     */
+    public Quaternion getLocalRotation() {
+        Vector3f v1, v2;
+        Quaternion rot = origineRotation.inverse();
+        v1 = rot.mult(startPickLoc.subtract(startSpatialLocation).normalize());
+        v2 = rot.mult(finalPickLoc.subtract(startSpatialLocation).normalize());
+        Vector3f axis = v1.cross(v2);
+        float angle = v1.angleBetween(v2);
+        return new Quaternion().fromAngleAxis(angle, axis);
+    }
+
+    /**
+     *
+     * @return the translation in WorldSpace
+     */
+    public Vector3f getTranslation() {
+        return finalPickLoc.subtract(startPickLoc);
+    }
+
+    /**
+     *
+     * @param axisConstrainte
+     * @return
+     */
+    public Vector3f getTranslation(Vector3f axisConstrainte) {
+        Vector3f localConstrainte = (origineRotation.mult(axisConstrainte)).normalize(); // according to the "plane" rotation
+        Vector3f constrainedTranslation = localConstrainte.mult(getTranslation().dot(localConstrainte));
+        return constrainedTranslation;
+    }
+
+    /**
+     *
+     * @param axisConstrainte
+     * @return
+     */
+    public Vector3f getLocalTranslation(Vector3f axisConstrainte) {
+        //return plane.getWorldRotation().inverse().mult(getTranslation(axisConstrainte));
+        return getTranslation(origineRotation.inverse().mult(axisConstrainte));
+    }
+
+}

+ 56 - 67
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/RotateTool.java

@@ -16,35 +16,38 @@ import com.jme3.math.Vector3f;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import org.openide.loaders.DataObject;
- 
+import org.openide.util.Lookup;
+
 /**
  *
  * @author kbender
  */
 public class RotateTool extends SceneEditTool {
- 
-    private Vector3f pickedPlane;
+
+    private Vector3f pickedMarker;
     private Vector2f lastScreenCoord;
     private Quaternion startRotate;
     private Quaternion lastRotate;
     private boolean wasDragging = false;
- 
+    private PickManager pickManager;
+
     public RotateTool() {
-        axisPickType = AxisMarkerPickType.axisAndPlane;
+        axisPickType = AxisMarkerPickType.planeOnly;
         setOverrideCameraControl(true);
     }
- 
+
     @Override
     public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
         super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController);
+        pickManager = Lookup.getDefault().lookup(PickManager.class);
         displayPlanes();
     }
- 
+
     @Override
     public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
         if (!pressed) {
             setDefaultAxisMarkerColors();
-            pickedPlane = null; // mouse released, reset selection
+            pickedMarker = null; // mouse released, reset selection
             lastScreenCoord = null;
             if (wasDragging) {
                 actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
@@ -52,108 +55,94 @@ public class RotateTool extends SceneEditTool {
             }
         }
     }
- 
+
     @Override
     public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
- 
+
     }
- 
+
     @Override
     public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
-        if (pickedPlane == null) {
+        if (pickedMarker == null) {
             highlightAxisMarker(camera, screenCoord, axisPickType);
-        }
-        else {
-            pickedPlane = null;
+        } else {
+            pickedMarker = null;
         }
     }
- 
+
     @Override
     public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
- 
+
         if (!pressed) {
             setDefaultAxisMarkerColors();
-            pickedPlane = null; // mouse released, reset selection
+            pickedMarker = null; // mouse released, reset selection
             lastScreenCoord = null;
- 
+
             if (wasDragging) {
                 actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
                 wasDragging = false;
             }
             return;
         }
- 
-        if (toolController.getSelectedSpatial() == null)
-        {
+
+        if (toolController.getSelectedSpatial() == null) {
             return;
         }
- 
-        if (pickedPlane == null)
-        {
-            pickedPlane = pickAxisMarker(camera, screenCoord, axisPickType);
-            if (pickedPlane == null)
-            {
+
+        if (pickedMarker == null) {
+            pickedMarker = pickAxisMarker(camera, screenCoord, axisPickType);
+            if (pickedMarker == null) {
                 return;
             }
+
+            if (pickedMarker.equals(QUAD_XY)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY,
+                        PickManager.TransformationType.local, camera, screenCoord);
+            } else if (pickedMarker.equals(QUAD_XZ)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ,
+                        PickManager.TransformationType.local, camera, screenCoord);
+            } else if (pickedMarker.equals(QUAD_YZ)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ,
+                        PickManager.TransformationType.local, camera, screenCoord);
+            }
             startRotate = toolController.getSelectedSpatial().getLocalRotation().clone();
         }
- 
-        if (lastScreenCoord == null) {
-            lastScreenCoord = screenCoord;
-        } else {
-            Quaternion rotate = new Quaternion();
-            float diff;
-            if(pickedPlane.equals(QUAD_XY))
-            {
-                diff = -(screenCoord.x-lastScreenCoord.x);
-                diff *= 0.03f;
-                rotate = rotate.fromAngleAxis(diff, Vector3f.UNIT_Z);
-            }
-            else if(pickedPlane.equals(QUAD_YZ))
-            {
-                diff = -(screenCoord.y-lastScreenCoord.y);
-                diff *= 0.03f;
-                rotate = rotate.fromAngleAxis(diff, Vector3f.UNIT_X);
-            }
-            else if(pickedPlane.equals(QUAD_XZ))
-            {
-                diff = screenCoord.x-lastScreenCoord.x;
-                diff *= 0.03f;
-                rotate = rotate.fromAngleAxis(diff, Vector3f.UNIT_Y);
-            }
- 
-            lastScreenCoord = screenCoord;
-            Quaternion rotation = toolController.getSelectedSpatial().getLocalRotation().mult(rotate);
-            lastRotate = rotation;
+        if (!pickManager.updatePick(camera, screenCoord)) {
+            return;
+        }
+
+        if (pickedMarker.equals(QUAD_XY) || pickedMarker.equals(QUAD_XZ) || pickedMarker.equals(QUAD_YZ)) {
+            Quaternion rotation = startRotate.mult(pickManager.getLocalRotation());
             toolController.getSelectedSpatial().setLocalRotation(rotation);
-            updateToolsTransformation();
+            lastRotate = rotation;
         }
- 
+        updateToolsTransformation();
         wasDragging = true;
     }
- 
+
     @Override
-    public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
- 
+    public
+            void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
+
     }
- 
+
     private class ScaleUndo extends AbstractUndoableSceneEdit {
- 
+
         private Spatial spatial;
-        private Quaternion before,after;
- 
+        private Quaternion before, after;
+
         ScaleUndo(Spatial spatial, Quaternion before, Quaternion after) {
             this.spatial = spatial;
             this.before = before;
             this.after = after;
         }
- 
+
         @Override
         public void sceneUndo() {
             spatial.setLocalRotation(before);
             toolController.selectedSpatialTransformed();
         }
- 
+
         @Override
         public void sceneRedo() {
             spatial.setLocalRotation(after);

+ 35 - 16
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/ScaleTool.java

@@ -10,11 +10,13 @@ import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
 import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
 import com.jme3.gde.scenecomposer.SceneComposerToolController;
 import com.jme3.gde.scenecomposer.SceneEditTool;
+import com.jme3.math.Quaternion;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import org.openide.loaders.DataObject;
+import org.openide.util.Lookup;
 
 /**
  *
@@ -24,10 +26,10 @@ public class ScaleTool extends SceneEditTool {
 
     private Vector3f pickedMarker;
     private Vector3f constraintAxis; //used for one axis scale
-    private Vector2f lastScreenCoord;
     private Vector3f startScale;
     private Vector3f lastScale;
     private boolean wasDragging = false;
+    private PickManager pickManager;
 
     public ScaleTool() {
         axisPickType = AxisMarkerPickType.axisAndPlane;
@@ -37,6 +39,7 @@ public class ScaleTool extends SceneEditTool {
     @Override
     public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
         super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController);
+                pickManager = Lookup.getDefault().lookup(PickManager.class);
         displayPlanes();
     }
 
@@ -45,12 +48,12 @@ public class ScaleTool extends SceneEditTool {
         if (!pressed) {
             setDefaultAxisMarkerColors();
             pickedMarker = null; // mouse released, reset selection
-            lastScreenCoord = null;
             constraintAxis = Vector3f.UNIT_XYZ; // no axis constraint
             if (wasDragging) {
                 actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startScale, lastScale));
                 wasDragging = false;
             }
+            pickManager.reset();
         }
     }
 
@@ -63,11 +66,10 @@ public class ScaleTool extends SceneEditTool {
     public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
         if (pickedMarker == null) {
             highlightAxisMarker(camera, screenCoord, axisPickType, true);
+        } else {
+            pickedMarker = null;
+            pickManager.reset();
         }
-        /*else {
-         pickedPlane = null;
-         lastScreenCoord = null;
-         }*/
     }
 
     @Override
@@ -75,12 +77,12 @@ public class ScaleTool extends SceneEditTool {
         if (!pressed) {
             setDefaultAxisMarkerColors();
             pickedMarker = null; // mouse released, reset selection
-            lastScreenCoord = null;
             constraintAxis = Vector3f.UNIT_XYZ; // no axis constraint
             if (wasDragging) {
                 actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startScale, lastScale));
                 wasDragging = false;
             }
+            pickManager.reset();
             return;
         }
 
@@ -92,27 +94,44 @@ public class ScaleTool extends SceneEditTool {
             if (pickedMarker == null) {
                 return;
             }
-            if (pickedMarker.equals(ARROW_X)) {
+
+            if (pickedMarker.equals(QUAD_XY) || pickedMarker.equals(QUAD_XZ) || pickedMarker.equals(QUAD_YZ)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), 
+                        PickManager.TransformationType.camera, camera, screenCoord);
+            } else if (pickedMarker.equals(ARROW_X)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, 
+                        PickManager.TransformationType.global, camera, screenCoord);
                 constraintAxis = Vector3f.UNIT_X; // scale only X
             } else if (pickedMarker.equals(ARROW_Y)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, 
+                        PickManager.TransformationType.global, camera, screenCoord);
                 constraintAxis = Vector3f.UNIT_Y; // scale only Y
             } else if (pickedMarker.equals(ARROW_Z)) {
+                pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, 
+                        PickManager.TransformationType.global, camera, screenCoord);
                 constraintAxis = Vector3f.UNIT_Z; // scale only Z
             }
             startScale = toolController.getSelectedSpatial().getLocalScale().clone();
         }
 
-        if (lastScreenCoord == null) {
-            lastScreenCoord = screenCoord;
-        } else {
-            float diff = screenCoord.y - lastScreenCoord.y;
-            diff *= 0.1f;
-            lastScreenCoord = screenCoord;
-            Vector3f scale = toolController.getSelectedSpatial().getLocalScale().add(new Vector3f(diff, diff, diff).multLocal(constraintAxis));
+        if (!pickManager.updatePick(camera, screenCoord)) {
+            return;
+        }
+        if (pickedMarker.equals(QUAD_XY) || pickedMarker.equals(QUAD_XZ) || pickedMarker.equals(QUAD_YZ)) {
+            constraintAxis = pickManager.getStartOffset().normalize();
+            float diff = pickManager.getTranslation(constraintAxis).dot(constraintAxis);
+            diff *= 0.5f;
+            Vector3f scale = startScale.add(new Vector3f(diff, diff, diff));
+            lastScale = scale;
+            toolController.getSelectedSpatial().setLocalScale(scale);
+        } else if (pickedMarker.equals(ARROW_X) || pickedMarker.equals(ARROW_Y) || pickedMarker.equals(ARROW_Z)) {
+            Vector3f diff = pickManager.getLocalTranslation(constraintAxis);
+            diff.multLocal(0.5f);
+            Vector3f scale = startScale.add(diff);
             lastScale = scale;
             toolController.getSelectedSpatial().setLocalScale(scale);
-            updateToolsTransformation();
         }
+        updateToolsTransformation();
 
         wasDragging = true;
     }