Merge pull request #273 from Dokthar/scenecomposer/master
SDK SceneComposer : new ShortcutTool
This commit is contained in:
commit
f6a2452ad0
@ -11,6 +11,7 @@ import com.jme3.gde.core.scene.controller.SceneToolController;
|
|||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.scenecomposer.tools.PickManager;
|
import com.jme3.gde.scenecomposer.tools.PickManager;
|
||||||
|
import com.jme3.gde.scenecomposer.tools.shortcuts.ShortcutManager;
|
||||||
import com.jme3.input.event.KeyInputEvent;
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
import com.jme3.light.Light;
|
import com.jme3.light.Light;
|
||||||
import com.jme3.light.PointLight;
|
import com.jme3.light.PointLight;
|
||||||
@ -31,6 +32,7 @@ import com.jme3.scene.control.Control;
|
|||||||
import com.jme3.scene.shape.Quad;
|
import com.jme3.scene.shape.Quad;
|
||||||
import com.jme3.texture.Texture;
|
import com.jme3.texture.Texture;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -184,7 +186,12 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
* @param camera
|
* @param camera
|
||||||
*/
|
*/
|
||||||
public void doEditToolActivatedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
public void doEditToolActivatedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
||||||
if (editTool != null) {
|
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
|
||||||
|
|
||||||
|
if (scm.isActive()) {
|
||||||
|
scm.getActiveShortcut().setCamera(camera);
|
||||||
|
scm.getActiveShortcut().actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
|
} else if (editTool != null) {
|
||||||
editTool.setCamera(camera);
|
editTool.setCamera(camera);
|
||||||
editTool.actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
editTool.actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
}
|
}
|
||||||
@ -198,36 +205,66 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
* @param camera
|
* @param camera
|
||||||
*/
|
*/
|
||||||
public void doEditToolActivatedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
public void doEditToolActivatedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
||||||
if (editTool != null) {
|
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
|
||||||
|
|
||||||
|
if (scm.isActive()) {
|
||||||
|
scm.getActiveShortcut().setCamera(camera);
|
||||||
|
scm.getActiveShortcut().actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
|
} else if (editTool != null) {
|
||||||
editTool.setCamera(camera);
|
editTool.setCamera(camera);
|
||||||
editTool.actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
editTool.actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doEditToolMoved(Vector2f mouseLoc, Camera camera) {
|
public void doEditToolMoved(Vector2f mouseLoc, Camera camera) {
|
||||||
if (editTool != null) {
|
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
|
||||||
|
|
||||||
|
if (scm.isActive()) {
|
||||||
|
scm.getActiveShortcut().setCamera(camera);
|
||||||
|
scm.getActiveShortcut().mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial);
|
||||||
|
} else if (editTool != null) {
|
||||||
editTool.setCamera(camera);
|
editTool.setCamera(camera);
|
||||||
editTool.mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial);
|
editTool.mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doEditToolDraggedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
public void doEditToolDraggedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
||||||
if (editTool != null) {
|
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
|
||||||
|
|
||||||
|
if (scm.isActive()) {
|
||||||
|
scm.getActiveShortcut().setCamera(camera);
|
||||||
|
scm.getActiveShortcut().draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
|
} else if (editTool != null) {
|
||||||
editTool.setCamera(camera);
|
editTool.setCamera(camera);
|
||||||
editTool.draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
editTool.draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doEditToolDraggedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
public void doEditToolDraggedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) {
|
||||||
if (editTool != null) {
|
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
|
||||||
|
|
||||||
|
if (scm.isActive()) {
|
||||||
|
scm.getActiveShortcut().setCamera(null);
|
||||||
|
scm.getActiveShortcut().draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
|
} else if (editTool != null) {
|
||||||
editTool.setCamera(camera);
|
editTool.setCamera(camera);
|
||||||
editTool.draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
editTool.draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void doKeyPressed(KeyInputEvent kie) {
|
public void doKeyPressed(KeyInputEvent kie) {
|
||||||
if (editTool != null) {
|
ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class);
|
||||||
editTool.keyPressed(kie);
|
|
||||||
|
if (scm.isActive()) {
|
||||||
|
scm.doKeyPressed(kie);
|
||||||
|
} else {
|
||||||
|
if (scm.activateShortcut(kie)) {
|
||||||
|
scm.getActiveShortcut().activate(manager, toolsNode, onTopToolsNode, selected, this);
|
||||||
|
} else {
|
||||||
|
if (editTool != null) {
|
||||||
|
editTool.keyPressed(kie);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,204 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.getParent().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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,9 +33,9 @@ public class PickManager {
|
|||||||
private Spatial spatial;
|
private Spatial spatial;
|
||||||
private SceneComposerToolController.TransformationType transformationType;
|
private SceneComposerToolController.TransformationType transformationType;
|
||||||
|
|
||||||
protected static final Quaternion PLANE_XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0));
|
public 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
|
public 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 static final Quaternion PLANE_XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0)); //PITCH090
|
||||||
|
|
||||||
|
|
||||||
public PickManager() {
|
public PickManager() {
|
||||||
@ -75,7 +75,7 @@ public class PickManager {
|
|||||||
origineRotation = new Quaternion(Quaternion.IDENTITY);
|
origineRotation = new Quaternion(Quaternion.IDENTITY);
|
||||||
} else if (transformationType == SceneComposerToolController.TransformationType.camera) {
|
} else if (transformationType == SceneComposerToolController.TransformationType.camera) {
|
||||||
rot.set(camera.getRotation());
|
rot.set(camera.getRotation());
|
||||||
origineRotation = camera.getRotation().clone();
|
origineRotation = camera.getRotation();
|
||||||
}
|
}
|
||||||
plane.setLocalRotation(rot);
|
plane.setLocalRotation(rot);
|
||||||
}
|
}
|
||||||
@ -87,10 +87,6 @@ public class PickManager {
|
|||||||
* @return true if the the new picked location is set, else return false.
|
* @return true if the the new picked location is set, else return false.
|
||||||
*/
|
*/
|
||||||
public boolean updatePick(Camera camera, Vector2f screenCoord) {
|
public boolean updatePick(Camera camera, Vector2f screenCoord) {
|
||||||
if(transformationType == SceneComposerToolController.TransformationType.camera){
|
|
||||||
origineRotation = camera.getRotation();
|
|
||||||
plane.setLocalRotation(camera.getRotation());
|
|
||||||
}
|
|
||||||
finalPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null);
|
finalPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null);
|
||||||
return finalPickLoc != null;
|
return finalPickLoc != null;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import org.openide.util.Lookup;
|
|||||||
public class RotateTool extends SceneEditTool {
|
public class RotateTool extends SceneEditTool {
|
||||||
|
|
||||||
private Vector3f pickedMarker;
|
private Vector3f pickedMarker;
|
||||||
private Vector2f lastScreenCoord;
|
|
||||||
private Quaternion startRotate;
|
private Quaternion startRotate;
|
||||||
private Quaternion lastRotate;
|
private Quaternion lastRotate;
|
||||||
private boolean wasDragging = false;
|
private boolean wasDragging = false;
|
||||||
@ -48,9 +47,8 @@ public class RotateTool extends SceneEditTool {
|
|||||||
if (!pressed) {
|
if (!pressed) {
|
||||||
setDefaultAxisMarkerColors();
|
setDefaultAxisMarkerColors();
|
||||||
pickedMarker = null; // mouse released, reset selection
|
pickedMarker = null; // mouse released, reset selection
|
||||||
lastScreenCoord = null;
|
|
||||||
if (wasDragging) {
|
if (wasDragging) {
|
||||||
actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
|
actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
|
||||||
wasDragging = false;
|
wasDragging = false;
|
||||||
}
|
}
|
||||||
pickManager.reset();
|
pickManager.reset();
|
||||||
@ -100,10 +98,9 @@ public class RotateTool extends SceneEditTool {
|
|||||||
if (!pressed) {
|
if (!pressed) {
|
||||||
setDefaultAxisMarkerColors();
|
setDefaultAxisMarkerColors();
|
||||||
pickedMarker = null; // mouse released, reset selection
|
pickedMarker = null; // mouse released, reset selection
|
||||||
lastScreenCoord = null;
|
|
||||||
|
|
||||||
if (wasDragging) {
|
if (wasDragging) {
|
||||||
actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
|
actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotate, lastRotate));
|
||||||
wasDragging = false;
|
wasDragging = false;
|
||||||
}
|
}
|
||||||
pickManager.reset();
|
pickManager.reset();
|
||||||
@ -138,12 +135,12 @@ public class RotateTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScaleUndo extends AbstractUndoableSceneEdit {
|
private class RotateUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
private Spatial spatial;
|
private Spatial spatial;
|
||||||
private Quaternion before, after;
|
private Quaternion before, after;
|
||||||
|
|
||||||
ScaleUndo(Spatial spatial, Quaternion before, Quaternion after) {
|
RotateUndo(Spatial spatial, Quaternion before, Quaternion after) {
|
||||||
this.spatial = spatial;
|
this.spatial = spatial;
|
||||||
this.before = before;
|
this.before = before;
|
||||||
this.after = after;
|
this.after = after;
|
||||||
|
@ -8,425 +8,51 @@ import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
|
|||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
|
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
|
||||||
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
|
||||||
import com.jme3.gde.scenecomposer.SceneEditTool;
|
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.Quaternion;
|
|
||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
import com.jme3.terrain.Terrain;
|
import com.jme3.terrain.Terrain;
|
||||||
import org.openide.loaders.DataObject;
|
import org.openide.loaders.DataObject;
|
||||||
import org.openide.util.Lookup;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This duplicates the Blender manipulate tool.
|
* This duplicates the Blender manipulate tool. It supports quick access to
|
||||||
* It supports quick access to Grab, Rotate, and Scale operations
|
* Grab, Rotate, and Scale operations by typing one of the following keys: 'g',
|
||||||
* by typing one of the following keys: 'g', 'r', or 's'
|
* 'r', or 's' Those keys can be followed by an axis key to specify what axis to
|
||||||
* Those keys can be followed by an axis key to specify what axis
|
* perform the transformation: x, y, z Then, after the operation and axis are
|
||||||
* to perform the transformation: x, y, z
|
* selected, you can type in a number and then hit 'enter' to complete the
|
||||||
* Then, after the operation and axis are selected, you can type in a
|
* transformation.
|
||||||
* number and then hit 'enter' to complete the transformation.
|
*
|
||||||
*
|
* Ctrl+Shift+D will duplicate an object X will delete an object
|
||||||
* Ctrl+Shift+D will duplicate an object
|
*
|
||||||
* X will delete an object
|
* ITEMS TO FINISH: 1) fixed scale and rotation values by holding Ctrl and
|
||||||
*
|
* dragging mouse BUGS: 1) window always needs focus from primary click when it
|
||||||
* ITEMS TO FINISH:
|
* should focus from secondary and middle mouse
|
||||||
* 1) fixed scale and rotation values by holding Ctrl and dragging mouse
|
*
|
||||||
* BUGS:
|
|
||||||
* 1) window always needs focus from primary click when it should focus from secondary and middle mouse
|
|
||||||
*
|
|
||||||
* @author Brent Owens
|
* @author Brent Owens
|
||||||
*/
|
*/
|
||||||
public class SelectTool extends SceneEditTool {
|
public class SelectTool extends SceneEditTool {
|
||||||
|
|
||||||
private enum State {
|
|
||||||
|
|
||||||
translate, rotate, scale
|
|
||||||
};
|
|
||||||
private State currentState = null;
|
|
||||||
private Vector3f currentAxis = Vector3f.UNIT_XYZ;
|
|
||||||
private StringBuilder numberBuilder = new StringBuilder(); // gets appended with numbers
|
|
||||||
private Quaternion startRot;
|
|
||||||
private Vector3f startTrans;
|
|
||||||
private Vector3f startScale;
|
|
||||||
private boolean wasDraggingL = false;
|
|
||||||
private boolean wasDraggingR = false;
|
private boolean wasDraggingR = false;
|
||||||
private boolean wasDownR = false;
|
private boolean wasDownR = false;
|
||||||
private boolean ctrlDown = false;
|
|
||||||
private boolean shiftDown = false;
|
|
||||||
private boolean altDown = false;
|
|
||||||
private MoveManager.MoveUndo moving;
|
|
||||||
private ScaleUndo scaling;
|
|
||||||
private RotateUndo rotating;
|
|
||||||
private Vector2f startMouseCoord; // for scaling and rotation
|
|
||||||
private Vector2f startSelectedCoord; // for scaling and rotation
|
|
||||||
private float lastRotAngle; // used for rotation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is stateful:
|
* This is stateful: First it checks for a command (rotate, translate,
|
||||||
* First it checks for a command (rotate, translate, delete, etc..)
|
* delete, etc..) Then it checks for an axis (x,y,z) Then it checks for a
|
||||||
* Then it checks for an axis (x,y,z)
|
* number (user typed a number Then, finally, it checks if Enter was hit.
|
||||||
* Then it checks for a number (user typed a number
|
*
|
||||||
* Then, finally, it checks if Enter was hit.
|
|
||||||
*
|
|
||||||
* If either of the commands was actioned, the preceeding states/axis/amount
|
* If either of the commands was actioned, the preceeding states/axis/amount
|
||||||
* will be reset. For example if the user types: G Y 2 R
|
* will be reset. For example if the user types: G Y 2 R Then it will: 1)
|
||||||
* Then it will:
|
* Set state as 'Translate' for the G (grab) 2) Set the axis as 'Y'; it will
|
||||||
* 1) Set state as 'Translate' for the G (grab)
|
* translate along the Y axis 3) Distance will be 2, when the 2 key is hit
|
||||||
* 2) Set the axis as 'Y'; it will translate along the Y axis
|
* 4) Distance, Axis, and state are then reset because a new state was set:
|
||||||
* 3) Distance will be 2, when the 2 key is hit
|
* Rotate it won't actually translate because 'Enter' was not hit and 'R'
|
||||||
* 4) Distance, Axis, and state are then reset because a new state was set: Rotate
|
* reset the state.
|
||||||
* it won't actually translate because 'Enter' was not hit and 'R' reset the state.
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public void keyPressed(KeyInputEvent kie) {
|
|
||||||
|
|
||||||
checkModificatorKeys(kie); // alt,shift,ctrl
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
|
|
||||||
if (selected == null) {
|
|
||||||
return; // only do anything if a spatial is selected
|
|
||||||
}
|
|
||||||
// key released
|
|
||||||
if (kie.isPressed()) {
|
|
||||||
boolean commandUsed = checkCommandKey(kie);
|
|
||||||
boolean stateChange = checkStateKey(kie);
|
|
||||||
boolean axisChange = checkAxisKey(kie);
|
|
||||||
boolean numberChange = checkNumberKey(kie);
|
|
||||||
boolean enterHit = checkEnterHit(kie);
|
|
||||||
boolean escHit = checkEscHit(kie);
|
|
||||||
|
|
||||||
if (commandUsed) {
|
|
||||||
return; // commands take priority
|
|
||||||
}
|
|
||||||
if (stateChange) {
|
|
||||||
currentAxis = Vector3f.UNIT_XYZ;
|
|
||||||
numberBuilder = new StringBuilder();
|
|
||||||
recordInitialState(selected);
|
|
||||||
} else if (axisChange) {
|
|
||||||
} else if (numberChange) {
|
|
||||||
} else if (enterHit) {
|
|
||||||
if (currentState != null && numberBuilder.length() > 0) {
|
|
||||||
applyKeyedChangeState(selected);
|
|
||||||
clearState(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------
|
|
||||||
// reset conditions below:
|
|
||||||
|
|
||||||
if (escHit) {
|
|
||||||
if (moving != null) {
|
|
||||||
moving.sceneUndo();
|
|
||||||
}
|
|
||||||
|
|
||||||
moving = null;
|
|
||||||
clearState();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stateChange && !axisChange && !numberChange && !enterHit && !escHit) {
|
|
||||||
// nothing valid was hit, reset the state
|
|
||||||
//clearState(); // this will be
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abort any manipulations
|
|
||||||
*/
|
|
||||||
private void clearState() {
|
|
||||||
clearState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearState(boolean resetSelected) {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
if (resetSelected && selected != null) {
|
|
||||||
// reset the transforms
|
|
||||||
if (startRot != null) {
|
|
||||||
selected.setLocalRotation(startRot);
|
|
||||||
}
|
|
||||||
if (startTrans != null) {
|
|
||||||
selected.setLocalTranslation(startTrans);
|
|
||||||
}
|
|
||||||
if (startScale != null) {
|
|
||||||
selected.setLocalScale(startScale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentState = null;
|
|
||||||
currentAxis = Vector3f.UNIT_XYZ;
|
|
||||||
numberBuilder = new StringBuilder();
|
|
||||||
startRot = null;
|
|
||||||
startTrans = null;
|
|
||||||
startScale = null;
|
|
||||||
startMouseCoord = null;
|
|
||||||
startSelectedCoord = null;
|
|
||||||
lastRotAngle = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recordInitialState(Spatial selected) {
|
|
||||||
startRot = selected.getLocalRotation().clone();
|
|
||||||
startTrans = selected.getLocalTranslation().clone();
|
|
||||||
startScale = selected.getLocalScale().clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the changes entered by a number, not by mouse.
|
|
||||||
* Translate: adds the value to the current local translation
|
|
||||||
* Rotate: rotates by X degrees
|
|
||||||
* Scale: scale the current scale by X amount
|
|
||||||
*/
|
|
||||||
private void applyKeyedChangeState(Spatial selected) {
|
|
||||||
Float value = null;
|
|
||||||
try {
|
|
||||||
value = new Float(numberBuilder.toString());
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentState == State.translate) {
|
|
||||||
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 == Vector3f.UNIT_X) {
|
|
||||||
x = value;
|
|
||||||
} else if (currentAxis == Vector3f.UNIT_Y) {
|
|
||||||
y = value;
|
|
||||||
} else if (currentAxis == Vector3f.UNIT_Z) {
|
|
||||||
z = value;
|
|
||||||
} else if (currentAxis == Vector3f.UNIT_XYZ) {
|
|
||||||
x = value;
|
|
||||||
y = value;
|
|
||||||
z = value;
|
|
||||||
}
|
|
||||||
Vector3f before = selected.getLocalScale().clone();
|
|
||||||
Vector3f after = selected.getLocalScale().multLocal(x, y, z);
|
|
||||||
selected.setLocalScale(after);
|
|
||||||
actionPerformed(new ScaleUndo(selected, before, after));
|
|
||||||
} else if (currentState == State.rotate) {
|
|
||||||
float x = 0, y = 0, z = 0;
|
|
||||||
if (currentAxis == Vector3f.UNIT_X) {
|
|
||||||
x = 1;
|
|
||||||
} else if (currentAxis == Vector3f.UNIT_Y) {
|
|
||||||
y = 1;
|
|
||||||
} else if (currentAxis == Vector3f.UNIT_Z) {
|
|
||||||
z = 1;
|
|
||||||
}
|
|
||||||
Vector3f axis = new Vector3f(x, y, z);
|
|
||||||
Quaternion initialRot = selected.getLocalRotation().clone();
|
|
||||||
Quaternion rot = new Quaternion();
|
|
||||||
rot = rot.fromAngleAxis(value * FastMath.DEG_TO_RAD, axis);
|
|
||||||
selected.setLocalRotation(selected.getLocalRotation().mult(rot));
|
|
||||||
RotateUndo undo = new RotateUndo(selected, initialRot, rot);
|
|
||||||
actionPerformed(undo);
|
|
||||||
toolController.updateSelection(null);// force a re-draw of the bbox shape
|
|
||||||
toolController.updateSelection(selected);
|
|
||||||
|
|
||||||
}
|
|
||||||
clearState(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkModificatorKeys(KeyInputEvent kie) {
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL) {
|
|
||||||
ctrlDown = kie.isPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT) {
|
|
||||||
shiftDown = kie.isPressed();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU) {
|
|
||||||
altDown = kie.isPressed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkCommandKey(KeyInputEvent kie) {
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_D) {
|
|
||||||
if (shiftDown) {
|
|
||||||
duplicateSelected();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// X will only delete if the user isn't already transforming
|
|
||||||
if (currentState == null && kie.getKeyCode() == KeyInput.KEY_X) {
|
|
||||||
if (!ctrlDown && !shiftDown) {
|
|
||||||
deleteSelected();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkStateKey(KeyInputEvent kie) {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_G && !ctrlDown) {
|
|
||||||
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 && !ctrlDown) {
|
|
||||||
currentState = State.rotate;
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_S && !ctrlDown) {
|
|
||||||
currentState = State.scale;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkAxisKey(KeyInputEvent kie) {
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_X) {
|
|
||||||
currentAxis = Vector3f.UNIT_X;
|
|
||||||
checkMovePlane(MoveManager.XY, MoveManager.XZ);
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_Y) {
|
|
||||||
currentAxis = Vector3f.UNIT_Y;
|
|
||||||
checkMovePlane(MoveManager.XY, MoveManager.YZ);
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_Z) {
|
|
||||||
currentAxis = Vector3f.UNIT_Z;
|
|
||||||
checkMovePlane(MoveManager.XZ, MoveManager.YZ);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkMovePlane(Quaternion rot1, Quaternion rot2) {
|
|
||||||
if (currentState == State.translate) {
|
|
||||||
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(rot1) < rot.dot(rot2)) {
|
|
||||||
planRot = rot1;
|
|
||||||
} else {
|
|
||||||
planRot = rot2;
|
|
||||||
}
|
|
||||||
moveManager.updatePlaneRotation(planRot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkNumberKey(KeyInputEvent kie) {
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_MINUS) {
|
|
||||||
if (numberBuilder.length() > 0) {
|
|
||||||
if (numberBuilder.charAt(0) == '-') {
|
|
||||||
numberBuilder.replace(0, 1, "");
|
|
||||||
} else {
|
|
||||||
numberBuilder.insert(0, '-');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
numberBuilder.append('-');
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_0 || kie.getKeyCode() == KeyInput.KEY_NUMPAD0) {
|
|
||||||
numberBuilder.append('0');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_1 || kie.getKeyCode() == KeyInput.KEY_NUMPAD1) {
|
|
||||||
numberBuilder.append('1');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_2 || kie.getKeyCode() == KeyInput.KEY_NUMPAD2) {
|
|
||||||
numberBuilder.append('2');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_3 || kie.getKeyCode() == KeyInput.KEY_NUMPAD3) {
|
|
||||||
numberBuilder.append('3');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_4 || kie.getKeyCode() == KeyInput.KEY_NUMPAD4) {
|
|
||||||
numberBuilder.append('4');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_5 || kie.getKeyCode() == KeyInput.KEY_NUMPAD5) {
|
|
||||||
numberBuilder.append('5');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_6 || kie.getKeyCode() == KeyInput.KEY_NUMPAD6) {
|
|
||||||
numberBuilder.append('6');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_7 || kie.getKeyCode() == KeyInput.KEY_NUMPAD7) {
|
|
||||||
numberBuilder.append('7');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_8 || kie.getKeyCode() == KeyInput.KEY_NUMPAD8) {
|
|
||||||
numberBuilder.append('8');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_9 || kie.getKeyCode() == KeyInput.KEY_NUMPAD9) {
|
|
||||||
numberBuilder.append('9');
|
|
||||||
return true;
|
|
||||||
} else if (kie.getKeyCode() == KeyInput.KEY_PERIOD) {
|
|
||||||
if (numberBuilder.indexOf(".") == -1) { // if it doesn't exist yet
|
|
||||||
if (numberBuilder.length() == 0
|
|
||||||
|| (numberBuilder.length() == 1 && numberBuilder.charAt(0) == '-')) {
|
|
||||||
numberBuilder.append("0.");
|
|
||||||
} else {
|
|
||||||
numberBuilder.append(".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkEnterHit(KeyInputEvent kie) {
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_RETURN) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkEscHit(KeyInputEvent kie) {
|
|
||||||
if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
|
||||||
if (!pressed) {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
// left mouse released
|
|
||||||
if (!wasDraggingL) {
|
|
||||||
// left mouse pressed
|
|
||||||
if (currentState != null) {
|
|
||||||
// finish manipulating the spatial
|
|
||||||
if (moving != null) {
|
|
||||||
moving.setAfter(selected.getLocalTranslation());
|
|
||||||
actionPerformed(moving);
|
|
||||||
moving = null;
|
|
||||||
clearState(false);
|
|
||||||
} else if (scaling != null) {
|
|
||||||
scaling.after = selected.getLocalScale().clone();
|
|
||||||
actionPerformed(scaling);
|
|
||||||
scaling = null;
|
|
||||||
clearState(false);
|
|
||||||
toolController.rebuildSelectionBox();
|
|
||||||
} else if (rotating != null) {
|
|
||||||
rotating.after = selected.getLocalRotation().clone();
|
|
||||||
actionPerformed(rotating);
|
|
||||||
rotating = null;
|
|
||||||
clearState(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// mouse released and wasn't dragging, place cursor
|
|
||||||
final Vector3f result = pickWorldLocation(getCamera(), screenCoord, rootNode);
|
|
||||||
if (result != null) {
|
|
||||||
if (toolController.isSnapToGrid()) {
|
|
||||||
result.set(Math.round(result.x), result.y, Math.round(result.z));
|
|
||||||
}
|
|
||||||
toolController.setCursorLocation(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wasDraggingL = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -435,19 +61,7 @@ public class SelectTool extends SceneEditTool {
|
|||||||
Spatial selected = toolController.getSelectedSpatial();
|
Spatial selected = toolController.getSelectedSpatial();
|
||||||
// mouse down
|
// mouse down
|
||||||
|
|
||||||
if (moving != null) {
|
if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already
|
||||||
moving.sceneUndo();
|
|
||||||
moving = null;
|
|
||||||
clearState();
|
|
||||||
} else if (scaling != null) {
|
|
||||||
scaling.sceneUndo();
|
|
||||||
scaling = null;
|
|
||||||
clearState();
|
|
||||||
} else if (rotating != null) {
|
|
||||||
rotating.sceneUndo();
|
|
||||||
rotating = null;
|
|
||||||
clearState();
|
|
||||||
} else if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already
|
|
||||||
// pick on the spot
|
// pick on the spot
|
||||||
Spatial s = pickWorldSpatial(camera, screenCoord, rootNode);
|
Spatial s = pickWorldSpatial(camera, screenCoord, rootNode);
|
||||||
if (!toolController.selectTerrain() && isTerrain(s)) {
|
if (!toolController.selectTerrain() && isTerrain(s)) {
|
||||||
@ -498,8 +112,8 @@ public class SelectTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Climb up the spatial until we find the first node parent.
|
* Climb up the spatial until we find the first node parent. TODO: use
|
||||||
* TODO: use userData to determine the actual model's parent.
|
* userData to determine the actual model's parent.
|
||||||
*/
|
*/
|
||||||
private Spatial findModelNodeParent(Spatial child) {
|
private Spatial findModelNodeParent(Spatial child) {
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
@ -519,14 +133,10 @@ public class SelectTool extends SceneEditTool {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
|
||||||
if (currentState != null) {
|
|
||||||
handleMouseManipulate(screenCoord, currentState, currentAxis, rootNode, currentDataObject, selectedSpatial);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
wasDraggingL = pressed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -535,252 +145,8 @@ public class SelectTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manipulate the spatial
|
* Check if the selected item is a Terrain It will climb up the parent tree
|
||||||
*/
|
* to see if a parent is terrain too. Recursive call.
|
||||||
private void handleMouseManipulate(Vector2f screenCoord,
|
|
||||||
State state,
|
|
||||||
Vector3f axis,
|
|
||||||
JmeNode rootNode,
|
|
||||||
DataObject currentDataObject,
|
|
||||||
JmeSpatial selectedSpatial) {
|
|
||||||
if (state == State.translate) {
|
|
||||||
doMouseTranslate(axis, screenCoord, rootNode, selectedSpatial);
|
|
||||||
} else if (state == State.scale) {
|
|
||||||
doMouseScale(axis, screenCoord, rootNode, selectedSpatial);
|
|
||||||
} else if (state == State.rotate) {
|
|
||||||
doMouseRotate(axis, screenCoord, rootNode, selectedSpatial);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
// 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) {
|
|
||||||
startMouseCoord = screenCoord.clone();
|
|
||||||
}
|
|
||||||
if (startSelectedCoord == null) {
|
|
||||||
Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation());
|
|
||||||
startSelectedCoord = new Vector2f(screen.x, screen.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scaling == null) {
|
|
||||||
scaling = new ScaleUndo(selected, selected.getLocalScale().clone(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
float origDist = startMouseCoord.distanceSquared(startSelectedCoord);
|
|
||||||
float newDist = screenCoord.distanceSquared(startSelectedCoord);
|
|
||||||
if (origDist == 0) {
|
|
||||||
origDist = 1;
|
|
||||||
}
|
|
||||||
float ratio = newDist / origDist;
|
|
||||||
Vector3f prev = selected.getLocalScale();
|
|
||||||
if (axis == Vector3f.UNIT_X) {
|
|
||||||
selected.setLocalScale(ratio, prev.y, prev.z);
|
|
||||||
} else if (axis == Vector3f.UNIT_Y) {
|
|
||||||
selected.setLocalScale(prev.x, ratio, prev.z);
|
|
||||||
} else if (axis == Vector3f.UNIT_Z) {
|
|
||||||
selected.setLocalScale(prev.x, prev.y, ratio);
|
|
||||||
} else {
|
|
||||||
selected.setLocalScale(ratio, ratio, ratio);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doMouseRotate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
if (startMouseCoord == null) {
|
|
||||||
startMouseCoord = screenCoord.clone();
|
|
||||||
}
|
|
||||||
if (startSelectedCoord == null) {
|
|
||||||
Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation());
|
|
||||||
startSelectedCoord = new Vector2f(screen.x, screen.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rotating == null) {
|
|
||||||
rotating = new RotateUndo(selected, selected.getLocalRotation().clone(), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2f origRot = startMouseCoord.subtract(startSelectedCoord);
|
|
||||||
Vector2f newRot = screenCoord.subtract(startSelectedCoord);
|
|
||||||
float newRotAngle = origRot.angleBetween(newRot);
|
|
||||||
float temp = newRotAngle;
|
|
||||||
|
|
||||||
if (lastRotAngle != 0) {
|
|
||||||
newRotAngle -= lastRotAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastRotAngle = temp;
|
|
||||||
|
|
||||||
Quaternion rotate = new Quaternion();
|
|
||||||
if (axis != Vector3f.UNIT_XYZ) {
|
|
||||||
rotate = rotate.fromAngleAxis(newRotAngle, selected.getWorldRotation().inverse().mult(axis));
|
|
||||||
} else {
|
|
||||||
rotate = rotate.fromAngleAxis(newRotAngle, selected.getWorldRotation().inverse().mult(getCamera().getDirection().mult(-1).normalizeLocal()));
|
|
||||||
}
|
|
||||||
selected.setLocalRotation(selected.getLocalRotation().mult(rotate));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void duplicateSelected() {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
if (selected == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Spatial clone = selected.clone();
|
|
||||||
clone.move(1, 0, 1);
|
|
||||||
|
|
||||||
selected.getParent().attachChild(clone);
|
|
||||||
actionPerformed(new DuplicateUndo(clone, selected.getParent()));
|
|
||||||
selected = clone;
|
|
||||||
final Spatial cloned = clone;
|
|
||||||
final JmeNode rootNode = toolController.getRootNode();
|
|
||||||
refreshSelected(rootNode, selected.getParent());
|
|
||||||
|
|
||||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (cloned != null) {
|
|
||||||
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(cloned)});
|
|
||||||
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(cloned));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// set to automatically 'grab'/'translate' the new cloned model
|
|
||||||
toolController.updateSelection(selected);
|
|
||||||
currentState = State.translate;
|
|
||||||
currentAxis = Vector3f.UNIT_XYZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteSelected() {
|
|
||||||
Spatial selected = toolController.getSelectedSpatial();
|
|
||||||
if (selected == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Node parent = selected.getParent();
|
|
||||||
selected.removeFromParent();
|
|
||||||
actionPerformed(new DeleteUndo(selected, parent));
|
|
||||||
|
|
||||||
selected = null;
|
|
||||||
toolController.updateSelection(selected);
|
|
||||||
|
|
||||||
final JmeNode rootNode = toolController.getRootNode();
|
|
||||||
refreshSelected(rootNode, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshSelected(final JmeNode jmeRootNode, final Node parent) {
|
|
||||||
java.awt.EventQueue.invokeLater(new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
jmeRootNode.getChild(parent).refresh(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ScaleUndo extends AbstractUndoableSceneEdit {
|
|
||||||
|
|
||||||
private Spatial spatial;
|
|
||||||
private Vector3f before, after;
|
|
||||||
|
|
||||||
ScaleUndo(Spatial spatial, Vector3f before, Vector3f after) {
|
|
||||||
this.spatial = spatial;
|
|
||||||
this.before = before;
|
|
||||||
this.after = after;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneUndo() {
|
|
||||||
spatial.setLocalScale(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneRedo() {
|
|
||||||
spatial.setLocalScale(after);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RotateUndo extends AbstractUndoableSceneEdit {
|
|
||||||
|
|
||||||
private Spatial spatial;
|
|
||||||
private Quaternion before, after;
|
|
||||||
|
|
||||||
RotateUndo(Spatial spatial, Quaternion before, Quaternion after) {
|
|
||||||
this.spatial = spatial;
|
|
||||||
this.before = before;
|
|
||||||
this.after = after;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneUndo() {
|
|
||||||
spatial.setLocalRotation(before);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneRedo() {
|
|
||||||
spatial.setLocalRotation(after);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DeleteUndo extends AbstractUndoableSceneEdit {
|
|
||||||
|
|
||||||
private Spatial spatial;
|
|
||||||
private Node parent;
|
|
||||||
|
|
||||||
DeleteUndo(Spatial spatial, Node parent) {
|
|
||||||
this.spatial = spatial;
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneUndo() {
|
|
||||||
parent.attachChild(spatial);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneRedo() {
|
|
||||||
spatial.removeFromParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class DuplicateUndo extends AbstractUndoableSceneEdit {
|
|
||||||
|
|
||||||
private Spatial spatial;
|
|
||||||
private Node parent;
|
|
||||||
|
|
||||||
DuplicateUndo(Spatial spatial, Node parent) {
|
|
||||||
this.spatial = spatial;
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneUndo() {
|
|
||||||
spatial.removeFromParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sceneRedo() {
|
|
||||||
parent.attachChild(spatial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the selected item is a Terrain
|
|
||||||
* It will climb up the parent tree to see if
|
|
||||||
* a parent is terrain too.
|
|
||||||
* Recursive call.
|
|
||||||
*/
|
*/
|
||||||
protected boolean isTerrain(Spatial s) {
|
protected boolean isTerrain(Spatial s) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
|
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
|
||||||
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
|
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import org.openide.loaders.DataObject;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
public class DeleteShortcut extends ShortcutTool {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActivableBy(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_X && kie.isPressed()) {
|
||||||
|
if (Lookup.getDefault().lookup(ShortcutManager.class).isShiftDown()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
|
||||||
|
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
hideMarker();
|
||||||
|
if (selectedSpatial != null) {
|
||||||
|
delete();
|
||||||
|
}
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delete() {
|
||||||
|
Spatial selected = toolController.getSelectedSpatial();
|
||||||
|
|
||||||
|
Node parent = selected.getParent();
|
||||||
|
selected.removeFromParent();
|
||||||
|
actionPerformed(new DeleteUndo(selected, parent));
|
||||||
|
|
||||||
|
selected = null;
|
||||||
|
toolController.updateSelection(selected);
|
||||||
|
|
||||||
|
final JmeNode rootNode = toolController.getRootNode();
|
||||||
|
refreshSelected(rootNode, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshSelected(final JmeNode jmeRootNode, final Node parent) {
|
||||||
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
jmeRootNode.getChild(parent).refresh(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyInputEvent kie) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeleteUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Node parent;
|
||||||
|
|
||||||
|
DeleteUndo(Spatial spatial, Node parent) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneUndo() {
|
||||||
|
parent.attachChild(spatial);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneRedo() {
|
||||||
|
spatial.removeFromParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
|
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
|
||||||
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
|
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
import com.jme3.math.Vector2f;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
|
import com.jme3.scene.Spatial;
|
||||||
|
import org.openide.loaders.DataObject;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
public class DuplicateShortcut extends ShortcutTool {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActivableBy(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_D && kie.isPressed()) {
|
||||||
|
if (Lookup.getDefault().lookup(ShortcutManager.class).isShiftDown()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
|
||||||
|
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
hideMarker();
|
||||||
|
if (selectedSpatial != null) {
|
||||||
|
duplicate();
|
||||||
|
terminate();
|
||||||
|
|
||||||
|
//then enable move shortcut
|
||||||
|
toolController.doKeyPressed(new KeyInputEvent(KeyInput.KEY_G, 'g', true, false));
|
||||||
|
} else {
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void duplicate() {
|
||||||
|
Spatial selected = toolController.getSelectedSpatial();
|
||||||
|
|
||||||
|
Spatial clone = selected.clone();
|
||||||
|
clone.move(1, 0, 1);
|
||||||
|
|
||||||
|
selected.getParent().attachChild(clone);
|
||||||
|
actionPerformed(new DuplicateUndo(clone, selected.getParent()));
|
||||||
|
selected = clone;
|
||||||
|
final Spatial cloned = clone;
|
||||||
|
final JmeNode rootNode = toolController.getRootNode();
|
||||||
|
refreshSelected(rootNode, selected.getParent());
|
||||||
|
|
||||||
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (cloned != null) {
|
||||||
|
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(cloned)});
|
||||||
|
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(cloned));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
toolController.updateSelection(selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshSelected(final JmeNode jmeRootNode, final Node parent) {
|
||||||
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
jmeRootNode.getChild(parent).refresh(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyInputEvent kie) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DuplicateUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Node parent;
|
||||||
|
|
||||||
|
DuplicateUndo(Spatial spatial, Node parent) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneUndo() {
|
||||||
|
spatial.removeFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneRedo() {
|
||||||
|
parent.attachChild(spatial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
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.tools.PickManager;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
public class MoveShortcut extends ShortcutTool {
|
||||||
|
|
||||||
|
private Vector3f currentAxis;
|
||||||
|
private StringBuilder numberBuilder;
|
||||||
|
private Spatial spatial;
|
||||||
|
private PickManager pickManager;
|
||||||
|
private boolean pickEnabled;
|
||||||
|
private Vector3f startPosition;
|
||||||
|
private Vector3f finalPosition;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public boolean isActivableBy(KeyInputEvent kie) {
|
||||||
|
return kie.getKeyCode() == KeyInput.KEY_G;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
spatial.setLocalTranslation(startPosition);
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply() {
|
||||||
|
actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startPosition, finalPosition));
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Spatial selectedSpatial) {
|
||||||
|
spatial = selectedSpatial;
|
||||||
|
startPosition = spatial.getLocalTranslation().clone();
|
||||||
|
currentAxis = Vector3f.UNIT_XYZ;
|
||||||
|
pickManager = Lookup.getDefault().lookup(PickManager.class);
|
||||||
|
pickEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
|
||||||
|
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
hideMarker();
|
||||||
|
numberBuilder = new StringBuilder();
|
||||||
|
if (selectedSpatial == null) {
|
||||||
|
terminate();
|
||||||
|
} else {
|
||||||
|
init(selectedSpatial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyInputEvent kie) {
|
||||||
|
if (kie.isPressed()) {
|
||||||
|
Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie);
|
||||||
|
|
||||||
|
Vector3f axis = new Vector3f();
|
||||||
|
boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis);
|
||||||
|
if (axisChanged) {
|
||||||
|
currentAxis = axis;
|
||||||
|
}
|
||||||
|
boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder);
|
||||||
|
boolean enterHit = ShortcutManager.checkEnterHit(kie);
|
||||||
|
boolean escHit = ShortcutManager.checkEscHit(kie);
|
||||||
|
|
||||||
|
if (escHit) {
|
||||||
|
cancel();
|
||||||
|
} else if (enterHit) {
|
||||||
|
apply();
|
||||||
|
} else if (axisChanged && pickEnabled) {
|
||||||
|
//update pick manager
|
||||||
|
|
||||||
|
if (currentAxis.equals(Vector3f.UNIT_X)) {
|
||||||
|
pickManager.setTransformation(PickManager.PLANE_XY, getTransformType(), camera);
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
|
||||||
|
pickManager.setTransformation(PickManager.PLANE_YZ, getTransformType(), camera);
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
|
||||||
|
pickManager.setTransformation(PickManager.PLANE_XZ, getTransformType(), camera);
|
||||||
|
}
|
||||||
|
} else if (axisChanged || numberChanged) {
|
||||||
|
//update transformation
|
||||||
|
float number = ShortcutManager.getNumberKey(numberBuilder);
|
||||||
|
Vector3f translation = currentAxis.mult(number);
|
||||||
|
finalPosition = startPosition.add(translation);
|
||||||
|
spatial.setLocalTranslation(finalPosition);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
|
||||||
|
|
||||||
|
if (!pickEnabled) {
|
||||||
|
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), SceneComposerToolController.TransformationType.camera, camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_X)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pickManager.updatePick(camera, screenCoord)) {
|
||||||
|
//pick update success
|
||||||
|
Vector3f diff;
|
||||||
|
|
||||||
|
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
|
||||||
|
diff = pickManager.getTranslation();
|
||||||
|
} else {
|
||||||
|
diff = pickManager.getTranslation(currentAxis);
|
||||||
|
}
|
||||||
|
Vector3f position = startPosition.add(diff);
|
||||||
|
finalPosition = position;
|
||||||
|
toolController.getSelectedSpatial().setLocalTranslation(position);
|
||||||
|
updateToolsTransformation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
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.tools.PickManager;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
public class RotateShortcut extends ShortcutTool {
|
||||||
|
|
||||||
|
private Vector3f currentAxis;
|
||||||
|
private StringBuilder numberBuilder;
|
||||||
|
private Spatial spatial;
|
||||||
|
private PickManager pickManager;
|
||||||
|
private boolean pickEnabled;
|
||||||
|
private Quaternion startRotation;
|
||||||
|
private Quaternion finalRotation;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public boolean isActivableBy(KeyInputEvent kie) {
|
||||||
|
return kie.getKeyCode() == KeyInput.KEY_R;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
spatial.setLocalRotation(startRotation);
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply() {
|
||||||
|
actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotation, finalRotation));
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Spatial selectedSpatial) {
|
||||||
|
spatial = selectedSpatial;
|
||||||
|
startRotation = spatial.getLocalRotation().clone();
|
||||||
|
currentAxis = Vector3f.UNIT_XYZ;
|
||||||
|
pickManager = Lookup.getDefault().lookup(PickManager.class);
|
||||||
|
pickEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
|
||||||
|
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
hideMarker();
|
||||||
|
numberBuilder = new StringBuilder();
|
||||||
|
if (selectedSpatial == null) {
|
||||||
|
terminate();
|
||||||
|
} else {
|
||||||
|
init(selectedSpatial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyInputEvent kie) {
|
||||||
|
if (kie.isPressed()) {
|
||||||
|
Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie);
|
||||||
|
|
||||||
|
Vector3f axis = new Vector3f();
|
||||||
|
boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis);
|
||||||
|
if (axisChanged) {
|
||||||
|
currentAxis = axis;
|
||||||
|
}
|
||||||
|
boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder);
|
||||||
|
boolean enterHit = ShortcutManager.checkEnterHit(kie);
|
||||||
|
boolean escHit = ShortcutManager.checkEscHit(kie);
|
||||||
|
|
||||||
|
if (escHit) {
|
||||||
|
cancel();
|
||||||
|
} else if (enterHit) {
|
||||||
|
apply();
|
||||||
|
} else if (axisChanged && pickEnabled) {
|
||||||
|
pickEnabled = false;
|
||||||
|
spatial.setLocalRotation(startRotation.clone());
|
||||||
|
} else if (axisChanged || numberChanged) {
|
||||||
|
//update transformation
|
||||||
|
/* float number = ShortcutManager.getNumberKey(numberBuilder);
|
||||||
|
Vector3f translation = currentAxis.mult(number);
|
||||||
|
finalPosition = startPosition.add(translation);
|
||||||
|
spatial.setLocalTranslation(finalPosition);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
|
||||||
|
|
||||||
|
if (!pickEnabled) {
|
||||||
|
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), SceneComposerToolController.TransformationType.camera, camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_X)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pickManager.updatePick(camera, screenCoord)) {
|
||||||
|
|
||||||
|
Quaternion rotation = startRotation.mult(pickManager.getRotation(startRotation.inverse()));
|
||||||
|
toolController.getSelectedSpatial().setLocalRotation(rotation);
|
||||||
|
finalRotation = rotation;
|
||||||
|
updateToolsTransformation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RotateUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Quaternion before, after;
|
||||||
|
|
||||||
|
RotateUndo(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);
|
||||||
|
toolController.selectedSpatialTransformed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager;
|
||||||
|
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.tools.PickManager;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
public class ScaleShortcut extends ShortcutTool {
|
||||||
|
|
||||||
|
private Vector3f currentAxis;
|
||||||
|
private StringBuilder numberBuilder;
|
||||||
|
private Spatial spatial;
|
||||||
|
private PickManager pickManager;
|
||||||
|
private boolean pickEnabled;
|
||||||
|
private Vector3f startScale;
|
||||||
|
private Vector3f finalScale;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
|
||||||
|
public boolean isActivableBy(KeyInputEvent kie) {
|
||||||
|
return kie.getKeyCode() == KeyInput.KEY_S;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel() {
|
||||||
|
spatial.setLocalScale(startScale);
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void apply() {
|
||||||
|
actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startScale, finalScale));
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(Spatial selectedSpatial) {
|
||||||
|
spatial = selectedSpatial;
|
||||||
|
startScale = spatial.getLocalScale().clone();
|
||||||
|
currentAxis = Vector3f.UNIT_XYZ;
|
||||||
|
pickManager = Lookup.getDefault().lookup(PickManager.class);
|
||||||
|
pickEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) {
|
||||||
|
super.activate(manager, toolNode, onTopToolNode, selectedSpatial, toolController); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
hideMarker();
|
||||||
|
numberBuilder = new StringBuilder();
|
||||||
|
if (selectedSpatial == null) {
|
||||||
|
terminate();
|
||||||
|
} else {
|
||||||
|
init(selectedSpatial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyInputEvent kie) {
|
||||||
|
if (kie.isPressed()) {
|
||||||
|
Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie);
|
||||||
|
|
||||||
|
Vector3f axis = new Vector3f();
|
||||||
|
boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis);
|
||||||
|
if (axisChanged) {
|
||||||
|
currentAxis = axis;
|
||||||
|
}
|
||||||
|
boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder);
|
||||||
|
boolean enterHit = ShortcutManager.checkEnterHit(kie);
|
||||||
|
boolean escHit = ShortcutManager.checkEscHit(kie);
|
||||||
|
|
||||||
|
if (escHit) {
|
||||||
|
cancel();
|
||||||
|
} else if (enterHit) {
|
||||||
|
apply();
|
||||||
|
} else if (axisChanged && pickEnabled) {
|
||||||
|
pickEnabled = false;
|
||||||
|
} else if (axisChanged || numberChanged) {
|
||||||
|
//update transformation
|
||||||
|
/* float number = ShortcutManager.getNumberKey(numberBuilder);
|
||||||
|
Vector3f translation = currentAxis.mult(number);
|
||||||
|
finalPosition = startPosition.add(translation);
|
||||||
|
spatial.setLocalTranslation(finalPosition);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) {
|
||||||
|
|
||||||
|
if (!pickEnabled) {
|
||||||
|
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), SceneComposerToolController.TransformationType.camera, camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_X)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Y)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else if (currentAxis.equals(Vector3f.UNIT_Z)) {
|
||||||
|
pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord);
|
||||||
|
pickEnabled = true;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pickManager.updatePick(camera, screenCoord)) {
|
||||||
|
Vector3f scale = startScale;
|
||||||
|
if (currentAxis.equals(Vector3f.UNIT_XYZ)) {
|
||||||
|
Vector3f constraintAxis = pickManager.getStartOffset().normalize();
|
||||||
|
float diff = pickManager.getTranslation(constraintAxis).dot(constraintAxis);
|
||||||
|
diff *= 0.5f;
|
||||||
|
scale = startScale.add(new Vector3f(diff, diff, diff));
|
||||||
|
} else {
|
||||||
|
// Get the translation in the spatial Space
|
||||||
|
Quaternion worldToSpatial = toolController.getSelectedSpatial().getWorldRotation().inverse();
|
||||||
|
Vector3f diff = pickManager.getTranslation(worldToSpatial.mult(currentAxis));
|
||||||
|
diff.multLocal(0.5f);
|
||||||
|
scale = startScale.add(diff);
|
||||||
|
}
|
||||||
|
finalScale = scale;
|
||||||
|
toolController.getSelectedSpatial().setLocalScale(scale);
|
||||||
|
updateToolsTransformation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScaleUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Vector3f before, after;
|
||||||
|
|
||||||
|
ScaleUndo(Spatial spatial, Vector3f before, Vector3f after) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.before = before;
|
||||||
|
this.after = after;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneUndo() {
|
||||||
|
spatial.setLocalScale(before);
|
||||||
|
toolController.selectedSpatialTransformed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneRedo() {
|
||||||
|
spatial.setLocalScale(after);
|
||||||
|
toolController.selectedSpatialTransformed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
import com.jme3.gde.scenecomposer.SceneEditTool;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
@ServiceProvider(service = ShortcutManager.class)
|
||||||
|
public class ShortcutManager {
|
||||||
|
|
||||||
|
private ShortcutTool currentShortcut;
|
||||||
|
private ArrayList<ShortcutTool> shortcutList;
|
||||||
|
private boolean ctrlDown = false;
|
||||||
|
private boolean shiftDown = false;
|
||||||
|
private boolean altDown = false;
|
||||||
|
|
||||||
|
public ShortcutManager() {
|
||||||
|
shortcutList = new ArrayList<ShortcutTool>();
|
||||||
|
shortcutList.add(new MoveShortcut());
|
||||||
|
shortcutList.add(new RotateShortcut());
|
||||||
|
shortcutList.add(new ScaleShortcut());
|
||||||
|
shortcutList.add(new DuplicateShortcut());
|
||||||
|
shortcutList.add(new DeleteShortcut());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Methodes
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* This MUST be called by the shortcut tool once the modifications are done.
|
||||||
|
*/
|
||||||
|
public void terminate() {
|
||||||
|
currentShortcut = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true if a shortCutTool is active, else return false.
|
||||||
|
*/
|
||||||
|
public boolean isActive() {
|
||||||
|
return currentShortcut != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ctrlDown
|
||||||
|
*/
|
||||||
|
public boolean isCtrlDown() {
|
||||||
|
return ctrlDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the shiftDown
|
||||||
|
*/
|
||||||
|
public boolean isShiftDown() {
|
||||||
|
return shiftDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the altDown
|
||||||
|
*/
|
||||||
|
public boolean isAltDown() {
|
||||||
|
return altDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current shortcut to <code>shortcut</code>. cancel the current
|
||||||
|
* shortcut if it was still active
|
||||||
|
*
|
||||||
|
* @param shortcut the ShortCutTool to set
|
||||||
|
*/
|
||||||
|
public void setShortCut(ShortcutTool shortcut) {
|
||||||
|
if (isActive()) {
|
||||||
|
currentShortcut.cancel();
|
||||||
|
}
|
||||||
|
currentShortcut = shortcut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the shortcut that can be enable with the given kei, the current
|
||||||
|
* shortcut cannot be enable twice. This also check for command key used to
|
||||||
|
* provide isCtrlDown(), isShiftDown() and isAltDown().
|
||||||
|
*
|
||||||
|
* @param kie the KeyInputEvent
|
||||||
|
* @return the activable shortcut else return null
|
||||||
|
*/
|
||||||
|
public ShortcutTool getActivableShortcut(KeyInputEvent kie) {
|
||||||
|
if (checkCommandeKey(kie)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (ShortcutTool s : shortcutList) {
|
||||||
|
if (s != currentShortcut) {
|
||||||
|
if (s.isActivableBy(kie)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the current active shortcut
|
||||||
|
*/
|
||||||
|
public ShortcutTool getActiveShortcut() {
|
||||||
|
return currentShortcut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param kie the KeyInputEvent
|
||||||
|
* @return true if the given Kei can enable a sortcut, else false
|
||||||
|
*/
|
||||||
|
public boolean canActivateShortcut(KeyInputEvent kie) {
|
||||||
|
return getActivableShortcut(kie) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current shortcut with the shortcut one that can be enable with
|
||||||
|
* the given key
|
||||||
|
*
|
||||||
|
* @param kie the KeyInputEvent
|
||||||
|
* @return true is the shortcut changed, else false
|
||||||
|
*/
|
||||||
|
public boolean activateShortcut(KeyInputEvent kie) {
|
||||||
|
ShortcutTool newShortcut = getActivableShortcut(kie);
|
||||||
|
if (newShortcut != null) {
|
||||||
|
currentShortcut = newShortcut;
|
||||||
|
}
|
||||||
|
return newShortcut != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This should be called to trigger the currentShortcut.keyPressed() method.
|
||||||
|
* This also check for command key used to provide isCtrlDown(),
|
||||||
|
* isShiftDown() and isAltDown().
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
*/
|
||||||
|
public void doKeyPressed(KeyInputEvent kie) {
|
||||||
|
if (checkCommandeKey(kie)) {
|
||||||
|
//return;
|
||||||
|
} else if (isActive()) {
|
||||||
|
currentShortcut.keyPressed(kie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkCommandeKey(KeyInputEvent kie) {
|
||||||
|
if (checkCtrlHit(kie)) {
|
||||||
|
ctrlDown = kie.isPressed();
|
||||||
|
return true;
|
||||||
|
} else if (checkAltHit(kie)) {
|
||||||
|
altDown = kie.isPressed();
|
||||||
|
return true;
|
||||||
|
} else if (checkShiftHit(kie)) {
|
||||||
|
shiftDown = kie.isPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
STATIC
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @return true if the given kie is KEY_RETURN
|
||||||
|
*/
|
||||||
|
public static boolean checkEnterHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_RETURN) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @return true if the given kie is KEY_ESCAPE
|
||||||
|
*/
|
||||||
|
public static boolean checkEscHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @return true if the given kie is KEY_LCONTROL || KEY_RCONTROL
|
||||||
|
*/
|
||||||
|
public static boolean checkCtrlHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @return true if the given kie is KEY_LSHIFT || KEY_RSHIFT
|
||||||
|
*/
|
||||||
|
public static boolean checkShiftHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @return true if the given kie is KEY_LMENU || KEY_RMENU
|
||||||
|
*/
|
||||||
|
public static boolean checkAltHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store the number kie into the numberBuilder
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @param numberBuilder
|
||||||
|
* @return true if the given kie is handled as a number key event
|
||||||
|
*/
|
||||||
|
public static boolean checkNumberKey(KeyInputEvent kie, StringBuilder numberBuilder) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_MINUS) {
|
||||||
|
if (numberBuilder.length() > 0) {
|
||||||
|
if (numberBuilder.charAt(0) == '-') {
|
||||||
|
numberBuilder.replace(0, 1, "");
|
||||||
|
} else {
|
||||||
|
numberBuilder.insert(0, '-');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
numberBuilder.append('-');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_0 || kie.getKeyCode() == KeyInput.KEY_NUMPAD0) {
|
||||||
|
numberBuilder.append('0');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_1 || kie.getKeyCode() == KeyInput.KEY_NUMPAD1) {
|
||||||
|
numberBuilder.append('1');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_2 || kie.getKeyCode() == KeyInput.KEY_NUMPAD2) {
|
||||||
|
numberBuilder.append('2');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_3 || kie.getKeyCode() == KeyInput.KEY_NUMPAD3) {
|
||||||
|
numberBuilder.append('3');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_4 || kie.getKeyCode() == KeyInput.KEY_NUMPAD4) {
|
||||||
|
numberBuilder.append('4');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_5 || kie.getKeyCode() == KeyInput.KEY_NUMPAD5) {
|
||||||
|
numberBuilder.append('5');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_6 || kie.getKeyCode() == KeyInput.KEY_NUMPAD6) {
|
||||||
|
numberBuilder.append('6');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_7 || kie.getKeyCode() == KeyInput.KEY_NUMPAD7) {
|
||||||
|
numberBuilder.append('7');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_8 || kie.getKeyCode() == KeyInput.KEY_NUMPAD8) {
|
||||||
|
numberBuilder.append('8');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_9 || kie.getKeyCode() == KeyInput.KEY_NUMPAD9) {
|
||||||
|
numberBuilder.append('9');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_PERIOD) {
|
||||||
|
if (numberBuilder.indexOf(".") == -1) { // if it doesn't exist yet
|
||||||
|
if (numberBuilder.length() == 0
|
||||||
|
|| (numberBuilder.length() == 1 && numberBuilder.charAt(0) == '-')) {
|
||||||
|
numberBuilder.append("0.");
|
||||||
|
} else {
|
||||||
|
numberBuilder.append(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param numberBuilder the StringBuilder storing the float number
|
||||||
|
* @return the float value created from the given StringBuilder
|
||||||
|
*/
|
||||||
|
public static float getNumberKey(StringBuilder numberBuilder) {
|
||||||
|
if (numberBuilder.length() == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return new Float(numberBuilder.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for axis input for key X,Y,Z and store the corresponding UNIT_ into
|
||||||
|
* the axisStore
|
||||||
|
*
|
||||||
|
* @param kie
|
||||||
|
* @param axisStore
|
||||||
|
* @return true if the given kie is handled as a Axis input
|
||||||
|
*/
|
||||||
|
public static boolean checkAxisKey(KeyInputEvent kie, Vector3f axisStore) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_X) {
|
||||||
|
axisStore.set(Vector3f.UNIT_X);
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_Y) {
|
||||||
|
axisStore.set(Vector3f.UNIT_Y);
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_Z) {
|
||||||
|
axisStore.set(Vector3f.UNIT_Z);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.shortcuts;
|
||||||
|
|
||||||
|
import com.jme3.gde.scenecomposer.SceneEditTool;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
import org.openide.util.Lookup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author dokthar
|
||||||
|
*/
|
||||||
|
public abstract class ShortcutTool extends SceneEditTool {
|
||||||
|
|
||||||
|
public abstract boolean isActivableBy(KeyInputEvent kie);
|
||||||
|
|
||||||
|
public abstract void cancel();
|
||||||
|
|
||||||
|
protected final void terminate() {
|
||||||
|
Lookup.getDefault().lookup(ShortcutManager.class).terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void keyPressed(KeyInputEvent kie);
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user