159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/*
259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine
359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved.
459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without
659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are
759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met:
859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright
1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer.
1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright
1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   notice, this list of conditions and the following disclaimer in the
1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   documentation and/or other materials provided with the distribution.
1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   may be used to endorse or promote products derived from this software
1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *   without specific prior written permission.
1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta *
2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */
3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.material.plugins;
3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.*;
3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState.BlendMode;
3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.RenderState.FaceCullMode;
3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.*;
3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.TechniqueDef.LightMode;
4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.TechniqueDef.ShadowMode;
4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.ColorRGBA;
4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector2f;
4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f;
4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.shader.VarType;
4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture;
4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture.WrapMode;
4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Texture2D;
4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.PlaceholderAssets;
4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.blockparser.BlockLanguageParser;
5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.blockparser.Statement;
5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException;
5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.InputStream;
5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List;
5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level;
5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger;
5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class J3MLoader implements AssetLoader {
5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final Logger logger = Logger.getLogger(J3MLoader.class.getName());
6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private AssetManager assetManager;
6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private AssetKey key;
6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private MaterialDef materialDef;
6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Material material;
6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private TechniqueDef technique;
6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private RenderState renderState;
6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private String shaderLang;
7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private String vertName;
7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private String fragName;
7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private static final String whitespacePattern = "\\p{javaWhitespace}+";
7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public J3MLoader(){
7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void throwIfNequal(String expected, String got) throws IOException {
7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (expected == null)
8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Expected a statement, got '"+got+"'!");
8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (!expected.equals(got))
8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Expected '"+expected+"', got '"+got+"'!");
8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // <TYPE> <LANG> : <SOURCE>
8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readShaderStatement(String statement) throws IOException {
8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(":");
8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length != 2){
9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Shader statement syntax incorrect" + statement);
9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] typeAndLang = split[0].split(whitespacePattern);
9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (typeAndLang.length != 2){
9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Shader statement syntax incorrect: " + statement);
9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        shaderLang = typeAndLang[1];
9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (typeAndLang[0].equals("VertexShader")){
9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            vertName = split[1].trim();
9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (typeAndLang[0].equals("FragmentShader")){
10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            fragName = split[1].trim();
10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // LightMode <MODE>
10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readLightMode(String statement) throws IOException{
10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(whitespacePattern);
10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length != 2){
10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("LightMode statement syntax incorrect");
10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        LightMode lm = LightMode.valueOf(split[1]);
11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        technique.setLightMode(lm);
11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // ShadowMode <MODE>
11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readShadowMode(String statement) throws IOException{
11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(whitespacePattern);
11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length != 2){
11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("ShadowMode statement syntax incorrect");
11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        ShadowMode sm = ShadowMode.valueOf(split[1]);
12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        technique.setShadowMode(sm);
12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private Object readValue(VarType type, String value) throws IOException{
12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (type.isTextureType()){
12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            String texturePath = readString("[\n;(//)(\\})]");
12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            String texturePath = value.trim();
12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            boolean flipY = false;
12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            boolean repeat = false;
13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (texturePath.startsWith("Flip Repeat ")){
13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texturePath = texturePath.substring(12).trim();
13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                flipY = true;
13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                repeat = true;
13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else if (texturePath.startsWith("Flip ")){
13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texturePath = texturePath.substring(5).trim();
13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                flipY = true;
13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else if (texturePath.startsWith("Repeat ")){
13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                texturePath = texturePath.substring(7).trim();
13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                repeat = true;
14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            TextureKey texKey = new TextureKey(texturePath, flipY);
14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texKey.setAsCube(type == VarType.TextureCubeMap);
14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            texKey.setGenerateMips(true);
14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Texture tex;
14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            try {
14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tex = assetManager.loadTexture(texKey);
14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } catch (AssetNotFoundException ex){
15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[]{texKey, key});
15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tex = null;
15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (tex != null){
15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (repeat){
15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    tex.setWrap(WrapMode.Repeat);
15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else{
15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                tex = new Texture2D(PlaceholderAssets.getPlaceholderImage());
15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return tex;
16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            String[] split = value.trim().split(whitespacePattern);
16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            switch (type){
16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Float:
16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (split.length != 1){
16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new IOException("Float value parameter must have 1 entry: " + value);
16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                     return Float.parseFloat(split[0]);
16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Vector2:
17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (split.length != 2){
17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new IOException("Vector2 value parameter must have 2 entries: " + value);
17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return new Vector2f(Float.parseFloat(split[0]),
17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                               Float.parseFloat(split[1]));
17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Vector3:
17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (split.length != 3){
17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new IOException("Vector3 value parameter must have 3 entries: " + value);
17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return new Vector3f(Float.parseFloat(split[0]),
18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                               Float.parseFloat(split[1]),
18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                               Float.parseFloat(split[2]));
18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Vector4:
18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (split.length != 4){
18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new IOException("Vector4 value parameter must have 4 entries: " + value);
18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return new ColorRGBA(Float.parseFloat(split[0]),
18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                                Float.parseFloat(split[1]),
18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                                Float.parseFloat(split[2]),
18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                                                Float.parseFloat(split[3]));
19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Int:
19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (split.length != 1){
19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new IOException("Int value parameter must have 1 entry: " + value);
19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return Integer.parseInt(split[0]);
19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                case Boolean:
19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    if (split.length != 1){
19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                        throw new IOException("Boolean value parameter must have 1 entry: " + value);
19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    }
19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    return Boolean.parseBoolean(split[0]);
20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                default:
20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    throw new UnsupportedOperationException("Unknown type: "+type);
20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // <TYPE> <NAME> [ "(" <FFBINDING> ")" ] [ ":" <DEFAULTVAL> ]
20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readParam(String statement) throws IOException{
20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String name;
20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String defaultVal = null;
21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        FixedFuncBinding ffBinding = null;
21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(":");
21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Parse default val
21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length == 1){
21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // Doesn't contain default value
21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (split.length != 2){
21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("Parameter statement syntax incorrect");
22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statement = split[0].trim();
22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            defaultVal = split[1].trim();
22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Parse ffbinding
22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        int startParen = statement.indexOf("(");
22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (startParen != -1){
22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // get content inside parentheses
22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            int endParen = statement.indexOf(")", startParen);
23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            String bindingStr = statement.substring(startParen+1, endParen).trim();
23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            try {
23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                ffBinding = FixedFuncBinding.valueOf(bindingStr);
23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            } catch (IllegalArgumentException ex){
23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("FixedFuncBinding '" +
23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                                      split[1] + "' does not exist!");
23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            statement = statement.substring(0, startParen);
23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Parse type + name
24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        split = statement.split(whitespacePattern);
24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length != 2){
24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Parameter statement syntax incorrect");
24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        VarType type;
24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split[0].equals("Color")){
24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            type = VarType.Vector4;
24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            type = VarType.valueOf(split[0]);
25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        name = split[1];
25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Object defaultValObj = null;
25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (defaultVal != null){
25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            defaultValObj = readValue(type, defaultVal);
25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        materialDef.addMaterialParam(type, name, defaultValObj, ffBinding);
26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readValueParam(String statement) throws IOException{
26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // Use limit=1 incase filename contains colons
26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(":", 2);
26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length != 2){
26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Value parameter statement syntax incorrect");
26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String name = split[0].trim();
27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        // parse value
27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        MatParam p = material.getMaterialDef().getMaterialParam(name);
27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (p == null){
27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("The material parameter: "+name+" is undefined.");
27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Object valueObj = readValue(p.getVarType(), split[1]);
27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (p.getVarType().isTextureType()){
27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            material.setTextureParam(name, p.getVarType(), (Texture) valueObj);
28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            material.setParam(name, p.getVarType(), valueObj);
28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readMaterialParams(List<Statement> paramsList) throws IOException{
28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : paramsList){
28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readParam(statement.getLine());
28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readExtendingMaterialParams(List<Statement> paramsList) throws IOException{
29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : paramsList){
29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readValueParam(statement.getLine());
29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readWorldParams(List<Statement> worldParams) throws IOException{
29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : worldParams){
29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            technique.addWorldParam(statement.getLine());
30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private boolean parseBoolean(String word){
30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        return word != null && word.equals("On");
30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readRenderStateStatement(String statement) throws IOException{
30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(whitespacePattern);
30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split[0].equals("Wireframe")){
31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setWireframe(parseBoolean(split[1]));
31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("FaceCull")){
31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setFaceCullMode(FaceCullMode.valueOf(split[1]));
31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("DepthWrite")){
31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setDepthWrite(parseBoolean(split[1]));
31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("DepthTest")){
31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setDepthTest(parseBoolean(split[1]));
31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("Blend")){
31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setBlendMode(BlendMode.valueOf(split[1]));
31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("AlphaTestFalloff")){
32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setAlphaTest(true);
32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setAlphaFallOff(Float.parseFloat(split[1]));
32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("PolyOffset")){
32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float factor = Float.parseFloat(split[1]);
32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            float units = Float.parseFloat(split[2]);
32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setPolyOffset(factor, units);
32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("ColorWrite")){
32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setColorWrite(parseBoolean(split[1]));
32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("PointSprite")){
32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            renderState.setPointSprite(parseBoolean(split[1]));
33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throwIfNequal(null, split[0]);
33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readAdditionalRenderState(List<Statement> renderStates) throws IOException{
33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        renderState = material.getAdditionalRenderState();
33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : renderStates){
33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readRenderStateStatement(statement.getLine());
33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        renderState = null;
34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readRenderState(List<Statement> renderStates) throws IOException{
34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        renderState = new RenderState();
34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : renderStates){
34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readRenderStateStatement(statement.getLine());
34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        technique.setRenderState(renderState);
34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        renderState = null;
35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    // <DEFINENAME> [ ":" <PARAMNAME> ]
35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readDefine(String statement) throws IOException{
35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(":");
35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length == 1){
35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // add preset define
35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            technique.addShaderPresetDefine(split[0].trim(), VarType.Boolean, true);
35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split.length == 2){
35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            technique.addShaderParamDefine(split[1].trim(), split[0].trim());
36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Define syntax incorrect");
36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readDefines(List<Statement> defineList) throws IOException{
36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : defineList){
36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readDefine(statement.getLine());
36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readTechniqueStatement(Statement statement) throws IOException{
37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.getLine().split("[ \\{]");
37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split[0].equals("VertexShader") ||
37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            split[0].equals("FragmentShader")){
37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readShaderStatement(statement.getLine());
37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("LightMode")){
37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readLightMode(statement.getLine());
37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("ShadowMode")){
38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readShadowMode(statement.getLine());
38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("WorldParameters")){
38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readWorldParams(statement.getContents());
38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("RenderState")){
38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readRenderState(statement.getContents());
38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split[0].equals("Defines")){
38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readDefines(statement.getContents());
38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throwIfNequal(null, split[0]);
38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readTransparentStatement(String statement) throws IOException{
39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = statement.split(whitespacePattern);
39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length != 2){
39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Transparent statement syntax incorrect");
39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        material.setTransparent(parseBoolean(split[1]));
39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void readTechnique(Statement techStat) throws IOException{
40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = techStat.getLine().split(whitespacePattern);
40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length == 1){
40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            technique = new TechniqueDef(null);
40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split.length == 2){
40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            technique = new TechniqueDef(split[1]);
40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Technique statement syntax incorrect");
40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : techStat.getContents()){
41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            readTechniqueStatement(statement);
41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (vertName != null && fragName != null){
41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            technique.setShaderFile(vertName, fragName, shaderLang);
41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        materialDef.addTechniqueDef(technique);
41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        technique = null;
42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        vertName = null;
42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        fragName = null;
42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        shaderLang = null;
42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    private void loadFromRoot(List<Statement> roots) throws IOException{
42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (roots.size() == 2){
42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            Statement exception = roots.get(0);
42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            String line = exception.getLine();
42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (line.startsWith("Exception")){
43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new AssetLoadException(line.substring("Exception ".length()));
43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else{
43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("In multiroot material, expected first statement to be 'Exception'");
43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (roots.size() != 1){
43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Too many roots in J3M/J3MD file");
43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        boolean extending = false;
43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        Statement materialStat = roots.get(0);
44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String materialName = materialStat.getLine();
44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (materialName.startsWith("MaterialDef")){
44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            materialName = materialName.substring("MaterialDef ".length()).trim();
44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            extending = false;
44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (materialName.startsWith("Material")){
44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            materialName = materialName.substring("Material ".length()).trim();
44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            extending = true;
44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Specified file is not a Material file");
44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        String[] split = materialName.split(":", 2);
45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (materialName.equals("")){
45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Material name cannot be empty");
45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (split.length == 2){
45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!extending){
45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("Must use 'Material' when extending.");
46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            String extendedMat = split[1].trim();
46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            MaterialDef def = (MaterialDef) assetManager.loadAsset(new AssetKey(extendedMat));
46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (def == null)
46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("Extended material "+extendedMat+" cannot be found.");
46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            material = new Material(def);
46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            material.setKey(key);
47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta//            material.setAssetName(fileName);
47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else if (split.length == 1){
47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (extending){
47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("Expected ':', got '{'");
47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            materialDef = new MaterialDef(assetManager, materialName);
47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // NOTE: pass file name for defs so they can be loaded later
47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            materialDef.setAssetName(key.getName());
47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            throw new IOException("Cannot use colon in material name/path");
48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        for (Statement statement : materialStat.getContents()){
48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            split = statement.getLine().split("[ \\{]");
48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            String statType = split[0];
48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (extending){
48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (statType.equals("MaterialParameters")){
48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    readExtendingMaterialParams(statement.getContents());
48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }else if (statType.equals("AdditionalRenderState")){
48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    readAdditionalRenderState(statement.getContents());
49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }else if (statType.equals("Transparent")){
49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    readTransparentStatement(statement.getLine());
49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }else{
49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                if (statType.equals("Technique")){
49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    readTechnique(statement);
49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }else if (statType.equals("MaterialParameters")){
49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    readMaterialParams(statement.getContents());
49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }else{
49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                    throw new IOException("Expected material statement, got '"+statType+"'");
50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                }
50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    public Object load(AssetInfo info) throws IOException {
50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        this.assetManager = info.getManager();
50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        InputStream in = info.openStream();
50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        try {
51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            key = info.getKey();
51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            loadFromRoot(BlockLanguageParser.parse(in));
51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        } finally {
51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (in != null){
51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                in.close();
51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        if (material != null){
51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            if (!(info.getKey() instanceof MaterialKey)){
52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta                throw new IOException("Material instances must be loaded via MaterialKey");
52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            }
52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // material implementation
52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return material;
52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }else{
52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            // material definition
52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta            return materialDef;
52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta        }
52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta    }
52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta
53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta}
531