/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.material.plugin.export.materialdef;
import com.jme3.material.*;
import com.jme3.shader.*;
import java.io.*;
import java.util.Collection;
import java.util.regex.*;
import static java.util.regex.Pattern.compile;
/**
* @author nehon
*/
public class J3mdTechniqueDefWriter {
public J3mdTechniqueDefWriter() {
}
public void write(TechniqueDef techniqueDef, Collection<MatParam> matParams, OutputStreamWriter out) throws IOException {
out.write(" Technique");
if(!techniqueDef.getName().equals("Default")) {
out.write(" ");
out.write(techniqueDef.getName());
}
out.write(" {\n");
//Light mode
if(techniqueDef.getLightMode() != TechniqueDef.LightMode.Disable ){
out.write(" LightMode ");
out.write(techniqueDef.getLightMode().name());
out.write("\n\n");
}
//Shadow mode
if(techniqueDef.getShadowMode() != TechniqueDef.ShadowMode.Disable ){
out.write(" ShadowMode ");
out.write(techniqueDef.getShadowMode().name());
out.write("\n\n");
}
//Shaders
if(!techniqueDef.isUsingShaderNodes()) {
writeShaders(techniqueDef, out);
}
//World params
if(!techniqueDef.getWorldBindings().isEmpty()){
writeWorldParams(techniqueDef, out);
}
//ShaderNodes
if(techniqueDef.isUsingShaderNodes()){
writeShaderNodes(techniqueDef, matParams, out);
} else {
//When we have ShaderNodes, Defines are handled differently so we don't have to write them.
//Defines
if (techniqueDef.getDefineNames().length != 0) {
writeDefines(techniqueDef, matParams, out);
}
}
//render state
RenderState rs = techniqueDef.getRenderState();
if(rs != null){
out.write(" RenderState {\n");
writeRenderState(rs, out);
out.write(" }\n\n");
}
//forced render state
rs = techniqueDef.getForcedRenderState();
if(rs != null){
out.write(" ForcedRenderState {\n");
writeRenderState(rs, out);
out.write(" }\n\n");
}
//no render
if(techniqueDef.isNoRender()){
out.write(" NoRender\n\n");
}
out.write(" }\n");
}
private void writeDefines(TechniqueDef techniqueDef, Collection<MatParam> matParams, OutputStreamWriter out) throws IOException {
out.write(" Defines {\n");
for (int i = 0; i < techniqueDef.getDefineNames().length; i++) {
String matParamName = getMatParamNameForDefineId(techniqueDef, matParams, i);
if (matParamName != null) {
String defineName = techniqueDef.getDefineNames()[i];
out.write(" ");
out.write(defineName);
out.write(": ");
out.write(matParamName);
out.write("\n");
}
}
out.write(" }\n\n");
}
private void writeShaderNodes(TechniqueDef techniqueDef, Collection<MatParam> matParams, OutputStreamWriter out) throws IOException {
out.write(" VertexShaderNodes {\n");
for (ShaderNode shaderNode : techniqueDef.getShaderNodes()) {
if(shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex){
writeShaderNode(out, shaderNode, matParams);
}
}
out.write(" }\n\n");
out.write(" FragmentShaderNodes {\n");
for (ShaderNode shaderNode : techniqueDef.getShaderNodes()) {
if(shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment){
writeShaderNode(out, shaderNode, matParams);
}
}
out.write(" }\n\n");
}
private void writeWorldParams(TechniqueDef techniqueDef, OutputStreamWriter out) throws IOException {
out.write(" WorldParameters {\n");
for (UniformBinding uniformBinding : techniqueDef.getWorldBindings()) {
out.write(" ");
out.write(uniformBinding.toString());
out.write("\n");
}
out.write(" }\n\n");
}
private void writeShaders(TechniqueDef techniqueDef, OutputStreamWriter out) throws IOException {
if (techniqueDef.getShaderProgramNames().size() > 0) {
for (Shader.ShaderType shaderType : techniqueDef.getShaderProgramNames().keySet()) {
// System.err.println(shaderType + " " +techniqueDef.getShaderProgramNames().get(shaderType) + " " +techniqueDef.getShaderProgramLanguage(shaderType))
out.write(" ");
out.write(shaderType.name());
out.write("Shader ");
out.write(techniqueDef.getShaderProgramLanguage(shaderType));
out.write(": ");
out.write(techniqueDef.getShaderProgramNames().get(shaderType));
out.write("\n");
}
out.write("\n");
}
}
private void writeShaderNode( OutputStreamWriter out, ShaderNode shaderNode, Collection<MatParam> matParams) throws IOException {
out.write(" ShaderNode ");
out.write(shaderNode.getName());
out.write(" {\n");
if (shaderNode.getCondition() != null){
out.write(" Condition: ");
out.write(formatCondition(shaderNode.getCondition(), matParams));
out.write("\n");
}
out.write(" Definition: ");
out.write(shaderNode.getDefinition().getName());
out.write(": ");
out.write(shaderNode.getDefinition().getPath());
out.write("\n");
out.write(" InputMappings{\n");
for (VariableMapping mapping : shaderNode.getInputMapping()) {
writeVariableMapping(out, shaderNode, mapping, matParams);
}
out.write(" }\n");
out.write(" OutputMappings{\n");
for (VariableMapping mapping : shaderNode.getOutputMapping()) {
writeVariableMapping(out, shaderNode, mapping, matParams);
}
out.write(" }\n");
out.write(" }\n");
}
private void writeVariableMapping(OutputStreamWriter out, ShaderNode shaderNode, VariableMapping mapping, Collection<MatParam> matParams) throws IOException {
out.write(" ");
if(!mapping.getLeftVariable().getNameSpace().equals(shaderNode.getName())) {
out.write(mapping.getLeftVariable().getNameSpace());
out.write(".");
}
out.write(mapping.getLeftVariable().getName());
if(!mapping.getLeftSwizzling().equals("")){
out.write(".");
out.write(mapping.getLeftSwizzling());
}
out.write(" = ");
if(!mapping.getRightVariable().getNameSpace().equals(shaderNode.getName())) {
out.write(mapping.getRightVariable().getNameSpace());
out.write(".");
}
out.write(mapping.getRightVariable().getName().replaceFirst("g_","").replaceFirst("m_",""));
if(!mapping.getRightSwizzling().equals("")){
out.write(".");
out.write(mapping.getRightSwizzling());
}
if (mapping.getCondition() != null){
out.write(" : ");
out.write(formatCondition(mapping.getCondition(),matParams));
}
out.write("\n");
}
private String formatCondition(String condition, Collection<MatParam> matParams){
//condition = condition.replaceAll("defined\\(","");
String res = condition;
Pattern pattern = Pattern.compile("defined\\(([A-Z0-9]*)\\)");
Matcher m = pattern.matcher(condition);
while(m.find()){
String match = m.group(0);
String defineName = m.group(1).toLowerCase();
for (MatParam matParam : matParams) {
if(matParam.getName().toLowerCase().equals(defineName)){
res = res.replace(match, matParam.getName());
}
}
}
return res;
}
private void writeRenderStateAttribute(OutputStreamWriter out, String name, String value) throws IOException {
out.write(" ");
out.write(name);
out.write(" ");
out.write(value);
out.write("\n");
}
private void writeRenderState(RenderState rs, OutputStreamWriter out) throws IOException {
RenderState defRs = RenderState.DEFAULT;
if(rs.getBlendMode() != defRs.getBlendMode()) {
writeRenderStateAttribute(out, "Blend", rs.getBlendMode().name());
}
if(rs.isWireframe() != defRs.isWireframe()) {
writeRenderStateAttribute(out, "Wireframe", rs.isWireframe()?"On":"Off");
}
if(rs.getFaceCullMode() != defRs.getFaceCullMode()) {
writeRenderStateAttribute(out, "FaceCull", rs.getFaceCullMode().name());
}
if(rs.isDepthWrite() != defRs.isDepthWrite()) {
writeRenderStateAttribute(out, "DepthWrite", rs.isDepthWrite()?"On":"Off");
}
if(rs.isDepthTest() != defRs.isDepthTest()) {
writeRenderStateAttribute(out, "DepthTest", rs.isDepthTest()?"On":"Off");
}
if(rs.getBlendEquation() != defRs.getBlendEquation()) {
writeRenderStateAttribute(out, "BlendEquation", rs.getBlendEquation().name());
}
if(rs.getBlendEquationAlpha() != defRs.getBlendEquationAlpha()) {
writeRenderStateAttribute(out, "BlendEquationAlpha", rs.getBlendEquationAlpha().name());
}
if(rs.getPolyOffsetFactor() != defRs.getPolyOffsetFactor() || rs.getPolyOffsetUnits() != defRs.getPolyOffsetUnits()) {
writeRenderStateAttribute(out, "PolyOffset", rs.getPolyOffsetFactor() + " " + rs.getPolyOffsetUnits());
}
if(rs.isColorWrite() != defRs.isColorWrite()) {
writeRenderStateAttribute(out, "ColorWrite", rs.isColorWrite()?"On":"Off");
}
if(rs.getDepthFunc() != defRs.getDepthFunc()) {
writeRenderStateAttribute(out, "DepthFunc", rs.getDepthFunc().name());
}
if(rs.getLineWidth() != defRs.getLineWidth()) {
writeRenderStateAttribute(out, "LineWidth", Float.toString(rs.getLineWidth()));
}
}
private String getMatParamNameForDefineId(TechniqueDef techniqueDef, Collection<MatParam> matParams, int defineId) {
for (MatParam matParam : matParams) {
Integer id = techniqueDef.getShaderParamDefineId(matParam.getName());
if(id !=null && id == defineId){
return matParam.getName();
}
}
return null;
}
}