Added alphamap rename tool to the terrain editor. Removing a texture layer now clears all alpha for that layer

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10838 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
experimental
bre..om 11 years ago
parent a2a39bd0d5
commit d61ac1afe5
  1. 5
      sdk/jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractStatefulGLToolAction.java
  2. 4
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/Bundle.properties
  3. 202
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainAction.java
  4. 74
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainVisualPanel1.form
  5. 92
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainVisualPanel1.java
  6. 50
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainWizardAction.java
  7. 70
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainWizardPanel1.java
  8. 98
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java
  9. 13
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form
  10. 21
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java
  11. 4
      sdk/jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainToolAction.java

@ -91,10 +91,11 @@ public abstract class AbstractStatefulGLToolAction {
}; };
if (manager != null) // this is a temporary check, it should never be null but occasionally is if (manager != null) // this is a temporary check, it should never be null but occasionally is
manager.addEdit(this, undoer); manager.addEdit(this, undoer);
setModified(rootNode, dataObject);
}
} }
if (dataObject != null)
setModified(rootNode, dataObject);
}
protected void setModified(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) { protected void setModified(final AbstractSceneExplorerNode rootNode, final DataObject dataObject) {
if (dataObject.isModified()) if (dataObject.isModified())

@ -96,7 +96,6 @@ TerrainEditorTopComponent.toolHint.level=Right click to set desired height value
TerrainEditorTopComponent.jPanel2.border.title=Material TerrainEditorTopComponent.jPanel2.border.title=Material
TerrainEditorTopComponent.jLabel1.text=Shininess TerrainEditorTopComponent.jLabel1.text=Shininess
TerrainEditorTopComponent.wardIsoCheckBox.text=WardIso
TerrainEditorTopComponent.shininessField.text=0.0 TerrainEditorTopComponent.shininessField.text=0.0
TerrainEditorTopComponent.shininessField.toolTipText=0 or greater TerrainEditorTopComponent.shininessField.toolTipText=0 or greater
TerrainEditorTopComponent.jLabel3.text=Sharpness TerrainEditorTopComponent.jLabel3.text=Sharpness
@ -127,3 +126,6 @@ TerrainEditorTopComponent.borderDistanceLabel.tooltip=Distance means how far fro
TerrainEditorTopComponent.borderHeightLAbel.tooltip=Height means how high the border will go (also accept negative values). TerrainEditorTopComponent.borderHeightLAbel.tooltip=Height means how high the border will go (also accept negative values).
TerrainEditorTopComponent.paintButton.toolTipText=Erase a texture from the terrain TerrainEditorTopComponent.paintButton.toolTipText=Erase a texture from the terrain
TerrainEditorTopComponent.paintButton.text= TerrainEditorTopComponent.paintButton.text=
RenameTerrainVisualPanel1.ranemeLabel.text=Rename Terrain Alphamaps
RenameTerrainVisualPanel1.renameField.text=
RenameTerrainVisualPanel1.jLabel1.text=Terrain alphamaps are named with the scene name when first created.

@ -0,0 +1,202 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.gde.terraineditor;
import com.jme3.asset.TextureKey;
import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.core.scene.SceneApplication;
import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode;
import com.jme3.gde.core.sceneexplorer.nodes.JmeTerrainQuad;
import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractToolWizardAction;
import com.jme3.gde.core.sceneexplorer.nodes.actions.ToolAction;
import com.jme3.material.MatParam;
import com.jme3.material.Material;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.texture.Texture;
import java.awt.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import org.openide.DialogDisplayer;
import org.openide.WizardDescriptor;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
/**
* Rename the alpha-maps.
*
* @author bowens
*/
@org.openide.util.lookup.ServiceProvider(service = ToolAction.class)
public class RenameTerrainAction extends AbstractToolWizardAction {
private String oldName;
private String newName;
public RenameTerrainAction() {
name = "Rename Terrain Alphamaps";
}
public Class<?> getNodeClass() {
return JmeTerrainQuad.class;
}
@Override
protected Object showWizard(Node node) {
AbstractSceneExplorerNode rootNode = (AbstractSceneExplorerNode) node;
TerrainQuad quad = rootNode.getLookup().lookup(TerrainQuad.class);
MatParam param = quad.getMaterial().getParam("AlphaMap");
if (param == null)
oldName = null;
else {
String[] splita = param.getValueAsString().split("/");
String[] split = splita[splita.length-1].split("-alphablend0.png");
String first = split[0];
oldName = first;
}
List<WizardDescriptor.Panel<WizardDescriptor>> panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
panels.add(new RenameTerrainWizardPanel1());
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
}
}
WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<WizardDescriptor>(panels));
// {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
wiz.setTitleFormat(new MessageFormat("{0}"));
wiz.setTitle("Rename the alphamaps of the terrain");
wiz.putProperty("oldName", oldName);
if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
return wiz;
}
return null;
}
@Override
protected Object doApplyTool(AbstractSceneExplorerNode rootNode, Object settings) {
WizardDescriptor wiz = (WizardDescriptor) settings;
if (wiz == null || wiz.getProperties() == null || wiz.getProperties().get("newName") == null)
return null;
newName = cleanFileName( wiz.getProperties().get("newName").toString() );
if (newName == null)
return null;
TerrainQuad quad = rootNode.getLookup().lookup(TerrainQuad.class);
rename(quad, oldName, newName);
return quad;
}
@Override
protected void doUndoTool(AbstractSceneExplorerNode rootNode, Object undoObject) {
TerrainQuad quad = rootNode.getLookup().lookup(TerrainQuad.class);
rename(quad, newName, oldName);
}
private void rename(TerrainQuad quad, String prevName, String newName) {
ProjectAssetManager manager = (ProjectAssetManager) SceneApplication.getApplication().getAssetManager();
String texFolder = "Textures/terrain-alpha/";
// rename the files
String texFolderFilePath = manager.getAssetFolderName() +"/"+ texFolder;
String prevPath0 = texFolderFilePath+prevName+"-alphablend0.png";
String prevPath1 = texFolderFilePath+prevName+"-alphablend1.png";
String prevPath2 = texFolderFilePath+prevName+"-alphablend2.png";
String newPath0 = texFolderFilePath+newName+"-alphablend0.png";
String newPath1 = texFolderFilePath+newName+"-alphablend1.png";
String newPath2 = texFolderFilePath+newName+"-alphablend2.png";
try {
File f0_a = new File(prevPath0);
File f0_b = new File(newPath0);
copyFile(f0_a, f0_b);
//f0_a.delete();
File f1_a = new File(prevPath1);
File f1_b = new File(newPath1);
copyFile(f1_a, f1_b);
//f1_a.delete();
File f2_a = new File(prevPath2);
File f2_b = new File(newPath2);
copyFile(f2_a, f2_b);
//f2_a.delete();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
// set the new mat params
String alphaPath0 = texFolder+newName+"-alphablend0.png";
String alphaPath1 = texFolder+newName+"-alphablend1.png";
String alphaPath2 = texFolder+newName+"-alphablend2.png";
TextureKey tk0 = (TextureKey) manager.loadTexture(texFolder+prevName+"-alphablend0.png").getKey();
TextureKey tk1 = (TextureKey) manager.loadTexture(texFolder+prevName+"-alphablend1.png").getKey();
TextureKey tk2 = (TextureKey) manager.loadTexture(texFolder+prevName+"-alphablend2.png").getKey();
Texture tex0 = manager.loadTexture(cloneKeyParams(tk0, alphaPath0) );
Texture tex1 = manager.loadTexture(cloneKeyParams(tk1, alphaPath1) );
Texture tex2 = manager.loadTexture(cloneKeyParams(tk2, alphaPath2) );
Material material = quad.getMaterial();
material.setTexture("AlphaMap", tex0);
material.setTexture("AlphaMap_1", tex1);
material.setTexture("AlphaMap_2", tex2);
}
private void copyFile(File sourceFile, File destFile) throws IOException {
if(!destFile.exists()) {
destFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally {
if(source != null) {
source.close();
}
if(destination != null) {
destination.close();
}
}
}
private String cleanFileName(String name) {
if (name == null)
return null;
return name.replaceAll("[\\W]|_", "");
}
private TextureKey cloneKeyParams(TextureKey tkOrig, String path) {
TextureKey tk = new TextureKey(path, false);
tk.setAnisotropy(tkOrig.getAnisotropy());
tk.setAsCube(tkOrig.isAsCube());
tk.setAsTexture3D(tkOrig.isAsTexture3D());
tk.setGenerateMips(tkOrig.isGenerateMips());
tk.setTextureTypeHint(tkOrig.getTextureTypeHint());
return tk;
}
}

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="ranemeLabel" min="-2" pref="139" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="renameField" min="-2" pref="193" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="ranemeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="renameField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="26" max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" pref="14" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="ranemeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jme3/gde/terraineditor/Bundle.properties" key="RenameTerrainVisualPanel1.ranemeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="renameField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jme3/gde/terraineditor/Bundle.properties" key="RenameTerrainVisualPanel1.renameField.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="renameFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="com/jme3/gde/terraineditor/Bundle.properties" key="RenameTerrainVisualPanel1.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

@ -0,0 +1,92 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.gde.terraineditor;
import javax.swing.JPanel;
public final class RenameTerrainVisualPanel1 extends JPanel {
/**
* Creates new form RenameTerrainVisualPanel1
*/
public RenameTerrainVisualPanel1() {
initComponents();
}
@Override
public String getName() {
return "Rename Alphamaps";
}
public String getRenamed() {
return renameField.getText();
}
void setOriginalName(String name) {
renameField.setText(name);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
ranemeLabel = new javax.swing.JLabel();
renameField = new javax.swing.JTextField();
jLabel1 = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(ranemeLabel, org.openide.util.NbBundle.getMessage(RenameTerrainVisualPanel1.class, "RenameTerrainVisualPanel1.ranemeLabel.text")); // NOI18N
renameField.setText(org.openide.util.NbBundle.getMessage(RenameTerrainVisualPanel1.class, "RenameTerrainVisualPanel1.renameField.text")); // NOI18N
renameField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
renameFieldActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(RenameTerrainVisualPanel1.class, "RenameTerrainVisualPanel1.jLabel1.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(ranemeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 139, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(renameField, javax.swing.GroupLayout.PREFERRED_SIZE, 193, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ranemeLabel)
.addComponent(renameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 26, Short.MAX_VALUE)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
);
}// </editor-fold>//GEN-END:initComponents
private void renameFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renameFieldActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_renameFieldActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel ranemeLabel;
private javax.swing.JTextField renameField;
// End of variables declaration//GEN-END:variables
}

@ -0,0 +1,50 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.gde.terraineditor;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import org.openide.DialogDisplayer;
import org.openide.WizardDescriptor;
// An example action demonstrating how the wizard could be called from within
// your code. You can move the code below wherever you need, or register an action:
// @ActionID(category="...", id="com.jme3.gde.terraineditor.RenameTerrainWizardAction")
// @ActionRegistration(displayName="Open RenameTerrain Wizard")
// @ActionReference(path="Menu/Tools", position=...)
public final class RenameTerrainWizardAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
List<WizardDescriptor.Panel<WizardDescriptor>> panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
panels.add(new RenameTerrainWizardPanel1());
String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
// Default step name to component name of panel.
steps[i] = c.getName();
if (c instanceof JComponent) { // assume Swing components
JComponent jc = (JComponent) c;
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
}
}
WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<WizardDescriptor>(panels));
// {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
wiz.setTitleFormat(new MessageFormat("{0}"));
wiz.setTitle("...dialog title...");
if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
// do something
}
}
}

@ -0,0 +1,70 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.gde.terraineditor;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
public class RenameTerrainWizardPanel1 implements WizardDescriptor.Panel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private RenameTerrainVisualPanel1 component;
// Get the visual component for the panel. In this template, the component
// is kept separate. This can be more efficient: if the wizard is created
// but never displayed, or not all panels are displayed, it is better to
// create only those which really need to be visible.
@Override
public RenameTerrainVisualPanel1 getComponent() {
if (component == null) {
component = new RenameTerrainVisualPanel1();
}
return component;
}
@Override
public HelpCtx getHelp() {
// Show no Help button for this panel:
return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx("help.key.here");
}
@Override
public boolean isValid() {
// If it is always OK to press Next or Finish, then:
return true;
// If it depends on some condition (form filled out...) and
// this condition changes (last form field filled in...) then
// use ChangeSupport to implement add/removeChangeListener below.
// WizardDescriptor.ERROR/WARNING/INFORMATION_MESSAGE will also be useful.
}
@Override
public void addChangeListener(ChangeListener l) {
}
@Override
public void removeChangeListener(ChangeListener l) {
}
@Override
public void readSettings(WizardDescriptor wiz) {
RenameTerrainVisualPanel1 comp = (RenameTerrainVisualPanel1) getComponent();
String name = wiz.getProperty("oldName").toString();
comp.setOriginalName(name);
}
@Override
public void storeSettings(WizardDescriptor wiz) {
RenameTerrainVisualPanel1 comp = (RenameTerrainVisualPanel1) getComponent();
String name = comp.getRenamed();
wiz.putProperty("newName", name );
}
}

@ -42,7 +42,9 @@ import com.jme3.gde.core.sceneexplorer.nodes.JmeSpatial;
import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit; import com.jme3.gde.core.undoredo.AbstractUndoableSceneEdit;
import com.jme3.gde.core.undoredo.SceneUndoRedoManager; import com.jme3.gde.core.undoredo.SceneUndoRedoManager;
import com.jme3.gde.core.util.TerrainUtils; import com.jme3.gde.core.util.TerrainUtils;
import com.jme3.gde.terraineditor.tools.PaintTerrainToolAction;
import com.jme3.material.MatParam; import com.jme3.material.MatParam;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f; import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
@ -50,6 +52,7 @@ import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.terrain.ProgressMonitor; import com.jme3.terrain.ProgressMonitor;
import com.jme3.terrain.Terrain; import com.jme3.terrain.Terrain;
import com.jme3.texture.Image;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode; import com.jme3.texture.Texture.WrapMode;
import com.jme3.util.SkyFactory; import com.jme3.util.SkyFactory;
@ -62,6 +65,8 @@ import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException; import javax.swing.undo.CannotUndoException;
import jme3tools.converters.ImageToAwt; import jme3tools.converters.ImageToAwt;
@ -107,15 +112,15 @@ public class TerrainEditorController implements NodeListener {
currentFileObject.saveAsset(); currentFileObject.saveAsset();
//TerrainSaveCookie sc = currentFileObject.getCookie(TerrainSaveCookie.class); //TerrainSaveCookie sc = currentFileObject.getCookie(TerrainSaveCookie.class);
//if (sc != null) { //if (sc != null) {
Node root = rootNode.getLookup().lookup(Node.class); //Node root = rootNode.getLookup().lookup(Node.class);
doSaveAlphaImages((Terrain)getTerrain(root)); doSaveAlphaImages();
//} //}
return null; return null;
} }
}); });
} }
} }
protected TerrainSaveCookie terrainSaveCookie = new TerrainSaveCookie(); private TerrainSaveCookie terrainSaveCookie = new TerrainSaveCookie();
public TerrainEditorController(JmeSpatial jmeRootNode, AssetDataObject currentFileObject, TerrainEditorTopComponent topComponent) { public TerrainEditorController(JmeSpatial jmeRootNode, AssetDataObject currentFileObject, TerrainEditorTopComponent topComponent) {
@ -501,6 +506,7 @@ public class TerrainEditorController implements NodeListener {
if (SceneApplication.getApplication().isOgl()) { if (SceneApplication.getApplication().isOgl()) {
doRemoveDiffuseTexture(layer); doRemoveDiffuseTexture(layer);
doRemoveNormalMap(layer); doRemoveNormalMap(layer);
doClearAlphaMap(layer);
} else { } else {
try { try {
SceneApplication.getApplication().enqueue(new Callable() { SceneApplication.getApplication().enqueue(new Callable() {
@ -542,6 +548,43 @@ public class TerrainEditorController implements NodeListener {
setNeedsSave(true); setNeedsSave(true);
} }
private void doClearAlphaMap(int selectedTextureIndex) {
Terrain terrain = (Terrain) getTerrain(null);
if (terrain == null)
return;
int alphaIdx = selectedTextureIndex/4; // 4 = rgba = 4 textures
int texIndex = selectedTextureIndex - ((selectedTextureIndex/4)*4); // selectedTextureIndex/4 is an int floor
//selectedTextureIndex - (alphaIdx * 4)
Texture tex = doGetAlphaTexture(terrain, alphaIdx);
Image image = tex.getImage();
PaintTerrainToolAction paint = new PaintTerrainToolAction();
ColorRGBA color = ColorRGBA.Black;
for (int y=0; y<image.getHeight(); y++) {
for (int x=0; x<image.getWidth(); x++) {
paint.manipulatePixel(image, x, y, color, false); // gets the color at that location (false means don't write to the buffer)
switch (texIndex) {
case 0:
color.r = 0; break;
case 1:
color.g = 0; break;
case 2:
color.b = 0; break;
case 3:
color.a = 0; break;
}
color.clamp();
paint.manipulatePixel(image, x, y, color, true); // set the new color
}
}
image.getData(0).rewind();
tex.getImage().setUpdateNeeded();
setNeedsSave(true);
}
/** /**
* Get the normal map texture at the specified layer. * Get the normal map texture at the specified layer.
* Run this on the GL thread! * Run this on the GL thread!
@ -713,12 +756,12 @@ public class TerrainEditorController implements NodeListener {
* Save the terrain's alpha maps to disk, in the Textures/terrain-alpha/ directory * Save the terrain's alpha maps to disk, in the Textures/terrain-alpha/ directory
* @throws IOException * @throws IOException
*/ */
private synchronized void doSaveAlphaImages(Terrain terrain) { private synchronized void doSaveAlphaImages() {
terrainNode = null;
// re-look it up
Terrain terrain = (Terrain)getTerrain(rootNode);
if (terrain == null) {
getTerrain(rootNode);
return;
}
AssetManager manager = SceneApplication.getApplication().getAssetManager(); AssetManager manager = SceneApplication.getApplication().getAssetManager();
String assetFolder = null; String assetFolder = null;
@ -727,22 +770,53 @@ public class TerrainEditorController implements NodeListener {
if (assetFolder == null) if (assetFolder == null)
throw new IllegalStateException("AssetManager was not a ProjectAssetManager. Could not locate image save directories."); throw new IllegalStateException("AssetManager was not a ProjectAssetManager. Could not locate image save directories.");
Texture alpha1 = doGetAlphaTexture(terrain, 0); Texture alpha1 = doGetAlphaTexture(terrain, 0);
BufferedImage bi1 = ImageToAwt.convert(alpha1.getImage(), false, true, 0); BufferedImage bi1 = ImageToAwt.convert(alpha1.getImage(), false, true, 0);
File imageFile1 = new File(assetFolder+alpha1.getKey().getName()); File imageFile1 = new File(assetFolder+"/"+alpha1.getKey().getName());
Texture alpha2 = doGetAlphaTexture(terrain, 1); Texture alpha2 = doGetAlphaTexture(terrain, 1);
BufferedImage bi2 = ImageToAwt.convert(alpha2.getImage(), false, true, 0); BufferedImage bi2 = ImageToAwt.convert(alpha2.getImage(), false, true, 0);
File imageFile2 = new File(assetFolder+alpha2.getKey().getName()); File imageFile2 = new File(assetFolder+"/"+alpha2.getKey().getName());
Texture alpha3 = doGetAlphaTexture(terrain, 2); Texture alpha3 = doGetAlphaTexture(terrain, 2);
BufferedImage bi3 = ImageToAwt.convert(alpha3.getImage(), false, true, 0); BufferedImage bi3 = ImageToAwt.convert(alpha3.getImage(), false, true, 0);
File imageFile3 = new File(assetFolder+alpha3.getKey().getName()); File imageFile3 = new File(assetFolder+"/"+alpha3.getKey().getName());
ImageOutputStream ios1 = null;
ImageOutputStream ios2 = null;
ImageOutputStream ios3 = null;
try { try {
ImageIO.write(bi1, "png", imageFile1); ios1 = new FileImageOutputStream(imageFile1);
ios2 = new FileImageOutputStream(imageFile2);
ios3 = new FileImageOutputStream(imageFile3);
ImageIO.write(bi1, "png", ios1);
ImageIO.write(bi2, "png", imageFile2); ImageIO.write(bi2, "png", imageFile2);
ImageIO.write(bi3, "png", imageFile3); ImageIO.write(bi3, "png", imageFile3);
} catch (IOException ex) {
System.out.println("Failed saving alphamaps");
System.out.println(" "+imageFile1);
System.out.println(" "+imageFile2);
System.out.println(" "+imageFile3);
Exceptions.printStackTrace(ex);
} finally {
try {
if (ios1 != null)
ios1.close();
} catch (IOException ex) { } catch (IOException ex) {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);
} }
try {
if (ios2 != null)
ios2.close();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
try {
if (ios3 != null)
ios3.close();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
} }

@ -631,7 +631,6 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="wardIsoCheckBox" alignment="0" pref="111" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="shininessField" min="-2" pref="41" max="-2" attributes="0"/> <Component id="shininessField" min="-2" pref="41" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -643,8 +642,6 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="wardIsoCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="triPlanarCheckBox" min="-2" max="-2" attributes="0"/> <Component id="triPlanarCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
@ -657,16 +654,6 @@
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Component class="javax.swing.JCheckBox" name="wardIsoCheckBox">
<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.wardIsoCheckBox.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="wardIsoCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="shininessField"> <Component class="javax.swing.JTextField" name="shininessField">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">

@ -264,7 +264,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
remainingTexTitleLabel = new javax.swing.JLabel(); remainingTexTitleLabel = new javax.swing.JLabel();
remainingTexturesLabel = new javax.swing.JLabel(); remainingTexturesLabel = new javax.swing.JLabel();
jPanel2 = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel();
wardIsoCheckBox = new javax.swing.JCheckBox();
shininessField = new javax.swing.JTextField(); shininessField = new javax.swing.JTextField();
jLabel1 = new javax.swing.JLabel(); jLabel1 = new javax.swing.JLabel();
triPlanarCheckBox = new javax.swing.JCheckBox(); triPlanarCheckBox = new javax.swing.JCheckBox();
@ -273,7 +272,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
hintTextArea = new javax.swing.JTextArea(); hintTextArea = new javax.swing.JTextArea();
textureFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.textureFileChooser.approveButtonText_1")); // NOI18N textureFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.textureFileChooser.approveButtonText_1")); // NOI18N
textureFileChooser.setCurrentDirectory(new java.io.File("C:\\Assets\\Textures")); textureFileChooser.setCurrentDirectory(new java.io.File("F:\\Assets\\Textures"));
textureFileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.textureFileChooser.dialogTitle_1")); // NOI18N textureFileChooser.setDialogTitle(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.textureFileChooser.dialogTitle_1")); // NOI18N
textureFileChooser.setFileFilter(new ImageFilter()); textureFileChooser.setFileFilter(new ImageFilter());
@ -590,13 +589,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.jPanel2.border.title"))); // NOI18N jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.jPanel2.border.title"))); // NOI18N
jPanel2.setOpaque(false); jPanel2.setOpaque(false);
org.openide.awt.Mnemonics.setLocalizedText(wardIsoCheckBox, org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.wardIsoCheckBox.text")); // NOI18N
wardIsoCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
wardIsoCheckBoxActionPerformed(evt);
}
});
shininessField.setText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.shininessField.text")); // NOI18N shininessField.setText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.shininessField.text")); // NOI18N
shininessField.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.shininessField.toolTipText")); // NOI18N shininessField.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.shininessField.toolTipText")); // NOI18N
shininessField.setInputVerifier(new ShininessVerifier()); shininessField.setInputVerifier(new ShininessVerifier());
@ -625,7 +617,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
jPanel2.setLayout(jPanel2Layout); jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup( jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(wardIsoCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createSequentialGroup() .addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(shininessField, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(shininessField, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@ -635,8 +626,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
jPanel2Layout.setVerticalGroup( jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup() .addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(wardIsoCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(triPlanarCheckBox) .addComponent(triPlanarCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
@ -818,10 +807,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
}//GEN-LAST:event_shininessFieldActionPerformed }//GEN-LAST:event_shininessFieldActionPerformed
private void wardIsoCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_wardIsoCheckBoxActionPerformed
editorController.setWardIsoEnabled(wardIsoCheckBox.isSelected());
}//GEN-LAST:event_wardIsoCheckBoxActionPerformed
private void shininessFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_shininessFieldKeyTyped private void shininessFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_shininessFieldKeyTyped
if (KeyEvent.VK_ENTER == evt.getKeyCode() || if (KeyEvent.VK_ENTER == evt.getKeyCode() ||
KeyEvent.VK_TAB == evt.getKeyCode() ){ KeyEvent.VK_TAB == evt.getKeyCode() ){
@ -946,7 +931,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
private javax.swing.JTable textureTable; private javax.swing.JTable textureTable;
private javax.swing.JPanel toolSettingsPanel; private javax.swing.JPanel toolSettingsPanel;
private javax.swing.JCheckBox triPlanarCheckBox; private javax.swing.JCheckBox triPlanarCheckBox;
private javax.swing.JCheckBox wardIsoCheckBox;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
/** /**
@ -1448,7 +1432,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
editorController.enableTextureButtons(); editorController.enableTextureButtons();
triPlanarCheckBox.setSelected(editorController.isTriPlanarEnabled()); triPlanarCheckBox.setSelected(editorController.isTriPlanarEnabled());
wardIsoCheckBox.setSelected(editorController.isWardIsoEnabled()); //wardIsoCheckBox.setSelected(editorController.isWardIsoEnabled());
shininessField.setText(""+editorController.getShininess()); shininessField.setText(""+editorController.getShininess());
} }
@ -1493,6 +1477,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
return; // abort return; // abort
} }
getTableModel().removeTexture(selectedIndex); getTableModel().removeTexture(selectedIndex);
editorController.removeTextureLayer(selectedIndex);
} }
private TextureTableModel getTableModel() { private TextureTableModel getTableModel() {

@ -54,6 +54,8 @@ public class PaintTerrainToolAction extends AbstractTerrainToolAction {
private float weight; private float weight;
private int selectedTextureIndex; private int selectedTextureIndex;
public PaintTerrainToolAction() {}
public PaintTerrainToolAction(Vector3f markerLocation, float radius, float weight, int selectedTextureIndex) { public PaintTerrainToolAction(Vector3f markerLocation, float radius, float weight, int selectedTextureIndex) {
this.worldLoc = markerLocation.clone(); this.worldLoc = markerLocation.clone();
this.radius = radius; this.radius = radius;
@ -232,7 +234,7 @@ public class PaintTerrainToolAction extends AbstractTerrainToolAction {
* @param color color to get/set * @param color color to get/set
* @param write to write the color or not * @param write to write the color or not
*/ */
protected void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){ public void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){
ByteBuffer buf = image.getData(0); ByteBuffer buf = image.getData(0);
int width = image.getWidth(); int width = image.getWidth();

Loading…
Cancel
Save