- 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-0572b91ccdca3.0
parent
91f2353a57
commit
7beda908c1
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue