diff --git a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java index 1bd692a..ebbad97 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientProxy.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientProxy.java @@ -23,6 +23,8 @@ import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend; import ru.windcorp.progressia.client.graphics.backend.RenderTaskQueue; import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; import ru.windcorp.progressia.client.graphics.flat.LayerTestUI; +import ru.windcorp.progressia.client.graphics.font.TestTypeface; +import ru.windcorp.progressia.client.graphics.font.Typefaces; import ru.windcorp.progressia.client.graphics.gui.LayerTestGUI; import ru.windcorp.progressia.client.graphics.texture.Atlases; import ru.windcorp.progressia.client.graphics.world.LayerWorld; @@ -37,6 +39,7 @@ public class ClientProxy implements Proxy { try { RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); + RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(new TestTypeface())); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java index 11b2f9e..8c0e0ac 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Optica + * Progressia * Copyright (C) 2020 Wind Corporation * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java index 884b2ed..9828518 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/FlatRenderProgram.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Optica + * Progressia * Copyright (C) 2020 Wind Corporation * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java index 8fbffcc..8859786 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/LayerTestUI.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Optica + * Progressia * Copyright (C) 2020 Wind Corporation * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java index fe018c7..bf22e2a 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/RenderTarget.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Optica + * Progressia * Copyright (C) 2020 Wind Corporation * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java b/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java index f02e171..31d24a1 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/flat/TransformedMask.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Optica + * Progressia * Copyright (C) 2020 Wind Corporation * * This program is free software: you can redistribute it and/or modify diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java new file mode 100755 index 0000000..497ddff --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/Font.java @@ -0,0 +1,126 @@ +package ru.windcorp.progressia.client.graphics.font; + +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.model.WorldRenderable; + +public class Font { + + private final Typeface typeface; + + private final int style; + private final float align; + private final int color; + + public Font(Typeface typeface, int style, float align, int color) { + this.typeface = typeface; + this.style = style; + this.align = align; + this.color = color; + } + + public Font(Typeface typeface) { + this(typeface, Typeface.Style.PLAIN, Typeface.ALIGN_LEFT, Colors.WHITE); + } + + public Font() { + this(Typefaces.getDefault()); + } + + public Typeface getTypeface() { + return typeface; + } + + public int getStyle() { + return style; + } + + public float getAlign() { + return align; + } + + public int getColor() { + return color; + } + + public WorldRenderable assemble( + CharSequence chars, int maxWidth + ) { + return typeface.assemble(chars, style, align, maxWidth, color); + } + + public int getWidth(CharSequence chars, int maxWidth) { + return typeface.getWidth(chars, style, align, maxWidth); + } + + public int getHeight(CharSequence chars, int maxWidth) { + return typeface.getHeight(chars, style, align, maxWidth); + } + + public Vec2i getSize(CharSequence chars, int maxWidth, Vec2i result) { + return typeface.getSize(chars, style, align, maxWidth, result); + } + + public boolean supports(char c) { + return typeface.supports(c); + } + + /** + * Creates a new {@link Font} with the specified {@code style} exactly. This + * object's style is ignored. + * @param style the new style + * @return the new font + */ + public Font withStyle(int style) { + return new Font(getTypeface(), style, getAlign(), getColor()); + } + + public Font deriveBold() { + return withStyle(getStyle() | Typeface.Style.BOLD); + } + + public Font deriveItalic() { + return withStyle(getStyle() | Typeface.Style.ITALIC); + } + + public Font deriveUnderlined() { + return withStyle(getStyle() | Typeface.Style.UNDERLINED); + } + + public Font deriveStrikethru() { + return withStyle(getStyle() | Typeface.Style.STRIKETHRU); + } + + public Font deriveShadow() { + return withStyle(getStyle() | Typeface.Style.SHADOW); + } + + public Font deriveNotBold() { + return withStyle(getStyle() & ~Typeface.Style.BOLD); + } + + public Font deriveNotItalic() { + return withStyle(getStyle() & ~Typeface.Style.ITALIC); + } + + public Font deriveNotUnderlined() { + return withStyle(getStyle() & ~Typeface.Style.UNDERLINED); + } + + public Font deriveNotStrikethru() { + return withStyle(getStyle() & ~Typeface.Style.STRIKETHRU); + } + + public Font deriveNotShadow() { + return withStyle(getStyle() & ~Typeface.Style.SHADOW); + } + + public Font withAlign(float align) { + return new Font(getTypeface(), getStyle(), align, getColor()); + } + + public Font withColor(int color) { + return new Font(getTypeface(), getStyle(), getAlign(), color); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/TestTypeface.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/TestTypeface.java new file mode 100755 index 0000000..0442aec --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/TestTypeface.java @@ -0,0 +1,93 @@ +package ru.windcorp.progressia.client.graphics.font; + +import java.io.IOException; + +import glm.vec._2.Vec2; +import glm.vec._3.Vec3; +import gnu.trove.map.TCharObjectMap; +import gnu.trove.map.hash.TCharObjectHashMap; +import ru.windcorp.progressia.client.graphics.backend.Usage; +import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; +import ru.windcorp.progressia.client.graphics.model.Face; +import ru.windcorp.progressia.client.graphics.model.Faces; +import ru.windcorp.progressia.client.graphics.model.Shape; +import ru.windcorp.progressia.client.graphics.model.WorldRenderable; +import ru.windcorp.progressia.client.graphics.texture.SimpleTexture; +import ru.windcorp.progressia.client.graphics.texture.Sprite; +import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.texture.TextureLoader; +import ru.windcorp.progressia.client.graphics.texture.TexturePrimitive; +import ru.windcorp.progressia.client.graphics.texture.TextureSettings; +import ru.windcorp.progressia.common.resource.ResourceManager; + +public class TestTypeface extends Typeface { + + private static final TCharObjectMap TEXTURES = new TCharObjectHashMap<>(); + + private static final Vec3 SIZE = new Vec3(8, 8, 0); + + public TestTypeface() { + super("Test"); + + TexturePrimitive primitive = null; + try { + primitive = new TexturePrimitive(TextureLoader.loadPixels( + ResourceManager.getTextureResource("font_test"), + new TextureSettings(false) + ).toStatic()); + } catch (IOException e) { + throw new RuntimeException(e); + } + + Vec2 size = new Vec2(0.5f, 0.5f); + + TEXTURES.put('A', new SimpleTexture(new Sprite(primitive, new Vec2(0, 0.5f), size))); + TEXTURES.put('B', new SimpleTexture(new Sprite(primitive, new Vec2(0.5f, 0.5f), size))); + TEXTURES.put('C', new SimpleTexture(new Sprite(primitive, new Vec2(0, 0), size))); + TEXTURES.put('D', new SimpleTexture(new Sprite(primitive, new Vec2(0.5f, 0), size))); + } + + @Override + public WorldRenderable assemble( + CharSequence chars, int style, + float align, int maxWidth, + int color + ) { + Face[] faces = new Face[chars.length()]; + + Vec3 caret = new Vec3(); + + for (int i = 0; i < chars.length(); ++i) { + char c = chars.charAt(i); + + if (supports(c)) { + faces[i] = Faces.createRectangle( + FlatRenderProgram.getDefault(), + TEXTURES.get(c), new Vec3(1, 1, 1), + caret, new Vec3(SIZE.x, 0, 0), new Vec3(0, SIZE.y, 0) + ); + } + + caret.x += SIZE.x; + } + + return new Shape(Usage.STATIC, FlatRenderProgram.getDefault(), faces); + } + + @Override + protected long getSize( + CharSequence chars, int style, + float align, int maxWidth + ) { + return pack( + (int) (chars.length() * SIZE.x), + (int) (SIZE.y) + ); + } + + @Override + public boolean supports(char c) { + return TEXTURES.containsKey(c); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java new file mode 100755 index 0000000..ca3b7c9 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typeface.java @@ -0,0 +1,102 @@ +package ru.windcorp.progressia.client.graphics.font; + +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.model.WorldRenderable; +import ru.windcorp.progressia.common.util.CoordinatePacker; +import ru.windcorp.progressia.common.util.Named; + +public abstract class Typeface extends Named { + + public static class Style { + public static final int + BOLD = 1 << 0, + ITALIC = 1 << 1, + UNDERLINED = 1 << 2, + STRIKETHRU = 1 << 3, + SHADOW = 1 << 4; + + public static final int PLAIN = 0; + + public static boolean isBold(int style) { + return (style & BOLD) != 0; + } + + public static boolean isItalic(int style) { + return (style & ITALIC) != 0; + } + + public static boolean isUnderlined(int style) { + return (style & UNDERLINED) != 0; + } + + public static boolean isStrikethru(int style) { + return (style & STRIKETHRU) != 0; + } + + public static boolean hasShadow(int style) { + return (style & SHADOW) != 0; + } + } + + public static final float ALIGN_LEFT = 0; + public static final float ALIGN_RIGHT = 1; + public static final float ALIGN_CENTER = 0.5f; + + public Typeface(String name) { + super(name); + } + + public abstract WorldRenderable assemble( + CharSequence chars, int style, + float align, int maxWidth, + int color + ); + + public int getWidth( + CharSequence chars, int style, + float align, int maxWidth + ) { + return getWidth(getSize(chars, style, align, maxWidth)); + } + + public int getHeight( + CharSequence chars, int style, + float align, int maxWidth + ) { + return getHeight(getSize(chars, style, align, maxWidth)); + } + + public Vec2i getSize( + CharSequence chars, int style, + float align, int maxWidth, + Vec2i result + ) { + if (result == null) { + result = new Vec2i(); + } + + long packed = getSize(chars, style, align, maxWidth); + result.set(getWidth(packed), getHeight(packed)); + return result; + } + + protected abstract long getSize( + CharSequence chars, int style, + float align, int maxWidth + ); + + protected static long pack(int width, int height) { + return CoordinatePacker.pack2IntsIntoLong(width, height); + } + + protected static int getWidth(long packed) { + return CoordinatePacker.unpack2IntsFromLong(packed, 0); + } + + protected static int getHeight(long packed) { + return CoordinatePacker.unpack2IntsFromLong(packed, 1); + } + + public abstract boolean supports(char c); + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java new file mode 100755 index 0000000..e4d6076 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/font/Typefaces.java @@ -0,0 +1,15 @@ +package ru.windcorp.progressia.client.graphics.font; + +public class Typefaces { + + private static Typeface def = null; + + public static Typeface getDefault() { + return def; + } + + public static void setDefault(Typeface def) { + Typefaces.def = def; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java old mode 100644 new mode 100755 index af7cfc6..9260476 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -232,7 +232,7 @@ public class Component extends Named { valid = true; } catch (Exception e) { - throw new RuntimeException(); + throw new RuntimeException(e); } } @@ -245,7 +245,7 @@ public class Component extends Named { try { return getLayout().calculatePreferredSize(this); } catch (Exception e) { - throw new RuntimeException(); + throw new RuntimeException(e); } } @@ -517,7 +517,7 @@ public class Component extends Named { break; } } catch (Exception e) { - throw new RuntimeException(); + throw new RuntimeException(e); } } @@ -610,7 +610,7 @@ public class Component extends Named { try { assembleSelf(target); } catch (Exception e) { - throw new RuntimeException(); + throw new RuntimeException(e); } assembleChildren(target); @@ -618,7 +618,7 @@ public class Component extends Named { try { postAssembleSelf(target); } catch (Exception e) { - throw new RuntimeException(); + throw new RuntimeException(e); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java old mode 100644 new mode 100755 index 1bd9f9c..5f53652 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/GUILayer.java @@ -49,5 +49,11 @@ public abstract class GUILayer extends AssembledFlatLayer { protected void handleInput(Input input) { getRoot().dispatchInput(input); } + + @Override + public void invalidate() { + super.invalidate(); + getRoot().invalidate(); + } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java new file mode 100755 index 0000000..c70f464 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Label.java @@ -0,0 +1,62 @@ +package ru.windcorp.progressia.client.graphics.gui; + +import java.util.function.Supplier; + +import glm.mat._4.Mat4; +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.font.Font; + +public class Label extends Component { + + private Font font; + private String currentText; + private Vec2i currentSize; + private Supplier contents; + + public Label(String name, Font font, Supplier contents) { + super(name); + this.font = font; + this.contents = contents; + update(); + } + + public Label(String name, Font font, String contents) { + this(name, font, () -> contents); + } + + public void update() { + currentText = contents.get(); + currentSize = font.getSize(currentText, Integer.MAX_VALUE, null).mul(4); + } + + @Override + public synchronized Vec2i getPreferredSize() { + return currentSize; + } + + public Font getFont() { + return font; + } + + public String getCurrentText() { + return currentText; + } + + public Supplier getContentSupplier() { + return contents; + } + + @Override + protected void assembleSelf(RenderTarget target) { + target.pushTransform( + new Mat4().identity().translate(getX(), getY(), -1000) + .scale(4) + ); + + target.addCustomRenderer(font.assemble(currentText, Integer.MAX_VALUE)); + + target.popTransform(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java old mode 100644 new mode 100755 index 2d767c2..bb4d0a8 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/LayerTestGUI.java @@ -22,8 +22,10 @@ import com.google.common.eventbus.Subscribe; import glm.vec._2.i.Vec2i; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.font.Font; import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; import ru.windcorp.progressia.client.graphics.input.KeyEvent; public class LayerTestGUI extends GUILayer { @@ -69,7 +71,16 @@ public class LayerTestGUI extends GUILayer { public LayerTestGUI() { super("LayerTestGui", new LayoutAlign(1, 0.75, 5)); - getRoot().addChild(new DebugComponent("Alex", new Vec2i(200, 100), 0x44FF44)); + Panel panel = new Panel("Alex", new LayoutVertical(5)); + + panel.addChild(new DebugComponent("Bravo", new Vec2i(200, 100), 0x44FF44)); + + Component charlie = new DebugComponent("Charlie", null, 0x4444FF); + charlie.setLayout(new LayoutAlign()); + charlie.addChild(new Label("Delta", new Font(), "BABCBABCBABC")); + panel.addChild(charlie); + + getRoot().addChild(panel); } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java new file mode 100755 index 0000000..18c4172 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Panel.java @@ -0,0 +1,10 @@ +package ru.windcorp.progressia.client.graphics.gui; + +public class Panel extends Component { + + public Panel(String name, Layout layout) { + super(name); + setLayout(layout); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java index 6a3fcf0..c59405e 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/texture/TexturePrimitive.java @@ -82,7 +82,7 @@ public class TexturePrimitive implements OpenGLDeletable { currentlyBound[slot] = handle; } - protected void load() { + public void load() { if (isLoaded()) return; handle = pixels.load(); diff --git a/src/main/resources/assets/textures/font_test.png b/src/main/resources/assets/textures/font_test.png new file mode 100755 index 0000000..e80021f Binary files /dev/null and b/src/main/resources/assets/textures/font_test.png differ