diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties index 86f1414f9..43469051d 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/Bundle.properties @@ -44,8 +44,8 @@ SceneComposerTopComponent.scaleButton.text= SceneComposerTopComponent.selectButton.text= SceneComposerTopComponent.selectButton.toolTipText=Select SceneComposerTopComponent.moveButton.toolTipText=Move -SceneComposerTopComponent.rotateButton.toolTipText=Rotate (in-development) -SceneComposerTopComponent.scaleButton.toolTipText=Scale (in-development) +SceneComposerTopComponent.rotateButton.toolTipText=Rotate +SceneComposerTopComponent.scaleButton.toolTipText=Scale SceneComposerTopComponent.sceneInfoPanel.border.title=no scene loaded SceneComposerTopComponent.jLabel5.text=Effects : SceneComposerTopComponent.emitButton.toolTipText=Emit all particles of all particle emitters from the selected Node @@ -63,3 +63,5 @@ SceneComposerTopComponent.jToggleScene.toolTipText=Snap to Scene SceneComposerTopComponent.jToggleGrid.toolTipText=Snap to Grid SceneComposerTopComponent.jToggleSelectGeom.toolTipText=Select Geometries SceneComposerTopComponent.jToggleSelectTerrain.toolTipText=Select Terrain +SceneComposerTopComponent.scaleButton.AccessibleContext.accessibleDescription=Scale +SceneComposerTopComponent.transformationTypeComboBox.toolTipText=Choose the transformation type used by tools. 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 dff940e50..2ad04aa8d 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerToolController.java @@ -10,6 +10,7 @@ import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.scene.controller.SceneToolController; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; +import com.jme3.gde.scenecomposer.tools.PickManager; import com.jme3.input.event.KeyInputEvent; import com.jme3.light.Light; import com.jme3.light.PointLight; @@ -50,7 +51,12 @@ public class SceneComposerToolController extends SceneToolController { private boolean snapToScene = false; private boolean selectTerrain = false; private boolean selectGeometries = false; - + private TransformationType transformationType = TransformationType.local; + + public enum TransformationType { + local, global, camera + } + public SceneComposerToolController(final Node toolsNode, AssetManager manager, JmeNode rootNode) { super(toolsNode, manager); this.rootNode = rootNode; @@ -347,8 +353,37 @@ public class SceneComposerToolController extends SceneToolController { public void setSelectGeometries(boolean selectGeometries) { this.selectGeometries = selectGeometries; } - - + + public void setTransformationType(String type) { + if(type != null){ + if(type.equals("Local")){ + setTransformationType(transformationType.local); + } else if(type.equals("Global")){ + setTransformationType(TransformationType.global); + } else if(type.equals("Camera")){ + setTransformationType(TransformationType.camera); + } + } + } + /** + * @return the transformationType + */ + public TransformationType getTransformationType() { + return transformationType; + } + + /** + * @param transformationType the transformationType to set + */ + public void setTransformationType(TransformationType type) { + if(type != this.transformationType){ + this.transformationType = type; + if(editTool != null){ + //update the transform type of the tool + editTool.setTransformType(transformationType); + } + } + } /** * A marker on the screen that shows where a point light or diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form index 8b21fb202..fd4686f24 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.form @@ -99,6 +99,25 @@ <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/> <SubComponents> + <Component class="javax.swing.JComboBox" name="transformationTypeComboBox"> + <Properties> + <Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor"> + <StringArray count="3"> + <StringItem index="0" value="Local"/> + <StringItem index="1" value="Global"/> + <StringItem index="2" value="Camera"/> + </StringArray> + </Property> + <Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.transformationTypeComboBox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="transformationTypeComboBoxActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JToolBar$Separator" name="jSeparator9"> + </Component> <Component class="javax.swing.JToggleButton" name="selectButton"> <Properties> <Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor"> @@ -184,6 +203,11 @@ <Property name="horizontalTextPosition" type="int" value="0"/> <Property name="verticalTextPosition" type="int" value="3"/> </Properties> + <AccessibilityProperties> + <Property name="AccessibleContext.accessibleDescription" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.scaleButton.AccessibleContext.accessibleDescription" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/> + </Property> + </AccessibilityProperties> <Events> <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="scaleButtonActionPerformed"/> </Events> diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java index 1259d74a9..b06e126dc 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneComposerTopComponent.java @@ -97,6 +97,8 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce sceneInfoLabel1 = new javax.swing.JLabel(); sceneInfoLabel2 = new javax.swing.JLabel(); jToolBar1 = new javax.swing.JToolBar(); + transformationTypeComboBox = new javax.swing.JComboBox(); + jSeparator9 = new javax.swing.JToolBar.Separator(); selectButton = new javax.swing.JToggleButton(); moveButton = new javax.swing.JToggleButton(); rotateButton = new javax.swing.JToggleButton(); @@ -165,6 +167,16 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce jToolBar1.setFloatable(false); jToolBar1.setRollover(true); + transformationTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Local", "Global", "Camera" })); + transformationTypeComboBox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.transformationTypeComboBox.toolTipText")); // NOI18N + transformationTypeComboBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + transformationTypeComboBoxActionPerformed(evt); + } + }); + jToolBar1.add(transformationTypeComboBox); + jToolBar1.add(jSeparator9); + spatialModButtonGroup.add(selectButton); selectButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/icon_select.png"))); // NOI18N selectButton.setSelected(true); @@ -221,6 +233,8 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce } }); jToolBar1.add(scaleButton); + scaleButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.scaleButton.AccessibleContext.accessibleDescription")); // NOI18N + jToolBar1.add(jSeparator5); jToggleScene.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/scenecomposer/snapScene.png"))); // NOI18N @@ -644,6 +658,11 @@ private void jToggleSelectTerrainActionPerformed(java.awt.event.ActionEvent evt) private void jToggleSelectGeomActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jToggleSelectGeomActionPerformed toolController.setSelectGeometries(jToggleSelectGeom.isSelected()); }//GEN-LAST:event_jToggleSelectGeomActionPerformed + + private void transformationTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_transformationTypeComboBoxActionPerformed + toolController.setTransformationType((String)transformationTypeComboBox.getSelectedItem()); + }//GEN-LAST:event_transformationTypeComboBoxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton camToCursorSelectionButton; private javax.swing.JButton createPhysicsMeshButton; @@ -671,6 +690,7 @@ private void jToggleSelectGeomActionPerformed(java.awt.event.ActionEvent evt) {/ private javax.swing.JSeparator jSeparator6; private javax.swing.JToolBar.Separator jSeparator7; private javax.swing.JToolBar.Separator jSeparator8; + private javax.swing.JToolBar.Separator jSeparator9; private javax.swing.JTextField jTextField1; private javax.swing.JToggleButton jToggleGrid; private javax.swing.JToggleButton jToggleScene; @@ -692,6 +712,7 @@ private void jToggleSelectGeomActionPerformed(java.awt.event.ActionEvent evt) {/ private javax.swing.JToggleButton showGridToggleButton; private javax.swing.JToggleButton showSelectionToggleButton; private javax.swing.ButtonGroup spatialModButtonGroup; + private javax.swing.JComboBox transformationTypeComboBox; // End of variables declaration//GEN-END:variables private void emit(Spatial root) { diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java index 5409a3603..372984f8e 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditTool.java @@ -57,7 +57,8 @@ public abstract class SceneEditTool { protected Node axisMarker; protected Material redMat, blueMat, greenMat, yellowMat, cyanMat, magentaMat, orangeMat; protected Geometry quadXY, quadXZ, quadYZ; - + protected SceneComposerToolController.TransformationType transformType; + protected enum AxisMarkerPickType { axisOnly, planeOnly, axisAndPlane @@ -72,6 +73,7 @@ public abstract class SceneEditTool { public void activate(AssetManager manager, Node toolNode, Node onTopToolNode, Spatial selectedSpatial, SceneComposerToolController toolController) { this.manager = manager; this.toolController = toolController; + this.setTransformType(toolController.getTransformationType()); //this.selectedSpatial = selectedSpatial; addMarker(toolNode, onTopToolNode); } @@ -130,7 +132,19 @@ public abstract class SceneEditTool { public void doUpdateToolsTransformation() { if (toolController.getSelectedSpatial() != null) { axisMarker.setLocalTranslation(toolController.getSelectedSpatial().getWorldTranslation()); - axisMarker.setLocalRotation(toolController.getSelectedSpatial().getLocalRotation()); + switch (transformType) { + case local: + axisMarker.setLocalRotation(toolController.getSelectedSpatial().getLocalRotation()); + break; + case global: + axisMarker.setLocalRotation(Quaternion.IDENTITY); + break; + case camera: + if(camera != null){ + axisMarker.setLocalRotation(camera.getRotation()); + } + break; + } setAxisMarkerScale(toolController.getSelectedSpatial()); } else { axisMarker.setLocalTranslation(Vector3f.ZERO); @@ -487,4 +501,12 @@ public abstract class SceneEditTool { public void setCamera(Camera camera) { this.camera = camera; } + + public SceneComposerToolController.TransformationType getTransformType() { + return transformType; + } + + public void setTransformType(SceneComposerToolController.TransformationType transformType) { + this.transformType = transformType; + } } diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java index e0e8d009b..a553f35f2 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/MoveTool.java @@ -103,25 +103,19 @@ public class MoveTool extends SceneEditTool { } if (pickedMarker.equals(QUAD_XY)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord); } else if (pickedMarker.equals(QUAD_XZ)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord); } else if (pickedMarker.equals(QUAD_YZ)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord); } else if (pickedMarker.equals(ARROW_X)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord); constraintAxis = Vector3f.UNIT_X; // move only X } else if (pickedMarker.equals(ARROW_Y)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord); constraintAxis = Vector3f.UNIT_Y; // move only Y } else if (pickedMarker.equals(ARROW_Z)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord); constraintAxis = Vector3f.UNIT_Z; // move only Z } startPosition = toolController.getSelectedSpatial().getLocalTranslation().clone(); 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 d7075b9fe..fc0032edb 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 @@ -5,6 +5,7 @@ */ package com.jme3.gde.scenecomposer.tools; +import com.jme3.gde.scenecomposer.SceneComposerToolController; import com.jme3.gde.scenecomposer.SceneEditTool; import com.jme3.math.FastMath; import com.jme3.math.Quaternion; @@ -30,15 +31,12 @@ public class PickManager { private Quaternion origineRotation; private final Node plane; 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 enum TransformationType { - - local, global, camera - } public PickManager() { float size = 1000; @@ -55,7 +53,7 @@ public class PickManager { spatial = null; } - public void initiatePick(Spatial selectedSpatial, Quaternion planeRotation, TransformationType type, Camera camera, Vector2f screenCoord) { + public void initiatePick(Spatial selectedSpatial, Quaternion planeRotation, SceneComposerToolController.TransformationType type, Camera camera, Vector2f screenCoord) { spatial = selectedSpatial; startSpatialLocation = selectedSpatial.getWorldTranslation().clone(); @@ -65,16 +63,17 @@ public class PickManager { startPickLoc = SceneEditTool.pickWorldLocation(camera, screenCoord, plane, null); } - public void setTransformation(Quaternion planeRotation, TransformationType type) { + public void setTransformation(Quaternion planeRotation, SceneComposerToolController.TransformationType type) { Quaternion rot = new Quaternion(); - if (type == TransformationType.local) { + transformationType = type; + if (transformationType == SceneComposerToolController.TransformationType.local) { rot.set(spatial.getWorldRotation()); rot.multLocal(planeRotation); origineRotation = spatial.getWorldRotation().clone(); - } else if (type == TransformationType.global) { + } else if (transformationType == SceneComposerToolController.TransformationType.global) { rot.set(planeRotation); origineRotation = new Quaternion(Quaternion.IDENTITY); - } else if (type == TransformationType.camera) { + } else if (transformationType == SceneComposerToolController.TransformationType.camera) { rot.set(planeRotation); origineRotation = planeRotation.clone(); } @@ -82,6 +81,10 @@ public class PickManager { } 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; } 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 343d24818..c43ae52d0 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 @@ -96,14 +96,11 @@ public class RotateTool extends SceneEditTool { } if (pickedMarker.equals(QUAD_XY)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord); } else if (pickedMarker.equals(QUAD_XZ)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord); } else if (pickedMarker.equals(QUAD_YZ)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, - PickManager.TransformationType.local, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord); } startRotate = toolController.getSelectedSpatial().getLocalRotation().clone(); } diff --git a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/ScaleTool.java b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/ScaleTool.java index 1f0b5387b..edde41a24 100644 --- a/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/ScaleTool.java +++ b/sdk/jme3-scenecomposer/src/com/jme3/gde/scenecomposer/tools/ScaleTool.java @@ -97,18 +97,15 @@ public class ScaleTool extends SceneEditTool { if (pickedMarker.equals(QUAD_XY) || pickedMarker.equals(QUAD_XZ) || pickedMarker.equals(QUAD_YZ)) { pickManager.initiatePick(toolController.getSelectedSpatial(), camera.getRotation(), - PickManager.TransformationType.camera, camera, screenCoord); + SceneComposerToolController.TransformationType.camera, camera, screenCoord); } else if (pickedMarker.equals(ARROW_X)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, - PickManager.TransformationType.global, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XY, getTransformType(), camera, screenCoord); constraintAxis = Vector3f.UNIT_X; // scale only X } else if (pickedMarker.equals(ARROW_Y)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, - PickManager.TransformationType.global, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_YZ, getTransformType(), camera, screenCoord); constraintAxis = Vector3f.UNIT_Y; // scale only Y } else if (pickedMarker.equals(ARROW_Z)) { - pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, - PickManager.TransformationType.global, camera, screenCoord); + pickManager.initiatePick(toolController.getSelectedSpatial(), PickManager.PLANE_XZ, getTransformType(), camera, screenCoord); constraintAxis = Vector3f.UNIT_Z; // scale only Z } startScale = toolController.getSelectedSpatial().getLocalScale().clone(); @@ -125,7 +122,9 @@ public class ScaleTool extends SceneEditTool { lastScale = scale; toolController.getSelectedSpatial().setLocalScale(scale); } else if (pickedMarker.equals(ARROW_X) || pickedMarker.equals(ARROW_Y) || pickedMarker.equals(ARROW_Z)) { - Vector3f diff = pickManager.getLocalTranslation(constraintAxis); + // Get the translation in the spatial Space + Quaternion worldToSpatial = toolController.getSelectedSpatial().getWorldRotation().inverse(); + Vector3f diff = pickManager.getTranslation(worldToSpatial.mult(constraintAxis)); diff.multLocal(0.5f); Vector3f scale = startScale.add(diff); lastScale = scale;