diff --git a/src/main/java/li/cil/oc2/client/gui/TerminalScreen.java b/src/main/java/li/cil/oc2/client/gui/TerminalScreen.java index 16c0db92..e85eee20 100644 --- a/src/main/java/li/cil/oc2/client/gui/TerminalScreen.java +++ b/src/main/java/li/cil/oc2/client/gui/TerminalScreen.java @@ -20,11 +20,11 @@ public final class TerminalScreen extends Screen { private static final ResourceLocation BACKGROUND = new ResourceLocation(API.MOD_ID, "textures/gui/screen/terminal.png"); private static final ResourceLocation BACKGROUND_TERMINAL_FOCUSED = new ResourceLocation(API.MOD_ID, "textures/gui/screen/terminal_focused.png"); private static final int TEXTURE_SIZE = 512; - private static final int SCREEN_WIDTH = 8 + 80 * 9 / 2 + 8; + private static final int SCREEN_WIDTH = 8 + 80 * 8 / 2 + 8; private static final int SCREEN_HEIGHT = 8 + 24 * 16 / 2 + 8; private static final int TERMINAL_AREA_X = 8; private static final int TERMINAL_AREA_Y = 8; - private static final int TERMINAL_AREA_WIDTH = 80 * 9 / 2; + private static final int TERMINAL_AREA_WIDTH = 80 * 8 / 2; private static final int TERMINAL_AREA_HEIGHT = 24 * 16 / 2; private final ComputerTileEntity tileEntity; diff --git a/src/main/java/li/cil/oc2/client/gui/terminal/Terminal.java b/src/main/java/li/cil/oc2/client/gui/terminal/Terminal.java index 66da495b..b3947967 100644 --- a/src/main/java/li/cil/oc2/client/gui/terminal/Terminal.java +++ b/src/main/java/li/cil/oc2/client/gui/terminal/Terminal.java @@ -6,7 +6,6 @@ import com.mojang.blaze3d.systems.RenderSystem; import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue; import li.cil.ceres.api.Serialized; import li.cil.oc2.api.API; -import li.cil.oc2.client.render.font.MonospaceFontRenderer; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.SimpleSound; import net.minecraft.client.renderer.BufferBuilder; @@ -29,18 +28,6 @@ import java.util.concurrent.atomic.AtomicInteger; // Implements a couple of control sequences from here: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences @Serialized public final class Terminal { - private static final int CHAR_WIDTH = 8; - private static final int CHAR_HEIGHT = 16; - - private static final ResourceLocation LOCATION_FONT_TEXTURE = new ResourceLocation(API.MOD_ID, "textures/font/terminus.png"); - private static final int TEXTURE_RESOLUTION = 256; - private static final int TEXTURE_COLUMNS = 16; - private static final int TEXTURE_BOLD_SHIFT = TEXTURE_COLUMNS; // Bold chars are in right half of texture. - private static final float U_SIZE = CHAR_WIDTH / (float) TEXTURE_RESOLUTION; - private static final float V_SIZE = CHAR_HEIGHT / (float) TEXTURE_RESOLUTION; - private static final float U_STEP = CHAR_WIDTH / (float) TEXTURE_RESOLUTION; - private static final float V_STEP = CHAR_HEIGHT / (float) TEXTURE_RESOLUTION; - private static final int TAB_WIDTH = 4; private static final int WIDTH = 80, HEIGHT = 24; @@ -53,27 +40,8 @@ public final class Terminal { private static final int COLOR_CYAN = 6; private static final int COLOR_WHITE = 7; - private static final int[] COLORS = { - 0x010101, // Black - 0xEE3322, // Red - 0x33DD44, // Green - 0xFFCC11, // Yellow - 0x1188EE, // Blue - 0xDD33CC, // Magenta - 0x22CCDD, // Cyan - 0xEEEEEE, // White - }; - - private static final int[] DIM_COLORS = { - 0x010101, // Black - 0x772211, // Red - 0x116622, // Green - 0x886611, // Yellow - 0x115588, // Blue - 0x771177, // Magenta - 0x116677, // Cyan - 0x777777, // White - }; + private static final int CHAR_WIDTH = 8; + private static final int CHAR_HEIGHT = 16; private static final int COLOR_MASK = 0b111; private static final int COLOR_FOREGROUND_SHIFT = 3; @@ -112,29 +80,28 @@ public final class Terminal { // Style info packed into one byte for compact storage private byte style = DEFAULT_STYLE; - private final transient Object[] lines = new Object[HEIGHT]; // Cached vertex buffers for rendering, untyped for server. + // Rendering data for client private final transient AtomicInteger dirty = new AtomicInteger(-1); - private transient Object lastMatrix; // Untyped for server. + private transient Object renderer; public Terminal() { clear(); } public int getWidth() { - return WIDTH * MonospaceFontRenderer.INSTANCE.getCharWidth(); + return WIDTH * CHAR_WIDTH; } public int getHeight() { - return HEIGHT * MonospaceFontRenderer.INSTANCE.getCharHeight(); + return HEIGHT * CHAR_HEIGHT; } @OnlyIn(Dist.CLIENT) public void render(final MatrixStack stack) { - renderBuffer(stack); - - if (System.currentTimeMillis() % 1000 > 500) { - renderCursor(stack); + if (renderer == null) { + renderer = new Renderer(this); } + ((Renderer) renderer).render(dirty, stack); } public synchronized int readInput() { @@ -433,141 +400,6 @@ public final class Terminal { } } - @OnlyIn(Dist.CLIENT) - private void renderBuffer(final MatrixStack stack) { - validateLineCache(stack); - - GlStateManager.depthMask(false); - Minecraft.getInstance().getTextureManager().bindTexture(LOCATION_FONT_TEXTURE); - - final BufferBuilder buffer = Tessellator.getInstance().getBuffer(); - for (final Object line : lines) { - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); - buffer.setVertexState((BufferBuilder.State) line); - buffer.finishDrawing(); - WorldVertexBufferUploader.draw(buffer); - } - - GlStateManager.depthMask(true); - } - - @OnlyIn(Dist.CLIENT) - private void validateLineCache(final MatrixStack stack) { - if (!Objects.equals(lastMatrix, stack.getLast().getMatrix())) { - lastMatrix = stack.getLast().getMatrix(); - dirty.set(-1); - } - - if (dirty.get() == 0) { - return; - } - - final BufferBuilder buffer = Tessellator.getInstance().getBuffer(); - - final int mask = dirty.getAndSet(0); - for (int row = 0; row < lines.length; row++) { - if ((mask & (1 << row)) == 0) { - continue; - } - - stack.push(); - stack.translate(0, row * CHAR_HEIGHT, 0); - final Matrix4f matrix = stack.getLast().getMatrix(); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); - - float tx = 0f; - for (int col = 0, index = row * WIDTH; col < WIDTH; col++, index++) { - final int character = this.buffer[index] & 0xFF; - final byte colors = this.colors[index]; - final byte style = this.styles[index]; - - if ((style & STYLE_HIDDEN_MASK) != 0) continue; - - final int x = character % TEXTURE_COLUMNS + ((style & STYLE_BOLD_MASK) != 0 ? TEXTURE_BOLD_SHIFT : 0); - final int y = character / TEXTURE_COLUMNS; - final float u = x * U_STEP; - final float v = y * V_STEP; - - final int[] palette = (style & STYLE_DIM_MASK) != 0 ? DIM_COLORS : COLORS; - - final int foreground = palette[(colors >> COLOR_FOREGROUND_SHIFT) & COLOR_MASK]; - final int background = palette[colors & COLOR_MASK]; - - final int color = (style & STYLE_INVERT_MASK) != 0 ? background : foreground; - final float r = ((color >> 16) & 0xFF) / 255f; - final float g = ((color >> 8) & 0xFF) / 255f; - final float b = ((color) & 0xFF) / 255f; - - if (isPrintableCharacter((char) character)) { - buffer.pos(matrix, tx, CHAR_HEIGHT, 0).color(r, g, b, 1).tex(u, v + V_SIZE).endVertex(); - buffer.pos(matrix, tx + CHAR_WIDTH, CHAR_HEIGHT, 0).color(r, g, b, 1).tex(u + U_SIZE, v + V_SIZE).endVertex(); - buffer.pos(matrix, tx + CHAR_WIDTH, 0, 0).color(r, g, b, 1).tex(u + U_SIZE, v).endVertex(); - buffer.pos(matrix, tx, 0, 0).color(r, g, b, 1).tex(u, v).endVertex(); - } - - if ((style & STYLE_UNDERLINE_MASK) != 0) { - final float ulu = (TEXTURE_RESOLUTION - 1) / (float) TEXTURE_RESOLUTION; - final float ulv = 1 / (float) TEXTURE_RESOLUTION; - - buffer.pos(matrix, tx, CHAR_HEIGHT - 3, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); - buffer.pos(matrix, tx + CHAR_WIDTH, CHAR_HEIGHT - 3, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); - buffer.pos(matrix, tx + CHAR_WIDTH, CHAR_HEIGHT - 2, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); - buffer.pos(matrix, tx, CHAR_HEIGHT - 2, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); - } - - tx += CHAR_WIDTH; - } - - lines[row] = buffer.getVertexState(); - buffer.finishDrawing(); - buffer.discard(); - - stack.pop(); - } - } - - private static boolean isPrintableCharacter(final char ch) { - return ch == 0 || - (ch > ' ' && ch <= '~') || - ch >= 177; - } - - @OnlyIn(Dist.CLIENT) - private void renderCursor(final MatrixStack stack) { - if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) { - return; - } - - GlStateManager.depthMask(false); - RenderSystem.disableTexture(); - - stack.push(); - stack.translate(x * CHAR_WIDTH, y * CHAR_HEIGHT, 0); - - final Matrix4f matrix = stack.getLast().getMatrix(); - final BufferBuilder buffer = Tessellator.getInstance().getBuffer(); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); - - final int foreground = COLORS[COLOR_WHITE]; - final float r = ((foreground >> 16) & 0xFF) / 255f; - final float g = ((foreground >> 8) & 0xFF) / 255f; - final float b = ((foreground) & 0xFF) / 255f; - - buffer.pos(matrix, 0, CHAR_HEIGHT, 0).color(r, g, b, 1).endVertex(); - buffer.pos(matrix, CHAR_WIDTH, CHAR_HEIGHT, 0).color(r, g, b, 1).endVertex(); - buffer.pos(matrix, CHAR_WIDTH, 0, 0).color(r, g, b, 1).endVertex(); - buffer.pos(matrix, 0, 0, 0).color(r, g, b, 1).endVertex(); - - buffer.finishDrawing(); - WorldVertexBufferUploader.draw(buffer); - - stack.pop(); - - RenderSystem.enableTexture(); - GlStateManager.depthMask(true); - } - private void setCursorPos(final int x, final int y) { this.x = Math.max(0, Math.min(WIDTH - 1, x)); this.y = Math.max(0, Math.min(HEIGHT - 1, y)); @@ -627,7 +459,6 @@ public final class Terminal { System.arraycopy(buffer, WIDTH, buffer, 0, buffer.length - WIDTH); System.arraycopy(colors, WIDTH, colors, 0, colors.length - WIDTH); System.arraycopy(styles, WIDTH, styles, 0, styles.length - WIDTH); - System.arraycopy(lines, 1, lines, 0, lines.length - 1); Arrays.fill(buffer, WIDTH * HEIGHT - WIDTH, WIDTH * HEIGHT, (byte) ' '); Arrays.fill(colors, WIDTH * HEIGHT - WIDTH, WIDTH * HEIGHT, DEFAULT_COLORS); Arrays.fill(styles, WIDTH * HEIGHT - WIDTH, WIDTH * HEIGHT, DEFAULT_STYLE); @@ -635,4 +466,189 @@ public final class Terminal { // Offset is baked into buffers so we must rebuild them all. dirty.set(-1); } + + @OnlyIn(Dist.CLIENT) + private static final class Renderer { + private static final ResourceLocation LOCATION_FONT_TEXTURE = new ResourceLocation(API.MOD_ID, "textures/font/terminus.png"); + private static final int TEXTURE_RESOLUTION = 256; + private static final float ONE_OVER_TEXTURE_RESOLUTION = 1.0f / (float) TEXTURE_RESOLUTION; + private static final int TEXTURE_COLUMNS = 16; + private static final int TEXTURE_BOLD_SHIFT = TEXTURE_COLUMNS; // Bold chars are in right half of texture. + + private static final int[] COLORS = { + 0x010101, // Black + 0xEE3322, // Red + 0x33DD44, // Green + 0xFFCC11, // Yellow + 0x1188EE, // Blue + 0xDD33CC, // Magenta + 0x22CCDD, // Cyan + 0xEEEEEE, // White + }; + + private static final int[] DIM_COLORS = { + 0x010101, // Black + 0x772211, // Red + 0x116622, // Green + 0x886611, // Yellow + 0x115588, // Blue + 0x771177, // Magenta + 0x116677, // Cyan + 0x777777, // White + }; + + private final Terminal terminal; + + private final Object[] lines = new Object[HEIGHT]; // Cached vertex buffers for rendering, untyped for server. + private Object lastMatrix; // Untyped for server. + + public Renderer(final Terminal terminal) { + this.terminal = terminal; + } + + public void render(final AtomicInteger dirty, final MatrixStack stack) { + validateLineCache(dirty, stack); + renderBuffer(); + + if (System.currentTimeMillis() % 1000 > 500) { + renderCursor(stack); + } + } + + private void renderBuffer() { + GlStateManager.depthMask(false); + Minecraft.getInstance().getTextureManager().bindTexture(LOCATION_FONT_TEXTURE); + + final BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + for (final Object line : lines) { + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); + buffer.setVertexState((BufferBuilder.State) line); + buffer.finishDrawing(); + WorldVertexBufferUploader.draw(buffer); + } + + GlStateManager.depthMask(true); + } + + private void validateLineCache(final AtomicInteger dirty, final MatrixStack stack) { + if (!Objects.equals(lastMatrix, stack.getLast().getMatrix())) { + lastMatrix = stack.getLast().getMatrix(); + dirty.set(-1); + } + + if (dirty.get() == 0) { + return; + } + + final BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + + final int mask = dirty.getAndSet(0); + for (int row = 0; row < lines.length; row++) { + if ((mask & (1 << row)) == 0) { + continue; + } + + stack.push(); + stack.translate(0, row * CHAR_HEIGHT, 0); + final Matrix4f matrix = stack.getLast().getMatrix(); + + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX); + + float tx = 0f; + for (int col = 0, index = row * WIDTH; col < WIDTH; col++, index++) { + final int character = terminal.buffer[index] & 0xFF; + final byte colors = terminal.colors[index]; + final byte style = terminal.styles[index]; + + if ((style & STYLE_HIDDEN_MASK) != 0) continue; + + final int x = character % TEXTURE_COLUMNS + ((style & STYLE_BOLD_MASK) != 0 ? TEXTURE_BOLD_SHIFT : 0); + final int y = character / TEXTURE_COLUMNS; + // The +0.5f is to sample the center of our texture pixels. This counteracts small + // floating point inaccuracies in our texture coordinates introduced by varying + // render resolution. And since we use point sampling it doesn't matter where + // exactly inside a pixel we sample. + final float u0 = (x * CHAR_WIDTH + 0.5f) * ONE_OVER_TEXTURE_RESOLUTION; + final float u1 = ((x + 1) * CHAR_WIDTH + 0.5f) * ONE_OVER_TEXTURE_RESOLUTION; + final float v0 = (y * CHAR_HEIGHT + 0.5f) * ONE_OVER_TEXTURE_RESOLUTION; + final float v1 = ((y + 1) * CHAR_HEIGHT + 0.5f) * ONE_OVER_TEXTURE_RESOLUTION; + + final int[] palette = (style & STYLE_DIM_MASK) != 0 ? DIM_COLORS : COLORS; + + final int foreground = palette[(colors >> COLOR_FOREGROUND_SHIFT) & COLOR_MASK]; + final int background = palette[colors & COLOR_MASK]; + + final int color = (style & STYLE_INVERT_MASK) != 0 ? background : foreground; + final float r = ((color >> 16) & 0xFF) / 255f; + final float g = ((color >> 8) & 0xFF) / 255f; + final float b = ((color) & 0xFF) / 255f; + + if (isPrintableCharacter((char) character)) { + buffer.pos(matrix, tx, CHAR_HEIGHT, 0).color(r, g, b, 1).tex(u0, v1).endVertex(); + buffer.pos(matrix, tx + CHAR_WIDTH, CHAR_HEIGHT, 0).color(r, g, b, 1).tex(u1, v1).endVertex(); + buffer.pos(matrix, tx + CHAR_WIDTH, 0, 0).color(r, g, b, 1).tex(u1, v0).endVertex(); + buffer.pos(matrix, tx, 0, 0).color(r, g, b, 1).tex(u0, v0).endVertex(); + } + + if ((style & STYLE_UNDERLINE_MASK) != 0) { + final float ulu = (TEXTURE_RESOLUTION - 1) / (float) TEXTURE_RESOLUTION; + final float ulv = 1 / (float) TEXTURE_RESOLUTION; + + buffer.pos(matrix, tx, CHAR_HEIGHT - 3, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); + buffer.pos(matrix, tx + CHAR_WIDTH, CHAR_HEIGHT - 3, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); + buffer.pos(matrix, tx + CHAR_WIDTH, CHAR_HEIGHT - 2, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); + buffer.pos(matrix, tx, CHAR_HEIGHT - 2, 0).color(r, g, b, 1).tex(ulu, ulv).endVertex(); + } + + tx += CHAR_WIDTH; + } + + lines[row] = buffer.getVertexState(); + buffer.finishDrawing(); + buffer.discard(); + + stack.pop(); + } + } + + private void renderCursor(final MatrixStack stack) { + if (terminal.x < 0 || terminal.x >= WIDTH || terminal.y < 0 || terminal.y >= HEIGHT) { + return; + } + + GlStateManager.depthMask(false); + RenderSystem.disableTexture(); + + stack.push(); + stack.translate(terminal.x * CHAR_WIDTH, terminal.y * CHAR_HEIGHT, 0); + + final Matrix4f matrix = stack.getLast().getMatrix(); + final BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + + final int foreground = COLORS[COLOR_WHITE]; + final float r = ((foreground >> 16) & 0xFF) / 255f; + final float g = ((foreground >> 8) & 0xFF) / 255f; + final float b = ((foreground) & 0xFF) / 255f; + + buffer.pos(matrix, 0, CHAR_HEIGHT, 0).color(r, g, b, 1).endVertex(); + buffer.pos(matrix, CHAR_WIDTH, CHAR_HEIGHT, 0).color(r, g, b, 1).endVertex(); + buffer.pos(matrix, CHAR_WIDTH, 0, 0).color(r, g, b, 1).endVertex(); + buffer.pos(matrix, 0, 0, 0).color(r, g, b, 1).endVertex(); + + buffer.finishDrawing(); + WorldVertexBufferUploader.draw(buffer); + + stack.pop(); + + RenderSystem.enableTexture(); + GlStateManager.depthMask(true); + } + + private static boolean isPrintableCharacter(final char ch) { + return ch == 0 || + (ch > ' ' && ch <= '~') || + ch >= 177; + } + } } diff --git a/src/main/java/li/cil/oc2/client/render/font/FontRenderer.java b/src/main/java/li/cil/oc2/client/render/font/FontRenderer.java deleted file mode 100644 index 1bbdc5c6..00000000 --- a/src/main/java/li/cil/oc2/client/render/font/FontRenderer.java +++ /dev/null @@ -1,42 +0,0 @@ -package li.cil.oc2.client.render.font; - -import net.minecraft.client.renderer.Matrix4f; - -/** - * Base interface for font renderers. - */ -public interface FontRenderer { - /** - * Render the specified string. - * - * @param matrix transformation of the text to draw. - * @param value the string to render. - */ - void drawString(final Matrix4f matrix, final CharSequence value); - - /** - * Render up to the specified amount of characters of the specified string. - *

- * This is intended as a convenience method for clamped-width rendering, - * avoiding additional string operations such as substring. - * - * @param matrix transformation of the text to draw. - * @param value the string to render. - * @param maxChars the maximum number of characters to render. - */ - void drawString(final Matrix4f matrix, final CharSequence value, final int maxChars); - - /** - * Get the width of the characters drawn with the font renderer, in pixels. - * - * @return the width of the drawn characters. - */ - int getCharWidth(); - - /** - * Get the height of the characters drawn with the font renderer, in pixels. - * - * @return the height of the drawn characters. - */ - int getCharHeight(); -} diff --git a/src/main/java/li/cil/oc2/client/render/font/MonospaceFontRenderer.java b/src/main/java/li/cil/oc2/client/render/font/MonospaceFontRenderer.java deleted file mode 100644 index 86a80534..00000000 --- a/src/main/java/li/cil/oc2/client/render/font/MonospaceFontRenderer.java +++ /dev/null @@ -1,102 +0,0 @@ -package li.cil.oc2.client.render.font; - -import com.mojang.blaze3d.platform.GlStateManager; -import it.unimi.dsi.fastutil.ints.Int2IntMap; -import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import li.cil.oc2.api.API; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.Matrix4f; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.opengl.GL11; - -public final class MonospaceFontRenderer implements FontRenderer { - public static final FontRenderer INSTANCE = new MonospaceFontRenderer(); - - private static final ResourceLocation LOCATION_FONT_TEXTURE = new ResourceLocation(API.MOD_ID, "textures/font/monospace.png"); - private static final String CHARS = "\0\u263a\u263b\u2665\u2666\u2663\u2660\u2022\u25d8\u25cb\u25d9\u2642\u2640\u266a\u266b\u263c\u25ba\u25c4\u2195\u203c\u00b6\u00a7\u25ac\u21a8\u2191\u2193\u2192\u2190\u221f\u2194\u25b2\u25bc !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00a2\u00a3\u00a5\u20a7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u2310\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u00df\u0393\u03c0\u03a3\u03c3\u00b5\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u03c6\u03b5\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0"; - private static final int TEXTURE_RESOLUTION = 256; - - private final Int2IntMap CHAR_MAP; - - private final int COLUMNS = TEXTURE_RESOLUTION / getCharWidth(); - private final float U_SIZE = getCharWidth() / (float) TEXTURE_RESOLUTION; - private final float V_SIZE = getCharHeight() / (float) TEXTURE_RESOLUTION; - private final float U_STEP = getCharWidth() / (float) TEXTURE_RESOLUTION; - private final float V_STEP = getCharHeight() / (float) TEXTURE_RESOLUTION; - - private MonospaceFontRenderer() { - CHAR_MAP = new Int2IntOpenHashMap(); - final CharSequence chars = CHARS; - for (int index = 0; index < chars.length(); index++) { - CHAR_MAP.put(chars.charAt(index), index); - } - } - - public void drawString(final Matrix4f matrix, final CharSequence value) { - drawString(matrix, value, value.length()); - } - - public void drawString(final Matrix4f matrix, final CharSequence value, final int maxChars) { - GlStateManager.depthMask(false); - - Minecraft.getInstance().getTextureManager().bindTexture(LOCATION_FONT_TEXTURE); - - final Tessellator tessellator = Tessellator.getInstance(); - final BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - - float tx = 0f; - final int end = Math.min(maxChars, value.length()); - for (int i = 0; i < end; i++) { - final char ch = value.charAt(i); - drawChar(matrix, tx, ch, buffer); - tx += getCharWidth(); - } - - tessellator.draw(); - - GlStateManager.depthMask(true); - } - - // --------------------------------------------------------------------- // - // FontRenderer - - @Override - public int getCharWidth() { - return 9; - } - - @Override - public int getCharHeight() { - return 16; - } - - // --------------------------------------------------------------------- // - - private void drawChar(final Matrix4f matrix, final float x, final char ch, final BufferBuilder buffer) { - if (Character.isWhitespace(ch) || Character.isISOControl(ch)) { - return; - } - final int index = getCharIndex(ch); - - final int column = index % COLUMNS; - final int row = index / COLUMNS; - final float u = column * U_STEP; - final float v = row * V_STEP; - - buffer.pos(matrix, x, getCharHeight(), 0).tex(u, v + V_SIZE).endVertex(); - buffer.pos(matrix, x + getCharWidth(), getCharHeight(), 0).tex(u + U_SIZE, v + V_SIZE).endVertex(); - buffer.pos(matrix, x + getCharWidth(), 0, 0).tex(u + U_SIZE, v).endVertex(); - buffer.pos(matrix, x, 0, 0).tex(u, v).endVertex(); - } - - private int getCharIndex(final char ch) { - if (!CHAR_MAP.containsKey(ch)) { - return CHAR_MAP.get('?'); - } - return CHAR_MAP.get(ch); - } -} diff --git a/src/main/java/li/cil/oc2/client/render/font/package-info.java b/src/main/java/li/cil/oc2/client/render/font/package-info.java deleted file mode 100644 index 215dd2d2..00000000 --- a/src/main/java/li/cil/oc2/client/render/font/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -package li.cil.oc2.client.render.font; - -import mcp.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/resources/assets/oc2/textures/font/OFL.TXT b/src/main/resources/assets/oc2/textures/font/OFL.TXT new file mode 100644 index 00000000..38cbd33e --- /dev/null +++ b/src/main/resources/assets/oc2/textures/font/OFL.TXT @@ -0,0 +1,94 @@ +Copyright (c) 2019 Dimitar Toshkov Zhekov, +with Reserved Font Name "Terminus Font". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/main/resources/assets/oc2/textures/font/monospace.png b/src/main/resources/assets/oc2/textures/font/monospace.png deleted file mode 100644 index 31ef2e50..00000000 Binary files a/src/main/resources/assets/oc2/textures/font/monospace.png and /dev/null differ diff --git a/src/main/resources/assets/oc2/textures/gui/screen/terminal.png b/src/main/resources/assets/oc2/textures/gui/screen/terminal.png index d08c6791..eeb4f2cd 100644 Binary files a/src/main/resources/assets/oc2/textures/gui/screen/terminal.png and b/src/main/resources/assets/oc2/textures/gui/screen/terminal.png differ diff --git a/src/main/resources/assets/oc2/textures/gui/screen/terminal_focused.png b/src/main/resources/assets/oc2/textures/gui/screen/terminal_focused.png index d590f576..cffc6334 100644 Binary files a/src/main/resources/assets/oc2/textures/gui/screen/terminal_focused.png and b/src/main/resources/assets/oc2/textures/gui/screen/terminal_focused.png differ