From f6b7c3819a6bb0e062d7a81dac020eb04b64ee10 Mon Sep 17 00:00:00 2001 From: Maselbas Date: Sun, 10 May 2015 01:57:27 +0200 Subject: [PATCH 01/29] SDK SceneComposer : added abstract ShortcutTool class that extends SceneEditTool - added a shortcutManager that provide some usefull methodes for ShortcutTools. Also handle activation of shortcuts. - wip : implementation of the MoveShortcut (based on the same shortcut provided by the selectTool) using ShortcutTool and the ShortcutManager. - modified the SceneComposerToolController to work with the ShortcutManager & ShortcutTool --- .../SceneComposerToolController.java | 48 ++++- .../tools/shortcuts/MoveShortcut.java | 137 ++++++++++++ .../tools/shortcuts/ShortcutManager.java | 197 ++++++++++++++++++ .../tools/shortcuts/ShortcutTool.java | 29 +++ 4 files changed, 403 insertions(+), 8 deletions(-) create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutTool.java diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java index 50b6d5cfe..71fee925b 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java @@ -11,6 +11,7 @@ import com.jme3.gde.core.scene.controller.SceneToolController; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.scenecomposer.tools.PickManager; +import com.jme3.gde.scenecomposer.tools.shortcuts.ShortcutManager; import com.jme3.input.event.KeyInputEvent; import com.jme3.light.Light; import com.jme3.light.PointLight; @@ -31,6 +32,7 @@ import com.jme3.scene.control.Control; import com.jme3.scene.shape.Quad; import com.jme3.texture.Texture; import java.util.concurrent.Callable; +import org.openide.util.Lookup; /** * @@ -184,7 +186,11 @@ public class SceneComposerToolController extends SceneToolController { * @param camera */ public void doEditToolActivatedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) { - if (editTool != null) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + + if (scm.isActive()) { + scm.getActiveShortcut().actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } else if (editTool != null) { editTool.setCamera(camera); editTool.actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } @@ -198,36 +204,62 @@ public class SceneComposerToolController extends SceneToolController { * @param camera */ public void doEditToolActivatedSecondary(Vector2f mouseLoc, boolean pressed, Camera camera) { - if (editTool != null) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + + if (scm.isActive()) { + scm.getActiveShortcut().actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } else if (editTool != null) { editTool.setCamera(camera); editTool.actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } } public void doEditToolMoved(Vector2f mouseLoc, Camera camera) { - if (editTool != null) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + + if (scm.isActive()) { + scm.getActiveShortcut().mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial); + } else if (editTool != null) { editTool.setCamera(camera); editTool.mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial); } } public void doEditToolDraggedPrimary(Vector2f mouseLoc, boolean pressed, Camera camera) { - if (editTool != null) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + + if (scm.isActive()) { + scm.getActiveShortcut().draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } else 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) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + + if (scm.isActive()) { + scm.getActiveShortcut().draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); + } else if (editTool != null) { editTool.setCamera(camera); editTool.draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } } - void doKeyPressed(KeyInputEvent kie) { - if (editTool != null) { - editTool.keyPressed(kie); + public void doKeyPressed(KeyInputEvent kie) { + ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); + + if (scm.isActive()) { + scm.doKeyPressed(kie); + } else { + if (scm.activateShortcut(kie)) { + scm.getActiveShortcut().activate(manager, toolsNode, onTopToolsNode, selected, this); + } else { + if (editTool != null) { + editTool.keyPressed(kie); + } + } } } diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java new file mode 100644 index 000000000..e59fec76e --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java @@ -0,0 +1,137 @@ +/* + * 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.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 Vector3f initalLocation; + private Vector3f finalLocation; + private PickManager pickManager; + + @Override + public boolean isActivableBy(KeyInputEvent kie) { + return kie.getKeyCode() == KeyInput.KEY_G; + } + + @Override + public void cancel() { + spatial.setLocalTranslation(initalLocation); + terminate(); + } + + private void apply() { + // TODO creat UNDO/REDO + 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(); + numberBuilder = new StringBuilder(); + if (selectedSpatial == null) { + terminate(); + } else { + spatial = selectedSpatial; + initalLocation = spatial.getLocalTranslation(); + currentAxis = new Vector3f().set(Vector3f.UNIT_XYZ); + + pickManager = Lookup.getDefault().lookup(PickManager.class); + ///pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord); + } + } + + @Override + public void keyPressed(KeyInputEvent kie) { + if (kie.isPressed()) { + + /* + ShortcutTool otherShortcut = Lookup.getDefault().lookup(ShortcutManager.class).getActivableShortcut(kie); + if(otherShortcut != null){ + Lookup.getDefault().lookup(ShortcutManager.class).setShortCut(otherShortcut); + }*/ + Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie); + + boolean axisChanged = ShortcutManager.checkAxisKey(kie, currentAxis); + 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 || numberChanged) { + //update transformation + float number = ShortcutManager.getNumberkey(numberBuilder); + Vector3f translation = currentAxis.mult(number); + finalLocation = initalLocation.add(translation); + spatial.setLocalTranslation(finalLocation); + + } + + } + } + + @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) { + pickManager.updatePick(camera, screenCoord); + /* PickManager pickManager = Lookup.getDefault().lookup(PickManager.class); + if (toolController.isSnapToScene()) { + moveManager.setAlternativePickTarget(rootNode.getLookup().lookup(Node.class)); + } + // free form translation + moveManager.move(camera, screenCoord, axis, toolController.isSnapToGrid());*/ + } + + @Override + public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { + if (pressed) { + cancel(); + } + } + +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java new file mode 100644 index 000000000..38548087d --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java @@ -0,0 +1,197 @@ +/* + * 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 shortcutList; + + public ShortcutManager() { + shortcutList = new ArrayList(); + shortcutList.add(new MoveShortcut()); + } + + /* + Methodes + */ + public void terminate() { + currentShortcut = null; + } + + public boolean isActive() { + return currentShortcut != null; + } + + public void setShortCut(ShortcutTool shortcut) { + if (isActive()) { + currentShortcut.cancel(); + } + currentShortcut = shortcut; + } + + public ShortcutTool getActivableShortcut(KeyInputEvent kie) { + for (ShortcutTool s : shortcutList) { + if (s != currentShortcut) { + if (s.isActivableBy(kie)) { + return s; + } + } + } + return null; + } + + public ShortcutTool getActiveShortcut() { + return currentShortcut; + } + + public boolean canActivateShortcut(KeyInputEvent kie) { + return getActivableShortcut(kie) != null; + } + + public boolean activateShortcut(KeyInputEvent kie) { + currentShortcut = getActivableShortcut(kie); + return isActive(); + } + + public void doKeyPressed(KeyInputEvent kie) { + ///todo check commande key + if (isActive()) { + currentShortcut.keyPressed(kie); + } + } + + /* + STATIC + */ + public static boolean checkEnterHit(KeyInputEvent kie) { + if (kie.getKeyCode() == KeyInput.KEY_RETURN) { + return true; + } + return false; + } + + public static boolean checkEscHit(KeyInputEvent kie) { + if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) { + return true; + } + return false; + } + + public static boolean checkCtrlHit(KeyInputEvent kie) { + if (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL) { + return true; + } + return false; + } + + public static boolean checkShiftHit(KeyInputEvent kie) { + if (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT) { + return true; + } + return false; + } + + public static boolean checkAltHit(KeyInputEvent kie) { + if (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU) { + return true; + } + return false; + } + + 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; + } + + public static float getNumberkey(StringBuilder numberBuilder) { + if (numberBuilder.length() == 0) { + return 0; + } else { + return new Float(numberBuilder.toString()); + } + } + + public static boolean checkAxisKey(KeyInputEvent kie, Vector3f axisStore) { + if (kie.getKeyCode() == KeyInput.KEY_X) { + axisStore = Vector3f.UNIT_X; + return true; + } else if (kie.getKeyCode() == KeyInput.KEY_Y) { + axisStore = Vector3f.UNIT_Y; + return true; + } else if (kie.getKeyCode() == KeyInput.KEY_Z) { + axisStore = Vector3f.UNIT_Z; + return true; + } + return false; + } + +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutTool.java new file mode 100644 index 000000000..9b094fc1d --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutTool.java @@ -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); + +} From 92ab8b806035d89329e0b8ff64e16d5a0615fbef Mon Sep 17 00:00:00 2001 From: Maselbas Date: Thu, 14 May 2015 18:55:07 +0200 Subject: [PATCH 02/29] SDK SceneComposer : small modifications on the PickManager, now the camera rotation isn't cloned so it's no more necessary to update the rotation before the updataPick() --- .../jme3/gde/scenecomposer/tools/PickManager.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java index 22fa8478a..af4f11fe5 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/PickManager.java @@ -33,9 +33,9 @@ public class PickManager { private Spatial spatial; private SceneComposerToolController.TransformationType transformationType; - protected static final Quaternion PLANE_XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0)); - protected static final Quaternion PLANE_YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));//YAW090 - protected static final Quaternion PLANE_XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0)); //PITCH090 + public static final Quaternion PLANE_XY = new Quaternion().fromAngleAxis(0, new Vector3f(1, 0, 0)); + public static final Quaternion PLANE_YZ = new Quaternion().fromAngleAxis(-FastMath.PI / 2, new Vector3f(0, 1, 0));//YAW090 + public static final Quaternion PLANE_XZ = new Quaternion().fromAngleAxis(FastMath.PI / 2, new Vector3f(1, 0, 0)); //PITCH090 public PickManager() { @@ -75,7 +75,7 @@ public class PickManager { origineRotation = new Quaternion(Quaternion.IDENTITY); } else if (transformationType == SceneComposerToolController.TransformationType.camera) { rot.set(camera.getRotation()); - origineRotation = camera.getRotation().clone(); + origineRotation = camera.getRotation(); } plane.setLocalRotation(rot); } @@ -87,10 +87,6 @@ public class PickManager { * @return true if the the new picked location is set, else return false. */ public boolean updatePick(Camera camera, Vector2f screenCoord) { - if(transformationType == SceneComposerToolController.TransformationType.camera){ - origineRotation = camera.getRotation(); - plane.setLocalRotation(camera.getRotation()); - } finalPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null); return finalPickLoc != null; } From e27b8a5739cc5e6fe7e77875f705be60ca828d8f Mon Sep 17 00:00:00 2001 From: Maselbas Date: Thu, 14 May 2015 19:02:35 +0200 Subject: [PATCH 03/29] SDK SceneComposer : bugfix in the ShortcutManager, prevent from setting the currentShorcut to NULL when there are no new activable shortcuts --- .../tools/shortcuts/ShortcutManager.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java index 38548087d..5dad38d7c 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java @@ -66,8 +66,11 @@ public class ShortcutManager { } public boolean activateShortcut(KeyInputEvent kie) { - currentShortcut = getActivableShortcut(kie); - return isActive(); + ShortcutTool newShortcut = getActivableShortcut(kie); + if(newShortcut != null){ + currentShortcut = newShortcut; + } + return newShortcut != null; } public void doKeyPressed(KeyInputEvent kie) { @@ -182,13 +185,13 @@ public class ShortcutManager { public static boolean checkAxisKey(KeyInputEvent kie, Vector3f axisStore) { if (kie.getKeyCode() == KeyInput.KEY_X) { - axisStore = Vector3f.UNIT_X; + axisStore.set(Vector3f.UNIT_X); return true; } else if (kie.getKeyCode() == KeyInput.KEY_Y) { - axisStore = Vector3f.UNIT_Y; + axisStore.set(Vector3f.UNIT_Y); return true; } else if (kie.getKeyCode() == KeyInput.KEY_Z) { - axisStore = Vector3f.UNIT_Z; + axisStore.set(Vector3f.UNIT_Z); return true; } return false; From fb44f5fb7bfd58a971cec4838f314d18204559cd Mon Sep 17 00:00:00 2001 From: Maselbas Date: Thu, 14 May 2015 19:09:07 +0200 Subject: [PATCH 04/29] SDK SceneComposer : Added the new Move Shortcut, you can use this shortcut with all others tools --- .../SceneComposerToolController.java | 7 +- .../tools/shortcuts/MoveShortcut.java | 95 ++++++++++++++----- 2 files changed, 77 insertions(+), 25 deletions(-) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java index 71fee925b..00d15bb2f 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java @@ -189,6 +189,7 @@ public class SceneComposerToolController extends SceneToolController { ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); if (scm.isActive()) { + scm.getActiveShortcut().setCamera(camera); scm.getActiveShortcut().actionPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } else if (editTool != null) { editTool.setCamera(camera); @@ -207,6 +208,7 @@ public class SceneComposerToolController extends SceneToolController { ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); if (scm.isActive()) { + scm.getActiveShortcut().setCamera(camera); scm.getActiveShortcut().actionSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } else if (editTool != null) { editTool.setCamera(camera); @@ -218,6 +220,7 @@ public class SceneComposerToolController extends SceneToolController { ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); if (scm.isActive()) { + scm.getActiveShortcut().setCamera(camera); scm.getActiveShortcut().mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial); } else if (editTool != null) { editTool.setCamera(camera); @@ -229,6 +232,7 @@ public class SceneComposerToolController extends SceneToolController { ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); if (scm.isActive()) { + scm.getActiveShortcut().setCamera(camera); scm.getActiveShortcut().draggedPrimary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } else if (editTool != null) { editTool.setCamera(camera); @@ -240,6 +244,7 @@ public class SceneComposerToolController extends SceneToolController { ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); if (scm.isActive()) { + scm.getActiveShortcut().setCamera(null); scm.getActiveShortcut().draggedSecondary(mouseLoc, pressed, rootNode, editorController.getCurrentDataObject()); } else if (editTool != null) { editTool.setCamera(camera); @@ -249,7 +254,7 @@ public class SceneComposerToolController extends SceneToolController { public void doKeyPressed(KeyInputEvent kie) { ShortcutManager scm = Lookup.getDefault().lookup(ShortcutManager.class); - + if (scm.isActive()) { scm.doKeyPressed(kie); } else { diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java index e59fec76e..3b0f22562 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java @@ -12,6 +12,7 @@ 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; @@ -28,18 +29,21 @@ public class MoveShortcut extends ShortcutTool { private Vector3f currentAxis; private StringBuilder numberBuilder; private Spatial spatial; - private Vector3f initalLocation; private Vector3f finalLocation; 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(initalLocation); + spatial.setLocalTranslation(startPosition); terminate(); } @@ -48,6 +52,14 @@ public class MoveShortcut extends ShortcutTool { 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. @@ -56,27 +68,23 @@ public class MoveShortcut extends ShortcutTool { if (selectedSpatial == null) { terminate(); } else { - spatial = selectedSpatial; - initalLocation = spatial.getLocalTranslation(); - currentAxis = new Vector3f().set(Vector3f.UNIT_XYZ); - - pickManager = Lookup.getDefault().lookup(PickManager.class); - ///pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord); + init(selectedSpatial); } } @Override public void keyPressed(KeyInputEvent kie) { if (kie.isPressed()) { - - /* - ShortcutTool otherShortcut = Lookup.getDefault().lookup(ShortcutManager.class).getActivableShortcut(kie); - if(otherShortcut != null){ - Lookup.getDefault().lookup(ShortcutManager.class).setShortCut(otherShortcut); - }*/ + System.out.println(kie); Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie); - boolean axisChanged = ShortcutManager.checkAxisKey(kie, currentAxis); + Vector3f axis = new Vector3f(); + boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis); + if (axisChanged) { + currentAxis = axis; + System.out.println("AXIS : " + currentAxis); + + } boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder); boolean enterHit = ShortcutManager.checkEnterHit(kie); boolean escHit = ShortcutManager.checkEscHit(kie); @@ -85,11 +93,24 @@ public class MoveShortcut extends ShortcutTool { cancel(); } else if (enterHit) { apply(); + } else if (axisChanged && pickEnabled) { + //update pick manager + + if (currentAxis.equals(Vector3f.UNIT_X)) { + System.out.println("setTransformation X"); + pickManager.setTransformation(PickManager.PLANE_XY, getTransformType(), camera); + } else if (currentAxis.equals(Vector3f.UNIT_Y)) { + System.out.println("setTransformation Y"); + pickManager.setTransformation(PickManager.PLANE_YZ, getTransformType(), camera); + } else if (currentAxis.equals(Vector3f.UNIT_Z)) { + System.out.println("setTransformation Z"); + pickManager.setTransformation(PickManager.PLANE_XZ, getTransformType(), camera); + } } else if (axisChanged || numberChanged) { //update transformation float number = ShortcutManager.getNumberkey(numberBuilder); Vector3f translation = currentAxis.mult(number); - finalLocation = initalLocation.add(translation); + finalLocation = startPosition.add(translation); spatial.setLocalTranslation(finalLocation); } @@ -99,7 +120,7 @@ public class MoveShortcut extends ShortcutTool { @Override public void actionPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject dataObject) { - if (!pressed) { + if (pressed) { apply(); } } @@ -113,13 +134,39 @@ public class MoveShortcut extends ShortcutTool { @Override public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial) { - pickManager.updatePick(camera, screenCoord); - /* PickManager pickManager = Lookup.getDefault().lookup(PickManager.class); - if (toolController.isSnapToScene()) { - moveManager.setAlternativePickTarget(rootNode.getLookup().lookup(Node.class)); - } - // free form translation - moveManager.move(camera, screenCoord, axis, toolController.isSnapToGrid());*/ + + 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 From 6ef33e4c10750705d7c407e6c92fda9d62dc7b45 Mon Sep 17 00:00:00 2001 From: Maselbas Date: Fri, 15 May 2015 17:57:47 +0200 Subject: [PATCH 05/29] SDK SceneComposer : added UndoRedo for the MoveShortcut --- .../tools/shortcuts/MoveShortcut.java | 60 +++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java index 3b0f22562..a4dabb66b 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java @@ -6,8 +6,11 @@ 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; @@ -29,7 +32,6 @@ public class MoveShortcut extends ShortcutTool { private Vector3f currentAxis; private StringBuilder numberBuilder; private Spatial spatial; - private Vector3f finalLocation; private PickManager pickManager; private boolean pickEnabled; private Vector3f startPosition; @@ -48,7 +50,7 @@ public class MoveShortcut extends ShortcutTool { } private void apply() { - // TODO creat UNDO/REDO + actionPerformed(new MoveUndo(toolController.getSelectedSpatial(), startPosition, finalPosition)); terminate(); } @@ -110,8 +112,8 @@ public class MoveShortcut extends ShortcutTool { //update transformation float number = ShortcutManager.getNumberkey(numberBuilder); Vector3f translation = currentAxis.mult(number); - finalLocation = startPosition.add(translation); - spatial.setLocalTranslation(finalLocation); + finalPosition = startPosition.add(translation); + spatial.setLocalTranslation(finalPosition); } @@ -171,7 +173,9 @@ public class MoveShortcut extends ShortcutTool { @Override public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + if (pressed) { + apply(); + } } @Override @@ -180,5 +184,51 @@ public class MoveShortcut extends ShortcutTool { 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); + } + } } From 1f4ee34de8c4110da418d09ae1e7983ab499e82c Mon Sep 17 00:00:00 2001 From: Maselbas Date: Fri, 15 May 2015 18:43:45 +0200 Subject: [PATCH 06/29] SDK SceneComposer : add Rotate and Scale Shortcut, plus done some clean up into the MoveShorcut --- .../tools/shortcuts/MoveShortcut.java | 7 - .../tools/shortcuts/RotateShortcut.java | 189 +++++++++++++++++ .../tools/shortcuts/ScaleShortcut.java | 199 ++++++++++++++++++ .../tools/shortcuts/ShortcutManager.java | 11 +- 4 files changed, 398 insertions(+), 8 deletions(-) create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java index a4dabb66b..62cc70612 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java @@ -15,7 +15,6 @@ 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; @@ -77,15 +76,12 @@ public class MoveShortcut extends ShortcutTool { @Override public void keyPressed(KeyInputEvent kie) { if (kie.isPressed()) { - System.out.println(kie); Lookup.getDefault().lookup(ShortcutManager.class).activateShortcut(kie); Vector3f axis = new Vector3f(); boolean axisChanged = ShortcutManager.checkAxisKey(kie, axis); if (axisChanged) { currentAxis = axis; - System.out.println("AXIS : " + currentAxis); - } boolean numberChanged = ShortcutManager.checkNumberKey(kie, numberBuilder); boolean enterHit = ShortcutManager.checkEnterHit(kie); @@ -99,13 +95,10 @@ public class MoveShortcut extends ShortcutTool { //update pick manager if (currentAxis.equals(Vector3f.UNIT_X)) { - System.out.println("setTransformation X"); pickManager.setTransformation(PickManager.PLANE_XY, getTransformType(), camera); } else if (currentAxis.equals(Vector3f.UNIT_Y)) { - System.out.println("setTransformation Y"); pickManager.setTransformation(PickManager.PLANE_YZ, getTransformType(), camera); } else if (currentAxis.equals(Vector3f.UNIT_Z)) { - System.out.println("setTransformation Z"); pickManager.setTransformation(PickManager.PLANE_XZ, getTransformType(), camera); } } else if (axisChanged || numberChanged) { diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java new file mode 100644 index 000000000..1fb445b59 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java @@ -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(); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java new file mode 100644 index 000000000..21966e385 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java @@ -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(); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java index 5dad38d7c..bdbcfbe9e 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java @@ -26,6 +26,8 @@ public class ShortcutManager { public ShortcutManager() { shortcutList = new ArrayList(); shortcutList.add(new MoveShortcut()); + shortcutList.add(new RotateShortcut()); + shortcutList.add(new ScaleShortcut()); } /* @@ -72,7 +74,14 @@ public class ShortcutManager { } return newShortcut != null; } - + + /** + * This should be called to trigger the currentShortcut.keyPressed() method. + * This method do a first check for command key used to provide isCtrlDown, + * isShiftDown ect.. to de + * + * @param kie + */ public void doKeyPressed(KeyInputEvent kie) { ///todo check commande key if (isActive()) { From e9b1972aca2fb217ba79955c6926b63a1a7799a4 Mon Sep 17 00:00:00 2001 From: Maselbas Date: Fri, 15 May 2015 18:47:14 +0200 Subject: [PATCH 07/29] SDK SceneComposer : clean up in the RotateTool, changed the name of the UndoableSceneEdit from ScaleUndo to RotateUndo --- .../com/jme3/gde/scenecomposer/tools/RotateTool.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/RotateTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/RotateTool.java index 21e9a56d8..e5a125771 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/RotateTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/RotateTool.java @@ -25,7 +25,6 @@ import org.openide.util.Lookup; public class RotateTool extends SceneEditTool { private Vector3f pickedMarker; - private Vector2f lastScreenCoord; private Quaternion startRotate; private Quaternion lastRotate; private boolean wasDragging = false; @@ -48,9 +47,8 @@ public class RotateTool extends SceneEditTool { if (!pressed) { setDefaultAxisMarkerColors(); pickedMarker = null; // mouse released, reset selection - lastScreenCoord = null; if (wasDragging) { - actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate)); + actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotate, lastRotate)); wasDragging = false; } pickManager.reset(); @@ -100,10 +98,9 @@ public class RotateTool extends SceneEditTool { if (!pressed) { setDefaultAxisMarkerColors(); pickedMarker = null; // mouse released, reset selection - lastScreenCoord = null; if (wasDragging) { - actionPerformed(new ScaleUndo(toolController.getSelectedSpatial(), startRotate, lastRotate)); + actionPerformed(new RotateUndo(toolController.getSelectedSpatial(), startRotate, lastRotate)); wasDragging = false; } pickManager.reset(); @@ -138,12 +135,12 @@ public class RotateTool extends SceneEditTool { } } - private class ScaleUndo extends AbstractUndoableSceneEdit { + private class RotateUndo extends AbstractUndoableSceneEdit { private Spatial spatial; private Quaternion before, after; - ScaleUndo(Spatial spatial, Quaternion before, Quaternion after) { + RotateUndo(Spatial spatial, Quaternion before, Quaternion after) { this.spatial = spatial; this.before = before; this.after = after; From bbca035a43abd5e77f1859c81418ceca8f329c1a Mon Sep 17 00:00:00 2001 From: Maselbas Date: Fri, 15 May 2015 20:36:55 +0200 Subject: [PATCH 08/29] SDK SceneComposer : all shortcuts tool are now outside of the selectTool, - added the Delete and Duplicate shortcut - deleted the MoveManager - clean up the SelectTool (removed old shortCuts) - now the ShortcutManager can also provide to SorthcutTools the state of ctr, alt and shift key --- .../gde/scenecomposer/tools/MoveManager.java | 204 ----- .../gde/scenecomposer/tools/SelectTool.java | 694 +----------------- .../tools/shortcuts/DeleteShortcut.java | 123 ++++ .../tools/shortcuts/DuplicateShortcut.java | 141 ++++ .../tools/shortcuts/ShortcutManager.java | 52 +- 5 files changed, 342 insertions(+), 872 deletions(-) delete mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveManager.java create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java create mode 100644 sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DuplicateShortcut.java diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveManager.java deleted file mode 100644 index d7b92db91..000000000 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveManager.java +++ /dev/null @@ -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); - } - } -} 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 index 43d3cba3a..87f3c283f 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/SelectTool.java @@ -8,425 +8,51 @@ import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent; -import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; import com.jme3.gde.scenecomposer.SceneEditTool; -import com.jme3.input.KeyInput; -import com.jme3.input.event.KeyInputEvent; -import com.jme3.math.FastMath; -import com.jme3.math.Quaternion; import com.jme3.math.Vector2f; -import com.jme3.math.Vector3f; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import com.jme3.terrain.Terrain; import org.openide.loaders.DataObject; -import org.openide.util.Lookup; /** - * This duplicates the Blender manipulate tool. - * It supports quick access to Grab, Rotate, and Scale operations - * by typing one of the following keys: 'g', 'r', or 's' - * Those keys can be followed by an axis key to specify what axis - * to perform the transformation: x, y, z - * Then, after the operation and axis are selected, you can type in a - * number and then hit 'enter' to complete the transformation. - * - * Ctrl+Shift+D will duplicate an object - * X will delete an object - * - * ITEMS TO FINISH: - * 1) fixed scale and rotation values by holding Ctrl and dragging mouse - * BUGS: - * 1) window always needs focus from primary click when it should focus from secondary and middle mouse - * + * This duplicates the Blender manipulate tool. It supports quick access to + * Grab, Rotate, and Scale operations by typing one of the following keys: 'g', + * 'r', or 's' Those keys can be followed by an axis key to specify what axis to + * perform the transformation: x, y, z Then, after the operation and axis are + * selected, you can type in a number and then hit 'enter' to complete the + * transformation. + * + * Ctrl+Shift+D will duplicate an object X will delete an object + * + * ITEMS TO FINISH: 1) fixed scale and rotation values by holding Ctrl and + * dragging mouse BUGS: 1) window always needs focus from primary click when it + * should focus from secondary and middle mouse + * * @author Brent Owens */ public class SelectTool extends SceneEditTool { - private enum State { - - translate, rotate, scale - }; - private State currentState = null; - private Vector3f currentAxis = Vector3f.UNIT_XYZ; - private StringBuilder numberBuilder = new StringBuilder(); // gets appended with numbers - private Quaternion startRot; - private Vector3f startTrans; - private Vector3f startScale; - private boolean wasDraggingL = false; private boolean wasDraggingR = false; private boolean wasDownR = false; - private boolean ctrlDown = false; - private boolean shiftDown = false; - private boolean altDown = false; - private MoveManager.MoveUndo moving; - private ScaleUndo scaling; - private RotateUndo rotating; - private Vector2f startMouseCoord; // for scaling and rotation - private Vector2f startSelectedCoord; // for scaling and rotation - private float lastRotAngle; // used for rotation /** - * This is stateful: - * First it checks for a command (rotate, translate, delete, etc..) - * Then it checks for an axis (x,y,z) - * Then it checks for a number (user typed a number - * Then, finally, it checks if Enter was hit. - * + * This is stateful: First it checks for a command (rotate, translate, + * delete, etc..) Then it checks for an axis (x,y,z) Then it checks for a + * number (user typed a number Then, finally, it checks if Enter was hit. + * * If either of the commands was actioned, the preceeding states/axis/amount - * will be reset. For example if the user types: G Y 2 R - * Then it will: - * 1) Set state as 'Translate' for the G (grab) - * 2) Set the axis as 'Y'; it will translate along the Y axis - * 3) Distance will be 2, when the 2 key is hit - * 4) Distance, Axis, and state are then reset because a new state was set: Rotate - * it won't actually translate because 'Enter' was not hit and 'R' reset the state. - * + * will be reset. For example if the user types: G Y 2 R Then it will: 1) + * Set state as 'Translate' for the G (grab) 2) Set the axis as 'Y'; it will + * translate along the Y axis 3) Distance will be 2, when the 2 key is hit + * 4) Distance, Axis, and state are then reset because a new state was set: + * Rotate it won't actually translate because 'Enter' was not hit and 'R' + * reset the state. + * */ - @Override - public void keyPressed(KeyInputEvent kie) { - - checkModificatorKeys(kie); // alt,shift,ctrl - Spatial selected = toolController.getSelectedSpatial(); - - if (selected == null) { - return; // only do anything if a spatial is selected - } - // key released - if (kie.isPressed()) { - boolean commandUsed = checkCommandKey(kie); - boolean stateChange = checkStateKey(kie); - boolean axisChange = checkAxisKey(kie); - boolean numberChange = checkNumberKey(kie); - boolean enterHit = checkEnterHit(kie); - boolean escHit = checkEscHit(kie); - - if (commandUsed) { - return; // commands take priority - } - if (stateChange) { - currentAxis = Vector3f.UNIT_XYZ; - numberBuilder = new StringBuilder(); - recordInitialState(selected); - } else if (axisChange) { - } else if (numberChange) { - } else if (enterHit) { - if (currentState != null && numberBuilder.length() > 0) { - applyKeyedChangeState(selected); - clearState(false); - } - } - - - // ----------------------- - // reset conditions below: - - if (escHit) { - if (moving != null) { - moving.sceneUndo(); - } - - moving = null; - clearState(); - } - - if (!stateChange && !axisChange && !numberChange && !enterHit && !escHit) { - // nothing valid was hit, reset the state - //clearState(); // this will be - } - } - } - - /** - * Abort any manipulations - */ - private void clearState() { - clearState(true); - } - - private void clearState(boolean resetSelected) { - Spatial selected = toolController.getSelectedSpatial(); - if (resetSelected && selected != null) { - // reset the transforms - if (startRot != null) { - selected.setLocalRotation(startRot); - } - if (startTrans != null) { - selected.setLocalTranslation(startTrans); - } - if (startScale != null) { - selected.setLocalScale(startScale); - } - } - currentState = null; - currentAxis = Vector3f.UNIT_XYZ; - numberBuilder = new StringBuilder(); - startRot = null; - startTrans = null; - startScale = null; - startMouseCoord = null; - startSelectedCoord = null; - lastRotAngle = 0; - } - - private void recordInitialState(Spatial selected) { - startRot = selected.getLocalRotation().clone(); - startTrans = selected.getLocalTranslation().clone(); - startScale = selected.getLocalScale().clone(); - } - - /** - * Applies the changes entered by a number, not by mouse. - * Translate: adds the value to the current local translation - * Rotate: rotates by X degrees - * Scale: scale the current scale by X amount - */ - private void applyKeyedChangeState(Spatial selected) { - Float value = null; - try { - value = new Float(numberBuilder.toString()); - } catch (NumberFormatException e) { - return; - } - - if (currentState == State.translate) { - MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class); - moveManager.moveAcross(currentAxis, value, toolController.isSnapToGrid()); - moving.setAfter(selected.getLocalTranslation()); - actionPerformed(moving); - moving = null; - } else if (currentState == State.scale) { - float x = 1, y = 1, z = 1; - if (currentAxis == Vector3f.UNIT_X) { - x = value; - } else if (currentAxis == Vector3f.UNIT_Y) { - y = value; - } else if (currentAxis == Vector3f.UNIT_Z) { - z = value; - } else if (currentAxis == Vector3f.UNIT_XYZ) { - x = value; - y = value; - z = value; - } - Vector3f before = selected.getLocalScale().clone(); - Vector3f after = selected.getLocalScale().multLocal(x, y, z); - selected.setLocalScale(after); - actionPerformed(new ScaleUndo(selected, before, after)); - } else if (currentState == State.rotate) { - float x = 0, y = 0, z = 0; - if (currentAxis == Vector3f.UNIT_X) { - x = 1; - } else if (currentAxis == Vector3f.UNIT_Y) { - y = 1; - } else if (currentAxis == Vector3f.UNIT_Z) { - z = 1; - } - Vector3f axis = new Vector3f(x, y, z); - Quaternion initialRot = selected.getLocalRotation().clone(); - Quaternion rot = new Quaternion(); - rot = rot.fromAngleAxis(value * FastMath.DEG_TO_RAD, axis); - selected.setLocalRotation(selected.getLocalRotation().mult(rot)); - RotateUndo undo = new RotateUndo(selected, initialRot, rot); - actionPerformed(undo); - toolController.updateSelection(null);// force a re-draw of the bbox shape - toolController.updateSelection(selected); - - } - clearState(false); - } - - private void checkModificatorKeys(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_LCONTROL || kie.getKeyCode() == KeyInput.KEY_RCONTROL) { - ctrlDown = kie.isPressed(); - } - - if (kie.getKeyCode() == KeyInput.KEY_LSHIFT || kie.getKeyCode() == KeyInput.KEY_RSHIFT) { - shiftDown = kie.isPressed(); - } - - if (kie.getKeyCode() == KeyInput.KEY_LMENU || kie.getKeyCode() == KeyInput.KEY_RMENU) { - altDown = kie.isPressed(); - } - } - - private boolean checkCommandKey(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_D) { - if (shiftDown) { - duplicateSelected(); - return true; - } - } - // X will only delete if the user isn't already transforming - if (currentState == null && kie.getKeyCode() == KeyInput.KEY_X) { - if (!ctrlDown && !shiftDown) { - deleteSelected(); - return true; - } - } - return false; - } - - private boolean checkStateKey(KeyInputEvent kie) { - Spatial selected = toolController.getSelectedSpatial(); - if (kie.getKeyCode() == KeyInput.KEY_G && !ctrlDown) { - currentState = State.translate; - MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class); - moveManager.reset(); - Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y)); - moveManager.initiateMove(selected, rot, false); - moving = moveManager.makeUndo(); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_R && !ctrlDown) { - currentState = State.rotate; - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_S && !ctrlDown) { - currentState = State.scale; - return true; - } - return false; - } - - private boolean checkAxisKey(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_X) { - currentAxis = Vector3f.UNIT_X; - checkMovePlane(MoveManager.XY, MoveManager.XZ); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_Y) { - currentAxis = Vector3f.UNIT_Y; - checkMovePlane(MoveManager.XY, MoveManager.YZ); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_Z) { - currentAxis = Vector3f.UNIT_Z; - checkMovePlane(MoveManager.XZ, MoveManager.YZ); - return true; - } - return false; - } - - private void checkMovePlane(Quaternion rot1, Quaternion rot2) { - if (currentState == State.translate) { - MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class); - Quaternion rot = camera.getRotation().mult(new Quaternion().fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y)); - Quaternion planRot = null; - if (rot.dot(rot1) < rot.dot(rot2)) { - planRot = rot1; - } else { - planRot = rot2; - } - moveManager.updatePlaneRotation(planRot); - } - } - - private boolean checkNumberKey(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_MINUS) { - if (numberBuilder.length() > 0) { - if (numberBuilder.charAt(0) == '-') { - numberBuilder.replace(0, 1, ""); - } else { - numberBuilder.insert(0, '-'); - } - } else { - numberBuilder.append('-'); - } - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_0 || kie.getKeyCode() == KeyInput.KEY_NUMPAD0) { - numberBuilder.append('0'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_1 || kie.getKeyCode() == KeyInput.KEY_NUMPAD1) { - numberBuilder.append('1'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_2 || kie.getKeyCode() == KeyInput.KEY_NUMPAD2) { - numberBuilder.append('2'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_3 || kie.getKeyCode() == KeyInput.KEY_NUMPAD3) { - numberBuilder.append('3'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_4 || kie.getKeyCode() == KeyInput.KEY_NUMPAD4) { - numberBuilder.append('4'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_5 || kie.getKeyCode() == KeyInput.KEY_NUMPAD5) { - numberBuilder.append('5'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_6 || kie.getKeyCode() == KeyInput.KEY_NUMPAD6) { - numberBuilder.append('6'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_7 || kie.getKeyCode() == KeyInput.KEY_NUMPAD7) { - numberBuilder.append('7'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_8 || kie.getKeyCode() == KeyInput.KEY_NUMPAD8) { - numberBuilder.append('8'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_9 || kie.getKeyCode() == KeyInput.KEY_NUMPAD9) { - numberBuilder.append('9'); - return true; - } else if (kie.getKeyCode() == KeyInput.KEY_PERIOD) { - if (numberBuilder.indexOf(".") == -1) { // if it doesn't exist yet - if (numberBuilder.length() == 0 - || (numberBuilder.length() == 1 && numberBuilder.charAt(0) == '-')) { - numberBuilder.append("0."); - } else { - numberBuilder.append("."); - } - } - return true; - } - - return false; - } - - private boolean checkEnterHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_RETURN) { - return true; - } - return false; - } - - private boolean checkEscHit(KeyInputEvent kie) { - if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) { - return true; - } - return false; - } - @Override public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) { - if (!pressed) { - Spatial selected = toolController.getSelectedSpatial(); - // left mouse released - if (!wasDraggingL) { - // left mouse pressed - if (currentState != null) { - // finish manipulating the spatial - if (moving != null) { - moving.setAfter(selected.getLocalTranslation()); - actionPerformed(moving); - moving = null; - clearState(false); - } else if (scaling != null) { - scaling.after = selected.getLocalScale().clone(); - actionPerformed(scaling); - scaling = null; - clearState(false); - toolController.rebuildSelectionBox(); - } else if (rotating != null) { - rotating.after = selected.getLocalRotation().clone(); - actionPerformed(rotating); - rotating = null; - clearState(false); - } - } else { - // mouse released and wasn't dragging, place cursor - final Vector3f result = pickWorldLocation(getCamera(), screenCoord, rootNode); - if (result != null) { - if (toolController.isSnapToGrid()) { - result.set(Math.round(result.x), result.y, Math.round(result.z)); - } - toolController.setCursorLocation(result); - } - } - } - wasDraggingL = false; - } + } @Override @@ -435,19 +61,7 @@ public class SelectTool extends SceneEditTool { Spatial selected = toolController.getSelectedSpatial(); // mouse down - if (moving != null) { - moving.sceneUndo(); - moving = null; - clearState(); - } else if (scaling != null) { - scaling.sceneUndo(); - scaling = null; - clearState(); - } else if (rotating != null) { - rotating.sceneUndo(); - rotating = null; - clearState(); - } else if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already + if (!wasDraggingR && !wasDownR) { // wasn't dragging and was not down already // pick on the spot Spatial s = pickWorldSpatial(camera, screenCoord, rootNode); if (!toolController.selectTerrain() && isTerrain(s)) { @@ -498,8 +112,8 @@ public class SelectTool extends SceneEditTool { } /** - * Climb up the spatial until we find the first node parent. - * TODO: use userData to determine the actual model's parent. + * Climb up the spatial until we find the first node parent. TODO: use + * userData to determine the actual model's parent. */ private Spatial findModelNodeParent(Spatial child) { if (child == null) { @@ -519,14 +133,10 @@ public class SelectTool extends SceneEditTool { @Override public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) { - if (currentState != null) { - handleMouseManipulate(screenCoord, currentState, currentAxis, rootNode, currentDataObject, selectedSpatial); - } } @Override public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) { - wasDraggingL = pressed; } @Override @@ -535,252 +145,8 @@ public class SelectTool extends SceneEditTool { } /** - * Manipulate the spatial - */ - private void handleMouseManipulate(Vector2f screenCoord, - State state, - Vector3f axis, - JmeNode rootNode, - DataObject currentDataObject, - JmeSpatial selectedSpatial) { - if (state == State.translate) { - doMouseTranslate(axis, screenCoord, rootNode, selectedSpatial); - } else if (state == State.scale) { - doMouseScale(axis, screenCoord, rootNode, selectedSpatial); - } else if (state == State.rotate) { - doMouseRotate(axis, screenCoord, rootNode, selectedSpatial); - } - - } - - private void doMouseTranslate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) { - MoveManager moveManager = Lookup.getDefault().lookup(MoveManager.class); - if (toolController.isSnapToScene()) { - moveManager.setAlternativePickTarget(rootNode.getLookup().lookup(Node.class)); - } - // free form translation - moveManager.move(camera, screenCoord, axis, toolController.isSnapToGrid()); - } - - private void doMouseScale(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) { - Spatial selected = toolController.getSelectedSpatial(); - // scale based on the original mouse position and original model-to-screen position - // and compare that to the distance from the new mouse position and the original distance - if (startMouseCoord == null) { - startMouseCoord = screenCoord.clone(); - } - if (startSelectedCoord == null) { - Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation()); - startSelectedCoord = new Vector2f(screen.x, screen.y); - } - - if (scaling == null) { - scaling = new ScaleUndo(selected, selected.getLocalScale().clone(), null); - } - - float origDist = startMouseCoord.distanceSquared(startSelectedCoord); - float newDist = screenCoord.distanceSquared(startSelectedCoord); - if (origDist == 0) { - origDist = 1; - } - float ratio = newDist / origDist; - Vector3f prev = selected.getLocalScale(); - if (axis == Vector3f.UNIT_X) { - selected.setLocalScale(ratio, prev.y, prev.z); - } else if (axis == Vector3f.UNIT_Y) { - selected.setLocalScale(prev.x, ratio, prev.z); - } else if (axis == Vector3f.UNIT_Z) { - selected.setLocalScale(prev.x, prev.y, ratio); - } else { - selected.setLocalScale(ratio, ratio, ratio); - } - } - - private void doMouseRotate(Vector3f axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) { - Spatial selected = toolController.getSelectedSpatial(); - if (startMouseCoord == null) { - startMouseCoord = screenCoord.clone(); - } - if (startSelectedCoord == null) { - Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation()); - startSelectedCoord = new Vector2f(screen.x, screen.y); - } - - if (rotating == null) { - rotating = new RotateUndo(selected, selected.getLocalRotation().clone(), null); - } - - Vector2f origRot = startMouseCoord.subtract(startSelectedCoord); - Vector2f newRot = screenCoord.subtract(startSelectedCoord); - float newRotAngle = origRot.angleBetween(newRot); - float temp = newRotAngle; - - if (lastRotAngle != 0) { - newRotAngle -= lastRotAngle; - } - - lastRotAngle = temp; - - Quaternion rotate = new Quaternion(); - if (axis != Vector3f.UNIT_XYZ) { - rotate = rotate.fromAngleAxis(newRotAngle, selected.getWorldRotation().inverse().mult(axis)); - } else { - rotate = rotate.fromAngleAxis(newRotAngle, selected.getWorldRotation().inverse().mult(getCamera().getDirection().mult(-1).normalizeLocal())); - } - selected.setLocalRotation(selected.getLocalRotation().mult(rotate)); - - - } - - private void duplicateSelected() { - Spatial selected = toolController.getSelectedSpatial(); - if (selected == null) { - return; - } - Spatial clone = selected.clone(); - clone.move(1, 0, 1); - - selected.getParent().attachChild(clone); - actionPerformed(new DuplicateUndo(clone, selected.getParent())); - selected = clone; - final Spatial cloned = clone; - final JmeNode rootNode = toolController.getRootNode(); - refreshSelected(rootNode, selected.getParent()); - - java.awt.EventQueue.invokeLater(new Runnable() { - - @Override - public void run() { - if (cloned != null) { - SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(cloned)}); - SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(cloned)); - } - } - }); - - // set to automatically 'grab'/'translate' the new cloned model - toolController.updateSelection(selected); - currentState = State.translate; - currentAxis = Vector3f.UNIT_XYZ; - } - - private void deleteSelected() { - Spatial selected = toolController.getSelectedSpatial(); - if (selected == null) { - return; - } - Node parent = selected.getParent(); - selected.removeFromParent(); - actionPerformed(new DeleteUndo(selected, parent)); - - selected = null; - toolController.updateSelection(selected); - - final JmeNode rootNode = toolController.getRootNode(); - refreshSelected(rootNode, parent); - } - - private void refreshSelected(final JmeNode jmeRootNode, final Node parent) { - java.awt.EventQueue.invokeLater(new Runnable() { - - @Override - public void run() { - jmeRootNode.getChild(parent).refresh(false); - } - }); - } - - private class ScaleUndo extends AbstractUndoableSceneEdit { - - private Spatial spatial; - private Vector3f before, after; - - ScaleUndo(Spatial spatial, Vector3f before, Vector3f after) { - this.spatial = spatial; - this.before = before; - this.after = after; - } - - @Override - public void sceneUndo() { - spatial.setLocalScale(before); - } - - @Override - public void sceneRedo() { - spatial.setLocalScale(after); - } - } - - private class RotateUndo extends AbstractUndoableSceneEdit { - - private Spatial spatial; - private Quaternion before, after; - - RotateUndo(Spatial spatial, Quaternion before, Quaternion after) { - this.spatial = spatial; - this.before = before; - this.after = after; - } - - @Override - public void sceneUndo() { - spatial.setLocalRotation(before); - } - - @Override - public void sceneRedo() { - spatial.setLocalRotation(after); - } - } - - private class DeleteUndo extends AbstractUndoableSceneEdit { - - private Spatial spatial; - private Node parent; - - DeleteUndo(Spatial spatial, Node parent) { - this.spatial = spatial; - this.parent = parent; - } - - @Override - public void sceneUndo() { - parent.attachChild(spatial); - } - - @Override - public void sceneRedo() { - spatial.removeFromParent(); - } - } - - private class DuplicateUndo extends AbstractUndoableSceneEdit { - - private Spatial spatial; - private Node parent; - - DuplicateUndo(Spatial spatial, Node parent) { - this.spatial = spatial; - this.parent = parent; - } - - @Override - public void sceneUndo() { - spatial.removeFromParent(); - } - - @Override - public void sceneRedo() { - parent.attachChild(spatial); - } - } - - /** - * Check if the selected item is a Terrain - * It will climb up the parent tree to see if - * a parent is terrain too. - * Recursive call. + * Check if the selected item is a Terrain It will climb up the parent tree + * to see if a parent is terrain too. Recursive call. */ protected boolean isTerrain(Spatial s) { if (s == null) { diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java new file mode 100644 index 000000000..cc13ece1d --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DeleteShortcut.java @@ -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(); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DuplicateShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DuplicateShortcut.java new file mode 100644 index 000000000..d98eb6ee9 --- /dev/null +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/DuplicateShortcut.java @@ -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); + } + } +} diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java index bdbcfbe9e..512e36e0c 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java @@ -22,12 +22,17 @@ public class ShortcutManager { private ShortcutTool currentShortcut; private ArrayList shortcutList; + private boolean ctrlDown = false; + private boolean shiftDown = false; + private boolean altDown = false; public ShortcutManager() { shortcutList = new ArrayList(); shortcutList.add(new MoveShortcut()); shortcutList.add(new RotateShortcut()); shortcutList.add(new ScaleShortcut()); + shortcutList.add(new DuplicateShortcut()); + shortcutList.add(new DeleteShortcut()); } /* @@ -41,6 +46,27 @@ public class ShortcutManager { 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; + } + public void setShortCut(ShortcutTool shortcut) { if (isActive()) { currentShortcut.cancel(); @@ -49,6 +75,9 @@ public class ShortcutManager { } public ShortcutTool getActivableShortcut(KeyInputEvent kie) { + if (checkCommandeKey(kie)) { + return null; + } for (ShortcutTool s : shortcutList) { if (s != currentShortcut) { if (s.isActivableBy(kie)) { @@ -69,12 +98,12 @@ public class ShortcutManager { public boolean activateShortcut(KeyInputEvent kie) { ShortcutTool newShortcut = getActivableShortcut(kie); - if(newShortcut != null){ + if (newShortcut != null) { currentShortcut = newShortcut; } return newShortcut != null; } - + /** * This should be called to trigger the currentShortcut.keyPressed() method. * This method do a first check for command key used to provide isCtrlDown, @@ -83,12 +112,27 @@ public class ShortcutManager { * @param kie */ public void doKeyPressed(KeyInputEvent kie) { - ///todo check commande key - if (isActive()) { + 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 */ From 97e1cf8cf3344fb1cbcb8c477f1a486386692377 Mon Sep 17 00:00:00 2001 From: Maselbas Date: Fri, 15 May 2015 22:38:18 +0200 Subject: [PATCH 09/29] SDK SceneComposer : added comments in the ShortCutManager - refactor getNumberkey() to getNumberKey() --- .../tools/shortcuts/MoveShortcut.java | 2 +- .../tools/shortcuts/RotateShortcut.java | 2 +- .../tools/shortcuts/ScaleShortcut.java | 2 +- .../tools/shortcuts/ShortcutManager.java | 90 ++++++++++++++++++- 4 files changed, 89 insertions(+), 7 deletions(-) diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java index 62cc70612..6291ab932 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/MoveShortcut.java @@ -103,7 +103,7 @@ public class MoveShortcut extends ShortcutTool { } } else if (axisChanged || numberChanged) { //update transformation - float number = ShortcutManager.getNumberkey(numberBuilder); + float number = ShortcutManager.getNumberKey(numberBuilder); Vector3f translation = currentAxis.mult(number); finalPosition = startPosition.add(translation); spatial.setLocalTranslation(finalPosition); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java index 1fb445b59..8b9ffe404 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/RotateShortcut.java @@ -95,7 +95,7 @@ public class RotateShortcut extends ShortcutTool { spatial.setLocalRotation(startRotation.clone()); } else if (axisChanged || numberChanged) { //update transformation - /* float number = ShortcutManager.getNumberkey(numberBuilder); + /* float number = ShortcutManager.getNumberKey(numberBuilder); Vector3f translation = currentAxis.mult(number); finalPosition = startPosition.add(translation); spatial.setLocalTranslation(finalPosition); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java index 21966e385..8fa18858f 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ScaleShortcut.java @@ -94,7 +94,7 @@ public class ScaleShortcut extends ShortcutTool { pickEnabled = false; } else if (axisChanged || numberChanged) { //update transformation - /* float number = ShortcutManager.getNumberkey(numberBuilder); + /* float number = ShortcutManager.getNumberKey(numberBuilder); Vector3f translation = currentAxis.mult(number); finalPosition = startPosition.add(translation); spatial.setLocalTranslation(finalPosition); diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java index 512e36e0c..187293e92 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/shortcuts/ShortcutManager.java @@ -38,10 +38,17 @@ public class ShortcutManager { /* 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; } @@ -67,6 +74,12 @@ public class ShortcutManager { return altDown; } + /** + * Set the current shortcut to shortcut. cancel the current + * shortcut if it was still active + * + * @param shortcut the ShortCutTool to set + */ public void setShortCut(ShortcutTool shortcut) { if (isActive()) { currentShortcut.cancel(); @@ -74,10 +87,18 @@ public class ShortcutManager { 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)) { @@ -88,14 +109,30 @@ public class ShortcutManager { 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) { @@ -106,8 +143,8 @@ public class ShortcutManager { /** * This should be called to trigger the currentShortcut.keyPressed() method. - * This method do a first check for command key used to provide isCtrlDown, - * isShiftDown ect.. to de + * This also check for command key used to provide isCtrlDown(), + * isShiftDown() and isAltDown(). * * @param kie */ @@ -136,6 +173,11 @@ public class ShortcutManager { /* 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; @@ -143,6 +185,11 @@ public class ShortcutManager { 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; @@ -150,6 +197,11 @@ public class ShortcutManager { 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; @@ -157,6 +209,11 @@ public class ShortcutManager { 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; @@ -164,6 +221,11 @@ public class ShortcutManager { 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; @@ -171,6 +233,13 @@ public class ShortcutManager { 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) { @@ -228,7 +297,12 @@ public class ShortcutManager { return false; } - public static float getNumberkey(StringBuilder numberBuilder) { + /** + * + * @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 { @@ -236,6 +310,14 @@ public class ShortcutManager { } } + /** + * 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); From afc8f3f1cd9a2895dba0884711a4ca6c3204a5a1 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 22 May 2015 12:51:09 +0200 Subject: [PATCH 10/29] Fixed SpotLight default inititalisation for invSpotRange --- jme3-core/src/main/java/com/jme3/light/SpotLight.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java index f02f76fa4..e6443df7c 100644 --- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java +++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java @@ -63,7 +63,7 @@ public class SpotLight extends Light { protected float spotInnerAngle = FastMath.QUARTER_PI / 8; protected float spotOuterAngle = FastMath.QUARTER_PI / 6; protected float spotRange = 100; - protected float invSpotRange = 1 / 100; + protected float invSpotRange = 1f / 100; protected float packedAngleCos=0; protected float outerAngleCosSqr, outerAngleSinSqr; From 46e4c21c2c9b19cba337b8c3f1b7ffc12ca2b871 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Sun, 24 May 2015 16:09:41 +0200 Subject: [PATCH 11/29] Added: GL_MAX_VERTEX_UNIFORM_COMPONENTS --- jme3-core/src/main/java/com/jme3/renderer/Limits.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jme3-core/src/main/java/com/jme3/renderer/Limits.java b/jme3-core/src/main/java/com/jme3/renderer/Limits.java index b10c539b8..7df9bc76b 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Limits.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Limits.java @@ -75,4 +75,6 @@ public enum Limits { ColorTextureSamples, DepthTextureSamples, + + VertexUniformComponents, } From 14e4f2bfb3d986806bfd7a12e092a8bfd6d31f87 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Sun, 24 May 2015 16:12:28 +0200 Subject: [PATCH 12/29] Added: GL_MAX_VERTEX_UNIFORM_COMPONENTS --- jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java | 1 + .../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 76eedb521..21eedab52 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -99,6 +99,7 @@ public interface GL { public static final int GL_MAX_TEXTURE_SIZE = 0xD33; public static final int GL_MAX_VERTEX_ATTRIBS = 0x8869; public static final int GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; + public static final int GL_MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A; public static final int GL_MIRRORED_REPEAT = 0x8370; public static final int GL_NEAREST = 0x2600; public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 3f14bdb10..caf472543 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -196,7 +196,7 @@ public class GLRenderer implements Renderer { } int glslVer = extractVersion(gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)); - + switch (glslVer) { default: if (glslVer < 400) { @@ -249,7 +249,7 @@ public class GLRenderer implements Renderer { } limits.put(Limits.FragmentTextureUnits, getInteger(GL.GL_MAX_TEXTURE_IMAGE_UNITS)); - + // gl.glGetInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS, intBuf16); // vertexUniforms = intBuf16.get(0); // logger.log(Level.FINER, "Vertex Uniforms: {0}", vertexUniforms); @@ -257,7 +257,7 @@ public class GLRenderer implements Renderer { // gl.glGetInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16); // fragUniforms = intBuf16.get(0); // logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - + limits.put(Limits.VertexUniformComponents,getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS)); limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS)); limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE)); From 4bd774a6539656166ae815bdb147a6cff7b17910 Mon Sep 17 00:00:00 2001 From: Paul Speed Date: Thu, 28 May 2015 01:10:44 -0400 Subject: [PATCH 13/29] Created an abstract hosted connection service that has the autohost, start/stopHostingOnConnection support built into it. This is a very common things for connection based services and I got tired of cutting/pasting it all the time. RpcHostedService was modified to extend this base class instead of the more basic one. --- .../AbstractHostedConnectionService.java | 148 ++++++++++++++++++ .../network/service/rpc/RpcHostedService.java | 62 +------- 2 files changed, 153 insertions(+), 57 deletions(-) create mode 100644 jme3-networking/src/main/java/com/jme3/network/service/AbstractHostedConnectionService.java diff --git a/jme3-networking/src/main/java/com/jme3/network/service/AbstractHostedConnectionService.java b/jme3-networking/src/main/java/com/jme3/network/service/AbstractHostedConnectionService.java new file mode 100644 index 000000000..485712b95 --- /dev/null +++ b/jme3-networking/src/main/java/com/jme3/network/service/AbstractHostedConnectionService.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.network.service; + +import com.jme3.network.HostedConnection; +import com.jme3.network.Server; +import java.util.logging.Level; +import java.util.logging.Logger; + + +/** + * Convenient base class for HostedServices providing some default HostedService + * interface implementations as well as a few convenience methods + * such as getServiceManager() and getService(type). This implementation + * enhances the default capabilities provided by AbstractHostedService by + * adding automatic connection management. + * + *

Subclasses must at least override the onInitialize(), startHostingOnConnection(), and + * stopHostingOnConnection() methods to handle service and connection initialization.

+ * + *

An autoHost flag controls whether startHostingOnConnection() is called + * automatically when new connections are detected. If autoHohst is false then it + * is up to the implementation or appliction to specifically start hosting at + * some point.

+ * + * @author Paul Speed + */ +public abstract class AbstractHostedConnectionService extends AbstractHostedService { + + static final Logger log = Logger.getLogger(AbstractHostedConnectionService.class.getName()); + + private boolean autoHost; + + /** + * Creates a new HostedService that will autohost connections + * when detected. + */ + protected AbstractHostedConnectionService() { + this(true); + } + + /** + * Creates a new HostedService that will automatically host + * connections only if autoHost is true. + */ + protected AbstractHostedConnectionService( boolean autoHost ) { + this.autoHost = autoHost; + } + + /** + * When set to true, all new connections will automatically have + * hosting services attached to them by calling startHostingOnConnection(). + * If this is set to false then it is up to the application or other services + * to eventually call startHostingOnConnection(). + * + *

Reasons for doing this vary but usually would be because + * the client shouldn't be allowed to perform any service-related calls until + * it has provided more information... for example, logging in.

+ */ + public void setAutoHost( boolean b ) { + this.autoHost = b; + } + + /** + * Returns true if this service automatically attaches + * hosting capabilities to new connections. + */ + public boolean getAutoHost() { + return autoHost; + } + + + /** + * Performs implementation specific connection hosting setup. + * Generally this involves setting up some handlers or session + * attributes on the connection. If autoHost is true then this + * method is called automatically during connectionAdded() + * processing. + */ + public abstract void startHostingOnConnection( HostedConnection hc ); + + /** + * Performs implementation specific connection tear-down. + * This will be called automatically when the connectionRemoved() + * event occurs... whether the application has already called it + * or not. + */ + public abstract void stopHostingOnConnection( HostedConnection hc ); + + /** + * Called internally when a new connection is detected for + * the server. If the current autoHost property is true then + * startHostingOnConnection(hc) is called. + */ + @Override + public void connectionAdded(Server server, HostedConnection hc) { + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "connectionAdded({0}, {1})", new Object[]{server, hc}); + } + if( autoHost ) { + startHostingOnConnection(hc); + } + } + + /** + * Called internally when an existing connection is leaving + * the server. This method always calls stopHostingOnConnection(hc). + * Implementations should be aware that if they stopHostingOnConnection() + * early that they will get a second call when the connection goes away. + */ + @Override + public void connectionRemoved(Server server, HostedConnection hc) { + if( log.isLoggable(Level.FINEST) ) { + log.log(Level.FINEST, "connectionRemoved({0}, {1})", new Object[]{server, hc}); + } + stopHostingOnConnection(hc); + } +} diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rpc/RpcHostedService.java b/jme3-networking/src/main/java/com/jme3/network/service/rpc/RpcHostedService.java index 4a347b5a3..2d6f28593 100644 --- a/jme3-networking/src/main/java/com/jme3/network/service/rpc/RpcHostedService.java +++ b/jme3-networking/src/main/java/com/jme3/network/service/rpc/RpcHostedService.java @@ -35,8 +35,8 @@ package com.jme3.network.service.rpc; import com.jme3.network.HostedConnection; import com.jme3.network.Server; import com.jme3.network.serializing.Serializer; +import com.jme3.network.service.AbstractHostedConnectionService; import com.jme3.network.util.SessionDataDelegator; -import com.jme3.network.service.AbstractHostedService; import com.jme3.network.service.HostedServiceManager; import com.jme3.network.service.rpc.msg.RpcCallMessage; import com.jme3.network.service.rpc.msg.RpcResponseMessage; @@ -62,13 +62,12 @@ import java.util.logging.Logger; * * @author Paul Speed */ -public class RpcHostedService extends AbstractHostedService { +public class RpcHostedService extends AbstractHostedConnectionService { private static final String ATTRIBUTE_NAME = "rpcSession"; static final Logger log = Logger.getLogger(RpcHostedService.class.getName()); - private boolean autoHost; private SessionDataDelegator delegator; /** @@ -87,7 +86,7 @@ public class RpcHostedService extends AbstractHostedService { * on the specified 'autoHost' flag. */ public RpcHostedService( boolean autoHost ) { - this.autoHost = autoHost; + super(autoHost); // This works for me... has to be different in // the general case @@ -115,31 +114,6 @@ public class RpcHostedService extends AbstractHostedService { } } - /** - * When set to true, all new connections will automatically have - * RPC hosting services attached to them, meaning they can send - * and receive RPC calls. If this is set to false then it is up - * to other services to eventually call startHostingOnConnection(). - * - *

Reasons for doing this vary but usually would be because - * the client shouldn't be allowed to perform any RPC calls until - * it has provided more information. In general, this is unnecessary - * because the RpcHandler registries are not shared. Each client - * gets their own and RPC calls will fail until the appropriate - * objects have been registtered.

- */ - public void setAutoHost( boolean b ) { - this.autoHost = b; - } - - /** - * Returns true if this service automatically attaches RPC - * hosting capabilities to new connections. - */ - public boolean getAutoHost() { - return autoHost; - } - /** * Retrieves the RpcConnection for the specified HostedConnection * if that HostedConnection has had RPC services started using @@ -157,6 +131,7 @@ public class RpcHostedService extends AbstractHostedService { * This method is called automatically for all new connections if * autohost is set to true. */ + @Override public void startHostingOnConnection( HostedConnection hc ) { if( log.isLoggable(Level.FINEST) ) { log.log(Level.FINEST, "startHostingOnConnection:{0}", hc); @@ -173,6 +148,7 @@ public class RpcHostedService extends AbstractHostedService { * This method is called automatically for all leaving connections if * autohost is set to true. */ + @Override public void stopHostingOnConnection( HostedConnection hc ) { RpcConnection rpc = hc.getAttribute(ATTRIBUTE_NAME); if( rpc == null ) { @@ -195,33 +171,5 @@ public class RpcHostedService extends AbstractHostedService { server.removeMessageListener(delegator, delegator.getMessageTypes()); } - /** - * Called internally when a new connection is detected for - * the server. If the current autoHost property is true then - * startHostingOnConnection(hc) is called. - */ - @Override - public void connectionAdded(Server server, HostedConnection hc) { - if( log.isLoggable(Level.FINEST) ) { - log.log(Level.FINEST, "connectionAdded({0}, {1})", new Object[]{server, hc}); - } - if( autoHost ) { - startHostingOnConnection(hc); - } - } - - /** - * Called internally when an existing connection is leaving - * the server. If the current autoHost property is true then - * stopHostingOnConnection(hc) is called. - */ - @Override - public void connectionRemoved(Server server, HostedConnection hc) { - if( log.isLoggable(Level.FINEST) ) { - log.log(Level.FINEST, "connectionRemoved({0}, {1})", new Object[]{server, hc}); - } - stopHostingOnConnection(hc); - } - } From ceb45ff718780975bf8e253bd98100e951f73ba4 Mon Sep 17 00:00:00 2001 From: Normen Hansen Date: Sun, 31 May 2015 15:18:59 +0200 Subject: [PATCH 14/29] SDK: - close asset after loading with ModelImportTool --- .../src/com/jme3/gde/modelimporter/ImportModel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java index 1f3f57bf8..07b129628 100644 --- a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ImportModel.java @@ -212,6 +212,7 @@ public final class ImportModel implements ActionListener { } replaceLocatedTextures(spat, manager); targetData.saveAsset(); + targetData.closeAsset(); ((SpatialAssetDataObject) targetModel).getLookupContents().remove(tempProjectManager); } } catch (Exception ex) { From 6f33002f9ac5e9ba2401ec4212f165f0adf9d558 Mon Sep 17 00:00:00 2001 From: Normen Hansen Date: Sun, 31 May 2015 16:06:22 +0200 Subject: [PATCH 15/29] SDK: - close asset after loading with ModelImportTool --- .../com/jme3/gde/modelimporter/ModelImporterVisualPanel3.java | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel3.java b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel3.java index f7eeb57fa..51c0578e3 100644 --- a/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel3.java +++ b/sdk/jme3-model-importer/src/com/jme3/gde/modelimporter/ModelImporterVisualPanel3.java @@ -126,6 +126,7 @@ public final class ModelImporterVisualPanel3 extends JPanel { DialogDisplayer.getDefault().notifyLater(msg); Exceptions.printStackTrace(e); } + data.closeAsset(); manager.unregisterLocator(manager.getAssetFolderName(), UberAssetLocator.class); panel.fireChangeEvent(); } From e2d8fe829359dd6028d6810efddbf671d9980231 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sun, 31 May 2015 16:00:55 -0400 Subject: [PATCH 16/29] GLRenderer: support luminance / alpha textures in core profile --- .../java/com/jme3/renderer/opengl/GL.java | 2 + .../java/com/jme3/renderer/opengl/GL3.java | 13 ++++++- .../java/com/jme3/renderer/opengl/GL4.java | 2 +- .../jme3/renderer/opengl/GLImageFormat.java | 21 ++++++++++ .../jme3/renderer/opengl/GLImageFormats.java | 28 ++++++++++++++ .../com/jme3/renderer/opengl/GLRenderer.java | 2 +- .../com/jme3/renderer/opengl/TextureUtil.java | 38 +++++++++++++++++-- 7 files changed, 99 insertions(+), 7 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 76eedb521..12f14c8aa 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -74,6 +74,7 @@ public interface GL { public static final int GL_FRONT_AND_BACK = 0x408; public static final int GL_GEQUAL = 0x206; public static final int GL_GREATER = 0x204; + public static final int GL_GREEN = 0x1904; public static final int GL_INCR = 0x1E02; public static final int GL_INCR_WRAP = 0x8507; public static final int GL_INFO_LOG_LENGTH = 0x8B84; @@ -114,6 +115,7 @@ public interface GL { public static final int GL_OUT_OF_MEMORY = 0x505; public static final int GL_POINTS = 0x0; public static final int GL_POLYGON_OFFSET_FILL = 0x8037; + public static final int GL_RED = 0x1903; public static final int GL_RENDERER = 0x1F01; public static final int GL_REPEAT = 0x2901; public static final int GL_REPLACE = 0x1E01; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java index 190ed4547..2a7c38bb9 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java @@ -34,7 +34,7 @@ package com.jme3.renderer.opengl; import java.nio.IntBuffer; /** - * GL functions only available on vanilla desktop OpenGL 3.0. + * GL functions only available on vanilla desktop OpenGL 3.0+. * * @author Kirill Vainer */ @@ -43,6 +43,17 @@ public interface GL3 extends GL2 { public static final int GL_DEPTH_STENCIL_ATTACHMENT = 0x821A; public static final int GL_GEOMETRY_SHADER = 0x8DD9; public static final int GL_NUM_EXTENSIONS = 0x821D; + public static final int GL_R8 = 0x8229; + public static final int GL_R16F = 0x822D; + public static final int GL_R32F = 0x822E; + public static final int GL_RG16F = 0x822F; + public static final int GL_RG32F = 0x8230; + public static final int GL_RG = 0x8227; + public static final int GL_RG8 = 0x822B; + public static final int GL_TEXTURE_SWIZZLE_A = 0x8E45; + public static final int GL_TEXTURE_SWIZZLE_B = 0x8E44; + public static final int GL_TEXTURE_SWIZZLE_G = 0x8E43; + public static final int GL_TEXTURE_SWIZZLE_R = 0x8E42; public void glBindFragDataLocation(int param1, int param2, String param3); /// GL3+ public void glBindVertexArray(int param1); /// GL3+ diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java index ce982eebf..058bc00ec 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java @@ -34,7 +34,7 @@ package com.jme3.renderer.opengl; import java.nio.IntBuffer; /** - * GL functions only available on vanilla desktop OpenGL 3.0. + * GL functions only available on vanilla desktop OpenGL 4.0. * * @author Kirill Vainer */ diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormat.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormat.java index 71d95f59b..8e65fbdef 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormat.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormat.java @@ -42,6 +42,7 @@ public final class GLImageFormat { public final int format; public final int dataType; public final boolean compressed; + public final boolean swizzleRequired; /** * Constructor for formats. @@ -55,6 +56,7 @@ public final class GLImageFormat { this.format = format; this.dataType = dataType; this.compressed = false; + this.swizzleRequired = false; } /** @@ -63,11 +65,30 @@ public final class GLImageFormat { * @param internalFormat OpenGL internal format * @param format OpenGL format * @param dataType OpenGL datatype + * @param compressed Format is compressed */ public GLImageFormat(int internalFormat, int format, int dataType, boolean compressed) { this.internalFormat = internalFormat; this.format = format; this.dataType = dataType; this.compressed = compressed; + this.swizzleRequired = false; + } + + /** + * Constructor for formats. + * + * @param internalFormat OpenGL internal format + * @param format OpenGL format + * @param dataType OpenGL datatype + * @param compressed Format is compressed + * @param swizzleRequired Need to use texture swizzle to upload texture + */ + public GLImageFormat(int internalFormat, int format, int dataType, boolean compressed, boolean swizzleRequired) { + this.internalFormat = internalFormat; + this.format = format; + this.dataType = dataType; + this.compressed = compressed; + this.swizzleRequired = swizzleRequired; } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java index a7ef9f52d..ab80b9e2a 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLImageFormats.java @@ -52,6 +52,13 @@ public final class GLImageFormats { formatToGL[0][format.ordinal()] = new GLImageFormat(glInternalFormat, glFormat, glDataType); } + private static void formatSwiz(GLImageFormat[][] formatToGL, Image.Format format, + int glInternalFormat, + int glFormat, + int glDataType){ + formatToGL[0][format.ordinal()] = new GLImageFormat(glInternalFormat, glFormat, glDataType, false, true); + } + private static void formatSrgb(GLImageFormat[][] formatToGL, Image.Format format, int glInternalFormat, int glFormat, @@ -60,6 +67,14 @@ public final class GLImageFormats { formatToGL[1][format.ordinal()] = new GLImageFormat(glInternalFormat, glFormat, glDataType); } + private static void formatSrgbSwiz(GLImageFormat[][] formatToGL, Image.Format format, + int glInternalFormat, + int glFormat, + int glDataType) + { + formatToGL[1][format.ordinal()] = new GLImageFormat(glInternalFormat, glFormat, glDataType, false, true); + } + private static void formatComp(GLImageFormat[][] formatToGL, Image.Format format, int glCompressedFormat, int glFormat, @@ -88,6 +103,19 @@ public final class GLImageFormats { public static GLImageFormat[][] getFormatsForCaps(EnumSet caps) { GLImageFormat[][] formatToGL = new GLImageFormat[2][Image.Format.values().length]; + // Core Profile Formats (supported by both OpenGL Core 3.3 and OpenGL ES 3.0+) + if (caps.contains(Caps.CoreProfile)) { + formatSwiz(formatToGL, Format.Alpha8, GL3.GL_R8, GL.GL_RED, GL.GL_UNSIGNED_BYTE); + formatSwiz(formatToGL, Format.Luminance8, GL3.GL_R8, GL.GL_RED, GL.GL_UNSIGNED_BYTE); + formatSwiz(formatToGL, Format.Luminance8Alpha8, GL3.GL_RG8, GL3.GL_RG, GL.GL_UNSIGNED_BYTE); + formatSwiz(formatToGL, Format.Luminance16F, GL3.GL_R16F, GL.GL_RED, GLExt.GL_HALF_FLOAT_ARB); + formatSwiz(formatToGL, Format.Luminance32F, GL3.GL_R32F, GL.GL_RED, GL.GL_FLOAT); + formatSwiz(formatToGL, Format.Luminance16FAlpha16F, GL3.GL_RG16F, GL3.GL_RG, GLExt.GL_HALF_FLOAT_ARB); + + formatSrgbSwiz(formatToGL, Format.Luminance8, GLExt.GL_SRGB8_EXT, GL.GL_RED, GL.GL_UNSIGNED_BYTE); + formatSrgbSwiz(formatToGL, Format.Luminance8Alpha8, GLExt.GL_SRGB8_ALPHA8_EXT, GL3.GL_RG, GL.GL_UNSIGNED_BYTE); + } + if (caps.contains(Caps.OpenGL20)) { if (!caps.contains(Caps.CoreProfile)) { format(formatToGL, Format.Alpha8, GL2.GL_ALPHA8, GL.GL_ALPHA, GL.GL_UNSIGNED_BYTE); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 3f14bdb10..23527d1ab 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -106,7 +106,7 @@ public class GLRenderer implements Renderer { this.gl4 = gl instanceof GL4 ? (GL4)gl : null; this.glfbo = glfbo; this.glext = glext; - this.texUtil = new TextureUtil(gl, gl2, glext, context); + this.texUtil = new TextureUtil(gl, gl2, glext); } @Override diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java index 37ffe5ed3..a2f21ceaa 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/TextureUtil.java @@ -54,14 +54,12 @@ final class TextureUtil { private final GL gl; private final GL2 gl2; private final GLExt glext; - private final RenderContext context; private GLImageFormat[][] formats; - - public TextureUtil(GL gl, GL2 gl2, GLExt glext, RenderContext context) { + + public TextureUtil(GL gl, GL2 gl2, GLExt glext) { this.gl = gl; this.gl2 = gl2; this.glext = glext; - this.context = context; } public void initialize(EnumSet caps) { @@ -103,6 +101,33 @@ final class TextureUtil { return glFmt; } + private void setupTextureSwizzle(int target, Format format) { + // Needed for OpenGL 3.3 to support luminance / alpha formats + switch (format) { + case Alpha8: + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_R, GL.GL_ZERO); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_G, GL.GL_ZERO); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_B, GL.GL_ZERO); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_A, GL.GL_RED); + break; + case Luminance8: + case Luminance16F: + case Luminance32F: + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_R, GL.GL_RED); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_G, GL.GL_RED); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_B, GL.GL_RED); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_A, GL.GL_ONE); + break; + case Luminance8Alpha8: + case Luminance16FAlpha16F: + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_R, GL.GL_RED); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_G, GL.GL_RED); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_B, GL.GL_RED); + gl.glTexParameteri(target, GL3.GL_TEXTURE_SWIZZLE_A, GL.GL_GREEN); + break; + } + } + private void uploadTextureLevel(GLImageFormat format, int target, int level, int slice, int sliceCount, int width, int height, int depth, int samples, ByteBuffer data) { if (format.compressed && data != null) { if (target == GL2.GL_TEXTURE_3D) { @@ -242,6 +267,11 @@ final class TextureUtil { } int samples = image.getMultiSamples(); + + // For OGL3 core: setup texture swizzle. + if (oglFormat.swizzleRequired) { + setupTextureSwizzle(target, jmeFormat); + } for (int i = 0; i < mipSizes.length; i++) { int mipWidth = Math.max(1, width >> i); From 7fa735fdb1d15c36171bf9044dc2bc8aa45d97d4 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Thu, 18 Jun 2015 16:26:36 +0200 Subject: [PATCH 17/29] Remove root slash from the asset path --- .../src/plugins/java/com/jme3/asset/plugins/ZipLocator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jme3-core/src/plugins/java/com/jme3/asset/plugins/ZipLocator.java b/jme3-core/src/plugins/java/com/jme3/asset/plugins/ZipLocator.java index d20816f34..22e7cc244 100644 --- a/jme3-core/src/plugins/java/com/jme3/asset/plugins/ZipLocator.java +++ b/jme3-core/src/plugins/java/com/jme3/asset/plugins/ZipLocator.java @@ -82,6 +82,7 @@ public class ZipLocator implements AssetLocator { public AssetInfo locate(AssetManager manager, AssetKey key) { String name = key.getName(); + if(name.startsWith("/"))name=name.substring(1); ZipEntry entry = zipfile.getEntry(name); if (entry == null) return null; From f7a4fe9f2513ac0fa5f78b7aca12606efaa75da5 Mon Sep 17 00:00:00 2001 From: jmekaelthas Date: Thu, 18 Jun 2015 23:51:17 +0200 Subject: [PATCH 18/29] Improvement of the Inverse Kinematics Constraint. --- jme3-blender/build.gradle | 5 +- .../blender/constraints/Constraint.java | 4 +- .../definitions/ConstraintDefinition.java | 6 + .../ConstraintDefinitionFactory.java | 12 +- .../definitions/ConstraintDefinitionIK.java | 268 +++++++++--------- .../plugins/blender/math/DQuaternion.java | 128 +++++++++ .../plugins/blender/math/DTransform.java | 26 +- .../scene/plugins/blender/math/Matrix.java | 214 ++++++++++++++ 8 files changed, 510 insertions(+), 153 deletions(-) create mode 100644 jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Matrix.java diff --git a/jme3-blender/build.gradle b/jme3-blender/build.gradle index 1b42c7109..a556d7a65 100644 --- a/jme3-blender/build.gradle +++ b/jme3-blender/build.gradle @@ -6,4 +6,7 @@ dependencies { compile project(':jme3-core') compile project(':jme3-desktop') compile project(':jme3-effects') -} + compile ('org.ejml:core:0.27') + compile ('org.ejml:dense64:0.27') + compile ('org.ejml:simple:0.27') +} \ No newline at end of file diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/Constraint.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/Constraint.java index 91cfd2f3f..f2268199c 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/Constraint.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/Constraint.java @@ -64,7 +64,7 @@ public abstract class Constraint { Pointer pData = (Pointer) constraintStructure.getFieldValue("data"); if (pData.isNotNull()) { Structure data = pData.fetchData().get(0); - constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(data, ownerOMA, blenderContext); + constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(data, name, ownerOMA, blenderContext); Pointer pTar = (Pointer) data.getFieldValue("tar"); if (pTar != null && pTar.isNotNull()) { targetOMA = pTar.getOldMemoryAddress(); @@ -77,7 +77,7 @@ public abstract class Constraint { } } else { // Null constraint has no data, so create it here - constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(null, null, blenderContext); + constraintDefinition = ConstraintDefinitionFactory.createConstraintDefinition(null, name, null, blenderContext); } ownerSpace = Space.valueOf(((Number) constraintStructure.getFieldValue("ownspace")).byteValue()); ipo = influenceIpo; diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java index 346554052..a1f3a7316 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinition.java @@ -30,6 +30,8 @@ public abstract class ConstraintDefinition { protected Set alteredOmas; /** The variable that determines if the constraint will alter the track in any way. */ protected boolean trackToBeChanged = true; + /** The name of the constraint. */ + protected String constraintName; /** * Loads a constraint definition based on the constraint definition @@ -53,6 +55,10 @@ public abstract class ConstraintDefinition { constraintHelper = (ConstraintHelper) (blenderContext == null ? null : blenderContext.getHelper(ConstraintHelper.class)); this.ownerOMA = ownerOMA; } + + public void setConstraintName(String constraintName) { + this.constraintName = constraintName; + } /** * @return determines if the definition of the constraint will change the bone in any way; in most cases diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java index cbf727290..c1d69fe06 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionFactory.java @@ -92,7 +92,7 @@ public class ConstraintDefinitionFactory { * this exception is thrown when the blender file is somehow * corrupted */ - public static ConstraintDefinition createConstraintDefinition(Structure constraintStructure, Long ownerOMA, BlenderContext blenderContext) throws BlenderFileException { + public static ConstraintDefinition createConstraintDefinition(Structure constraintStructure, String constraintName, Long ownerOMA, BlenderContext blenderContext) throws BlenderFileException { if (constraintStructure == null) { return new ConstraintDefinitionNull(null, ownerOMA, blenderContext); } @@ -100,7 +100,9 @@ public class ConstraintDefinitionFactory { Class constraintDefinitionClass = CONSTRAINT_CLASSES.get(constraintClassName); if (constraintDefinitionClass != null) { try { - return (ConstraintDefinition) constraintDefinitionClass.getDeclaredConstructors()[0].newInstance(constraintStructure, ownerOMA, blenderContext); + ConstraintDefinition def = (ConstraintDefinition) constraintDefinitionClass.getDeclaredConstructors()[0].newInstance(constraintStructure, ownerOMA, blenderContext); + def.setConstraintName(constraintName); + return def; } catch (IllegalArgumentException e) { throw new BlenderFileException(e.getLocalizedMessage(), e); } catch (SecurityException e) { @@ -113,9 +115,9 @@ public class ConstraintDefinitionFactory { throw new BlenderFileException(e.getLocalizedMessage(), e); } } else { - String constraintName = UNSUPPORTED_CONSTRAINTS.get(constraintClassName); - if (constraintName != null) { - return new UnsupportedConstraintDefinition(constraintName); + String unsupportedConstraintClassName = UNSUPPORTED_CONSTRAINTS.get(constraintClassName); + if (unsupportedConstraintClassName != null) { + return new UnsupportedConstraintDefinition(unsupportedConstraintClassName); } else { throw new BlenderFileException("Unknown constraint type: " + constraintClassName); } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java index 35a4e5618..820a283b3 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/constraints/definitions/ConstraintDefinitionIK.java @@ -1,36 +1,32 @@ package com.jme3.scene.plugins.blender.constraints.definitions; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Set; + +import org.ejml.simple.SimpleMatrix; import com.jme3.animation.Bone; import com.jme3.math.Transform; -import com.jme3.math.Vector3f; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.animations.BoneContext; +import com.jme3.scene.plugins.blender.constraints.ConstraintHelper; import com.jme3.scene.plugins.blender.constraints.ConstraintHelper.Space; import com.jme3.scene.plugins.blender.file.Structure; import com.jme3.scene.plugins.blender.math.DQuaternion; import com.jme3.scene.plugins.blender.math.DTransform; +import com.jme3.scene.plugins.blender.math.Matrix; import com.jme3.scene.plugins.blender.math.Vector3d; -/** - * The Inverse Kinematics constraint. - * - * @author Wesley Shillingford (wezrule) - * @author Marcin Roguski (Kaelthas) - */ public class ConstraintDefinitionIK extends ConstraintDefinition { - private static final float MIN_DISTANCE = 0.0001f; + private static final float MIN_DISTANCE = 0.001f; private static final int FLAG_USE_TAIL = 0x01; private static final int FLAG_POSITION = 0x20; + private BonesChain bones; /** The number of affected bones. Zero means that all parent bones of the current bone should take part in baking. */ private int bonesAffected; - /** The total length of the bone chain. Useful for optimisation of computations speed in some cases. */ - private double chainLength; /** Indicates if the tail of the bone should be used or not. */ private boolean useTail; /** The amount of iterations of the algorithm. */ @@ -51,122 +47,85 @@ public class ConstraintDefinitionIK extends ConstraintDefinition { } } + @Override + public Set getAlteredOmas() { + return bones.alteredOmas; + } + @Override public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) { if (influence == 0 || !trackToBeChanged || targetTransform == null) { return;// no need to do anything } + DQuaternion q = new DQuaternion(); Vector3d t = new Vector3d(targetTransform.getTranslation()); - List bones = this.loadBones(); + bones = new BonesChain((Bone) this.getOwner(), useTail, bonesAffected, blenderContext); if (bones.size() == 0) { return;// no need to do anything } double distanceFromTarget = Double.MAX_VALUE; - int iterations = this.iterations; - if (bones.size() == 1) { - iterations = 1;// if only one bone is in the chain then only one iteration that will properly rotate it will be needed - } else { - // if the target cannot be rached by the bones' chain then the chain will become straight and point towards the target - // in this case only one iteration will be needed, computed from the root to top bone - BoneContext rootBone = bones.get(bones.size() - 1); - Transform rootBoneTransform = constraintHelper.getTransform(rootBone.getArmatureObjectOMA(), rootBone.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD); - if (t.distance(new Vector3d(rootBoneTransform.getTranslation())) >= chainLength) { - Collections.reverse(bones); - - for (BoneContext boneContext : bones) { - Bone bone = boneContext.getBone(); - DTransform boneTransform = new DTransform(constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD)); - - Vector3d e = boneTransform.getTranslation().add(boneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(boneContext.getLength()));// effector - Vector3d j = boneTransform.getTranslation(); // current join position - - Vector3d currentDir = e.subtractLocal(j).normalizeLocal(); - Vector3d target = t.subtract(j).normalizeLocal(); - double angle = currentDir.angleBetween(target); - if (angle != 0) { - Vector3d cross = currentDir.crossLocal(target).normalizeLocal(); - q.fromAngleAxis(angle, cross); - - if(bone.equals(this.getOwner())) { - if (boneContext.isLockX()) { - q.set(0, q.getY(), q.getZ(), q.getW()); - } - if (boneContext.isLockY()) { - q.set(q.getX(), 0, q.getZ(), q.getW()); - } - if (boneContext.isLockZ()) { - q.set(q.getX(), q.getY(), 0, q.getW()); - } - } - - boneTransform.getRotation().set(q.multLocal(boneTransform.getRotation())); - constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD, boneTransform.toTransform()); - } - } - - iterations = 0; + Vector3d target = new Vector3d(targetTransform.getTranslation()); + Vector3d[] rotationVectors = new Vector3d[bones.size()]; + BoneContext topBone = bones.get(0); + for (int i = 1; i <= iterations; ++i) { + DTransform topBoneTransform = bones.getWorldTransform(topBone); + Vector3d e = topBoneTransform.getTranslation().add(topBoneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(topBone.getLength()));// effector + distanceFromTarget = e.distance(t); + if (distanceFromTarget <= MIN_DISTANCE) { + break; } - } - List bestSolution = new ArrayList(bones.size()); - double bestSolutionDistance = Double.MAX_VALUE; - BoneContext topBone = bones.get(0); - for (int i = 0; i < iterations && distanceFromTarget > MIN_DISTANCE; ++i) { - for (BoneContext boneContext : bones) { - Bone bone = boneContext.getBone(); - DTransform topBoneTransform = new DTransform(constraintHelper.getTransform(topBone.getArmatureObjectOMA(), topBone.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD)); - DTransform boneWorldTransform = new DTransform(constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD)); + Matrix deltaP = new Matrix(3, 1); + deltaP.setColumn(target.subtract(e), 0); - Vector3d e = topBoneTransform.getTranslation().addLocal(topBoneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(topBone.getLength()));// effector + Matrix J = new Matrix(3, bones.size()); + int column = 0; + for (BoneContext boneContext : bones) { + DTransform boneWorldTransform = bones.getWorldTransform(boneContext); Vector3d j = boneWorldTransform.getTranslation(); // current join position + Vector3d vectorFromJointToEffector = e.subtract(j); + rotationVectors[column] = vectorFromJointToEffector.cross(target.subtract(j)).normalize(); + Vector3d col = rotationVectors[column].cross(vectorFromJointToEffector); + J.setColumn(col, column++); + } + Matrix J_1 = J.pseudoinverse(); - Vector3d currentDir = e.subtractLocal(j).normalizeLocal(); - Vector3d target = t.subtract(j).normalizeLocal(); - double angle = currentDir.angleBetween(target); - if (angle != 0) { - Vector3d cross = currentDir.crossLocal(target).normalizeLocal(); - q.fromAngleAxis(angle, cross); - - if(bone.equals(this.getOwner())) { - if (boneContext.isLockX()) { - q.set(0, q.getY(), q.getZ(), q.getW()); - } - if (boneContext.isLockY()) { - q.set(q.getX(), 0, q.getZ(), q.getW()); - } - if (boneContext.isLockZ()) { - q.set(q.getX(), q.getY(), 0, q.getW()); - } - } + SimpleMatrix deltaThetas = J_1.mult(deltaP); - boneWorldTransform.getRotation().set(q.multLocal(boneWorldTransform.getRotation())); - constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), bone.getName(), Space.CONSTRAINT_SPACE_WORLD, boneWorldTransform.toTransform()); - } else { - iterations = 0; - break; - } - } + for (int j = 0; j < deltaThetas.numRows(); ++j) { + double angle = deltaThetas.get(j, 0); + Vector3d rotationVector = rotationVectors[j]; - DTransform topBoneTransform = new DTransform(constraintHelper.getTransform(topBone.getArmatureObjectOMA(), topBone.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD)); - Vector3d e = topBoneTransform.getTranslation().addLocal(topBoneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(topBone.getLength()));// effector - distanceFromTarget = e.distance(t); - - if(distanceFromTarget < bestSolutionDistance) { - bestSolutionDistance = distanceFromTarget; - bestSolution.clear(); - for(BoneContext boneContext : bones) { - bestSolution.add(constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD)); + q.fromAngleAxis(angle, rotationVector); + BoneContext boneContext = bones.get(j); + Bone bone = boneContext.getBone(); + if (bone.equals(this.getOwner())) { + if (boneContext.isLockX()) { + q.set(0, q.getY(), q.getZ(), q.getW()); + } + if (boneContext.isLockY()) { + q.set(q.getX(), 0, q.getZ(), q.getW()); + } + if (boneContext.isLockZ()) { + q.set(q.getX(), q.getY(), 0, q.getW()); + } } + + DTransform boneTransform = bones.getWorldTransform(boneContext); + boneTransform.getRotation().set(q.mult(boneTransform.getRotation())); + bones.setWorldTransform(boneContext, boneTransform); } } - - // applying best solution - for(int i=0;i= 0; --i) { BoneContext boneContext = bones.get(i); - constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD, bestSolution.get(i)); + DTransform transform = bones.getWorldTransform(boneContext); + constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD, transform.toTransform()); } + bones.reset(); } @Override @@ -174,49 +133,12 @@ public class ConstraintDefinitionIK extends ConstraintDefinition { return "Inverse kinematics"; } - /** - * @return the bone contexts of all bones that will be used in this constraint computations - */ - private List loadBones() { - List bones = new ArrayList(); - Bone bone = (Bone) this.getOwner(); - if (bone == null) { - return bones; - } - if (!useTail) { - bone = bone.getParent(); - } - chainLength = 0; - while (bone != null) { - BoneContext boneContext = blenderContext.getBoneContext(bone); - chainLength += boneContext.getLength(); - bones.add(boneContext); - alteredOmas.add(boneContext.getBoneOma()); - if (bonesAffected != 0 && bones.size() >= bonesAffected) { - break; - } - // need to add spaces between bones to the chain length - Transform boneWorldTransform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD); - Vector3f boneWorldTranslation = boneWorldTransform.getTranslation(); - - bone = bone.getParent(); - - if (bone != null) { - boneContext = blenderContext.getBoneContext(bone); - Transform parentWorldTransform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD); - Vector3f parentWorldTranslation = parentWorldTransform.getTranslation(); - chainLength += boneWorldTranslation.distance(parentWorldTranslation); - } - } - return bones; - } - @Override public boolean isTrackToBeChanged() { if (trackToBeChanged) { // need to check the bone structure too (when constructor was called not all of the bones might have been loaded yet) // that is why it is also checked here - List bones = this.loadBones(); + bones = new BonesChain((Bone) this.getOwner(), useTail, bonesAffected, blenderContext); trackToBeChanged = bones.size() > 0; } return trackToBeChanged; @@ -226,4 +148,68 @@ public class ConstraintDefinitionIK extends ConstraintDefinition { public boolean isTargetRequired() { return true; } + + private static class BonesChain extends ArrayList { + private static final long serialVersionUID = -1850524345643600718L; + + private Set alteredOmas = new HashSet(); + private List originalBonesMatrices = new ArrayList(); + private List bonesMatrices = new ArrayList(); + + public BonesChain(Bone bone, boolean useTail, int bonesAffected, BlenderContext blenderContext) { + if (bone != null) { + ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class); + if (!useTail) { + bone = bone.getParent(); + } + while (bone != null && this.size() < bonesAffected) { + BoneContext boneContext = blenderContext.getBoneContext(bone); + this.add(boneContext); + alteredOmas.add(boneContext.getBoneOma()); + + Space space = this.size() < bonesAffected ? Space.CONSTRAINT_SPACE_LOCAL : Space.CONSTRAINT_SPACE_WORLD; + Transform transform = constraintHelper.getTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), space); + originalBonesMatrices.add(new DTransform(transform).toMatrix()); + + bone = bone.getParent(); + } + this.reset(); + } + } + + public DTransform getWorldTransform(BoneContext bone) { + int index = this.indexOf(bone); + return this.getWorldMatrix(index).toTransform(); + } + + public void setWorldTransform(BoneContext bone, DTransform transform) { + int index = this.indexOf(bone); + Matrix boneMatrix = transform.toMatrix(); + + if (index < this.size() - 1) { + // computing the current bone local transform + Matrix parentWorldMatrix = this.getWorldMatrix(index + 1); + SimpleMatrix m = parentWorldMatrix.invert().mult(boneMatrix); + boneMatrix = new Matrix(m); + } + bonesMatrices.set(index, boneMatrix); + } + + public Matrix getWorldMatrix(int index) { + if (index == this.size() - 1) { + return new Matrix(bonesMatrices.get(this.size() - 1)); + } + + SimpleMatrix result = this.getWorldMatrix(index + 1); + result = result.mult(bonesMatrices.get(index)); + return new Matrix(result); + } + + public void reset() { + bonesMatrices.clear(); + for (Matrix m : originalBonesMatrices) { + bonesMatrices.add(new Matrix(m)); + } + } + } } diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DQuaternion.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DQuaternion.java index 359abf057..9739ccd4b 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DQuaternion.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DQuaternion.java @@ -164,6 +164,134 @@ public final class DQuaternion implements Savable, Cloneable, java.io.Serializab w = 1; } + /** + * norm returns the norm of this quaternion. This is the dot + * product of this quaternion with itself. + * + * @return the norm of the quaternion. + */ + public double norm() { + return w * w + x * x + y * y + z * z; + } + + public DQuaternion fromRotationMatrix(double m00, double m01, double m02, + double m10, double m11, double m12, double m20, double m21, double m22) { + // first normalize the forward (F), up (U) and side (S) vectors of the rotation matrix + // so that the scale does not affect the rotation + double lengthSquared = m00 * m00 + m10 * m10 + m20 * m20; + if (lengthSquared != 1f && lengthSquared != 0f) { + lengthSquared = 1.0 / Math.sqrt(lengthSquared); + m00 *= lengthSquared; + m10 *= lengthSquared; + m20 *= lengthSquared; + } + lengthSquared = m01 * m01 + m11 * m11 + m21 * m21; + if (lengthSquared != 1 && lengthSquared != 0f) { + lengthSquared = 1.0 / Math.sqrt(lengthSquared); + m01 *= lengthSquared; + m11 *= lengthSquared; + m21 *= lengthSquared; + } + lengthSquared = m02 * m02 + m12 * m12 + m22 * m22; + if (lengthSquared != 1f && lengthSquared != 0f) { + lengthSquared = 1.0 / Math.sqrt(lengthSquared); + m02 *= lengthSquared; + m12 *= lengthSquared; + m22 *= lengthSquared; + } + + // Use the Graphics Gems code, from + // ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z + // *NOT* the "Matrix and Quaternions FAQ", which has errors! + + // the trace is the sum of the diagonal elements; see + // http://mathworld.wolfram.com/MatrixTrace.html + double t = m00 + m11 + m22; + + // we protect the division by s by ensuring that s>=1 + if (t >= 0) { // |w| >= .5 + double s = Math.sqrt(t + 1); // |s|>=1 ... + w = 0.5f * s; + s = 0.5f / s; // so this division isn't bad + x = (m21 - m12) * s; + y = (m02 - m20) * s; + z = (m10 - m01) * s; + } else if (m00 > m11 && m00 > m22) { + double s = Math.sqrt(1.0 + m00 - m11 - m22); // |s|>=1 + x = s * 0.5f; // |x| >= .5 + s = 0.5f / s; + y = (m10 + m01) * s; + z = (m02 + m20) * s; + w = (m21 - m12) * s; + } else if (m11 > m22) { + double s = Math.sqrt(1.0 + m11 - m00 - m22); // |s|>=1 + y = s * 0.5f; // |y| >= .5 + s = 0.5f / s; + x = (m10 + m01) * s; + z = (m21 + m12) * s; + w = (m02 - m20) * s; + } else { + double s = Math.sqrt(1.0 + m22 - m00 - m11); // |s|>=1 + z = s * 0.5f; // |z| >= .5 + s = 0.5f / s; + x = (m02 + m20) * s; + y = (m21 + m12) * s; + w = (m10 - m01) * s; + } + + return this; + } + + /** + * toRotationMatrix converts this quaternion to a rotational + * matrix. The result is stored in result. 4th row and 4th column values are + * untouched. Note: the result is created from a normalized version of this quat. + * + * @param result + * The Matrix4f to store the result in. + * @return the rotation matrix representation of this quaternion. + */ + public Matrix toRotationMatrix(Matrix result) { + Vector3d originalScale = new Vector3d(); + + result.toScaleVector(originalScale); + result.setScale(1, 1, 1); + double norm = this.norm(); + // we explicitly test norm against one here, saving a division + // at the cost of a test and branch. Is it worth it? + double s = norm == 1f ? 2f : norm > 0f ? 2f / norm : 0; + + // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs + // will be used 2-4 times each. + double xs = x * s; + double ys = y * s; + double zs = z * s; + double xx = x * xs; + double xy = x * ys; + double xz = x * zs; + double xw = w * xs; + double yy = y * ys; + double yz = y * zs; + double yw = w * ys; + double zz = z * zs; + double zw = w * zs; + + // using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here + result.set(0, 0, 1 - (yy + zz)); + result.set(0, 1, xy - zw); + result.set(0, 2, xz + yw); + result.set(1, 0, xy + zw); + result.set(1, 1, 1 - (xx + zz)); + result.set(1, 2, yz - xw); + result.set(2, 0, xz - yw); + result.set(2, 1, yz + xw); + result.set(2, 2, 1 - (xx + yy)); + + result.setScale(originalScale); + + return result; + } + /** * fromAngleAxis sets this quaternion to the values specified * by an angle and an axis of rotation. This method creates an object, so diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DTransform.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DTransform.java index ed31a4c98..28fcda0c7 100644 --- a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DTransform.java +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/DTransform.java @@ -31,11 +31,15 @@ */ package com.jme3.scene.plugins.blender.math; -import com.jme3.export.*; -import com.jme3.math.Transform; - import java.io.IOException; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.export.Savable; +import com.jme3.math.Transform; + /** * Started Date: Jul 16, 2004
*
@@ -57,6 +61,12 @@ public final class DTransform implements Savable, Cloneable, java.io.Serializabl private Vector3d translation; private Vector3d scale; + public DTransform() { + translation = new Vector3d(); + rotation = new DQuaternion(); + scale = new Vector3d(); + } + public DTransform(Transform transform) { translation = new Vector3d(transform.getTranslation()); rotation = new DQuaternion(transform.getRotation()); @@ -66,7 +76,15 @@ public final class DTransform implements Savable, Cloneable, java.io.Serializabl public Transform toTransform() { return new Transform(translation.toVector3f(), rotation.toQuaternion(), scale.toVector3f()); } - + + public Matrix toMatrix() { + Matrix m = Matrix.identity(4); + m.setTranslation(translation); + m.setRotationQuaternion(rotation); + m.setScale(scale); + return m; + } + /** * Sets this translation to the given value. * @param trans diff --git a/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Matrix.java b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Matrix.java new file mode 100644 index 000000000..5ea580b84 --- /dev/null +++ b/jme3-blender/src/main/java/com/jme3/scene/plugins/blender/math/Matrix.java @@ -0,0 +1,214 @@ +package com.jme3.scene.plugins.blender.math; + +import java.text.DecimalFormat; + +import org.ejml.ops.CommonOps; +import org.ejml.simple.SimpleMatrix; +import org.ejml.simple.SimpleSVD; + +import com.jme3.math.FastMath; + +/** + * Encapsulates a 4x4 matrix + * + * + */ +public class Matrix extends SimpleMatrix { + private static final long serialVersionUID = 2396600537315902559L; + + public Matrix(int rows, int cols) { + super(rows, cols); + } + + /** + * Copy constructor + */ + public Matrix(SimpleMatrix m) { + super(m); + } + + public Matrix(double[][] data) { + super(data); + } + + public static Matrix identity(int size) { + Matrix result = new Matrix(size, size); + CommonOps.setIdentity(result.mat); + return result; + } + + public Matrix pseudoinverse() { + return this.pseudoinverse(1); + } + + @SuppressWarnings("unchecked") + public Matrix pseudoinverse(double lambda) { + SimpleSVD simpleSVD = this.svd(); + + SimpleMatrix U = simpleSVD.getU(); + SimpleMatrix S = simpleSVD.getW(); + SimpleMatrix V = simpleSVD.getV(); + + int N = Math.min(this.numRows(),this.numCols()); + double maxSingular = 0; + for( int i = 0; i < N; i++ ) { + if( S.get(i, i) > maxSingular ) { + maxSingular = S.get(i, i); + } + } + + double tolerance = FastMath.DBL_EPSILON * Math.max(this.numRows(),this.numCols()) * maxSingular; + for(int i=0;isetRotationQuaternion builds a rotation from a + * Quaternion. + * + * @param quat + * the quaternion to build the rotation from. + * @throws NullPointerException + * if quat is null. + */ + public void setRotationQuaternion(DQuaternion quat) { + quat.toRotationMatrix(this); + } + + public DTransform toTransform() { + DTransform result = new DTransform(); + result.setTranslation(this.toTranslationVector()); + result.setRotation(this.toRotationQuat()); + result.setScale(this.toScaleVector()); + return result; + } + + public Vector3d toTranslationVector() { + return new Vector3d(this.get(0, 3), this.get(1, 3), this.get(2, 3)); + } + + public DQuaternion toRotationQuat() { + DQuaternion quat = new DQuaternion(); + quat.fromRotationMatrix(this.get(0, 0), this.get(0, 1), this.get(0, 2), this.get(1, 0), this.get(1, 1), this.get(1, 2), this.get(2, 0), this.get(2, 1), this.get(2, 2)); + return quat; + } + + /** + * Retreives the scale vector from the matrix and stores it into a given + * vector. + * + * @param the + * vector where the scale will be stored + */ + public Vector3d toScaleVector() { + Vector3d result = new Vector3d(); + this.toScaleVector(result); + return result; + } + + /** + * Retreives the scale vector from the matrix and stores it into a given + * vector. + * + * @param the + * vector where the scale will be stored + */ + public void toScaleVector(Vector3d vector) { + double scaleX = Math.sqrt(this.get(0, 0) * this.get(0, 0) + this.get(1, 0) * this.get(1, 0) + this.get(2, 0) * this.get(2, 0)); + double scaleY = Math.sqrt(this.get(0, 1) * this.get(0, 1) + this.get(1, 1) * this.get(1, 1) + this.get(2, 1) * this.get(2, 1)); + double scaleZ = Math.sqrt(this.get(0, 2) * this.get(0, 2) + this.get(1, 2) * this.get(1, 2) + this.get(2, 2) * this.get(2, 2)); + vector.set(scaleX, scaleY, scaleZ); + } +} From b8fe36ed7650473097cc0f8fb58648d4cb725d1b Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Thu, 18 Jun 2015 23:00:17 -0400 Subject: [PATCH 19/29] glsllib with macros to convert glsl 1.1 shaders to 1.5 --- .../Common/ShaderLib/GLSL150Compat.glsllib | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib diff --git a/jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib b/jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib new file mode 100644 index 000000000..336490696 --- /dev/null +++ b/jme3-core/src/main/resources/Common/ShaderLib/GLSL150Compat.glsllib @@ -0,0 +1,14 @@ +#if _VERSION_ >= 150 +out vec4 outFragColor; +# define texture1D texture +# define texture2D texture +# define texture3D texture +# define texture2DLod texture +# if defined VERTEX_SHADER +# define varying out +# define attribute in +# elif defined FRAGMENT_SHADER +# define varying in +# define gl_FragColor outFragColor +# endif +#endif \ No newline at end of file From 43dc7345d0ea32f2cd3d00d520c6a4b0dfb10f9c Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 19 Jun 2015 22:21:56 +0200 Subject: [PATCH 20/29] Changed to VertexUniformVectors --- jme3-core/src/main/java/com/jme3/renderer/Limits.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/Limits.java b/jme3-core/src/main/java/com/jme3/renderer/Limits.java index 7df9bc76b..86cddb178 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Limits.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Limits.java @@ -76,5 +76,5 @@ public enum Limits { DepthTextureSamples, - VertexUniformComponents, + VertexUniformVectors, } From 4cd0c5bffb17e8e7883c95eac03a5937c517464b Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 19 Jun 2015 22:22:40 +0200 Subject: [PATCH 21/29] Added MAX_VERTEX_UNIFORM_VECTORS constant //untested however --- jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 21eedab52..04f496332 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -100,6 +100,7 @@ public interface GL { public static final int GL_MAX_VERTEX_ATTRIBS = 0x8869; public static final int GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; public static final int GL_MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A; + public static final int GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; public static final int GL_MIRRORED_REPEAT = 0x8370; public static final int GL_NEAREST = 0x2600; public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702; From 8cb2be60feeeeea425759db9f3fc4d5208a91778 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 19 Jun 2015 22:26:12 +0200 Subject: [PATCH 22/29] Added a switch to use VECTORS on GLES and COMPONENTS/4 on Desktop --- .../com/jme3/renderer/opengl/GLRenderer.java | 367 +++++++++--------- 1 file changed, 193 insertions(+), 174 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index caf472543..2da5e28f9 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -56,6 +56,7 @@ import com.jme3.util.BufferUtils; import com.jme3.util.ListMap; import com.jme3.util.MipMapGenerator; import com.jme3.util.NativeObjectManager; + import java.nio.*; import java.util.Arrays; import java.util.EnumMap; @@ -66,6 +67,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; + import jme3tools.shader.ShaderDebug; public class GLRenderer implements Renderer { @@ -73,7 +75,7 @@ public class GLRenderer implements Renderer { private static final Logger logger = Logger.getLogger(GLRenderer.class.getName()); private static final boolean VALIDATE_SHADER = false; private static final Pattern GLVERSION_PATTERN = Pattern.compile(".*?(\\d+)\\.(\\d+).*"); - + private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); private final StringBuilder stringBuf = new StringBuilder(250); private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); @@ -83,7 +85,7 @@ public class GLRenderer implements Renderer { private final NativeObjectManager objManager = new NativeObjectManager(); private final EnumSet caps = EnumSet.noneOf(Caps.class); private final EnumMap limits = new EnumMap(Limits.class); - + private FrameBuffer mainFbOverride = null; private final Statistics statistics = new Statistics(); private int vpX, vpY, vpW, vpH; @@ -98,12 +100,12 @@ public class GLRenderer implements Renderer { private final GLExt glext; private final GLFbo glfbo; private final TextureUtil texUtil; - + public GLRenderer(GL gl, GLExt glext, GLFbo glfbo) { this.gl = gl; - this.gl2 = gl instanceof GL2 ? (GL2)gl : null; - this.gl3 = gl instanceof GL3 ? (GL3)gl : null; - this.gl4 = gl instanceof GL4 ? (GL4)gl : null; + this.gl2 = gl instanceof GL2 ? (GL2) gl : null; + this.gl3 = gl instanceof GL3 ? (GL3) gl : null; + this.gl4 = gl instanceof GL4 ? (GL4) gl : null; this.glfbo = glfbo; this.glext = glext; this.texUtil = new TextureUtil(gl, gl2, glext, context); @@ -118,7 +120,7 @@ public class GLRenderer implements Renderer { public EnumSet getCaps() { return caps; } - + // Not making public yet ... public EnumMap getLimits() { return limits; @@ -140,7 +142,7 @@ public class GLRenderer implements Renderer { } return extensionSet; } - + public static int extractVersion(String version) { Matcher m = GLVERSION_PATTERN.matcher(version); if (m.matches()) { @@ -160,17 +162,17 @@ public class GLRenderer implements Renderer { private boolean hasExtension(String extensionName) { return extensions.contains(extensionName); } - + private void loadCapabilitiesES() { caps.add(Caps.GLSL100); caps.add(Caps.OpenGLES20); - + // Important: Do not add OpenGL20 - that's the desktop capability! } - + private void loadCapabilitiesGL2() { int oglVer = extractVersion(gl.glGetString(GL.GL_VERSION)); - + if (oglVer >= 200) { caps.add(Caps.OpenGL20); if (oglVer >= 210) { @@ -194,7 +196,7 @@ public class GLRenderer implements Renderer { } } } - + int glslVer = extractVersion(gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)); switch (glslVer) { @@ -222,27 +224,27 @@ public class GLRenderer implements Renderer { caps.add(Caps.GLSL100); break; } - + // Workaround, always assume we support GLSL100 & GLSL110 // Supporting OpenGL 2.0 means supporting GLSL 1.10. caps.add(Caps.GLSL110); caps.add(Caps.GLSL100); - + // Fix issue in TestRenderToMemory when GL.GL_FRONT is the main // buffer being used. context.initialDrawBuf = getInteger(GL2.GL_DRAW_BUFFER); context.initialReadBuf = getInteger(GL2.GL_READ_BUFFER); - + // XXX: This has to be GL.GL_BACK for canvas on Mac // Since initialDrawBuf is GL.GL_FRONT for pbuffer, gotta // change this value later on ... // initialDrawBuf = GL.GL_BACK; // initialReadBuf = GL.GL_BACK; } - + private void loadCapabilitiesCommon() { extensions = loadExtensions(); - + limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); if (limits.get(Limits.VertexTextureUnits) > 0) { caps.add(Caps.VertexTextureFetch); @@ -257,62 +259,66 @@ public class GLRenderer implements Renderer { // gl.glGetInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16); // fragUniforms = intBuf16.get(0); // logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - limits.put(Limits.VertexUniformComponents,getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS)); + if (caps.contains(Caps.OpenGLES20)) { + limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_VECTORS)); + } else { + limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4); + } limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS)); limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE)); - if (hasExtension("GL_ARB_draw_instanced") && - hasExtension("GL_ARB_instanced_arrays")) { + if (hasExtension("GL_ARB_draw_instanced") && + hasExtension("GL_ARB_instanced_arrays")) { caps.add(Caps.MeshInstancing); } if (hasExtension("GL_OES_element_index_uint") || gl2 != null) { caps.add(Caps.IntegerIndexBuffer); } - + if (hasExtension("GL_ARB_texture_buffer_object")) { caps.add(Caps.TextureBuffer); } - + // == texture format extensions == - + boolean hasFloatTexture; hasFloatTexture = hasExtension("GL_OES_texture_half_float") && - hasExtension("GL_OES_texture_float"); - + hasExtension("GL_OES_texture_float"); + if (!hasFloatTexture) { hasFloatTexture = hasExtension("GL_ARB_texture_float") && - hasExtension("GL_ARB_half_float_pixel"); - + hasExtension("GL_ARB_half_float_pixel"); + if (!hasFloatTexture) { hasFloatTexture = caps.contains(Caps.OpenGL30); } } - + if (hasFloatTexture) { caps.add(Caps.FloatTexture); } - + if (hasExtension("GL_OES_depth_texture") || gl2 != null) { caps.add(Caps.DepthTexture); - + // TODO: GL_OES_depth24 } - - if (hasExtension("GL_OES_rgb8_rgba8") || - hasExtension("GL_ARM_rgba8") || - hasExtension("GL_EXT_texture_format_BGRA8888")) { + + if (hasExtension("GL_OES_rgb8_rgba8") || + hasExtension("GL_ARM_rgba8") || + hasExtension("GL_EXT_texture_format_BGRA8888")) { caps.add(Caps.Rgba8); } - + if (caps.contains(Caps.OpenGL30) || hasExtension("GL_OES_packed_depth_stencil")) { caps.add(Caps.PackedDepthStencilBuffer); } if (hasExtension("GL_ARB_color_buffer_float") && - hasExtension("GL_ARB_half_float_pixel")) { + hasExtension("GL_ARB_half_float_pixel")) { // XXX: Require both 16 and 32 bit float support for FloatColorBuffer. caps.add(Caps.FloatColorBuffer); } @@ -321,44 +327,44 @@ public class GLRenderer implements Renderer { caps.add(Caps.FloatDepthBuffer); } - if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || - caps.contains(Caps.OpenGL30)) { + if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || + caps.contains(Caps.OpenGL30)) { // Either OpenGL3 is available or both packed_float & half_float_pixel. caps.add(Caps.PackedFloatColorBuffer); caps.add(Caps.PackedFloatTexture); } - + if (hasExtension("GL_EXT_texture_shared_exponent") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.SharedExponentTexture); } - + if (hasExtension("GL_EXT_texture_compression_s3tc")) { caps.add(Caps.TextureCompressionS3TC); } - + if (hasExtension("GL_ARB_ES3_compatibility")) { caps.add(Caps.TextureCompressionETC2); caps.add(Caps.TextureCompressionETC1); } else if (hasExtension("GL_OES_compressed_ETC1_RGB8_texture")) { caps.add(Caps.TextureCompressionETC1); } - + // == end texture format extensions == - + if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.VertexBufferArray); } - if (hasExtension("GL_ARB_texture_non_power_of_two") || - hasExtension("GL_OES_texture_npot") || - caps.contains(Caps.OpenGL30)) { + if (hasExtension("GL_ARB_texture_non_power_of_two") || + hasExtension("GL_OES_texture_npot") || + caps.contains(Caps.OpenGL30)) { caps.add(Caps.NonPowerOfTwoTextures); } else { logger.log(Level.WARNING, "Your graphics card does not " - + "support non-power-of-2 textures. " - + "Some features might not work."); + + "support non-power-of-2 textures. " + + "Some features might not work."); } - + if (caps.contains(Caps.OpenGLES20)) { // OpenGL ES 2 has some limited support for NPOT textures caps.add(Caps.PartialNonPowerOfTwoTextures); @@ -374,14 +380,14 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_EXT_framebuffer_object") || gl3 != null) { caps.add(Caps.FrameBuffer); - + limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT)); limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT)); - + if (hasExtension("GL_EXT_framebuffer_blit")) { caps.add(Caps.FrameBufferBlit); } - + if (hasExtension("GL_EXT_framebuffer_multisample")) { caps.add(Caps.FrameBufferMultisample); limits.put(Limits.FrameBufferSamples, getInteger(GLExt.GL_MAX_SAMPLES_EXT)); @@ -419,10 +425,10 @@ public class GLRenderer implements Renderer { } caps.add(Caps.Multisample); } - + // Supports sRGB pipeline. - if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) - || caps.contains(Caps.OpenGL30) ) { + if ((hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) + || caps.contains(Caps.OpenGL30)) { caps.add(Caps.Srgb); } @@ -430,47 +436,46 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_ARB_seamless_cube_map") || caps.contains(Caps.OpenGL32)) { caps.add(Caps.SeamlessCubemap); } - + if (caps.contains(Caps.OpenGL32) && !hasExtension("GL_ARB_compatibility")) { caps.add(Caps.CoreProfile); } - + if (hasExtension("GL_ARB_get_program_binary")) { int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); if (binaryFormats > 0) { caps.add(Caps.BinaryShader); } } - + // Print context information logger.log(Level.INFO, "OpenGL Renderer Information\n" + - " * Vendor: {0}\n" + - " * Renderer: {1}\n" + - " * OpenGL Version: {2}\n" + - " * GLSL Version: {3}\n" + - " * Profile: {4}", - new Object[]{ - gl.glGetString(GL.GL_VENDOR), - gl.glGetString(GL.GL_RENDERER), - gl.glGetString(GL.GL_VERSION), - gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION), - caps.contains(Caps.CoreProfile) ? "Core" : "Compatibility" - }); - + " * Vendor: {0}\n" + + " * Renderer: {1}\n" + + " * OpenGL Version: {2}\n" + + " * GLSL Version: {3}\n" + + " * Profile: {4}", + new Object[]{ + gl.glGetString(GL.GL_VENDOR), + gl.glGetString(GL.GL_RENDERER), + gl.glGetString(GL.GL_VERSION), + gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION), + caps.contains(Caps.CoreProfile) ? "Core" : "Compatibility" + }); + // Print capabilities (if fine logging is enabled) if (logger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(); sb.append("Supported capabilities: \n"); - for (Caps cap : caps) - { + for (Caps cap : caps) { sb.append("\t").append(cap.toString()).append("\n"); } logger.log(Level.FINE, sb.toString()); } - + texUtil.initialize(caps); } - + private void loadCapabilities() { if (gl2 != null) { loadCapabilitiesGL2(); @@ -479,31 +484,31 @@ public class GLRenderer implements Renderer { } loadCapabilitiesCommon(); } - + private int getInteger(int en) { intBuf16.clear(); gl.glGetInteger(en, intBuf16); return intBuf16.get(0); } - + private boolean getBoolean(int en) { gl.glGetBoolean(en, nameBuf); - return nameBuf.get(0) != (byte)0; + return nameBuf.get(0) != (byte) 0; } - + @SuppressWarnings("fallthrough") public void initialize() { loadCapabilities(); - + // Initialize default state.. gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); - + if (caps.contains(Caps.CoreProfile)) { // Core Profile requires VAO to be bound. gl3.glGenVertexArrays(intBuf16); int vaoId = intBuf16.get(0); gl3.glBindVertexArray(vaoId); - } + } if (gl2 != null) { gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE); if (!caps.contains(Caps.CoreProfile)) { @@ -535,9 +540,11 @@ public class GLRenderer implements Renderer { invalidateState(); } - /*********************************************************************\ - |* Render State *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Render State *| + * \******************************************************************** + */ public void setDepthRange(float start, float end) { gl.glDepthRange(start, end); } @@ -602,7 +609,7 @@ public class GLRenderer implements Renderer { } if (state.isDepthTest() && !context.depthTestEnabled) { - gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(convertTestFunction(context.depthFunc)); context.depthTestEnabled = true; } else if (!state.isDepthTest() && context.depthTestEnabled) { @@ -714,7 +721,7 @@ public class GLRenderer implements Renderer { case Color: case Screen: gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; + break; case Exclusion: gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR); break; @@ -814,9 +821,11 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Camera and World transforms *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Camera and World transforms *| + * \******************************************************************** + */ public void setViewPort(int x, int y, int w, int h) { if (x != vpX || vpY != y || vpW != w || vpH != h) { gl.glViewport(x, y, w, h); @@ -858,9 +867,11 @@ public class GLRenderer implements Renderer { gl.resetStats(); } - /*********************************************************************\ - |* Shaders *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Shaders *| + * \******************************************************************** + */ protected void updateUniformLocation(Shader shader, Uniform uniform) { int loc = gl.glGetUniformLocation(shader.getId(), uniform.getName()); if (loc < 0) { @@ -1040,12 +1051,12 @@ public class GLRenderer implements Renderer { boolean gles2 = caps.contains(Caps.OpenGLES20); String language = source.getLanguage(); - + if (gles2 && !language.equals("GLSL100")) { throw new RendererException("This shader cannot run in OpenGL ES 2. " - + "Only GLSL 1.00 shaders are supported."); + + "Only GLSL 1.00 shaders are supported."); } - + // Upload shader source. // Merge the defines and source code. stringBuf.setLength(0); @@ -1072,17 +1083,17 @@ public class GLRenderer implements Renderer { } } } - + if (linearizeSrgbImages) { stringBuf.append("#define SRGB 1\n"); } - + stringBuf.append(source.getDefines()); stringBuf.append(source.getSource()); - + intBuf1.clear(); intBuf1.put(0, stringBuf.length()); - gl.glShaderSource(id, new String[]{ stringBuf.toString() }, intBuf1); + gl.glShaderSource(id, new String[]{stringBuf.toString()}, intBuf1); gl.glCompileShader(id); gl.glGetShader(id, GL.GL_COMPILE_STATUS, intBuf1); @@ -1137,7 +1148,7 @@ public class GLRenderer implements Renderer { // If using GLSL 1.5, we bind the outputs for the user // For versions 3.3 and up, user should use layout qualifiers instead. boolean bindFragDataRequired = false; - + for (ShaderSource source : shader.getSources()) { if (source.isUpdateNeeded()) { updateShaderSourceData(source); @@ -1245,9 +1256,11 @@ public class GLRenderer implements Renderer { shader.resetObject(); } - /*********************************************************************\ - |* Framebuffers *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Framebuffers *| + * \******************************************************************** + */ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { copyFrameBuffer(src, dst, true); } @@ -1402,7 +1415,7 @@ public class GLRenderer implements Renderer { } else if (attachmentSlot < 0 || attachmentSlot >= 16) { throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); } - + return GLFbo.GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; } @@ -1412,7 +1425,7 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded()) { // Check NPOT requirements checkNonPowerOfTwo(tex); - + updateTexImageData(image, tex.getType(), 0, false); // NOTE: For depth textures, sets nearest/no-mips mode @@ -1476,7 +1489,7 @@ public class GLRenderer implements Renderer { } checkFrameBufferError(); - + fb.clearUpdateNeeded(); } @@ -1569,7 +1582,7 @@ public class GLRenderer implements Renderer { // update viewport to reflect framebuffer's resolution setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - + if (context.boundFBO != fb.getId()) { glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId()); statistics.onFrameBufferUse(fb, true); @@ -1640,7 +1653,7 @@ public class GLRenderer implements Renderer { public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { readFrameBufferWithGLFormat(fb, byteBuf, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); } - + private void readFrameBufferWithGLFormat(FrameBuffer fb, ByteBuffer byteBuf, int glFormat, int dataType) { if (fb != null) { RenderBuffer rb = fb.getColorBuffer(); @@ -1662,8 +1675,8 @@ public class GLRenderer implements Renderer { gl.glReadPixels(vpX, vpY, vpW, vpH, glFormat, dataType, byteBuf); } - - public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { + + public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { GLImageFormat glFormat = texUtil.getImageFormatWithError(format, false); readFrameBufferWithGLFormat(fb, byteBuf, glFormat.format, glFormat.dataType); } @@ -1695,15 +1708,17 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Textures *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Textures *| + * \******************************************************************** + */ private int convertTextureType(Texture.Type type, int samples, int face) { if (samples > 1 && !caps.contains(Caps.TextureMultisample)) { - throw new RendererException("Multisample textures are not supported" + - " by the video hardware."); + throw new RendererException("Multisample textures are not supported" + + " by the video hardware."); } - + switch (type) { case TwoDimensional: if (samples > 1) { @@ -1723,8 +1738,8 @@ public class GLRenderer implements Renderer { } case ThreeDimensional: if (!caps.contains(Caps.OpenGL20)) { - throw new RendererException("3D textures are not supported" + - " by the video hardware."); + throw new RendererException("3D textures are not supported" + + " by the video hardware."); } return GL2.GL_TEXTURE_3D; case CubeMap: @@ -1752,7 +1767,7 @@ public class GLRenderer implements Renderer { } private int convertMinFilter(Texture.MinFilter filter, boolean haveMips) { - if (haveMips){ + if (haveMips) { switch (filter) { case Trilinear: return GL.GL_LINEAR_MIPMAP_LINEAR; @@ -1807,11 +1822,11 @@ public class GLRenderer implements Renderer { int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); boolean haveMips = true; - + if (image != null) { haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps(); } - + // filter things if (image.getLastTextureState().magFilter != tex.getMagFilter()) { int magFilter = convertMagFilter(tex.getMagFilter()); @@ -1834,7 +1849,7 @@ public class GLRenderer implements Renderer { context.seamlessCubemap = false; } } - + if (tex.getAnisotropicFilter() > 1) { if (caps.contains(Caps.TextureFilterAnisotropic)) { gl.glTexParameterf(target, @@ -1867,19 +1882,19 @@ public class GLRenderer implements Renderer { throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); } - if(tex.isNeedCompareModeUpdate() && gl2 != null){ + if (tex.isNeedCompareModeUpdate() && gl2 != null) { // R to Texture compare mode if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); - gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); + gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL); } else { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL); } - }else{ - //restoring default value - gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); + } else { + //restoring default value + gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); } tex.compareModeUpdated(); } @@ -1888,10 +1903,10 @@ public class GLRenderer implements Renderer { /** * Validates if a potentially NPOT texture is supported by the hardware. *

- * Textures with power-of-2 dimensions are supported on all hardware, however + * Textures with power-of-2 dimensions are supported on all hardware, however * non-power-of-2 textures may or may not be supported depending on which * texturing features are used. - * + * * @param tex The texture to validate. * @throws RendererException If the texture is not supported by the hardware */ @@ -1900,23 +1915,23 @@ public class GLRenderer implements Renderer { // Texture is power-of-2, safe to use. return; } - + if (caps.contains(Caps.NonPowerOfTwoTextures)) { // Texture is NPOT but it is supported by video hardware. return; } - + // Maybe we have some / partial support for NPOT? if (!caps.contains(Caps.PartialNonPowerOfTwoTextures)) { // Cannot use any type of NPOT texture (uncommon) throw new RendererException("non-power-of-2 textures are not " - + "supported by the video hardware"); + + "supported by the video hardware"); } - + // Partial NPOT supported.. if (tex.getMinFilter().usesMipMapLevels()) { throw new RendererException("non-power-of-2 textures with mip-maps " - + "are not supported by the video hardware"); + + "are not supported by the video hardware"); } switch (tex.getType()) { @@ -1924,7 +1939,7 @@ public class GLRenderer implements Renderer { case ThreeDimensional: if (tex.getWrap(WrapAxis.R) != Texture.WrapMode.EdgeClamp) { throw new RendererException("repeating non-power-of-2 textures " - + "are not supported by the video hardware"); + + "are not supported by the video hardware"); } // fallthrough intentional!!! case TwoDimensionalArray: @@ -1932,22 +1947,22 @@ public class GLRenderer implements Renderer { if (tex.getWrap(WrapAxis.S) != Texture.WrapMode.EdgeClamp || tex.getWrap(WrapAxis.T) != Texture.WrapMode.EdgeClamp) { throw new RendererException("repeating non-power-of-2 textures " - + "are not supported by the video hardware"); + + "are not supported by the video hardware"); } break; default: throw new UnsupportedOperationException("unrecongized texture type"); } } - + /** * Uploads the given image to the GL driver. - * - * @param img The image to upload - * @param type How the data in the image argument should be interpreted. - * @param unit The texture slot to be used to upload the image, not important + * + * @param img The image to upload + * @param type How the data in the image argument should be interpreted. + * @param unit The texture slot to be used to upload the image, not important * @param scaleToPot If true, the image will be scaled to power-of-2 dimensions - * before being uploaded. + * before being uploaded. */ public void updateTexImageData(Image img, Texture.Type type, int unit, boolean scaleToPot) { int texId = img.getId(); @@ -1968,7 +1983,7 @@ public class GLRenderer implements Renderer { gl.glActiveTexture(GL.GL_TEXTURE0 + unit); context.boundTextureUnit = unit; } - + gl.glBindTexture(target, texId); context.boundTextures[unit] = img; @@ -2011,12 +2026,12 @@ public class GLRenderer implements Renderer { throw new RendererException("Multisample textures are not supported by the video hardware"); } } - + // Check if graphics card doesn't support depth textures if (img.getFormat().isDepthFormat() && !caps.contains(Caps.DepthTexture)) { throw new RendererException("Depth textures are not supported by the video hardware"); } - + if (target == GL.GL_TEXTURE_CUBE_MAP) { // Check max texture size before upload int cubeSize = limits.get(Limits.CubemapSize); @@ -2053,12 +2068,12 @@ public class GLRenderer implements Renderer { if (!caps.contains(Caps.TextureArray)) { throw new RendererException("Texture arrays not supported by graphics hardware"); } - + List data = imageForUpload.getData(); - + // -1 index specifies prepare data for 2D Array texUtil.uploadTexture(imageForUpload, target, -1, linearizeSrgbImages); - + for (int i = 0; i < data.size(); i++) { // upload each slice of 2D array in turn // this time with the appropriate index @@ -2087,21 +2102,21 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) { // Check NPOT requirements boolean scaleToPot = false; - + try { checkNonPowerOfTwo(tex); } catch (RendererException ex) { if (logger.isLoggable(Level.WARNING)) { int nextWidth = FastMath.nearestPowerOfTwo(tex.getImage().getWidth()); int nextHeight = FastMath.nearestPowerOfTwo(tex.getImage().getHeight()); - logger.log(Level.WARNING, - "Non-power-of-2 textures are not supported! Scaling texture '" + tex.getName() + - "' of size " + tex.getImage().getWidth() + "x" + tex.getImage().getHeight() + - " to " + nextWidth + "x" + nextHeight); + logger.log(Level.WARNING, + "Non-power-of-2 textures are not supported! Scaling texture '" + tex.getName() + + "' of size " + tex.getImage().getWidth() + "x" + tex.getImage().getHeight() + + " to " + nextWidth + "x" + nextHeight); } scaleToPot = true; } - + updateTexImageData(image, tex.getType(), unit, scaleToPot); } @@ -2146,9 +2161,11 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Vertex Buffers and Attributes *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Vertex Buffers and Attributes *| + * \******************************************************************** + */ private int convertUsage(Usage usage) { switch (usage) { case Static: @@ -2222,7 +2239,7 @@ public class GLRenderer implements Renderer { //statistics.onVertexBufferUse(vb, false); } } - + int usage = convertUsage(vb.getUsage()); vb.getData().rewind(); @@ -2283,7 +2300,7 @@ public class GLRenderer implements Renderer { if (context.boundShaderProgram <= 0) { throw new IllegalStateException("Cannot render mesh without shader bound"); } - + Attribute attrib = context.boundShader.getAttribute(vb.getBufferType()); int loc = attrib.getLocation(); if (loc == -1) { @@ -2413,7 +2430,7 @@ public class GLRenderer implements Renderer { // What is this? throw new RendererException("Unexpected format for index buffer: " + indexBuf.getFormat()); } - + if (indexBuf.isUpdateNeeded()) { updateBufferData(indexBuf); } @@ -2486,9 +2503,11 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Render Calls *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Render Calls *| + * \******************************************************************** + */ public int convertElementMode(Mesh.Mode mode) { switch (mode) { case Points: @@ -2530,7 +2549,7 @@ public class GLRenderer implements Renderer { if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); } - + if (instanceData != null) { setVertexAttrib(instanceData, null); } @@ -2580,11 +2599,11 @@ public class GLRenderer implements Renderer { } private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - + // Here while count is still passed in. Can be removed when/if // the method is collapsed again. -pspeed count = Math.max(mesh.getInstanceCount(), count); - + VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); @@ -2602,7 +2621,7 @@ public class GLRenderer implements Renderer { setVertexAttrib(vb, null); } } - + for (VertexBuffer vb : mesh.getBufferList().getArray()) { if (vb.getBufferType() == Type.InterleavedData || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers @@ -2637,7 +2656,7 @@ public class GLRenderer implements Renderer { gl.glLineWidth(mesh.getLineWidth()); context.lineWidth = mesh.getLineWidth(); } - + if (gl4 != null && mesh.getMode().equals(Mode.Patch)) { gl4.glPatchParameter(mesh.getPatchVertexCount()); } @@ -2653,12 +2672,12 @@ public class GLRenderer implements Renderer { // Gamma correction if (!caps.contains(Caps.Srgb) && enableSrgb) { // Not supported, sorry. - logger.warning("sRGB framebuffer is not supported " + - "by video hardware, but was requested."); - + logger.warning("sRGB framebuffer is not supported " + + "by video hardware, but was requested."); + return; } - + setFrameBuffer(null); if (enableSrgb) { From 1e0468bdbe4a1f48a24fc426531c87a3a36c4023 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 19 Jun 2015 23:07:28 +0200 Subject: [PATCH 23/29] Removed empty lines --- .../com/jme3/renderer/opengl/GLRenderer.java | 365 +++++++++--------- 1 file changed, 191 insertions(+), 174 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index caf472543..23d3eea17 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -73,7 +73,7 @@ public class GLRenderer implements Renderer { private static final Logger logger = Logger.getLogger(GLRenderer.class.getName()); private static final boolean VALIDATE_SHADER = false; private static final Pattern GLVERSION_PATTERN = Pattern.compile(".*?(\\d+)\\.(\\d+).*"); - + private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); private final StringBuilder stringBuf = new StringBuilder(250); private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); @@ -83,7 +83,7 @@ public class GLRenderer implements Renderer { private final NativeObjectManager objManager = new NativeObjectManager(); private final EnumSet caps = EnumSet.noneOf(Caps.class); private final EnumMap limits = new EnumMap(Limits.class); - + private FrameBuffer mainFbOverride = null; private final Statistics statistics = new Statistics(); private int vpX, vpY, vpW, vpH; @@ -98,12 +98,12 @@ public class GLRenderer implements Renderer { private final GLExt glext; private final GLFbo glfbo; private final TextureUtil texUtil; - + public GLRenderer(GL gl, GLExt glext, GLFbo glfbo) { this.gl = gl; - this.gl2 = gl instanceof GL2 ? (GL2)gl : null; - this.gl3 = gl instanceof GL3 ? (GL3)gl : null; - this.gl4 = gl instanceof GL4 ? (GL4)gl : null; + this.gl2 = gl instanceof GL2 ? (GL2) gl : null; + this.gl3 = gl instanceof GL3 ? (GL3) gl : null; + this.gl4 = gl instanceof GL4 ? (GL4) gl : null; this.glfbo = glfbo; this.glext = glext; this.texUtil = new TextureUtil(gl, gl2, glext, context); @@ -118,7 +118,7 @@ public class GLRenderer implements Renderer { public EnumSet getCaps() { return caps; } - + // Not making public yet ... public EnumMap getLimits() { return limits; @@ -140,7 +140,7 @@ public class GLRenderer implements Renderer { } return extensionSet; } - + public static int extractVersion(String version) { Matcher m = GLVERSION_PATTERN.matcher(version); if (m.matches()) { @@ -160,17 +160,17 @@ public class GLRenderer implements Renderer { private boolean hasExtension(String extensionName) { return extensions.contains(extensionName); } - + private void loadCapabilitiesES() { caps.add(Caps.GLSL100); caps.add(Caps.OpenGLES20); - + // Important: Do not add OpenGL20 - that's the desktop capability! } - + private void loadCapabilitiesGL2() { int oglVer = extractVersion(gl.glGetString(GL.GL_VERSION)); - + if (oglVer >= 200) { caps.add(Caps.OpenGL20); if (oglVer >= 210) { @@ -194,7 +194,7 @@ public class GLRenderer implements Renderer { } } } - + int glslVer = extractVersion(gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)); switch (glslVer) { @@ -222,27 +222,27 @@ public class GLRenderer implements Renderer { caps.add(Caps.GLSL100); break; } - + // Workaround, always assume we support GLSL100 & GLSL110 // Supporting OpenGL 2.0 means supporting GLSL 1.10. caps.add(Caps.GLSL110); caps.add(Caps.GLSL100); - + // Fix issue in TestRenderToMemory when GL.GL_FRONT is the main // buffer being used. context.initialDrawBuf = getInteger(GL2.GL_DRAW_BUFFER); context.initialReadBuf = getInteger(GL2.GL_READ_BUFFER); - + // XXX: This has to be GL.GL_BACK for canvas on Mac // Since initialDrawBuf is GL.GL_FRONT for pbuffer, gotta // change this value later on ... // initialDrawBuf = GL.GL_BACK; // initialReadBuf = GL.GL_BACK; } - + private void loadCapabilitiesCommon() { extensions = loadExtensions(); - + limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); if (limits.get(Limits.VertexTextureUnits) > 0) { caps.add(Caps.VertexTextureFetch); @@ -257,62 +257,66 @@ public class GLRenderer implements Renderer { // gl.glGetInteger(GL.GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, intBuf16); // fragUniforms = intBuf16.get(0); // logger.log(Level.FINER, "Fragment Uniforms: {0}", fragUniforms); - limits.put(Limits.VertexUniformComponents,getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS)); + if (caps.contains(Caps.OpenGLES20)) { + limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_VECTORS)); + } else { + limits.put(Limits.VertexUniformVectors, getInteger(GL.GL_MAX_VERTEX_UNIFORM_COMPONENTS) / 4); + } limits.put(Limits.VertexAttributes, getInteger(GL.GL_MAX_VERTEX_ATTRIBS)); limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE)); - if (hasExtension("GL_ARB_draw_instanced") && - hasExtension("GL_ARB_instanced_arrays")) { + if (hasExtension("GL_ARB_draw_instanced") && + hasExtension("GL_ARB_instanced_arrays")) { caps.add(Caps.MeshInstancing); } if (hasExtension("GL_OES_element_index_uint") || gl2 != null) { caps.add(Caps.IntegerIndexBuffer); } - + if (hasExtension("GL_ARB_texture_buffer_object")) { caps.add(Caps.TextureBuffer); } - + // == texture format extensions == - + boolean hasFloatTexture; hasFloatTexture = hasExtension("GL_OES_texture_half_float") && - hasExtension("GL_OES_texture_float"); - + hasExtension("GL_OES_texture_float"); + if (!hasFloatTexture) { hasFloatTexture = hasExtension("GL_ARB_texture_float") && - hasExtension("GL_ARB_half_float_pixel"); - + hasExtension("GL_ARB_half_float_pixel"); + if (!hasFloatTexture) { hasFloatTexture = caps.contains(Caps.OpenGL30); } } - + if (hasFloatTexture) { caps.add(Caps.FloatTexture); } - + if (hasExtension("GL_OES_depth_texture") || gl2 != null) { caps.add(Caps.DepthTexture); - + // TODO: GL_OES_depth24 } - - if (hasExtension("GL_OES_rgb8_rgba8") || - hasExtension("GL_ARM_rgba8") || - hasExtension("GL_EXT_texture_format_BGRA8888")) { + + if (hasExtension("GL_OES_rgb8_rgba8") || + hasExtension("GL_ARM_rgba8") || + hasExtension("GL_EXT_texture_format_BGRA8888")) { caps.add(Caps.Rgba8); } - + if (caps.contains(Caps.OpenGL30) || hasExtension("GL_OES_packed_depth_stencil")) { caps.add(Caps.PackedDepthStencilBuffer); } if (hasExtension("GL_ARB_color_buffer_float") && - hasExtension("GL_ARB_half_float_pixel")) { + hasExtension("GL_ARB_half_float_pixel")) { // XXX: Require both 16 and 32 bit float support for FloatColorBuffer. caps.add(Caps.FloatColorBuffer); } @@ -321,44 +325,44 @@ public class GLRenderer implements Renderer { caps.add(Caps.FloatDepthBuffer); } - if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || - caps.contains(Caps.OpenGL30)) { + if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || + caps.contains(Caps.OpenGL30)) { // Either OpenGL3 is available or both packed_float & half_float_pixel. caps.add(Caps.PackedFloatColorBuffer); caps.add(Caps.PackedFloatTexture); } - + if (hasExtension("GL_EXT_texture_shared_exponent") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.SharedExponentTexture); } - + if (hasExtension("GL_EXT_texture_compression_s3tc")) { caps.add(Caps.TextureCompressionS3TC); } - + if (hasExtension("GL_ARB_ES3_compatibility")) { caps.add(Caps.TextureCompressionETC2); caps.add(Caps.TextureCompressionETC1); } else if (hasExtension("GL_OES_compressed_ETC1_RGB8_texture")) { caps.add(Caps.TextureCompressionETC1); } - + // == end texture format extensions == - + if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.VertexBufferArray); } - if (hasExtension("GL_ARB_texture_non_power_of_two") || - hasExtension("GL_OES_texture_npot") || - caps.contains(Caps.OpenGL30)) { + if (hasExtension("GL_ARB_texture_non_power_of_two") || + hasExtension("GL_OES_texture_npot") || + caps.contains(Caps.OpenGL30)) { caps.add(Caps.NonPowerOfTwoTextures); } else { logger.log(Level.WARNING, "Your graphics card does not " - + "support non-power-of-2 textures. " - + "Some features might not work."); + + "support non-power-of-2 textures. " + + "Some features might not work."); } - + if (caps.contains(Caps.OpenGLES20)) { // OpenGL ES 2 has some limited support for NPOT textures caps.add(Caps.PartialNonPowerOfTwoTextures); @@ -374,14 +378,14 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_EXT_framebuffer_object") || gl3 != null) { caps.add(Caps.FrameBuffer); - + limits.put(Limits.RenderBufferSize, getInteger(GLFbo.GL_MAX_RENDERBUFFER_SIZE_EXT)); limits.put(Limits.FrameBufferAttachments, getInteger(GLFbo.GL_MAX_COLOR_ATTACHMENTS_EXT)); - + if (hasExtension("GL_EXT_framebuffer_blit")) { caps.add(Caps.FrameBufferBlit); } - + if (hasExtension("GL_EXT_framebuffer_multisample")) { caps.add(Caps.FrameBufferMultisample); limits.put(Limits.FrameBufferSamples, getInteger(GLExt.GL_MAX_SAMPLES_EXT)); @@ -419,10 +423,10 @@ public class GLRenderer implements Renderer { } caps.add(Caps.Multisample); } - + // Supports sRGB pipeline. - if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) - || caps.contains(Caps.OpenGL30) ) { + if ((hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) + || caps.contains(Caps.OpenGL30)) { caps.add(Caps.Srgb); } @@ -430,47 +434,46 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_ARB_seamless_cube_map") || caps.contains(Caps.OpenGL32)) { caps.add(Caps.SeamlessCubemap); } - + if (caps.contains(Caps.OpenGL32) && !hasExtension("GL_ARB_compatibility")) { caps.add(Caps.CoreProfile); } - + if (hasExtension("GL_ARB_get_program_binary")) { int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); if (binaryFormats > 0) { caps.add(Caps.BinaryShader); } } - + // Print context information logger.log(Level.INFO, "OpenGL Renderer Information\n" + - " * Vendor: {0}\n" + - " * Renderer: {1}\n" + - " * OpenGL Version: {2}\n" + - " * GLSL Version: {3}\n" + - " * Profile: {4}", - new Object[]{ - gl.glGetString(GL.GL_VENDOR), - gl.glGetString(GL.GL_RENDERER), - gl.glGetString(GL.GL_VERSION), - gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION), - caps.contains(Caps.CoreProfile) ? "Core" : "Compatibility" - }); - + " * Vendor: {0}\n" + + " * Renderer: {1}\n" + + " * OpenGL Version: {2}\n" + + " * GLSL Version: {3}\n" + + " * Profile: {4}", + new Object[]{ + gl.glGetString(GL.GL_VENDOR), + gl.glGetString(GL.GL_RENDERER), + gl.glGetString(GL.GL_VERSION), + gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION), + caps.contains(Caps.CoreProfile) ? "Core" : "Compatibility" + }); + // Print capabilities (if fine logging is enabled) if (logger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(); sb.append("Supported capabilities: \n"); - for (Caps cap : caps) - { + for (Caps cap : caps) { sb.append("\t").append(cap.toString()).append("\n"); } logger.log(Level.FINE, sb.toString()); } - + texUtil.initialize(caps); } - + private void loadCapabilities() { if (gl2 != null) { loadCapabilitiesGL2(); @@ -479,31 +482,31 @@ public class GLRenderer implements Renderer { } loadCapabilitiesCommon(); } - + private int getInteger(int en) { intBuf16.clear(); gl.glGetInteger(en, intBuf16); return intBuf16.get(0); } - + private boolean getBoolean(int en) { gl.glGetBoolean(en, nameBuf); - return nameBuf.get(0) != (byte)0; + return nameBuf.get(0) != (byte) 0; } - + @SuppressWarnings("fallthrough") public void initialize() { loadCapabilities(); - + // Initialize default state.. gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); - + if (caps.contains(Caps.CoreProfile)) { // Core Profile requires VAO to be bound. gl3.glGenVertexArrays(intBuf16); int vaoId = intBuf16.get(0); gl3.glBindVertexArray(vaoId); - } + } if (gl2 != null) { gl2.glEnable(GL2.GL_VERTEX_PROGRAM_POINT_SIZE); if (!caps.contains(Caps.CoreProfile)) { @@ -535,9 +538,11 @@ public class GLRenderer implements Renderer { invalidateState(); } - /*********************************************************************\ - |* Render State *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Render State *| + * \******************************************************************** + */ public void setDepthRange(float start, float end) { gl.glDepthRange(start, end); } @@ -602,7 +607,7 @@ public class GLRenderer implements Renderer { } if (state.isDepthTest() && !context.depthTestEnabled) { - gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(convertTestFunction(context.depthFunc)); context.depthTestEnabled = true; } else if (!state.isDepthTest() && context.depthTestEnabled) { @@ -714,7 +719,7 @@ public class GLRenderer implements Renderer { case Color: case Screen: gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; + break; case Exclusion: gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR); break; @@ -814,9 +819,11 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Camera and World transforms *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Camera and World transforms *| + * \******************************************************************** + */ public void setViewPort(int x, int y, int w, int h) { if (x != vpX || vpY != y || vpW != w || vpH != h) { gl.glViewport(x, y, w, h); @@ -858,9 +865,11 @@ public class GLRenderer implements Renderer { gl.resetStats(); } - /*********************************************************************\ - |* Shaders *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Shaders *| + * \******************************************************************** + */ protected void updateUniformLocation(Shader shader, Uniform uniform) { int loc = gl.glGetUniformLocation(shader.getId(), uniform.getName()); if (loc < 0) { @@ -1040,12 +1049,12 @@ public class GLRenderer implements Renderer { boolean gles2 = caps.contains(Caps.OpenGLES20); String language = source.getLanguage(); - + if (gles2 && !language.equals("GLSL100")) { throw new RendererException("This shader cannot run in OpenGL ES 2. " - + "Only GLSL 1.00 shaders are supported."); + + "Only GLSL 1.00 shaders are supported."); } - + // Upload shader source. // Merge the defines and source code. stringBuf.setLength(0); @@ -1072,17 +1081,17 @@ public class GLRenderer implements Renderer { } } } - + if (linearizeSrgbImages) { stringBuf.append("#define SRGB 1\n"); } - + stringBuf.append(source.getDefines()); stringBuf.append(source.getSource()); - + intBuf1.clear(); intBuf1.put(0, stringBuf.length()); - gl.glShaderSource(id, new String[]{ stringBuf.toString() }, intBuf1); + gl.glShaderSource(id, new String[]{stringBuf.toString()}, intBuf1); gl.glCompileShader(id); gl.glGetShader(id, GL.GL_COMPILE_STATUS, intBuf1); @@ -1137,7 +1146,7 @@ public class GLRenderer implements Renderer { // If using GLSL 1.5, we bind the outputs for the user // For versions 3.3 and up, user should use layout qualifiers instead. boolean bindFragDataRequired = false; - + for (ShaderSource source : shader.getSources()) { if (source.isUpdateNeeded()) { updateShaderSourceData(source); @@ -1245,9 +1254,11 @@ public class GLRenderer implements Renderer { shader.resetObject(); } - /*********************************************************************\ - |* Framebuffers *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Framebuffers *| + * \******************************************************************** + */ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { copyFrameBuffer(src, dst, true); } @@ -1402,7 +1413,7 @@ public class GLRenderer implements Renderer { } else if (attachmentSlot < 0 || attachmentSlot >= 16) { throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); } - + return GLFbo.GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; } @@ -1412,7 +1423,7 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded()) { // Check NPOT requirements checkNonPowerOfTwo(tex); - + updateTexImageData(image, tex.getType(), 0, false); // NOTE: For depth textures, sets nearest/no-mips mode @@ -1476,7 +1487,7 @@ public class GLRenderer implements Renderer { } checkFrameBufferError(); - + fb.clearUpdateNeeded(); } @@ -1569,7 +1580,7 @@ public class GLRenderer implements Renderer { // update viewport to reflect framebuffer's resolution setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - + if (context.boundFBO != fb.getId()) { glfbo.glBindFramebufferEXT(GLFbo.GL_FRAMEBUFFER_EXT, fb.getId()); statistics.onFrameBufferUse(fb, true); @@ -1640,7 +1651,7 @@ public class GLRenderer implements Renderer { public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { readFrameBufferWithGLFormat(fb, byteBuf, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); } - + private void readFrameBufferWithGLFormat(FrameBuffer fb, ByteBuffer byteBuf, int glFormat, int dataType) { if (fb != null) { RenderBuffer rb = fb.getColorBuffer(); @@ -1662,8 +1673,8 @@ public class GLRenderer implements Renderer { gl.glReadPixels(vpX, vpY, vpW, vpH, glFormat, dataType, byteBuf); } - - public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { + + public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { GLImageFormat glFormat = texUtil.getImageFormatWithError(format, false); readFrameBufferWithGLFormat(fb, byteBuf, glFormat.format, glFormat.dataType); } @@ -1695,15 +1706,17 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Textures *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Textures *| + * \******************************************************************** + */ private int convertTextureType(Texture.Type type, int samples, int face) { if (samples > 1 && !caps.contains(Caps.TextureMultisample)) { - throw new RendererException("Multisample textures are not supported" + - " by the video hardware."); + throw new RendererException("Multisample textures are not supported" + + " by the video hardware."); } - + switch (type) { case TwoDimensional: if (samples > 1) { @@ -1723,8 +1736,8 @@ public class GLRenderer implements Renderer { } case ThreeDimensional: if (!caps.contains(Caps.OpenGL20)) { - throw new RendererException("3D textures are not supported" + - " by the video hardware."); + throw new RendererException("3D textures are not supported" + + " by the video hardware."); } return GL2.GL_TEXTURE_3D; case CubeMap: @@ -1752,7 +1765,7 @@ public class GLRenderer implements Renderer { } private int convertMinFilter(Texture.MinFilter filter, boolean haveMips) { - if (haveMips){ + if (haveMips) { switch (filter) { case Trilinear: return GL.GL_LINEAR_MIPMAP_LINEAR; @@ -1807,11 +1820,11 @@ public class GLRenderer implements Renderer { int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); boolean haveMips = true; - + if (image != null) { haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps(); } - + // filter things if (image.getLastTextureState().magFilter != tex.getMagFilter()) { int magFilter = convertMagFilter(tex.getMagFilter()); @@ -1834,7 +1847,7 @@ public class GLRenderer implements Renderer { context.seamlessCubemap = false; } } - + if (tex.getAnisotropicFilter() > 1) { if (caps.contains(Caps.TextureFilterAnisotropic)) { gl.glTexParameterf(target, @@ -1867,19 +1880,19 @@ public class GLRenderer implements Renderer { throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); } - if(tex.isNeedCompareModeUpdate() && gl2 != null){ + if (tex.isNeedCompareModeUpdate() && gl2 != null) { // R to Texture compare mode if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); - gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); + gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL); } else { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL); } - }else{ - //restoring default value - gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); + } else { + //restoring default value + gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); } tex.compareModeUpdated(); } @@ -1888,10 +1901,10 @@ public class GLRenderer implements Renderer { /** * Validates if a potentially NPOT texture is supported by the hardware. *

- * Textures with power-of-2 dimensions are supported on all hardware, however + * Textures with power-of-2 dimensions are supported on all hardware, however * non-power-of-2 textures may or may not be supported depending on which * texturing features are used. - * + * * @param tex The texture to validate. * @throws RendererException If the texture is not supported by the hardware */ @@ -1900,23 +1913,23 @@ public class GLRenderer implements Renderer { // Texture is power-of-2, safe to use. return; } - + if (caps.contains(Caps.NonPowerOfTwoTextures)) { // Texture is NPOT but it is supported by video hardware. return; } - + // Maybe we have some / partial support for NPOT? if (!caps.contains(Caps.PartialNonPowerOfTwoTextures)) { // Cannot use any type of NPOT texture (uncommon) throw new RendererException("non-power-of-2 textures are not " - + "supported by the video hardware"); + + "supported by the video hardware"); } - + // Partial NPOT supported.. if (tex.getMinFilter().usesMipMapLevels()) { throw new RendererException("non-power-of-2 textures with mip-maps " - + "are not supported by the video hardware"); + + "are not supported by the video hardware"); } switch (tex.getType()) { @@ -1924,7 +1937,7 @@ public class GLRenderer implements Renderer { case ThreeDimensional: if (tex.getWrap(WrapAxis.R) != Texture.WrapMode.EdgeClamp) { throw new RendererException("repeating non-power-of-2 textures " - + "are not supported by the video hardware"); + + "are not supported by the video hardware"); } // fallthrough intentional!!! case TwoDimensionalArray: @@ -1932,22 +1945,22 @@ public class GLRenderer implements Renderer { if (tex.getWrap(WrapAxis.S) != Texture.WrapMode.EdgeClamp || tex.getWrap(WrapAxis.T) != Texture.WrapMode.EdgeClamp) { throw new RendererException("repeating non-power-of-2 textures " - + "are not supported by the video hardware"); + + "are not supported by the video hardware"); } break; default: throw new UnsupportedOperationException("unrecongized texture type"); } } - + /** * Uploads the given image to the GL driver. - * - * @param img The image to upload - * @param type How the data in the image argument should be interpreted. - * @param unit The texture slot to be used to upload the image, not important + * + * @param img The image to upload + * @param type How the data in the image argument should be interpreted. + * @param unit The texture slot to be used to upload the image, not important * @param scaleToPot If true, the image will be scaled to power-of-2 dimensions - * before being uploaded. + * before being uploaded. */ public void updateTexImageData(Image img, Texture.Type type, int unit, boolean scaleToPot) { int texId = img.getId(); @@ -1968,7 +1981,7 @@ public class GLRenderer implements Renderer { gl.glActiveTexture(GL.GL_TEXTURE0 + unit); context.boundTextureUnit = unit; } - + gl.glBindTexture(target, texId); context.boundTextures[unit] = img; @@ -2011,12 +2024,12 @@ public class GLRenderer implements Renderer { throw new RendererException("Multisample textures are not supported by the video hardware"); } } - + // Check if graphics card doesn't support depth textures if (img.getFormat().isDepthFormat() && !caps.contains(Caps.DepthTexture)) { throw new RendererException("Depth textures are not supported by the video hardware"); } - + if (target == GL.GL_TEXTURE_CUBE_MAP) { // Check max texture size before upload int cubeSize = limits.get(Limits.CubemapSize); @@ -2053,12 +2066,12 @@ public class GLRenderer implements Renderer { if (!caps.contains(Caps.TextureArray)) { throw new RendererException("Texture arrays not supported by graphics hardware"); } - + List data = imageForUpload.getData(); - + // -1 index specifies prepare data for 2D Array texUtil.uploadTexture(imageForUpload, target, -1, linearizeSrgbImages); - + for (int i = 0; i < data.size(); i++) { // upload each slice of 2D array in turn // this time with the appropriate index @@ -2087,21 +2100,21 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) { // Check NPOT requirements boolean scaleToPot = false; - + try { checkNonPowerOfTwo(tex); } catch (RendererException ex) { if (logger.isLoggable(Level.WARNING)) { int nextWidth = FastMath.nearestPowerOfTwo(tex.getImage().getWidth()); int nextHeight = FastMath.nearestPowerOfTwo(tex.getImage().getHeight()); - logger.log(Level.WARNING, - "Non-power-of-2 textures are not supported! Scaling texture '" + tex.getName() + - "' of size " + tex.getImage().getWidth() + "x" + tex.getImage().getHeight() + - " to " + nextWidth + "x" + nextHeight); + logger.log(Level.WARNING, + "Non-power-of-2 textures are not supported! Scaling texture '" + tex.getName() + + "' of size " + tex.getImage().getWidth() + "x" + tex.getImage().getHeight() + + " to " + nextWidth + "x" + nextHeight); } scaleToPot = true; } - + updateTexImageData(image, tex.getType(), unit, scaleToPot); } @@ -2146,9 +2159,11 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Vertex Buffers and Attributes *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Vertex Buffers and Attributes *| + * \******************************************************************** + */ private int convertUsage(Usage usage) { switch (usage) { case Static: @@ -2222,7 +2237,7 @@ public class GLRenderer implements Renderer { //statistics.onVertexBufferUse(vb, false); } } - + int usage = convertUsage(vb.getUsage()); vb.getData().rewind(); @@ -2283,7 +2298,7 @@ public class GLRenderer implements Renderer { if (context.boundShaderProgram <= 0) { throw new IllegalStateException("Cannot render mesh without shader bound"); } - + Attribute attrib = context.boundShader.getAttribute(vb.getBufferType()); int loc = attrib.getLocation(); if (loc == -1) { @@ -2413,7 +2428,7 @@ public class GLRenderer implements Renderer { // What is this? throw new RendererException("Unexpected format for index buffer: " + indexBuf.getFormat()); } - + if (indexBuf.isUpdateNeeded()) { updateBufferData(indexBuf); } @@ -2486,9 +2501,11 @@ public class GLRenderer implements Renderer { } } - /*********************************************************************\ - |* Render Calls *| - \*********************************************************************/ + /** + * ******************************************************************\ + * |* Render Calls *| + * \******************************************************************** + */ public int convertElementMode(Mesh.Mode mode) { switch (mode) { case Points: @@ -2530,7 +2547,7 @@ public class GLRenderer implements Renderer { if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); } - + if (instanceData != null) { setVertexAttrib(instanceData, null); } @@ -2580,11 +2597,11 @@ public class GLRenderer implements Renderer { } private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - + // Here while count is still passed in. Can be removed when/if // the method is collapsed again. -pspeed count = Math.max(mesh.getInstanceCount(), count); - + VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); @@ -2602,7 +2619,7 @@ public class GLRenderer implements Renderer { setVertexAttrib(vb, null); } } - + for (VertexBuffer vb : mesh.getBufferList().getArray()) { if (vb.getBufferType() == Type.InterleavedData || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers @@ -2637,7 +2654,7 @@ public class GLRenderer implements Renderer { gl.glLineWidth(mesh.getLineWidth()); context.lineWidth = mesh.getLineWidth(); } - + if (gl4 != null && mesh.getMode().equals(Mode.Patch)) { gl4.glPatchParameter(mesh.getPatchVertexCount()); } @@ -2653,12 +2670,12 @@ public class GLRenderer implements Renderer { // Gamma correction if (!caps.contains(Caps.Srgb) && enableSrgb) { // Not supported, sorry. - logger.warning("sRGB framebuffer is not supported " + - "by video hardware, but was requested."); - + logger.warning("sRGB framebuffer is not supported " + + "by video hardware, but was requested."); + return; } - + setFrameBuffer(null); if (enableSrgb) { From a8b3407b469dcfff6ddd873768f7370f6e17ca49 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 19 Jun 2015 23:08:00 +0200 Subject: [PATCH 24/29] Removed empty lines --- .../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 2da5e28f9..23d3eea17 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -56,7 +56,6 @@ import com.jme3.util.BufferUtils; import com.jme3.util.ListMap; import com.jme3.util.MipMapGenerator; import com.jme3.util.NativeObjectManager; - import java.nio.*; import java.util.Arrays; import java.util.EnumMap; @@ -67,7 +66,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; - import jme3tools.shader.ShaderDebug; public class GLRenderer implements Renderer { From 8d0c371796851e7535d154a4a0a4ec6bdc669ad3 Mon Sep 17 00:00:00 2001 From: zzuegg Date: Fri, 19 Jun 2015 23:16:24 +0200 Subject: [PATCH 25/29] Hopefully fixed --- .../com/jme3/renderer/opengl/GLRenderer.java | 89 ++++++++----------- 1 file changed, 38 insertions(+), 51 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 23d3eea17..bb145edbe 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -101,9 +101,9 @@ public class GLRenderer implements Renderer { public GLRenderer(GL gl, GLExt glext, GLFbo glfbo) { this.gl = gl; - this.gl2 = gl instanceof GL2 ? (GL2) gl : null; - this.gl3 = gl instanceof GL3 ? (GL3) gl : null; - this.gl4 = gl instanceof GL4 ? (GL4) gl : null; + this.gl2 = gl instanceof GL2 ? (GL2)gl : null; + this.gl3 = gl instanceof GL3 ? (GL3)gl : null; + this.gl4 = gl instanceof GL4 ? (GL4)gl : null; this.glfbo = glfbo; this.glext = glext; this.texUtil = new TextureUtil(gl, gl2, glext, context); @@ -425,8 +425,8 @@ public class GLRenderer implements Renderer { } // Supports sRGB pipeline. - if ((hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) - || caps.contains(Caps.OpenGL30)) { + if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) + || caps.contains(Caps.OpenGL30) ) { caps.add(Caps.Srgb); } @@ -465,7 +465,8 @@ public class GLRenderer implements Renderer { if (logger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(); sb.append("Supported capabilities: \n"); - for (Caps cap : caps) { + for (Caps cap : caps) + { sb.append("\t").append(cap.toString()).append("\n"); } logger.log(Level.FINE, sb.toString()); @@ -491,7 +492,7 @@ public class GLRenderer implements Renderer { private boolean getBoolean(int en) { gl.glGetBoolean(en, nameBuf); - return nameBuf.get(0) != (byte) 0; + return nameBuf.get(0) != (byte)0; } @SuppressWarnings("fallthrough") @@ -538,11 +539,9 @@ public class GLRenderer implements Renderer { invalidateState(); } - /** - * ******************************************************************\ - * |* Render State *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Render State *| + \*********************************************************************/ public void setDepthRange(float start, float end) { gl.glDepthRange(start, end); } @@ -819,11 +818,9 @@ public class GLRenderer implements Renderer { } } - /** - * ******************************************************************\ - * |* Camera and World transforms *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Camera and World transforms *| + \*********************************************************************/ public void setViewPort(int x, int y, int w, int h) { if (x != vpX || vpY != y || vpW != w || vpH != h) { gl.glViewport(x, y, w, h); @@ -865,11 +862,9 @@ public class GLRenderer implements Renderer { gl.resetStats(); } - /** - * ******************************************************************\ - * |* Shaders *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Shaders *| + \*********************************************************************/ protected void updateUniformLocation(Shader shader, Uniform uniform) { int loc = gl.glGetUniformLocation(shader.getId(), uniform.getName()); if (loc < 0) { @@ -1091,7 +1086,7 @@ public class GLRenderer implements Renderer { intBuf1.clear(); intBuf1.put(0, stringBuf.length()); - gl.glShaderSource(id, new String[]{stringBuf.toString()}, intBuf1); + gl.glShaderSource(id, new String[]{ stringBuf.toString() }, intBuf1); gl.glCompileShader(id); gl.glGetShader(id, GL.GL_COMPILE_STATUS, intBuf1); @@ -1254,11 +1249,9 @@ public class GLRenderer implements Renderer { shader.resetObject(); } - /** - * ******************************************************************\ - * |* Framebuffers *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Framebuffers *| + \*********************************************************************/ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { copyFrameBuffer(src, dst, true); } @@ -1706,11 +1699,9 @@ public class GLRenderer implements Renderer { } } - /** - * ******************************************************************\ - * |* Textures *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Textures *| + \*********************************************************************/ private int convertTextureType(Texture.Type type, int samples, int face) { if (samples > 1 && !caps.contains(Caps.TextureMultisample)) { throw new RendererException("Multisample textures are not supported" + @@ -1765,7 +1756,7 @@ public class GLRenderer implements Renderer { } private int convertMinFilter(Texture.MinFilter filter, boolean haveMips) { - if (haveMips) { + if (haveMips){ switch (filter) { case Trilinear: return GL.GL_LINEAR_MIPMAP_LINEAR; @@ -1880,7 +1871,7 @@ public class GLRenderer implements Renderer { throw new UnsupportedOperationException("Unknown texture type: " + tex.getType()); } - if (tex.isNeedCompareModeUpdate() && gl2 != null) { + if(tex.isNeedCompareModeUpdate() && gl2 != null){ // R to Texture compare mode if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); @@ -1890,7 +1881,7 @@ public class GLRenderer implements Renderer { } else { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_LEQUAL); } - } else { + }else{ //restoring default value gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); } @@ -1901,7 +1892,7 @@ public class GLRenderer implements Renderer { /** * Validates if a potentially NPOT texture is supported by the hardware. *

- * Textures with power-of-2 dimensions are supported on all hardware, however + * Textures with power-of-2 dimensions are supported on all hardware, however * non-power-of-2 textures may or may not be supported depending on which * texturing features are used. * @@ -1956,11 +1947,11 @@ public class GLRenderer implements Renderer { /** * Uploads the given image to the GL driver. * - * @param img The image to upload - * @param type How the data in the image argument should be interpreted. - * @param unit The texture slot to be used to upload the image, not important + * @param img The image to upload + * @param type How the data in the image argument should be interpreted. + * @param unit The texture slot to be used to upload the image, not important * @param scaleToPot If true, the image will be scaled to power-of-2 dimensions - * before being uploaded. + * before being uploaded. */ public void updateTexImageData(Image img, Texture.Type type, int unit, boolean scaleToPot) { int texId = img.getId(); @@ -2159,11 +2150,9 @@ public class GLRenderer implements Renderer { } } - /** - * ******************************************************************\ - * |* Vertex Buffers and Attributes *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Vertex Buffers and Attributes *| + \*********************************************************************/ private int convertUsage(Usage usage) { switch (usage) { case Static: @@ -2501,11 +2490,9 @@ public class GLRenderer implements Renderer { } } - /** - * ******************************************************************\ - * |* Render Calls *| - * \******************************************************************** - */ + /*********************************************************************\ + |* Render Calls *| + \*********************************************************************/ public int convertElementMode(Mesh.Mode mode) { switch (mode) { case Points: From 86900c9d0965f749266efff20e103245ab89c0a3 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sat, 20 Jun 2015 14:28:41 -0400 Subject: [PATCH 26/29] Travis-CI: Try to fix notifications --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8a29bd1f8..f7b3add47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,10 @@ branches: notifications: slack: - secure: "PWEk4+VL986c3gAjWp12nqyifvxCjBqKoESG9d7zWh1uiTLadTHhZJRMdsye36FCpz/c/Jt7zCRO/5y7FaubQptnRrkrRfjp5f99MJRzQVXnUAM+y385qVkXKRKd/PLpM7XPm4AvjvxHCyvzX2wamRvul/TekaXKB9Ti5FCN87s=" on_success: change on_failure: always + rooms: + secure: "PWEk4+VL986c3gAjWp12nqyifvxCjBqKoESG9d7zWh1uiTLadTHhZJRMdsye36FCpz/c/Jt7zCRO/5y7FaubQptnRrkrRfjp5f99MJRzQVXnUAM+y385qVkXKRKd/PLpM7XPm4AvjvxHCyvzX2wamRvul/TekaXKB9Ti5FCN87s=" before_install: # required libs for android build tools From 5a1faac6294e076157bcd210dca17c5a122219ab Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sat, 20 Jun 2015 14:37:01 -0400 Subject: [PATCH 27/29] Travis-CI: create zip dist as part of build --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f7b3add47..2b324fdbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,12 @@ notifications: rooms: secure: "PWEk4+VL986c3gAjWp12nqyifvxCjBqKoESG9d7zWh1uiTLadTHhZJRMdsye36FCpz/c/Jt7zCRO/5y7FaubQptnRrkrRfjp5f99MJRzQVXnUAM+y385qVkXKRKd/PLpM7XPm4AvjvxHCyvzX2wamRvul/TekaXKB9Ti5FCN87s=" -before_install: +install: + - ./gradlew assemble +script: + - ./gradlew check + - ./gradlew createZipDistribution +# before_install: # required libs for android build tools # sudo apt-get update # sudo apt-get install -qq p7zip-full From c39abf48de49bd661b1f5b5fc2d7c1e3dc069373 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Sat, 20 Jun 2015 15:59:45 -0400 Subject: [PATCH 28/29] Travis-CI: enable releases --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2b324fdbb..71c3b576f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,9 +21,20 @@ notifications: install: - ./gradlew assemble + script: - ./gradlew check - ./gradlew createZipDistribution + +deploy: + provider: releases + api_key: + secure: "KbFiMt0a8FxUKvCJUYwikLYaqqGMn1p6k4OsXnGqwptQZEUIayabNLHeaD2kTNT3e6AY1ETwQLff/lB2LttmIo4g5NWW63g1K3A/HwgnhJwETengiProZ/Udl+ugPeDL/+ar43HUhFq4knBnzFKnEcHAThTPVqH/RMDvZf1UUYI=" + file: build/distributions/jME3.1.0_snapshot-github_2015-06-20.zip + skip_cleanup: true + on: + tags: true + # before_install: # required libs for android build tools # sudo apt-get update From 97a2f58be7b0d8e411bdc02c4c97e83ea004bfae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=A4rtner?= Date: Mon, 22 Jun 2015 13:59:11 +0200 Subject: [PATCH 29/29] [Nifty-GUI] Using java logger, instead of stdout Replaced call to System.out.println() with proper logging call. --- .../src/main/java/com/jme3/cinematic/events/GuiEvent.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java b/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java index 2f5d788b4..f832b4266 100644 --- a/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java +++ b/jme3-niftygui/src/main/java/com/jme3/cinematic/events/GuiEvent.java @@ -38,6 +38,8 @@ import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import de.lessvoid.nifty.Nifty; import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -45,6 +47,8 @@ import java.io.IOException; */ public class GuiEvent extends AbstractCinematicEvent { + static final Logger log = Logger.getLogger(GuiEvent.class.getName()); + protected String screen; protected Nifty nifty; @@ -76,7 +80,7 @@ public class GuiEvent extends AbstractCinematicEvent { @Override public void onPlay() { - System.out.println("screen should be " + screen); + log.log(Level.FINEST, "screen should be {0}", screen); nifty.gotoScreen(screen); }