diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java index 1d045c863..af2636b67 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/SceneCameraController.java @@ -46,7 +46,7 @@ public class SceneCameraController extends AbstractCameraController { } @Override - protected void checkClick(int button) { + protected void checkClick(int button, boolean pressed) { } } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java index 7b2d01deb..0c2701648 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java @@ -51,6 +51,7 @@ import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; import com.jme3.renderer.RenderManager; import java.util.concurrent.Callable; +import java.util.logging.Logger; /** * @@ -70,8 +71,16 @@ public abstract class AbstractCameraController extends AbstractAppState implemen protected Object master; protected boolean moved = false; protected boolean movedR = false; - protected boolean checkClick = false; + protected boolean buttonDownL = false; + protected boolean buttonDownR = false; + protected boolean checkClickL = false; protected boolean checkClickR = false; + protected boolean checkReleaseL = false; + protected boolean checkReleaseR = false; + protected boolean checkDragged = false; + protected boolean checkDraggedR = false; + protected boolean checkReleaseLeft = false; + protected boolean checkReleaseRight = false; public AbstractCameraController(Camera cam, InputManager inputManager) { this.cam = cam; @@ -151,15 +160,22 @@ public abstract class AbstractCameraController extends AbstractAppState implemen cam.setLocation(loc); } - public void onAction(String string, boolean bln, float f) { + /*public void onAction(String string, boolean bln, float f) { if ("MouseButtonLeft".equals(string)) { if (bln) { leftMouse = true; moved = false; } else { + if (leftMouse) + checkReleaseLeft = true; leftMouse = false; if (!moved) { - checkClick = true; + if (checkClick == false) + checkClick = true; + checkDragged = false; + } else { + checkDragged = true; + checkClick = false; } } } @@ -168,49 +184,56 @@ public abstract class AbstractCameraController extends AbstractAppState implemen rightMouse = true; movedR = false; } else { + if (rightMouse) + checkReleaseRight = true; rightMouse = false; if (!movedR) { - checkClickR = true; + if (checkClickR == false) + checkClickR = true; + checkDraggedR = false; + } else { + checkDraggedR = true; + checkClickR = false; } } } - } + }*/ public void onAnalog(String string, float f1, float f) { if ("MouseAxisX".equals(string)) { moved = true; movedR = true; - if (leftMouse) { + if (buttonDownL) { rotateCamera(Vector3f.UNIT_Y, -f1 * 2.5f); } - if (rightMouse) { + if (buttonDownR) { panCamera(f1 * 2.5f, 0); } } else if ("MouseAxisY".equals(string)) { moved = true; movedR = true; - if (leftMouse) { + if (buttonDownL) { rotateCamera(cam.getLeft(), -f1 * 2.5f); } - if (rightMouse) { + if (buttonDownR) { panCamera(0, -f1 * 2.5f); } } else if ("MouseAxisX-".equals(string)) { moved = true; movedR = true; - if (leftMouse) { + if (buttonDownL) { rotateCamera(Vector3f.UNIT_Y, f1 * 2.5f); } - if (rightMouse) { + if (buttonDownR) { panCamera(-f1 * 2.5f, 0); } } else if ("MouseAxisY-".equals(string)) { moved = true; movedR = true; - if (leftMouse) { + if (buttonDownL) { rotateCamera(cam.getLeft(), f1 * 2.5f); } - if (rightMouse) { + if (buttonDownR) { panCamera(0, f1 * 2.5f); } } else if ("MouseWheel".equals(string)) { @@ -219,6 +242,37 @@ public abstract class AbstractCameraController extends AbstractAppState implemen zoomCamera(-.1f); } } + + public void onAction(String string, boolean pressed, float f) { + if ("MouseButtonLeft".equals(string)) { + if (pressed) { + if (!buttonDownL) { // mouse clicked + checkClickL = true; + checkReleaseL = false; + } + } else { + if (buttonDownL) { // mouse released + checkReleaseL = true; + checkClickL = false; + } + } + buttonDownL = pressed; + } + if ("MouseButtonRight".equals(string)) { + if (pressed) { + if (!buttonDownR) { // mouse clicked + checkClickR = true; + checkReleaseR = false; + } + } else { + if (buttonDownR) { // mouse released + checkReleaseR = true; + checkClickR = false; + } + } + buttonDownR = pressed; + } + } public void onJoyAxisEvent(JoyAxisEvent jae) { } @@ -242,39 +296,129 @@ public abstract class AbstractCameraController extends AbstractAppState implemen /**APPSTATE**/ private boolean appInit = false; + + @Override public void initialize(AppStateManager asm, Application aplctn) { appInit = true; } + @Override public boolean isInitialized() { return appInit; } + @Override public void stateAttached(AppStateManager asm) { } + @Override public void stateDetached(AppStateManager asm) { } + @Override public void update(float f) { - if (checkClick) { - checkClick(0); - checkClick = false; - } - if (checkClickR) { - checkClick(1); - checkClickR = false; + if (moved) { + // moved, check for drags + if (checkReleaseL || checkReleaseR) { + // drag released + if (checkReleaseL) + checkDragged(0, false); + if (checkReleaseR) + checkDragged(1, false); + checkReleaseL = false; + checkReleaseR = false; + } else { + if (buttonDownL) + checkDragged(0, true); + else if (buttonDownR) + checkDragged(1, true); + else + checkMoved(); // no dragging, just moved + } + + moved = false; + } else { + // not moved, check for just clicks + if (checkClickL) { + checkClick(0, true); + checkClickL = false; + } + if (checkReleaseL) { + checkClick(0, false); + checkReleaseL = false; + } + if (checkClickR) { + checkClick(1, true); + checkClickR = false; + } + if (checkReleaseR) { + checkClick(1, false); + checkReleaseR = false; + } } + + /*if (checkDragged || checkDraggedR) { + if (checkDragged) { + checkDragged(0); + checkReleaseLeft = false; + checkDragged = false; + checkClick = false; + checkClickR = false; + } + if (checkDraggedR) { + checkDragged(1); + checkReleaseRight = false; + checkDraggedR = false; + checkClick = false; + checkClickR = false; + } + } else { + if (checkClick) { + checkClick(0, checkReleaseLeft); + checkReleaseLeft = false; + checkClick = false; + checkDragged = false; + checkDraggedR = false; + } + if (checkClickR) { + checkClick(1, checkReleaseRight); + checkReleaseRight = false; + checkClickR = false; + checkDragged = false; + checkDraggedR = false; + } + }*/ } - protected abstract void checkClick(int button); + /** + * mouse clicked, not dragged + * @param pressed true if pressed, false if released + */ + protected abstract void checkClick(int button, boolean pressed); + + /** + * Mouse dragged while button is depressed + */ + protected void checkDragged(int button, boolean pressed) { + // override in sub classes + } + + /** + * The mouse moved, no dragging or buttons pressed + */ + protected void checkMoved() { + // override in subclasses + } + @Override public void render(RenderManager rm) { } + @Override public void postRender() { } + @Override public void cleanup() { } diff --git a/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java index 4374622e0..c9d5714d9 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/SceneToolController.java @@ -61,33 +61,34 @@ public class SceneToolController implements AppState { } protected void initTools() { - Material redMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); - redMat.getAdditionalRenderState().setWireframe(true); - redMat.setColor("Color", ColorRGBA.Red); + //Material redMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + //redMat.getAdditionalRenderState().setWireframe(true); + //redMat.setColor("Color", ColorRGBA.Red); Material greenMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); greenMat.getAdditionalRenderState().setWireframe(true); greenMat.setColor("Color", ColorRGBA.Green); - Material blueMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); - blueMat.getAdditionalRenderState().setWireframe(true); - blueMat.setColor("Color", ColorRGBA.Blue); + //Material blueMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + //blueMat.getAdditionalRenderState().setWireframe(true); + //blueMat.setColor("Color", ColorRGBA.Blue); Material grayMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); grayMat.getAdditionalRenderState().setWireframe(true); grayMat.setColor("Color", ColorRGBA.Gray); - + //cursor if (cursor == null) { cursor = new Node(); } cursor.detachAllChildren(); - Geometry cursorArrowX = new Geometry("cursorArrowX", new Arrow(Vector3f.UNIT_X)); - Geometry cursorArrowY = new Geometry("cursorArrowY", new Arrow(Vector3f.UNIT_Y)); - Geometry cursorArrowZ = new Geometry("cursorArrowZ", new Arrow(Vector3f.UNIT_Z)); - cursorArrowX.setMaterial(redMat); + //Geometry cursorArrowX = new Geometry("cursorArrowX", new Arrow(Vector3f.UNIT_X)); + Geometry cursorArrowY = new Geometry("cursorArrowY", new Arrow(new Vector3f(0,-1,0))); + cursorArrowY.setLocalTranslation(0, 1, 0); + //Geometry cursorArrowZ = new Geometry("cursorArrowZ", new Arrow(Vector3f.UNIT_Z)); + //cursorArrowX.setMaterial(redMat); cursorArrowY.setMaterial(greenMat); - cursorArrowZ.setMaterial(blueMat); - cursor.attachChild(cursorArrowX); + //cursorArrowZ.setMaterial(blueMat); + //cursor.attachChild(cursorArrowX); cursor.attachChild(cursorArrowY); - cursor.attachChild(cursorArrowZ); + //cursor.attachChild(cursorArrowZ); toolsNode.attachChild(cursor); //grid diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/ToggleButtonGroup.java b/sdk/jme3-core/src/com/jme3/gde/core/util/ToggleButtonGroup.java similarity index 98% rename from sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/ToggleButtonGroup.java rename to sdk/jme3-core/src/com/jme3/gde/core/util/ToggleButtonGroup.java index d3048a02c..d30cc98d1 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/ToggleButtonGroup.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/util/ToggleButtonGroup.java @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.gde.terraineditor; +package com.jme3.gde.core.util; import javax.swing.AbstractButton; import javax.swing.ButtonGroup; diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties index 74dd0b095..4898b7d08 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties @@ -44,3 +44,11 @@ SceneComposerTopComponent.jTextField1.text=10 SceneComposerTopComponent.jLabel4.text=kg SceneComposerTopComponent.jButton1.text=make character SceneComposerTopComponent.fixedCheckBox.text=radius/height +SceneComposerTopComponent.moveButton.text= +SceneComposerTopComponent.rotateButton.text= +SceneComposerTopComponent.scaleButton.text= +SceneComposerTopComponent.selectButton.text= +SceneComposerTopComponent.selectButton.toolTipText=Select +SceneComposerTopComponent.moveButton.toolTipText=Move +SceneComposerTopComponent.rotateButton.toolTipText=Rotate (in-development) +SceneComposerTopComponent.scaleButton.toolTipText=Scale (in-development) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java index d791d0268..7a889827d 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/ComposerCameraController.java @@ -36,6 +36,8 @@ import com.jme3.collision.CollisionResults; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.scene.controller.AbstractCameraController; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.input.KeyInput; +import com.jme3.input.event.KeyInputEvent; import com.jme3.math.Ray; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; @@ -50,6 +52,8 @@ public class ComposerCameraController extends AbstractCameraController { private Node rootNode; private JmeNode jmeRootNode; + private SceneComposerToolController toolController; + private boolean forceCameraControls = false; // when user holds shift, this is true public ComposerCameraController(Camera cam, JmeNode rootNode) { super(cam, SceneApplication.getApplication().getInputManager()); @@ -57,49 +61,114 @@ public class ComposerCameraController extends AbstractCameraController { this.rootNode = rootNode.getLookup().lookup(Node.class); } - public void checkClick(int button) { + private boolean isEditButtonEnabled() { + return toolController.isEditToolEnabled(); + } + + public void setToolController(SceneComposerToolController toolController) { + this.toolController = toolController; + } + + public boolean isToolUsesCameraControls() { + return !toolController.isOverrideCameraControl(); + } + + public Camera getCamera() { + return cam; + } + + @Override + public void onKeyEvent(KeyInputEvent kie) { + if (kie.isPressed()) { + if ( KeyInput.KEY_LSHIFT == kie.getKeyCode() ) { + forceCameraControls = true; + } + } else if (kie.isReleased()){ + if ( KeyInput.KEY_LSHIFT == kie.getKeyCode() ) { + forceCameraControls = false; + } + } + } + + @Override + public void checkClick(int button, boolean pressed) { if (button == 0) { - CollisionResults results = new CollisionResults(); - Ray ray = new Ray(); - Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone(); - Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone(); - dir.subtractLocal(pos).normalizeLocal(); - ray.setOrigin(pos); - ray.setDirection(dir); - rootNode.collideWith(ray, results); - if (results == null) { - return; + if (isEditButtonEnabled() && !forceCameraControls) { + toolController.doEditToolActivatedPrimary(new Vector2f(mouseX,mouseY), pressed, cam); } - final CollisionResult result = results.getClosestCollision(); - java.awt.EventQueue.invokeLater(new Runnable() { - - public void run() { - if (result != null && result.getGeometry() != null) { - SceneApplication.getApplication().setCurrentFileNode(jmeRootNode.getChild(result.getGeometry())); - } else { - SceneApplication.getApplication().setCurrentFileNode(jmeRootNode); - } - } - }); - checkClick = false; } if (button == 1) { - CollisionResults results = new CollisionResults(); - Ray ray = new Ray(); - Vector3f pos = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0).clone(); - Vector3f dir = cam.getWorldCoordinates(new Vector2f(mouseX, mouseY), 0.3f).clone(); - dir.subtractLocal(pos).normalizeLocal(); - ray.setOrigin(pos); - ray.setDirection(dir); - rootNode.collideWith(ray, results); - if (results == null) { - return; + if (isEditButtonEnabled() && !forceCameraControls) { + toolController.doEditToolActivatedSecondary(new Vector2f(mouseX,mouseY), pressed, cam); + } + } + } + + @Override + protected void checkDragged(int button, boolean pressed) { + if (button == 0) + toolController.doEditToolDraggedPrimary(new Vector2f(mouseX, mouseY), pressed, cam); + else if (button == 1) + toolController.doEditToolDraggedSecondary(new Vector2f(mouseX, mouseY), pressed, cam); + } + + @Override + protected void checkMoved() { + toolController.doEditToolMoved(new Vector2f(mouseX, mouseY), cam); + } + + @Override + public void onAnalog(String string, float f1, float f) { + if ("MouseAxisX".equals(string)) { + moved = true; + movedR = true; + if (isToolUsesCameraControls() || forceCameraControls) { + if (buttonDownL) { + rotateCamera(Vector3f.UNIT_Y, -f1 * 2.5f); + } + if (buttonDownR) { + panCamera(f1 * 2.5f, 0); + } } - CollisionResult result = results.getClosestCollision(); - if (result != null) { - ((SceneComposerTopComponent) master).doMoveCursor(result.getContactPoint());//getGeometry().getWorldTranslation().add(result.getGeometry().getWorldRotation().mult(result.getContactPoint()))); + } else if ("MouseAxisY".equals(string)) { + moved = true; + movedR = true; + if (isToolUsesCameraControls() || forceCameraControls) { + if (buttonDownL) { + rotateCamera(cam.getLeft(), -f1 * 2.5f); + } + if (buttonDownR) { + panCamera(0, -f1 * 2.5f); + } + } + } else if ("MouseAxisX-".equals(string)) { + moved = true; + movedR = true; + if (isToolUsesCameraControls() || forceCameraControls) { + if (buttonDownL) { + rotateCamera(Vector3f.UNIT_Y, f1 * 2.5f); + } + if (buttonDownR) { + panCamera(-f1 * 2.5f, 0); + } + } + } else if ("MouseAxisY-".equals(string)) { + moved = true; + movedR = true; + if (isToolUsesCameraControls() || forceCameraControls) { + if (buttonDownL) { + rotateCamera(cam.getLeft(), f1 * 2.5f); + } + if (buttonDownR) { + panCamera(0, f1 * 2.5f); + } } - checkClickR = false; + } else if ("MouseWheel".equals(string)) { + zoomCamera(.1f); + } else if ("MouseWheel-".equals(string)) { + zoomCamera(-.1f); } } + + } diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java new file mode 100644 index 000000000..c17001042 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java @@ -0,0 +1,179 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + +import com.jme3.asset.AssetManager; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.scene.controller.SceneToolController; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import java.util.concurrent.Callable; + +/** + * + * @author Brent Owens + */ +public class SceneComposerToolController extends SceneToolController { + + private JmeNode rootNode; + private SceneEditTool editTool; + private SceneEditorController editorController; + private ComposerCameraController cameraController; + private Camera overlayCam; + private ViewPort overlayView; + private Node onTopToolsNode; + + public SceneComposerToolController(Node toolsNode, AssetManager manager, JmeNode rootNode) { + super(toolsNode, manager); + this.rootNode = rootNode; + } + + public SceneComposerToolController(AssetManager manager) { + super(manager); + } + + public void setEditorController(SceneEditorController editorController) { + this.editorController = editorController; + } + + public void setCameraController(ComposerCameraController cameraController) { + this.cameraController = cameraController; + + // a node in a viewport that will always render on top + onTopToolsNode = new Node("OverlayNode"); + overlayView = SceneApplication.getApplication().getRenderManager().createMainView("Overlay", this.cameraController.getCamera()); + overlayView.setClearFlags(false, true, false); + overlayView.attachScene( onTopToolsNode ); + } + + @Override + public void cleanup() { + super.cleanup(); + SceneApplication.getApplication().getRenderManager().removeMainView(overlayView); + cameraController = null; + editorController = null; + onTopToolsNode.detachAllChildren(); + } + + @Override + public void update(float tpf) { + super.update(tpf); + if (onTopToolsNode != null) { + onTopToolsNode.updateLogicalState(tpf); + onTopToolsNode.updateGeometricState(); + } + if (editTool != null) + editTool.updateToolsTransformation(selected); + + } + + @Override + public void render(RenderManager rm) { + super.render(rm); + } + + public boolean isEditToolEnabled() { + return editTool != null; + } + + /** + * If the current tool overrides camera zoom/pan controls + */ + public boolean isOverrideCameraControl() { + if (editTool != null) + return editTool.isOverrideCameraControl(); + else + return false; + } + + /** + * Scene composer edit tool activated. Pass in null to remove tools. + * + * @param sceneEditButton pass in null to hide any existing tool markers + */ + public void showEditTool(final SceneEditTool sceneEditTool) { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + doEnableEditTool(sceneEditTool); + return null; + } + }); + } + + private void doEnableEditTool(SceneEditTool sceneEditTool) { + if (editTool != null) + editTool.hideMarker(); + editTool = sceneEditTool; + editTool.activate(manager, toolsNode, onTopToolsNode, selected, this); + } + + public void selectedSpatialTransformed() { + if (editTool != null) { + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + editTool.updateToolsTransformation(selected); + return null; + } + }); + } + } + + public void setSelected(Spatial selected) { + this.selected = selected; + } + + public void setNeedsSave(boolean needsSave) { + editorController.setNeedsSave(needsSave); + } + + /** + * Primary button activated, send command to the tool + * for appropriate action. + */ + public void doEditToolActivatedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) { + if (editTool != null){ + editTool.setCamera(camera); + editTool.actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } + } + + /** + * Secondary button activated, send command to the tool + * for appropriate action. + */ + public void doEditToolActivatedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) { + if (editTool != null){ + editTool.setCamera(camera); + editTool.actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } + } + + public void doEditToolMoved(Vector2f mouseLoc, Camera camera) { + if (editTool != null){ + editTool.setCamera(camera); + editTool.mouseMoved(mouseLoc); + } + } + + public void doEditToolDraggedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) { + if (editTool != null) { + editTool.setCamera(camera); + editTool.draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } + } + + public void doEditToolDraggedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) { + if (editTool != null){ + editTool.setCamera(camera); + editTool.draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form index c8d7ccaca..71846046c 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form @@ -1,6 +1,13 @@
+ + + + + + + @@ -28,7 +35,7 @@ - + @@ -73,7 +80,7 @@ - + @@ -117,7 +124,7 @@ - + @@ -151,6 +158,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -332,12 +426,12 @@ - + - + diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java index 7cce546fe..4a9e97ec0 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java @@ -12,15 +12,17 @@ import com.jme3.gde.core.scene.PreviewRequest; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.scene.SceneListener; import com.jme3.gde.core.scene.SceneRequest; -import com.jme3.gde.core.scene.controller.SceneToolController; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; +import com.jme3.gde.scenecomposer.tools.MoveTool; +import com.jme3.gde.scenecomposer.tools.SelectTool; import com.jme3.math.Vector3f; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import java.util.Collection; import java.util.logging.Logger; +import javax.swing.ButtonGroup; import javax.swing.border.TitledBorder; import org.openide.util.Lookup.Result; import org.openide.util.LookupEvent; @@ -55,7 +57,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce private static final String PREFERRED_ID = "SceneComposerTopComponent"; private final Result result; ComposerCameraController camController; - SceneToolController toolController; + SceneComposerToolController toolController; SceneEditorController editorController; // private SaveCookie saveCookie = new SaveCookieImpl(); private SceneRequest currentRequest; @@ -77,6 +79,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce // //GEN-BEGIN:initComponents private void initComponents() { + spatialModButtonGroup = new ButtonGroup(); sceneInfoPanel = new javax.swing.JPanel(); sceneInfoLabel1 = new javax.swing.JLabel(); sceneInfoLabel2 = new javax.swing.JLabel(); @@ -84,6 +87,11 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce jScrollPane1 = new javax.swing.JScrollPane(); jList1 = new javax.swing.JList(); jToolBar1 = new javax.swing.JToolBar(); + selectButton = new javax.swing.JToggleButton(); + moveButton = new javax.swing.JToggleButton(); + rotateButton = new javax.swing.JToggleButton(); + scaleButton = new javax.swing.JToggleButton(); + jSeparator5 = new javax.swing.JToolBar.Separator(); addObjectButton = new javax.swing.JButton(); addCursorButton = new javax.swing.JButton(); moveToCursorButton = new javax.swing.JButton(); @@ -134,7 +142,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce .addComponent(sceneInfoLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sceneInfoLabel2) - .addContainerGap(93, Short.MAX_VALUE)) + .addContainerGap(105, Short.MAX_VALUE)) ); palettePanel.setBackground(new java.awt.Color(204, 204, 204)); @@ -150,13 +158,63 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce ); palettePanelLayout.setVerticalGroup( palettePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 133, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 139, Short.MAX_VALUE) ); jToolBar1.setBackground(new java.awt.Color(204, 204, 204)); jToolBar1.setFloatable(false); jToolBar1.setRollover(true); + spatialModButtonGroup.add(selectButton); + selectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_select.png"))); // NOI18N + selectButton.setSelected(true); + org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectButton.text")); // NOI18N + selectButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectButton.toolTipText")); // NOI18N + selectButton.setFocusable(false); + selectButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + selectButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + selectButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + selectButtonActionPerformed(evt); + } + }); + jToolBar1.add(selectButton); + + spatialModButtonGroup.add(moveButton); + moveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_arrow_out.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(moveButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveButton.text")); // NOI18N + moveButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.moveButton.toolTipText")); // NOI18N + moveButton.setFocusable(false); + moveButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + moveButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + moveButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + moveButtonActionPerformed(evt); + } + }); + jToolBar1.add(moveButton); + + spatialModButtonGroup.add(rotateButton); + rotateButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_arrow_rotate_clockwise.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(rotateButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.rotateButton.text")); // NOI18N + rotateButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.rotateButton.toolTipText")); // NOI18N + rotateButton.setEnabled(false); + rotateButton.setFocusable(false); + rotateButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + rotateButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jToolBar1.add(rotateButton); + + spatialModButtonGroup.add(scaleButton); + scaleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_arrow_inout.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(scaleButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.scaleButton.text")); // NOI18N + scaleButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.scaleButton.toolTipText")); // NOI18N + scaleButton.setEnabled(false); + scaleButton.setFocusable(false); + scaleButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + scaleButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + jToolBar1.add(scaleButton); + jToolBar1.add(jSeparator5); + addObjectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/add.gif"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(addObjectButton, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.addObjectButton.text")); // NOI18N addObjectButton.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.addObjectButton.toolTipText")); // NOI18N @@ -274,11 +332,11 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce jPanel3.setLayout(jPanel3Layout); jPanel3Layout.setHorizontalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 190, Short.MAX_VALUE) + .addGap(0, 211, Short.MAX_VALUE) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 21, Short.MAX_VALUE) + .addGap(0, 23, Short.MAX_VALUE) ); jToolBar1.add(jPanel3); @@ -357,7 +415,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sceneInfoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 696, Short.MAX_VALUE) + .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 708, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -400,6 +458,7 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce private void moveToCursorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveToCursorButtonActionPerformed if (editorController != null) { editorController.moveSelectedSpatial(toolController.getCursorLocation()); + toolController.selectedSpatialTransformed(); } }//GEN-LAST:event_moveToCursorButtonActionPerformed @@ -442,6 +501,17 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce } }//GEN-LAST:event_jButton1ActionPerformed + + private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed + SelectTool tool = new SelectTool(); + toolController.showEditTool(tool); + }//GEN-LAST:event_selectButtonActionPerformed + + private void moveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveButtonActionPerformed + MoveTool tool = new MoveTool(); + toolController.showEditTool(tool); + }//GEN-LAST:event_moveButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton addCursorButton; private javax.swing.JButton addObjectButton; @@ -464,19 +534,25 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce private javax.swing.JToolBar.Separator jSeparator2; private javax.swing.JToolBar.Separator jSeparator3; private javax.swing.JToolBar.Separator jSeparator4; + private javax.swing.JToolBar.Separator jSeparator5; private javax.swing.JTextField jTextField1; private javax.swing.JToolBar jToolBar1; private javax.swing.JToolBar jToolBar2; private javax.swing.JToolBar jToolBar3; + private javax.swing.JToggleButton moveButton; private javax.swing.JButton moveToCursorButton; private javax.swing.JPanel palettePanel; private javax.swing.JSpinner radiusSpinner; private javax.swing.JButton resetCursorButton; + private javax.swing.JToggleButton rotateButton; + private javax.swing.JToggleButton scaleButton; private javax.swing.JLabel sceneInfoLabel1; private javax.swing.JLabel sceneInfoLabel2; private javax.swing.JPanel sceneInfoPanel; + private javax.swing.JToggleButton selectButton; private javax.swing.JToggleButton showGridToggleButton; private javax.swing.JToggleButton showSelectionToggleButton; + private javax.swing.ButtonGroup spatialModButtonGroup; // End of variables declaration//GEN-END:variables /** @@ -811,10 +887,16 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce if (toolController != null) { toolController.cleanup(); } - toolController = new SceneToolController(currentRequest.getToolNode(), currentRequest.getManager()); + toolController = new SceneComposerToolController(currentRequest.getToolNode(), currentRequest.getManager(), request.getJmeNode()); camController = new ComposerCameraController(SceneApplication.getApplication().getCamera(), request.getJmeNode()); + toolController.setEditorController(editorController); + camController.setToolController(toolController); camController.setMaster(this); camController.enable(); + + toolController.setCameraController(camController); + SelectTool tool = new SelectTool(); + toolController.showEditTool(tool); }/* else { SceneApplication.getApplication().removeSceneListener(this); currentRequest = null; diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java new file mode 100644 index 000000000..8281527f8 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java @@ -0,0 +1,508 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer; + + +import com.jme3.asset.AssetManager; +import com.jme3.bounding.BoundingBox; +import com.jme3.bounding.BoundingVolume; +import com.jme3.bullet.collision.PhysicsCollisionObject; +import com.jme3.bullet.control.CharacterControl; +import com.jme3.bullet.control.GhostControl; +import com.jme3.bullet.control.PhysicsControl; +import com.jme3.bullet.control.RigidBodyControl; +import com.jme3.bullet.control.VehicleControl; +import com.jme3.bullet.util.DebugShapeFactory; +import com.jme3.collision.CollisionResult; +import com.jme3.collision.CollisionResults; +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; +import com.jme3.material.Material; +import com.jme3.material.RenderState.BlendMode; +import com.jme3.material.RenderState.FaceCullMode; +import com.jme3.math.ColorRGBA; +import com.jme3.math.FastMath; +import com.jme3.math.Matrix3f; +import com.jme3.math.Quaternion; +import com.jme3.math.Ray; +import com.jme3.math.Transform; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; +import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.debug.Arrow; +import com.jme3.scene.debug.WireBox; +import com.jme3.scene.shape.Quad; +import java.util.concurrent.Callable; +import org.openide.loaders.DataObject; +import org.openide.util.Lookup; + +/** + * + * @author Brent Owens + */ +public abstract class SceneEditTool { + + protected SceneComposerToolController toolController; + protected AssetManager manager; + protected Camera camera; + private boolean overrideCameraControl = false; // if true, you cannot pan/zoom unless you hold SHIFT + + // the key to load the tool hint text from the resource bundle + protected String toolHintTextKey = "SceneComposerTopComponent.toolHint.default"; // not used yet + + protected Spatial selectedSpatial; + protected Spatial selectionShape; + protected Node toolNode; + protected Node onTopToolNode; + + protected Node axisMarker; + protected Material redMat, blueMat, greenMat, yellowMat, cyanMat, magentaMat, orangeMat; + + protected enum AxisMarkerPickType {axisOnly, planeOnly, axisAndPlane}; + protected AxisMarkerPickType axisPickType; + + + /** + * The tool was selected, start showing the marker. + * @param manager + * @param toolNode: parent node that the marker will attach to + */ + public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) { + this.manager = manager; + this.toolController = toolController; + this.selectedSpatial = selectedSpatial; + addMarker(toolNode, onTopToolNode); + } + + protected void addMarker(Node toolNode, Node onTopToolNode) { + this.toolNode = toolNode; + this.onTopToolNode = onTopToolNode; + + if (axisMarker == null) { + axisMarker = createAxisMarker(); + } + axisMarker.removeFromParent(); + this.onTopToolNode.attachChild(axisMarker); + setDefaultAxisMarkerColors(); + + // create and add the selection shape + if (selectionShape != null) + selectionShape.removeFromParent(); + + selectionShape = createSelectionShape(toolNode, selectedSpatial); + + if (selectionShape != null) { + setDefaultSelectionShapeColors(); + this.toolNode.attachChild(selectionShape); + axisMarker.setLocalTranslation(selectedSpatial.getWorldTranslation()); + selectionShape.setLocalTranslation(selectedSpatial.getWorldTranslation()); + } + + } + + protected void replaceSelectionShape(Spatial spatial) { + if (spatial != null) { + if (selectionShape != null) + selectionShape.removeFromParent(); + selectedSpatial = spatial; + toolController.setSelected(spatial); + selectionShape = createSelectionShape(toolNode, selectedSpatial); + setDefaultSelectionShapeColors(); + toolNode.attachChild(selectionShape); + } + else { + if (selectionShape != null) + selectionShape.removeFromParent(); + selectionShape = null; + } + } + + /** + * Remove the marker from it's parent (the tools node) + */ + public void hideMarker() { + if (axisMarker != null) + axisMarker.removeFromParent(); + if (selectionShape != null) + selectionShape.removeFromParent(); + } + + public boolean isOverrideCameraControl() { + return overrideCameraControl; + } + + public void setOverrideCameraControl(boolean overrideCameraControl) { + this.overrideCameraControl = overrideCameraControl; + } + + /** + * Called when the selected spatial has been modified + * outside of the tool. + */ + public void updateToolsTransformation(final Spatial spatial) { + + if (selectionShape == null) + return; + + // has anything changed? + if (!selectionShape.getLocalTranslation().equals(spatial.getWorldTranslation()) && + !selectionShape.getLocalRotation().equals(spatial.getWorldRotation()) && + !selectionShape.getLocalScale().equals(spatial.getWorldScale())) + return; + + // something has updated, so update the tools + selectionShape.setLocalTranslation(spatial.getWorldTranslation()); + selectionShape.setLocalRotation(spatial.getWorldRotation()); + selectionShape.setLocalScale(selectedSpatial.getWorldScale()); + + SceneApplication.getApplication().enqueue(new Callable() { + public Object call() throws Exception { + axisMarker.setLocalTranslation(spatial.getWorldTranslation()); + axisMarker.setLocalRotation(selectedSpatial.getWorldRotation()); + return null; + } + }); + } + + /** + * The primary action for the tool gets activated + */ + public abstract void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject); + + /** + * The secondary action for the tool gets activated + */ + public abstract void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject); + + /** + * Called when the mouse is moved but not dragged (ie no buttons are pressed) + */ + public abstract void mouseMoved(Vector2f screenCoord); + + /** + * Called when the mouse is moved while the primary button is down + */ + public abstract void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject); + + /** + * Called when the mouse is moved while the secondary button is down + */ + public abstract void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject); + + /** + * Call when an action is performed that requires the scene to be saved + * and an undo can be performed + * @param undoer your implementation, probably with a begin and end state for undoing + */ + protected void actionPerformed(AbstractUndoableSceneEdit undoer) { + Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, undoer); + toolController.setNeedsSave(true); + } + + + /** + * Given the mouse coordinates, pick the geometry that is closest to the camera. + * @param jmeRootNode to pick from + * @return the selected spatial, or null if nothing + */ + protected Spatial pickWorldSpatial(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) { + Node rootNode = jmeRootNode.getLookup().lookup(Node.class); + CollisionResult cr = pick(cam, mouseLoc, rootNode); + if (cr != null) + return cr.getGeometry(); + else + return null; + } + + /** + * Given the mouse coordinate, pick the world location where the mouse intersects + * a geometry. + * @param jmeRootNode to pick from + * @return the location of the pick, or null if nothing collided with the mouse + */ + protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) { + Node rootNode = jmeRootNode.getLookup().lookup(Node.class); + return pickWorldLocation(cam, mouseLoc, rootNode); + } + + + protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, Node rootNode) { + CollisionResult cr = pick(cam, mouseLoc, rootNode); + if (cr != null) + return cr.getContactPoint(); + else + return null; + } + + /** + * Pick a part of the axis marker. The result is a Vector3f that represents + * what part of the axis was selected. + * For example if (1,0,0) is returned, then the X-axis pole was selected. + * If (0,1,1) is returned, then the Y-Z plane was selected. + * + * @return null if it did not intersect the marker + */ + protected Vector3f pickAxisMarker(Camera cam, Vector2f mouseLoc, AxisMarkerPickType pickType) { + if (axisMarker == null) + return null; + + CollisionResult cr = pick(cam, mouseLoc, axisMarker); + if (cr == null || cr.getGeometry() == null) + return null; + + if (pickType == AxisMarkerPickType.planeOnly) { + if ("quadXY".equals(cr.getGeometry().getName()) ) { + return new Vector3f(1,1,0); + } else if ("quadXZ".equals(cr.getGeometry().getName()) ) { + return new Vector3f(1,0,1); + } else if ("quadYZ".equals(cr.getGeometry().getName()) ) { + return new Vector3f(0,1,1); + } + } + else if (pickType == AxisMarkerPickType.axisOnly) { + if ("arrowX".equals(cr.getGeometry().getName()) ) { + return new Vector3f(1,0,0); + } else if ("arrowY".equals(cr.getGeometry().getName()) ) { + return new Vector3f(0,1,0); + } else if ("arrowZ".equals(cr.getGeometry().getName()) ) { + return new Vector3f(0,1,0); + } + } else if (pickType == AxisMarkerPickType.axisAndPlane) { + if ("arrowX".equals(cr.getGeometry().getName()) ) { + return new Vector3f(1,0,0); + } else if ("arrowY".equals(cr.getGeometry().getName()) ) { + return new Vector3f(0,1,0); + } else if ("arrowZ".equals(cr.getGeometry().getName()) ) { + return new Vector3f(0,1,0); + } else if ("quadXY".equals(cr.getGeometry().getName()) ) { + return new Vector3f(1,1,0); + } else if ("quadXZ".equals(cr.getGeometry().getName()) ) { + return new Vector3f(1,0,1); + } else if ("quadYZ".equals(cr.getGeometry().getName()) ) { + return new Vector3f(0,1,1); + } + } + return null; + } + + private CollisionResult pick(Camera cam, Vector2f mouseLoc, Node node) { + CollisionResults results = new CollisionResults(); + Ray ray = new Ray(); + Vector3f pos = cam.getWorldCoordinates(mouseLoc, 0).clone(); + Vector3f dir = cam.getWorldCoordinates(mouseLoc, 0.1f).clone(); + dir.subtractLocal(pos).normalizeLocal(); + ray.setOrigin(pos); + ray.setDirection(dir); + node.collideWith(ray, results); + CollisionResult result = results.getClosestCollision(); + return result; + } + + /** + * Show what axis or plane the mouse is currently over and will affect. + * @param axisMarkerPickType + */ + protected void highlightAxisMarker(Camera camera, Vector2f screenCoord, AxisMarkerPickType axisMarkerPickType) { + setDefaultAxisMarkerColors(); + Vector3f picked = pickAxisMarker(camera, screenCoord, axisPickType); + if (picked == null) + return; + + if (picked.equals(new Vector3f(1,0,0))) + axisMarker.getChild("arrowX").setMaterial(orangeMat); + else if (picked.equals(new Vector3f(0,1,0))) + axisMarker.getChild("arrowY").setMaterial(orangeMat); + else if (picked.equals(new Vector3f(0,0,1))) + axisMarker.getChild("arrowZ").setMaterial(orangeMat); + else if (picked.equals(new Vector3f(1,1,0))) + axisMarker.getChild("quadXY").setMaterial(orangeMat); + else if (picked.equals(new Vector3f(1,0,1))) + axisMarker.getChild("quadXZ").setMaterial(orangeMat); + else if (picked.equals(new Vector3f(0,1,1))) + axisMarker.getChild("quadYZ").setMaterial(orangeMat); + } + + /** + * Create the axis marker that is selectable + */ + protected Node createAxisMarker() { + float size = 2; + float arrowSize = size; + float planeSize = size*0.7f; + + Quaternion YAW090 = new Quaternion().fromAngleAxis(-FastMath.PI/2, new Vector3f(0,1,0)); + Quaternion PITCH090 = new Quaternion().fromAngleAxis(FastMath.PI/2, new Vector3f(1,0,0)); + + redMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + redMat.getAdditionalRenderState().setWireframe(true); + redMat.setColor("Color", ColorRGBA.Red); + //redMat.getAdditionalRenderState().setDepthTest(false); + greenMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + greenMat.getAdditionalRenderState().setWireframe(true); + greenMat.setColor("Color", ColorRGBA.Green); + //greenMat.getAdditionalRenderState().setDepthTest(false); + blueMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + blueMat.getAdditionalRenderState().setWireframe(true); + blueMat.setColor("Color", ColorRGBA.Blue); + //blueMat.getAdditionalRenderState().setDepthTest(false); + yellowMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + yellowMat.getAdditionalRenderState().setWireframe(false); + yellowMat.setColor("Color", new ColorRGBA(1f, 1f, 0f, 0.25f)); + yellowMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); + yellowMat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); + //yellowMat.getAdditionalRenderState().setDepthTest(false); + cyanMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + cyanMat.getAdditionalRenderState().setWireframe(false); + cyanMat.setColor("Color", new ColorRGBA(0f, 1f, 1f, 0.25f)); + cyanMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); + cyanMat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); + //cyanMat.getAdditionalRenderState().setDepthTest(false); + magentaMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + magentaMat.getAdditionalRenderState().setWireframe(false); + magentaMat.setColor("Color", new ColorRGBA(1f, 0f, 1f, 0.25f)); + magentaMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); + magentaMat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); + //magentaMat.getAdditionalRenderState().setDepthTest(false); + + orangeMat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); + orangeMat.getAdditionalRenderState().setWireframe(false); + orangeMat.setColor("Color", new ColorRGBA(251f/255f, 130f/255f, 0f, 0.4f)); + orangeMat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); + orangeMat.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off); + + Node axis = new Node(); + + // create arrows + Geometry arrowX = new Geometry("arrowX", new Arrow(new Vector3f(arrowSize,0,0))); + Geometry arrowY = new Geometry("arrowY", new Arrow(new Vector3f(0,arrowSize,0))); + Geometry arrowZ = new Geometry("arrowZ", new Arrow(new Vector3f(0,0,arrowSize))); + axis.attachChild(arrowX); + axis.attachChild(arrowY); + axis.attachChild(arrowZ); + + // create planes + Geometry quadXY = new Geometry("quadXY", new Quad(planeSize, planeSize) ); + Geometry quadXZ = new Geometry("quadXZ", new Quad(planeSize, planeSize) ); + quadXZ.setLocalRotation(PITCH090); + Geometry quadYZ = new Geometry("quadYZ", new Quad(planeSize, planeSize) ); + quadYZ.setLocalRotation(YAW090); + axis.attachChild(quadXY); + axis.attachChild(quadXZ); + axis.attachChild(quadYZ); + + axis.setModelBound(new BoundingBox()); + return axis; + } + + protected void setDefaultAxisMarkerColors() { + axisMarker.getChild("arrowX").setMaterial(redMat); + axisMarker.getChild("arrowY").setMaterial(blueMat); + axisMarker.getChild("arrowZ").setMaterial(greenMat); + axisMarker.getChild("quadXY").setMaterial(yellowMat); + axisMarker.getChild("quadXZ").setMaterial(magentaMat); + axisMarker.getChild("quadYZ").setMaterial(cyanMat); + } + + protected void setDefaultSelectionShapeColors() { + if (selectionShape != null) { + Material mat = new Material(SceneApplication.getApplication().getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); + mat.getAdditionalRenderState().setWireframe(true); + mat.setColor("Color", new ColorRGBA(0.8f,0.8f,0.8f,0.3f)); + mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); + selectionShape.setMaterial(mat); + } + } + + protected Spatial createSelectionShape(Node toolNode, Spatial spat) { + if (spat == null) + return null; + if (selectionShape != null) { + selectionShape.removeFromParent(); + selectionShape = null; + } + if (spat instanceof Geometry) { + return getGeometrySelection(toolNode, (Geometry) spat); + } else if (spat.getControl(PhysicsControl.class) != null) { + return getPhysicsSelection(toolNode, spat); + } else { + return getBoxSelection(toolNode, spat); + } + } + + protected Geometry getGeometrySelection(Node toolNode, Geometry geom) { + Mesh mesh = geom.getMesh(); + if (mesh == null) { + return null; + } + Geometry selectionGeometry = new Geometry("selection_geometry_sceneviewer", mesh); + selectionGeometry.setLocalTransform(geom.getWorldTransform()); + toolNode.attachChild(selectionGeometry); + return selectionGeometry; + } + + protected Geometry getBoxSelection(Node toolNode, Spatial geom) { + BoundingVolume bound = geom.getWorldBound(); + if (bound instanceof BoundingBox) { + BoundingBox bbox = (BoundingBox) bound; + Vector3f extent = new Vector3f(); + bbox.getExtent(extent); + WireBox wireBox=new WireBox(); + wireBox.fromBoundingBox(bbox); + Geometry selectionGeometry = new Geometry("selection_geometry_sceneviewer", wireBox); + selectionGeometry.setLocalTransform(geom.getWorldTransform()); + toolNode.attachChild(selectionGeometry); + return selectionGeometry; + } + return null; + } + + protected Spatial getPhysicsSelection(Node toolNode, Spatial geom) { + PhysicsCollisionObject control = geom.getControl(RigidBodyControl.class); + if (control == null) { + control = geom.getControl(VehicleControl.class); + } + if (control == null) { + control = geom.getControl(GhostControl.class); + } + if (control == null) { + control = geom.getControl(CharacterControl.class); + } + if (control == null) { + return null; + } + Spatial selectionGeometry = DebugShapeFactory.getDebugShape(control.getCollisionShape()); + if (selectionGeometry != null) { + selectionGeometry.setLocalTransform(geom.getWorldTransform()); + toolNode.attachChild(selectionGeometry); + return selectionGeometry; + } + return null; + } + + protected void detachSelectionShape() { + if (selectionShape != null) { + selectionShape.removeFromParent(); + selectionShape = null; + } + } + + + public Camera getCamera() { + return camera; + } + + public void setCamera(Camera camera) { + this.camera = camera; + } + + + +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_inout.png b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_inout.png new file mode 100644 index 000000000..82ca9d58f Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_inout.png differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_out.png b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_out.png new file mode 100644 index 000000000..0609b3e1a Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_out.png differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_rotate_clockwise.png b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_rotate_clockwise.png new file mode 100644 index 000000000..11b6dd34e Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_arrow_rotate_clockwise.png differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_select.png b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_select.png new file mode 100644 index 000000000..23cb91792 Binary files /dev/null and b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/icon_select.png differ diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java new file mode 100644 index 000000000..c897d0aeb --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java @@ -0,0 +1,160 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer.tools; + +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.scenecomposer.SceneEditTool; +import com.jme3.material.Material; +import com.jme3.math.FastMath; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial; +import com.jme3.scene.shape.Quad; +import org.openide.loaders.DataObject; + +/** + * Move an object. + * When created, it generates a quad that will lie along a plane + * that the user selects for moving on. When the mouse is over + * the axisMarker, it will highlight the plane that it is over: XY,XZ,YZ. + * When clicked and then dragged, the selected object will move along that + * plane. + * @author Brent Owens + */ +public class MoveTool extends SceneEditTool { + + private Vector3f pickedPlane; + private Vector3f startLoc; + private Vector3f lastLoc; + private boolean wasDragging = false; + private Vector3f offset; + private Node plane; + Material pinkMat; + private final Quaternion XY = new Quaternion().fromAngleAxis(0, new Vector3f(1,0,0)); + private final Quaternion YZ = new Quaternion().fromAngleAxis(-FastMath.PI/2, new Vector3f(0,1,0)); + private final Quaternion XZ = new Quaternion().fromAngleAxis(FastMath.PI/2, new Vector3f(1,0,0)); + + + public MoveTool() { + axisPickType = AxisMarkerPickType.planeOnly; + setOverrideCameraControl(true); + + float size = 1000; + Geometry g = new Geometry("plane", new Quad(size, size)); + g.setLocalTranslation(-size/2, -size/2, 0); + plane = new Node(); + plane.attachChild(g); + } + + + + @Override + public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) { + if (!pressed) { + setDefaultAxisMarkerColors(); + pickedPlane = null; // mouse released, reset selection + offset = null; + if (wasDragging) { + actionPerformed(new MoveUndo(selectedSpatial, startLoc, lastLoc)); + wasDragging = false; + } + } + } + + @Override + public void actionSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) { + + } + + @Override + public void mouseMoved(Vector2f screenCoord) { + if (pickedPlane == null) { + highlightAxisMarker(camera, screenCoord, axisPickType); + } + else { + pickedPlane = null; + offset = null; + } + } + + @Override + public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + if (!pressed) { + setDefaultAxisMarkerColors(); + pickedPlane = null; // mouse released, reset selection + offset = null; + if (wasDragging) { + actionPerformed(new MoveUndo(selectedSpatial, startLoc, lastLoc)); + wasDragging = false; + } + return; + } + + if (selectedSpatial == null) + return; + if (pickedPlane == null) { + pickedPlane = pickAxisMarker(camera, screenCoord, axisPickType); + if (pickedPlane == null) + return; + startLoc = selectedSpatial.getLocalTranslation().clone(); + + if (pickedPlane.equals(new Vector3f(1,1,0))) + plane.setLocalRotation(XY); + else if (pickedPlane.equals(new Vector3f(1,0,1))) + plane.setLocalRotation(XZ); + else if (pickedPlane.equals(new Vector3f(0,1,1))) + plane.setLocalRotation(YZ); + plane.setLocalTranslation(startLoc); + } + + Vector3f planeHit = pickWorldLocation(camera, screenCoord, plane); + if (planeHit == null) + return; + + if (offset == null) + offset = planeHit.subtract(startLoc); // get the offset when we start so it doesn't jump + + Vector3f newPos = planeHit.subtract(offset); + lastLoc = newPos; + selectedSpatial.setLocalTranslation(newPos); + updateToolsTransformation(selectedSpatial); + + wasDragging = true; + } + + @Override + public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + + } + + private class MoveUndo extends AbstractUndoableSceneEdit { + + private Spatial spatial; + private Vector3f before,after; + + MoveUndo(Spatial spatial, Vector3f before, Vector3f after) { + this.spatial = spatial; + this.before = before; + this.after = after; + } + + @Override + public void sceneUndo() { + spatial.setLocalTranslation(before); + toolController.selectedSpatialTransformed(); + } + + @Override + public void sceneRedo() { + spatial.setLocalTranslation(after); + toolController.selectedSpatialTransformed(); + } + + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java new file mode 100644 index 000000000..299900d86 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java @@ -0,0 +1,81 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.jme3.gde.scenecomposer.tools; + +import com.jme3.gde.core.scene.SceneApplication; +import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; +import com.jme3.gde.scenecomposer.SceneEditTool; +import com.jme3.math.Quaternion; +import com.jme3.math.Vector2f; +import com.jme3.math.Vector3f; +import com.jme3.scene.Spatial; +import java.util.concurrent.Callable; +import org.openide.loaders.DataObject; + +/** + * + * @author Brent Owens + */ +public class SelectTool extends SceneEditTool { + + protected Spatial selected; + private boolean wasDragging = false; + + + @Override + public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) { + if (!pressed && !wasDragging) { + // mouse released and wasn't dragging, select a new spatial + final Spatial result = pickWorldSpatial(getCamera(), screenCoord, rootNode); + + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + if (result != null) { + SceneApplication.getApplication().setCurrentFileNode(rootNode.getChild(result)); + } else { + SceneApplication.getApplication().setCurrentFileNode(rootNode); + } + } + }); + + if (result != null) { + replaceSelectionShape(result); + updateToolsTransformation(selectedSpatial); + } + + } + + if (!pressed) { + wasDragging = false; + } + } + + @Override + public void actionSecondary(final Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) { + if (!pressed && !wasDragging) { + final Vector3f result = pickWorldLocation(getCamera(), screenCoord, rootNode); + toolController.doSetCursorLocation(result); + } + if (!pressed) { + wasDragging = false; + } + } + + @Override + public void mouseMoved(Vector2f screenCoord) { + + } + + @Override + public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + wasDragging = pressed; + } + + @Override + public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + wasDragging = pressed; + } + +} diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java index 1f596d1bf..9b5e5dec9 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java @@ -32,13 +32,10 @@ package com.jme3.gde.terraineditor; import com.jme3.app.Application; -import com.jme3.app.state.AppStateManager; import com.jme3.collision.CollisionResult; import com.jme3.collision.CollisionResults; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.scene.controller.AbstractCameraController; -import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; -import com.jme3.input.InputManager; import com.jme3.input.KeyInput; import com.jme3.input.event.KeyInputEvent; import com.jme3.input.event.MouseMotionEvent; @@ -46,7 +43,6 @@ import com.jme3.math.Ray; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; -import java.util.logging.Logger; /** @@ -177,7 +173,7 @@ public class TerrainCameraController extends AbstractCameraController { } @Override - protected void checkClick(int button) { + protected void checkClick(int button, boolean pressed) { if (button == 0) { if (isTerrainEditButtonEnabled() && !forceCameraControls) { if (leftMouse) diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java index 4ae6ab997..fe5668450 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java @@ -42,9 +42,8 @@ import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.core.sceneexplorer.nodes.JmeTerrainQuad; import com.jme3.gde.core.sceneexplorer.nodes.NodeUtility; import com.jme3.gde.core.properties.TexturePropertyEditor; -import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; -import com.jme3.gde.core.undoredo.SceneUndoRedoManager; import com.jme3.gde.core.util.DataObjectSaveNode; +import com.jme3.gde.core.util.ToggleButtonGroup; import com.jme3.gde.terraineditor.sky.SkyboxWizardAction; import com.jme3.gde.terraineditor.tools.EraseTerrainTool; import com.jme3.gde.terraineditor.tools.LevelTerrainTool; @@ -82,8 +81,6 @@ import javax.swing.filechooser.FileSystemView; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; -import javax.swing.undo.CannotRedoException; -import javax.swing.undo.CannotUndoException; import jme3tools.converters.ImageToAwt; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; @@ -104,7 +101,6 @@ import org.openide.explorer.ExplorerUtils; import org.openide.nodes.NodeListener; import org.openide.util.Exceptions; import org.openide.util.HelpCtx; -import org.openide.util.Lookup; import org.openide.util.Lookup.Result; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java index cf94a0f5f..1352dd967 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java @@ -38,13 +38,8 @@ import com.jme3.gde.core.scene.controller.SceneToolController; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.terraineditor.tools.TerrainTool; -import com.jme3.material.Material; -import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; -import com.jme3.scene.Geometry; -import com.jme3.scene.Mesh; import com.jme3.scene.Node; -import com.jme3.scene.shape.Sphere; import java.util.concurrent.Callable; /** diff --git a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java index 6e6ba8885..553f9fa37 100644 --- a/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java +++ b/sdk/jme3-vehicle-creator/src/com/jme3/gde/vehiclecreator/VehicleCreatorCameraController.java @@ -57,7 +57,7 @@ public class VehicleCreatorCameraController extends AbstractCameraController { } @Override - protected void checkClick(int button) { + protected void checkClick(int button, boolean pressed) { } /**