patch for the terrain editor slope tool from shirkit

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9588 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
bre..ns 13 years ago
parent e9af2e4dc4
commit 8fa651fe43
  1. 4
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties
  2. 9
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form
  3. 20
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java
  4. 1
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeExtraToolParams.java
  5. 95
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainTool.java
  6. 99
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/SlopeTerrainToolAction.java

@ -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

@ -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">

@ -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);
}

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

@ -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;
}
}

@ -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;

Loading…
Cancel
Save