Skip to content

Commit

Permalink
port to rich text
Browse files Browse the repository at this point in the history
  • Loading branch information
ghzdude committed Jan 9, 2025
1 parent 36a9249 commit 55fefcd
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@
import net.minecraft.util.text.TextFormatting;

import com.cleanroommc.modularui.api.drawable.IDrawable;
import com.cleanroommc.modularui.api.drawable.IHoverable;
import com.cleanroommc.modularui.api.drawable.IKey;
import com.cleanroommc.modularui.api.drawable.IRichTextBuilder;
import com.cleanroommc.modularui.api.widget.ITooltip;
import com.cleanroommc.modularui.api.widget.IWidget;
import com.cleanroommc.modularui.drawable.text.DynamicKey;
import com.cleanroommc.modularui.drawable.text.RichText;
import com.cleanroommc.modularui.factory.PosGuiData;
import com.cleanroommc.modularui.screen.ModularPanel;
import com.cleanroommc.modularui.screen.RichTooltip;
import com.cleanroommc.modularui.screen.viewport.GuiContext;
import com.cleanroommc.modularui.theme.WidgetTheme;
import com.cleanroommc.modularui.utils.Alignment;
import com.cleanroommc.modularui.value.sync.BooleanSyncValue;
import com.cleanroommc.modularui.value.sync.IntSyncValue;
Expand All @@ -33,29 +39,30 @@
import com.cleanroommc.modularui.widget.ScrollWidget;
import com.cleanroommc.modularui.widget.Widget;
import com.cleanroommc.modularui.widget.scroll.VerticalScrollData;
import com.cleanroommc.modularui.widget.sizer.Area;
import com.cleanroommc.modularui.widget.sizer.Box;
import com.cleanroommc.modularui.widgets.CycleButtonWidget;
import com.cleanroommc.modularui.widgets.ProgressWidget;
import com.cleanroommc.modularui.widgets.RichTextWidget;
import com.cleanroommc.modularui.widgets.SlotGroupWidget;
import com.cleanroommc.modularui.widgets.layout.Column;
import com.cleanroommc.modularui.widgets.layout.Flow;
import com.cleanroommc.modularui.widgets.layout.Row;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.DoubleSupplier;
import java.util.function.Function;
import java.util.function.IntSupplier;
import java.util.function.Supplier;

import static com.cleanroommc.modularui.api.drawable.IKey.renderer;

public class MultiblockUIFactory {

private final MultiblockWithDisplayBase mte;
Expand Down Expand Up @@ -144,7 +151,7 @@ private Widget<?> createIndicator() {
.pos(174 - 5, screenHeight - 18 - 3)
.onUpdateListener(w -> w.overlay(getIndicatorOverlay(builder)))
.tooltip(tooltip -> tooltip.setAutoUpdate(true))
.tooltipBuilder(tooltip -> tooltip.addDrawableLines(builder.getTextList()));
.tooltipBuilder(builder::buildTooltip);
}

private IDrawable getIndicatorOverlay(Builder builder) {
Expand Down Expand Up @@ -308,27 +315,29 @@ public MultiblockUIFactory customScreen(Supplier<ParentWidget<?>> customScreen)
protected Widget<?> createScreen(PanelSyncManager syncManager) {
final var builder = builder();
this.displayText.accept(builder);
var col = new Column();
builder.build(col);
RichTextWidget widget = new RichTextWidget();
builder.buildDisplay(widget);
final var compare = builder();

return new ParentWidget<>()
.child(createIndicator())
.child(customScreen != null ? customScreen.get() : new ScrollWidget<>(new VerticalScrollData())
.sizeRel(1f)
.child(col.expanded()
.child(widget.sizeRel(1f)
.alignment(Alignment.TopLeft)
.margin(4, 4)
.onUpdateListener(column -> {
// really debating on if the display screen should be its own widget
compare.clear();
// compare.clear();
this.displayText.accept(compare);
if (!builder.hasChanged(compare) && !dirty) return;
builder.clear();
column.getChildren().clear();
this.displayText.accept(builder);
builder.build(column);
resize(column);
dirty = false;
// if (!builder.hasChanged(compare) && !dirty) return;
// builder.clear();
if (builder.hasChanged(compare))
widget.markDirty();
// this.displayText.accept(builder);
// builder.build(column);
// resize(column);
// dirty = false;
})))
.background(GTGuiTextures.DISPLAY)
.size(190, screenHeight)
Expand Down Expand Up @@ -465,9 +474,11 @@ protected static Builder builder() {
@SuppressWarnings({ "UnusedReturnValue", "unused" })
public static class Builder {

private final List<IDrawable> textList;
private Function<IDrawable, Widget<?>> widgetFunction = Builder::keyMapper;
private final Int2ObjectMap<IDrawable> tooltips = new Int2ObjectArrayMap<>();
private final RichText text = new RichText();
private final List<Consumer<IRichTextBuilder<? extends IRichTextBuilder<?>>>> textList = new ArrayList<>();
// private final List<IDrawable> textList;
// private Function<IDrawable, Widget<?>> widgetFunction = Builder::keyMapper;
// private final Int2ObjectMap<IDrawable> tooltips = new Int2ObjectArrayMap<>();

private BooleanSupplier isWorkingEnabled = () -> false;
private BooleanSupplier isActive = () -> false;
Expand All @@ -479,15 +490,15 @@ public static class Builder {
private IKey runningKey = IKey.lang("gregtech.multiblock.running").format(TextFormatting.GREEN);
private boolean dirty;

protected static Widget<?> keyMapper(IDrawable key) {
return key.asWidget()
.widthRel(1f)
.height(12);
}
// protected static Widget<?> keyMapper(IDrawable key) {
// return key.asWidget()
// .widthRel(1f)
// .height(12);
// }

private Builder() {
this.textList = new ArrayList<>();
}
// private Builder() {
// this.textList = new ArrayList<>();
// }

public Builder structureFormed(boolean structureFormed) {
this.isStructureFormed = structureFormed;
Expand Down Expand Up @@ -672,11 +683,11 @@ public Builder addWorkingStatusLine() {

addKey(KeyUtil.string(() -> {
if (!isWorkingEnabled.getAsBoolean()) {
return TextFormatting.GOLD + pausedKey.get();
return pausedKey.getFormatted();
} else if (isActive.getAsBoolean()) {
return TextFormatting.GREEN + runningKey.get();
return runningKey.getFormatted();
} else {
return TextFormatting.GRAY + idlingKey.get();
return idlingKey.getFormatted();
}
}));
return this;
Expand Down Expand Up @@ -881,25 +892,25 @@ public Builder addFuelNeededLine(String fuelName, IntSupplier previousRecipeDura

/** Insert an empty line into the text list. */
public Builder addEmptyLine() {
addKey(IKey.EMPTY); // this is going to cause problems maybe
this.text.newLine();
return this;
}

/** Add custom text dynamically, allowing for custom application logic. */
public Builder addCustom(Consumer<List<IDrawable>> customConsumer) {
List<IDrawable> customKeys = new ArrayList<>();
customConsumer.accept(customKeys);
customKeys.forEach(this::addKey);
public Builder addCustom(Consumer<RichText> customConsumer) {
// List<IDrawable> customKeys = new ArrayList<>();
customConsumer.accept(this.text);
// customKeys.forEach(this::addKey);
return this;
}

/**
* @param widgetFunction function to build widgets from keys
*/
public Builder widgetFunction(Function<IDrawable, Widget<?>> widgetFunction) {
this.widgetFunction = widgetFunction;
return this;
}
// /**
// * @param widgetFunction function to build widgets from keys
// */
// public Builder widgetFunction(Function<IDrawable, Widget<?>> widgetFunction) {
// this.widgetFunction = widgetFunction;
// return this;
// }

protected boolean isEmpty() {
return textList.isEmpty();
Expand All @@ -909,41 +920,129 @@ protected void clear() {
textList.clear();
}

protected void build(ParentWidget<?> parent) {
for (int i = 0; i < textList.size(); i++) {
var line = this.widgetFunction.apply(textList.get(i));
if (tooltips.containsKey(i))
line.addTooltipLine(tooltips.get(i));
parent.child(line);
}
protected void buildDisplay(RichTextWidget parent) {
parent.textBuilder(richText -> this.textList.forEach(t -> t.accept(richText)));
// for (int i = 0; i < textList.size(); i++) {
// var line = this.widgetFunction.apply(textList.get(i));
// if (tooltips.containsKey(i))
// line.addTooltipLine(tooltips.get(i));
// parent.child(line);
// }
}

protected List<IDrawable> getTextList() {
return Collections.unmodifiableList(textList);
protected void buildTooltip(RichTooltip tooltip) {
this.textList.forEach(t -> t.accept(tooltip));
// parent.tooltipBuilder(richText -> this.textList.forEach(t -> t.accept(richText)));
}

protected boolean hasChanged(Builder other) {
if (textList.size() != other.textList.size()) return true;
for (int i = 0; i < textList.size(); i++) {
IDrawable left = textList.get(i), right = other.textList.get(i);

// dynamic keys are impossible to check, skip
if (left instanceof DynamicKey && right instanceof DynamicKey)
continue;
protected RichText getTextList() {
// return Collections.unmodifiableList(textList);
return this.text;
}

if (!left.equals(right))
protected boolean hasChanged(Builder other) {
List<String> cur = text.getStringRepresentation();
List<String> oth = other.text.getStringRepresentation();
if (cur.size() != oth.size()) return true;
for (int i = 0; i < cur.size(); i++) {
if (!Objects.equals(cur.get(i), oth.get(i)))
return true;
}
return false;
}

private void addKey(IDrawable key) {
this.textList.add(key);
// this.text.add(key);
textList.add(richText -> richText.addLine(key));
// this.textList.add(key);
}

private void addKey(IDrawable key, IDrawable hover) {
this.tooltips.put(textList.size(), hover);
addKey(key);
// this.text.add();
// this.tooltips.put(textList.size(), hover);
// addKey(key.asIcon().asHoverable().addTooltipLine(hover));
addKey(new TestDrawable(key, hover));
}
}

private static class TestDrawable implements IHoverable, ITooltip<TestDrawable> {

private final IDrawable drawable;
private RichTooltip tooltip;
private final Area area;

private TestDrawable(IDrawable drawable, IDrawable hover) {
this.drawable = drawable;
this.area = drawable instanceof IKey key ? calculateArea(key) : new Area();
tooltip().addLine(hover);
}

private Area calculateArea(IKey key) {
renderer.setSimulate(true);
renderer.setScale(1f);
renderer.draw(key.getFormatted());
renderer.getMaxWidth(Collections.singletonList(key.getFormatted()));
int h = (int) renderer.getLastWidth();
int w = (int) renderer.getLastHeight();
renderer.setSimulate(false);
return new Area(0, 0, w, h);
}

@Override
public void setRenderedAt(int x, int y) {
this.area.setPos(x, y);
}

@Override
public Area getRenderedArea() {
return this.area;
}

@Override
public int getWidth() {
return this.area.w();
}

@Override
public int getHeight() {
return this.area.h();
}

@Override
public Box getMargin() {
return this.area.getMargin();
}

@Override
@Nullable
public RichTooltip getTooltip() {
return tooltip;
}

@Override
public @NotNull RichTooltip tooltip() {
if (this.tooltip == null) this.tooltip = new RichTooltip(area -> area.set(getRenderedArea()));
return tooltip;
}

@Override
public TestDrawable tooltip(RichTooltip tooltip) {
this.tooltip = tooltip;
return this;
}

@Override
public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) {
if (drawable instanceof IKey key) {
renderer.setColor(widgetTheme.getTextColor());
renderer.setShadow(widgetTheme.getTextShadow());
renderer.setAlignment(Alignment.CenterLeft, width, height);
renderer.setScale(1f);
renderer.setPos(x, y);
renderer.draw(key.getFormatted());
} else {
drawable.draw(context, x, y, width, height, widgetTheme);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@
import codechicken.lib.render.pipeline.IVertexOperation;
import codechicken.lib.vec.Matrix4;
import com.cleanroommc.modularui.api.GuiAxis;
import com.cleanroommc.modularui.api.drawable.IDrawable;
import com.cleanroommc.modularui.api.drawable.IKey;
import com.cleanroommc.modularui.api.widget.Interactable;
import com.cleanroommc.modularui.drawable.ItemDrawable;
import com.cleanroommc.modularui.drawable.Rectangle;
import com.cleanroommc.modularui.drawable.text.RichText;
import com.cleanroommc.modularui.screen.ModularPanel;
import com.cleanroommc.modularui.utils.Color;
import com.cleanroommc.modularui.value.sync.BooleanSyncValue;
Expand Down Expand Up @@ -219,27 +219,27 @@ protected MultiblockUIFactory createUIFactory() {
});
}

private void addCustomData(List<IDrawable> keyList) {
private void addCustomData(RichText keyList) {
if (isStructureFormed()) {
// Steam Output line
IKey steamOutput = KeyUtil.number(TextFormatting.AQUA,
recipeLogic::getLastTickSteam, " L/t");

keyList.add(KeyUtil.lang(TextFormatting.GRAY,
keyList.addLine(KeyUtil.lang(TextFormatting.GRAY,
"gregtech.multiblock.large_boiler.steam_output", steamOutput));

// Efficiency line
IKey efficiency = KeyUtil.number(
() -> getNumberColor(recipeLogic.getHeatScaled()),
recipeLogic::getHeatScaled, "%");
keyList.add(KeyUtil.lang(TextFormatting.GRAY,
keyList.addLine(KeyUtil.lang(TextFormatting.GRAY,
"gregtech.multiblock.large_boiler.efficiency", efficiency));

// Throttle line
IKey throttle = KeyUtil.number(
() -> getNumberColor(getThrottle()),
this::getThrottle, "%");
keyList.add(KeyUtil.lang(TextFormatting.GRAY,
keyList.addLine(KeyUtil.lang(TextFormatting.GRAY,
"gregtech.multiblock.large_boiler.throttle", throttle));
}
}
Expand Down
Loading

0 comments on commit 55fefcd

Please sign in to comment.