added Blender-esque manipulation tool to scene composer
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9452 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
ea0be5cf9f
commit
f96e0d771e
@ -55,3 +55,9 @@ SceneComposerTopComponent.jButton2.text=
|
|||||||
SceneComposerTopComponent.jButton3.text=
|
SceneComposerTopComponent.jButton3.text=
|
||||||
SceneComposerTopComponent.jButton2.toolTipText=start the physics simulation and add all objects to the physics space
|
SceneComposerTopComponent.jButton2.toolTipText=start the physics simulation and add all objects to the physics space
|
||||||
SceneComposerTopComponent.jButton3.toolTipText=stop the physics simulation and remove all objects from the physics space
|
SceneComposerTopComponent.jButton3.toolTipText=stop the physics simulation and remove all objects from the physics space
|
||||||
|
SceneComposerTopComponent.snapToSceneCheckbox.text=Snap to Scene
|
||||||
|
SceneComposerTopComponent.snapToGridCheckbox.text=Snap to Grid
|
||||||
|
SceneComposerTopComponent.snapToGridCheckbox.toolTipText=Moving an object will snap to the unit grid coordinates
|
||||||
|
SceneComposerTopComponent.snapToSceneCheckbox.toolTipText=When moving an object, it will snap to whatever is under the mouse
|
||||||
|
SceneComposerTopComponent.selectTerrainCheckbox.text=Select Terrain
|
||||||
|
SceneComposerTopComponent.selectTerrainCheckbox.toolTipText=If selected, terrain can be selected, otherwise it will be ignored by the mouse
|
||||||
|
@ -80,6 +80,7 @@ public class ComposerCameraController extends AbstractCameraController {
|
|||||||
forceCameraControls = false;
|
forceCameraControls = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
toolController.doKeyPressed(kie);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -116,4 +117,5 @@ public class ComposerCameraController extends AbstractCameraController {
|
|||||||
public boolean useCameraControls() {
|
public boolean useCameraControls() {
|
||||||
return isToolUsesCameraControls() || forceCameraControls;
|
return isToolUsesCameraControls() || forceCameraControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import com.jme3.audio.AudioNode;
|
|||||||
import com.jme3.gde.core.scene.SceneApplication;
|
import com.jme3.gde.core.scene.SceneApplication;
|
||||||
import com.jme3.gde.core.scene.controller.SceneToolController;
|
import com.jme3.gde.core.scene.controller.SceneToolController;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
import com.jme3.light.Light;
|
import com.jme3.light.Light;
|
||||||
import com.jme3.light.PointLight;
|
import com.jme3.light.PointLight;
|
||||||
import com.jme3.light.SpotLight;
|
import com.jme3.light.SpotLight;
|
||||||
@ -44,6 +46,10 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
private Node nonSpatialMarkersNode;
|
private Node nonSpatialMarkersNode;
|
||||||
private Material lightMarkerMaterial;
|
private Material lightMarkerMaterial;
|
||||||
private Material audioMarkerMaterial;
|
private Material audioMarkerMaterial;
|
||||||
|
private JmeSpatial selectedSpatial;
|
||||||
|
private boolean snapToGrid = false;
|
||||||
|
private boolean snapToScene = true;
|
||||||
|
private boolean selectTerrain = false;
|
||||||
|
|
||||||
public SceneComposerToolController(final Node toolsNode, AssetManager manager, JmeNode rootNode) {
|
public SceneComposerToolController(final Node toolsNode, AssetManager manager, JmeNode rootNode) {
|
||||||
super(toolsNode, manager);
|
super(toolsNode, manager);
|
||||||
@ -190,7 +196,7 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
public void doEditToolMoved(Vector2f mouseLoc, Camera camera) {
|
public void doEditToolMoved(Vector2f mouseLoc, Camera camera) {
|
||||||
if (editTool != null) {
|
if (editTool != null) {
|
||||||
editTool.setCamera(camera);
|
editTool.setCamera(camera);
|
||||||
editTool.mouseMoved(mouseLoc);
|
editTool.mouseMoved(mouseLoc, rootNode, editorController.getCurrentDataObject(), selectedSpatial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +214,12 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doKeyPressed(KeyInputEvent kie) {
|
||||||
|
if (editTool != null) {
|
||||||
|
editTool.keyPressed(kie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a marker for the light to the scene if it does not exist yet
|
* Adds a marker for the light to the scene if it does not exist yet
|
||||||
*/
|
*/
|
||||||
@ -290,6 +302,30 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSnapToGrid() {
|
||||||
|
return snapToGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSnapToGrid(boolean snapToGrid) {
|
||||||
|
this.snapToGrid = snapToGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSnapToScene(boolean snapToScene) {
|
||||||
|
this.snapToScene = snapToScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSnapToScene() {
|
||||||
|
return snapToScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean selectTerrain() {
|
||||||
|
return selectTerrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectTerrain(boolean selectTerrain) {
|
||||||
|
this.selectTerrain = selectTerrain;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker on the screen that shows where a point light or
|
* A marker on the screen that shows where a point light or
|
||||||
* a spot light is. This marker is not part of the scene,
|
* a spot light is. This marker is not part of the scene,
|
||||||
@ -441,4 +477,11 @@ public class SceneComposerToolController extends SceneToolController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JmeNode getRootNode() {
|
||||||
|
return rootNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedSpatial(JmeSpatial selectedSpatial) {
|
||||||
|
this.selectedSpatial = selectedSpatial;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,13 +443,24 @@
|
|||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="jSeparator6" alignment="0" pref="357" max="32767" attributes="0"/>
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="10" pref="10" max="10" attributes="0"/>
|
<EmptySpace min="10" pref="10" max="10" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<Component id="snapToSceneCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
|
<Component id="snapToGridCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||||
|
<Component id="selectTerrainCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
<Component id="jLabel5" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="emitButton" pref="302" max="32767" attributes="0"/>
|
<Component id="emitButton" pref="302" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<Component id="jSeparator6" alignment="0" pref="357" max="32767" attributes="0"/>
|
</Group>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
@ -468,7 +479,13 @@
|
|||||||
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="emitButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="emitButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace pref="40" max="32767" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="snapToSceneCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="snapToGridCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="selectTerrainCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace pref="15" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -601,6 +618,46 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="emitButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="emitButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="snapToSceneCheckbox">
|
||||||
|
<Properties>
|
||||||
|
<Property name="selected" type="boolean" value="true"/>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.snapToSceneCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</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.snapToSceneCheckbox.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="snapToSceneCheckboxActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="snapToGridCheckbox">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.snapToGridCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</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.snapToGridCheckbox.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="snapToGridCheckboxActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="selectTerrainCheckbox">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="com/jme3/gde/scenecomposer/Bundle.properties" key="SceneComposerTopComponent.selectTerrainCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</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.selectTerrainCheckbox.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="selectTerrainCheckboxActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
|
@ -132,6 +132,9 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
|
|||||||
jSeparator6 = new javax.swing.JSeparator();
|
jSeparator6 = new javax.swing.JSeparator();
|
||||||
jLabel5 = new javax.swing.JLabel();
|
jLabel5 = new javax.swing.JLabel();
|
||||||
emitButton = new javax.swing.JButton();
|
emitButton = new javax.swing.JButton();
|
||||||
|
snapToSceneCheckbox = new javax.swing.JCheckBox();
|
||||||
|
snapToGridCheckbox = new javax.swing.JCheckBox();
|
||||||
|
selectTerrainCheckbox = new javax.swing.JCheckBox();
|
||||||
|
|
||||||
setBackground(new java.awt.Color(204, 204, 204));
|
setBackground(new java.awt.Color(204, 204, 204));
|
||||||
|
|
||||||
@ -421,6 +424,31 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
snapToSceneCheckbox.setSelected(true);
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(snapToSceneCheckbox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToSceneCheckbox.text")); // NOI18N
|
||||||
|
snapToSceneCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToSceneCheckbox.toolTipText")); // NOI18N
|
||||||
|
snapToSceneCheckbox.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
snapToSceneCheckboxActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(snapToGridCheckbox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToGridCheckbox.text")); // NOI18N
|
||||||
|
snapToGridCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.snapToGridCheckbox.toolTipText")); // NOI18N
|
||||||
|
snapToGridCheckbox.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
snapToGridCheckboxActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(selectTerrainCheckbox, org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectTerrainCheckbox.text")); // NOI18N
|
||||||
|
selectTerrainCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(SceneComposerTopComponent.class, "SceneComposerTopComponent.selectTerrainCheckbox.toolTipText")); // NOI18N
|
||||||
|
selectTerrainCheckbox.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
selectTerrainCheckboxActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
|
javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
|
||||||
jPanel4.setLayout(jPanel4Layout);
|
jPanel4.setLayout(jPanel4Layout);
|
||||||
jPanel4Layout.setHorizontalGroup(
|
jPanel4Layout.setHorizontalGroup(
|
||||||
@ -430,12 +458,20 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
|
|||||||
.addGroup(jPanel4Layout.createSequentialGroup()
|
.addGroup(jPanel4Layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(jSeparator6, javax.swing.GroupLayout.DEFAULT_SIZE, 357, Short.MAX_VALUE)
|
||||||
.addGroup(jPanel4Layout.createSequentialGroup()
|
.addGroup(jPanel4Layout.createSequentialGroup()
|
||||||
.addGap(10, 10, 10)
|
.addGap(10, 10, 10)
|
||||||
|
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(jPanel4Layout.createSequentialGroup()
|
||||||
|
.addComponent(snapToSceneCheckbox)
|
||||||
|
.addGap(18, 18, 18)
|
||||||
|
.addComponent(snapToGridCheckbox)
|
||||||
|
.addGap(18, 18, 18)
|
||||||
|
.addComponent(selectTerrainCheckbox))
|
||||||
|
.addGroup(jPanel4Layout.createSequentialGroup()
|
||||||
.addComponent(jLabel5)
|
.addComponent(jLabel5)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(emitButton, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE))
|
.addComponent(emitButton, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE)))))
|
||||||
.addComponent(jSeparator6, javax.swing.GroupLayout.DEFAULT_SIZE, 357, Short.MAX_VALUE))
|
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
);
|
);
|
||||||
jPanel4Layout.setVerticalGroup(
|
jPanel4Layout.setVerticalGroup(
|
||||||
@ -450,7 +486,12 @@ public final class SceneComposerTopComponent extends TopComponent implements Sce
|
|||||||
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(jLabel5)
|
.addComponent(jLabel5)
|
||||||
.addComponent(emitButton))
|
.addComponent(emitButton))
|
||||||
.addContainerGap(40, Short.MAX_VALUE))
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(snapToSceneCheckbox)
|
||||||
|
.addComponent(snapToGridCheckbox)
|
||||||
|
.addComponent(selectTerrainCheckbox))
|
||||||
|
.addContainerGap(15, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
@ -572,6 +613,18 @@ private void scaleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F
|
|||||||
toolController.showEditTool(tool);
|
toolController.showEditTool(tool);
|
||||||
}//GEN-LAST:event_rotateButtonActionPerformed
|
}//GEN-LAST:event_rotateButtonActionPerformed
|
||||||
|
|
||||||
|
private void snapToSceneCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_snapToSceneCheckboxActionPerformed
|
||||||
|
toolController.setSnapToScene(snapToSceneCheckbox.isSelected());
|
||||||
|
}//GEN-LAST:event_snapToSceneCheckboxActionPerformed
|
||||||
|
|
||||||
|
private void snapToGridCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_snapToGridCheckboxActionPerformed
|
||||||
|
toolController.setSnapToGrid(snapToGridCheckbox.isSelected());
|
||||||
|
}//GEN-LAST:event_snapToGridCheckboxActionPerformed
|
||||||
|
|
||||||
|
private void selectTerrainCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectTerrainCheckboxActionPerformed
|
||||||
|
toolController.setSelectTerrain(selectTerrainCheckbox.isSelected());
|
||||||
|
}//GEN-LAST:event_selectTerrainCheckboxActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton camToCursorSelectionButton;
|
private javax.swing.JButton camToCursorSelectionButton;
|
||||||
private javax.swing.JButton createPhysicsMeshButton;
|
private javax.swing.JButton createPhysicsMeshButton;
|
||||||
@ -611,8 +664,11 @@ private void scaleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F
|
|||||||
private javax.swing.JLabel sceneInfoLabel2;
|
private javax.swing.JLabel sceneInfoLabel2;
|
||||||
private javax.swing.JPanel sceneInfoPanel;
|
private javax.swing.JPanel sceneInfoPanel;
|
||||||
private javax.swing.JToggleButton selectButton;
|
private javax.swing.JToggleButton selectButton;
|
||||||
|
private javax.swing.JCheckBox selectTerrainCheckbox;
|
||||||
private javax.swing.JToggleButton showGridToggleButton;
|
private javax.swing.JToggleButton showGridToggleButton;
|
||||||
private javax.swing.JToggleButton showSelectionToggleButton;
|
private javax.swing.JToggleButton showSelectionToggleButton;
|
||||||
|
private javax.swing.JCheckBox snapToGridCheckbox;
|
||||||
|
private javax.swing.JCheckBox snapToSceneCheckbox;
|
||||||
private javax.swing.ButtonGroup spatialModButtonGroup;
|
private javax.swing.ButtonGroup spatialModButtonGroup;
|
||||||
// End of variables declaration//GEN-END:variables
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
@ -862,6 +918,7 @@ private void scaleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (toolController != null) {
|
if (toolController != null) {
|
||||||
|
toolController.setSelectedSpatial(spatial);
|
||||||
toolController.updateSelection(spatial.getLookup().lookup(Spatial.class));
|
toolController.updateSelection(spatial.getLookup().lookup(Spatial.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,10 @@ import com.jme3.collision.CollisionResult;
|
|||||||
import com.jme3.collision.CollisionResults;
|
import com.jme3.collision.CollisionResults;
|
||||||
import com.jme3.gde.core.scene.SceneApplication;
|
import com.jme3.gde.core.scene.SceneApplication;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
import com.jme3.gde.core.undoredo.SceneUndoRedoManager;
|
import com.jme3.gde.core.undoredo.SceneUndoRedoManager;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
import com.jme3.material.RenderState.BlendMode;
|
import com.jme3.material.RenderState.BlendMode;
|
||||||
import com.jme3.material.RenderState.FaceCullMode;
|
import com.jme3.material.RenderState.FaceCullMode;
|
||||||
@ -39,6 +41,7 @@ import com.jme3.scene.Spatial;
|
|||||||
import com.jme3.scene.debug.Arrow;
|
import com.jme3.scene.debug.Arrow;
|
||||||
import com.jme3.scene.debug.WireBox;
|
import com.jme3.scene.debug.WireBox;
|
||||||
import com.jme3.scene.shape.Quad;
|
import com.jme3.scene.shape.Quad;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import org.openide.loaders.DataObject;
|
import org.openide.loaders.DataObject;
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
@ -178,7 +181,7 @@ public abstract class SceneEditTool {
|
|||||||
/**
|
/**
|
||||||
* Called when the mouse is moved but not dragged (ie no buttons are pressed)
|
* Called when the mouse is moved but not dragged (ie no buttons are pressed)
|
||||||
*/
|
*/
|
||||||
public abstract void mouseMoved(Vector2f screenCoord);
|
public abstract void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject dataObject, JmeSpatial selectedSpatial);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the mouse is moved while the primary button is down
|
* Called when the mouse is moved while the primary button is down
|
||||||
@ -190,6 +193,8 @@ public abstract class SceneEditTool {
|
|||||||
*/
|
*/
|
||||||
public abstract void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject);
|
public abstract void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject);
|
||||||
|
|
||||||
|
public void keyPressed(KeyInputEvent kie) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call when an action is performed that requires the scene to be saved
|
* Call when an action is performed that requires the scene to be saved
|
||||||
* and an undo can be performed
|
* and an undo can be performed
|
||||||
@ -223,11 +228,23 @@ public abstract class SceneEditTool {
|
|||||||
*/
|
*/
|
||||||
protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) {
|
protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode) {
|
||||||
Node rootNode = jmeRootNode.getLookup().lookup(Node.class);
|
Node rootNode = jmeRootNode.getLookup().lookup(Node.class);
|
||||||
return pickWorldLocation(cam, mouseLoc, rootNode);
|
return pickWorldLocation(cam, mouseLoc, rootNode, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, Node rootNode) {
|
/**
|
||||||
CollisionResult cr = pick(cam, mouseLoc, rootNode);
|
* Pick anything except the excluded spatial
|
||||||
|
* @param excludeSpat to not pick
|
||||||
|
*/
|
||||||
|
protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, JmeNode jmeRootNode, JmeSpatial excludeSpat) {
|
||||||
|
Node rootNode = jmeRootNode.getLookup().lookup(Node.class);
|
||||||
|
return pickWorldLocation(cam, mouseLoc, rootNode, excludeSpat);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Vector3f pickWorldLocation(Camera cam, Vector2f mouseLoc, Node rootNode, JmeSpatial excludeSpat) {
|
||||||
|
Spatial exclude = null;
|
||||||
|
if (excludeSpat != null)
|
||||||
|
exclude = excludeSpat.getLookup().lookup(Spatial.class);
|
||||||
|
CollisionResult cr = doPick(cam, mouseLoc, rootNode, exclude);
|
||||||
if (cr != null) {
|
if (cr != null) {
|
||||||
return cr.getContactPoint();
|
return cr.getContactPoint();
|
||||||
} else {
|
} else {
|
||||||
@ -235,6 +252,46 @@ public abstract class SceneEditTool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CollisionResult doPick(Camera cam, Vector2f mouseLoc, Node node, Spatial exclude) {
|
||||||
|
CollisionResults results = new CollisionResults();
|
||||||
|
Ray ray = new Ray();
|
||||||
|
Vector3f pos = cam.getWorldCoordinates(mouseLoc, 0).clone();
|
||||||
|
Vector3f dir = cam.getWorldCoordinates(mouseLoc, 0.1f).clone();
|
||||||
|
dir.subtractLocal(pos).normalizeLocal();
|
||||||
|
ray.setOrigin(pos);
|
||||||
|
ray.setDirection(dir);
|
||||||
|
node.collideWith(ray, results);
|
||||||
|
CollisionResult result = null;
|
||||||
|
if (exclude == null)
|
||||||
|
result = results.getClosestCollision();
|
||||||
|
else {
|
||||||
|
Iterator<CollisionResult> it = results.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
CollisionResult cr = it.next();
|
||||||
|
if (isExcluded(cr.getGeometry(), exclude))
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
return cr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the selected spatial the one we want to exclude from the picking?
|
||||||
|
* Recursively looks up the parents to find out.
|
||||||
|
*/
|
||||||
|
private boolean isExcluded(Spatial s, Spatial exclude) {
|
||||||
|
if (s.equals(exclude))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (s.getParent() != null) {
|
||||||
|
return isExcluded(s.getParent(), exclude);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick a part of the axis marker. The result is a Vector3f that represents
|
* Pick a part of the axis marker. The result is a Vector3f that represents
|
||||||
* what part of the axis was selected.
|
* what part of the axis was selected.
|
||||||
|
@ -8,6 +8,7 @@ import com.jme3.asset.AssetManager;
|
|||||||
import com.jme3.bullet.control.CharacterControl;
|
import com.jme3.bullet.control.CharacterControl;
|
||||||
import com.jme3.bullet.control.RigidBodyControl;
|
import com.jme3.bullet.control.RigidBodyControl;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
||||||
import com.jme3.gde.scenecomposer.SceneEditTool;
|
import com.jme3.gde.scenecomposer.SceneEditTool;
|
||||||
@ -87,7 +88,7 @@ public class MoveTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(Vector2f screenCoord) {
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
|
||||||
if (pickedPlane == null) {
|
if (pickedPlane == null) {
|
||||||
highlightAxisMarker(camera, screenCoord, axisPickType);
|
highlightAxisMarker(camera, screenCoord, axisPickType);
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ public class MoveTool extends SceneEditTool {
|
|||||||
plane.setLocalTranslation(startLoc);
|
plane.setLocalTranslation(startLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3f planeHit = pickWorldLocation(camera, screenCoord, plane);
|
Vector3f planeHit = pickWorldLocation(camera, screenCoord, plane, null);
|
||||||
if (planeHit == null)
|
if (planeHit == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ package com.jme3.gde.scenecomposer.tools;
|
|||||||
|
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
||||||
import com.jme3.gde.scenecomposer.SceneEditTool;
|
import com.jme3.gde.scenecomposer.SceneEditTool;
|
||||||
@ -58,7 +59,7 @@ public class RotateTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(Vector2f screenCoord) {
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
|
||||||
if (pickedPlane == null) {
|
if (pickedPlane == null) {
|
||||||
highlightAxisMarker(camera, screenCoord, axisPickType);
|
highlightAxisMarker(camera, screenCoord, axisPickType);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package com.jme3.gde.scenecomposer.tools;
|
|||||||
|
|
||||||
import com.jme3.asset.AssetManager;
|
import com.jme3.asset.AssetManager;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
import com.jme3.gde.scenecomposer.SceneComposerToolController;
|
||||||
import com.jme3.gde.scenecomposer.SceneEditTool;
|
import com.jme3.gde.scenecomposer.SceneEditTool;
|
||||||
@ -57,7 +58,7 @@ public class ScaleTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(Vector2f screenCoord) {
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
|
||||||
if (pickedPlane == null) {
|
if (pickedPlane == null) {
|
||||||
highlightAxisMarker(camera, screenCoord, axisPickType, true);
|
highlightAxisMarker(camera, screenCoord, axisPickType, true);
|
||||||
}
|
}
|
||||||
|
@ -6,36 +6,636 @@ package com.jme3.gde.scenecomposer.tools;
|
|||||||
|
|
||||||
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
|
import com.jme3.gde.core.sceneexplorer.SceneExplorerTopComponent;
|
||||||
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeNode;
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
|
||||||
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
|
import com.jme3.gde.core.sceneviewer.SceneViewerTopComponent;
|
||||||
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
|
||||||
import com.jme3.gde.scenecomposer.SceneEditTool;
|
import com.jme3.gde.scenecomposer.SceneEditTool;
|
||||||
|
import com.jme3.input.KeyInput;
|
||||||
|
import com.jme3.input.event.KeyInputEvent;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
|
import com.jme3.math.Matrix3f;
|
||||||
|
import com.jme3.math.Quaternion;
|
||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
|
import com.jme3.terrain.Terrain;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import org.openide.loaders.DataObject;
|
import org.openide.loaders.DataObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 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
|
||||||
|
* 2) ESC will not reset currentState (ESC get hijacked)
|
||||||
|
* 3) rotation towards screen is busted (wrong axis)
|
||||||
*
|
*
|
||||||
* @author Brent Owens
|
* @author Brent Owens
|
||||||
*/
|
*/
|
||||||
public class SelectTool extends SceneEditTool {
|
public class SelectTool extends SceneEditTool {
|
||||||
|
|
||||||
protected Spatial selected;
|
protected Spatial selected;
|
||||||
private boolean wasDragging = false;
|
|
||||||
|
private enum State {translate, rotate, scale};
|
||||||
|
private State currentState = null;
|
||||||
|
|
||||||
|
private enum Axis {x, y, z};
|
||||||
|
private Axis currentAxis = null;
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void keyPressed(KeyInputEvent kie) {
|
||||||
|
|
||||||
|
checkModificatorKeys(kie); // alt,shift,ctrl
|
||||||
|
|
||||||
|
if (selected == null)
|
||||||
|
return; // only do anything if a spatial is selected
|
||||||
|
|
||||||
|
// key released
|
||||||
|
if (kie.isReleased()) {
|
||||||
|
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 = null;
|
||||||
|
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) {
|
||||||
|
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 = null;
|
||||||
|
numberBuilder = new StringBuilder();
|
||||||
|
startRot = null;
|
||||||
|
startTrans = null;
|
||||||
|
startScale = null;
|
||||||
|
startMouseCoord = null;
|
||||||
|
startSelectedCoord = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
float x = 0, y= 0, z = 0;
|
||||||
|
if (currentAxis == Axis.x)
|
||||||
|
x = value;
|
||||||
|
else if (currentAxis == Axis.y)
|
||||||
|
y = value;
|
||||||
|
else if (currentAxis == Axis.z)
|
||||||
|
z = value;
|
||||||
|
Vector3f before = selected.getLocalTranslation().clone();
|
||||||
|
Vector3f after = selected.getLocalTranslation().addLocal(x, y, z);
|
||||||
|
selected.setLocalTranslation(after);
|
||||||
|
actionPerformed(new MoveUndo(selected, before, after));
|
||||||
|
} else if (currentState == State.scale) {
|
||||||
|
float x = 1, y= 1, z = 1;
|
||||||
|
if (currentAxis == Axis.x)
|
||||||
|
x = value;
|
||||||
|
else if (currentAxis == Axis.y)
|
||||||
|
y = value;
|
||||||
|
else if (currentAxis == Axis.z)
|
||||||
|
z = value;
|
||||||
|
else if (currentAxis == null) {
|
||||||
|
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 == Axis.x)
|
||||||
|
x = 1;
|
||||||
|
else if (currentAxis == Axis.y)
|
||||||
|
y = 1;
|
||||||
|
else if (currentAxis == Axis.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (ctrlDown && 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) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_G) {
|
||||||
|
currentState = State.translate;
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_R) {
|
||||||
|
currentState = State.rotate;
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_S) {
|
||||||
|
currentState = State.scale;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkAxisKey(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_X) {
|
||||||
|
currentAxis = Axis.x;
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_Y) {
|
||||||
|
currentAxis = Axis.y;
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_Z) {
|
||||||
|
currentAxis = Axis.z;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
numberBuilder.append('0');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_1) {
|
||||||
|
numberBuilder.append('1');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_2) {
|
||||||
|
numberBuilder.append('2');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_3) {
|
||||||
|
numberBuilder.append('3');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_4) {
|
||||||
|
numberBuilder.append('4');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_5) {
|
||||||
|
numberBuilder.append('5');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_6) {
|
||||||
|
numberBuilder.append('6');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_7) {
|
||||||
|
numberBuilder.append('7');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_8) {
|
||||||
|
numberBuilder.append('8');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_9) {
|
||||||
|
numberBuilder.append('9');
|
||||||
|
return true;
|
||||||
|
} else if (kie.getKeyCode() == KeyInput.KEY_PERIOD) {
|
||||||
|
if (numberBuilder.indexOf(".") == -1){ // if it doesn't exist yet
|
||||||
|
if (numberBuilder.length() == 0 ||
|
||||||
|
(numberBuilder.length() == 1 && numberBuilder.charAt(0) == '-'))
|
||||||
|
numberBuilder.append("0.");
|
||||||
|
else
|
||||||
|
numberBuilder.append(".");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkEnterHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_RETURN) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkEscHit(KeyInputEvent kie) {
|
||||||
|
if (kie.getKeyCode() == KeyInput.KEY_ESCAPE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
|
public void actionPrimary(Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
|
||||||
if (!pressed && !wasDragging) {
|
if (!pressed) {
|
||||||
// mouse released and wasn't dragging, select a new spatial
|
// left mouse released
|
||||||
final Spatial result = pickWorldSpatial(getCamera(), screenCoord, rootNode);
|
if (!wasDraggingL) {
|
||||||
|
// left mouse pressed
|
||||||
|
if (currentState != null) {
|
||||||
|
// finish manipulating the spatial
|
||||||
|
if (moving != null) {
|
||||||
|
moving.after = selected.getLocalTranslation().clone();
|
||||||
|
actionPerformed(moving);
|
||||||
|
moving = null;
|
||||||
|
clearState(false);
|
||||||
|
} else if (scaling != null) {
|
||||||
|
scaling.after = selected.getLocalScale().clone();
|
||||||
|
actionPerformed(scaling);
|
||||||
|
scaling = null;
|
||||||
|
clearState(false);
|
||||||
|
} 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.doSetCursorLocation(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wasDraggingL = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionSecondary(final Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
|
||||||
|
if (pressed) {
|
||||||
|
// mouse down
|
||||||
|
|
||||||
|
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) ) {
|
||||||
|
// only select non-terrain
|
||||||
|
selected = null;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// climb up and find the Model Node (parent) and select that, don't select the geom
|
||||||
|
Spatial linkNodeParent = findModelNodeParent(s);
|
||||||
|
if (linkNodeParent != null)
|
||||||
|
s = linkNodeParent;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
final Spatial selec = s;
|
||||||
|
selected = selec;
|
||||||
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (selec != null) {
|
||||||
|
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(selec)});
|
||||||
|
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(selec));
|
||||||
|
} else {
|
||||||
|
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode});
|
||||||
|
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toolController.updateSelection(selected);
|
||||||
|
}
|
||||||
|
wasDownR = true;
|
||||||
|
} else {
|
||||||
|
// mouse up, stop everything
|
||||||
|
wasDownR = false;
|
||||||
|
wasDraggingR = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 instanceof Node)
|
||||||
|
return child;
|
||||||
|
|
||||||
|
if (child.getParent() != null)
|
||||||
|
return findModelNodeParent(child.getParent());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved(Vector2f screenCoord, JmeNode rootNode, DataObject currentDataObject, JmeSpatial selectedSpatial) {
|
||||||
|
if (currentState != null) {
|
||||||
|
//if (currentAxis != null) {
|
||||||
|
// manipulate from specific axis
|
||||||
|
handleMouseManipulate(screenCoord, currentState, currentAxis, rootNode, currentDataObject, selectedSpatial);
|
||||||
|
//} else {
|
||||||
|
// manipulate from screen coordinates
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
wasDraggingL = pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
||||||
|
wasDraggingR = pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manipulate the spatial
|
||||||
|
*/
|
||||||
|
private void handleMouseManipulate( Vector2f screenCoord,
|
||||||
|
State state,
|
||||||
|
Axis 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(Axis axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
|
||||||
|
// free form translation
|
||||||
|
if (axis == null) {
|
||||||
|
if (toolController.isSnapToScene()) {
|
||||||
|
if (moving == null)
|
||||||
|
moving = new MoveUndo(selected, selected.getLocalTranslation().clone(), null);
|
||||||
|
Vector3f loc = pickWorldLocation(camera, screenCoord, rootNode, selectedSpatial);
|
||||||
|
if (loc != null) {
|
||||||
|
//Node sel = selectedSpatial.getLookup().lookup(Node.class);
|
||||||
|
if (toolController.isSnapToGrid()) {
|
||||||
|
selected.setLocalTranslation(loc.set(Math.round(loc.x), loc.y, Math.round(loc.z)));
|
||||||
|
} else {
|
||||||
|
selected.setLocalTranslation(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//TODO drag alone a camera-oriented axis
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//snap to specific axis, ignoring snapToScene
|
||||||
|
if (moving == null)
|
||||||
|
moving = new MoveUndo(selected, selected.getLocalTranslation().clone(), null);
|
||||||
|
Vector3f loc = pickWorldLocation(camera, screenCoord, rootNode, selectedSpatial);
|
||||||
|
if (loc != null) {
|
||||||
|
if (toolController.isSnapToGrid())
|
||||||
|
loc.set(Math.round(loc.x), Math.round(loc.y), Math.round(loc.z)); // round the values
|
||||||
|
|
||||||
|
//Node sel = selectedSpatial.getLookup().lookup(Node.class);
|
||||||
|
Vector3f prev = selected.getLocalTranslation().clone();
|
||||||
|
Vector3f newLoc = new Vector3f(prev);
|
||||||
|
if (axis == Axis.x)
|
||||||
|
newLoc.x = loc.x;
|
||||||
|
else if (axis == Axis.y)
|
||||||
|
newLoc.y = loc.y;
|
||||||
|
if (axis == Axis.z)
|
||||||
|
newLoc.z = loc.z;
|
||||||
|
|
||||||
|
selected.setLocalTranslation(newLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doMouseScale(Axis axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
|
||||||
|
// 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 == Axis.x)
|
||||||
|
selected.setLocalScale(ratio, prev.y, prev.z);
|
||||||
|
else if (axis == Axis.y)
|
||||||
|
selected.setLocalScale(prev.x, ratio, prev.z);
|
||||||
|
else if (axis == Axis.z)
|
||||||
|
selected.setLocalScale(prev.x, prev.y, ratio);
|
||||||
|
else
|
||||||
|
selected.setLocalScale(ratio, ratio, ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doMouseRotate(Axis axis, Vector2f screenCoord, JmeNode rootNode, JmeSpatial selectedSpatial) {
|
||||||
|
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 == Axis.x) {
|
||||||
|
rotate = rotate.fromAngleAxis(newRotAngle, Vector3f.UNIT_X);
|
||||||
|
} else if (axis == Axis.y) {
|
||||||
|
rotate = rotate.fromAngleAxis(newRotAngle, Vector3f.UNIT_Y);
|
||||||
|
} else if (axis == Axis.z) {
|
||||||
|
rotate = rotate.fromAngleAxis(newRotAngle, Vector3f.UNIT_Z);
|
||||||
|
} else {
|
||||||
|
Vector3f screen = getCamera().getScreenCoordinates(selected.getWorldTranslation());
|
||||||
|
rotate = rotate.fromAngleAxis(newRotAngle, screen.normalize());
|
||||||
|
}
|
||||||
|
selected.setLocalRotation(selected.getLocalRotation().mult(rotate));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void duplicateSelected() {
|
||||||
|
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() {
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (result != null) {
|
if (cloned != null) {
|
||||||
// System.out.println(rootNode.getChild(result).getName());
|
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(cloned)});
|
||||||
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode.getChild(result)});
|
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(cloned));
|
||||||
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode.getChild(result));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode});
|
SceneViewerTopComponent.findInstance().setActivatedNodes(new org.openide.nodes.Node[]{rootNode});
|
||||||
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode);
|
SceneExplorerTopComponent.findInstance().setSelectedNode(rootNode);
|
||||||
@ -43,40 +643,157 @@ public class SelectTool extends SceneEditTool {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result != null) {
|
// set to automatically 'grab'/'translate' the new cloned model
|
||||||
updateToolsTransformation();
|
toolController.updateSelection(selected);
|
||||||
}
|
currentState = State.translate;
|
||||||
|
currentAxis = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pressed) {
|
private void deleteSelected() {
|
||||||
wasDragging = false;
|
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 MoveUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Vector3f before,after;
|
||||||
|
|
||||||
|
MoveUndo(Spatial spatial, Vector3f before, Vector3f after) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.before = before;
|
||||||
|
this.after = after;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionSecondary(final Vector2f screenCoord, boolean pressed, final JmeNode rootNode, DataObject dataObject) {
|
public void sceneUndo() {
|
||||||
if (!pressed && !wasDragging) {
|
spatial.setLocalTranslation(before);
|
||||||
final Vector3f result = pickWorldLocation(getCamera(), screenCoord, rootNode);
|
|
||||||
if (result != null) {
|
|
||||||
toolController.doSetCursorLocation(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!pressed) {
|
|
||||||
wasDragging = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved(Vector2f screenCoord) {
|
public void sceneRedo() {
|
||||||
|
spatial.setLocalTranslation(after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public void draggedPrimary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
public void sceneUndo() {
|
||||||
wasDragging = pressed;
|
spatial.setLocalScale(before);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draggedSecondary(Vector2f screenCoord, boolean pressed, JmeNode rootNode, DataObject currentDataObject) {
|
public void sceneRedo() {
|
||||||
wasDragging = pressed;
|
spatial.setLocalScale(after);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RotateUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Quaternion before,after;
|
||||||
|
|
||||||
|
RotateUndo(Spatial spatial, Quaternion before, Quaternion after) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.before = before;
|
||||||
|
this.after = after;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneUndo() {
|
||||||
|
spatial.setLocalRotation(before);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneRedo() {
|
||||||
|
spatial.setLocalRotation(after);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeleteUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Node parent;
|
||||||
|
|
||||||
|
DeleteUndo(Spatial spatial, Node parent) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneUndo() {
|
||||||
|
parent.attachChild(spatial);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneRedo() {
|
||||||
|
spatial.removeFromParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DuplicateUndo extends AbstractUndoableSceneEdit {
|
||||||
|
|
||||||
|
private Spatial spatial;
|
||||||
|
private Node parent;
|
||||||
|
|
||||||
|
DuplicateUndo(Spatial spatial, Node parent) {
|
||||||
|
this.spatial = spatial;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneUndo() {
|
||||||
|
spatial.removeFromParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sceneRedo() {
|
||||||
|
parent.attachChild(spatial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the selected item is a Terrain
|
||||||
|
* It will climb up the parent tree to see if
|
||||||
|
* a parent is terrain too.
|
||||||
|
* Recursive call.
|
||||||
|
*/
|
||||||
|
protected boolean isTerrain(Spatial s) {
|
||||||
|
if (s instanceof Terrain)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (s.getParent() != null) {
|
||||||
|
return isTerrain(s.getParent());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user