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;
}
}