Explorar el Código

SDK :
- Created a MoveManager than now handles move methods.
- MoveTool and SelectTool now use the MoveManager.
- Blender like move now use a camera aligned plane to move along so things are more "blenderish"
- One can enter move/rotate/scale values with the numpad


git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9604 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

rem..om hace 13 años
padre
commit
2a04470702

+ 1 - 1
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java

@@ -48,7 +48,7 @@ public class SceneComposerToolController extends SceneToolController {
     private Material audioMarkerMaterial;
     private JmeSpatial selectedSpatial;
     private boolean snapToGrid = false;
-    private boolean snapToScene = true;
+    private boolean snapToScene = false;
     private boolean selectTerrain = false;
 
     public SceneComposerToolController(final Node toolsNode, AssetManager manager, JmeNode rootNode) {

+ 9 - 1
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form

@@ -620,7 +620,9 @@
         </Component>
         <Component class="javax.swing.JCheckBox" name="snapToSceneCheckbox">
           <Properties>
-            <Property name="selected" type="boolean" value="true"/>
+            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+              <Color blue="cc" green="cc" red="cc" type="rgb"/>
+            </Property>
             <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
               <ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.snapToSceneCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
             </Property>
@@ -634,6 +636,9 @@
         </Component>
         <Component class="javax.swing.JCheckBox" name="snapToGridCheckbox">
           <Properties>
+            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+              <Color blue="cc" green="cc" red="cc" type="rgb"/>
+            </Property>
             <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
               <ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.snapToGridCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
             </Property>
@@ -647,6 +652,9 @@
         </Component>
         <Component class="javax.swing.JCheckBox" name="selectTerrainCheckbox">
           <Properties>
+            <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+              <Color blue="cc" green="cc" red="cc" type="rgb"/>
+            </Property>
             <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
               <ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.selectTerrainCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
             </Property>

+ 3 - 1
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java

@@ -428,7 +428,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
             }
         });
 
-        snapToSceneCheckbox.setSelected(true);
+        snapToSceneCheckbox.setBackground(new java.awt.Color(204, 204, 204));
         org.openide.awt.Mnemonics.setLocalizedText(snapToSceneCheckbox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToSceneCheckbox.text")); // NOI18N
         snapToSceneCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToSceneCheckbox.toolTipText")); // NOI18N
         snapToSceneCheckbox.addActionListener(new java.awt.event.ActionListener() {
@@ -437,6 +437,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
             }
         });
 
+        snapToGridCheckbox.setBackground(new java.awt.Color(204, 204, 204));
         org.openide.awt.Mnemonics.setLocalizedText(snapToGridCheckbox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToGridCheckbox.text")); // NOI18N
         snapToGridCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToGridCheckbox.toolTipText")); // NOI18N
         snapToGridCheckbox.addActionListener(new java.awt.event.ActionListener() {
@@ -445,6 +446,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
             }
         });
 
+        selectTerrainCheckbox.setBackground(new java.awt.Color(204, 204, 204));
         org.openide.awt.Mnemonics.setLocalizedText(selectTerrainCheckbox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectTerrainCheckbox.text")); // NOI18N
         selectTerrainCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectTerrainCheckbox.toolTipText")); // NOI18N
         selectTerrainCheckbox.addActionListener(new java.awt.event.ActionListener() {

+ 37 - 52
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java

@@ -6,14 +6,6 @@ package com.jme3.gde.scenecomposer;
 
 import com.jme3.asset.AssetManager;
 import com.jme3.bounding.BoundingBox;
-import com.jme3.bounding.BoundingVolume;
-import com.jme3.bullet.collision.PhysicsCollisionObject;
-import com.jme3.bullet.control.CharacterControl;
-import com.jme3.bullet.control.GhostControl;
-import com.jme3.bullet.control.PhysicsControl;
-import com.jme3.bullet.control.RigidBodyControl;
-import com.jme3.bullet.control.VehicleControl;
-import com.jme3.bullet.util.DebugShapeFactory;
 import com.jme3.collision.CollisionResult;
 import com.jme3.collision.CollisionResults;
 import com.jme3.gde.core.scene.SceneApplication;
@@ -27,19 +19,15 @@ import com.jme3.material.RenderState.BlendMode;
 import com.jme3.material.RenderState.FaceCullMode;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.FastMath;
-import com.jme3.math.Matrix3f;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Ray;
-import com.jme3.math.Transform;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.scene.debug.Arrow;
-import com.jme3.scene.debug.WireBox;
 import com.jme3.scene.shape.Quad;
 import java.util.Iterator;
 import java.util.concurrent.Callable;
@@ -136,7 +124,6 @@ public abstract class SceneEditTool {
                 doUpdateToolsTransformation();
                 return null;
             }
-
         });
     }
 
@@ -150,7 +137,7 @@ public abstract class SceneEditTool {
             axisMarker.setLocalRotation(Quaternion.IDENTITY);
         }
     }
-    
+
     /**
      * Adjust the scale of the marker so it is relative to the size of the
      * selected spatial. It will have a minimum scale of 2.
@@ -160,14 +147,14 @@ public abstract class SceneEditTool {
             if (selected.getWorldBound() instanceof BoundingBox) {
                 BoundingBox bbox = (BoundingBox) selected.getWorldBound();
                 float smallest = Math.min(Math.min(bbox.getXExtent(), bbox.getYExtent()), bbox.getZExtent());
-                float scale = Math.max(1, smallest/2f);
-                axisMarker.setLocalScale(new Vector3f(scale,scale,scale));
+                float scale = Math.max(1, smallest / 2f);
+                axisMarker.setLocalScale(new Vector3f(scale, scale, scale));
             }
         } else {
-            axisMarker.setLocalScale(new Vector3f(2,2,2));
+            axisMarker.setLocalScale(new Vector3f(2, 2, 2));
         }
     }
-    
+
     /**
      * The primary action for the tool gets activated
      */
@@ -193,8 +180,9 @@ public abstract class SceneEditTool {
      */
     public abstract void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject);
 
-    public void keyPressed(KeyInputEvent kie) {}
-    
+    public void keyPressed(KeyInputEvent kie) {
+    }
+
     /**
      * Call when an action is performed that requires the scene to be saved
      * and an undo can be performed
@@ -210,7 +198,7 @@ public abstract class SceneEditTool {
      * @param jmeRootNode to pick from
      * @return the selected spatial, or null if nothing
      */
-    protected Spatial pickWorldSpatial(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) {
+    public static Spatial pickWorldSpatial(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) {
         Node rootNode = jmeRootNode.getLookup().lookup(Node.class);
         CollisionResult cr = pick(cam, mouseLoc, rootNode);
         if (cr != null) {
@@ -226,24 +214,22 @@ public abstract class SceneEditTool {
      * @param jmeRootNode to pick from
      * @return the location of the pick, or null if nothing collided with the mouse
      */
-    protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) {
+    public static Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) {
         Node rootNode = jmeRootNode.getLookup().lookup(Node.class);
         return pickWorldLocation(cam, mouseLoc, rootNode, null);
     }
-    
+
     /**
      * Pick anything except the excluded spatial
      * @param excludeSpat to not pick
      */
-    protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode, JmeSpatial excludeSpat) {
+    public static Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode, JmeSpatial excludeSpat) {
         Node rootNode = jmeRootNode.getLookup().lookup(Node.class);
-        return pickWorldLocation(cam, mouseLoc, rootNode, excludeSpat);
+        Spatial exclude = excludeSpat.getLookup().lookup(Spatial.class);
+        return pickWorldLocation(cam, mouseLoc, rootNode, exclude);
     }
 
-    protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, Node rootNode, JmeSpatial excludeSpat) {
-        Spatial exclude = null;
-        if (excludeSpat != null)
-            exclude = excludeSpat.getLookup().lookup(Spatial.class);
+    public static Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, Node rootNode, Spatial exclude) {
         CollisionResult cr = doPick(cam, mouseLoc, rootNode, exclude);
         if (cr != null) {
             return cr.getContactPoint();
@@ -252,46 +238,48 @@ public abstract class SceneEditTool {
         }
     }
 
-    private CollisionResult doPick(Camera cam, Vector2f mouseLoc, Node node, Spatial exclude) {
+    private static CollisionResult doPick(Camera cam, Vector2f mouseLoc, Node node, Spatial exclude) {
         CollisionResults results = new CollisionResults();
         Ray ray = new Ray();
         Vector3f pos = cam.getWorldCoordinates(mouseLoc, 0).clone();
-        Vector3f dir = cam.getWorldCoordinates(mouseLoc, 0.1f).clone();
+        Vector3f dir = cam.getWorldCoordinates(mouseLoc, 0.3f).clone();
         dir.subtractLocal(pos).normalizeLocal();
         ray.setOrigin(pos);
         ray.setDirection(dir);
         node.collideWith(ray, results);
         CollisionResult result = null;
-        if (exclude == null)
+        if (exclude == null) {
             result = results.getClosestCollision();
-        else {
+        } else {
             Iterator<CollisionResult> it = results.iterator();
             while (it.hasNext()) {
                 CollisionResult cr = it.next();
-                if (isExcluded(cr.getGeometry(), exclude))
+                if (isExcluded(cr.getGeometry(), exclude)) {
                     continue;
-                else
+                } else {
                     return cr;
+                }
             }
-            
+
         }
         return result;
     }
-    
+
     /**
      * Is the selected spatial the one we want to exclude from the picking?
      * Recursively looks up the parents to find out.
      */
-    private boolean isExcluded(Spatial s, Spatial exclude) {
-        if (s.equals(exclude))
+    private static boolean isExcluded(Spatial s, Spatial exclude) {
+        if (s.equals(exclude)) {
             return true;
-        
+        }
+
         if (s.getParent() != null) {
             return isExcluded(s.getParent(), exclude);
         }
         return false;
     }
-    
+
     /**
      * Pick a part of the axis marker. The result is a Vector3f that represents
      * what part of the axis was selected.
@@ -344,7 +332,7 @@ public abstract class SceneEditTool {
         return null;
     }
 
-    private CollisionResult pick(Camera cam, Vector2f mouseLoc, Node node) {
+    private static CollisionResult pick(Camera cam, Vector2f mouseLoc, Node node) {
         CollisionResults results = new CollisionResults();
         Ray ray = new Ray();
         Vector3f pos = cam.getWorldCoordinates(mouseLoc, 0).clone();
@@ -364,7 +352,7 @@ public abstract class SceneEditTool {
     protected void highlightAxisMarker(Camera camera, Vector2f screenCoord, AxisMarkerPickType axisMarkerPickType) {
         highlightAxisMarker(camera, screenCoord, axisMarkerPickType, false);
     }
-    
+
     /**
      * Show what axis or plane the mouse is currently over and will affect.
      * @param axisMarkerPickType 
@@ -379,20 +367,18 @@ public abstract class SceneEditTool {
 
         if (picked == ARROW_X) {
             axisMarker.getChild("arrowX").setMaterial(orangeMat);
-        } 
-        else if (picked == ARROW_Y) {
+        } else if (picked == ARROW_Y) {
             axisMarker.getChild("arrowY").setMaterial(orangeMat);
-        } 
-        else if (picked == ARROW_Z) {
+        } else if (picked == ARROW_Z) {
             axisMarker.getChild("arrowZ").setMaterial(orangeMat);
-        } 
-        
+        }
+
         if (picked == QUAD_XY || colorAll) {
             axisMarker.getChild("quadXY").setMaterial(orangeMat);
-        } 
+        }
         if (picked == QUAD_XZ || colorAll) {
             axisMarker.getChild("quadXZ").setMaterial(orangeMat);
-        } 
+        }
         if (picked == QUAD_YZ || colorAll) {
             axisMarker.getChild("quadYZ").setMaterial(orangeMat);
         }
@@ -492,7 +478,6 @@ public abstract class SceneEditTool {
         quadYZ.setMaterial(cyanMat);
     }
 
-  
     public Camera getCamera() {
         return camera;
     }

+ 203 - 0
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveManager.java

@@ -0,0 +1,203 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.scenecomposer.tools;
+
+import com.jme3.bullet.control.CharacterControl;
+import com.jme3.bullet.control.RigidBodyControl;
+import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
+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 Nehon
+ */
+@ServiceProvider(service = MoveManager.class)
+public class MoveManager {
+
+    private Vector3f startLoc;
+    private Vector3f startWorldLoc;
+    private Vector3f lastLoc;
+    private Vector3f offset;
+    private Node alternativePickTarget = null;
+    private Node plane;
+    private Spatial spatial;
+    protected static final Quaternion XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
+    protected static final Quaternion YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));
+    protected static final Quaternion XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0));
+    //temp vars 
+    private Quaternion rot = new Quaternion();
+    private Vector3f newPos = new Vector3f();
+
+    public MoveManager() {
+        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 Vector3f getOffset() {
+        return offset;
+    }
+
+    public void reset() {
+        offset = null;
+        startLoc = null;
+        startWorldLoc = null;
+        lastLoc = null;
+        spatial = null;
+        alternativePickTarget = null;
+    }
+
+    public void initiateMove(Spatial selectedSpatial, Quaternion planeRotation, boolean local) {
+        spatial = selectedSpatial;
+        startLoc = selectedSpatial.getLocalTranslation().clone();
+        startWorldLoc = selectedSpatial.getWorldTranslation().clone();
+        if (local) {
+            rot.set(selectedSpatial.getWorldRotation());
+            plane.setLocalRotation(rot.multLocal(planeRotation));
+        } else {
+            rot.set(planeRotation);
+        }
+
+        plane.setLocalRotation(rot);
+        plane.setLocalTranslation(startWorldLoc);
+
+    }
+
+    public void updatePlaneRotation(Quaternion planeRotation) {
+        plane.setLocalRotation(rot);
+    }
+
+    public boolean move(Camera camera, Vector2f screenCoord) {
+        return move(camera, screenCoord, Vector3f.UNIT_XYZ, false);
+    }
+
+    public boolean move(Camera camera, Vector2f screenCoord, Vector3f constraintAxis, boolean gridSnap) {
+        Node toPick = alternativePickTarget == null ? plane : alternativePickTarget;
+
+        Vector3f planeHit = SceneEditTool.pickWorldLocation(camera, screenCoord, toPick, alternativePickTarget == null ? null : spatial);
+        if (planeHit == null) {
+            return false;
+        }
+
+        Spatial parent = spatial.getParent();
+        //we are moving the root node, there is a slight chance that something went wrong.
+        if (parent == null) {
+            return false;
+        }
+
+        //offset in world space
+        if (offset == null) {
+            offset = planeHit.subtract(spatial.getWorldTranslation()); // get the offset when we start so it doesn't jump
+        }
+
+        newPos.set(planeHit).subtractLocal(offset);
+
+        //constraining the translation with the contraintAxis.
+        Vector3f tmp = startWorldLoc.mult(Vector3f.UNIT_XYZ.subtract(constraintAxis));
+        newPos.multLocal(constraintAxis).addLocal(tmp);
+        worldToLocalMove(gridSnap);
+        return true;
+    }
+
+    private void worldToLocalMove(boolean gridSnap) {
+        //snap to grid (grid is assumed 1 WU per cell)
+        if (gridSnap) {
+            newPos.set(Math.round(newPos.x), Math.round(newPos.y), Math.round(newPos.z));
+        }
+
+        //computing the inverse world transform to get the new localtranslation
+        newPos.subtractLocal(spatial.getParent().getWorldTranslation());
+        newPos = spatial.getParent().getWorldRotation().inverse().normalizeLocal().multLocal(newPos);
+        newPos.divideLocal(spatial.getWorldScale());
+        lastLoc = newPos;
+        spatial.setLocalTranslation(newPos);
+
+        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());
+        }
+    }
+
+    public boolean moveAcross(Vector3f constraintAxis, float value, boolean gridSnap) {
+        newPos.set(startWorldLoc).addLocal(constraintAxis.mult(value));
+        Spatial parent = spatial.getParent();
+        //we are moving the root node, there is a slight chance that something went wrong.
+        if (parent == null) {
+            return false;
+        }
+        worldToLocalMove(gridSnap);
+        return true;
+    }
+
+    public MoveUndo makeUndo() {
+        return new MoveUndo(spatial, startLoc, lastLoc);
+    }
+
+    public void setAlternativePickTarget(Node alternativePickTarget) {
+        this.alternativePickTarget = alternativePickTarget;
+    }
+
+    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);
+        }
+    }
+}

+ 14 - 119
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java

@@ -5,23 +5,16 @@
 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.material.Material;
-import com.jme3.math.FastMath;
-import com.jme3.math.Quaternion;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
-import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
-import com.jme3.scene.shape.Quad;
 import org.openide.loaders.DataObject;
+import org.openide.util.Lookup;
 
 /**
  * Move an object.
@@ -35,35 +28,19 @@ import org.openide.loaders.DataObject;
 public class MoveTool extends SceneEditTool {
 
     private Vector3f pickedPlane;
-    private Vector3f startLoc = new Vector3f();
-    private Vector3f lastLoc = new Vector3f();
     private boolean wasDragging = false;
-    private Vector3f offset;
-    private Node plane;
-    Material pinkMat;
-    private final Quaternion XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
-    private final Quaternion YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));
-    private final Quaternion XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0));
-    //temp vars 
-    private Quaternion rot = new Quaternion();
-    private Vector3f newPos = new Vector3f();
+    private MoveManager moveManager;
 
     public MoveTool() {
         axisPickType = AxisMarkerPickType.axisAndPlane;
         setOverrideCameraControl(true);
 
-        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);
-
-
     }
 
     @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);
         displayPlanes();
     }
 
@@ -72,11 +49,11 @@ public class MoveTool extends SceneEditTool {
         if (!pressed) {
             setDefaultAxisMarkerColors();
             pickedPlane = null; // mouse released, reset selection
-            offset = null;
             if (wasDragging) {
-                actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startLoc, lastLoc));
+                actionPerformed(moveManager.makeUndo());
                 wasDragging = false;
             }
+            moveManager.reset();
         }
     }
 
@@ -86,11 +63,12 @@ public class MoveTool extends SceneEditTool {
 
     @Override
     public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
+        
         if (pickedPlane == null) {
             highlightAxisMarker(camera, screenCoord, axisPickType);
         } else {
             pickedPlane = null;
-            offset = null;
+            moveManager.reset();
         }
     }
 
@@ -99,11 +77,11 @@ public class MoveTool extends SceneEditTool {
         if (!pressed) {
             setDefaultAxisMarkerColors();
             pickedPlane = null; // mouse released, reset selection
-            offset = null;
             if (wasDragging) {
-                actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startLoc, lastLoc));
+                actionPerformed(moveManager.makeUndo());
                 wasDragging = false;
             }
+            moveManager.reset();
             return;
         }
 
@@ -116,61 +94,18 @@ public class MoveTool extends SceneEditTool {
             if (pickedPlane == null) {
                 return;
             }
-            startLoc = toolController.getSelectedSpatial().getLocalTranslation().clone();
-            rot = rot.set(toolController.getSelectedSpatial().getWorldRotation());
+
             if (pickedPlane.equals(new Vector3f(1, 1, 0))) {
-                plane.setLocalRotation(rot.multLocal(XY));
+                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.XY, true);
             } else if (pickedPlane.equals(new Vector3f(1, 0, 1))) {
-                plane.setLocalRotation(rot.multLocal(XZ));
+                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.XZ, true);
             } else if (pickedPlane.equals(new Vector3f(0, 1, 1))) {
-                plane.setLocalRotation(rot.multLocal(YZ));
+                moveManager.initiateMove(toolController.getSelectedSpatial(), MoveManager.YZ, true);
             }
-            plane.setLocalTranslation(startLoc);
         }
-
-        Vector3f planeHit = pickWorldLocation(camera, screenCoord, plane, null);
-        if (planeHit == null) {
+        if (!moveManager.move(camera, screenCoord)) {
             return;
         }
-
-        Spatial selected = toolController.getSelectedSpatial();
-        Spatial parent = selected.getParent();
-
-
-        if (parent == null) {
-            //we are moving the root node, move is computed in local translation
-            if (offset == null) {
-                offset = planeHit.subtract(startLoc); // get the offset when we start so it doesn't jump
-            }
-
-            newPos.set(planeHit).subtractLocal(offset);
-            lastLoc.set(newPos);
-            selected.setLocalTranslation(newPos);
-        } else {
-
-            //offset in world space
-            if (offset == null) {
-                offset = planeHit.subtract(selected.getWorldTranslation()); // get the offset when we start so it doesn't jump
-            }
-
-            newPos = planeHit.subtract(offset);
-
-            //computing the inverse world transform to get the new localtranslation
-            newPos.subtractLocal(selected.getParent().getWorldTranslation());
-            newPos = selected.getParent().getWorldRotation().inverse().normalizeLocal().multLocal(newPos);
-            newPos.divideLocal(selected.getWorldScale());
-            selected.setLocalTranslation(newPos);
-            lastLoc.set(newPos);
-        }
-
-        RigidBodyControl control = toolController.getSelectedSpatial().getControl(RigidBodyControl.class);
-        if (control != null) {
-            control.setPhysicsLocation(toolController.getSelectedSpatial().getWorldTranslation());
-        }
-        CharacterControl character = toolController.getSelectedSpatial().getControl(CharacterControl.class);
-        if (character != null) {
-            character.setPhysicsLocation(toolController.getSelectedSpatial().getWorldTranslation());
-        }
         updateToolsTransformation();
 
         wasDragging = true;
@@ -179,44 +114,4 @@ public class MoveTool extends SceneEditTool {
     @Override
     public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
     }
-
-    private class MoveUndo extends AbstractUndoableSceneEdit {
-
-        private Spatial spatial;
-        private Vector3f before, after;
-
-        MoveUndo(Spatial spatial, Vector3f before, Vector3f after) {
-            this.spatial = spatial;
-            this.before = before;
-            this.after = after;
-        }
-
-        @Override
-        public void sceneUndo() {
-            spatial.setLocalTranslation(before);
-            RigidBodyControl control = toolController.getSelectedSpatial().getControl(RigidBodyControl.class);
-            if (control != null) {
-                control.setPhysicsLocation(toolController.getSelectedSpatial().getWorldTranslation());
-            }
-            CharacterControl character = toolController.getSelectedSpatial().getControl(CharacterControl.class);
-            if (character != null) {
-                character.setPhysicsLocation(toolController.getSelectedSpatial().getWorldTranslation());
-            }
-            toolController.selectedSpatialTransformed();
-        }
-
-        @Override
-        public void sceneRedo() {
-            spatial.setLocalTranslation(after);
-            RigidBodyControl control = toolController.getSelectedSpatial().getControl(RigidBodyControl.class);
-            if (control != null) {
-                control.setPhysicsLocation(toolController.getSelectedSpatial().getWorldTranslation());
-            }
-            CharacterControl character = toolController.getSelectedSpatial().getControl(CharacterControl.class);
-            if (character != null) {
-                character.setPhysicsLocation(toolController.getSelectedSpatial().getWorldTranslation());
-            }
-            toolController.selectedSpatialTransformed();
-        }
-    }
 }

+ 84 - 123
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java

@@ -13,16 +13,14 @@ import com.jme3.gde.scenecomposer.SceneEditTool;
 import com.jme3.input.KeyInput;
 import com.jme3.input.event.KeyInputEvent;
 import com.jme3.math.FastMath;
-import com.jme3.math.Matrix3f;
 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 com.jme3.terrain.Terrain;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 import org.openide.loaders.DataObject;
+import org.openide.util.Lookup;
 
 /**
  * This duplicates the Blender manipulate tool.
@@ -50,8 +48,8 @@ public class SelectTool extends SceneEditTool {
     private enum State {translate, rotate, scale};
     private State currentState = null;
     
-    private enum Axis {x, y, z};
-    private Axis currentAxis = null;
+    
+    private Vector3f currentAxis = Vector3f.UNIT_XYZ;
     
     private StringBuilder numberBuilder = new StringBuilder(); // gets appended with numbers
     
@@ -66,7 +64,7 @@ public class SelectTool extends SceneEditTool {
     private boolean shiftDown = false;
     private boolean altDown = false;
     
-    private MoveUndo moving;
+    private MoveManager.MoveUndo moving;
     private ScaleUndo scaling;
     private RotateUndo rotating;
     private Vector2f startMouseCoord; // for scaling and rotation
@@ -111,7 +109,7 @@ public class SelectTool extends SceneEditTool {
                 return; // commands take priority
             
             if (stateChange) {
-                currentAxis = null;
+                currentAxis = Vector3f.UNIT_XYZ;
                 numberBuilder = new StringBuilder();
                 recordInitialState(selected);
             }
@@ -161,7 +159,7 @@ public class SelectTool extends SceneEditTool {
                 selected.setLocalScale(startScale);
         }
         currentState = null;
-        currentAxis = null;
+        currentAxis = Vector3f.UNIT_XYZ;
         numberBuilder = new StringBuilder();
         startRot = null;
         startTrans = null;
@@ -192,26 +190,20 @@ public class SelectTool extends SceneEditTool {
         }
         
         if (currentState == State.translate) {
-            float x = 0, y= 0, z = 0;
-            if (currentAxis == Axis.x)
-                x = value;
-            else if (currentAxis == Axis.y)
-                y = value;
-            else if (currentAxis == Axis.z)
-                z = value;
-            Vector3f before = selected.getLocalTranslation().clone();
-            Vector3f after = selected.getLocalTranslation().addLocal(x, y, z);
-            selected.setLocalTranslation(after);
-            actionPerformed(new MoveUndo(selected, before, after));
+            MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
+            moveManager.moveAcross(currentAxis, value, toolController.isSnapToGrid());
+            moving.setAfter(selected.getLocalTranslation());
+            actionPerformed(moving);
+            moving = null;
         } else if (currentState == State.scale) {
             float x = 1, y= 1, z = 1;
-            if (currentAxis == Axis.x)
+            if (currentAxis == Vector3f.UNIT_X)
                 x = value;
-            else if (currentAxis == Axis.y)
+            else if (currentAxis == Vector3f.UNIT_Y)
                 y = value;
-            else if (currentAxis == Axis.z)
+            else if (currentAxis == Vector3f.UNIT_Z)
                 z = value;
-            else if (currentAxis == null) {
+            else if (currentAxis == Vector3f.UNIT_XYZ) {
                 x = value;
                 y = value;
                 z = value;
@@ -222,11 +214,11 @@ public class SelectTool extends SceneEditTool {
             actionPerformed(new ScaleUndo(selected, before, after));
         } else if (currentState == State.rotate) {
             float x = 0, y= 0, z = 0;
-            if (currentAxis == Axis.x)
+            if (currentAxis == Vector3f.UNIT_X)
                 x = 1;
-            else if (currentAxis == Axis.y)
+            else if (currentAxis == Vector3f.UNIT_Y)
                 y = 1;
-            else if (currentAxis == Axis.z)
+            else if (currentAxis == Vector3f.UNIT_Z)
                 z = 1;
             Vector3f axis = new Vector3f(x,y,z);
             Quaternion initialRot = selected.getLocalRotation().clone();
@@ -238,6 +230,7 @@ public class SelectTool extends SceneEditTool {
             toolController.updateSelection(null);// force a re-draw of the bbox shape
             toolController.updateSelection(selected);
         }
+        clearState(false);
     }
     
     private void checkModificatorKeys(KeyInputEvent kie) {
@@ -271,6 +264,11 @@ public class SelectTool extends SceneEditTool {
     private boolean checkStateKey(KeyInputEvent kie) {
         if (kie.getKeyCode() == KeyInput.KEY_G) {
             currentState = State.translate;
+            MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
+            moveManager.reset();
+            Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI,Vector3f.UNIT_Y));
+            moveManager.initiateMove(selected, rot, false);
+            moving = moveManager.makeUndo();
             return true;
         } else if (kie.getKeyCode() == KeyInput.KEY_R) {
             currentState = State.rotate;
@@ -284,13 +282,40 @@ public class SelectTool extends SceneEditTool {
     
     private boolean checkAxisKey(KeyInputEvent kie) {
         if (kie.getKeyCode() == KeyInput.KEY_X) {
-            currentAxis = Axis.x;
+            currentAxis = Vector3f.UNIT_X;
+            MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
+            Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI,Vector3f.UNIT_Y));
+            Quaternion planRot = null;          
+            if(rot.dot(MoveManager.XY)<rot.dot(MoveManager.XZ)){
+                planRot = MoveManager.XY;
+            }else{
+                planRot = MoveManager.XZ;
+            }           
+            moveManager.updatePlaneRotation(planRot);
             return true;
         } else if (kie.getKeyCode() == KeyInput.KEY_Y) {
-            currentAxis = Axis.y;
+            currentAxis = Vector3f.UNIT_Y;
+            MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
+            Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI,Vector3f.UNIT_Y));
+            Quaternion planRot = null;          
+            if(rot.dot(MoveManager.XY)<rot.dot(MoveManager.YZ)){
+                planRot = MoveManager.XY;
+            }else{
+                planRot = MoveManager.YZ;
+            }           
+            moveManager.updatePlaneRotation(planRot);
             return true;
         } else if (kie.getKeyCode() == KeyInput.KEY_Z) {
-            currentAxis = Axis.z;
+            currentAxis = Vector3f.UNIT_Z;
+             MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
+            Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI,Vector3f.UNIT_Y));
+            Quaternion planRot = null;          
+            if(rot.dot(MoveManager.XZ)<rot.dot(MoveManager.YZ)){
+                planRot = MoveManager.XZ;
+            }else{
+                planRot = MoveManager.YZ;
+            }           
+            moveManager.updatePlaneRotation(planRot);
             return true;
         }
         return false;
@@ -307,34 +332,34 @@ public class SelectTool extends SceneEditTool {
             } else
                 numberBuilder.append('-');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_0) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_0 || kie.getKeyCode() == KeyInput.KEY_NUMPAD0) {
             numberBuilder.append('0');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_1) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_1 || kie.getKeyCode() == KeyInput.KEY_NUMPAD1) {
             numberBuilder.append('1');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_2) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_2 || kie.getKeyCode() == KeyInput.KEY_NUMPAD2) {
             numberBuilder.append('2');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_3) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_3 || kie.getKeyCode() == KeyInput.KEY_NUMPAD3) {
             numberBuilder.append('3');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_4) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_4 || kie.getKeyCode() == KeyInput.KEY_NUMPAD4) {
             numberBuilder.append('4');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_5) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_5 || kie.getKeyCode() == KeyInput.KEY_NUMPAD5) {
             numberBuilder.append('5');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_6) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_6 || kie.getKeyCode() == KeyInput.KEY_NUMPAD6) {
             numberBuilder.append('6');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_7) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_7 || kie.getKeyCode() == KeyInput.KEY_NUMPAD7) {
             numberBuilder.append('7');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_8) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_8 || kie.getKeyCode() == KeyInput.KEY_NUMPAD8) {
             numberBuilder.append('8');
             return true;
-        } else if (kie.getKeyCode() == KeyInput.KEY_9) {
+        } else if (kie.getKeyCode() == KeyInput.KEY_9 || kie.getKeyCode() == KeyInput.KEY_NUMPAD9) {
             numberBuilder.append('9');
             return true;
         } else if (kie.getKeyCode() == KeyInput.KEY_PERIOD) {
@@ -374,7 +399,7 @@ public class SelectTool extends SceneEditTool {
                 if (currentState != null) {
                     // finish manipulating the spatial
                     if (moving != null) {
-                        moving.after = selected.getLocalTranslation().clone();
+                        moving.setAfter(selected.getLocalTranslation());
                         actionPerformed(moving);
                         moving = null;
                         clearState(false);
@@ -483,12 +508,7 @@ public class SelectTool extends SceneEditTool {
     @Override
     public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
         if (currentState != null) {
-            //if (currentAxis != null) {
-                // manipulate from specific axis
-                handleMouseManipulate(screenCoord, currentState, currentAxis, rootNode, currentDataObject, selectedSpatial);
-            //} else {
-                // manipulate from screen coordinates
-            //}
+            handleMouseManipulate(screenCoord, currentState, currentAxis, rootNode, currentDataObject, selectedSpatial);   
         }
     }
 
@@ -507,7 +527,7 @@ public class SelectTool extends SceneEditTool {
      */
     private void handleMouseManipulate( Vector2f screenCoord, 
                                         State state, 
-                                        Axis axis, 
+                                        Vector3f axis, 
                                         JmeNode rootNode, 
                                         DataObject currentDataObject, 
                                         JmeSpatial selectedSpatial) 
@@ -523,50 +543,17 @@ public class SelectTool extends SceneEditTool {
         }
             
     }
-    
-    private void doMouseTranslate(Axis axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
-        // free form translation
-        if (axis == null) {
-            if (toolController.isSnapToScene()) {
-                if (moving == null)
-                    moving = new MoveUndo(selected, selected.getLocalTranslation().clone(), null);
-                Vector3f loc = pickWorldLocation(camera, screenCoord, rootNode, selectedSpatial);
-                if (loc != null) {
-                    //Node sel = selectedSpatial.getLookup().lookup(Node.class);
-                    if (toolController.isSnapToGrid()) {
-                        selected.setLocalTranslation(loc.set(Math.round(loc.x), loc.y, Math.round(loc.z)));
-                    } else {
-                        selected.setLocalTranslation(loc);
-                    }
-                }
-            } else {
-                //TODO drag alone a camera-oriented axis
-            }
-        } else {
-            //snap to specific axis, ignoring snapToScene
-            if (moving == null)
-                moving = new MoveUndo(selected, selected.getLocalTranslation().clone(), null);
-            Vector3f loc = pickWorldLocation(camera, screenCoord, rootNode, selectedSpatial);
-            if (loc != null) {
-                if (toolController.isSnapToGrid())
-                    loc.set(Math.round(loc.x), Math.round(loc.y), Math.round(loc.z)); // round the values
-                
-                //Node sel = selectedSpatial.getLookup().lookup(Node.class);
-                Vector3f prev = selected.getLocalTranslation().clone();
-                Vector3f newLoc = new Vector3f(prev);
-                if (axis == Axis.x)
-                    newLoc.x = loc.x;
-                else if (axis == Axis.y)
-                    newLoc.y = loc.y;
-                if (axis == Axis.z)
-                    newLoc.z = loc.z;
-                
-                selected.setLocalTranslation(newLoc);
-            }
+
+    private void doMouseTranslate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
+        MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class);
+        if(toolController.isSnapToScene()){
+            moveManager.setAlternativePickTarget(rootNode.getLookup().lookup(Node.class));
         }
+        // free form translation
+         moveManager.move(camera, screenCoord, axis,toolController.isSnapToGrid());
     }
     
-    private void doMouseScale(Axis axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
+    private void doMouseScale(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
         // scale based on the original mouse position and original model-to-screen position
         // and compare that to the distance from the new mouse position and the original distance
         if (startMouseCoord == null)
@@ -585,17 +572,17 @@ public class SelectTool extends SceneEditTool {
             origDist = 1;
         float ratio = newDist/origDist;
         Vector3f prev = selected.getLocalScale();
-        if (axis == Axis.x)
+        if (axis == Vector3f.UNIT_X)
             selected.setLocalScale(ratio, prev.y, prev.z);
-        else if (axis == Axis.y)
+        else if (axis == Vector3f.UNIT_Y)
             selected.setLocalScale(prev.x, ratio, prev.z);
-        else if (axis == Axis.z)
+        else if (axis == Vector3f.UNIT_Z)
             selected.setLocalScale(prev.x, prev.y, ratio);
         else
             selected.setLocalScale(ratio, ratio, ratio);
     }
     
-    private void doMouseRotate(Axis axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
+    private void doMouseRotate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
         if (startMouseCoord == null)
             startMouseCoord = screenCoord.clone();
         if (startSelectedCoord == null) {
@@ -617,15 +604,11 @@ public class SelectTool extends SceneEditTool {
         lastRotAngle = temp;
         
         Quaternion rotate = new Quaternion();
-        if (axis == Axis.x) {
-            rotate = rotate.fromAngleAxis(newRotAngle, Vector3f.UNIT_X);
-        } else if (axis == Axis.y) {
-            rotate = rotate.fromAngleAxis(newRotAngle, Vector3f.UNIT_Y);
-        } else if (axis == Axis.z) {
-            rotate = rotate.fromAngleAxis(newRotAngle, Vector3f.UNIT_Z);
+        if (axis != Vector3f.UNIT_XYZ) {
+            rotate = rotate.fromAngleAxis(newRotAngle, axis);
         } else {
-            Vector3f screen = getCamera().getLocation().subtract(selected.getWorldTranslation()).normalize();
-            rotate = rotate.fromAngleAxis(newRotAngle, screen);
+            //Vector3f screen = getCamera().getLocation().subtract(selected.getWorldTranslation()).normalize();
+            rotate = rotate.fromAngleAxis(newRotAngle, getCamera().getDirection());
         }
         selected.setLocalRotation(selected.getLocalRotation().mult(rotate));
         
@@ -661,7 +644,7 @@ public class SelectTool extends SceneEditTool {
         // set to automatically 'grab'/'translate' the new cloned model
         toolController.updateSelection(selected);
         currentState = State.translate;
-        currentAxis = null;
+        currentAxis = Vector3f.UNIT_XYZ;
     }
     
     private void deleteSelected() {
@@ -687,28 +670,6 @@ public class SelectTool extends SceneEditTool {
         });
     }
     
-    private class MoveUndo extends AbstractUndoableSceneEdit {
-
-        private Spatial spatial;
-        private Vector3f before,after;
-        
-        MoveUndo(Spatial spatial, Vector3f before, Vector3f after) {
-            this.spatial = spatial;
-            this.before = before;
-            this.after = after;
-        }
-        
-        @Override
-        public void sceneUndo() {
-            spatial.setLocalTranslation(before);
-        }
-
-        @Override
-        public void sceneRedo() {
-            spatial.setLocalTranslation(after);
-        }
-    }
-    
     private class ScaleUndo extends AbstractUndoableSceneEdit {
 
         private Spatial spatial;