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 6b0ae7e7c..bc8445ed8 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 @@ -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 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 7459ee179..2fd8b2097 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 @@ -188,12 +188,15 @@ - + - + + + + @@ -548,7 +551,7 @@ - + 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 2cc370eb1..d466dd42b 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 @@ -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); } diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeExtraToolParams.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeExtraToolParams.java index 8309335e1..0de3060d6 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeExtraToolParams.java +++ b/sdk/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; } diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainTool.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainTool.java index cc85371a2..6f85d486a 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainTool.java +++ b/sdk/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; } - - } diff --git a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainToolAction.java b/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainToolAction.java index d55ab6e80..d3bcf079d 100644 --- a/sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainToolAction.java +++ b/sdk/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 undoLocs; private List 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 locs = new ArrayList(); List heights = new ArrayList(); undoHeights = new ArrayList(); - - 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;