Added test text rendering

- Added Typeface
- Added Font (Typeface + style)
- Added Label to display text in GUI
- Added Panels to quickly group Components
- Added a test font
  - Ignores all parameters but text itself
  - Only ABCD are supported (no whitespace)
This commit is contained in:
OLEGSHA 2020-08-16 08:31:06 +04:00
parent 4370c523e6
commit 0e99685583
17 changed files with 440 additions and 12 deletions

View File

@ -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.backend.RenderTaskQueue;
import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram; import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram;
import ru.windcorp.progressia.client.graphics.flat.LayerTestUI; 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.gui.LayerTestGUI;
import ru.windcorp.progressia.client.graphics.texture.Atlases; import ru.windcorp.progressia.client.graphics.texture.Atlases;
import ru.windcorp.progressia.client.graphics.world.LayerWorld; import ru.windcorp.progressia.client.graphics.world.LayerWorld;
@ -37,6 +39,7 @@ public class ClientProxy implements Proxy {
try { try {
RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init); RenderTaskQueue.waitAndInvoke(FlatRenderProgram::init);
RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init); RenderTaskQueue.waitAndInvoke(WorldRenderProgram::init);
RenderTaskQueue.waitAndInvoke(() -> Typefaces.setDefault(new TestTypeface()));
} catch (InterruptedException e) { } catch (InterruptedException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();

View File

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Optica * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020 Wind Corporation
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Optica * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020 Wind Corporation
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Optica * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020 Wind Corporation
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Optica * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020 Wind Corporation
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Optica * Progressia
* Copyright (C) 2020 Wind Corporation * Copyright (C) 2020 Wind Corporation
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify

View File

@ -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);
}
}

View File

@ -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<Texture> 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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -232,7 +232,7 @@ public class Component extends Named {
valid = true; valid = true;
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(); throw new RuntimeException(e);
} }
} }
@ -245,7 +245,7 @@ public class Component extends Named {
try { try {
return getLayout().calculatePreferredSize(this); return getLayout().calculatePreferredSize(this);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(); throw new RuntimeException(e);
} }
} }
@ -517,7 +517,7 @@ public class Component extends Named {
break; break;
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(); throw new RuntimeException(e);
} }
} }
@ -610,7 +610,7 @@ public class Component extends Named {
try { try {
assembleSelf(target); assembleSelf(target);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(); throw new RuntimeException(e);
} }
assembleChildren(target); assembleChildren(target);
@ -618,7 +618,7 @@ public class Component extends Named {
try { try {
postAssembleSelf(target); postAssembleSelf(target);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(); throw new RuntimeException(e);
} }
} }

View File

@ -49,5 +49,11 @@ public abstract class GUILayer extends AssembledFlatLayer {
protected void handleInput(Input input) { protected void handleInput(Input input) {
getRoot().dispatchInput(input); getRoot().dispatchInput(input);
} }
@Override
public void invalidate() {
super.invalidate();
getRoot().invalidate();
}
} }

View File

@ -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<String> contents;
public Label(String name, Font font, Supplier<String> 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<String> 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();
}
}

View File

@ -22,8 +22,10 @@ import com.google.common.eventbus.Subscribe;
import glm.vec._2.i.Vec2i; import glm.vec._2.i.Vec2i;
import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.Colors;
import ru.windcorp.progressia.client.graphics.flat.RenderTarget; 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.event.HoverEvent;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; 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; import ru.windcorp.progressia.client.graphics.input.KeyEvent;
public class LayerTestGUI extends GUILayer { public class LayerTestGUI extends GUILayer {
@ -69,7 +71,16 @@ public class LayerTestGUI extends GUILayer {
public LayerTestGUI() { public LayerTestGUI() {
super("LayerTestGui", new LayoutAlign(1, 0.75, 5)); 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);
} }
} }

View File

@ -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);
}
}

View File

@ -82,7 +82,7 @@ public class TexturePrimitive implements OpenGLDeletable {
currentlyBound[slot] = handle; currentlyBound[slot] = handle;
} }
protected void load() { public void load() {
if (isLoaded()) return; if (isLoaded()) return;
handle = pixels.load(); handle = pixels.load();

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B