diff --git a/src/main/java/speiger/src/coreengine/NewInputTest.java b/src/main/java/speiger/src/coreengine/NewInputTest.java index 936b867..7efcee0 100644 --- a/src/main/java/speiger/src/coreengine/NewInputTest.java +++ b/src/main/java/speiger/src/coreengine/NewInputTest.java @@ -88,7 +88,7 @@ public class NewInputTest { applyWindowSize(window); System.out.println("Testing: "+GL.getCapabilities().OpenGL41); System.out.println("Testing: "+Integer.divideUnsigned(-1, 255)); - + GL11.glEnable(GL43.GL_MULTISAMPLE); int size = 512; int half = size >> 1; @@ -160,9 +160,7 @@ public class NewInputTest { // offset += font.drawText(style, "§ox ", 50+offset, y, -1, buffer, scale, false); // offset += font.drawText(style, "Jumps ", 50+offset, y, -1, buffer, scale, false); // offset += font.drawText(style, "over the Lazy dog", 50+offset, y, -1, buffer, scale, true); -// font.drawText(s, 50, 50, -1, buffer, true); - - +// font.drawText(s, 50, 50, -1, buffer, true); GLStateTracker tracker = GLStateTracker.instance(); GL11.glClearColor(0.2F, 0.55F, 0.66F, 1F); while(!window.shouldClose()) { diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/font/Font.java b/src/main/java/speiger/src/coreengine/rendering/gui/font/Font.java index de81ab3..1fbb0d5 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/font/Font.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/font/Font.java @@ -8,6 +8,8 @@ import speiger.src.coreengine.rendering.gui.font.glyth.Glyth; import speiger.src.coreengine.rendering.gui.font.glyth.GlythData; import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.GlythBaker; import speiger.src.coreengine.rendering.tesselation.buffer.IVertexBuilder; +import speiger.src.coreengine.utils.helpers.TextUtil; +import speiger.src.coreengine.utils.misc.CodepointSequence; public class Font { private static final int FORMAT_CODE_POINT = '§'; @@ -39,6 +41,10 @@ public class Font { return styledCache[font.style() & 0x3].glyth(font, codepoint); } + public float width(FontStyle font, int codepoint) { + return styledCache[font.style() & 0x3].data(font, codepoint).advance(); + } + protected FontGroup font(AssetLocation font) { return fonts.get(font); } @@ -48,24 +54,23 @@ public class Font { } public float drawText(TextStyle style, String text, float x, float y, int color, TexturedBuffer buffer, float scale, boolean end) { - TextStyle[] currentStyle = {style}; - int[] currentColor = {currentStyle[0].hasColor() ? currentStyle[0].color() : color}; + TextStyle currentStyle = style; + int currentColor = currentStyle.hasColor() ? currentStyle.color() : color; float xStart = x; int previousCodepoint = -1; for(int i = 0,m=text.length();i { - currentStyle[0] = T; - currentColor[0] = T.hasColor() ? T.color() : color; - })) { - i = text.indexOf('>', i)+1; - continue; + CodepointSequence result; + if(codepoint == FORMAT_CODE_POINT && (result = findValue(CodepointSequence.of(text, i))) != null) { + currentStyle = currentStyle.parseArguments(style, result.toString().split(",")); + currentColor = currentStyle.hasColor() ? currentStyle.color() : color; + i += result.length()+3; } - GlythData data = data(currentStyle[0].font(), codepoint); + GlythData data = data(currentStyle.font(), codepoint); if(previousCodepoint != -1) { x -= data.kerning(previousCodepoint); } - Glyth glyth = glyth(currentStyle[0].font(), codepoint); + Glyth glyth = glyth(currentStyle.font(), codepoint); if(glyth.isValid()) { float minX = (glyth.left() + x) * scale; float minY = (glyth.top() + y) * scale; @@ -73,12 +78,12 @@ public class Font { float maxY = (glyth.bottom() + y) * scale; IVertexBuilder builder = buffer.builderForTexture(glyth.texture()); - builder.pos(minX, minY, 0F).tex(glyth.minU(), glyth.minV()).rgba(currentColor[0]).endVertex(); - builder.pos(maxX, minY, 0F).tex(glyth.maxU(), glyth.minV()).rgba(currentColor[0]).endVertex(); - builder.pos(maxX, maxY, 0F).tex(glyth.maxU(), glyth.maxV()).rgba(currentColor[0]).endVertex(); - builder.pos(maxX, maxY, 0F).tex(glyth.maxU(), glyth.maxV()).rgba(currentColor[0]).endVertex(); - builder.pos(minX, maxY, 0F).tex(glyth.minU(), glyth.maxV()).rgba(currentColor[0]).endVertex(); - builder.pos(minX, minY, 0F).tex(glyth.minU(), glyth.minV()).rgba(currentColor[0]).endVertex(); + builder.pos(minX, minY, 0F).tex(glyth.minU(), glyth.minV()).rgba(currentColor).endVertex(); + builder.pos(maxX, minY, 0F).tex(glyth.maxU(), glyth.minV()).rgba(currentColor).endVertex(); + builder.pos(maxX, maxY, 0F).tex(glyth.maxU(), glyth.maxV()).rgba(currentColor).endVertex(); + builder.pos(maxX, maxY, 0F).tex(glyth.maxU(), glyth.maxV()).rgba(currentColor).endVertex(); + builder.pos(minX, maxY, 0F).tex(glyth.minU(), glyth.maxV()).rgba(currentColor).endVertex(); + builder.pos(minX, minY, 0F).tex(glyth.minU(), glyth.minV()).rgba(currentColor).endVertex(); } x += data.advance(); i += Character.charCount(codepoint); @@ -88,14 +93,11 @@ public class Font { return x - xStart; } - boolean applyStyle(String text, int index, TextStyle style, TextStyle original, Consumer consumer) { - if(text.length() <= index || text.codePointAt(index) != '<') return false; - int endIndex = text.indexOf('>', index); - if(endIndex == -1) return false; - String[] formatting = text.substring(index+1, endIndex).split(","); - if(formatting.length <= 0) return false; - consumer.accept(style.parseArguments(original, formatting)); - return true; + static CodepointSequence findValue(CodepointSequence input) { + if(input.length() < 3 || input.codePointAt(0) != FORMAT_CODE_POINT || input.codePointAt(1) != '<') return null; + int end = TextUtil.findEnd(input, "§<", ">"); + if(end == -1) return null; + return input.subSequence(2, end-1); } diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/font/FontManager.java b/src/main/java/speiger/src/coreengine/rendering/gui/font/FontManager.java index d490560..ab9649f 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/font/FontManager.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/font/FontManager.java @@ -7,6 +7,7 @@ import java.util.function.BiFunction; import com.google.gson.JsonObject; +import speiger.src.collections.floats.maps.interfaces.Float2ObjectMap; import speiger.src.collections.objects.lists.ObjectArrayList; import speiger.src.collections.objects.lists.ObjectList; import speiger.src.collections.objects.maps.interfaces.Object2ObjectMap; @@ -26,6 +27,7 @@ import speiger.src.coreengine.utils.helpers.JsonUtil; public class FontManager extends SteppedReloadableAsset>> { private static final int TEXTURE_SIZE = 512; private static final AssetFilter FILTER = AssetFilter.json("font"); + Float2ObjectMap cachedFonts = Float2ObjectMap.builder().map(); Map fonts = Object2ObjectMap.builder().linkedMap(); Map> fontParsers = Object2ObjectMap.builder().map(); List listeners = new ObjectArrayList<>(); @@ -80,6 +82,7 @@ public class FontManager extends SteppedReloadableAsset new Font(fonts, this::stitch, T, listeners::add)); } private Glyth stitch(IGlythSheetInfo info) { diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/font/FontSplitter.java b/src/main/java/speiger/src/coreengine/rendering/gui/font/FontSplitter.java index c1218e0..7f574e2 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/font/FontSplitter.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/font/FontSplitter.java @@ -1,5 +1,7 @@ package speiger.src.coreengine.rendering.gui.font; +import speiger.src.coreengine.utils.misc.CodepointSequence; + public class FontSplitter { private static final int FORMAT_CODE_POINT = '§'; @@ -18,19 +20,89 @@ public class FontSplitter { } public float width(TextStyle style, String text, boolean applyStyleChanges) { - TextStyle[] currentStyle = new TextStyle[] {style}; + TextStyle currentStyle = style; float total = 0F; for(int i = 0,m=text.length();i currentStyle[0] = T)) { - i = text.indexOf('>', i)+1; + CodepointSequence result; + if(codepoint == FORMAT_CODE_POINT && applyStyleChanges && (result = Font.findValue(CodepointSequence.of(text, i))) != null) { + currentStyle = currentStyle.parseArguments(style, result.toString().split(",")); + i += result.length()+3; continue; } - total += font.data(style.font(), codepoint).advance(); + total += font.width(currentStyle.font(), codepoint); } return total; } + public String[] split(TextStyle style, String text, boolean applyTextStyles) { + + return null; + } + public static String removeStyleChanges(String input) { + StringBuilder builder = new StringBuilder(input); + for(int i = 0;i=0;i--) { + totalWidth += widths[i]; + if(totalWidth >= maxWidth) return text.substring(i, text.length()); + } + } + else { + float totalWidth = 0F; + for(int i = text.length()-1;i>=0;i--) { + int codepoint = text.codePointAt(i); + totalWidth += font.width(style.font(), codepoint); + if(totalWidth >= maxWidth) return text.substring(i, text.length()); + } + } + return text; + } + + public String splitHeadByWidth(TextStyle style, String text, float maxWidth, boolean applyStyleChanges) { + TextStyle current = style; + float width = 0F; + for(int i = 0,m=text.length();i= maxWidth) return text.substring(0, i); + } + return text; + } } diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/font/TextStyle.java b/src/main/java/speiger/src/coreengine/rendering/gui/font/TextStyle.java index a0152f7..a9595b1 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/font/TextStyle.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/font/TextStyle.java @@ -56,6 +56,7 @@ public record TextStyle(FontStyle font, int styleFlags, int color) { } public TextStyle parseArguments(TextStyle original, String... args) { + if(args == null || args.length <= 0) return this; AssetLocation font = font().font(); boolean bold = font().bold(); boolean italic = font().italic(); diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/renderer/IUIRenderer.java b/src/main/java/speiger/src/coreengine/rendering/gui/renderer/IUIRenderer.java index 6aa28a8..b0eaeaa 100644 --- a/src/main/java/speiger/src/coreengine/rendering/gui/renderer/IUIRenderer.java +++ b/src/main/java/speiger/src/coreengine/rendering/gui/renderer/IUIRenderer.java @@ -1,13 +1,20 @@ package speiger.src.coreengine.rendering.gui.renderer; +import java.util.function.Consumer; + +import speiger.src.coreengine.math.misc.Facing; +import speiger.src.coreengine.math.vector.matrix.Matrix4f; import speiger.src.coreengine.math.vector.quaternion.Quaternion; import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox; +import speiger.src.coreengine.rendering.textures.base.ITexture; public interface IUIRenderer { public boolean isInScissors(IGuiBox box); public void pushScissors(IGuiBox box); public void popScissors(); + public TexturedRect getCachedRect(); + public void flush(); public void pushTransform(); @@ -21,4 +28,28 @@ public interface IUIRenderer { public void scale(float x, float y); public void rotate(Quaternion rotation); + + public void drawCustom(Consumer matrix); + + public void drawLine(float minX, float minY, float maxX, float maxY, float zLevel, int color); + + public default void drawFrame(IGuiBox box, int color) { drawFrame(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), 0F, color); } + public default void drawFrame(IGuiBox box, float zLevel, int color) { drawFrame(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, color); } + public void drawFrame(float minX, float minY, float maxX, float maxY, float zLevel, int color); + + public default void drawRect(IGuiBox box, int color) { drawRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), 0F, color); } + public default void drawRect(IGuiBox box, float zLevel, int color) { drawRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, color); } + public void drawRect(float minX, float minY, float maxX, float maxY, float zLevel, int color); + + public default void drawRect(IGuiBox box, int startColor, int endColor, Facing facing) { drawGradientRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), 0F, startColor, endColor, facing); } + public default void drawRect(IGuiBox box, float zLevel, int startColor, int endColor, Facing facing) { drawGradientRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, startColor, endColor, facing); } + public void drawGradientRect(float minX, float minY, float maxX, float maxY, float zLevel, int startColor, int endColor, Facing facing); + + public default void drawTexturedRect(IGuiBox box, ITexture texture, int color) { drawTexturedRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), 0F, texture.id(), texture.minU(), texture.minV(), texture.maxU(), texture.maxV(), color); } + public default void drawTexturedRect(IGuiBox box, float zLevel, ITexture texture, int color) { drawTexturedRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, texture.id(), texture.minU(), texture.minV(), texture.maxU(), texture.maxV(), color); } + public default void drawTexturedRect(float minX, float minY, float maxX, float maxY, float zLevel, ITexture texture, int color) { drawTexturedRect(minX, minY, maxX, maxY, zLevel, texture.id(), texture.minU(), texture.minV(), texture.maxU(), texture.maxV(), color); } + public default void drawTexturedRect(IGuiBox box, float zLevel, ITexture texture, float minU, float minV, float maxU, float maxV, int color) { drawTexturedRect(box.getMinX(), box.getMinY(), box.getMaxX(), box.getMaxY(), zLevel, texture.id(), minU, minV, maxU, maxV, color); } + public void drawTexturedRect(float minX, float minY, float maxX, float maxY, float zLevel, int texture, float minU, float minV, float maxU, float maxV, int color); + + } diff --git a/src/main/java/speiger/src/coreengine/rendering/gui/renderer/TexturedRect.java b/src/main/java/speiger/src/coreengine/rendering/gui/renderer/TexturedRect.java new file mode 100644 index 0000000..ca3badb --- /dev/null +++ b/src/main/java/speiger/src/coreengine/rendering/gui/renderer/TexturedRect.java @@ -0,0 +1,111 @@ +package speiger.src.coreengine.rendering.gui.renderer; + +import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox; +import speiger.src.coreengine.rendering.textures.base.ITexture; +import speiger.src.coreengine.rendering.textures.base.UVRect; + +public class TexturedRect { + private static final TexturedRect CACHED = new TexturedRect(); + float minX; + float minY; + float maxX; + float maxY; + float zLevel; + int texture; + float minU; + float minV; + float maxU; + float maxV; + int color; + + public static TexturedRect of() { + CACHED.reset(); + return CACHED; + } + + public void draw(IUIRenderer renderer) { + renderer.drawTexturedRect(minX, minY, maxX, maxY, zLevel, texture, minU, minV, maxU, maxV, color); + } + + public TexturedRect area(IGuiBox box) { + this.minX = box.getMinX(); + this.minY = box.getMinY(); + this.maxX = box.getMaxX(); + this.maxY = box.getMaxY(); + return this; + } + + public TexturedRect area(float minX, float minY, float maxX, float maxY) { + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + return this; + } + + public TexturedRect z(float zLevel) { + this.zLevel = zLevel; + return this; + } + + public TexturedRect tex(ITexture texture) { + this.texture = texture.id(); + return this; + } + + public TexturedRect tex(int texture) { + this.texture = texture; + return this; + } + + public TexturedRect color(int color) { + this.color = color; + return this; + } + + public TexturedRect uv() { + this.minU = 0F; + this.minV = 0F; + this.maxU = 1F; + this.maxV = 1F; + return this; + } + + public TexturedRect uv(ITexture texture) { + this.minU = texture.minU(); + this.minV = texture.minV(); + this.maxU = texture.maxU(); + this.maxV = texture.maxV(); + return this; + } + + public TexturedRect uv(UVRect rect) { + this.minU = rect.minU(); + this.minV = rect.minV(); + this.maxU = rect.maxU(); + this.maxV = rect.maxV(); + return this; + } + + public TexturedRect uv(float minU, float minV, float maxU, float maxV) { + this.minU = minU; + this.minV = minV; + this.maxU = maxU; + this.maxV = maxV; + return this; + } + + public void reset() { + minX = 0; + minY = 0; + maxX = 0; + maxY = 0; + zLevel = 0; + texture = 0; + minU = 0F; + minV = 0F; + maxU = 1F; + maxV = 1F; + color = -1; + } +} \ No newline at end of file diff --git a/src/main/java/speiger/src/coreengine/rendering/textures/base/UVRect.java b/src/main/java/speiger/src/coreengine/rendering/textures/base/UVRect.java new file mode 100644 index 0000000..2b51993 --- /dev/null +++ b/src/main/java/speiger/src/coreengine/rendering/textures/base/UVRect.java @@ -0,0 +1,7 @@ +package speiger.src.coreengine.rendering.textures.base; + +public record UVRect(float minU, float minV, float maxU, float maxV) { + public UVRect(ITexture texture) { + this(texture.minU(), texture.minV(), texture.maxU(), texture.maxV()); + } +} diff --git a/src/main/java/speiger/src/coreengine/utils/helpers/TextUtil.java b/src/main/java/speiger/src/coreengine/utils/helpers/TextUtil.java index 77bd950..afea55e 100644 --- a/src/main/java/speiger/src/coreengine/utils/helpers/TextUtil.java +++ b/src/main/java/speiger/src/coreengine/utils/helpers/TextUtil.java @@ -6,6 +6,7 @@ import java.util.Locale; import speiger.src.coreengine.math.misc.ColorUtils; import speiger.src.coreengine.utils.io.GameLog; import speiger.src.coreengine.utils.io.GameLog.LogLevel; +import speiger.src.coreengine.utils.misc.CodepointSequence; public class TextUtil { @@ -26,6 +27,23 @@ public class TextUtil catch (Exception e) { return defaultValue; } } + public static int findEnd(CodepointSequence text, String prefix, String suffix) { + if(!text.startsWith(prefix)) return -1; + int count = 1; + for(int i = prefix.length(),m=text.length()-suffix.length();i", ""); } @@ -88,12 +106,4 @@ public class TextUtil public static String convertTime(long time, String key, DecimalFormat format) { return key + (time >= 1000000 ? format.format(time /= 1000000)+"ms" : (time >= 1000 ? format.format(time /= 1000)+"qs" : format.format(time)+"ns")); } - - public static String repeate(String s, int amount) { - StringBuilder builder = new StringBuilder(); - for(int i = 0;i to || to > parent.length()) { + throw new IndexOutOfBoundsException("Index Out of Bounds: From="+from+", To="+to+" Length="+parent.length()); + } + } + + public OfBuilder(StringBuilder parent, int from) { + this(parent, from, parent.length()); + } + + @Override + public char charAt(int index) { + Objects.checkIndex(index, length()); + return parent.charAt(index+from); + } + + @Override + public int length() { + return to-from; + } + + @Override + public CodepointSequence subSequence(int start, int end) { + Objects.checkFromToIndex(start, end, length()); + return new OfBuilder(parent, from+start, from+end); + } + + @Override + public int codePointAt(int index) { + Objects.checkIndex(index, length()); + return parent.codePointAt(index+from); + } + + @Override + public int codePointBefore(int index) { + Objects.checkIndex(index-1, length()); + return parent.codePointBefore(index+from); + } + + @Override + public int codePointCount(int beginIndex, int endIndex) { + Objects.checkFromToIndex(beginIndex, endIndex, length()); + return parent.codePointCount(beginIndex+from, endIndex+from); + } + + @Override + public int offsetByCodePoints(int index, int codePointOffset) { + Objects.checkFromIndexSize(index, codePointOffset, length()); + return parent.offsetByCodePoints(index+from, codePointOffset); + } + + @Override + public final String toString() { + return parent.substring(from, to); + } + + @Override + public boolean startsWith(String value, int offset) { + if(offset < 0 || length() - offset < value.length()) return false; + for(int i = 0,m=value.length();i to || to > parent.length()) { + throw new IndexOutOfBoundsException("Index Out of Bounds: From="+from+", To="+to+" Length="+parent.length()); + } + } + + public OfString(String parent, int from) { + this(parent, from, parent.length()); + } + + @Override + public int length() { + return to-from; + } + + @Override + public char charAt(int index) { + Objects.checkIndex(index, length()); + return parent.charAt(index+from); + } + + @Override + public CodepointSequence subSequence(int start, int end) { + Objects.checkFromToIndex(start, end, length()); + return new OfString(parent, from+start, from+end); + } + + @Override + public boolean startsWith(String value, int offset) { + if(offset < 0 || value.length() > length()-offset) return false; + return parent.startsWith(value, offset+from); + } + + @Override + public int codePointAt(int index) { + Objects.checkIndex(index, length()); + return parent.codePointAt(index+from); + } + + @Override + public int codePointBefore(int index) { + Objects.checkIndex(index-1, length()); + return parent.codePointBefore(index+from); + } + + @Override + public int codePointCount(int beginIndex, int endIndex) { + Objects.checkFromToIndex(beginIndex, endIndex, length()); + return parent.codePointCount(beginIndex+from, endIndex+from); + } + + @Override + public int offsetByCodePoints(int index, int codePointOffset) { + Objects.checkFromIndexSize(index, codePointOffset, length()); + return parent.offsetByCodePoints(index+from, codePointOffset); + } + + @Override + public final String toString() { + return parent.substring(from, to); + } + } +}