浏览代码

SDK:
- Add way to store packed textures to png files when creating j3m files

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10122 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

nor..67 12 年之前
父节点
当前提交
ce4c1417ca

+ 71 - 5
jme3-materialeditor/src/com/jme3/gde/materials/EditableMaterialFile.java

@@ -5,9 +5,13 @@
 package com.jme3.gde.materials;
 
 import com.jme3.gde.core.assets.ProjectAssetManager;
+import com.jme3.gde.materials.wizards.StoreTextureWizardWizardAction;
 import com.jme3.material.MatParam;
 import com.jme3.material.Material;
-import com.jme3.system.JmeSystem;
+import com.jme3.texture.Image;
+import com.jme3.texture.Texture;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -22,6 +26,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
+import jme3tools.converters.ImageToAwt;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileSystem;
 import org.openide.filesystems.FileUtil;
@@ -29,10 +39,12 @@ import org.openide.util.Exceptions;
 
 /**
  * Provides an editable j3m file
+ *
  * @author normenhansen
  */
 public class EditableMaterialFile {
 
+    private static final Logger logger = Logger.getLogger(EditableMaterialFile.class.getName());
     private String name;
     private String matDefName;
     private FileObject material;
@@ -139,7 +151,7 @@ public class EditableMaterialFile {
                                     value += " " + lines[i];
                                 }
                                 prop.setValue(value.trim());
-                            }                           
+                            }
                             additionalRenderStates.put(prop.getName(), prop);
                         }
                     }
@@ -153,6 +165,7 @@ public class EditableMaterialFile {
 
     /**
      * finds and loads the matdef file either from project or from base jme
+     *
      * @param line
      */
     private void parseMaterialProperties(String line) {
@@ -196,6 +209,7 @@ public class EditableMaterialFile {
     /**
      * Finds and loads the matdef file either from project or from base jme,
      * then applies the parameter values to the material parameter entries.
+     *
      * @param line
      */
     private void checkWithMatDef() {
@@ -253,7 +267,9 @@ public class EditableMaterialFile {
     }
 
     /**
-     * returns the new content of the material file, filled with the new parameters
+     * returns the new content of the material file, filled with the new
+     * parameters
+     *
      * @return
      */
     public String getUpdatedContent() {
@@ -409,6 +425,7 @@ public class EditableMaterialFile {
 
     /**
      * trims a line and removes comments
+     *
      * @param line
      * @return
      */
@@ -422,13 +439,14 @@ public class EditableMaterialFile {
 
     /**
      * trims a line and removes everything behind colon
+     *
      * @param line
      * @return
      */
     private String trimName(String line) {
         line = trimLine(line);
         int idx = line.indexOf("(");
-        if(idx == -1){
+        if (idx == -1) {
             idx = line.indexOf(":");
         }
         if (idx != -1) {
@@ -467,6 +485,7 @@ public class EditableMaterialFile {
 
     /**
      * Creates the data from a material
+     *
      * @param mat
      */
     public void setAsMaterial(Material mat) throws IOException {
@@ -478,7 +497,7 @@ public class EditableMaterialFile {
         Collection<MatParam> params = mat.getParams();
         for (Iterator<MatParam> it = params.iterator(); it.hasNext();) {
             MatParam matParam = it.next();
-            materialParameters.put(matParam.getName(), new MaterialProperty(matParam));
+            checkPackedTextureProps(mat, matParam);
         }
         additionalRenderStates.put("Wireframe", new MaterialProperty("OnOff", "Wireframe", mat.getAdditionalRenderState().isWireframe() ? "On" : "Off"));
         additionalRenderStates.put("DepthWrite", new MaterialProperty("OnOff", "DepthWrite", mat.getAdditionalRenderState().isDepthWrite() ? "On" : "Off"));
@@ -493,6 +512,53 @@ public class EditableMaterialFile {
         setAsText(getUpdatedContent());
     }
 
+    /**
+     * Prompts user to save packed textures
+     *
+     * @param mat
+     * @param param
+     */
+    private void checkPackedTextureProps(Material mat, MatParam param) {
+        MaterialProperty prop = new MaterialProperty(param);
+        materialParameters.put(param.getName(), prop);
+        if (prop.getValue() == null) {
+            switch (param.getVarType()) {
+                case Texture2D:
+                case Texture3D:
+                case TextureArray:
+                case TextureBuffer:
+                case TextureCubeMap:
+                    try {
+                        Texture tex = mat.getTextureParam(param.getName()).getTextureValue();
+                        Image img = tex.getImage();
+                        if (img == null) {
+                            logger.log(Level.INFO, "No image found");
+                            return;
+                        }
+                        BufferedImage image = ImageToAwt.convert(img, false, false, 0);
+                        ByteArrayOutputStream out = new ByteArrayOutputStream();
+                        ImageWriter imgWrtr = ImageIO.getImageWritersByFormatName("png").next();
+                        ImageOutputStream imgOutStrm;
+                        imgOutStrm = ImageIO.createImageOutputStream(out);
+                        imgWrtr.setOutput(imgOutStrm);
+                        ImageWriteParam jpgWrtPrm = imgWrtr.getDefaultWriteParam();
+                        imgWrtr.write(null, new IIOImage(image, null, null), jpgWrtPrm);
+                        imgOutStrm.close();
+                        out.close();
+                        String name = material.getName();
+                        name = "Textures/" + name + "-" + param.getName() + ".png";
+                        StoreTextureWizardWizardAction act = new StoreTextureWizardWizardAction(manager, out.toByteArray(), name);
+                        act.actionPerformed(null);
+                        prop.setValue(act.getName());
+                    } catch (Exception ex) {
+                        Exceptions.printStackTrace(ex);
+                    }
+                    break;
+                default:
+            }
+        }
+    }
+
     /**
      * @return the matDefName
      */

+ 4 - 6
jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java

@@ -4,11 +4,7 @@
  */
 package com.jme3.gde.materials;
 
-import com.jme3.asset.AssetKey;
-import com.jme3.asset.TextureKey;
 import com.jme3.material.MatParam;
-import com.jme3.math.ColorRGBA;
-import com.jme3.texture.Texture2D;
 
 /**
  *
@@ -32,8 +28,10 @@ public class MaterialProperty {
     public MaterialProperty(MatParam param) {
         this.type = param.getVarType().name();
         this.name = param.getName();
-        Object obj = param.getValue();
-        this.value = param.getValueAsString();
+        try {
+            this.value = param.getValueAsString();
+        } catch (UnsupportedOperationException e) {
+        }
     }
 
     /**

+ 2 - 0
jme3-materialeditor/src/com/jme3/gde/materials/wizards/Bundle.properties

@@ -0,0 +1,2 @@
+StoreTextureWizardVisualPanel1.jTextField1.text=
+StoreTextureWizardVisualPanel1.jLabel1.text=Save asset to:

+ 57 - 0
jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.form

@@ -0,0 +1,57 @@
+<?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" attributes="0">
+              <EmptySpace max="-2" attributes="0"/>
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <Component id="jLabel1" pref="388" max="32767" attributes="0"/>
+                  <Component id="jTextField1" max="32767" attributes="0"/>
+              </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"/>
+              <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jTextField1" min="-2" max="-2" attributes="0"/>
+              <EmptySpace pref="244" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JTextField" name="jTextField1">
+      <Properties>
+        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString bundle="com/jme3/gde/materials/wizards/Bundle.properties" key="StoreTextureWizardVisualPanel1.jTextField1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </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/materials/wizards/Bundle.properties" key="StoreTextureWizardVisualPanel1.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
+    </Component>
+  </SubComponents>
+</Form>

+ 71 - 0
jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.java

@@ -0,0 +1,71 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.materials.wizards;
+
+import javax.swing.JPanel;
+
+public final class StoreTextureWizardVisualPanel1 extends JPanel {
+
+    /**
+     * Creates new form StoreTextureWizardVisualPanel1
+     */
+    public StoreTextureWizardVisualPanel1() {
+        initComponents();
+    }
+
+    @Override
+    public String getName() {
+        return "Set storage path";
+    }
+    
+    public void setPath(String path){
+        jTextField1.setText(path);
+    }
+
+    public String getPath(){
+        return jTextField1.getText();
+    }
+    
+    /**
+     * 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() {
+
+        jTextField1 = new javax.swing.JTextField();
+        jLabel1 = new javax.swing.JLabel();
+
+        jTextField1.setText(org.openide.util.NbBundle.getMessage(StoreTextureWizardVisualPanel1.class, "StoreTextureWizardVisualPanel1.jTextField1.text")); // NOI18N
+
+        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(StoreTextureWizardVisualPanel1.class, "StoreTextureWizardVisualPanel1.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, 388, Short.MAX_VALUE)
+                    .addComponent(jTextField1))
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(layout.createSequentialGroup()
+                .addContainerGap()
+                .addComponent(jLabel1)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap(244, Short.MAX_VALUE))
+        );
+    }// </editor-fold>//GEN-END:initComponents
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JLabel jLabel1;
+    private javax.swing.JTextField jTextField1;
+    // End of variables declaration//GEN-END:variables
+}

+ 119 - 0
jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardAction.java

@@ -0,0 +1,119 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.materials.wizards;
+
+import com.jme3.gde.core.assets.ProjectAssetManager;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JComponent;
+import org.openide.DialogDisplayer;
+import org.openide.NotifyDescriptor;
+import org.openide.WizardDescriptor;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+
+// 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.materials.wizards.StoreTextureWizardWizardAction")
+// @ActionRegistration(displayName="Open StoreTextureWizard Wizard")
+// @ActionReference(path="Menu/Tools", position=...)
+public final class StoreTextureWizardWizardAction implements ActionListener {
+
+    private final ProjectAssetManager mgr;
+    private byte[] data;
+    private String name;
+
+    public StoreTextureWizardWizardAction(ProjectAssetManager mgr, byte[] data, String name) {
+        this.mgr = mgr;
+        this.data = data;
+        this.name = name;
+    }
+
+    public StoreTextureWizardWizardAction(ProjectAssetManager mgr, byte[] data) {
+        this.mgr = mgr;
+        this.data = data;
+    }
+
+    public StoreTextureWizardWizardAction(ProjectAssetManager mgr) {
+        this.mgr = mgr;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        if (mgr == null) {
+            return;
+        }
+        List<WizardDescriptor.Panel<WizardDescriptor>> panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
+        panels.add(new StoreTextureWizardWizardPanel1());
+        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));
+        if (name != null) {
+            wiz.putProperty("path", name);
+        } else {
+            wiz.putProperty("path", "Textures/MyTexture.png");
+        }
+        // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
+        wiz.setTitleFormat(new MessageFormat("{0}"));
+        wiz.setTitle("Save texture as..");
+        if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
+            String path = (String) wiz.getProperties().get("path");
+            if (path != null) {
+                name = path;
+                OutputStream out = null;
+                try {
+                    FileObject file = mgr.getAssetFolder().getFileObject(path);
+                    if (file != null) {
+                        NotifyDescriptor.Confirmation mesg = new NotifyDescriptor.Confirmation("File exists, overwrite?",
+                                "File Exists",
+                                NotifyDescriptor.YES_NO_OPTION);
+                        DialogDisplayer.getDefault().notify(mesg);
+                        if (mesg.getValue() != NotifyDescriptor.Confirmation.YES_OPTION) {
+                            return;
+                        }
+                    }
+                    file = FileUtil.createData(mgr.getAssetFolder(), path);
+                    out = new BufferedOutputStream(file.getOutputStream());
+                    out.write(data);
+                } catch (IOException ex) {
+                    DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Message("Failed to create data!\n" + ex));
+                    Exceptions.printStackTrace(ex);
+                } finally {
+                    if (out != null) {
+                        try {
+                            out.close();
+                        } catch (IOException ex) {
+                            Exceptions.printStackTrace(ex);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+}

+ 66 - 0
jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardPanel1.java

@@ -0,0 +1,66 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.gde.materials.wizards;
+
+import javax.swing.event.ChangeListener;
+import org.openide.WizardDescriptor;
+import org.openide.util.HelpCtx;
+
+public class StoreTextureWizardWizardPanel1 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 StoreTextureWizardVisualPanel1 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 StoreTextureWizardVisualPanel1 getComponent() {
+        if (component == null) {
+            component = new StoreTextureWizardVisualPanel1();
+        }
+        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) {
+        component.setPath((String)wiz.getProperty("path"));
+    }
+
+    @Override
+    public void storeSettings(WizardDescriptor wiz) {
+        wiz.putProperty("path", component.getPath());
+    }
+}