* added terrain tool undo/redo support git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7718 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
5024fa6c32
commit
e08dc6f6cf
@ -0,0 +1,105 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.core.sceneexplorer.nodes.actions; |
||||||
|
|
||||||
|
import com.jme3.gde.core.scene.SceneApplication; |
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; |
||||||
|
import com.jme3.gde.core.undoredo.SceneUndoRedoManager; |
||||||
|
import java.util.concurrent.Callable; |
||||||
|
import javax.swing.undo.CannotRedoException; |
||||||
|
import javax.swing.undo.CannotUndoException; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
import org.openide.util.Lookup; |
||||||
|
|
||||||
|
/** |
||||||
|
* Similar as AbstractToolAction but this one is executed from the GL thread. |
||||||
|
* This is also allowed to be stateful. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public abstract class AbstractStatefulGLToolAction { |
||||||
|
|
||||||
|
protected String name = "*"; |
||||||
|
|
||||||
|
public void actionPerformed(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { |
||||||
|
SceneApplication.getApplication().enqueue(new Callable<Void>() { |
||||||
|
|
||||||
|
public Void call() throws Exception { |
||||||
|
doActionPerformed(rootNode, dataObject); |
||||||
|
return null; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public void doActionPerformed(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { |
||||||
|
|
||||||
|
final Object object = doApplyTool(rootNode); |
||||||
|
if (object!=null) { |
||||||
|
Lookup lookup = Lookup.getDefault() ; |
||||||
|
SceneUndoRedoManager manager = lookup.lookup(SceneUndoRedoManager.class); |
||||||
|
|
||||||
|
AbstractUndoableSceneEdit undoer = new AbstractUndoableSceneEdit() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void sceneUndo() throws CannotUndoException { |
||||||
|
doUndoTool(rootNode,object); |
||||||
|
setModified(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void sceneRedo() throws CannotRedoException { |
||||||
|
doApplyTool(rootNode); |
||||||
|
setModified(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
manager.addEdit(this, undoer); |
||||||
|
setModified(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
protected void setModified(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { |
||||||
|
java.awt.EventQueue.invokeLater(new Runnable() { |
||||||
|
|
||||||
|
public void run() { |
||||||
|
dataObject.setModified(true); |
||||||
|
rootNode.refresh(true); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract Object doApplyTool(AbstractSceneExplorerNode rootNode); |
||||||
|
|
||||||
|
protected abstract void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject); |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractStatefulGLToolAction; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
import com.jme3.terrain.Terrain; |
||||||
|
|
||||||
|
/** |
||||||
|
* Helps find the terrain in the scene |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public abstract class AbstractTerrainToolAction extends AbstractStatefulGLToolAction { |
||||||
|
|
||||||
|
protected Terrain getTerrain(Spatial root) { |
||||||
|
|
||||||
|
// is this the terrain?
|
||||||
|
if (root instanceof Terrain && root instanceof Node) { |
||||||
|
return (Terrain)root; |
||||||
|
} |
||||||
|
|
||||||
|
if (root instanceof Node) { |
||||||
|
Node n = (Node) root; |
||||||
|
for (Spatial c : n.getChildren()) { |
||||||
|
if (c instanceof Node){ |
||||||
|
Terrain res = getTerrain(c); |
||||||
|
if (res != null) |
||||||
|
return res; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Erase the texture on the terrain |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class EraseTerrainTool extends TerrainTool { |
||||||
|
|
||||||
|
@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); // negate the weight
|
||||||
|
action.doActionPerformed(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
super.addMarkerPrimary(parent); |
||||||
|
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Cyan); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Level the terrain. Uses a desired height point set by the secondary |
||||||
|
* action (right mouse button) and raises/lowers the terrain to that |
||||||
|
* desired height. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class LevelTerrainTool extends TerrainTool { |
||||||
|
|
||||||
|
private Vector3f desiredHeight; |
||||||
|
|
||||||
|
|
||||||
|
public LevelTerrainTool() { |
||||||
|
toolHintTextKey = "TerrainEditorTopComponent.toolHint.level"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void activate(AssetManager manager, Node parent) { |
||||||
|
super.activate(manager, parent); |
||||||
|
addMarkerSecondary(parent); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
if (radius == 0 || weight == 0) |
||||||
|
return; |
||||||
|
if (desiredHeight == null) |
||||||
|
desiredHeight = point.clone(); |
||||||
|
LevelTerrainToolAction action = new LevelTerrainToolAction(point, radius, weight, desiredHeight); |
||||||
|
action.doActionPerformed(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
desiredHeight = point; |
||||||
|
markerSecondary.setLocalTranslation(desiredHeight); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
super.addMarkerPrimary(parent); |
||||||
|
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Red); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,159 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.Vector2f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.terrain.Terrain; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Level the terrain to a desired height, executed from the OpenGL thread. |
||||||
|
* It will pull down or raise terrain towards the desired height, still |
||||||
|
* using the radius of the tool and the weight. There are some slight rounding |
||||||
|
* errors that are corrected with float epsilon testing. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class LevelTerrainToolAction extends AbstractTerrainToolAction { |
||||||
|
|
||||||
|
private Vector3f worldLoc; |
||||||
|
private float radius; |
||||||
|
private float height; |
||||||
|
private Vector3f levelTerrainLocation; |
||||||
|
|
||||||
|
List<Vector2f> undoLocs; |
||||||
|
List<Float> undoHeights; |
||||||
|
|
||||||
|
public LevelTerrainToolAction(Vector3f markerLocation, float radius, float height, Vector3f levelTerrainLocation) { |
||||||
|
this.worldLoc = markerLocation.clone(); |
||||||
|
this.radius = radius; |
||||||
|
this.height = height; |
||||||
|
this.levelTerrainLocation = levelTerrainLocation; |
||||||
|
name = "Level terrain"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||||
|
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||||
|
if (terrain == null) |
||||||
|
return null; |
||||||
|
modifyHeight(terrain, radius, height); |
||||||
|
return terrain; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||||
|
if (undoObject == null) |
||||||
|
return; |
||||||
|
if (undoLocs == null || undoHeights == null) |
||||||
|
return; |
||||||
|
resetHeight((Terrain)undoObject, undoLocs, undoHeights); |
||||||
|
} |
||||||
|
|
||||||
|
private void modifyHeight(Terrain terrain, float radius, float height) { |
||||||
|
if (levelTerrainLocation == null) |
||||||
|
return; |
||||||
|
|
||||||
|
float desiredHeight = levelTerrainLocation.y; |
||||||
|
|
||||||
|
int radiusStepsX = (int)(radius / ((Node)terrain).getLocalScale().x); |
||||||
|
int radiusStepsZ = (int)(radius / ((Node)terrain).getLocalScale().z); |
||||||
|
|
||||||
|
float xStepAmount = ((Node)terrain).getLocalScale().x; |
||||||
|
float zStepAmount = ((Node)terrain).getLocalScale().z; |
||||||
|
|
||||||
|
List<Vector2f> locs = new ArrayList<Vector2f>(); |
||||||
|
List<Float> heights = new ArrayList<Float>(); |
||||||
|
|
||||||
|
for (int z=-radiusStepsZ; z<radiusStepsZ; z++) { |
||||||
|
for (int x=-radiusStepsZ; x<radiusStepsX; x++) { |
||||||
|
|
||||||
|
float locX = worldLoc.x + (x*xStepAmount); |
||||||
|
float locZ = worldLoc.z + (z*zStepAmount); |
||||||
|
|
||||||
|
// see if it is in the radius of the tool
|
||||||
|
if (ToolUtils.isInRadius(locX-worldLoc.x,locZ-worldLoc.z,radius)) { |
||||||
|
|
||||||
|
Vector2f terrainLoc = new Vector2f(locX, locZ); |
||||||
|
// adjust height based on radius of the tool
|
||||||
|
float terrainHeightAtLoc = terrain.getHeightmapHeight(terrainLoc)*terrain.getSpatial().getWorldScale().y; |
||||||
|
float radiusWeight = ToolUtils.calculateRadiusPercent(radius, locX-worldLoc.x, locZ-worldLoc.z); |
||||||
|
|
||||||
|
float epsilon = 0.1f*height; // rounding error for snapping
|
||||||
|
|
||||||
|
float adj = 0; |
||||||
|
if (terrainHeightAtLoc < desiredHeight) |
||||||
|
adj = 1; |
||||||
|
else if (terrainHeightAtLoc > desiredHeight) |
||||||
|
adj = -1; |
||||||
|
|
||||||
|
adj *= radiusWeight * height; |
||||||
|
|
||||||
|
// 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); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
undoLocs = locs; |
||||||
|
undoHeights = heights; |
||||||
|
|
||||||
|
// do the actual height adjustment
|
||||||
|
terrain.adjustHeight(locs, heights); |
||||||
|
|
||||||
|
((Node)terrain).updateModelBound(); // or else we won't collide with it where we just edited
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void resetHeight(Terrain terrain, List<Vector2f> undoLocs, List<Float> undoHeights) { |
||||||
|
List<Float> neg = new ArrayList<Float>(); |
||||||
|
for (Float f : undoHeights) |
||||||
|
neg.add( f * -1f ); |
||||||
|
|
||||||
|
terrain.adjustHeight(undoLocs, neg); |
||||||
|
((Node)terrain).updateModelBound(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Lowers the terrain |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class LowerTerrainTool extends TerrainTool { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
if (radius == 0 || weight == 0) |
||||||
|
return; |
||||||
|
RaiseTerrainToolAction action = new RaiseTerrainToolAction(point, radius, -weight); // negative weight
|
||||||
|
action.doActionPerformed(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
// no secondary option
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
super.addMarkerPrimary(parent); |
||||||
|
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Green); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class PaintTerrainTool extends TerrainTool { |
||||||
|
|
||||||
|
@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); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
super.addMarkerPrimary(parent); |
||||||
|
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Cyan); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,260 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.material.MatParam; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector2f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.terrain.Terrain; |
||||||
|
import com.jme3.terrain.geomipmap.TerrainQuad; |
||||||
|
import com.jme3.texture.Image; |
||||||
|
import com.jme3.texture.Texture; |
||||||
|
import java.nio.ByteBuffer; |
||||||
|
|
||||||
|
/** |
||||||
|
* Paint the texture at the specified location. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class PaintTerrainToolAction extends AbstractTerrainToolAction { |
||||||
|
|
||||||
|
private Vector3f worldLoc; |
||||||
|
private float radius; |
||||||
|
private float weight; |
||||||
|
private int selectedTextureIndex; |
||||||
|
|
||||||
|
public PaintTerrainToolAction(Vector3f markerLocation, float radius, float weight, int selectedTextureIndex) { |
||||||
|
this.worldLoc = markerLocation.clone(); |
||||||
|
this.radius = radius; |
||||||
|
this.weight = weight; |
||||||
|
this.selectedTextureIndex = selectedTextureIndex; |
||||||
|
name = "Paint terrain"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||||
|
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||||
|
if (terrain == null) |
||||||
|
return null; |
||||||
|
paintTexture(terrain, worldLoc, radius, weight, selectedTextureIndex); |
||||||
|
return terrain; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||||
|
if (undoObject == null) |
||||||
|
return; |
||||||
|
paintTexture((Terrain)undoObject, worldLoc, radius, -weight, selectedTextureIndex); |
||||||
|
} |
||||||
|
|
||||||
|
public void paintTexture(Terrain terrain, Vector3f markerLocation, float toolRadius, float toolWeight, int selectedTextureIndex) { |
||||||
|
if (selectedTextureIndex < 0 || markerLocation == null) |
||||||
|
return; |
||||||
|
|
||||||
|
int alphaIdx = selectedTextureIndex/4; // 4 = rgba = 4 textures
|
||||||
|
Texture tex = getAlphaTexture(terrain, alphaIdx); |
||||||
|
Image image = tex.getImage(); |
||||||
|
|
||||||
|
Vector2f UV = terrain.getPointPercentagePosition(markerLocation.x, markerLocation.z); |
||||||
|
|
||||||
|
// get the radius of the brush in pixel-percent
|
||||||
|
float brushSize = toolRadius/((TerrainQuad)terrain).getTotalSize(); |
||||||
|
int texIndex = selectedTextureIndex - ((selectedTextureIndex/4)*4); // selectedTextureIndex/4 is an int floor, do not simplify the equation
|
||||||
|
boolean erase = toolWeight<0; |
||||||
|
if (erase) |
||||||
|
toolWeight *= -1; |
||||||
|
|
||||||
|
doPaintAction(texIndex, image, UV, true, brushSize, erase, toolWeight); |
||||||
|
|
||||||
|
tex.getImage().setUpdateNeeded(); |
||||||
|
} |
||||||
|
|
||||||
|
private Texture getAlphaTexture(Terrain terrain, int alphaLayer) { |
||||||
|
if (terrain == null) |
||||||
|
return null; |
||||||
|
MatParam matParam = null; |
||||||
|
if (alphaLayer == 0) |
||||||
|
matParam = terrain.getMaterial().getParam("AlphaMap"); |
||||||
|
else if(alphaLayer == 1) |
||||||
|
matParam = terrain.getMaterial().getParam("AlphaMap_1"); |
||||||
|
else if(alphaLayer == 2) |
||||||
|
matParam = terrain.getMaterial().getParam("AlphaMap_2"); |
||||||
|
|
||||||
|
if (matParam == null || matParam.getValue() == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Texture tex = (Texture) matParam.getValue(); |
||||||
|
return tex; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Goes through each pixel in the image. At each pixel it looks to see if the UV mouse coordinate is within the |
||||||
|
* of the brush. If it is in the brush radius, it gets the existing color from that pixel so it can add/subtract to/from it. |
||||||
|
* Essentially it does a radius check and adds in a fade value. It does this to the color value returned by the |
||||||
|
* first pixel color query. |
||||||
|
* Next it sets the color of that pixel. If it was within the radius, the color will change. If it was outside |
||||||
|
* the radius, then nothing will change, the color will be the same; but it will set it nonetheless. Not efficient. |
||||||
|
* |
||||||
|
* If the mouse is being dragged with the button down, then the dragged value should be set to true. This will reduce |
||||||
|
* the intensity of the brush to 10% of what it should be per spray. Otherwise it goes to 100% opacity within a few pixels. |
||||||
|
* This makes it work a little more realistically. |
||||||
|
* |
||||||
|
* @param image to manipulate |
||||||
|
* @param uv the world x,z coordinate |
||||||
|
* @param dragged true if the mouse button is down and it is being dragged, use to reduce brush intensity |
||||||
|
* @param radius in percentage so it can be translated to the image dimensions |
||||||
|
* @param erase true if the tool should remove the paint instead of add it |
||||||
|
* @param fadeFalloff the percentage of the radius when the paint begins to start fading |
||||||
|
*/ |
||||||
|
protected void doPaintAction(int texIndex, Image image, Vector2f uv, boolean dragged, float radius, boolean erase, float fadeFalloff){ |
||||||
|
Vector2f texuv = new Vector2f(); |
||||||
|
ColorRGBA color = ColorRGBA.Black; |
||||||
|
|
||||||
|
float width = image.getWidth(); |
||||||
|
float height = image.getHeight(); |
||||||
|
|
||||||
|
int minx = (int) (uv.x*width - radius*width); // convert percents to pixels to limit how much we iterate
|
||||||
|
int maxx = (int) (uv.x*width + radius*width); |
||||||
|
int miny = (int) (uv.y*height - radius*height); |
||||||
|
int maxy = (int) (uv.y*height + radius*height); |
||||||
|
|
||||||
|
float radiusSquared = radius*radius; |
||||||
|
float radiusFalloff = radius*fadeFalloff; |
||||||
|
// go through each pixel, in the radius of the tool, in the image
|
||||||
|
for (int y = miny; y < maxy; y++){ |
||||||
|
for (int x = minx; x < maxx; x++){ |
||||||
|
|
||||||
|
texuv.set((float)x / width, (float)y / height);// gets the position in percentage so it can compare with the mouse UV coordinate
|
||||||
|
|
||||||
|
float dist = texuv.distanceSquared(uv); |
||||||
|
if (dist < radiusSquared ) { // if the pixel is within the distance of the radius, set a color (distance times intensity)
|
||||||
|
manipulatePixel(image, x, y, color, false); // gets the color at that location (false means don't write to the buffer)
|
||||||
|
|
||||||
|
// calculate the fade falloff intensity
|
||||||
|
float intensity = 0.1f; |
||||||
|
if (dist > radiusFalloff) { |
||||||
|
float dr = radius - radiusFalloff; // falloff to radius length
|
||||||
|
float d2 = dist - radiusFalloff; // dist minus falloff
|
||||||
|
d2 = d2/dr; // dist percentage of falloff length
|
||||||
|
intensity = 1-d2; // fade out more the farther away it is
|
||||||
|
} |
||||||
|
|
||||||
|
//if (dragged)
|
||||||
|
// intensity = intensity*0.1f; // magical divide it by 10 to reduce its intensity when mouse is dragged
|
||||||
|
|
||||||
|
if (erase) { |
||||||
|
switch (texIndex) { |
||||||
|
case 0: |
||||||
|
color.r -= intensity; break; |
||||||
|
case 1: |
||||||
|
color.g -= intensity; break; |
||||||
|
case 2: |
||||||
|
color.b -= intensity; break; |
||||||
|
case 3: |
||||||
|
color.a -= intensity; break; |
||||||
|
} |
||||||
|
} else { |
||||||
|
switch (texIndex) { |
||||||
|
case 0: |
||||||
|
color.r += intensity; break; |
||||||
|
case 1: |
||||||
|
color.g += intensity; break; |
||||||
|
case 2: |
||||||
|
color.b += intensity; break; |
||||||
|
case 3: |
||||||
|
color.a += intensity; break; |
||||||
|
} |
||||||
|
} |
||||||
|
color.clamp(); |
||||||
|
|
||||||
|
manipulatePixel(image, x, y, color, true); // set the new color
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
image.getData(0).rewind(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* We are only using RGBA8 images for alpha textures right now. |
||||||
|
* @param image to get/set the color on |
||||||
|
* @param x location |
||||||
|
* @param y location |
||||||
|
* @param color color to get/set |
||||||
|
* @param write to write the color or not |
||||||
|
*/ |
||||||
|
protected void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){ |
||||||
|
ByteBuffer buf = image.getData(0); |
||||||
|
int width = image.getWidth(); |
||||||
|
|
||||||
|
int position = (y * width + x) * 4; |
||||||
|
|
||||||
|
if ( position> buf.capacity()-1 || position<0 ) |
||||||
|
return; |
||||||
|
|
||||||
|
if (write) { |
||||||
|
switch (image.getFormat()){ |
||||||
|
case RGBA8: |
||||||
|
buf.position( position ); |
||||||
|
buf.put(float2byte(color.r)) |
||||||
|
.put(float2byte(color.g)) |
||||||
|
.put(float2byte(color.b)) |
||||||
|
.put(float2byte(color.a)); |
||||||
|
return; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException("Image format: "+image.getFormat()); |
||||||
|
} |
||||||
|
} else { |
||||||
|
switch (image.getFormat()){ |
||||||
|
case RGBA8: |
||||||
|
buf.position( position ); |
||||||
|
color.set(byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get())); |
||||||
|
return; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException("Image format: "+image.getFormat()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private float byte2float(byte b){ |
||||||
|
return ((float)(b & 0xFF)) / 255f; |
||||||
|
} |
||||||
|
|
||||||
|
private byte float2byte(float f){ |
||||||
|
return (byte) (f * 255f); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,69 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Raise the terrain |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class RaiseTerrainTool extends TerrainTool { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
if (radius == 0 || weight == 0) |
||||||
|
return; |
||||||
|
RaiseTerrainToolAction action = new RaiseTerrainToolAction(point, radius, weight); |
||||||
|
action.doActionPerformed(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
// no secondary option
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
super.addMarkerPrimary(parent); |
||||||
|
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Green); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.Vector2f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.terrain.Terrain; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Raise/lower the terrain, executed from the OpenGL thread. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class RaiseTerrainToolAction extends AbstractTerrainToolAction { |
||||||
|
|
||||||
|
private Vector3f worldLoc; |
||||||
|
private float radius; |
||||||
|
private float height; |
||||||
|
|
||||||
|
public RaiseTerrainToolAction(Vector3f markerLocation, float radius, float height) { |
||||||
|
this.worldLoc = markerLocation.clone(); |
||||||
|
this.radius = radius; |
||||||
|
this.height = height; |
||||||
|
name = "Raise terrain"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||||
|
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||||
|
if (terrain == null) |
||||||
|
return null; |
||||||
|
modifyHeight(terrain, radius, height); |
||||||
|
return terrain; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||||
|
if (undoObject == null) |
||||||
|
return; |
||||||
|
modifyHeight((Terrain)undoObject, radius, -height); |
||||||
|
} |
||||||
|
|
||||||
|
private void modifyHeight(Terrain terrain, float radius, float heightDir) { |
||||||
|
|
||||||
|
int radiusStepsX = (int) (radius / ((Node)terrain).getLocalScale().x); |
||||||
|
int radiusStepsZ = (int) (radius / ((Node)terrain).getLocalScale().z); |
||||||
|
|
||||||
|
float xStepAmount = ((Node)terrain).getLocalScale().x; |
||||||
|
float zStepAmount = ((Node)terrain).getLocalScale().z; |
||||||
|
|
||||||
|
List<Vector2f> locs = new ArrayList<Vector2f>(); |
||||||
|
List<Float> heights = new ArrayList<Float>(); |
||||||
|
|
||||||
|
for (int z=-radiusStepsZ; z<radiusStepsZ; z++) { |
||||||
|
for (int x=-radiusStepsZ; x<radiusStepsX; x++) { |
||||||
|
|
||||||
|
float locX = worldLoc.x + (x*xStepAmount); |
||||||
|
float locZ = worldLoc.z + (z*zStepAmount); |
||||||
|
|
||||||
|
// see if it is in the radius of the tool
|
||||||
|
if (ToolUtils.isInRadius(locX-worldLoc.x,locZ-worldLoc.z,radius)) { |
||||||
|
// adjust height based on radius of the tool
|
||||||
|
float h = ToolUtils.calculateHeight(radius, heightDir, locX-worldLoc.x, locZ-worldLoc.z); |
||||||
|
// increase the height
|
||||||
|
locs.add(new Vector2f(locX, locZ)); |
||||||
|
heights.add(h); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// do the actual height adjustment
|
||||||
|
terrain.adjustHeight(locs, heights); |
||||||
|
|
||||||
|
((Node)terrain).updateModelBound(); // or else we won't collide with it where we just edited
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Smooth the terrain by averaging the heights of the surrounding areas. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class SmoothTerrainTool extends TerrainTool { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
if (radius == 0 || weight == 0) |
||||||
|
return; |
||||||
|
SmoothTerrainToolAction action = new SmoothTerrainToolAction(point, radius, weight); |
||||||
|
action.doActionPerformed(rootNode, dataObject); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject) { |
||||||
|
// do nothing
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
super.addMarkerPrimary(parent); |
||||||
|
markerPrimary.getMaterial().setColor("Color", ColorRGBA.Yellow); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,159 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.math.Vector2f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.terrain.Terrain; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Smooth bumps in the terrain by averaging the height in the tool radius. |
||||||
|
* The smoothAmount affects how many neighbour points are averaged, The smaller |
||||||
|
* the value, then only the smaller bumps will disappear. A large value will |
||||||
|
* smooth larger hills. |
||||||
|
* |
||||||
|
* @author sploreg |
||||||
|
*/ |
||||||
|
public class SmoothTerrainToolAction extends AbstractTerrainToolAction { |
||||||
|
|
||||||
|
private Vector3f worldLoc; |
||||||
|
private float radius; |
||||||
|
private float height; |
||||||
|
|
||||||
|
List<Vector2f> undoLocs; |
||||||
|
List<Float> undoHeights; |
||||||
|
|
||||||
|
public SmoothTerrainToolAction(Vector3f markerLocation, float radius, float height) { |
||||||
|
this.worldLoc = markerLocation.clone(); |
||||||
|
this.radius = radius; |
||||||
|
this.height = height; |
||||||
|
name = "Smooth terrain"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Object doApplyTool(AbstractSceneExplorerNode rootNode) { |
||||||
|
Terrain terrain = getTerrain(rootNode.getLookup().lookup(Node.class)); |
||||||
|
if (terrain == null) |
||||||
|
return null; |
||||||
|
modifyHeight(terrain, radius, height); |
||||||
|
return terrain; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) { |
||||||
|
if (undoObject == null) |
||||||
|
return; |
||||||
|
if (undoLocs == null || undoHeights == null) |
||||||
|
return; |
||||||
|
resetHeight((Terrain)undoObject, undoLocs, undoHeights); |
||||||
|
} |
||||||
|
|
||||||
|
private void modifyHeight(Terrain terrain, float radius, float height) { |
||||||
|
|
||||||
|
int radiusStepsX = (int)(radius / ((Node)terrain).getLocalScale().x); |
||||||
|
int radiusStepsZ = (int)(radius / ((Node)terrain).getLocalScale().z); |
||||||
|
|
||||||
|
float xStepAmount = ((Node)terrain).getLocalScale().x; |
||||||
|
float zStepAmount = ((Node)terrain).getLocalScale().z; |
||||||
|
|
||||||
|
List<Vector2f> locs = new ArrayList<Vector2f>(); |
||||||
|
List<Float> heights = new ArrayList<Float>(); |
||||||
|
|
||||||
|
for (int z=-radiusStepsZ; z<radiusStepsZ; z++) { |
||||||
|
for (int x=-radiusStepsZ; x<radiusStepsX; x++) { |
||||||
|
|
||||||
|
float locX = worldLoc.x + (x*xStepAmount); |
||||||
|
float locZ = worldLoc.z + (z*zStepAmount); |
||||||
|
|
||||||
|
// see if it is in the radius of the tool
|
||||||
|
if (ToolUtils.isInRadius(locX-worldLoc.x,locZ-worldLoc.z,radius)) { |
||||||
|
|
||||||
|
Vector2f terrainLoc = new Vector2f(locX, locZ); |
||||||
|
// adjust height based on radius of the tool
|
||||||
|
float center = terrain.getHeightmapHeight(terrainLoc); |
||||||
|
float left = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x-1, terrainLoc.y)); |
||||||
|
float right = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x+1, terrainLoc.y)); |
||||||
|
float up = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x, terrainLoc.y+1)); |
||||||
|
float down = terrain.getHeightmapHeight(new Vector2f(terrainLoc.x, terrainLoc.y-1)); |
||||||
|
int count = 1; |
||||||
|
float amount = center; |
||||||
|
if (left != Float.NaN) { |
||||||
|
amount += left; |
||||||
|
count++; |
||||||
|
} |
||||||
|
if (right != Float.NaN) { |
||||||
|
amount += right; |
||||||
|
count++; |
||||||
|
} |
||||||
|
if (up != Float.NaN) { |
||||||
|
amount += up; |
||||||
|
count++; |
||||||
|
} |
||||||
|
if (down != Float.NaN) { |
||||||
|
amount += down; |
||||||
|
count++; |
||||||
|
} |
||||||
|
|
||||||
|
amount /= count; // take average
|
||||||
|
|
||||||
|
// weigh it
|
||||||
|
float diff = amount-center; |
||||||
|
diff *= height; |
||||||
|
|
||||||
|
locs.add(terrainLoc); |
||||||
|
heights.add(diff); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
undoLocs = locs; |
||||||
|
undoHeights = heights; |
||||||
|
|
||||||
|
// do the actual height adjustment
|
||||||
|
terrain.adjustHeight(locs, heights); |
||||||
|
|
||||||
|
((Node)terrain).updateModelBound(); // or else we won't collide with it where we just edited
|
||||||
|
} |
||||||
|
|
||||||
|
private void resetHeight(Terrain terrain, List<Vector2f> undoLocs, List<Float> undoHeights) { |
||||||
|
List<Float> neg = new ArrayList<Float>(); |
||||||
|
for (Float f : undoHeights) |
||||||
|
neg.add( f * -1f ); |
||||||
|
|
||||||
|
terrain.adjustHeight(undoLocs, neg); |
||||||
|
((Node)terrain).updateModelBound(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,184 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.asset.AssetManager; |
||||||
|
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Mesh; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.VertexBuffer; |
||||||
|
import com.jme3.scene.shape.Sphere; |
||||||
|
import com.jme3.util.IntMap.Entry; |
||||||
|
import org.openide.loaders.DataObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* Modifies the terrain in some way. |
||||||
|
* It has a primary and secondary action, activated from left and right mouse button respectively. |
||||||
|
* It will also attach tool geometries to the scene so the user can see where they are editing. |
||||||
|
* |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public abstract class TerrainTool { |
||||||
|
|
||||||
|
protected AssetManager manager; |
||||||
|
protected Geometry markerPrimary; |
||||||
|
protected Geometry markerSecondary; |
||||||
|
protected float radius; |
||||||
|
protected float weight; |
||||||
|
protected float maxToolSize = 20; // override in sub classes
|
||||||
|
|
||||||
|
// the key to load the tool hint text from the resource bundle
|
||||||
|
protected String toolHintTextKey = "TerrainEditorTopComponent.toolHint.default"; |
||||||
|
|
||||||
|
/** |
||||||
|
* The tool was selected, start showing the marker. |
||||||
|
* @param manager |
||||||
|
* @param parent node that the marker will attach to |
||||||
|
*/ |
||||||
|
public void activate(AssetManager manager, Node parent) { |
||||||
|
this.manager = manager; |
||||||
|
addMarkerPrimary(parent); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The primary action for the tool gets activated |
||||||
|
*/ |
||||||
|
public abstract void actionPrimary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject); |
||||||
|
|
||||||
|
/** |
||||||
|
* The secondary action for the tool gets activated |
||||||
|
*/ |
||||||
|
public abstract void actionSecondary(Vector3f point, int textureIndex, AbstractSceneExplorerNode rootNode, DataObject dataObject); |
||||||
|
|
||||||
|
/** |
||||||
|
* Location of the primary editor marker |
||||||
|
*/ |
||||||
|
public Vector3f getMarkerPrimaryLocation() { |
||||||
|
if (markerPrimary != null) |
||||||
|
return markerPrimary.getLocalTranslation(); |
||||||
|
else |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Move the marker to a new location, usually follows the mouse |
||||||
|
* @param newLoc |
||||||
|
*/ |
||||||
|
public void markerMoved(Vector3f newLoc) { |
||||||
|
if (markerPrimary != null) |
||||||
|
markerPrimary.setLocalTranslation(newLoc); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The radius of the tool has changed, so update the marker |
||||||
|
* @param radius percentage of the max radius |
||||||
|
*/ |
||||||
|
public void radiusChanged(float radius) { |
||||||
|
this.radius = maxToolSize*radius; |
||||||
|
|
||||||
|
if (markerPrimary != null) { |
||||||
|
for (Entry e: markerPrimary.getMesh().getBuffers()) |
||||||
|
((VertexBuffer)e.getValue()).resetObject(); |
||||||
|
((Sphere)markerPrimary.getMesh()).updateGeometry(8, 8, this.radius); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The weight of the tool has changed. Optionally change |
||||||
|
* the marker look. |
||||||
|
* @param weight percent |
||||||
|
*/ |
||||||
|
public void weightChanged(float weight) { |
||||||
|
this.weight = weight; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the primary marker mesh, follows the mouse. |
||||||
|
* @param parent it will attach to |
||||||
|
*/ |
||||||
|
public void addMarkerPrimary(Node parent) { |
||||||
|
if (markerPrimary == null) { |
||||||
|
markerPrimary = new Geometry("edit marker primary"); |
||||||
|
Mesh m = new Sphere(8, 8, radius); |
||||||
|
markerPrimary.setMesh(m); |
||||||
|
Material mat = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat.getAdditionalRenderState().setWireframe(true); |
||||||
|
markerPrimary.setMaterial(mat); |
||||||
|
markerPrimary.setLocalTranslation(0,0,0); |
||||||
|
mat.setColor("Color", ColorRGBA.LightGray); |
||||||
|
} |
||||||
|
parent.attachChild(markerPrimary); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the secondary marker mesh, placed |
||||||
|
* with the right mouse button. |
||||||
|
* @param parent it will attach to |
||||||
|
*/ |
||||||
|
public void addMarkerSecondary(Node parent) { |
||||||
|
if (markerSecondary == null) { |
||||||
|
markerSecondary = new Geometry("edit marker secondary"); |
||||||
|
Mesh m2 = new Sphere(8, 8, 0.5f); |
||||||
|
markerSecondary.setMesh(m2); |
||||||
|
Material mat2 = new Material(manager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat2.getAdditionalRenderState().setWireframe(false); |
||||||
|
markerSecondary.setMaterial(mat2); |
||||||
|
markerSecondary.setLocalTranslation(0,0,0); |
||||||
|
mat2.setColor("Color", ColorRGBA.Red); |
||||||
|
} |
||||||
|
parent.attachChild(markerSecondary); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Remove the markers from the scene. |
||||||
|
*/ |
||||||
|
public void hideMarkers() { |
||||||
|
if (markerPrimary != null) |
||||||
|
markerPrimary.removeFromParent(); |
||||||
|
if (markerSecondary != null) |
||||||
|
markerSecondary.removeFromParent(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getToolHintTextKey() { |
||||||
|
return toolHintTextKey; |
||||||
|
} |
||||||
|
|
||||||
|
public void setToolHintTextKey(String toolHintTextKey) { |
||||||
|
this.toolHintTextKey = toolHintTextKey; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2011 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.jme3.gde.terraineditor.tools; |
||||||
|
|
||||||
|
import com.jme3.math.Vector2f; |
||||||
|
|
||||||
|
/** |
||||||
|
* Handy utilities for the editor tools |
||||||
|
* @author Brent Owens |
||||||
|
*/ |
||||||
|
public class ToolUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* See if the X,Y coordinate is in the radius of the circle. It is assumed |
||||||
|
* that the "grid" being tested is located at 0,0 and its dimensions are 2*radius. |
||||||
|
* @param x |
||||||
|
* @param z |
||||||
|
* @param radius |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static boolean isInRadius(float x, float y, float radius) { |
||||||
|
Vector2f point = new Vector2f(x,y); |
||||||
|
// return true if the distance is less than equal to the radius
|
||||||
|
return Math.abs(point.length()) <= radius; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Interpolate the height value based on its distance from the center (how far along |
||||||
|
* the radius it is). |
||||||
|
* The farther from the center, the less the height will be. |
||||||
|
* This produces a linear height falloff. |
||||||
|
* @param radius of the tool |
||||||
|
* @param heightFactor potential height value to be adjusted |
||||||
|
* @param x location |
||||||
|
* @param z location |
||||||
|
* @return the adjusted height value |
||||||
|
*/ |
||||||
|
public static float calculateHeight(float radius, float heightFactor, float x, float z) { |
||||||
|
float val = calculateRadiusPercent(radius, x, z); |
||||||
|
return heightFactor * val; |
||||||
|
} |
||||||
|
|
||||||
|
public static float calculateRadiusPercent(float radius, float x, float z) { |
||||||
|
// find percentage for each 'unit' in radius
|
||||||
|
Vector2f point = new Vector2f(x,z); |
||||||
|
float val = Math.abs(point.length()) / radius; |
||||||
|
val = 1f - val; |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
public static int compareFloat(float a, float b, float epsilon) { |
||||||
|
if (floatEquals(a, b, epsilon)) |
||||||
|
return 0; |
||||||
|
else if (floatLessThan(a, b, epsilon)) |
||||||
|
return -1; |
||||||
|
else |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean floatEquals(float a, float b, float epsilon) { |
||||||
|
return a == b ? true : Math.abs(a - b) < epsilon; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean floatLessThan(float a, float b, float epsilon) { |
||||||
|
return b - a > epsilon; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean floatGreaterThan(float a, float b, float epsilon) { |
||||||
|
return a - b > epsilon; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue