Skip to content

Commit

Permalink
Pair down parameters per Pepper's pondering
Browse files Browse the repository at this point in the history
- Flatten TextVisual API to be less of a parameter container
- This is mostly a surface change
- Do not accept x and y positions, instead force the user to translate
  in their matrix
- Track light from light updates to apply when setting up text
- Add (unoptimized) updateLight, backgroundColor, and updateObfuscated
  methods to TextVisual
  • Loading branch information
Jozufozu committed Oct 10, 2024
1 parent c3ac594 commit 1091a47
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dev.engine_room.flywheel.lib.visual.text;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -53,8 +52,6 @@ public final class TextVisual {
private final Matrix4f pose = new Matrix4f();

private FormattedCharSequence text = FormattedCharSequence.EMPTY;
private float x;
private float y;
private int backgroundColor = 0;
private int light;

Expand All @@ -63,91 +60,60 @@ public TextVisual(InstancerProvider provider) {
.createInstance());
}

public TextVisual addLayer(TextLayer layer) {
layers.add(layer);
return this;
}

public TextVisual addLayers(Collection<TextLayer> layers) {
this.layers.addAll(layers);
return this;
}

public TextVisual layers(Collection<TextLayer> layers) {
public void setup(FormattedCharSequence textLine, List<TextLayer> layers, Matrix4f pose, int light) {
// TODO: probably don't store everything
this.text = textLine;
this.layers.clear();
this.layers.addAll(layers);
return this;
}
this.pose.set(pose);
this.light = light;

public TextVisual clearLayers() {
layers.clear();
return this;
setup();
}

public Matrix4f pose() {
return pose;
public void updateObfuscated() {
// TODO: track obfuscated glyphs and update here
setup();
}

public TextVisual text(FormattedCharSequence text) {
this.text = text;
return this;
public void backgroundColor(int backgroundColor) {
// TODO: don't setup the whole thing
this.backgroundColor = backgroundColor;
setup();
}

public TextVisual x(float x) {
this.x = x;
return this;
public void updateLight(int packedLight) {
// TODO: just iterate over instances and update light
light = packedLight;
setup();
}

public TextVisual y(float y) {
this.y = y;
return this;
}
private void setup() {
recycler.resetCount();

public TextVisual pos(float x, float y) {
this.x = x;
this.y = y;
return this;
}
var sink = SINKS.get();
sink.prepare(recycler, layers, pose, light);

public TextVisual backgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
return this;
}
text.accept(sink);

public TextVisual light(int light) {
this.light = light;
return this;
sink.addBackground(backgroundColor, 0, sink.x);
sink.clear();

recycler.discardExtra();
}

public TextVisual reset() {
private TextVisual reset() {
// TODO: should this be public? what should it do?
layers.clear();
pose.identity();

text = FormattedCharSequence.EMPTY;
x = 0;
y = 0;
backgroundColor = 0;
light = 0;

return this;
}

// TODO: track glyph instances and add method to update only UVs of obfuscated glyphs, method to update only
// background color, and method to only update light
public void setup() {
recycler.resetCount();

var sink = SINKS.get();
sink.prepare(recycler, layers, pose, light, x, y);

text.accept(sink);

sink.addBackground(backgroundColor, x, sink.x);
sink.clear();

recycler.discardExtra();
}

public void delete() {
recycler.delete();
}
Expand Down Expand Up @@ -196,15 +162,13 @@ private static class Sink implements FormattedCharSink {
private int light;

private float x;
private float y;

public void prepare(SmartRecycler<GlyphInstanceKey, GlyphInstance> recycler, List<TextLayer> layers, Matrix4f pose, int light, float x, float y) {
public void prepare(SmartRecycler<GlyphInstanceKey, GlyphInstance> recycler, List<TextLayer> layers, Matrix4f pose, int light) {
this.recycler = recycler;
this.layers = layers;
this.pose = pose;
this.light = light;
this.x = x;
this.y = y;
this.x = 0;
}

public void clear() {
Expand Down Expand Up @@ -233,18 +197,18 @@ public boolean accept(int index, Style style, int codePoint) {
if (!(glyph instanceof EmptyGlyph)) {
GlyphInstance instance = recycler.get(key(layer, glyphInfo, glyph, bold));
float shadowOffset = glyphInfo.getShadowOffset();
instance.setGlyph(glyph, pose, x + offset.x() * shadowOffset, y + offset.y() * shadowOffset, style.isItalic());
instance.setGlyph(glyph, pose, x + offset.x() * shadowOffset, offset.y() * shadowOffset, style.isItalic());
instance.colorArgb(color);
instance.light(light);
instance.setChanged();
}

// SpecialGlyphs.WHITE, which effects use, has a shadowOffset of 1, so don't modify the offset returned by the layer.
if (style.isStrikethrough()) {
addEffect(layer, x + offset.x() - 1.0f, y + offset.y() + 4.5f, x + offset.x() + advance, y + offset.y() + 4.5f - 1.0f, 0.01f, color);
addEffect(layer, x + offset.x() - 1.0f, offset.y() + 4.5f, x + offset.x() + advance, offset.y() + 4.5f - 1.0f, 0.01f, color);
}
if (style.isUnderlined()) {
addEffect(layer, x + offset.x() - 1.0f, y + offset.y() + 9.0f, x + offset.x() + advance, y + offset.y() + 9.0f - 1.0f, 0.01f, color);
addEffect(layer, x + offset.x() - 1.0f, offset.y() + 9.0f, x + offset.x() + advance, offset.y() + 9.0f - 1.0f, 0.01f, color);
}
}

Expand All @@ -260,7 +224,7 @@ public void addBackground(int backgroundColor, float startX, float endX) {
var glyphExtension = FlwLibLink.INSTANCE.getBakedGlyphExtension(glyph);

GlyphInstance instance = recycler.get(effectKey(glyphExtension.flywheel$texture(), TextLayer.GlyphMaterial.SEE_THROUGH, 0));
instance.setEffect(glyph, pose, startX - 1.0f, y + 9.0f, endX + 1.0f, y - 1.0f, 0.01f);
instance.setEffect(glyph, pose, startX - 1.0f, 9.0f, endX + 1.0f, 1.0f, 0.01f);
instance.colorArgb(backgroundColor);
instance.light(light);
instance.setChanged();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ public class SignVisual extends AbstractBlockEntityVisual<SignBlockEntity> imple
// Most of the time this will be empty.
private final List<TextVisual> obfuscated = new ArrayList<>();

private int packedLight = 0;

private SignText lastFrontText;
private SignText lastBackText;

Expand Down Expand Up @@ -127,30 +129,28 @@ public void beginFrame(Context ctx) {
// The is visible check is relatively expensive compared to the boolean checks above,
// so only do it when it'll actually save some work in obfuscating.
if (isVisible(ctx.frustum())) {
obfuscated.forEach(TextVisual::setup);
obfuscated.forEach(TextVisual::updateObfuscated);
}
}
}

@Override
public void updateLight(float partialTick) {
int packedLight = computePackedLight();
packedLight = computePackedLight();
instances.traverse(instance -> {
instance.light(packedLight)
.setChanged();
});

if (!lastFrontText.hasGlowingText()) {
for (var text : frontTextVisuals) {
text.light(packedLight);
text.setup();
text.updateLight(packedLight);
}
}

if (!lastBackText.hasGlowingText()) {
for (var text : backTextVisuals) {
text.light(packedLight);
text.setup();
text.updateLight(packedLight);
}
}
}
Expand Down Expand Up @@ -216,26 +216,20 @@ private void setupText(SignText text, boolean isFrontText) {
float x = (float) (-FONT.width(textLine) / 2);
float y = i * lineHeight - lineDelta;

var textVisual = textVisuals[i].layers(layers)
.text(textLine)
.pos(x, y)
.backgroundColor(0);

var pose = textVisual.pose().set(initialPose);
var pose = new Matrix4f(initialPose);
if (!isFrontText) {
pose.rotateY(Mth.PI);
}
float scale = 0.015625f * getSignTextRenderScale();
var textOffset = getTextOffset();
pose.translate((float) textOffset.x, (float) textOffset.y, (float) textOffset.z);
pose.scale(scale, -scale, scale);
pose.translate(x, y, 0.0f);

if (text.hasGlowingText()) {
textVisual.light(LightTexture.FULL_BRIGHT);
}
// FIXME: incorrect light when going from glowing to non-glowing

textVisual.setup();
var textVisual = textVisuals[i];
int light = text.hasGlowingText() ? LightTexture.FULL_BRIGHT : packedLight;
textVisual.setup(textLine, layers, pose, light);

if (hasObfuscation(textLine)) {
obfuscated.add(textVisual);
Expand Down

0 comments on commit 1091a47

Please sign in to comment.