|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|