Ver código fonte

patch for the terrain editor slope tool from shirkit

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9588 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
bre..ns 13 anos atrás
pai
commit
fe875dcf35

+ 2 - 2
jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties

@@ -119,12 +119,12 @@ CreateTerrainVisualPanel2.smoothIterationsLabel.text=Rough
 CreateTerrainVisualPanel2.jLabel6.text=Smooth
 CreateTerrainVisualPanel2.jLabel7.text=Height Scale:
 CreateTerrainVisualPanel2.heightScale.text=1
-TerrainEditorTopComponent.toolHint.shirkit=Right click to set the markers position. A simple right click set the first marker, holding ctrl sets the second marker. Hold the Left button to apply the slope in the area you are hovering.
+TerrainEditorTopComponent.toolHint.slope=Right click to set the markers position. A simple right click set the first marker, holding ctrl sets the second marker. Hold the Left button to apply the slope in the area you are hovering.
 TerrainEditorTopComponent.jLabel6.text=
-TerrainEditorTopComponent.jLabel7.text=
 TerrainEditorTopComponent.levelPrecisionCheckbox.text=Precision
 TerrainEditorTopComponent.levelAbsoluteCheckbox.text=Absolute
 TerrainEditorTopComponent.levelAbsoluteHeightField.text=0
 TerrainEditorTopComponent.slopePrecisionCheckbox.text=Precision
 TerrainEditorTopComponent.slopeTerrainButton.toolTipText=Slope terrain
 TerrainEditorTopComponent.slopeTerrainButton.text=
+TerrainEditorTopComponent.slopeLockCheckbox.text=Lock

+ 6 - 3
jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form

@@ -188,12 +188,15 @@
             <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="slopePrecisionCheckboxActionPerformed"/>
           </Events>
         </Component>
-        <Component class="javax.swing.JLabel" name="jLabel7">
+        <Component class="javax.swing.JCheckBox" name="slopeLockCheckbox">
           <Properties>
             <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="com/jme3/gde/terraineditor/Bundle.properties" key="TerrainEditorTopComponent.jLabel7.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+              <ResourceString bundle="com/jme3/gde/terraineditor/Bundle.properties" key="TerrainEditorTopComponent.slopeLockCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
             </Property>
           </Properties>
+          <Events>
+            <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="slopeLockCheckboxActionPerformed"/>
+          </Events>
         </Component>
       </SubComponents>
     </Container>
@@ -548,7 +551,7 @@
           <Layout>
             <DimensionLayout dim="0">
               <Group type="103" groupAlignment="0" attributes="0">
-                  <EmptySpace min="0" pref="147" max="32767" attributes="0"/>
+                  <EmptySpace min="0" pref="148" max="32767" attributes="0"/>
               </Group>
             </DimensionLayout>
             <DimensionLayout dim="1">

+ 15 - 5
jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java

@@ -239,7 +239,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         scaleField = new javax.swing.JTextField();
         slopeBrushPanel = new javax.swing.JPanel();
         slopePrecisionCheckbox = new javax.swing.JCheckBox();
-        jLabel7 = new javax.swing.JLabel();
+        slopeLockCheckbox = new javax.swing.JCheckBox();
         jToolBar1 = new javax.swing.JToolBar();
         createTerrainButton = new javax.swing.JButton();
         jSeparator1 = new javax.swing.JToolBar.Separator();
@@ -381,8 +381,13 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         });
         slopeBrushPanel.add(slopePrecisionCheckbox);
 
-        org.openide.awt.Mnemonics.setLocalizedText(jLabel7, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.jLabel7.text")); // NOI18N
-        slopeBrushPanel.add(jLabel7);
+        org.openide.awt.Mnemonics.setLocalizedText(slopeLockCheckbox, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.slopeLockCheckbox.text")); // NOI18N
+        slopeLockCheckbox.addActionListener(new java.awt.event.ActionListener() {
+            public void actionPerformed(java.awt.event.ActionEvent evt) {
+                slopeLockCheckboxActionPerformed(evt);
+            }
+        });
+        slopeBrushPanel.add(slopeLockCheckbox);
 
         setBackground(java.awt.Color.gray);
 
@@ -572,7 +577,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         jPanel3.setLayout(jPanel3Layout);
         jPanel3Layout.setHorizontalGroup(
             jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGap(0, 147, Short.MAX_VALUE)
+            .addGap(0, 148, Short.MAX_VALUE)
         );
         jPanel3Layout.setVerticalGroup(
             jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@@ -953,6 +958,10 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         updateSlopeToolParams();
     }//GEN-LAST:event_slopePrecisionCheckboxActionPerformed
 
+    private void slopeLockCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_slopeLockCheckboxActionPerformed
+        updateSlopeToolParams();
+    }//GEN-LAST:event_slopeLockCheckboxActionPerformed
+
     // Variables declaration - do not modify//GEN-BEGIN:variables
     private javax.swing.JButton addTextureButton;
     private javax.swing.JButton createTerrainButton;
@@ -966,7 +975,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
     private javax.swing.JLabel jLabel3;
     private javax.swing.JLabel jLabel4;
     private javax.swing.JLabel jLabel6;
-    private javax.swing.JLabel jLabel7;
     private javax.swing.JPanel jPanel2;
     private javax.swing.JPanel jPanel3;
     private javax.swing.JScrollPane jScrollPane1;
@@ -996,6 +1004,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
     private javax.swing.JLabel scaleLabel;
     private javax.swing.JTextField shininessField;
     private javax.swing.JPanel slopeBrushPanel;
+    private javax.swing.JCheckBox slopeLockCheckbox;
     private javax.swing.JCheckBox slopePrecisionCheckbox;
     private javax.swing.JToggleButton slopeTerrainButton;
     private javax.swing.JToggleButton smoothTerrainButton;
@@ -1048,6 +1057,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
      private void updateSlopeToolParams() {
          SlopeExtraToolParams params = new SlopeExtraToolParams();
          params.precision = slopePrecisionCheckbox.isSelected();
+         params.lock = slopeLockCheckbox.isSelected();
          toolController.setExtraToolParams(params);
     }
     

+ 1 - 0
jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeExtraToolParams.java

@@ -40,5 +40,6 @@ import com.jme3.gde.terraineditor.ExtraToolParams;
 public class SlopeExtraToolParams implements ExtraToolParams {
     
     public boolean precision;
+    public boolean lock;
     
 }

+ 77 - 18
jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainTool.java

@@ -32,32 +32,39 @@
 package com.jme3.gde.terraineditor.tools;
 
 import com.jme3.asset.AssetManager;
+import com.jme3.font.BitmapText;
 import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode;
 import com.jme3.gde.terraineditor.ExtraToolParams;
 import com.jme3.input.KeyInput;
 import com.jme3.input.event.KeyInputEvent;
 import com.jme3.material.Material;
 import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
 import com.jme3.math.Vector3f;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.Node;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.control.BillboardControl;
+import com.jme3.scene.shape.Line;
 import com.jme3.scene.shape.Sphere;
 import org.openide.loaders.DataObject;
 
 /**
- * Generates a slope between two control points.
+ *
  * @author Shirkit
  */
 public class SlopeTerrainTool extends TerrainTool {
 
     private Vector3f point1, point2;
-    private Geometry markerThird;
+    private Geometry markerThird, line;
     private Node parent;
     private SlopeExtraToolParams toolParams;
+    private BitmapText angleText;
+    private boolean leftCtrl = false;
 
     public SlopeTerrainTool() {
-        toolHintTextKey = "TerrainEditorTopComponent.toolHint.shirkit";
+        toolHintTextKey = "TerrainEditorTopComponent.toolHint.slope";
     }
 
     @Override
@@ -65,17 +72,20 @@ public class SlopeTerrainTool extends TerrainTool {
         super.activate(manager, parent);
         addMarkerSecondary(parent);
         addMarkerThird(parent);
+        addLineAndText();
         this.parent = parent;
     }
 
     @Override
     public void hideMarkers() {
         super.hideMarkers();
-        if (markerThird != null) {
+        if (markerThird != null)
             markerThird.removeFromParent();
-        }
+
+        line.removeFromParent();
+        angleText.removeFromParent();
     }
-    
+
     private void addMarkerThird(Node parent) {
         if (markerThird == null) {
             markerThird = new Geometry("edit marker secondary");
@@ -90,20 +100,29 @@ public class SlopeTerrainTool extends TerrainTool {
         parent.attachChild(markerThird);
     }
 
+    private void addLineAndText() {
+        line = new Geometry("line", new Line(Vector3f.ZERO, Vector3f.ZERO));
+        Material m = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md");
+        m.setColor("Color", ColorRGBA.White);
+        line.setMaterial(m);
+
+        angleText = new BitmapText(manager.loadFont("Interface/Fonts/Default.fnt"));
+        BillboardControl control = new BillboardControl();
+        angleText.addControl(control);
+        angleText.setSize(0.5f);
+        angleText.setCullHint(Spatial.CullHint.Never);
+    }
+
     @Override
     public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) {
-        if (point1 != null && point2 != null) {
-            SlopeTerrainToolAction action = new SlopeTerrainToolAction(point, point1, point2, radius, weight, toolParams.precision);
+        if (point1 != null && point2 != null && point1.distance(point2) > 0.01f) { // Preventing unexpected behavior, like destroying the terrain
+            SlopeTerrainToolAction action = new SlopeTerrainToolAction(point, point1, point2, radius, weight, toolParams.precision, toolParams.lock);
             action.actionPerformed(rootNode, dataObject);
         }
     }
-    private boolean leftCtrl = false;
 
     @Override
     public void keyPressed(KeyInputEvent kie) {
-        if (kie.getKeyCode() == KeyInput.KEY_LCONTROL) {
-            leftCtrl = kie.isPressed();
-        }
         switch (kie.getKeyCode()) {
             case KeyInput.KEY_LCONTROL:
                 leftCtrl = kie.isPressed();
@@ -113,25 +132,67 @@ public class SlopeTerrainTool extends TerrainTool {
                 point2 = null;
                 markerSecondary.removeFromParent();
                 markerThird.removeFromParent();
+                line.removeFromParent();
+                angleText.removeFromParent();
+                break;
+            case KeyInput.KEY_UP:
+                markerThird.move(0f, 0.1f, 0f);
+                point2.set(markerThird.getLocalTranslation());
+                updateAngle();
+                break;
+            case KeyInput.KEY_DOWN:
+                markerThird.move(0f, -0.1f, 0f);
+                point2.set(markerThird.getLocalTranslation());
+                updateAngle();
                 break;
         }
     }
 
+    private void updateAngle() {
+        Vector3f temp, higher, lower;
+        if (point2.y > point1.y) {
+            temp = point2;
+            higher = point2;
+            lower = point1;
+        } else {
+            temp = point1;
+            higher = point1;
+            lower = point2;
+        }
+        temp = temp.clone().setY(lower.y);
+
+        float angle = ((FastMath.asin(temp.distance(higher) / lower.distance(higher))) * FastMath.RAD_TO_DEG);
+
+        angleText.setText(angle + " degrees");
+        angleText.setLocalTranslation(new Vector3f().interpolate(point1, point2, 0.5f));
+
+        if (line.getParent() == null) {
+            parent.attachChild(line);
+            parent.attachChild(angleText);
+        }
+        ((Line) line.getMesh()).updatePoints(point1, point2);
+    }
+
     @Override
     public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) {
         if (leftCtrl) {
             point2 = point;
-            if (markerThird.getParent() == null) {
+            if (markerThird.getParent() == null)
                 parent.attachChild(markerThird);
-            }
+
             markerThird.setLocalTranslation(point);
         } else {
             point1 = point;
-            if (markerSecondary.getParent() == null) {
+            if (markerSecondary.getParent() == null)
                 parent.attachChild(markerSecondary);
-            }
+
             markerSecondary.setLocalTranslation(point);
         }
+        if (point1 != null && point2 != null)
+            updateAngle();
+        else
+            if (line != null)
+                line.removeFromParent();
     }
 
     @Override
@@ -139,6 +200,4 @@ public class SlopeTerrainTool extends TerrainTool {
         if (params instanceof SlopeExtraToolParams)
             this.toolParams = (SlopeExtraToolParams) params;
     }
-    
-    
 }

+ 54 - 45
jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainToolAction.java

@@ -32,7 +32,9 @@
 package com.jme3.gde.terraineditor.tools;
 
 import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode;
-import com.jme3.math.*;
+import com.jme3.math.Plane;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
 import com.jme3.scene.Node;
 import com.jme3.terrain.Terrain;
 import java.util.ArrayList;
@@ -52,41 +54,43 @@ public class SlopeTerrainToolAction extends AbstractTerrainToolAction {
     private List<Vector2f> undoLocs;
     private List<Float> undoHeights;
     private final boolean precise;
+    private final boolean lock;
 
-    public SlopeTerrainToolAction(Vector3f current, Vector3f point1, Vector3f point2, float radius, float weight, boolean precise) {
+    public SlopeTerrainToolAction(Vector3f current, Vector3f point1, Vector3f point2, float radius, float weight, boolean precise, boolean lock) {
         this.current = current.clone();
         this.point1 = point1;
         this.point2 = point2;
         this.radius = radius;
         this.weight = weight;
         this.precise = precise;
+        this.lock = lock;
         name = "Slope terrain";
     }
 
     @Override
     protected Object doApplyTool(AbstractSceneExplorerNode rootNode) {
         Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class));
-        if (terrain == null) {
+        if (terrain == null)
             return null;
-        }
 
-        modifyHeight(terrain, point1, point2, current, radius, weight, precise);
+        modifyHeight(terrain, point1, point2, current, radius, weight, precise, lock);
 
         return terrain;
     }
 
     @Override
     protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) {
-        if (undoObject == null) {
+        if (undoObject == null)
             return;
-        }
-        if (undoLocs == null || undoHeights == null) {
+
+        if (undoLocs == null || undoHeights == null)
             return;
-        }
+
         resetHeight((Terrain) undoObject, undoLocs, undoHeights, precise);
     }
 
-    private void modifyHeight(Terrain terrain, Vector3f point1, Vector3f point2, Vector3f current, float radius, float weight, boolean precise) {
+    private void modifyHeight(Terrain terrain, Vector3f point1, Vector3f point2, Vector3f current, float radius, float weight, boolean precise, boolean lock) {
+        // Make sure we go for the right direction, or we could be creating a slope to the oposite side
         if (point1.y > point2.y) {
             Vector3f temp = point1;
             point1 = point2;
@@ -104,55 +108,60 @@ public class SlopeTerrainToolAction extends AbstractTerrainToolAction {
         List<Vector2f> locs = new ArrayList<Vector2f>();
         List<Float> heights = new ArrayList<Float>();
         undoHeights = new ArrayList<Float>();
-        
-        for (int z = -radiusStepsZ; z < radiusStepsZ; z++) {
+
+        Plane p1 = new Plane();
+        Plane p2 = new Plane();
+        p1.setOriginNormal(point1, point1.subtract(point2).normalize());
+        p2.setOriginNormal(point2, point1.subtract(point2).normalize());
+
+        for (int z = -radiusStepsZ; z < radiusStepsZ; z++)
             for (int x = -radiusStepsZ; x < radiusStepsX; x++) {
 
                 float locX = current.x + (x * xStepAmount);
                 float locZ = current.z + (z * zStepAmount);
-                
-                // see if it is in the radius of the tool
-                if (ToolUtils.isInRadius(locX - current.x, locZ - current.z, radius)) {
-                    
+
+                if (ToolUtils.isInRadius(locX - current.x, locZ - current.z, radius)) { // see if it is in the radius of the tool
                     Vector2f terrainLoc = new Vector2f(locX, locZ);
+
                     // adjust height based on radius of the tool
                     float terrainHeightAtLoc = terrain.getHeightmapHeight(terrainLoc) * ((Node) terrain).getWorldScale().y;
-                    float radiusWeight = ToolUtils.calculateRadiusPercent(radius, locX - current.x, locZ - current.z);
-
                     float point1Distance = point1.distance(new Vector3f(locX, terrainHeightAtLoc, locZ));
                     float desiredHeight = point1.y + (point2.y - point1.y) * (point1Distance / totaldistance);
-                    
-                    if (!precise) {
-                        float epsilon = 0.1f * weight; // rounding error for snapping
-
-                        float adj = 0;
-                        if (terrainHeightAtLoc < desiredHeight) {
-                            adj = 1;
-                        } else if (terrainHeightAtLoc > desiredHeight) {
-                            adj = -1;
+                    if (!lock || (lock && p1.whichSide(new Vector3f(locX, 0f, locZ)) != p2.whichSide(new Vector3f(locX, 0f, locZ))))
+                        if (!precise) {
+                            float epsilon = 0.1f * weight; // rounding error for snapping
+
+                            float adj = 0;
+                            if (terrainHeightAtLoc < desiredHeight)
+                                adj = 1;
+                            else
+                                if (terrainHeightAtLoc > desiredHeight)
+                                    adj = -1;
+
+                            float radiusWeight = ToolUtils.calculateRadiusPercent(radius, locX - current.x, locZ - current.z);
+
+                            adj *= radiusWeight * weight;
+
+                            // test if adjusting too far and then cap it
+                            if (adj > 0 && ToolUtils.floatGreaterThan((terrainHeightAtLoc + adj), desiredHeight, epsilon))
+                                adj = desiredHeight - terrainHeightAtLoc;
+                            else
+                                if (adj < 0 && ToolUtils.floatLessThan((terrainHeightAtLoc + adj), desiredHeight, epsilon))
+                                    adj = terrainHeightAtLoc - desiredHeight;
+
+                            if (!ToolUtils.floatEquals(adj, 0, 0.001f)) {
+                                locs.add(terrainLoc);
+                                heights.add(adj);
+                            }
+                        } else {
+                            locs.add(terrainLoc);
+                            heights.add(desiredHeight);
+                            undoHeights.add(terrainHeightAtLoc);
                         }
 
-                        adj *= radiusWeight * weight;
 
-                        // test if adjusting too far and then cap it
-                        if (adj > 0 && ToolUtils.floatGreaterThan((terrainHeightAtLoc + adj), desiredHeight, epsilon)) {
-                            adj = desiredHeight - terrainHeightAtLoc;
-                        } else if (adj < 0 && ToolUtils.floatLessThan((terrainHeightAtLoc + adj), desiredHeight, epsilon)) {
-                            adj = terrainHeightAtLoc - desiredHeight;
-                        }
-                        
-                        if (!ToolUtils.floatEquals(adj, 0, 0.001f)) {
-                            locs.add(terrainLoc);
-                            heights.add(adj);
-                        }
-                    } else {
-                        locs.add(terrainLoc);
-                        heights.add(desiredHeight);
-                        undoHeights.add(terrainHeightAtLoc);
-                    }
                 }
             }
-        }
         undoLocs = locs;
         if (!precise)
             undoHeights = heights;