package com.someluigi.slperiph.ccportable.gfx;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import net.minecraft.client.renderer.RenderEngine;
import net.minecraft.client.renderer.Tessellator;
import org.lwjgl.opengl.GL11;
import com.someluigi.slperiph.ccportable.shared.Terminal;
public class TerminalRenderer {
public static boolean getBlink(){
return System.currentTimeMillis() % 1000 < 500;
}
protected RenderEngine render;
protected Tessellator buff;
public static final int FONT_WIDTH = 6;
public static final int FONT_HEIGHT = 8;
public static int TERM_PADDING_X = 3;
public static int TERM_PADDING_Y = 4;
protected static double U = 1 / 16d;
protected static double W = 6 / 128d;
protected int[] charWidth = new int[256];
protected int[] colors = new int[]{
0x1E1B1B, 0xB3312C, 0x3B511A, 0x51301A,
0x253192, 0x7B2FBE, 0x287697, 0x999999,
0x434343, 0xD88198, 0x41CD34, 0xDEDE6C,
0x6689D3, 0xC354CD, 0xEB8844, 0xF0F0F0
};
protected int charTexture = -1;
public TerminalRenderer(RenderEngine engine, Tessellator buff) {
this.render = engine;
this.buff = buff;
BufferedImage image;
try {
image = ImageIO.read(getClass().getResourceAsStream(
"/font/default.png"));
} catch (IOException e) {
throw new RuntimeException();
}
int w = image.getWidth();
int h = image.getHeight();
int[] rgbData = new int[w * h];
image.getRGB(0, 0, w, h, rgbData, 0, w);
for (int chrIndex = 0; chrIndex < 256; chrIndex++) {
int x = chrIndex % 16;
int y = chrIndex / 16;
int wide = 7;
while (wide >= 0) {
int baseIndex = x * 8 + wide;
boolean isEmpty = true;
for (int lY = 0; lY < 8; lY++) {
int index = (y * 8 + lY) * w;
if ((rgbData[baseIndex + index] & 0xFF) > 0) {
isEmpty = false;
break;
}
}
if (!isEmpty)
break;
wide--;
}
if (chrIndex == 32) // Space is 2 wide
wide = 2;
charWidth[chrIndex] = (wide + 2);
}
// Fix control chars
for (int index = 0xB0; index < 0xDF; index++)
charWidth[index] = FONT_WIDTH;
// Setup the texture
charTexture = engine.allocateAndSetupTexture(image);
}
protected void setColor( int code ){
int color = colors[code % 16];
buff.setColorOpaque(color >> 16 & 255, color >> 8 & 255, color & 255);
}
protected void renderCharAt(int xPos, int yPos, char chr) {
if (chr == 32)
return;
double u0 = (chr % 16) * U;
double v0 = (chr >> 4) * U;
if (0xB0 < chr)
u0 += 1 / 128d;
buff.addVertexWithUV(xPos, yPos, 0, u0, v0);
buff.addVertexWithUV(xPos, yPos + FONT_HEIGHT, 0, u0, v0 + U);
buff.addVertexWithUV(xPos + FONT_WIDTH, yPos + FONT_HEIGHT, 0, u0 + W, v0 + U);
buff.addVertexWithUV(xPos + FONT_WIDTH, yPos, 0, u0 + W, v0);
}
public void renderSingleChar( int x, int y, char chr ){
if (chr == 32)
return;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, charTexture);
buff.startDrawingQuads();
renderCharAt(x, y, chr);
buff.draw();
}
public void renderText(int x, int y, char[] line) {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, charTexture);
buff.startDrawingQuads();
for (int index = 0; index < line.length; index++) {
char chr = line[index];
if ( chr > 255 )
chr = '?';
int wide = charWidth[chr];
int off = (FONT_WIDTH - wide) / 2;
renderCharAt(x + off, y, chr);
x += FONT_WIDTH;
}
buff.draw();
}
public void renderTextColor( int x, int y, char[] line, byte[] lineColor, int hOff ){
int anchorX = x -3;
//Render background
GL11.glDisable( GL11.GL_TEXTURE_2D );
buff.startDrawingQuads();
int cellW = FONT_WIDTH;
int cellH = FONT_HEIGHT +1 +hOff;
for (int index = 0; index < line.length; index++){
int color = (lineColor[index] >> 4) & 15;
color = colors[color];
if ( index == 0 || index == line.length -1 )
cellW = FONT_WIDTH +3;
else
cellW = FONT_WIDTH;
buff.setColorOpaque_I(color);
buff.addVertex(anchorX, y, 0);
buff.addVertex(anchorX, y +cellH, 0);
buff.addVertex(anchorX +cellW, y +cellH, 0);
buff.addVertex(anchorX +cellW, y, 0);
anchorX += cellW;
}
buff.draw();
//Render characters
GL11.glEnable( GL11.GL_TEXTURE_2D );
GL11.glBindTexture(GL11.GL_TEXTURE_2D, charTexture);
buff.startDrawingQuads();
anchorX = x;
for (int index = 0; index < line.length; index++) {
char chr = line[index];
if ( chr > 255 )
chr = '?';
int wide = charWidth[chr];
int off = (FONT_WIDTH - wide) / 2;
buff.setColorOpaque_I( colors[ lineColor[index] & 15 ] );
renderCharAt(anchorX + off, y, chr);
anchorX += FONT_WIDTH;
}
buff.draw();
}
public void renderTerminal( Terminal term, int x, int y ){
GL11.glColor3f(1, 1, 1);
int anchorX = x;
int anchorY = y;
byte[][] codes = term.charColors;
char[][] chars = term.chars;
//Draw background
if ( term.isColorSupported ){
GL11.glDisable( GL11.GL_TEXTURE_2D );
buff.startDrawingQuads();
int cellH = FONT_HEIGHT +1;
int len = codes.length -1;
for ( int lineID = 0; lineID <= len; lineID++ ){
if ( lineID == 0 || lineID == len ){
cellH = FONT_HEIGHT +1 + TERM_PADDING_Y;
} else {
cellH = FONT_HEIGHT +1;
}
drawBackground(x, anchorY, codes[lineID], cellH);
anchorY += cellH;
}
buff.draw();
}
//Render characters
GL11.glEnable( GL11.GL_TEXTURE_2D );
GL11.glBindTexture(GL11.GL_TEXTURE_2D, charTexture);
anchorX = x +TERM_PADDING_X;
anchorY = y +TERM_PADDING_Y;
buff.startDrawingQuads();
for ( int lineID = 0; lineID < chars.length; lineID++ ){
char[] line = chars[lineID];
byte[] lineColor = term.isColorSupported ? codes[lineID] : null;
anchorX = x +TERM_PADDING_X;
for ( int index = 0; index < line.length; index++ ){
char chr = line[index];
if ( chr > 255 )
chr = '?';
int wide = charWidth[chr];
int off = (FONT_WIDTH - wide) / 2;
if ( lineColor != null )
buff.setColorOpaque_I( colors[ lineColor[index] & 15 ] );
renderCharAt(anchorX + off, anchorY, chr);
anchorX += FONT_WIDTH;
}
anchorY += FONT_HEIGHT +1;
}
buff.draw();
//Draw the cursor
GL11.glColor3f(1, 1, 1);
if ( term.cursorBlink && getBlink() ){
int cX = term.getCursorX();
int cY = term.getCursorY();
//Don't draw an out of bounds cursor
if ( cX < 0 || term.w < cX || cY < 0 || term.h < cY )
return;
anchorX = x +TERM_PADDING_X + cX *TerminalRenderer.FONT_WIDTH;
anchorY = y +TERM_PADDING_Y + cY *9;
renderSingleChar(anchorX, anchorY, '_');
}
}
protected void drawBackground( int anchorX, int anchorY, byte[] lineColor, int cellH ){
int cellW = FONT_WIDTH +1;
int len = lineColor.length -1;
for ( int index = 0; index <= len; index++ ){
int color = (lineColor[index] >> 4) & 15;
color = colors[color];
if ( index == 0 || index == len ){
cellW = FONT_WIDTH +TERM_PADDING_X;
} else {
cellW = FONT_WIDTH;
}
buff.setColorOpaque_I(color);
buff.addVertex(anchorX, anchorY, 0);
buff.addVertex(anchorX, anchorY +cellH, 0);
buff.addVertex(anchorX +cellW, anchorY +cellH, 0);
buff.addVertex(anchorX +cellW, anchorY, 0);
anchorX += cellW;
}
}
}