package openblocks.client.renderer.tileentity;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.common.MinecraftForge;
import openblocks.Config;
import openblocks.OpenBlocks.Blocks;
import openblocks.common.tileentity.TileEntityImaginary;
import openblocks.common.tileentity.TileEntityImaginary.ICollisionData;
import openblocks.common.tileentity.TileEntityImaginary.PanelData;
import openblocks.common.tileentity.TileEntityImaginary.Property;
import openblocks.common.tileentity.TileEntityImaginary.StairsData;
import org.lwjgl.opengl.GL11;
public class TileEntityImaginaryRenderer extends TileEntitySpecialRenderer {
private abstract static class ElementDisplay {
public Integer pencilDisplayList;
public Integer crayonDisplayList;
@Override
public void finalize() {
clear();
}
private void clear() {
if (crayonDisplayList != null) {
GL11.glDeleteLists(crayonDisplayList, 1);
crayonDisplayList = null;
}
if (pencilDisplayList != null) {
GL11.glDeleteLists(pencilDisplayList, 1);
pencilDisplayList = null;
}
}
public Integer getDisplayList(boolean isPencil) {
return isPencil? getPencilDisplayList() : getCrayonDisplayList();
}
private Integer getCrayonDisplayList() {
if (crayonDisplayList == null) crayonDisplayList = compileList(getCrayonTexture());
return crayonDisplayList;
}
private Integer getPencilDisplayList() {
if (pencilDisplayList == null) pencilDisplayList = compileList(getPencilTexture());
return pencilDisplayList;
}
private int compileList(IIcon icon) {
int displayList = GL11.glGenLists(1);
GL11.glNewList(displayList, GL11.GL_COMPILE);
GL11.glAlphaFunc(GL11.GL_GREATER, 0.0F);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
Tessellator tes = new Tessellator();
tes.startDrawingQuads();
addQuads(tes, icon);
tes.draw();
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_BLEND);
GL11.glAlphaFunc(GL11.GL_GREATER, 0.1F);
GL11.glEndList();
return displayList;
}
protected abstract void addQuads(Tessellator tes, IIcon icon);
protected abstract IIcon getPencilTexture();
protected abstract IIcon getCrayonTexture();
}
private final static ElementDisplay blockDisplay = new ElementDisplay() {
@Override
public void addQuads(Tessellator tes, IIcon icon) {
final double delta0 = 0.001;
final double delta1 = 1 - 0.001;
tes.addVertexWithUV(0, 0, delta0, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(0, 1, delta0, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(1, 1, delta0, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(1, 0, delta0, icon.getMaxU(), icon.getMinV());
tes.addVertexWithUV(0, 0, delta1, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(1, 0, delta1, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(1, 1, delta1, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(0, 1, delta1, icon.getMaxU(), icon.getMinV());
tes.addVertexWithUV(delta1, 0, 0, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(delta1, 1, 0, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(delta1, 1, 1, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(delta1, 0, 1, icon.getMaxU(), icon.getMinV());
tes.addVertexWithUV(delta0, 0, 0, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(delta0, 0, 1, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(delta0, 1, 1, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(delta0, 1, 0, icon.getMaxU(), icon.getMinV());
tes.addVertexWithUV(0, delta1, 0, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(0, delta1, 1, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(1, delta1, 1, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(1, delta1, 0, icon.getMaxU(), icon.getMinV());
tes.addVertexWithUV(0, delta0, 0, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(1, delta0, 0, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(1, delta0, 1, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(0, delta0, 1, icon.getMaxU(), icon.getMinV());
}
@Override
protected IIcon getPencilTexture() {
return Blocks.imaginary.texturePencilBlock;
}
@Override
protected IIcon getCrayonTexture() {
return Blocks.imaginary.textureCrayonBlock;
}
};
private final static ElementDisplay panelDisplay = new ElementDisplay() {
@Override
public void addQuads(Tessellator tes, IIcon icon) {
tes.addVertexWithUV(0, 0, 0, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(0, 0, 1, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(1, 0, 1, icon.getMaxU(), icon.getMaxV());
tes.addVertexWithUV(1, 0, 0, icon.getMaxU(), icon.getMinV());
}
@Override
protected IIcon getPencilTexture() {
return Blocks.imaginary.texturePencilPanel;
}
@Override
protected IIcon getCrayonTexture() {
return Blocks.imaginary.textureCrayonPanel;
}
};
private final static ElementDisplay halfPanelDisplay = new ElementDisplay() {
@Override
public void addQuads(Tessellator tes, IIcon icon) {
tes.addVertexWithUV(-0.5, 0, -0.5, icon.getMinU(), icon.getMaxV());
tes.addVertexWithUV(-0.5, 0, +0.5, icon.getMinU(), icon.getMinV());
tes.addVertexWithUV(+0.5, 0, +0.5, icon.getMaxU(), icon.getMinV());
tes.addVertexWithUV(+0.5, 0, -0.5, icon.getMaxU(), icon.getMaxV());
}
@Override
protected IIcon getPencilTexture() {
return Blocks.imaginary.texturePencilHalfPanel;
}
@Override
protected IIcon getCrayonTexture() {
return Blocks.imaginary.textureCrayonHalfPanel;
}
};
public TileEntityImaginaryRenderer() {
MinecraftForge.EVENT_BUS.register(this);
}
@Override
public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float partialTicks) {
final TileEntityImaginary te = (TileEntityImaginary)tileentity;
boolean isVisible = te.is(Property.VISIBLE);
if (isVisible && te.visibility < 1) te.visibility = Math.min(te.visibility
+ Config.imaginaryFadingSpeed, 1);
else if (!isVisible && te.visibility > 0) te.visibility = Math.max(te.visibility
- Config.imaginaryFadingSpeed, 0);
if (te.visibility <= 0) return;
bindTexture(TextureMap.locationBlocksTexture);
if (!te.isPencil()) {
byte red = (byte)(te.color >> 16);
byte green = (byte)(te.color >> 8);
byte blue = (byte)(te.color >> 0);
GL11.glColor4ub(red, green, blue, (byte)(255 * te.visibility));
} else {
GL11.glColor4ub((byte)255, (byte)255, (byte)255, (byte)(255 * te.visibility));
}
GL11.glPushMatrix();
GL11.glTranslated(x, y, z);
final ICollisionData data = te.collisionData;
if (data instanceof PanelData) {
PanelData pd = (PanelData)data;
GL11.glTranslated(0, pd.height, 0);
int displayList = panelDisplay.getDisplayList(te.isPencil());
GL11.glCallList(displayList);
} else if (data instanceof StairsData) {
StairsData sd = (StairsData)data;
GL11.glTranslated(0.5, 0, 0.5);
switch (sd.orientation) {
case NORTH:
break;
case EAST:
GL11.glRotatef(-90, 0, 1, 0);
break;
case SOUTH:
GL11.glRotatef(180, 0, 1, 0);
break;
case WEST:
GL11.glRotatef(90, 0, 1, 0);
break;
default:
break;
}
int displayList = halfPanelDisplay.getDisplayList(te.isPencil());
GL11.glTranslated(0, sd.lowerPanelHeight, 0);
GL11.glCallList(displayList);
GL11.glTranslated(0, sd.upperPanelHeight - sd.lowerPanelHeight, -0.5);
GL11.glCallList(displayList);
} else {
int displayList = blockDisplay.getDisplayList(te.isPencil());
GL11.glCallList(displayList);
}
GL11.glPopMatrix();
}
/**
* @param evt
*/
@SubscribeEvent
public void onTextureReload(TextureStitchEvent.Pre evt) {
blockDisplay.clear();
panelDisplay.clear();
halfPanelDisplay.clear();
}
}