More progress on Fonts and layouts.
This commit is contained in:
parent
9ba9e81686
commit
8d7c7d2d97
|
@ -47,7 +47,7 @@ public interface ILayoutComponent {
|
|||
public ArrayFetcher(boolean includeInvisible) {
|
||||
this.includeInvisible = includeInvisible;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean acceptsInvisble() {
|
||||
return includeInvisible;
|
||||
|
@ -61,8 +61,27 @@ public interface ILayoutComponent {
|
|||
result[INDEX_MAX_Y] = Math.max(maxY, result[INDEX_MAX_Y]);
|
||||
}
|
||||
|
||||
public float[] getResult() {
|
||||
public void reset() {
|
||||
result[0] = Float.MAX_VALUE;
|
||||
result[1] = Float.MAX_VALUE;
|
||||
result[2] = -Float.MAX_VALUE;
|
||||
result[3] = -Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
public void hardReset() {
|
||||
result = new float[] {Float.MAX_VALUE, Float.MAX_VALUE, -Float.MAX_VALUE, -Float.MAX_VALUE};
|
||||
}
|
||||
|
||||
public float[] result() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public float[] unscaledResult(IGuiBox owner) {
|
||||
float[] unscaled = new float[4];
|
||||
for(int i = 0;i<4;i++) {
|
||||
unscaled[i] = result[i] / owner.getScale();
|
||||
}
|
||||
return unscaled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import speiger.src.coreengine.rendering.gui.font.glyth.UnbakedGlyth.GlythBaker;
|
|||
import speiger.src.coreengine.rendering.tesselation.buffer.IVertexBuilder;
|
||||
|
||||
public class Font {
|
||||
public static final FontStyle DEFAULT = new FontStyle(AssetLocation.of("default"), 18);
|
||||
public static final FontStyle DEFAULT = new FontStyle(AssetLocation.of("default"), 0, 18F);
|
||||
|
||||
Map<AssetLocation, FontGroup> fonts;
|
||||
GlythBaker baker;
|
||||
|
@ -30,12 +30,12 @@ public class Font {
|
|||
}
|
||||
}
|
||||
|
||||
public GlythData data(FontStyle font, int codepoint, int style) {
|
||||
return styledCache[style & 0x3].data(font, codepoint);
|
||||
public GlythData data(FontStyle font, int codepoint) {
|
||||
return styledCache[font.style() & 0x3].data(font, codepoint);
|
||||
}
|
||||
|
||||
public Glyth glyth(FontStyle font, int codepoint, int style) {
|
||||
return styledCache[style & 0x3].glyth(font, codepoint);
|
||||
public Glyth glyth(FontStyle font, int codepoint) {
|
||||
return styledCache[font.style() & 0x3].glyth(font, codepoint);
|
||||
}
|
||||
|
||||
protected FontGroup font(AssetLocation font) {
|
||||
|
@ -51,11 +51,11 @@ public class Font {
|
|||
int previousCodepoint = -1;
|
||||
for(int i = 0,m=text.length();i<m;) {
|
||||
int codepoint = text.codePointAt(i);
|
||||
GlythData data = data(style, codepoint, 0);
|
||||
GlythData data = data(style, codepoint);
|
||||
if(previousCodepoint != -1) {
|
||||
x -= data.kerning(previousCodepoint);
|
||||
}
|
||||
Glyth glyth = glyth(style, codepoint, 0);
|
||||
Glyth glyth = glyth(style, codepoint);
|
||||
if(glyth.isValid()) {
|
||||
float minX = glyth.left() + x;
|
||||
float minY = glyth.top() + y;
|
||||
|
|
|
@ -2,17 +2,57 @@ package speiger.src.coreengine.rendering.gui.font;
|
|||
|
||||
import speiger.src.coreengine.assets.AssetLocation;
|
||||
|
||||
public record FontStyle(AssetLocation font, float size) {
|
||||
public record FontStyle(AssetLocation font, int style, float size) {
|
||||
public static final int REGULAR = 0;
|
||||
public static final int BOLD = 1;
|
||||
public static final int ITALIC = 2;
|
||||
public static final int BOLD_ITCALIC = 3;
|
||||
|
||||
public FontStyle {
|
||||
if(style < 0 || style > 3) throw new IllegalArgumentException("Style can only be between 0-3. Style found: "+style);
|
||||
}
|
||||
|
||||
public FontStyle(AssetLocation font, float size) {
|
||||
this(font, REGULAR, size);
|
||||
}
|
||||
|
||||
public FontStyle(AssetLocation font, boolean bold, boolean italic, float size) {
|
||||
this(font, (bold ? BOLD : 0) | (italic ? ITALIC : 0), size);
|
||||
}
|
||||
|
||||
public FontStyle with(AssetLocation font, int style, float size) {
|
||||
return new FontStyle(font, style, size);
|
||||
}
|
||||
|
||||
public FontStyle with(AssetLocation font, float size) {
|
||||
return new FontStyle(font, size);
|
||||
return new FontStyle(font, style, size);
|
||||
}
|
||||
|
||||
public FontStyle with(AssetLocation font) {
|
||||
return new FontStyle(font, size);
|
||||
return new FontStyle(font, style, size);
|
||||
}
|
||||
|
||||
public FontStyle with(float size) {
|
||||
return new FontStyle(font, size);
|
||||
return new FontStyle(font, style, size);
|
||||
}
|
||||
}
|
||||
|
||||
public FontStyle with(int style) {
|
||||
return new FontStyle(font, style, size);
|
||||
}
|
||||
|
||||
public FontStyle withBold(boolean bold) {
|
||||
return new FontStyle(font, bold ? (style | BOLD) : (style & ~BOLD), size);
|
||||
}
|
||||
|
||||
public FontStyle withItalic(boolean italic) {
|
||||
return new FontStyle(font, italic ? (style | ITALIC) : (style & ~ITALIC), size);
|
||||
}
|
||||
|
||||
public boolean bold() {
|
||||
return (style() & BOLD) != 0;
|
||||
}
|
||||
|
||||
public boolean italic() {
|
||||
return (style() & ITALIC) != 0;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package speiger.src.coreengine.rendering.gui.layout.constraints;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import speiger.src.coreengine.rendering.gui.components.base.GuiComponent;
|
||||
|
@ -32,6 +33,26 @@ public class Constraints {
|
|||
}
|
||||
}
|
||||
|
||||
public static record Children(float padding, boolean includeChildOffsets) implements ISimpleConstraint {
|
||||
|
||||
public static Children onlyBounds() { return new Children(0F, false); }
|
||||
public static Children onlyBounds(float padding) { return new Children(padding, false); }
|
||||
public static Children withPos() { return new Children(0F, true); }
|
||||
public static Children withPos(float padding) { return new Children(padding, true); }
|
||||
|
||||
@Override
|
||||
public void apply(IGuiBox owner, IGuiBox parent, Target target) {
|
||||
if(target.isPosition()) return;
|
||||
float value = 0F;
|
||||
List<IGuiBox> children = owner.children();
|
||||
for(int i = 0,m=children.size();i<m;i++) {
|
||||
IGuiBox child = children.get(i);
|
||||
value = Math.max(value, child.getBaseX() + (includeChildOffsets() ? child.getBaseWidth() : 0));
|
||||
}
|
||||
target.set(owner, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static record Relative(float value, float padding) implements ISimpleConstraint {
|
||||
|
||||
public static Relative of(float value) { return new Relative(value, 0F); }
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.function.BooleanSupplier;
|
|||
|
||||
import speiger.src.coreengine.rendering.gui.components.base.GuiComponent;
|
||||
import speiger.src.coreengine.rendering.gui.layout.constraints.Constraints.Center;
|
||||
import speiger.src.coreengine.rendering.gui.layout.constraints.Constraints.Children;
|
||||
import speiger.src.coreengine.rendering.gui.layout.constraints.Constraints.Conditional;
|
||||
import speiger.src.coreengine.rendering.gui.layout.constraints.Constraints.Parent;
|
||||
import speiger.src.coreengine.rendering.gui.layout.constraints.Constraints.Pixels;
|
||||
|
@ -13,7 +14,6 @@ import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;
|
|||
public interface IConstraint {
|
||||
public void apply(GuiComponent owner, GuiComponent child, Target target);
|
||||
|
||||
|
||||
public static IConstraint pixels(float value) { return Pixels.of(value); }
|
||||
public static IConstraint pixelsInv(float value) { return Pixels.inverted(value); }
|
||||
|
||||
|
@ -22,6 +22,11 @@ public interface IConstraint {
|
|||
public static IConstraint parentInv() { return Parent.inverted(); }
|
||||
public static IConstraint parentInv(float padding) { return Parent.inverted(padding); }
|
||||
|
||||
public static IConstraint children() { return Children.onlyBounds(); }
|
||||
public static IConstraint children(float padding) { return Children.onlyBounds(padding); }
|
||||
public static IConstraint childrenPos() { return Children.withPos(); }
|
||||
public static IConstraint childrenPos(float padding) { return Children.withPos(padding); }
|
||||
|
||||
public static IConstraint relative(float value) { return Relative.of(value); }
|
||||
public static IConstraint relative(float value, float padding) { return Relative.of(value, padding); }
|
||||
|
||||
|
@ -59,8 +64,8 @@ public interface IConstraint {
|
|||
|
||||
public float get(IGuiBox box) {
|
||||
return switch(this) {
|
||||
case X -> box.getMinX();
|
||||
case Y -> box.getMinY();
|
||||
case X -> box.getBaseX();
|
||||
case Y -> box.getBaseY();
|
||||
case WIDTH -> box.getBaseWidth();
|
||||
case HEIGHT -> box.getBaseHeight();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
package speiger.src.coreengine.rendering.gui.layout.layouts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.coreengine.rendering.gui.components.base.GuiComponent;
|
||||
import speiger.src.coreengine.rendering.gui.components.base.ILayoutComponent.ArrayFetcher;
|
||||
import speiger.src.coreengine.rendering.guiOld.helper.box.IGuiBox;
|
||||
|
||||
public class FlowLayout implements ILayout<Object> {
|
||||
private static final int ALIGN_DISABLED = -1;
|
||||
public static final int ALIGN_START = 0;
|
||||
public static final int ALIGN_CENTER = 1;
|
||||
public static final int ALIGN_END = 2;
|
||||
|
||||
private List<GuiComponent> comps = new ObjectArrayList<>();
|
||||
protected float xGap;
|
||||
protected float yGap;
|
||||
protected int direction = ALIGN_END;
|
||||
protected int verticalAlignement = ALIGN_DISABLED;
|
||||
protected boolean includeInvisible = false;
|
||||
protected boolean isVertical = false;
|
||||
|
||||
|
||||
public FlowLayout(int direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public FlowLayout(float xGap, float yGap) {
|
||||
this.xGap = xGap;
|
||||
this.yGap = yGap;
|
||||
}
|
||||
|
||||
public FlowLayout(float xGap, float yGap, int direction) {
|
||||
this.xGap = xGap;
|
||||
this.yGap = yGap;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public FlowLayout verticalAlign(int alignment) {
|
||||
verticalAlignement = Math.clamp(alignment, -1, 2);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlowLayout includeInvisible() {
|
||||
includeInvisible = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FlowLayout vertical(boolean value) {
|
||||
isVertical = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowLayout add(GuiComponent comp, Object value) {
|
||||
comps.add(comp);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlowLayout remove(GuiComponent comp) {
|
||||
comps.remove(comp);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(GuiComponent owner) {
|
||||
int size = comps.size();
|
||||
float max = isVertical ? owner.getBox().getBaseHeight() : owner.getBox().getBaseWidth();
|
||||
float x = xGap;
|
||||
float y = yGap;
|
||||
float[] heights = new float[size];
|
||||
float[] widths = new float[size];
|
||||
int startIndex = 0;
|
||||
ArrayFetcher fetcher = new ArrayFetcher(includeInvisible);
|
||||
for(int i = 0,m=comps.size();i<m;i++) {
|
||||
comps.get(i).calculateBounds(fetcher);
|
||||
float[] bounds = fetcher.unscaledResult(owner.getBox());
|
||||
float width = bounds[2] - bounds[0];
|
||||
float height = bounds[3] - bounds[1];
|
||||
widths[i] = width;
|
||||
heights[i] = height;
|
||||
if(isVertical) {
|
||||
if(y + height + yGap > max) {
|
||||
x += processComponents(startIndex, i, x, max, y, widths, heights);
|
||||
y = yGap;
|
||||
startIndex = i;
|
||||
}
|
||||
y += height + yGap;
|
||||
fetcher.reset();
|
||||
continue;
|
||||
}
|
||||
else if(x + width + xGap > max) {
|
||||
y += processComponents(startIndex, i, y, max, x, widths, heights);
|
||||
x = xGap;
|
||||
startIndex = i;
|
||||
}
|
||||
x += width + xGap;
|
||||
fetcher.reset();
|
||||
}
|
||||
processComponents(startIndex, size, y, max, x, widths, heights);
|
||||
}
|
||||
|
||||
private void setX(IGuiBox box, float x) {
|
||||
if(isVertical) box.setY(x);
|
||||
else box.setX(x);
|
||||
}
|
||||
|
||||
private void setY(IGuiBox box, float y) {
|
||||
if(isVertical) box.setX(y);
|
||||
else box.setY(y);
|
||||
}
|
||||
|
||||
private float processComponents(int start, int end, float yStart, float maxWidth, float widthSum, float[] widths, float[] heights) {
|
||||
float x = calculateStartPos(start, end, maxWidth, widthSum);
|
||||
float yAligner = 0F;
|
||||
if(verticalAlignement > 0) {
|
||||
for(int i = start;i<end;i++) {
|
||||
yAligner = Math.max(yAligner, isVertical ? (verticalAlignement == 2 ? widths[i] * 0.5F : widths[i]) : (verticalAlignement == 2 ? heights[i] * 0.5F : heights[i]));
|
||||
}
|
||||
}
|
||||
float jump = yAligner;
|
||||
yAligner += yStart;
|
||||
|
||||
for(int i = start;i<end;i++) {
|
||||
IGuiBox box = comps.get(i).getBox();
|
||||
setX(box, x);
|
||||
switch(verticalAlignement) {
|
||||
case ALIGN_DISABLED: break;
|
||||
case ALIGN_START: {
|
||||
setY(box, yStart);
|
||||
break;
|
||||
}
|
||||
case ALIGN_CENTER: {
|
||||
setY(box, yAligner - heights[i] * 0.5F);
|
||||
break;
|
||||
}
|
||||
case ALIGN_END: {
|
||||
setY(box, yAligner);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(direction == ALIGN_END) x -= widths[i] + (isVertical ? yGap : xGap);
|
||||
else x += widths[i] + (isVertical ? yGap : xGap);
|
||||
}
|
||||
return jump;
|
||||
}
|
||||
|
||||
private float calculateStartPos(int start, int end, float ownerWidth, float widthSum) {
|
||||
return switch(direction) {
|
||||
case ALIGN_CENTER -> ownerWidth * 0.5F - widthSum * 0.5F;
|
||||
case ALIGN_END -> ownerWidth - xGap;
|
||||
default -> xGap;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
package speiger.src.coreengine.rendering.gui.layout.layouts;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import speiger.src.coreengine.rendering.gui.components.base.GuiComponent;
|
||||
|
||||
public interface ILayout {
|
||||
public default ILayout add(GuiComponent comp) { return add(comp, null); }
|
||||
public ILayout add(GuiComponent comp, Object value);
|
||||
public ILayout remove(GuiComponent comp);
|
||||
public interface ILayout<T> extends Consumer<GuiComponent> {
|
||||
public default ILayout<T> add(GuiComponent comp) { return add(comp, null); }
|
||||
public ILayout<T> add(GuiComponent comp, T value);
|
||||
public ILayout<T> remove(GuiComponent comp);
|
||||
|
||||
public void apply();
|
||||
public void apply(GuiComponent owner);
|
||||
@Override
|
||||
default void accept(GuiComponent t) { apply(t); }
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@ package speiger.src.coreengine.rendering.guiOld.helper.box;
|
|||
import java.util.List;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.lists.ObjectList;
|
||||
|
||||
public class GuiBox implements IGuiBox
|
||||
{
|
||||
List<IGuiBox> children = new ObjectArrayList<>();
|
||||
ObjectList<IGuiBox> children = new ObjectArrayList<>();
|
||||
IGuiBox parent;
|
||||
|
||||
float minX;
|
||||
|
@ -62,6 +63,11 @@ public class GuiBox implements IGuiBox
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IGuiBox> children() {
|
||||
return children.unmodifiable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGuiBox onChanged() {
|
||||
minX = parent == null ? baseX : parent.getMinX(baseX);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package speiger.src.coreengine.rendering.guiOld.helper.box;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import speiger.src.coreengine.math.misc.Facing;
|
||||
import speiger.src.coreengine.math.misc.FacingList;
|
||||
|
||||
|
@ -8,6 +10,7 @@ public interface IGuiBox extends IScreenBox
|
|||
public IGuiBox addChild(IGuiBox box);
|
||||
public IGuiBox removeChild(IGuiBox box);
|
||||
public IGuiBox clearChildren();
|
||||
public List<IGuiBox> children();
|
||||
public IGuiBox setParent(IGuiBox box);
|
||||
public IGuiBox getParent();
|
||||
public IGuiBox onChanged();
|
||||
|
|
|
@ -3,10 +3,11 @@ package speiger.src.coreengine.rendering.guiOld.helper.box;
|
|||
import java.util.List;
|
||||
|
||||
import speiger.src.collections.objects.lists.ObjectArrayList;
|
||||
import speiger.src.collections.objects.lists.ObjectList;
|
||||
|
||||
public class ParentBox implements IGuiBox
|
||||
{
|
||||
List<IGuiBox> children = new ObjectArrayList<>();
|
||||
ObjectList<IGuiBox> children = new ObjectArrayList<>();
|
||||
IGuiBox parent;
|
||||
|
||||
float minX;
|
||||
|
@ -50,6 +51,11 @@ public class ParentBox implements IGuiBox
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IGuiBox> children() {
|
||||
return children.unmodifiable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGuiBox onChanged() {
|
||||
for(int i = 0,m=children.size();i<m;i++) {
|
||||
|
|
Loading…
Reference in New Issue