Merge pull request #273 from Dokthar/scenecomposer/master
SDK SceneComposer : new ShortcutToolexperimental
commit
f6a2452ad0
@ -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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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…
Reference in new issue