A complete 3D game development suite written purely in Java.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
jmonkeyengine/sdk/jme3-materialeditor/src/com/jme3/gde/materialdefinition/EditableMatDefFile.java

365 lines
15 KiB

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.gde.materialdefinition;
import com.jme3.asset.AssetKey;
import com.jme3.gde.core.assets.ProjectAssetManager;
import com.jme3.gde.core.scene.SceneApplication;
import com.jme3.gde.materialdefinition.fileStructure.MatDefBlock;
import com.jme3.gde.materialdefinition.fileStructure.ShaderNodeBlock;
import com.jme3.gde.materialdefinition.fileStructure.TechniqueBlock;
import com.jme3.gde.materialdefinition.fileStructure.UberStatement;
import com.jme3.gde.materialdefinition.fileStructure.leaves.InputMappingBlock;
import com.jme3.gde.materialdefinition.fileStructure.leaves.LeafStatement;
import com.jme3.gde.materialdefinition.fileStructure.leaves.MatParamBlock;
import com.jme3.gde.materialdefinition.fileStructure.leaves.OutputMappingBlock;
import com.jme3.gde.materialdefinition.navigator.node.MatDefNode;
import com.jme3.material.MatParam;
import com.jme3.material.Material;
import com.jme3.material.MaterialDef;
import com.jme3.material.plugins.J3MLoader;
import com.jme3.material.plugins.MatParseException;
import com.jme3.shader.Glsl100ShaderGenerator;
import com.jme3.shader.Glsl150ShaderGenerator;
import com.jme3.shader.Shader;
import com.jme3.shader.ShaderGenerator;
import com.jme3.util.blockparser.BlockLanguageParser;
import com.jme3.util.blockparser.Statement;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyledDocument;
import org.openide.cookies.EditorCookie;
import org.openide.explorer.ExplorerManager;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.nodes.Node;
import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.WeakListeners;
/**
*
* @author Nehon
*/
public class EditableMatDefFile {
private FileObject matDefFile;
private final MatDefDataObject obj;
private Material material;
private MatDefBlock matDefStructure;
private TechniqueBlock currentTechnique;
private MaterialDef materialDef;
private ProjectAssetManager assetManager;
private ShaderGenerator glsl100;
private ShaderGenerator glsl150;
private final static String GLSL100 = "GLSL100";
private Lookup lookup;
private boolean loaded = false;
private boolean dirty = false;
public EditableMatDefFile(Lookup lookup) {
obj = lookup.lookup(MatDefDataObject.class);
load(lookup);
}
public final void load(Lookup lookup) {
loaded = false;
this.matDefFile = obj.getPrimaryFile();
this.assetManager = lookup.lookup(ProjectAssetManager.class);
this.glsl100 = new Glsl100ShaderGenerator(assetManager);
this.glsl150 = new Glsl150ShaderGenerator(assetManager);
this.lookup = lookup;
if (matDefStructure != null) {
obj.getLookupContents().remove(matDefStructure);
matDefStructure = null;
}
if (materialDef != null) {
obj.getLookupContents().remove(materialDef);
materialDef = null;
}
if (material != null) {
obj.getLookupContents().remove(material);
matToRemove = material;
material = null;
}
FileLock lock = null;
InputStream in = null;
boolean matParseError = false;
try {
lock = matDefFile.lock();
in = obj.getPrimaryFile().getInputStream();
List<Statement> sta = BlockLanguageParser.parse(in);
matDefStructure = new MatDefBlock(sta.get(0));
if (assetManager != null) {
AssetKey<MaterialDef> matDefKey = new AssetKey<MaterialDef>(assetManager.getRelativeAssetPath(assetManager.getRelativeAssetPath(matDefFile.getPath())));
assetManager.deleteFromCache(matDefKey);
materialDef = (MaterialDef) assetManager.loadAsset(assetManager.getRelativeAssetPath(matDefFile.getPath()));
}
} catch (Exception ex) {
Throwable t = ex.getCause();
while (t != null) {
if (t instanceof MatParseException) {
Logger.getLogger(EditableMatDefFile.class.getName()).log(Level.SEVERE, t.getMessage());
matParseError = true;
}
t = t.getCause();
}
if (!matParseError) {
Exceptions.printStackTrace(ex);
}
} finally {
if (lock != null) {
lock.releaseLock();
}
if (in != null) {
try {
in.close();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}
if (materialDef != null && !matParseError) {
if(currentTechnique == null){
currentTechnique = matDefStructure.getTechniques().get(0);
}
registerListener(matDefStructure);
obj.getLookupContents().add(matDefStructure);
updateLookupWithMaterialData(obj);
loaded = true;
}
}
private void registerListener(Statement sta) {
if (sta instanceof UberStatement) {
((UberStatement) sta).addPropertyChangeListener(WeakListeners.propertyChange(changeListener, ((UberStatement) sta)));
} else if (sta instanceof LeafStatement) {
((LeafStatement) sta).addPropertyChangeListener(WeakListeners.propertyChange(changeListener, ((LeafStatement) sta)));
}
if (sta.getContents() != null) {
for (Statement statement : sta.getContents()) {
registerListener(statement);
}
}
}
public void buildOverview(ExplorerManager mgr) {
if (materialDef != null) {
mgr.setRootContext(new MatDefNode(lookup));
} else {
mgr.setRootContext(Node.EMPTY);
}
}
public String getShaderCode(String version, Shader.ShaderType type) {
try {
material.selectTechnique(currentTechnique.getName(), SceneApplication.getApplication().getRenderManager());
Shader s;
if (version.equals(GLSL100)) {
glsl100.initialize(material.getActiveTechnique());
s = glsl100.generateShader();
} else {
glsl150.initialize(material.getActiveTechnique());
s = glsl150.generateShader();
}
for (Shader.ShaderSource source : s.getSources()) {
if (source.getType() == type) {
return source.getSource();
}
}
return "";
} catch (Exception e) {
Exceptions.printStackTrace(e);
return "error generating shader " + e.getMessage();
}
}
public TechniqueBlock getCurrentTechnique() {
return currentTechnique;
}
public void setCurrentTechnique(TechniqueBlock tech){
this.currentTechnique = tech;
}
public MatDefBlock getMatDefStructure() {
return matDefStructure;
}
private final MatStructChangeListener changeListener = new MatStructChangeListener();
J3MLoader loader = new J3MLoader();
private void updateLookupWithMaterialData(MatDefDataObject obj) {
obj.getLookupContents().add(materialDef);
material = new Material(materialDef);
try {
//material.selectTechnique("Default", SceneApplication.getApplication().getRenderManager());
if (matToRemove != null) {
for (MatParam matParam : matToRemove.getParams()) {
try {
material.setParam(matParam.getName(), matParam.getVarType(), matParam.getValue());
} catch (IllegalArgumentException ie) {
matToRemove.clearParam(matParam.getName());
}
}
obj.getLookupContents().remove(matToRemove);
matToRemove = null;
}
obj.getLookupContents().add(material);
} catch (Exception e) {
Logger.getLogger(EditableMatDefFile.class.getName()).log(Level.WARNING, "Error making material {0}", e.getMessage());
material = matToRemove;
}
}
public boolean isLoaded() {
return loaded;
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
public void setLoaded(boolean loaded) {
this.loaded = loaded;
}
private class MatStructChangeListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() instanceof ShaderNodeBlock && evt.getPropertyName().equals("name")) {
String oldValue = (String) evt.getOldValue();
String newValue = (String) evt.getNewValue();
for (ShaderNodeBlock shaderNodeBlock : currentTechnique.getShaderNodes()) {
List<InputMappingBlock> lin = shaderNodeBlock.getInputs();
if (lin != null) {
for (InputMappingBlock inputMappingBlock : shaderNodeBlock.getInputs()) {
if (inputMappingBlock.getLeftNameSpace().equals(oldValue)) {
inputMappingBlock.setLeftNameSpace(newValue);
}
if (inputMappingBlock.getRightNameSpace().equals(oldValue)) {
inputMappingBlock.setRightNameSpace(newValue);
}
}
}
List<OutputMappingBlock> l = shaderNodeBlock.getOutputs();
if (l != null) {
for (OutputMappingBlock outputMappingBlock : l) {
if (outputMappingBlock.getRightNameSpace().equals(oldValue)) {
outputMappingBlock.setRightNameSpace(newValue);
}
}
}
}
}
if (evt.getPropertyName().equals(MatDefBlock.REMOVE_MAT_PARAM)) {
MatParamBlock oldValue = (MatParamBlock) evt.getOldValue();
for (ShaderNodeBlock shaderNodeBlock : currentTechnique.getShaderNodes()) {
if (shaderNodeBlock.getCondition() != null && shaderNodeBlock.getCondition().contains(oldValue.getName())) {
shaderNodeBlock.setCondition(shaderNodeBlock.getCondition().replaceAll(oldValue.getName(), "").trim());
}
List<InputMappingBlock> lin = shaderNodeBlock.getInputs();
if (lin != null) {
for (InputMappingBlock inputMappingBlock : shaderNodeBlock.getInputs()) {
if (inputMappingBlock.getCondition() != null && inputMappingBlock.getCondition().contains(oldValue.getName())) {
inputMappingBlock.setCondition(inputMappingBlock.getCondition().replaceAll(oldValue.getName(), "").trim());
}
}
}
List<OutputMappingBlock> l = shaderNodeBlock.getOutputs();
if (l != null) {
for (OutputMappingBlock outputMappingBlock : l) {
if (outputMappingBlock.getCondition() != null && outputMappingBlock.getCondition().contains(oldValue.getName())) {
outputMappingBlock.setCondition(outputMappingBlock.getCondition().replaceAll(oldValue.getName(), "").trim());
}
}
}
}
}
if (evt.getPropertyName().equals(MatDefBlock.ADD_MAT_PARAM)
|| evt.getPropertyName().equals(TechniqueBlock.ADD_SHADER_NODE)
|| evt.getPropertyName().equals(ShaderNodeBlock.ADD_MAPPING)) {
registerListener((Statement) evt.getNewValue());
}
applyChange();
}
}
Material matToRemove;
private void applyChange() {
try {
EditorCookie ec = lookup.lookup(EditorCookie.class);
final StyledDocument doc = ec.getDocument();
final BadLocationException[] exc = new BadLocationException[]{null};
NbDocument.runAtomicAsUser(ec.getDocument(), new Runnable() {
public void run() {
try {
doc.remove(0, doc.getLength());
doc.insertString(doc.getLength(),
matDefStructure.toString(),
SimpleAttributeSet.EMPTY);
} catch (BadLocationException e) {
exc[0] = e;
}
}
});
} catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
AssetKey<MaterialDef> key = new AssetKey<MaterialDef>(assetManager.getRelativeAssetPath(matDefFile.getPath()));
obj.getLookupContents().remove(materialDef);
matToRemove = material;
List<Statement> l = new ArrayList<Statement>();
l.add(matDefStructure);
try {
materialDef = loader.loadMaterialDef(l, assetManager, key);
} catch (IOException ex) {
Logger.getLogger(EditableMatDefFile.class.getName()).log(Level.SEVERE, ex.getMessage());
}
updateLookupWithMaterialData(obj);
}
public void cleanup(){
if (matDefStructure != null) {
obj.getLookupContents().remove(matDefStructure);
matDefStructure = null;
}
if (materialDef != null) {
obj.getLookupContents().remove(materialDef);
materialDef = null;
}
if (material != null) {
obj.getLookupContents().remove(material);
matToRemove = material;
material = null;
}
setCurrentTechnique(null);
setLoaded(false);
}
}