mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-25 06:26:56 +01:00
Pair down parameters per Pepper's pondering
- 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
This commit is contained in:
parent
c3ac594d37
commit
1091a478e1
2 changed files with 56 additions and 98 deletions
|
@ -1,7 +1,6 @@
|
||||||
package dev.engine_room.flywheel.lib.visual.text;
|
package dev.engine_room.flywheel.lib.visual.text;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -53,8 +52,6 @@ public final class TextVisual {
|
||||||
private final Matrix4f pose = new Matrix4f();
|
private final Matrix4f pose = new Matrix4f();
|
||||||
|
|
||||||
private FormattedCharSequence text = FormattedCharSequence.EMPTY;
|
private FormattedCharSequence text = FormattedCharSequence.EMPTY;
|
||||||
private float x;
|
|
||||||
private float y;
|
|
||||||
private int backgroundColor = 0;
|
private int backgroundColor = 0;
|
||||||
private int light;
|
private int light;
|
||||||
|
|
||||||
|
@ -63,91 +60,60 @@ public final class TextVisual {
|
||||||
.createInstance());
|
.createInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextVisual addLayer(TextLayer layer) {
|
public void setup(FormattedCharSequence textLine, List<TextLayer> layers, Matrix4f pose, int light) {
|
||||||
layers.add(layer);
|
// TODO: probably don't store everything
|
||||||
return this;
|
this.text = textLine;
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual addLayers(Collection<TextLayer> layers) {
|
|
||||||
this.layers.addAll(layers);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual layers(Collection<TextLayer> layers) {
|
|
||||||
this.layers.clear();
|
this.layers.clear();
|
||||||
this.layers.addAll(layers);
|
this.layers.addAll(layers);
|
||||||
return this;
|
this.pose.set(pose);
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual clearLayers() {
|
|
||||||
layers.clear();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Matrix4f pose() {
|
|
||||||
return pose;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual text(FormattedCharSequence text) {
|
|
||||||
this.text = text;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual x(float x) {
|
|
||||||
this.x = x;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual y(float y) {
|
|
||||||
this.y = y;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual pos(float x, float y) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual backgroundColor(int backgroundColor) {
|
|
||||||
this.backgroundColor = backgroundColor;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextVisual light(int light) {
|
|
||||||
this.light = light;
|
this.light = light;
|
||||||
return this;
|
|
||||||
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextVisual reset() {
|
public void updateObfuscated() {
|
||||||
|
// TODO: track obfuscated glyphs and update here
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void backgroundColor(int backgroundColor) {
|
||||||
|
// TODO: don't setup the whole thing
|
||||||
|
this.backgroundColor = backgroundColor;
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLight(int packedLight) {
|
||||||
|
// TODO: just iterate over instances and update light
|
||||||
|
light = packedLight;
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setup() {
|
||||||
|
recycler.resetCount();
|
||||||
|
|
||||||
|
var sink = SINKS.get();
|
||||||
|
sink.prepare(recycler, layers, pose, light);
|
||||||
|
|
||||||
|
text.accept(sink);
|
||||||
|
|
||||||
|
sink.addBackground(backgroundColor, 0, sink.x);
|
||||||
|
sink.clear();
|
||||||
|
|
||||||
|
recycler.discardExtra();
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextVisual reset() {
|
||||||
|
// TODO: should this be public? what should it do?
|
||||||
layers.clear();
|
layers.clear();
|
||||||
pose.identity();
|
pose.identity();
|
||||||
|
|
||||||
text = FormattedCharSequence.EMPTY;
|
text = FormattedCharSequence.EMPTY;
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
backgroundColor = 0;
|
backgroundColor = 0;
|
||||||
light = 0;
|
light = 0;
|
||||||
|
|
||||||
return this;
|
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() {
|
public void delete() {
|
||||||
recycler.delete();
|
recycler.delete();
|
||||||
}
|
}
|
||||||
|
@ -196,15 +162,13 @@ public final class TextVisual {
|
||||||
private int light;
|
private int light;
|
||||||
|
|
||||||
private float x;
|
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.recycler = recycler;
|
||||||
this.layers = layers;
|
this.layers = layers;
|
||||||
this.pose = pose;
|
this.pose = pose;
|
||||||
this.light = light;
|
this.light = light;
|
||||||
this.x = x;
|
this.x = 0;
|
||||||
this.y = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
@ -233,7 +197,7 @@ public final class TextVisual {
|
||||||
if (!(glyph instanceof EmptyGlyph)) {
|
if (!(glyph instanceof EmptyGlyph)) {
|
||||||
GlyphInstance instance = recycler.get(key(layer, glyphInfo, glyph, bold));
|
GlyphInstance instance = recycler.get(key(layer, glyphInfo, glyph, bold));
|
||||||
float shadowOffset = glyphInfo.getShadowOffset();
|
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.colorArgb(color);
|
||||||
instance.light(light);
|
instance.light(light);
|
||||||
instance.setChanged();
|
instance.setChanged();
|
||||||
|
@ -241,10 +205,10 @@ public final class TextVisual {
|
||||||
|
|
||||||
// SpecialGlyphs.WHITE, which effects use, has a shadowOffset of 1, so don't modify the offset returned by the layer.
|
// SpecialGlyphs.WHITE, which effects use, has a shadowOffset of 1, so don't modify the offset returned by the layer.
|
||||||
if (style.isStrikethrough()) {
|
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()) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +224,7 @@ public final class TextVisual {
|
||||||
var glyphExtension = FlwLibLink.INSTANCE.getBakedGlyphExtension(glyph);
|
var glyphExtension = FlwLibLink.INSTANCE.getBakedGlyphExtension(glyph);
|
||||||
|
|
||||||
GlyphInstance instance = recycler.get(effectKey(glyphExtension.flywheel$texture(), TextLayer.GlyphMaterial.SEE_THROUGH, 0));
|
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.colorArgb(backgroundColor);
|
||||||
instance.light(light);
|
instance.light(light);
|
||||||
instance.setChanged();
|
instance.setChanged();
|
||||||
|
|
|
@ -60,6 +60,8 @@ public class SignVisual extends AbstractBlockEntityVisual<SignBlockEntity> imple
|
||||||
// Most of the time this will be empty.
|
// Most of the time this will be empty.
|
||||||
private final List<TextVisual> obfuscated = new ArrayList<>();
|
private final List<TextVisual> obfuscated = new ArrayList<>();
|
||||||
|
|
||||||
|
private int packedLight = 0;
|
||||||
|
|
||||||
private SignText lastFrontText;
|
private SignText lastFrontText;
|
||||||
private SignText lastBackText;
|
private SignText lastBackText;
|
||||||
|
|
||||||
|
@ -127,14 +129,14 @@ public class SignVisual extends AbstractBlockEntityVisual<SignBlockEntity> imple
|
||||||
// The is visible check is relatively expensive compared to the boolean checks above,
|
// 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.
|
// so only do it when it'll actually save some work in obfuscating.
|
||||||
if (isVisible(ctx.frustum())) {
|
if (isVisible(ctx.frustum())) {
|
||||||
obfuscated.forEach(TextVisual::setup);
|
obfuscated.forEach(TextVisual::updateObfuscated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLight(float partialTick) {
|
public void updateLight(float partialTick) {
|
||||||
int packedLight = computePackedLight();
|
packedLight = computePackedLight();
|
||||||
instances.traverse(instance -> {
|
instances.traverse(instance -> {
|
||||||
instance.light(packedLight)
|
instance.light(packedLight)
|
||||||
.setChanged();
|
.setChanged();
|
||||||
|
@ -142,15 +144,13 @@ public class SignVisual extends AbstractBlockEntityVisual<SignBlockEntity> imple
|
||||||
|
|
||||||
if (!lastFrontText.hasGlowingText()) {
|
if (!lastFrontText.hasGlowingText()) {
|
||||||
for (var text : frontTextVisuals) {
|
for (var text : frontTextVisuals) {
|
||||||
text.light(packedLight);
|
text.updateLight(packedLight);
|
||||||
text.setup();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lastBackText.hasGlowingText()) {
|
if (!lastBackText.hasGlowingText()) {
|
||||||
for (var text : backTextVisuals) {
|
for (var text : backTextVisuals) {
|
||||||
text.light(packedLight);
|
text.updateLight(packedLight);
|
||||||
text.setup();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,12 +216,7 @@ public class SignVisual extends AbstractBlockEntityVisual<SignBlockEntity> imple
|
||||||
float x = (float) (-FONT.width(textLine) / 2);
|
float x = (float) (-FONT.width(textLine) / 2);
|
||||||
float y = i * lineHeight - lineDelta;
|
float y = i * lineHeight - lineDelta;
|
||||||
|
|
||||||
var textVisual = textVisuals[i].layers(layers)
|
var pose = new Matrix4f(initialPose);
|
||||||
.text(textLine)
|
|
||||||
.pos(x, y)
|
|
||||||
.backgroundColor(0);
|
|
||||||
|
|
||||||
var pose = textVisual.pose().set(initialPose);
|
|
||||||
if (!isFrontText) {
|
if (!isFrontText) {
|
||||||
pose.rotateY(Mth.PI);
|
pose.rotateY(Mth.PI);
|
||||||
}
|
}
|
||||||
|
@ -229,13 +224,12 @@ public class SignVisual extends AbstractBlockEntityVisual<SignBlockEntity> imple
|
||||||
var textOffset = getTextOffset();
|
var textOffset = getTextOffset();
|
||||||
pose.translate((float) textOffset.x, (float) textOffset.y, (float) textOffset.z);
|
pose.translate((float) textOffset.x, (float) textOffset.y, (float) textOffset.z);
|
||||||
pose.scale(scale, -scale, scale);
|
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)) {
|
if (hasObfuscation(textLine)) {
|
||||||
obfuscated.add(textVisual);
|
obfuscated.add(textVisual);
|
||||||
|
|
Loading…
Reference in a new issue