Răsfoiți Sursa

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
bre..om 12 ani în urmă
părinte
comite
4122caaf77

+ 3 - 2
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/AbstractStatefulGLToolAction.java

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

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

@@ -96,7 +96,6 @@ TerrainEditorTopComponent.toolHint.level=Right click to set desired height value
 
 TerrainEditorTopComponent.jPanel2.border.title=Material
 TerrainEditorTopComponent.jLabel1.text=Shininess
-TerrainEditorTopComponent.wardIsoCheckBox.text=WardIso
 TerrainEditorTopComponent.shininessField.text=0.0
 TerrainEditorTopComponent.shininessField.toolTipText=0 or greater
 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.paintButton.toolTipText=Erase a texture from the terrain
 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.

+ 202 - 0
jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainAction.java

@@ -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
+ */
[email protected](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;
+    }
+}

+ 74 - 0
jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainVisualPanel1.form

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

+ 92 - 0
jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainVisualPanel1.java

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

+ 50 - 0
jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainWizardAction.java

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

+ 70 - 0
jme3-terrain-editor/src/com/jme3/gde/terraineditor/RenameTerrainWizardPanel1.java

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

+ 87 - 13
jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorController.java

@@ -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.SceneUndoRedoManager;
 import com.jme3.gde.core.util.TerrainUtils;
+import com.jme3.gde.terraineditor.tools.PaintTerrainToolAction;
 import com.jme3.material.MatParam;
+import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
@@ -50,6 +52,7 @@ import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.terrain.ProgressMonitor;
 import com.jme3.terrain.Terrain;
+import com.jme3.texture.Image;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture.WrapMode;
 import com.jme3.util.SkyFactory;
@@ -62,6 +65,8 @@ import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import javax.imageio.ImageIO;
+import javax.imageio.stream.FileImageOutputStream;
+import javax.imageio.stream.ImageOutputStream;
 import javax.swing.undo.CannotRedoException;
 import javax.swing.undo.CannotUndoException;
 import jme3tools.converters.ImageToAwt;
@@ -107,15 +112,15 @@ public class TerrainEditorController implements NodeListener {
                     currentFileObject.saveAsset();
                     //TerrainSaveCookie sc = currentFileObject.getCookie(TerrainSaveCookie.class);
                     //if (sc != null) {
-                        Node root = rootNode.getLookup().lookup(Node.class);
-                        doSaveAlphaImages((Terrain)getTerrain(root));
+                        //Node root = rootNode.getLookup().lookup(Node.class);
+                        doSaveAlphaImages();
                     //}
                     return null;
                 }
             });
         }
     }
-    protected TerrainSaveCookie terrainSaveCookie = new TerrainSaveCookie();
+    private TerrainSaveCookie terrainSaveCookie = new TerrainSaveCookie();
 
     
     public TerrainEditorController(JmeSpatial jmeRootNode, AssetDataObject currentFileObject, TerrainEditorTopComponent topComponent) {
@@ -501,6 +506,7 @@ public class TerrainEditorController implements NodeListener {
         if (SceneApplication.getApplication().isOgl()) {
             doRemoveDiffuseTexture(layer);
             doRemoveNormalMap(layer);
+            doClearAlphaMap(layer);
         } else {
             try {
                 SceneApplication.getApplication().enqueue(new Callable() {
@@ -541,6 +547,43 @@ public class TerrainEditorController implements NodeListener {
 
         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.
@@ -713,12 +756,12 @@ public class TerrainEditorController implements NodeListener {
      * Save the terrain's alpha maps to disk, in the Textures/terrain-alpha/ directory
      * @throws IOException
      */
-    private synchronized void doSaveAlphaImages(Terrain terrain) {
+    private synchronized void doSaveAlphaImages() {
 
-        if (terrain == null) {
-            getTerrain(rootNode);
-            return;
-        }
+        terrainNode = null;
+        // re-look it up
+        Terrain terrain = (Terrain)getTerrain(rootNode);
+        
         
         AssetManager manager = SceneApplication.getApplication().getAssetManager();
         String assetFolder = null;
@@ -726,22 +769,53 @@ public class TerrainEditorController implements NodeListener {
             assetFolder = ((ProjectAssetManager)manager).getAssetFolderName();
         if (assetFolder == null)
             throw new IllegalStateException("AssetManager was not a ProjectAssetManager. Could not locate image save directories.");
-
+        
+        
         Texture alpha1 = doGetAlphaTexture(terrain, 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);
         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);
         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 {
-            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(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) {
+                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);
+            }
         }
         
     }

+ 0 - 13
jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.form

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

+ 3 - 18
jme3-terrain-editor/src/com/jme3/gde/terraineditor/TerrainEditorTopComponent.java

@@ -264,7 +264,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         remainingTexTitleLabel = new javax.swing.JLabel();
         remainingTexturesLabel = new javax.swing.JLabel();
         jPanel2 = new javax.swing.JPanel();
-        wardIsoCheckBox = new javax.swing.JCheckBox();
         shininessField = new javax.swing.JTextField();
         jLabel1 = new javax.swing.JLabel();
         triPlanarCheckBox = new javax.swing.JCheckBox();
@@ -273,7 +272,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         hintTextArea = new javax.swing.JTextArea();
 
         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.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.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.setToolTipText(org.openide.util.NbBundle.getMessage(TerrainEditorTopComponent.class, "TerrainEditorTopComponent.shininessField.toolTipText")); // NOI18N
         shininessField.setInputVerifier(new ShininessVerifier());
@@ -625,7 +617,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         jPanel2.setLayout(jPanel2Layout);
         jPanel2Layout.setHorizontalGroup(
             jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addComponent(wardIsoCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)
             .addGroup(jPanel2Layout.createSequentialGroup()
                 .addComponent(shininessField, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
@@ -635,8 +626,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         jPanel2Layout.setVerticalGroup(
             jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
             .addGroup(jPanel2Layout.createSequentialGroup()
-                .addComponent(wardIsoCheckBox)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addComponent(triPlanarCheckBox)
                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                 .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
@@ -818,10 +807,6 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
         
     }//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
         if (KeyEvent.VK_ENTER == 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.JPanel toolSettingsPanel;
     private javax.swing.JCheckBox triPlanarCheckBox;
-    private javax.swing.JCheckBox wardIsoCheckBox;
     // End of variables declaration//GEN-END:variables
 
     /**
@@ -1448,7 +1432,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
 
         editorController.enableTextureButtons();
         triPlanarCheckBox.setSelected(editorController.isTriPlanarEnabled());
-        wardIsoCheckBox.setSelected(editorController.isWardIsoEnabled());
+        //wardIsoCheckBox.setSelected(editorController.isWardIsoEnabled());
         shininessField.setText(""+editorController.getShininess());
     }
 
@@ -1493,6 +1477,7 @@ public final class TerrainEditorTopComponent extends TopComponent implements Sce
             return; // abort
         }
         getTableModel().removeTexture(selectedIndex);
+        editorController.removeTextureLayer(selectedIndex);
     }
 
     private TextureTableModel getTableModel() {

+ 3 - 1
jme3-terrain-editor/src/com/jme3/gde/terraineditor/tools/PaintTerrainToolAction.java

@@ -54,6 +54,8 @@ public class PaintTerrainToolAction extends AbstractTerrainToolAction {
     private float weight;
     private int selectedTextureIndex;
     
+    public PaintTerrainToolAction() {}
+    
     public PaintTerrainToolAction(Vector3f markerLocation, float radius, float weight, int selectedTextureIndex) {
         this.worldLoc = markerLocation.clone();
         this.radius = radius;
@@ -232,7 +234,7 @@ public class PaintTerrainToolAction extends AbstractTerrainToolAction {
      * @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){
+    public void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){
         ByteBuffer buf = image.getData(0);
         int width = image.getWidth();