- 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
3.0
nor..67 12 years ago
parent 9b1e2819a9
commit 7b46639a4c
  1. 72
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/EditableMaterialFile.java
  2. 8
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/MaterialProperty.java
  3. 2
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/Bundle.properties
  4. 57
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.form
  5. 71
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardVisualPanel1.java
  6. 119
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardAction.java
  7. 66
      sdk/jme3-materialeditor/src/com/jme3/gde/materials/wizards/StoreTextureWizardWizardPanel1.java

@ -5,9 +5,13 @@
package com.jme3.gde.materials; package com.jme3.gde.materials;
import com.jme3.gde.core.assets.ProjectAssetManager; import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.materials.wizards.StoreTextureWizardWizardAction;
import com.jme3.material.MatParam; import com.jme3.material.MatParam;
import com.jme3.material.Material; 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.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -22,6 +26,12 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; 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.FileObject;
import org.openide.filesystems.FileSystem; import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil; import org.openide.filesystems.FileUtil;
@ -29,10 +39,12 @@ import org.openide.util.Exceptions;
/** /**
* Provides an editable j3m file * Provides an editable j3m file
*
* @author normenhansen * @author normenhansen
*/ */
public class EditableMaterialFile { public class EditableMaterialFile {
private static final Logger logger = Logger.getLogger(EditableMaterialFile.class.getName());
private String name; private String name;
private String matDefName; private String matDefName;
private FileObject material; private FileObject material;
@ -153,6 +165,7 @@ public class EditableMaterialFile {
/** /**
* finds and loads the matdef file either from project or from base jme * finds and loads the matdef file either from project or from base jme
*
* @param line * @param line
*/ */
private void parseMaterialProperties(String 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, * Finds and loads the matdef file either from project or from base jme,
* then applies the parameter values to the material parameter entries. * then applies the parameter values to the material parameter entries.
*
* @param line * @param line
*/ */
private void checkWithMatDef() { 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 * @return
*/ */
public String getUpdatedContent() { public String getUpdatedContent() {
@ -409,6 +425,7 @@ public class EditableMaterialFile {
/** /**
* trims a line and removes comments * trims a line and removes comments
*
* @param line * @param line
* @return * @return
*/ */
@ -422,6 +439,7 @@ public class EditableMaterialFile {
/** /**
* trims a line and removes everything behind colon * trims a line and removes everything behind colon
*
* @param line * @param line
* @return * @return
*/ */
@ -467,6 +485,7 @@ public class EditableMaterialFile {
/** /**
* Creates the data from a material * Creates the data from a material
*
* @param mat * @param mat
*/ */
public void setAsMaterial(Material mat) throws IOException { public void setAsMaterial(Material mat) throws IOException {
@ -478,7 +497,7 @@ public class EditableMaterialFile {
Collection<MatParam> params = mat.getParams(); Collection<MatParam> params = mat.getParams();
for (Iterator<MatParam> it = params.iterator(); it.hasNext();) { for (Iterator<MatParam> it = params.iterator(); it.hasNext();) {
MatParam matParam = it.next(); 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("Wireframe", new MaterialProperty("OnOff", "Wireframe", mat.getAdditionalRenderState().isWireframe() ? "On" : "Off"));
additionalRenderStates.put("DepthWrite", new MaterialProperty("OnOff", "DepthWrite", mat.getAdditionalRenderState().isDepthWrite() ? "On" : "Off")); additionalRenderStates.put("DepthWrite", new MaterialProperty("OnOff", "DepthWrite", mat.getAdditionalRenderState().isDepthWrite() ? "On" : "Off"));
@ -493,6 +512,53 @@ public class EditableMaterialFile {
setAsText(getUpdatedContent()); 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 * @return the matDefName
*/ */

@ -4,11 +4,7 @@
*/ */
package com.jme3.gde.materials; package com.jme3.gde.materials;
import com.jme3.asset.AssetKey;
import com.jme3.asset.TextureKey;
import com.jme3.material.MatParam; 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) { public MaterialProperty(MatParam param) {
this.type = param.getVarType().name(); this.type = param.getVarType().name();
this.name = param.getName(); this.name = param.getName();
Object obj = param.getValue(); try {
this.value = param.getValueAsString(); this.value = param.getValueAsString();
} catch (UnsupportedOperationException e) {
}
} }
/** /**

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

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

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

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

@ -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());
}
}
Loading…
Cancel
Save