package codechicken.lib.render;
import codechicken.lib.render.CCRenderState.IVertexOperation;
import codechicken.lib.render.CCRenderState.VertexAttribute;
import java.util.ArrayList;
public class CCRenderPipeline
{
public class PipelineBuilder
{
public PipelineBuilder add(IVertexOperation op) {
ops.add(op);
return this;
}
public PipelineBuilder add(IVertexOperation... ops) {
for(int i = 0; i < ops.length; i++)
CCRenderPipeline.this.ops.add(ops[i]);
return this;
}
public void build() {
rebuild();
}
public void render() {
rebuild();
CCRenderState.render();
}
}
private class PipelineNode
{
public ArrayList<PipelineNode> deps = new ArrayList<PipelineNode>();
public IVertexOperation op;
public void add() {
if(op == null)
return;
for(int i = 0; i < deps.size(); i++)
deps.get(i).add();
deps.clear();
sorted.add(op);
op = null;
}
}
private ArrayList<VertexAttribute> attribs = new ArrayList<VertexAttribute>();
private ArrayList<IVertexOperation> ops = new ArrayList<IVertexOperation>();
private ArrayList<PipelineNode> nodes = new ArrayList<PipelineNode>();
private ArrayList<IVertexOperation> sorted = new ArrayList<IVertexOperation>();
private PipelineNode loading;
private PipelineBuilder builder = new PipelineBuilder();
public void setPipeline(IVertexOperation... ops) {
this.ops.clear();
for(int i = 0; i < ops.length; i++)
this.ops.add(ops[i]);
rebuild();
}
public void reset() {
ops.clear();
unbuild();
}
private void unbuild() {
for(int i = 0; i < attribs.size(); i++)
attribs.get(i).active = false;
attribs.clear();
sorted.clear();
}
public void rebuild() {
if(ops.isEmpty() || CCRenderState.model == null)
return;
//ensure enough nodes for all ops
while(nodes.size() < CCRenderState.operationCount())
nodes.add(new PipelineNode());
unbuild();
if(CCRenderState.useNormals)
addAttribute(CCRenderState.normalAttrib);
if(CCRenderState.useColour)
addAttribute(CCRenderState.colourAttrib);
if(CCRenderState.computeLighting)
addAttribute(CCRenderState.lightingAttrib);
for(int i = 0; i < ops.size(); i++) {
IVertexOperation op = ops.get(i);
loading = nodes.get(op.operationID());
boolean loaded = op.load();
if(loaded)
loading.op = op;
if(op instanceof VertexAttribute)
if(loaded)
attribs.add((VertexAttribute)op);
else
((VertexAttribute)op).active = false;
}
for(int i = 0; i < nodes.size(); i++)
nodes.get(i).add();
}
public void addRequirement(int opRef) {
loading.deps.add(nodes.get(opRef));
}
public void addDependency(VertexAttribute attrib) {
loading.deps.add(nodes.get(attrib.operationID()));
addAttribute(attrib);
}
public void addAttribute(VertexAttribute attrib) {
if(!attrib.active) {
ops.add(attrib);
attrib.active = true;
}
}
public void operate() {
for(int i = 0; i < sorted.size(); i++)
sorted.get(i).operate();
}
public PipelineBuilder builder() {
ops.clear();
return builder;
}
}