diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/EditableMaterialFile.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/EditableMaterialFile.java index 858721e39..d798be6d0 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/EditableMaterialFile.java +++ b/sdk/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 params = mat.getParams(); for (Iterator 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 */ diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java index 0a1d501cf..553b3655e 100644 --- a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java +++ b/sdk/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) { + } } /** diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/Bundle.properties b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/Bundle.properties new file mode 100644 index 000000000..dbeafebc6 --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/Bundle.properties @@ -0,0 +1,2 @@ +StoreTextureWizardVisualPanel1.jTextField1.text= +StoreTextureWizardVisualPanel1.jLabel1.text=Save asset to: diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.form b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.form new file mode 100644 index 000000000..7f1b20f7b --- /dev/null +++ b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.form @@ -0,0 +1,57 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.java new file mode 100644 index 000000000..ab5ce8538 --- /dev/null +++ b/sdk/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. + */ + // //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)) + ); + }// //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 +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardAction.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardAction.java new file mode 100644 index 000000000..3633f124c --- /dev/null +++ b/sdk/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> panels = new ArrayList>(); + 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(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; + } +} diff --git a/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardPanel1.java b/sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardPanel1.java new file mode 100644 index 000000000..5c7c3a9ff --- /dev/null +++ b/sdk/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 { + + /** + * 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()); + } +}