private void readTechnique(Statement techStat) throws IOException {
    isUseNodes = false;
    String[] split = techStat.getLine().split(whitespacePattern);
    if (split.length == 1) {
      technique = new TechniqueDef(null);
    } else if (split.length == 2) {
      String techName = split[1];
      technique = new TechniqueDef(techName);
    } else {
      throw new IOException("Technique statement syntax incorrect");
    }

    for (Statement statement : techStat.getContents()) {
      readTechniqueStatement(statement);
    }

    if (isUseNodes) {
      nodesLoaderDelegate.computeConditions();
      // used for caching later, the shader here is not a file.
      technique.setShaderFile(
          technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100");
    }

    if (shaderName.containsKey(Shader.ShaderType.Vertex)
        && shaderName.containsKey(Shader.ShaderType.Fragment)) {
      technique.setShaderFile(shaderName, shaderLanguage);
    }

    materialDef.addTechniqueDef(technique);
    technique = null;
    shaderLanguage.clear();
    shaderName.clear();
  }
  // <DEFINENAME> [ ":" <PARAMNAME> ]
  private void readDefine(String statement) throws IOException {
    String[] split = statement.split(":");
    if (split.length == 1) {
      String defineName = split[0].trim();
      presetDefines.add(defineName);
    } else if (split.length == 2) {
      String defineName = split[0].trim();
      String paramName = split[1].trim();
      MatParam param = materialDef.getMaterialParam(paramName);
      if (param == null) {
        logger.log(
            Level.WARNING,
            "In technique ''{0}'':\n"
                + "Define ''{1}'' mapped to non-existent"
                + " material parameter ''{2}'', ignoring.",
            new Object[] {technique.getName(), defineName, paramName});
        return;
      }

      VarType paramType = param.getVarType();
      technique.addShaderParamDefine(paramName, paramType, defineName);
    } else {
      throw new IOException("Define syntax incorrect");
    }
  }
 /**
  * reads a list of ShaderNode{} blocks
  *
  * @param statements the list of statements to parse
  * @throws IOException
  */
 protected void readShaderNode(List<Statement> statements) throws IOException {
   for (Statement statement : statements) {
     String line = statement.getLine();
     String[] split = statement.getLine().split("[ \\{]");
     if (line.startsWith("Definition")) {
       ShaderNodeDefinition def = findDefinition(statement);
       shaderNode.setDefinition(def);
       if (def.isNoOutput()) {
         techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(shaderNode.getName());
       }
     } else if (line.startsWith("Condition")) {
       String condition = line.substring(line.lastIndexOf(":") + 1).trim();
       extractCondition(condition, statement);
       shaderNode.setCondition(conditionParser.getFormattedExpression());
     } else if (line.startsWith("InputMapping")) {
       for (Statement statement1 : statement.getContents()) {
         VariableMapping mapping = readInputMapping(statement1);
         techniqueDef
             .getShaderGenerationInfo()
             .getUnusedNodes()
             .remove(mapping.getRightVariable().getNameSpace());
         shaderNode.getInputMapping().add(mapping);
       }
     } else if (line.startsWith("OutputMapping")) {
       for (Statement statement1 : statement.getContents()) {
         VariableMapping mapping = readOutputMapping(statement1);
         techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(shaderNode.getName());
         shaderNode.getOutputMapping().add(mapping);
       }
     } else {
       throw new MatParseException("ShaderNodeDefinition", split[0], statement);
     }
   }
 }
  /**
   * Reads alist of ShaderNodes
   *
   * @param statements the list of statements to read
   * @throws IOException
   */
  public void readNodes(List<Statement> statements) throws IOException {
    if (techniqueDef.getShaderNodes() == null) {
      techniqueDef.setShaderNodes(new ArrayList<ShaderNode>());
      techniqueDef.setShaderGenerationInfo(new ShaderGenerationInfo());
    }

    for (Statement statement : statements) {
      String[] split = statement.getLine().split("[ \\{]");
      if (statement.getLine().startsWith("ShaderNode ")) {
        String name = statement.getLine().substring("ShaderNode".length()).trim();
        if (nodes == null) {
          nodes = new HashMap<String, ShaderNode>();
        }
        if (!nodes.containsKey(name)) {
          shaderNode = new ShaderNode();
          shaderNode.setName(name);
          techniqueDef.getShaderGenerationInfo().getUnusedNodes().add(name);

          readShaderNode(statement.getContents());
          nodes.put(name, shaderNode);
          techniqueDef.getShaderNodes().add(shaderNode);
        } else {
          throw new MatParseException("ShaderNode " + name + " is already defined", statement);
        }

      } else {
        throw new MatParseException("ShaderNode", split[0], statement);
      }
    }
  }
 // <DEFINENAME> [ ":" <PARAMNAME> ]
 private void readDefine(String statement) throws IOException {
   String[] split = statement.split(":");
   if (split.length == 1) {
     // add preset define
     technique.addShaderPresetDefine(split[0].trim(), VarType.Boolean, true);
   } else if (split.length == 2) {
     technique.addShaderParamDefine(split[1].trim(), split[0].trim());
   } else {
     throw new IOException("Define syntax incorrect");
   }
 }
  protected void computeConditions() {

    updateConditions(vertexDeclaredUniforms);
    updateConditions(fragmentDeclaredUniforms);
    updateConditions(varyings);

    for (DeclaredVariable v : varyings.values()) {
      for (ShaderNode sn : techniqueDef.getShaderNodes()) {
        if (sn.getDefinition().getType() == Shader.ShaderType.Vertex) {
          for (VariableMapping mapping : sn.getInputMapping()) {
            if (mapping.getLeftVariable().equals(v.var)) {
              if (mapping.getCondition() == null || v.var.getCondition() == null) {
                mapping.setCondition(v.var.getCondition());
              } else {
                mapping.setCondition(
                    "(" + mapping.getCondition() + ") || (" + v.var.getCondition() + ")");
              }
            }
          }
        }
      }
    }

    updateConditions(attributes);
    //        updateConditions(fragmentGlobals);
    //        vertexGlobal.makeCondition();
  }
 private void readForcedRenderState(List<Statement> renderStates) throws IOException {
   renderState = new RenderState();
   for (Statement statement : renderStates) {
     readRenderStateStatement(statement);
   }
   technique.setForcedRenderState(renderState);
   renderState = null;
 }
 /**
  * finds an UniformBinding representing a WorldParam from the techniqueDef
  *
  * @param varName the name of the WorldParam
  * @return the corresponding UniformBinding to the WorldParam
  */
 protected UniformBinding findWorldParam(String varName) {
   for (UniformBinding worldParam : techniqueDef.getWorldBindings()) {
     if (varName.equals(worldParam.toString())) {
       return worldParam;
     }
   }
   return null;
 }
 // ShadowMode <MODE>
 private void readShadowMode(String statement) throws IOException {
   String[] split = statement.split(whitespacePattern);
   if (split.length != 2) {
     throw new IOException("ShadowMode statement syntax incorrect");
   }
   ShadowMode sm = ShadowMode.valueOf(split[1]);
   technique.setShadowMode(sm);
 }
 // LightMode <SPACE>
 private void readLightSpace(String statement) throws IOException {
   String[] split = statement.split(whitespacePattern);
   if (split.length != 2) {
     throw new IOException("LightSpace statement syntax incorrect");
   }
   TechniqueDef.LightSpace ls = TechniqueDef.LightSpace.valueOf(split[1]);
   technique.setLightSpace(ls);
 }
 /**
  * stores a global output
  *
  * @param var the variable to store
  * @param statement1 the statement being read
  * @throws IOException
  */
 public void storeGlobal(ShaderNodeVariable var, Statement statement1) throws IOException {
   var.setShaderOutput(true);
   if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) {
     ShaderNodeVariable global = techniqueDef.getShaderGenerationInfo().getVertexGlobal();
     if (global != null) {
       //                global.setCondition(mergeConditions(global.getCondition(),
       // var.getCondition(), "||"));
       //                var.setCondition(global.getCondition());
       if (!global.getName().equals(var.getName())) {
         throw new MatParseException(
             "A global output is already defined for the vertex shader: "
                 + global.getName()
                 + ". vertex shader can only have one global output",
             statement1);
       }
     } else {
       techniqueDef.getShaderGenerationInfo().setVertexGlobal(var);
     }
   } else if (shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment) {
     storeVariable(var, techniqueDef.getShaderGenerationInfo().getFragmentGlobals());
   }
 }
  private void readShaderDefinition(
      Shader.ShaderType shaderType, String name, String... languages) {
    shaderNames.put(shaderType, name);

    if (langSize != 0 && langSize != languages.length) {
      throw new AssetLoadException(
          "Technique "
              + technique.getName()
              + " must have the same number of languages for each shader type.");
    }
    langSize = languages.length;
    for (int i = 0; i < languages.length; i++) {
      if (i >= shaderLanguages.size()) {
        shaderLanguages.add(new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class));
      }
      shaderLanguages.get(i).put(shaderType, languages[i]);
    }
  }
 private void readTechniqueStatement(Statement statement) throws IOException {
   String[] split = statement.getLine().split("[ \\{]");
   if (split[0].equals("VertexShader")
       || split[0].equals("FragmentShader")
       || split[0].equals("GeometryShader")
       || split[0].equals("TessellationControlShader")
       || split[0].equals("TessellationEvaluationShader")) {
     readShaderStatement(statement.getLine());
   } else if (split[0].equals("LightMode")) {
     readLightMode(statement.getLine());
   } else if (split[0].equals("LightSpace")) {
     readLightSpace(statement.getLine());
   } else if (split[0].equals("ShadowMode")) {
     readShadowMode(statement.getLine());
   } else if (split[0].equals("WorldParameters")) {
     readWorldParams(statement.getContents());
   } else if (split[0].equals("RenderState")) {
     readRenderState(statement.getContents());
   } else if (split[0].equals("ForcedRenderState")) {
     readForcedRenderState(statement.getContents());
   } else if (split[0].equals("Defines")) {
     readDefines(statement.getContents());
   } else if (split[0].equals("ShaderNodesDefinitions")) {
     initNodesLoader();
     if (isUseNodes) {
       nodesLoaderDelegate.readNodesDefinitions(statement.getContents());
     }
   } else if (split[0].equals("VertexShaderNodes")) {
     initNodesLoader();
     if (isUseNodes) {
       nodesLoaderDelegate.readVertexShaderNodes(statement.getContents());
     }
   } else if (split[0].equals("FragmentShaderNodes")) {
     initNodesLoader();
     if (isUseNodes) {
       nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents());
     }
   } else if (split[0].equals("NoRender")) {
     technique.setNoRender(true);
   } else {
     throw new MatParseException(null, split[0], statement);
   }
 }
  /**
   * store a varying
   *
   * @param node the shaderNode
   * @param variable the variable to store
   */
  public void storeVaryings(ShaderNode node, ShaderNodeVariable variable) {
    variable.setShaderOutput(true);
    if (node.getDefinition().getType() == Shader.ShaderType.Vertex
        && shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment) {
      DeclaredVariable dv = varyings.get(variable.getName());
      if (dv == null) {
        techniqueDef.getShaderGenerationInfo().getVaryings().add(variable);
        dv = new DeclaredVariable(variable);

        varyings.put(variable.getName(), dv);
      }
      dv.addNode(shaderNode);
      // if a variable is declared with the same name as an input and an output and is a varying,
      // set it as a shader output so it's declared as a varying only once.
      for (VariableMapping variableMapping : node.getInputMapping()) {
        if (variableMapping.getLeftVariable().getName().equals(variable.getName())) {
          variableMapping.getLeftVariable().setShaderOutput(true);
        }
      }
    }
  }
 /**
  * Adds a define to the techniquedef
  *
  * @param paramName
  */
 public void addDefine(String paramName, VarType paramType) {
   if (techniqueDef.getShaderParamDefine(paramName) == null) {
     techniqueDef.addShaderParamDefine(paramName, paramType, paramName.toUpperCase());
   }
 }
 private void readWorldParams(List<Statement> worldParams) throws IOException {
   for (Statement statement : worldParams) {
     technique.addWorldParam(statement.getLine());
   }
 }
 /**
  * store an attribute
  *
  * @param var the variable ot store
  */
 public void storeAttribute(ShaderNodeVariable var) {
   storeVariable(var, techniqueDef.getShaderGenerationInfo().getAttributes());
 }
 /**
  * store a fragment uniform
  *
  * @param var the variable ot store
  */
 public void storeFragmentUniform(ShaderNodeVariable var) {
   storeVariable(var, techniqueDef.getShaderGenerationInfo().getFragmentUniforms());
 }
  private void readTechnique(Statement techStat) throws IOException {
    isUseNodes = false;
    String[] split = techStat.getLine().split(whitespacePattern);

    String name;
    if (split.length == 1) {
      name = TechniqueDef.DEFAULT_TECHNIQUE_NAME;
    } else if (split.length == 2) {
      name = split[1];
    } else {
      throw new IOException("Technique statement syntax incorrect");
    }

    String techniqueUniqueName = materialDef.getAssetName() + "@" + name;
    technique = new TechniqueDef(name, techniqueUniqueName.hashCode());

    for (Statement statement : techStat.getContents()) {
      readTechniqueStatement(statement);
    }

    technique.setShaderPrologue(createShaderPrologue(presetDefines));

    switch (technique.getLightMode()) {
      case Disable:
        technique.setLogic(new DefaultTechniqueDefLogic(technique));
        break;
      case MultiPass:
        technique.setLogic(new MultiPassLightingLogic(technique));
        break;
      case SinglePass:
        technique.setLogic(new SinglePassLightingLogic(technique));
        break;
      case StaticPass:
        technique.setLogic(new StaticPassLightingLogic(technique));
        break;
      case SinglePassAndImageBased:
        technique.setLogic(new SinglePassAndImageBasedLightingLogic(technique));
        break;
      default:
        throw new UnsupportedOperationException();
    }

    List<TechniqueDef> techniqueDefs = new ArrayList<>();

    if (isUseNodes) {
      nodesLoaderDelegate.computeConditions();

      // used for caching later, the shader here is not a file.

      // KIRILL 9/19/2015
      // Not sure if this is needed anymore, since shader caching
      // is now done by TechniqueDef.
      technique.setShaderFile(
          technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100");
      techniqueDefs.add(technique);
    } else if (shaderNames.containsKey(Shader.ShaderType.Vertex)
        && shaderNames.containsKey(Shader.ShaderType.Fragment)) {
      if (shaderLanguages.size() > 1) {
        for (int i = 1; i < shaderLanguages.size(); i++) {
          TechniqueDef td = null;
          try {
            td = (TechniqueDef) technique.clone();
          } catch (CloneNotSupportedException e) {
            e.printStackTrace();
          }
          td.setShaderFile(shaderNames, shaderLanguages.get(i));
          techniqueDefs.add(td);
        }
      }
      technique.setShaderFile(shaderNames, shaderLanguages.get(0));
      techniqueDefs.add(technique);

    } else {
      technique = null;
      shaderLanguages.clear();
      shaderNames.clear();
      presetDefines.clear();
      langSize = 0;
      logger.log(Level.WARNING, "Fixed function technique was ignored");
      logger.log(
          Level.WARNING,
          "Fixed function technique ''{0}'' was ignored for material {1}",
          new Object[] {name, key});
      return;
    }

    for (TechniqueDef techniqueDef : techniqueDefs) {
      materialDef.addTechniqueDef(techniqueDef);
    }

    technique = null;
    langSize = 0;
    shaderLanguages.clear();
    shaderNames.clear();
    presetDefines.clear();
  }