started implementing virtual terminal

This commit is contained in:
DaniTheSkunk 2022-10-09 03:36:12 +00:00
parent 94d657d7be
commit 1f4d3f4d83
7 changed files with 243 additions and 10 deletions

View File

@ -1,5 +1,6 @@
<component name="ProjectCodeStyleConfiguration"> <component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="ENABLE_SECOND_REFORMAT" value="true" />
<codeStyleSettings language="JAVA"> <codeStyleSettings language="JAVA">
<option name="SPACE_BEFORE_IF_PARENTHESES" value="false" /> <option name="SPACE_BEFORE_IF_PARENTHESES" value="false" />
<option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" /> <option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" />

View File

@ -1,5 +1,8 @@
import com.danitheskunk.skunkworks.*; import com.danitheskunk.skunkworks.*;
import com.danitheskunk.skunkworks.gfx.Color; import com.danitheskunk.skunkworks.gfx.Color;
import com.danitheskunk.skunkworks.gfx.vt.Terminal;
import java.nio.charset.StandardCharsets;
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
@ -26,38 +29,53 @@ public class Test {
var tex2 = window.loadTexture("C:\\art\\pixel stuff.png"); var tex2 = window.loadTexture("C:\\art\\pixel stuff.png");
var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16)); var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16));
var font = window.loadFontTileset("EGA8x14.png"); var font = window.loadFontTileset("EGA8x14.png");
var font2 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16*8.f); var fontThin = window.loadFontTileset("fonts\\thin-6x12.png");
var fontThin2 = window.loadFontTileset("fonts\\thin-12x12.png");
var font2 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16 * 8.f);
var font3 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16); var font3 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16);
var tex = window.loadTexture(img); var tex = window.loadTexture(img);
var slice = window.loadNineSlice("demoassets\\9slice-2.png"); var slice = window.loadNineSlice("demoassets\\9slice-2.png");
var term = new Terminal(new Vec2i(80, 45), fontThin2, fontThin);
//window.setDebug(true); //window.setDebug(true);
term.setChar(new Vec2i(0, 0), 0xC9, Color.GREEN);
term.setChar(new Vec2i(9, 9), 0xC9, Color.GREEN);
term.setChar(new Vec2i(10, 10), 0xC9, Color.GREEN);
while(!window.shouldClose()) { while(!window.shouldClose()) {
window.tick(); window.tick();
var renderContext = window.renderStart(); var renderContext = window.renderStart();
renderContext.drawTextureRectangle( /*renderContext.drawTextureRectangle(
new Recti(0, 0, 1280, 720), new Recti(0, 0, 1280, 720),
tex, tex,
false false
); );*/
//renderContext.drawTextureRectangle( //renderContext.drawTextureRectangle(
// new Recti(new Vec2i(200, 100), tex2.getSize()), // new Recti(new Vec2i(200, 100), tex2.getSize()),
// tex2, // tex2,
// true // true
//); //);
renderContext.drawTextureRectangle( /*renderContext.drawTextureRectangle(
new Recti(new Vec2i(400, 400), new Vec2i(160, 160)), new Recti(new Vec2i(400, 400), new Vec2i(160, 160)),
tileset.get(0x30), tileset.get(0x30),
true true
); );*/
renderContext.drawString(new Vec2i(710, 140), "hello world mew", font2); //byte[] str = {(byte)0xC9, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xCD, (byte)0xBB};
//renderContext.drawString(new Vec2i(36, 36), new String(str), fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 36), "\u00c9\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00BB", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 48), "\u00ba \u00ba", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 60), "\u00ba \u00ba", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(36, 72), "\u00c8\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00BC", fontThin2, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(48, 48), "The quick brown fox jumps over the lazy dog", fontThin, new Color(0, 255, 0));
//renderContext.drawString(new Vec2i(48, 60), "Soft Kitty, Warm Kitty, Little Ball of Fur. Happy Kitty, Sleepy Kitty, Purr Purr Purr.", fontThin, new Color(0, 255, 0));
renderContext.drawTerminal(term);
renderContext.drawNineSlice(slice, new Recti(100, 100, 75, 23)); //renderContext.drawNineSlice(slice, new Recti(100, 100, 75, 23));
//renderContext.drawString(new Vec2i(118, 117), "Meow", font3, new Color(0,0,0)); //renderContext.drawString(new Vec2i(118, 117), "Meow", font3, new Color(0,0,0));
renderContext.drawString(new Vec2i(122, 105), "Meow", font, new Color(0,0,0)); //renderContext.drawString(new Vec2i(122, 105), "Meow", font, new Color(0,0,0));
window.renderFinish(renderContext); window.renderFinish(renderContext);
} }

View File

@ -12,7 +12,8 @@ class RenderContext extends BaseRenderContext implements IRenderContext {
private final int texSizeIndex; private final int texSizeIndex;
private final int tintIndex; private final int tintIndex;
public RenderContext(TextureAtlas atlas, int texCoordIndex, int texOffsetIndex, int texSizeIndex, int tintIndex) { public RenderContext(Vec2i size, TextureAtlas atlas, int texCoordIndex, int texOffsetIndex, int texSizeIndex, int tintIndex) {
super(size);
this.atlas = atlas; this.atlas = atlas;
this.texCoordIndex = texCoordIndex; this.texCoordIndex = texCoordIndex;
this.texOffsetIndex = texOffsetIndex; this.texOffsetIndex = texOffsetIndex;

View File

@ -53,6 +53,7 @@ public class Window extends BaseWindow {
program = new Program(vertexSource, fragmentSource); program = new Program(vertexSource, fragmentSource);
program.use(); program.use();
renderContext = new RenderContext( renderContext = new RenderContext(
size,
textureAtlas, textureAtlas,
program.getAttribLocation("texCoord"), program.getAttribLocation("texCoord"),
program.getUniformLocation("texOffset"), program.getUniformLocation("texOffset"),

View File

@ -3,12 +3,19 @@ package com.danitheskunk.skunkworks.gfx;
import com.danitheskunk.skunkworks.gfx.font.IFont; import com.danitheskunk.skunkworks.gfx.font.IFont;
import com.danitheskunk.skunkworks.Recti; import com.danitheskunk.skunkworks.Recti;
import com.danitheskunk.skunkworks.Vec2i; import com.danitheskunk.skunkworks.Vec2i;
import com.danitheskunk.skunkworks.gfx.vt.Terminal;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
abstract public class BaseRenderContext implements IRenderContext { abstract public class BaseRenderContext implements IRenderContext {
protected Vec2i size;
protected BaseRenderContext(Vec2i size) {
this.size = size;
}
public void drawString(Vec2i pos, String string, IFont font) { public void drawString(Vec2i pos, String string, IFont font) {
drawString(pos, string, font, Color.WHITE); drawString(pos, string, font, Color.WHITE);
} }
@ -30,4 +37,35 @@ abstract public class BaseRenderContext implements IRenderContext {
x += font.getXAdvance(ch); x += font.getXAdvance(ch);
} }
} }
public void drawTerminal(Terminal terminal) {
var off = Vec2i.div(Vec2i.sub(size, terminal.getPixelSize()), 2);
drawTerminal(terminal, off);
}
public void drawTerminal(Terminal terminal, Vec2i pos) {
var termSize = terminal.getSize();
var charSize = terminal.getFullCharSize();
var halfCharSize = terminal.getHalfCharSize();
var halfFont = terminal.getHalfFont();
var fullFont = terminal.getFullFont();
for(int y = 0; y < termSize.getY(); ++y) {
for(int x = 0; x < termSize.getX(); ++x) {
var charPos = new Vec2i(x, y);
var bgColor = terminal.getBackgroundColor(charPos);
var fgColor = terminal.getForegroundColor(charPos);
var pixelPos = Vec2i.add(pos, Vec2i.mul(charPos, charSize));
var isHalfWidth = terminal.isHalfWidth(charPos);
drawTexture(pixelPos, fullFont.getTexture(0xdb), bgColor);
if(isHalfWidth) {
drawTexture(pixelPos, fullFont.getTexture(terminal.getLeftHalfChar(charPos)), fgColor);
drawTexture(Vec2i.add(pixelPos, halfCharSize), fullFont.getTexture(terminal.getRightHalfChar(charPos)), fgColor);
} else {
drawTexture(pixelPos, fullFont.getTexture(terminal.getChar(charPos)), fgColor);
}
}
}
}
} }

View File

@ -1,16 +1,29 @@
package com.danitheskunk.skunkworks.gfx; package com.danitheskunk.skunkworks.gfx;
import com.danitheskunk.skunkworks.*; import com.danitheskunk.skunkworks.Recti;
import com.danitheskunk.skunkworks.Vec2i;
import com.danitheskunk.skunkworks.gfx.font.IFont; import com.danitheskunk.skunkworks.gfx.font.IFont;
import com.danitheskunk.skunkworks.gfx.vt.Terminal;
public interface IRenderContext { public interface IRenderContext {
void drawNineSlice(NineSlice slice, Recti rect); //todo: add rounding mode void drawNineSlice(NineSlice slice, Recti rect); //todo: add rounding mode
void drawRectangle(Recti rect, Color color); void drawRectangle(Recti rect, Color color);
void drawString(Vec2i pos, String string, IFont font); void drawString(Vec2i pos, String string, IFont font);
void drawString(Vec2i pos, String string, IFont font, Color color); void drawString(Vec2i pos, String string, IFont font, Color color);
void drawTexture(Vec2i pos, ITexture texture); void drawTexture(Vec2i pos, ITexture texture);
void drawTexture(Vec2i pos, ITexture texture, Color color); void drawTexture(Vec2i pos, ITexture texture, Color color);
void drawTextureRectangle(Recti rect, ITexture texture, boolean repeat); void drawTextureRectangle(Recti rect, ITexture texture, boolean repeat);
void drawTextureRectangle(Recti rect, ITexture texture, Color color, boolean repeat); void drawTextureRectangle(Recti rect, ITexture texture, Color color, boolean repeat);
void drawTerminal(Terminal terminal);
void drawTerminal(Terminal terminal, Vec2i pos);
//todo: drawTextureRectangleRepeat //todo: drawTextureRectangleRepeat
} }

View File

@ -0,0 +1,161 @@
package com.danitheskunk.skunkworks.gfx.vt;
import com.danitheskunk.skunkworks.Vec2i;
import com.danitheskunk.skunkworks.gfx.Color;
import com.danitheskunk.skunkworks.gfx.font.IFont;
import java.util.ArrayList;
import java.util.List;
public class Terminal {
private List<Cell> cells;
private Vec2i size;
private Vec2i fullCharSize;
private Vec2i halfCharSize;
private IFont fullFont;
private IFont halfFont;
public Terminal(Vec2i size, IFont fullFont, IFont halfFont) {
this.cells = new ArrayList<>();
this.size = size;
this.fullFont = fullFont;
this.halfFont = halfFont;
if(!fullFont.isMonospace() || !halfFont.isMonospace()) {
throw new RuntimeException("Fonts need to be monospace");
}
this.fullCharSize = fullFont.getMonospaceSize();
this.halfCharSize = halfFont.getMonospaceSize();
if(fullCharSize.getY() != halfCharSize.getY() || fullCharSize.getX() != halfCharSize.getX() * 2) {
throw new RuntimeException("halfFont needs to be half width of fullFont");
}
for(int i = 0; i < size.getY() * size.getX(); ++i) {
var cell = new Cell();
cell.fullChar = 0;
cell.secondChar = 0;
cell.halfWidth = false;
cell.bgColor = Color.BLACK;
cell.fgColor = Color.WHITE;
cells.add(cell);
}
}
public Vec2i getFullCharSize() {
return fullCharSize;
}
public Vec2i getHalfCharSize() {
return halfCharSize;
}
public Vec2i getSize() {
return size;
}
public void setChar(Vec2i pos, int ch) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = ch;
cell.halfWidth = false;
}
public void setChar(Vec2i pos, int ch, Color foregroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = ch;
cell.halfWidth = false;
cell.fgColor = foregroundColor;
}
public void setChar(Vec2i pos, int ch, Color foregroundColor, Color backgroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = ch;
cell.halfWidth = false;
cell.fgColor = foregroundColor;
cell.bgColor = backgroundColor;
}
public void setHalfChars(Vec2i pos, int chLeft, int chRight) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = chLeft;
cell.secondChar = chRight;
cell.halfWidth = true;
}
public void setHalfChars(Vec2i pos, int chLeft, int chRight, Color foregroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = chLeft;
cell.secondChar = chRight;
cell.halfWidth = true;
cell.fgColor = foregroundColor;
}
public void setHalfChars(Vec2i pos, int chLeft, int chRight, Color foregroundColor, Color backgroundColor) {
var cell = cells.get(vecToPos(pos));
cell.fullChar = chLeft;
cell.secondChar = chRight;
cell.halfWidth = true;
cell.fgColor = foregroundColor;
cell.bgColor = backgroundColor;
}
public void setForegroundColor(Vec2i pos, Color color) {
var cell = cells.get(vecToPos(pos));
cell.fgColor = color;
}
public void setBackgroundColor(Vec2i pos, Color color) {
var cell = cells.get(vecToPos(pos));
cell.fgColor = color;
}
public int getChar(Vec2i pos) {
return cells.get(vecToPos(pos)).fullChar;
}
public int getLeftHalfChar(Vec2i pos) {
return cells.get(vecToPos(pos)).fullChar;
}
public int getRightHalfChar(Vec2i pos) {
return cells.get(vecToPos(pos)).secondChar;
}
public Color getForegroundColor(Vec2i pos) {
return cells.get(vecToPos(pos)).fgColor;
}
public Color getBackgroundColor(Vec2i pos) {
return cells.get(vecToPos(pos)).bgColor;
}
public boolean isHalfWidth(Vec2i pos) {
return cells.get(vecToPos(pos)).halfWidth;
}
private int vecToPos(Vec2i pos) {
return pos.getX() + pos.getY() * size.getX();
}
public IFont getFullFont() {
return fullFont;
}
public IFont getHalfFont() {
return halfFont;
}
public Vec2i getPixelSize() {
return Vec2i.mul(size, fullCharSize);
}
private class Cell {
int fullChar;
int secondChar;
boolean halfWidth;
Color bgColor;
Color fgColor;
}
}