|
@@ -0,0 +1,198 @@
|
|
|
+package me.hammerle.snuviengine.api;
|
|
|
+
|
|
|
+import java.nio.FloatBuffer;
|
|
|
+import me.hammerle.snuviengine.util.Color;
|
|
|
+import org.lwjgl.BufferUtils;
|
|
|
+import static org.lwjgl.opengl.GL11.*;
|
|
|
+import static org.lwjgl.opengl.GL15.*;
|
|
|
+import static org.lwjgl.opengl.GL20.*;
|
|
|
+import static org.lwjgl.opengl.GL30.*;
|
|
|
+
|
|
|
+public class FontRenderer
|
|
|
+{
|
|
|
+ private static final int MAX_LENGTH = 256;
|
|
|
+ private static final float[] COLORS = new float[128];
|
|
|
+ private static final float[] DARK_COLORS = new float[128];
|
|
|
+
|
|
|
+ static
|
|
|
+ {
|
|
|
+ COLORS['0'] = Float.intBitsToFloat(Color.get(0, 0, 0));
|
|
|
+ COLORS['1'] = Float.intBitsToFloat(Color.get(0, 0, 170));
|
|
|
+ COLORS['2'] = Float.intBitsToFloat(Color.get(0, 170, 0));
|
|
|
+ COLORS['3'] = Float.intBitsToFloat(Color.get(0, 170, 170));
|
|
|
+ COLORS['4'] = Float.intBitsToFloat(Color.get(170, 0, 0));
|
|
|
+ COLORS['5'] = Float.intBitsToFloat(Color.get(170, 0, 170));
|
|
|
+ COLORS['6'] = Float.intBitsToFloat(Color.get(255, 170, 0));
|
|
|
+ COLORS['7'] = Float.intBitsToFloat(Color.get(170, 170, 170));
|
|
|
+ COLORS['8'] = Float.intBitsToFloat(Color.get(85, 85, 85));
|
|
|
+ COLORS['9'] = Float.intBitsToFloat(Color.get(85, 85, 255));
|
|
|
+ COLORS['a'] = Float.intBitsToFloat(Color.get(85, 255, 85));
|
|
|
+ COLORS['b'] = Float.intBitsToFloat(Color.get(85, 255, 255));
|
|
|
+ COLORS['c'] = Float.intBitsToFloat(Color.get(255, 85, 85));
|
|
|
+ COLORS['d'] = Float.intBitsToFloat(Color.get(255, 85, 255));
|
|
|
+ COLORS['e'] = Float.intBitsToFloat(Color.get(255, 255, 85));
|
|
|
+ COLORS['f'] = Float.intBitsToFloat(Color.get(255, 255, 255));
|
|
|
+
|
|
|
+ float factor = 0.5f;
|
|
|
+ DARK_COLORS['0'] = Float.intBitsToFloat(Color.darken(Color.get(0, 0, 0), factor));
|
|
|
+ DARK_COLORS['1'] = Float.intBitsToFloat(Color.darken(Color.get(0, 0, 170), factor));
|
|
|
+ DARK_COLORS['2'] = Float.intBitsToFloat(Color.darken(Color.get(0, 170, 0), factor));
|
|
|
+ DARK_COLORS['3'] = Float.intBitsToFloat(Color.darken(Color.get(0, 170, 170), factor));
|
|
|
+ DARK_COLORS['4'] = Float.intBitsToFloat(Color.darken(Color.get(170, 0, 0), factor));
|
|
|
+ DARK_COLORS['5'] = Float.intBitsToFloat(Color.darken(Color.get(170, 0, 170), factor));
|
|
|
+ DARK_COLORS['6'] = Float.intBitsToFloat(Color.darken(Color.get(255, 170, 0), factor));
|
|
|
+ DARK_COLORS['7'] = Float.intBitsToFloat(Color.darken(Color.get(170, 170, 170), factor));
|
|
|
+ DARK_COLORS['8'] = Float.intBitsToFloat(Color.darken(Color.get(85, 85, 85), factor));
|
|
|
+ DARK_COLORS['9'] = Float.intBitsToFloat(Color.darken(Color.get(85, 85, 255), factor));
|
|
|
+ DARK_COLORS['a'] = Float.intBitsToFloat(Color.darken(Color.get(85, 255, 85), factor));
|
|
|
+ DARK_COLORS['b'] = Float.intBitsToFloat(Color.darken(Color.get(85, 255, 255), factor));
|
|
|
+ DARK_COLORS['c'] = Float.intBitsToFloat(Color.darken(Color.get(255, 85, 85), factor));
|
|
|
+ DARK_COLORS['d'] = Float.intBitsToFloat(Color.darken(Color.get(255, 85, 255), factor));
|
|
|
+ DARK_COLORS['e'] = Float.intBitsToFloat(Color.darken(Color.get(255, 255, 85), factor));
|
|
|
+ DARK_COLORS['f'] = Float.intBitsToFloat(Color.darken(Color.get(255, 255, 255), factor));
|
|
|
+ }
|
|
|
+
|
|
|
+ private int vao;
|
|
|
+ private int vbo;
|
|
|
+
|
|
|
+ private float color;
|
|
|
+
|
|
|
+ // number of floats per rectangle * layers (normal, shadow) * MAX_LENGTH
|
|
|
+ private FloatBuffer buffer = BufferUtils.createFloatBuffer(30 * 2 * MAX_LENGTH);
|
|
|
+
|
|
|
+ public FontRenderer()
|
|
|
+ {
|
|
|
+ Shader.addTask(() ->
|
|
|
+ {
|
|
|
+ vao = glGenVertexArrays();
|
|
|
+ vbo = glGenBuffers();
|
|
|
+
|
|
|
+ glBindVertexArray(vao);
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
|
+
|
|
|
+ glEnableVertexAttribArray(0);
|
|
|
+ glVertexAttribPointer(0, 2, GL_FLOAT, false, 20, 0);
|
|
|
+
|
|
|
+ glEnableVertexAttribArray(1);
|
|
|
+ glVertexAttribPointer(1, 2, GL_FLOAT, false, 20, 8);
|
|
|
+
|
|
|
+ glEnableVertexAttribArray(2);
|
|
|
+ glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, true, 20, 16);
|
|
|
+
|
|
|
+ glBufferData(GL_ARRAY_BUFFER, buffer, GL_STREAM_DRAW);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addRectangle(float minX, float minY, float maxX, float maxY, float tMinX, float tMinY, float tMaxX, float tMaxY)
|
|
|
+ {
|
|
|
+ buffer.put(minX);
|
|
|
+ buffer.put(maxY);
|
|
|
+ buffer.put(tMinX);
|
|
|
+ buffer.put(tMaxY);
|
|
|
+ buffer.put(color);
|
|
|
+
|
|
|
+ buffer.put(minX);
|
|
|
+ buffer.put(minY);
|
|
|
+ buffer.put(tMinX);
|
|
|
+ buffer.put(tMinY);
|
|
|
+ buffer.put(color);
|
|
|
+
|
|
|
+ buffer.put(maxX);
|
|
|
+ buffer.put(maxY);
|
|
|
+ buffer.put(tMaxX);
|
|
|
+ buffer.put(tMaxY);
|
|
|
+ buffer.put(color);
|
|
|
+
|
|
|
+ buffer.put(maxX);
|
|
|
+ buffer.put(maxY);
|
|
|
+ buffer.put(tMaxX);
|
|
|
+ buffer.put(tMaxY);
|
|
|
+ buffer.put(color);
|
|
|
+
|
|
|
+ buffer.put(minX);
|
|
|
+ buffer.put(minY);
|
|
|
+ buffer.put(tMinX);
|
|
|
+ buffer.put(tMinY);
|
|
|
+ buffer.put(color);
|
|
|
+
|
|
|
+ buffer.put(maxX);
|
|
|
+ buffer.put(minY);
|
|
|
+ buffer.put(tMaxX);
|
|
|
+ buffer.put(tMinY);
|
|
|
+ buffer.put(color);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void drawString(float x, float y, boolean shadow, String s)
|
|
|
+ {
|
|
|
+ int l = Math.min(s.length(), MAX_LENGTH);
|
|
|
+
|
|
|
+ if(shadow)
|
|
|
+ {
|
|
|
+ color = DARK_COLORS['f'];
|
|
|
+ float oldX = x;
|
|
|
+ float oldY = y;
|
|
|
+
|
|
|
+ for(int pos = 0; pos < l; pos++)
|
|
|
+ {
|
|
|
+ char c = s.charAt(pos);
|
|
|
+ if(c == '&')
|
|
|
+ {
|
|
|
+ pos++;
|
|
|
+ int index = s.charAt(pos);
|
|
|
+ if(index >= 0 && index <= COLORS.length)
|
|
|
+ {
|
|
|
+ color = DARK_COLORS[s.charAt(pos)];
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ float tMinX = (c & 0xF) / 16.0f;
|
|
|
+ float tMinY = 0.9375f - ((c >> 4) / 16.0f);
|
|
|
+ addRectangle(x + 1, y - 1, x + 17, y + 15, tMinX, tMinY, tMinX + 0.0625f, tMinY + 0.0625f);
|
|
|
+ x += 16;
|
|
|
+ }
|
|
|
+
|
|
|
+ x = oldX;
|
|
|
+ y = oldY;
|
|
|
+ }
|
|
|
+
|
|
|
+ color = COLORS['f'];
|
|
|
+ for(int pos = 0; pos < l; pos++)
|
|
|
+ {
|
|
|
+ char c = s.charAt(pos);
|
|
|
+ if(c == '&')
|
|
|
+ {
|
|
|
+ pos++;
|
|
|
+ int index = s.charAt(pos);
|
|
|
+ if(index >= 0 && index <= COLORS.length)
|
|
|
+ {
|
|
|
+ color = COLORS[s.charAt(pos)];
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ float tMinX = (c & 0xF) / 16.0f;
|
|
|
+ float tMinY = 0.9375f - ((c >> 4) / 16.0f);
|
|
|
+ addRectangle(x, y, x + 16, y + 16, tMinX, tMinY, tMinX + 0.0625f, tMinY + 0.0625f);
|
|
|
+ x += 16;
|
|
|
+ }
|
|
|
+
|
|
|
+ buffer.flip();
|
|
|
+
|
|
|
+ glBindVertexArray(vao);
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
|
+ glBufferSubData(GL_ARRAY_BUFFER, 0, buffer);
|
|
|
+ glDrawArrays(GL_TRIANGLES, 0, buffer.limit() / 5);
|
|
|
+
|
|
|
+ buffer.limit(buffer.capacity());
|
|
|
+ }
|
|
|
+
|
|
|
+ public void delete()
|
|
|
+ {
|
|
|
+ buffer = null;
|
|
|
+ glDeleteVertexArrays(vao);
|
|
|
+ glDeleteBuffers(vbo);
|
|
|
+ vao = -1;
|
|
|
+ vbo = -1;
|
|
|
+ }
|
|
|
+}
|