From ef700eff19511bb5390efbfa7b183c9acfe19daa Mon Sep 17 00:00:00 2001 From: "bre..om" Date: Fri, 8 Mar 2013 19:11:02 +0000 Subject: [PATCH] terrain paint tool remembers undo history as an entire mouseDown event now. RMB now erases git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10473 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../actions/AbstractStatefulGLToolAction.java | 8 +- .../jme3/gde/terraineditor/Bundle.properties | 2 - .../TerrainCameraController.java | 40 ++++--- .../TerrainEditorTopComponent.form | 28 +---- .../TerrainEditorTopComponent.java | 33 +----- .../terraineditor/TerrainToolController.java | 30 ++++- .../tools/AbstractTerrainToolAction.java | 8 +- .../terraineditor/tools/PaintTerrainTool.java | 110 +++++++++++++++++- .../tools/PaintTerrainToolAction.java | 6 +- .../gde/terraineditor/tools/TerrainTool.java | 15 +++ 10 files changed, 197 insertions(+), 83 deletions(-) diff --git a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractStatefulGLToolAction.java b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractStatefulGLToolAction.java index 647abf5fe..322c2386a 100644 --- a/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractStatefulGLToolAction.java +++ b/sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractStatefulGLToolAction.java @@ -62,9 +62,15 @@ public abstract class AbstractStatefulGLToolAction { } public void doActionPerformed(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { + doActionPerformed(rootNode, dataObject, true); + } + + public void doActionPerformed(final AbstractSceneExplorerNode rootNode, final DataObject dataObject, boolean recordUndo) { final Object object = doApplyTool(rootNode); - if (object!=null) { + + if (object!=null && recordUndo) { + Lookup lookup = Lookup.getDefault() ; SceneUndoRedoManager manager = lookup.lookup(SceneUndoRedoManager.class); diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties index 89be45313..5ac2494c0 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties @@ -89,8 +89,6 @@ TerrainEditorTopComponent.remainingTexturesLabel.text=\ TerrainEditorTopComponent.textureTable.columnModel.title4=Normal TerrainEditorTopComponent.eraseButton.toolTipText=Erase a texture from the terrain TerrainEditorTopComponent.eraseButton.text= -TerrainEditorTopComponent.paintButton.toolTipText=Paint a texture onto the terrain -TerrainEditorTopComponent.paintButton.text= TerrainEditorTopComponent.paintingPanel.border.title=Painting TerrainEditorTopComponent.triPlanarCheckBox.toolTipText=Enable if you have a lot of vertical surfaces. It will look nice but lower performance TerrainEditorTopComponent.triPlanarCheckBox.text=Tri-planar diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java index a60118776..e4deb552c 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainCameraController.java @@ -105,32 +105,43 @@ public class TerrainCameraController extends AbstractCameraController { @Override protected void checkClick(int button, boolean pressed) { + checkMouseButtonState(button, pressed); + } + + @Override + protected void checkDragged(int button, boolean pressed) { + checkMouseButtonState(button, pressed); + } + + private void checkMouseButtonState(int button, boolean pressed) { + if (isTerrainEditButtonEnabled() && !forceCameraControls) { + if (terrainEditToolActivated != pressed) + toolController.doTerrainEditToolActionEnded(); // button state change, trigger undo action + terrainEditToolActivated = pressed; + } - /*if (button == 0) { + + if (button == 0) { if (isTerrainEditButtonEnabled() && !forceCameraControls) { - terrainEditToolActivated = true; + toolController.setPrimary(pressed); + System.out.println("primary "+pressed); } } - - if (button == 1) { - if (isTerrainEditButtonEnabled() && !forceCameraControls) { - toolController.doTerrainEditToolAlternateActivated(); - } - }*/ - + if (button == 1) { if (isTerrainEditButtonEnabled() && !forceCameraControls) { - toolController.doTerrainEditToolAlternateActivated(); + toolController.setAlternate(pressed); + System.out.println("alternate "+pressed); } } } - @Override + /*@Override protected void checkDragged(int button, boolean pressed) { - if (button == 0 && !forceCameraControls) { + if ( (button == 0 || button == 1) && !forceCameraControls) { terrainEditToolActivated = true; } - } + }*/ @Override protected void checkMoved() { @@ -151,8 +162,9 @@ public class TerrainCameraController extends AbstractCameraController { lastModifyTime = 0; if (terrainEditToolActivated) { toolController.doTerrainEditToolActivated(); + toolController.doTerrainEditToolAlternateActivated(); } - terrainEditToolActivated = false; + //terrainEditToolActivated = false; lastModifyTime = app.getContext().getTimer().getTime(); } } diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form index 60b096578..b07ee78a3 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form @@ -1,4 +1,4 @@ - +
@@ -254,7 +254,7 @@ - + @@ -462,28 +462,6 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -498,6 +476,7 @@ + @@ -520,7 +499,6 @@ - diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java index a20935465..a13000398 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java @@ -252,7 +252,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce jSeparator2 = new javax.swing.JToolBar.Separator(); addTextureButton = new javax.swing.JButton(); removeTextureButton = new javax.swing.JButton(); - paintButton = new javax.swing.JToggleButton(); eraseButton = new javax.swing.JToggleButton(); jSeparator3 = new javax.swing.JToolBar.Separator(); radiusLabel = new javax.swing.JLabel(); @@ -512,24 +511,11 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce }); jToolBar1.add(removeTextureButton); - terrainModButtonGroup.add(paintButton); - paintButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-paint-circle.png"))); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(paintButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.paintButton.text")); // NOI18N - paintButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.paintButton.toolTipText")); // NOI18N - paintButton.setFocusable(false); - paintButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - paintButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); - paintButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - paintButtonActionPerformed(evt); - } - }); - jToolBar1.add(paintButton); - terrainModButtonGroup.add(eraseButton); eraseButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/jme3/gde/terraineditor/icon_terrain-erase-circle.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(eraseButton, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.eraseButton.text")); // NOI18N eraseButton.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.eraseButton.toolTipText")); // NOI18N + eraseButton.setEnabled(false); eraseButton.setFocusable(false); eraseButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); eraseButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); @@ -547,7 +533,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce radiusSlider.setMajorTickSpacing(10); radiusSlider.setMinorTickSpacing(5); radiusSlider.setPaintTicks(true); - radiusSlider.setSnapToTicks(true); radiusSlider.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.radiusSlider.toolTipText")); // NOI18N radiusSlider.setValue(5); radiusSlider.setOpaque(false); @@ -722,7 +707,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce .addComponent(hintPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(paintingPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(toolSettingsPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE) - .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 132, Short.MAX_VALUE))) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) ); }// //GEN-END:initComponents @@ -755,17 +740,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce } }//GEN-LAST:event_lowerTerrainButtonActionPerformed - private void paintButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_paintButtonActionPerformed - if (paintButton.isSelected()) { - PaintTerrainTool tool = new PaintTerrainTool(); - toolController.setTerrainEditButtonState(tool); - setHintText(tool); - } else { - toolController.setTerrainEditButtonState(null); - setHintText((TerrainTool) null); - } - }//GEN-LAST:event_paintButtonActionPerformed - private void addTextureButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTextureButtonActionPerformed if (editorController == null || editorController.getTerrain(null) == null) { return; @@ -807,7 +781,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce private void eraseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_eraseButtonActionPerformed if (eraseButton.isSelected()) { - EraseTerrainTool tool = new EraseTerrainTool(); + PaintTerrainTool tool = new PaintTerrainTool(); toolController.setTerrainEditButtonState(tool); setHintText(tool); } else { @@ -977,7 +951,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce private javax.swing.JToggleButton levelTerrainButton; private javax.swing.JToggleButton lowerTerrainButton; private javax.swing.JTextField octavesField; - private javax.swing.JToggleButton paintButton; private javax.swing.JPanel paintingPanel; private javax.swing.JLabel radiusLabel; private javax.swing.JSlider radiusSlider; diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java index b264e5c9c..531bd2fc6 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainToolController.java @@ -35,6 +35,7 @@ package com.jme3.gde.terraineditor; import com.jme3.asset.AssetManager; import com.jme3.gde.core.scene.SceneApplication; import com.jme3.gde.core.scene.controller.SceneToolController; +import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeNode; import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial; import com.jme3.gde.terraineditor.tools.TerrainTool; @@ -42,6 +43,7 @@ import com.jme3.input.event.KeyInputEvent; import com.jme3.math.Vector3f; import com.jme3.scene.Node; import java.util.concurrent.Callable; +import org.openide.loaders.DataObject; /** * The controller for the terrain modification tools. It will in turn interact @@ -63,6 +65,8 @@ public class TerrainToolController extends SceneToolController { private float toolWeight; private int selectedTextureIndex = -1; private boolean mesh = false; + private boolean primary = false; + private boolean alternate = false; public TerrainToolController(Node toolsNode, AssetManager manager, JmeNode rootNode) { @@ -200,7 +204,7 @@ public class TerrainToolController extends SceneToolController { */ public void doTerrainEditToolActivated() { - if (terrainTool != null) { + if (terrainTool != null && primary && !alternate) { Vector3f point = getMarkerLocation(); if (point != null) { topComponent.getExtraToolParams(); @@ -215,9 +219,11 @@ public class TerrainToolController extends SceneToolController { */ public void doTerrainEditToolAlternateActivated() { - if (terrainTool != null) { - Vector3f point = cameraController.getTerrainCollisionPoint(); + if (terrainTool != null && alternate && !primary) { + //Vector3f point = cameraController.getTerrainCollisionPoint(); + Vector3f point = getMarkerLocation(); if (point != null) { + topComponent.getExtraToolParams(); terrainTool.actionSecondary(point, selectedTextureIndex, jmeRootNode, editorController.getCurrentDataObject()); } @@ -225,6 +231,14 @@ public class TerrainToolController extends SceneToolController { } + public void setPrimary(boolean primary) { + this.primary = primary; + } + + public void setAlternate(boolean alternate) { + this.alternate = alternate; + } + void setExtraToolParams(ExtraToolParams params) { if (terrainTool != null) { terrainTool.setExtraParams(params); @@ -240,4 +254,14 @@ public class TerrainToolController extends SceneToolController { terrainTool.keyPressed(kie); } } + + /** + * The action on the tool has ended (mouse button up), record the Undo (for painting only now) + */ + void doTerrainEditToolActionEnded() { + if (terrainTool != null) { + System.out.println("undo tagged"); + terrainTool.actionEnded(jmeRootNode, editorController.getCurrentDataObject()); + } + } } diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/AbstractTerrainToolAction.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/AbstractTerrainToolAction.java index 64b891b1b..5ad1a0678 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/AbstractTerrainToolAction.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/AbstractTerrainToolAction.java @@ -43,11 +43,17 @@ import com.jme3.terrain.Terrain; */ public abstract class AbstractTerrainToolAction extends AbstractStatefulGLToolAction { + private Terrain terrain; + protected Terrain getTerrain(Spatial root) { + if (terrain != null) + return terrain; + // is this the terrain? if (root instanceof Terrain && root instanceof Node) { - return (Terrain)root; + terrain = (Terrain)root; + return terrain; } if (root instanceof Node) { diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainTool.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainTool.java index faa2b8cac..444148017 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainTool.java +++ b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainTool.java @@ -32,28 +32,82 @@ package com.jme3.gde.terraineditor.tools; import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; +import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractStatefulGLToolAction; +import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; +import com.jme3.gde.core.undoredo.SceneUndoRedoManager; import com.jme3.math.ColorRGBA; import com.jme3.math.Vector3f; import com.jme3.scene.Node; +import com.jme3.terrain.Terrain; +import java.util.ArrayList; +import java.util.List; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; import org.openide.loaders.DataObject; +import org.openide.util.Lookup; /** - * + * Paint or erase the textures on the terrain. + * * @author Brent Owens */ public class PaintTerrainTool extends TerrainTool { + private boolean painting = false; // to check when undo actions need to be set + List actions = new ArrayList(); + + @Override public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { - if (radius == 0 || weight == 0) - return; - PaintTerrainToolAction action = new PaintTerrainToolAction(point, radius, weight, textureIndex); - action.doActionPerformed(rootNode, dataObject); + setPrimary(true); + action(point, textureIndex, rootNode, dataObject); } @Override public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { - // do nothing + setPrimary(false); + action(point, textureIndex, rootNode, dataObject); + } + + private void action(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { + if (radius == 0 || weight == 0) + return; + + if (!painting) + painting = true; + + PaintTerrainToolAction action; + if (isPrimary()) + action = new PaintTerrainToolAction(point, radius, weight, textureIndex); + else + action = new PaintTerrainToolAction(point, radius, -weight, textureIndex); + action.doActionPerformed(rootNode, dataObject, false); + actions.add(action); + } + + @Override + public void actionEnded(AbstractSceneExplorerNode rootNode, DataObject dataObject) { + if (painting) { + painting = false; + + if (actions.isEmpty()) + return; + + // record undo action + List cloned = new ArrayList(); + cloned.addAll(actions); + recordUndo(cloned, rootNode, dataObject); + actions.clear(); + } + } + + /** + * Is it already painting? + * If the user releases the mouse outside the window, this can be used to check + * if they were painting, and if so, call actionEnded() + */ + public boolean isPainting() { + return painting; } @Override @@ -61,4 +115,48 @@ public class PaintTerrainTool extends TerrainTool { super.addMarkerPrimary(parent); markerPrimary.getMaterial().setColor("Color", ColorRGBA.Cyan); } + + private void recordUndo(final List actions, final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { + Lookup lookup = Lookup.getDefault() ; + SceneUndoRedoManager manager = lookup.lookup(SceneUndoRedoManager.class); + + AbstractUndoableSceneEdit undoer = new AbstractUndoableSceneEdit() { + + @Override + public void sceneUndo() throws CannotUndoException { + Terrain terrain = null; + for (int i=actions.size()-1; i>=0; i--) { + PaintTerrainToolAction a = actions.get(i); + if (terrain == null) + terrain = a.getTerrain(rootNode.getLookup().lookup(Node.class)); + a.doUndoTool(rootNode, terrain); + } + setModified(rootNode, dataObject); + } + + @Override + public void sceneRedo() throws CannotRedoException { + for (int i=0; i cachedMap = new HashMap(); // caching only + private boolean primary = true; public static enum Meshes { Box, Sphere @@ -103,6 +104,14 @@ public abstract class TerrainTool { this.manager = manager; addMarkerPrimary(parent); } + + public boolean isPrimary() { + return primary; + } + + public void setPrimary(boolean primary) { + this.primary = primary; + } /** * The primary action for the tool gets activated @@ -114,6 +123,12 @@ public abstract class TerrainTool { */ public abstract void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject); + /** + * The action has ended, record undo actions. + * Currently just implemented for Paint tool + */ + public void actionEnded(AbstractSceneExplorerNode rootNode, DataObject dataObject) {} + /** * Signals that this tool will or will not snap to fixed axis angles */