Changed namespace
This commit is contained in:
parent
47756e7ebf
commit
01c59be6ae
62 changed files with 107 additions and 4332 deletions
|
@ -5,7 +5,6 @@ import org.betterx.bclib.util.ColorExtractor;
|
|||
import org.betterx.bclib.util.MHelper;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -18,6 +17,7 @@ import net.fabricmc.api.EnvType;
|
|||
import net.fabricmc.api.Environment;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.wunder.lib.ui.ColorHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -25,23 +25,23 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
public class ColorUtil {
|
||||
public static final int BLACK = ChatFormatting.BLACK.getColor() | 0xFF000000;
|
||||
public static final int DARK_BLUE = ChatFormatting.DARK_BLUE.getColor() | 0xFF000000;
|
||||
public static final int DARK_GREEN = ChatFormatting.DARK_GREEN.getColor() | 0xFF000000;
|
||||
public static final int DARK_AQUA = ChatFormatting.DARK_AQUA.getColor() | 0xFF000000;
|
||||
public static final int DARK_RED = ChatFormatting.DARK_RED.getColor() | 0xFF000000;
|
||||
public static final int DARK_PURPLE = ChatFormatting.DARK_PURPLE.getColor() | 0xFF000000;
|
||||
public static final int GOLD = ChatFormatting.GOLD.getColor() | 0xFF000000;
|
||||
public static final int GRAY = ChatFormatting.GRAY.getColor() | 0xFF000000;
|
||||
public static final int DARK_GRAY = ChatFormatting.DARK_GRAY.getColor() | 0xFF000000;
|
||||
public static final int BLUE = ChatFormatting.BLUE.getColor() | 0xFF000000;
|
||||
public static final int GREEN = ChatFormatting.GREEN.getColor() | 0xFF000000;
|
||||
public static final int AQUA = ChatFormatting.AQUA.getColor() | 0xFF000000;
|
||||
public static final int RED = ChatFormatting.RED.getColor() | 0xFF000000;
|
||||
public static final int LIGHT_PURPLE = ChatFormatting.LIGHT_PURPLE.getColor() | 0xFF000000;
|
||||
public static final int YELLOW = ChatFormatting.YELLOW.getColor() | 0xFF000000;
|
||||
public static final int WHITE = ChatFormatting.WHITE.getColor() | 0xFF000000;
|
||||
public static final int DEFAULT_TEXT = WHITE;
|
||||
public static final int BLACK = ColorHelper.BLACK;
|
||||
public static final int DARK_BLUE = ColorHelper.DARK_BLUE;
|
||||
public static final int DARK_GREEN = ColorHelper.DARK_GREEN;
|
||||
public static final int DARK_AQUA = ColorHelper.DARK_AQUA;
|
||||
public static final int DARK_RED = ColorHelper.DARK_RED;
|
||||
public static final int DARK_PURPLE = ColorHelper.DARK_PURPLE;
|
||||
public static final int GOLD = ColorHelper.GOLD;
|
||||
public static final int GRAY = ColorHelper.GRAY;
|
||||
public static final int DARK_GRAY = ColorHelper.DARK_GRAY;
|
||||
public static final int BLUE = ColorHelper.BLUE;
|
||||
public static final int GREEN = ColorHelper.GREEN;
|
||||
public static final int AQUA = ColorHelper.AQUA;
|
||||
public static final int RED = ColorHelper.RED;
|
||||
public static final int LIGHT_PURPLE = ColorHelper.LIGHT_PURPLE;
|
||||
public static final int YELLOW = ColorHelper.YELLOW;
|
||||
public static final int WHITE = ColorHelper.WHITE;
|
||||
public static final int DEFAULT_TEXT = ColorHelper.WHITE;
|
||||
private static final float[] FLOAT_BUFFER = new float[4];
|
||||
private static final int ALPHA = 255 << 24;
|
||||
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.input.RelativeContainerEventHandler;
|
||||
import org.betterx.ui.layout.components.render.NullRenderer;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class AbstractHorizontalStack<S extends AbstractHorizontalStack<S>> extends AbstractStack<NullRenderer, S> implements RelativeContainerEventHandler {
|
||||
public AbstractHorizontalStack(Value width, Value height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateContainerWidth(int containerWidth) {
|
||||
int myWidth = width.calculateOrFill(containerWidth);
|
||||
int fixedWidth = components.stream().map(c -> c.width.calculate(myWidth)).reduce(0, Integer::sum);
|
||||
|
||||
int freeWidth = Math.max(0, myWidth - fixedWidth);
|
||||
fillWidth(myWidth, freeWidth);
|
||||
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
c.updateContainerWidth(c.width.calculatedSize());
|
||||
}
|
||||
|
||||
return myWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int updateContainerHeight(int containerHeight) {
|
||||
int myHeight = height.calculateOrFill(containerHeight);
|
||||
components.stream().forEach(c -> c.height.calculateOrFill(myHeight));
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
c.updateContainerHeight(c.height.calculatedSize());
|
||||
}
|
||||
return myHeight;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void setRelativeBounds(int left, int top) {
|
||||
super.setRelativeBounds(left, top);
|
||||
|
||||
int offset = 0;
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
int delta = relativeBounds.height - c.height.calculatedSize();
|
||||
if (c.vAlign == Alignment.MIN) delta = 0;
|
||||
else if (c.vAlign == Alignment.CENTER) delta /= 2;
|
||||
c.setRelativeBounds(offset, delta);
|
||||
offset += c.relativeBounds.width;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
int fixedWidth = components.stream().map(c -> c.width.calculateFixed()).reduce(0, Integer::sum);
|
||||
double percentage = components.stream().map(c -> c.width.calculateRelative()).reduce(0.0, Double::sum);
|
||||
|
||||
return (int) (fixedWidth / (1 - percentage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return components.stream().map(c -> c.height.calculateFixed()).reduce(0, Integer::max);
|
||||
}
|
||||
|
||||
|
||||
protected S addEmpty(Value size) {
|
||||
this.components.add(new Empty(size, Value.fixed(0)));
|
||||
return (S) this;
|
||||
}
|
||||
|
||||
protected VerticalStack addColumn(Value width, Value height) {
|
||||
VerticalStack stack = new VerticalStack(width, height);
|
||||
add(stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
protected VerticalStack addColumn() {
|
||||
return addColumn(Value.fit(), Value.fit());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.input.RelativeContainerEventHandler;
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Size;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
import org.betterx.ui.vanilla.VanillaScrollerRenderer;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public abstract class AbstractStack<R extends ComponentRenderer, T extends AbstractStack<R, T>> extends LayoutComponent<R, T> implements RelativeContainerEventHandler {
|
||||
protected final List<LayoutComponent<?, ?>> components = new LinkedList<>();
|
||||
|
||||
public AbstractStack(Value width, Value height) {
|
||||
this(width, height, null);
|
||||
}
|
||||
|
||||
public AbstractStack(Value width, Value height, R renderer) {
|
||||
super(width, height, renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fillWidth(int parentSize, int fillSize) {
|
||||
double totalFillWeight = components.stream().map(c -> c.width.fillWeight()).reduce(0.0, Double::sum);
|
||||
return components.stream()
|
||||
.map(c -> c.width.fill(fillSize, totalFillWeight))
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fillHeight(int parentSize, int fillSize) {
|
||||
double totalFillHeight = components.stream().map(c -> c.height.fillWeight()).reduce(0.0, Double::sum);
|
||||
return components.stream()
|
||||
.map(c -> c.height.fill(fillSize, totalFillHeight))
|
||||
.reduce(0, Integer::sum);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreenBounds(int worldX, int worldY) {
|
||||
super.updateScreenBounds(worldX, worldY);
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
c.updateScreenBounds(screenBounds.left, screenBounds.top);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderInBounds(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle renderBounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
super.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
c.render(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends GuiEventListener> children() {
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getInputBounds() {
|
||||
return relativeBounds;
|
||||
}
|
||||
|
||||
boolean dragging;
|
||||
|
||||
@Override
|
||||
public boolean isDragging() {
|
||||
return dragging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragging(boolean bl) {
|
||||
dragging = bl;
|
||||
}
|
||||
|
||||
GuiEventListener focused;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GuiEventListener getFocused() {
|
||||
return focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocused(@Nullable GuiEventListener guiEventListener) {
|
||||
focused = guiEventListener;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return components.isEmpty();
|
||||
}
|
||||
|
||||
protected abstract T addEmpty(Value size);
|
||||
|
||||
protected T add(LayoutComponent<?, ?> c) {
|
||||
this.components.add(c);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
protected T addSpacer(int size) {
|
||||
return addEmpty(Value.fixed(size));
|
||||
}
|
||||
|
||||
protected T addSpacer(float percentage) {
|
||||
return addEmpty(Value.relative(percentage));
|
||||
}
|
||||
|
||||
protected T addFiller() {
|
||||
return addEmpty(Value.fill());
|
||||
}
|
||||
|
||||
|
||||
protected Image addIcon(ResourceLocation location, Size resourceSize) {
|
||||
Image i = new Image(Value.fixed(24), Value.fixed(24), location, resourceSize);
|
||||
add(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
protected Image addImage(Value width, Value height, ResourceLocation location, Size resourceSize) {
|
||||
Image i = new Image(width, height, location, resourceSize);
|
||||
add(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
protected Checkbox addCheckbox(
|
||||
Value width, Value height, Component component,
|
||||
boolean selected
|
||||
) {
|
||||
Checkbox c = new Checkbox(width, height, component, selected, true);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
protected Button addButton(
|
||||
Value width, Value height,
|
||||
Component component
|
||||
) {
|
||||
Button b = new Button(width, height, component);
|
||||
add(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
protected VerticalScroll<VanillaScrollerRenderer> addScrollable(LayoutComponent<?, ?> content) {
|
||||
return addScrollable(Value.fill(), Value.fill(), content);
|
||||
}
|
||||
|
||||
protected VerticalScroll<VanillaScrollerRenderer> addScrollable(
|
||||
Value width,
|
||||
Value height,
|
||||
LayoutComponent<?, ?> content
|
||||
) {
|
||||
VerticalScroll<VanillaScrollerRenderer> s = VerticalScroll.create(width, height, content);
|
||||
add(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
protected Text addText(Value width, Value height, net.minecraft.network.chat.Component text) {
|
||||
Text t = new Text(width, height, text);
|
||||
add(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
protected MultiLineText addMultilineText(Value width, Value height, net.minecraft.network.chat.Component text) {
|
||||
MultiLineText t = new MultiLineText(width, height, text);
|
||||
add(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
protected Range<Integer> addRange(
|
||||
Value width, Value height,
|
||||
net.minecraft.network.chat.Component titleOrNull,
|
||||
int minValue, int maxValue, int initialValue
|
||||
) {
|
||||
Range<Integer> r = new Range<>(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
add(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
protected Range<Float> addRange(
|
||||
Value width, Value height,
|
||||
net.minecraft.network.chat.Component titleOrNull,
|
||||
float minValue, float maxValue, float initialValue
|
||||
) {
|
||||
Range<Float> r = new Range<>(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
add(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
protected Range<Double> addRange(
|
||||
Value width, Value height,
|
||||
net.minecraft.network.chat.Component titleOrNull,
|
||||
double minValue, double maxValue, double initialValue
|
||||
) {
|
||||
Range<Double> r = new Range<>(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
add(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
protected Input addInput(
|
||||
Value width, Value height, net.minecraft.network.chat.Component titleOrNull, String initialValue
|
||||
) {
|
||||
Input i = new Input(width, height, titleOrNull, initialValue);
|
||||
add(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
protected ColorSwatch addColorSwatch(Value width, Value height, int color) {
|
||||
ColorSwatch c = new ColorSwatch(width, height, color);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
protected ColorPicker addColorPicker(
|
||||
Value width,
|
||||
Value height,
|
||||
net.minecraft.network.chat.Component titleOrNull,
|
||||
int color
|
||||
) {
|
||||
ColorPicker c = new ColorPicker(width, height, titleOrNull, color);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
protected HLine addHorizontalSeparator(int height) {
|
||||
return addHLine(Value.relative(1.0 / 1.618033988749894), Value.fixed(height));
|
||||
}
|
||||
|
||||
protected HLine addHorizontalLine(int height) {
|
||||
return addHLine(Value.fill(), Value.fixed(height));
|
||||
}
|
||||
|
||||
protected HLine addHLine(Value width, Value height) {
|
||||
HLine l = new HLine(width, height);
|
||||
add(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
protected VLine addVerticalSeparator(int width) {
|
||||
return addVLine(Value.fixed(width), Value.relative(1.0 / 1.618033988749894));
|
||||
}
|
||||
|
||||
protected VLine addVerticalLine(int width) {
|
||||
return addVLine(Value.fixed(width), Value.fill());
|
||||
}
|
||||
|
||||
protected VLine addVLine(Value width, Value height) {
|
||||
VLine l = new VLine(width, height);
|
||||
add(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
protected Container addContainered(Value width, Value height, LayoutComponent<?, ?> content) {
|
||||
Container c = new Container(width, height);
|
||||
c.addChild(content);
|
||||
add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
protected Item addItem(ItemStack stack) {
|
||||
Item i = new Item(Value.fit(), Value.fit());
|
||||
i.setItem(stack);
|
||||
add(i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
|
||||
public abstract class AbstractVanillaComponent<C extends AbstractWidget, V extends AbstractVanillaComponent<C, V>> extends LayoutComponent<AbstractVanillaComponentRenderer<C, V>, V> {
|
||||
protected C vanillaComponent;
|
||||
protected final net.minecraft.network.chat.Component component;
|
||||
protected float alpha = 1.0f;
|
||||
protected boolean enabled = true;
|
||||
|
||||
public AbstractVanillaComponent(
|
||||
Value width,
|
||||
Value height,
|
||||
AbstractVanillaComponentRenderer<C, V> renderer,
|
||||
net.minecraft.network.chat.Component component
|
||||
) {
|
||||
super(width, height, renderer);
|
||||
this.component = component;
|
||||
renderer.linkedComponent = (V) this;
|
||||
}
|
||||
|
||||
protected abstract C createVanillaComponent();
|
||||
|
||||
@Override
|
||||
protected void onBoundsChanged() {
|
||||
vanillaComponent = createVanillaComponent();
|
||||
vanillaComponent.setAlpha(this.alpha);
|
||||
}
|
||||
|
||||
protected net.minecraft.network.chat.Component contentComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return renderer.getWidth(contentComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return renderer.getHeight(contentComponent());
|
||||
}
|
||||
|
||||
public float getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
public V setAlpha(float alpha) {
|
||||
this.alpha = alpha;
|
||||
if (vanillaComponent != null) {
|
||||
vanillaComponent.setAlpha(alpha);
|
||||
}
|
||||
return (V) this;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public V setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
return (V) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(double x, double y) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
vanillaComponent.mouseMoved(x - relativeBounds.left, y - relativeBounds.top);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.mouseClicked(x - relativeBounds.left, y - relativeBounds.top, button);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double x, double y, int button) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.mouseReleased(x - relativeBounds.left, y - relativeBounds.top, button);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double x, double y, int button, double x2, double y2) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.mouseDragged(
|
||||
x - relativeBounds.left,
|
||||
y - relativeBounds.top,
|
||||
button,
|
||||
x2 - relativeBounds.left,
|
||||
y2 - relativeBounds.top
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double x, double y, double f) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.mouseScrolled(x - relativeBounds.left, y - relativeBounds.top, f);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed(int i, int j, int k) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.keyPressed(i, j, k);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased(int i, int j, int k) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.keyReleased(i, j, k);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped(char c, int i) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.charTyped(c, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeFocus(boolean bl) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.changeFocus(bl);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double x, double y) {
|
||||
if (vanillaComponent != null && enabled)
|
||||
return vanillaComponent.isMouseOver(x - relativeBounds.left, y - relativeBounds.top);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.components.render.TextProvider;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class AbstractVanillaComponentRenderer<C extends AbstractWidget, V extends AbstractVanillaComponent<C, V>> implements ComponentRenderer, TextProvider {
|
||||
V linkedComponent;
|
||||
|
||||
protected V getLinkedComponent() {
|
||||
return linkedComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (linkedComponent != null) {
|
||||
if (linkedComponent.vanillaComponent != null) {
|
||||
if (!linkedComponent.enabled) {
|
||||
linkedComponent.vanillaComponent.setAlpha(linkedComponent.alpha / 2);
|
||||
}
|
||||
linkedComponent.vanillaComponent.render(poseStack, mouseX, mouseY, deltaTicks);
|
||||
if (!linkedComponent.enabled) {
|
||||
linkedComponent.vanillaComponent.setAlpha(linkedComponent.alpha);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.input.RelativeContainerEventHandler;
|
||||
import org.betterx.ui.layout.components.render.NullRenderer;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class AbstractVerticalStack<S extends AbstractVerticalStack<S>> extends AbstractStack<NullRenderer, S> implements RelativeContainerEventHandler {
|
||||
public AbstractVerticalStack(Value width, Value height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int updateContainerWidth(int containerWidth) {
|
||||
int myWidth = width.calculateOrFill(containerWidth);
|
||||
components.stream().forEach(c -> c.width.calculateOrFill(myWidth));
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
c.updateContainerWidth(c.width.calculatedSize());
|
||||
}
|
||||
return myWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateContainerHeight(int containerHeight) {
|
||||
int myHeight = height.calculateOrFill(containerHeight);
|
||||
int fixedHeight = components.stream().map(c -> c.height.calculate(myHeight)).reduce(0, Integer::sum);
|
||||
|
||||
int freeHeight = Math.max(0, myHeight - fixedHeight);
|
||||
fillHeight(myHeight, freeHeight);
|
||||
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
c.updateContainerHeight(c.height.calculatedSize());
|
||||
}
|
||||
|
||||
return myHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setRelativeBounds(int left, int top) {
|
||||
super.setRelativeBounds(left, top);
|
||||
|
||||
int offset = 0;
|
||||
for (LayoutComponent<?, ?> c : components) {
|
||||
int delta = relativeBounds.width - c.width.calculatedSize();
|
||||
if (c.hAlign == Alignment.MIN) delta = 0;
|
||||
else if (c.hAlign == Alignment.CENTER) delta /= 2;
|
||||
c.setRelativeBounds(delta, offset);
|
||||
offset += c.relativeBounds.height;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return components.stream().map(c -> c.width.calculateFixed()).reduce(0, Integer::max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
int fixedHeight = components.stream().map(c -> c.height.calculateFixed()).reduce(0, Integer::sum);
|
||||
double percentage = components.stream().map(c -> c.height.calculateRelative()).reduce(0.0, Double::sum);
|
||||
|
||||
return (int) (fixedHeight / (1 - percentage));
|
||||
}
|
||||
|
||||
protected S addEmpty(Value size) {
|
||||
this.components.add(new Empty(Value.fixed(0), size));
|
||||
return (S) this;
|
||||
}
|
||||
|
||||
protected HorizontalStack addRow(Value width, Value height) {
|
||||
HorizontalStack stack = new HorizontalStack(width, height);
|
||||
add(stack);
|
||||
return stack;
|
||||
}
|
||||
|
||||
protected HorizontalStack addRow() {
|
||||
return addRow(Value.fit(), Value.fit());
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.ButtonRenderer;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Button extends AbstractVanillaComponent<net.minecraft.client.gui.components.Button, Button> {
|
||||
public static final OnTooltip NO_TOOLTIP = (button, poseStack, i, j) -> {
|
||||
};
|
||||
public static final OnPress NO_ACTION = (button) -> {
|
||||
};
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface OnTooltip {
|
||||
void onTooltip(Button button, PoseStack poseStack, int mouseX, int mouseY);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface OnPress {
|
||||
void onPress(Button button);
|
||||
}
|
||||
|
||||
OnPress onPress;
|
||||
OnTooltip onTooltip;
|
||||
|
||||
boolean glow = false;
|
||||
|
||||
public Button(
|
||||
Value width,
|
||||
Value height,
|
||||
net.minecraft.network.chat.Component component
|
||||
) {
|
||||
super(width, height, new ButtonRenderer(), component);
|
||||
this.onPress = NO_ACTION;
|
||||
this.onTooltip = NO_TOOLTIP;
|
||||
}
|
||||
|
||||
public Button onPress(OnPress onPress) {
|
||||
this.onPress = onPress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button onToolTip(OnTooltip onTooltip) {
|
||||
this.onTooltip = onTooltip;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected net.minecraft.client.gui.components.Button createVanillaComponent() {
|
||||
Button self = this;
|
||||
return net.minecraft.client.gui.components.Button
|
||||
.builder(component, (bt) -> onPress.onPress(self))
|
||||
.bounds(0, 0, relativeBounds.width, relativeBounds.height)
|
||||
.tooltip((bt, stack, x, y) -> onTooltip.onTooltip(self, stack, x, y))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
public boolean isGlowing() {
|
||||
return glow;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.CheckboxRenderer;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Checkbox extends AbstractVanillaComponent<net.minecraft.client.gui.components.Checkbox, Checkbox> {
|
||||
public static SelectionChanged IGNORE_CHANGE = (a, b) -> {
|
||||
};
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SelectionChanged {
|
||||
void now(Checkbox checkBox, boolean selected);
|
||||
}
|
||||
|
||||
private final boolean selected;
|
||||
private final boolean showLabel;
|
||||
|
||||
private SelectionChanged onSelectionChange;
|
||||
|
||||
public Checkbox(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component,
|
||||
boolean selected, boolean showLabel
|
||||
) {
|
||||
super(width, height, new CheckboxRenderer(), component);
|
||||
onSelectionChange = IGNORE_CHANGE;
|
||||
this.selected = selected;
|
||||
this.showLabel = showLabel;
|
||||
}
|
||||
|
||||
public Checkbox onChange(SelectionChanged onSelectionChange) {
|
||||
this.onSelectionChange = onSelectionChange;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
if (vanillaComponent != null) return vanillaComponent.selected();
|
||||
return selected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected net.minecraft.client.gui.components.Checkbox createVanillaComponent() {
|
||||
Checkbox self = this;
|
||||
net.minecraft.client.gui.components.Checkbox cb = new net.minecraft.client.gui.components.Checkbox(
|
||||
0, 0,
|
||||
relativeBounds.width, relativeBounds.height,
|
||||
component,
|
||||
selected,
|
||||
showLabel
|
||||
) {
|
||||
@Override
|
||||
public void onPress() {
|
||||
super.onPress();
|
||||
onSelectionChange.now(self, this.selected());
|
||||
}
|
||||
};
|
||||
|
||||
onSelectionChange.now(this, cb.selected());
|
||||
return cb;
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ColorPicker extends AbstractHorizontalStack<ColorPicker> {
|
||||
ColorSwatch swatch;
|
||||
Input input;
|
||||
|
||||
public ColorPicker(Value width, Value height, Component title, int color) {
|
||||
super(width, height);
|
||||
swatch = addColorSwatch(Value.fixed(20), Value.fixed(20), color);
|
||||
input = addInput(Value.fill(), Value.fit(), title, ColorUtil.toRGBHex(color));
|
||||
|
||||
//input.setFilter(ColorUtil::validHexColor);
|
||||
input.setResponder(this::inputResponder);
|
||||
}
|
||||
|
||||
private void inputResponder(String value) {
|
||||
if (ColorUtil.validHexColor(value)) {
|
||||
int color = ColorUtil.parseHex(value);
|
||||
swatch.setColor(color);
|
||||
swatch.setOffsetInner(false);
|
||||
swatch.setBorderColor(ColorUtil.BLACK);
|
||||
} else {
|
||||
swatch.setOffsetInner(true);
|
||||
swatch.setBorderColor(ColorUtil.RED);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.render.RenderHelper;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ColorSwatch extends CustomRenderComponent<ColorSwatch> {
|
||||
private int color;
|
||||
private int borderColor = ColorUtil.BLACK;
|
||||
private boolean offsetInner = false;
|
||||
|
||||
public ColorSwatch(Value width, Value height, int color) {
|
||||
super(width, height);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customRender(PoseStack stack, int x, int y, float deltaTicks, Rectangle bounds, Rectangle clipRect) {
|
||||
int o = offsetInner ? 2 : 1;
|
||||
RenderHelper.outline(stack, 0, 0, bounds.width, bounds.height, borderColor);
|
||||
GuiComponent.fill(stack, o, o, bounds.width - o, bounds.height - o, color);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public ColorSwatch setColor(int color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBorderColor() {
|
||||
return borderColor;
|
||||
}
|
||||
|
||||
public ColorSwatch setBorderColor(int color) {
|
||||
this.borderColor = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getOffsetInner() {
|
||||
return offsetInner;
|
||||
}
|
||||
|
||||
public ColorSwatch setOffsetInner(boolean val) {
|
||||
this.offsetInner = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return 20;
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface ComponentWithBounds {
|
||||
Rectangle getRelativeBounds();
|
||||
}
|
|
@ -1,291 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.input.RelativeContainerEventHandler;
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.components.render.RenderHelper;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Container extends LayoutComponent<Container.ContainerRenderer, Container> implements RelativeContainerEventHandler {
|
||||
public static class ContainerRenderer implements ComponentRenderer {
|
||||
Container linkedContainer;
|
||||
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (linkedContainer != null) {
|
||||
if ((linkedContainer.backgroundColor & 0xFF000000) != 0)
|
||||
GuiComponent.fill(stack, 0, 0, bounds.width, bounds.height, linkedContainer.backgroundColor);
|
||||
|
||||
if ((linkedContainer.outlineColor & 0xFF000000) != 0)
|
||||
RenderHelper.outline(stack, 0, 0, bounds.width, bounds.height, linkedContainer.outlineColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record Positional(int left, int top, LayoutComponent<?, ?> component) {
|
||||
public int getMaxX() {
|
||||
return left + component().getContentWidth();
|
||||
}
|
||||
|
||||
public int getMaxY() {
|
||||
return top + component().getContentHeight();
|
||||
}
|
||||
}
|
||||
|
||||
private final List<Positional> children = new LinkedList<>();
|
||||
boolean dragging = false;
|
||||
GuiEventListener focused = null;
|
||||
boolean visible = true;
|
||||
|
||||
int paddingLeft, paddingTop, paddingRight, paddingBottom;
|
||||
|
||||
int backgroundColor = 0;
|
||||
int outlineColor = 0;
|
||||
|
||||
public Container(
|
||||
Value width,
|
||||
Value height
|
||||
) {
|
||||
super(width, height, new ContainerRenderer());
|
||||
renderer.linkedContainer = this;
|
||||
}
|
||||
|
||||
public Container addChild(LayoutComponent<?, ?> child) {
|
||||
children.add(new Positional(0, 0, child));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Container addChild(int left, int top, LayoutComponent<?, ?> child) {
|
||||
children.add(new Positional(left, top, child));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Container setVisible(boolean v) {
|
||||
this.visible = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getVisible() {
|
||||
return this.visible;
|
||||
}
|
||||
|
||||
public Container setBackgroundColor(int color) {
|
||||
this.backgroundColor = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return backgroundColor;
|
||||
}
|
||||
|
||||
public Container setOutlineColor(int color) {
|
||||
this.outlineColor = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getOutlineColor() {
|
||||
return outlineColor;
|
||||
}
|
||||
|
||||
public Container setPadding(int padding) {
|
||||
return setPadding(padding, padding, padding, padding);
|
||||
}
|
||||
|
||||
public Container setPadding(int left, int top, int right, int bottom) {
|
||||
this.paddingLeft = left;
|
||||
this.paddingTop = top;
|
||||
this.paddingRight = right;
|
||||
this.paddingBottom = bottom;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return children.stream()
|
||||
.map(Positional::getMaxX)
|
||||
.reduce(0, Math::max) + paddingLeft + paddingRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return children.stream()
|
||||
.map(Positional::getMaxY)
|
||||
.reduce(0, Math::max) + paddingTop + paddingBottom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getInputBounds() {
|
||||
return relativeBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends GuiEventListener> children() {
|
||||
return children.stream().map(p -> p.component).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDragging() {
|
||||
return dragging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragging(boolean bl) {
|
||||
dragging = bl;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GuiEventListener getFocused() {
|
||||
return focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocused(@Nullable GuiEventListener guiEventListener) {
|
||||
focused = guiEventListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int updateContainerWidth(int containerWidth) {
|
||||
int myWidth = width.calculateOrFill(containerWidth);
|
||||
for (var child : children) {
|
||||
child.component.width.calculateOrFill(myWidth - (paddingLeft + paddingRight));
|
||||
child.component.updateContainerWidth(child.component.width.calculatedSize());
|
||||
}
|
||||
return myWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int updateContainerHeight(int containerHeight) {
|
||||
int myHeight = height.calculateOrFill(containerHeight);
|
||||
for (var child : children) {
|
||||
child.component.height.calculateOrFill(myHeight - (paddingTop + paddingBottom));
|
||||
child.component.updateContainerHeight(child.component.height.calculatedSize());
|
||||
}
|
||||
return myHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderInBounds(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle renderBounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (visible) {
|
||||
super.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
|
||||
|
||||
setClippingRect(clipRect);
|
||||
for (var child : children) {
|
||||
child.component.render(
|
||||
poseStack, mouseX, mouseY, deltaTicks,
|
||||
renderBounds, clipRect
|
||||
);
|
||||
}
|
||||
setClippingRect(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void setRelativeBounds(int left, int top) {
|
||||
super.setRelativeBounds(left, top);
|
||||
|
||||
for (var child : children) {
|
||||
int childLeft = (relativeBounds.width - (paddingLeft + paddingRight)) - child.component.width.calculatedSize();
|
||||
if (child.component.hAlign == Alignment.MIN) childLeft = 0;
|
||||
else if (child.component.hAlign == Alignment.CENTER) childLeft /= 2;
|
||||
|
||||
int childTop = (relativeBounds.height - (paddingTop + paddingBottom)) - child.component.height.calculatedSize();
|
||||
if (child.component.vAlign == Alignment.MIN) childTop = 0;
|
||||
else if (child.component.vAlign == Alignment.CENTER) childTop /= 2;
|
||||
|
||||
child.component.setRelativeBounds(child.left + paddingLeft + childLeft, child.top + paddingTop + childTop);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreenBounds(int worldX, int worldY) {
|
||||
super.updateScreenBounds(worldX, worldY);
|
||||
for (Positional p : children) {
|
||||
p.component.updateScreenBounds(p.left + screenBounds.left, p.top + screenBounds.top);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(double d, double e) {
|
||||
if (visible)
|
||||
RelativeContainerEventHandler.super.mouseMoved(d, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double d, double e, int i) {
|
||||
if (visible)
|
||||
return RelativeContainerEventHandler.super.mouseClicked(d, e, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double d, double e, int i) {
|
||||
if (visible)
|
||||
return RelativeContainerEventHandler.super.mouseReleased(d, e, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double d, double e, double f) {
|
||||
if (visible)
|
||||
return RelativeContainerEventHandler.super.mouseScrolled(d, e, f);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double d, double e, int i, double f, double g) {
|
||||
if (visible)
|
||||
return RelativeContainerEventHandler.super.mouseDragged(d, e, i, f, g);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double x, double y) {
|
||||
if (visible) {
|
||||
boolean res = false;
|
||||
for (var child : children) {
|
||||
res |= child.component.isMouseOver(x, y);
|
||||
}
|
||||
|
||||
return res || relativeBounds.contains(x, y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Container create(LayoutComponent<?, ?> content) {
|
||||
return create(Value.fit(), Value.fit(), content);
|
||||
}
|
||||
|
||||
public static Container create(Value width, Value height, LayoutComponent<?, ?> content) {
|
||||
Container c = new Container(width, height);
|
||||
c.addChild(content);
|
||||
return c;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public abstract class CustomRenderComponent<C extends CustomRenderComponent<C>> extends LayoutComponent<CustomRenderComponent.CustomRenderRenderer<C>, C> {
|
||||
public CustomRenderComponent(
|
||||
Value width,
|
||||
Value height
|
||||
) {
|
||||
super(width, height, new CustomRenderRenderer<>());
|
||||
renderer.linkedComponent = (C) this;
|
||||
}
|
||||
|
||||
protected abstract void customRender(
|
||||
PoseStack stack,
|
||||
int x,
|
||||
int y,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
);
|
||||
|
||||
protected static class CustomRenderRenderer<C extends CustomRenderComponent<C>> implements ComponentRenderer {
|
||||
C linkedComponent;
|
||||
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (linkedComponent != null) {
|
||||
linkedComponent.customRender(stack, mouseX, mouseY, deltaTicks, bounds, clipRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.NullRenderer;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Empty extends LayoutComponent<NullRenderer, Empty> {
|
||||
public Empty(
|
||||
Value width,
|
||||
Value height
|
||||
) {
|
||||
super(width, height, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double d, double e) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.render.RenderHelper;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class HLine extends CustomRenderComponent {
|
||||
private int color = ColorUtil.DEFAULT_TEXT;
|
||||
|
||||
public HLine(Value width, Value height) {
|
||||
super(width, height);
|
||||
this.vAlign = Alignment.CENTER;
|
||||
this.hAlign = Alignment.CENTER;
|
||||
}
|
||||
|
||||
public HLine setColor(int color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customRender(PoseStack stack, int x, int y, float deltaTicks, Rectangle bounds, Rectangle clipRect) {
|
||||
int top = bounds.height - getContentHeight();
|
||||
if (vAlign == Alignment.CENTER) top /= 2;
|
||||
else if (vAlign == Alignment.MIN) top = 0;
|
||||
RenderHelper.hLine(stack, 0, bounds.width, top, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.values.Size;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
import org.betterx.ui.vanilla.VanillaScrollerRenderer;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class HorizontalStack extends AbstractHorizontalStack<HorizontalStack> {
|
||||
public HorizontalStack(Value width, Value height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
|
||||
public static HorizontalStack centered(LayoutComponent<?, ?> c) {
|
||||
return new HorizontalStack(Value.fill(), Value.fill()).addFiller().add(c).addFiller();
|
||||
}
|
||||
|
||||
public static HorizontalStack bottom(LayoutComponent<?, ?> c) {
|
||||
return new HorizontalStack(Value.fill(), Value.fill()).add(c).addFiller();
|
||||
}
|
||||
|
||||
protected HorizontalStack addEmpty(Value size) {
|
||||
this.components.add(new Empty(size, Value.fixed(0)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalStack add(LayoutComponent<?, ?> c) {
|
||||
return super.add(c);
|
||||
}
|
||||
|
||||
public VerticalStack addColumn(Value width, Value height) {
|
||||
return super.addColumn(width, height);
|
||||
}
|
||||
|
||||
public VerticalStack addColumn() {
|
||||
return super.addColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalStack addSpacer(int size) {
|
||||
return super.addSpacer(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalStack addSpacer(float percentage) {
|
||||
return super.addSpacer(percentage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalStack addFiller() {
|
||||
return super.addFiller();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Button addButton(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component
|
||||
) {
|
||||
return super.addButton(width, height, component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Checkbox addCheckbox(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component,
|
||||
boolean selected
|
||||
) {
|
||||
return super.addCheckbox(width, height, component, selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorPicker addColorPicker(Value width, Value height, Component titleOrNull, int color) {
|
||||
return super.addColorPicker(width, height, titleOrNull, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorSwatch addColorSwatch(Value width, Value height, int color) {
|
||||
return super.addColorSwatch(width, height, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container addContainered(Value width, Value height, LayoutComponent<?, ?> content) {
|
||||
return super.addContainered(width, height, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HLine addHLine(Value width, Value height) {
|
||||
return super.addHLine(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HLine addHorizontalLine(int height) {
|
||||
return super.addHorizontalLine(height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HLine addHorizontalSeparator(int height) {
|
||||
return super.addHorizontalSeparator(height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image addIcon(ResourceLocation location, Size resourceSize) {
|
||||
return super.addIcon(location, resourceSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image addImage(Value width, Value height, ResourceLocation location, Size resourceSize) {
|
||||
return super.addImage(width, height, location, resourceSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Input addInput(Value width, Value height, Component titleOrNull, String initialValue) {
|
||||
return super.addInput(width, height, titleOrNull, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiLineText addMultilineText(Value width, Value height, Component text) {
|
||||
return super.addMultilineText(width, height, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Double> addRange(
|
||||
Value width,
|
||||
Value height,
|
||||
Component titleOrNull,
|
||||
double minValue,
|
||||
double maxValue,
|
||||
double initialValue
|
||||
) {
|
||||
return super.addRange(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Float> addRange(
|
||||
Value width,
|
||||
Value height,
|
||||
Component titleOrNull,
|
||||
float minValue,
|
||||
float maxValue,
|
||||
float initialValue
|
||||
) {
|
||||
return super.addRange(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Integer> addRange(
|
||||
Value width,
|
||||
Value height,
|
||||
Component titleOrNull,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
int initialValue
|
||||
) {
|
||||
return super.addRange(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text addText(Value width, Value height, Component text) {
|
||||
return super.addText(width, height, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalScroll<VanillaScrollerRenderer> addScrollable(LayoutComponent<?, ?> content) {
|
||||
return super.addScrollable(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VLine addVerticalLine(int width) {
|
||||
return super.addVerticalLine(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VLine addVerticalSeparator(int width) {
|
||||
return super.addVerticalSeparator(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VLine addVLine(Value width, Value height) {
|
||||
return super.addVLine(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalScroll<VanillaScrollerRenderer> addScrollable(
|
||||
Value width,
|
||||
Value height,
|
||||
LayoutComponent<?, ?> content
|
||||
) {
|
||||
return super.addScrollable(width, height, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item addItem(ItemStack stack) {
|
||||
return super.addItem(stack);
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.RenderHelper;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Size;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Image extends CustomRenderComponent {
|
||||
protected Rectangle uvRect;
|
||||
public final ResourceLocation location;
|
||||
protected float alpha;
|
||||
protected Size resourceSize;
|
||||
|
||||
public Image(Value width, Value height, ResourceLocation location) {
|
||||
this(width, height, location, new Size(16, 16));
|
||||
}
|
||||
|
||||
public Image(Value width, Value height, ResourceLocation location, Size resourceSize) {
|
||||
super(width, height);
|
||||
this.location = location;
|
||||
this.uvRect = new Rectangle(0, 0, resourceSize.width(), resourceSize.height());
|
||||
this.resourceSize = resourceSize;
|
||||
this.alpha = 1f;
|
||||
}
|
||||
|
||||
|
||||
public Image setAlpha(float a) {
|
||||
alpha = a;
|
||||
return this;
|
||||
}
|
||||
|
||||
public float getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
|
||||
public Image setUvRect(int left, int top, int width, int height) {
|
||||
setUvRect(new Rectangle(left, top, width, height));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Image setUvRect(Rectangle rect) {
|
||||
uvRect = rect;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Rectangle getUvRect() {
|
||||
return uvRect;
|
||||
}
|
||||
|
||||
public Image setResourceSize(int width, int height) {
|
||||
return setResourceSize(new Size(width, height));
|
||||
}
|
||||
|
||||
public Image setResourceSize(Size sz) {
|
||||
resourceSize = sz;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Size getResourceSize() {
|
||||
return resourceSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return uvRect.width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return uvRect.height;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void customRender(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
RenderHelper.renderImage(stack, 0, 0, bounds.width, bounds.height, location, resourceSize, uvRect, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double d, double e) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.EditBoxRenderer;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Input extends AbstractVanillaComponent<EditBox, Input> {
|
||||
private Consumer<String> responder;
|
||||
private BiFunction<String, Integer, FormattedCharSequence> formatter;
|
||||
private Predicate<String> filter;
|
||||
private String initialValue = "";
|
||||
|
||||
public Input(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component,
|
||||
String initialValue
|
||||
) {
|
||||
super(width, height, new EditBoxRenderer(), component);
|
||||
this.initialValue = initialValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EditBox createVanillaComponent() {
|
||||
EditBox eb = new EditBox(renderer.getFont(),
|
||||
0, 0,
|
||||
relativeBounds.width, relativeBounds.height,
|
||||
null,
|
||||
component
|
||||
);
|
||||
if (responder != null) eb.setResponder(responder);
|
||||
if (filter != null) eb.setFilter(filter);
|
||||
if (formatter != null) eb.setFormatter(formatter);
|
||||
eb.setValue(initialValue);
|
||||
eb.setBordered(true);
|
||||
eb.setEditable(true);
|
||||
|
||||
return eb;
|
||||
}
|
||||
|
||||
public Input setResponder(Consumer<String> consumer) {
|
||||
this.responder = consumer;
|
||||
if (vanillaComponent != null) vanillaComponent.setResponder(responder);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Input setFormatter(BiFunction<String, Integer, FormattedCharSequence> formatter) {
|
||||
this.formatter = formatter;
|
||||
if (vanillaComponent != null) vanillaComponent.setFormatter(formatter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Input setFilter(Predicate<String> filter) {
|
||||
this.filter = filter;
|
||||
if (vanillaComponent != null) vanillaComponent.setFilter(filter);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
if (vanillaComponent != null) return vanillaComponent.getValue();
|
||||
return "";
|
||||
}
|
||||
|
||||
public Input setValue(String value) {
|
||||
if (vanillaComponent != null) vanillaComponent.setValue(value);
|
||||
else initialValue = value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component contentComponent() {
|
||||
return Component.literal(initialValue + "..");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeFocus(boolean bl) {
|
||||
return super.changeFocus(bl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
return super.mouseClicked(x, y, button);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.entity.ItemRenderer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class Item extends CustomRenderComponent {
|
||||
private ItemStack itemStack;
|
||||
|
||||
public Item(Value width, Value height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public Item setItem(ItemStack item) {
|
||||
this.itemStack = item;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customRender(PoseStack stack, int x, int y, float deltaTicks, Rectangle bounds, Rectangle clipRect) {
|
||||
final ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
|
||||
itemRenderer.renderAndDecorateItem(Minecraft.getInstance().player, itemStack, bounds.left, bounds.top, 0);
|
||||
itemRenderer.renderGuiItemDecorations(
|
||||
Minecraft.getInstance().font,
|
||||
itemStack,
|
||||
bounds.left,
|
||||
bounds.top,
|
||||
"" + itemStack.getCount()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return 16;
|
||||
}
|
||||
}
|
|
@ -1,184 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public abstract class LayoutComponent<R extends ComponentRenderer, L extends LayoutComponent<R, L>> implements ComponentWithBounds, GuiEventListener {
|
||||
protected final R renderer;
|
||||
protected final Value width;
|
||||
protected final Value height;
|
||||
protected String debugName;
|
||||
protected Rectangle relativeBounds;
|
||||
protected Rectangle screenBounds;
|
||||
protected Alignment vAlign = Alignment.MIN;
|
||||
protected Alignment hAlign = Alignment.MIN;
|
||||
|
||||
public LayoutComponent(Value width, Value height, R renderer) {
|
||||
this.width = width.attachComponent(this::getContentWidth);
|
||||
this.height = height.attachComponent(this::getContentHeight);
|
||||
this.renderer = renderer;
|
||||
}
|
||||
|
||||
public void reCalculateLayout() {
|
||||
updateContainerWidth(relativeBounds.width);
|
||||
updateContainerHeight(relativeBounds.height);
|
||||
setRelativeBounds(relativeBounds.left, relativeBounds.top);
|
||||
updateScreenBounds(screenBounds.left, screenBounds.top);
|
||||
}
|
||||
|
||||
protected int updateContainerWidth(int containerWidth) {
|
||||
return width.setCalculatedSize(containerWidth);
|
||||
}
|
||||
|
||||
protected int updateContainerHeight(int containerHeight) {
|
||||
return height.setCalculatedSize(containerHeight);
|
||||
}
|
||||
|
||||
void setRelativeBounds(int left, int top) {
|
||||
relativeBounds = new Rectangle(left, top, width.calculatedSize(), height.calculatedSize());
|
||||
onBoundsChanged();
|
||||
}
|
||||
|
||||
public void updateScreenBounds(int worldX, int worldY) {
|
||||
screenBounds = relativeBounds.movedBy(worldX, worldY);
|
||||
}
|
||||
|
||||
protected void onBoundsChanged() {
|
||||
}
|
||||
|
||||
public Rectangle getRelativeBounds() {
|
||||
return relativeBounds;
|
||||
}
|
||||
|
||||
public Rectangle getScreenBounds() {
|
||||
return screenBounds;
|
||||
}
|
||||
|
||||
public abstract int getContentWidth();
|
||||
public abstract int getContentHeight();
|
||||
|
||||
public int fillWidth(int parentSize, int fillSize) {
|
||||
return width.fill(fillSize);
|
||||
}
|
||||
|
||||
public int fillHeight(int parentSize, int fillSize) {
|
||||
return height.fill(fillSize);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width.calculatedSize();
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height.calculatedSize();
|
||||
}
|
||||
|
||||
protected final void setClippingRect(Rectangle clippingRect) {
|
||||
if (clippingRect == null) {
|
||||
RenderSystem.disableScissor();
|
||||
return;
|
||||
}
|
||||
final double uiScale = Minecraft.getInstance().getWindow().getGuiScale();
|
||||
final int windowHeight = Minecraft.getInstance().getWindow().getHeight();
|
||||
RenderSystem.enableScissor(
|
||||
(int) (clippingRect.left * uiScale),
|
||||
(int) (windowHeight - (clippingRect.bottom()) * uiScale),
|
||||
(int) (clippingRect.width * uiScale),
|
||||
(int) ((clippingRect.height) * uiScale)
|
||||
);
|
||||
}
|
||||
|
||||
public void render(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle parentBounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
Rectangle r = relativeBounds.movedBy(parentBounds.left, parentBounds.top);
|
||||
Rectangle clip = r.intersect(clipRect);
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(relativeBounds.left, relativeBounds.top, 0);
|
||||
//if (r.overlaps(clip))
|
||||
{
|
||||
renderInBounds(poseStack, mouseX - relativeBounds.left, mouseY - relativeBounds.top, deltaTicks, r, clip);
|
||||
}
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
protected void renderInBounds(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle renderBounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (renderer != null) {
|
||||
setClippingRect(clipRect);
|
||||
renderer.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
|
||||
setClippingRect(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "(" +
|
||||
(debugName == null ? "" : debugName + " - ") +
|
||||
relativeBounds + ", " +
|
||||
width.calculatedSize() + "x" + height.calculatedSize() +
|
||||
")";
|
||||
}
|
||||
|
||||
public L alignTop() {
|
||||
vAlign = Alignment.MIN;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
public L alignBottom() {
|
||||
vAlign = Alignment.MAX;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
public L centerVertical() {
|
||||
vAlign = Alignment.CENTER;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
public L alignLeft() {
|
||||
hAlign = Alignment.MIN;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
public L alignRight() {
|
||||
hAlign = Alignment.MAX;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
public L centerHorizontal() {
|
||||
hAlign = Alignment.CENTER;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
public L setDebugName(String d) {
|
||||
debugName = d;
|
||||
return (L) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double d, double e) {
|
||||
return relativeBounds.contains(d, e);
|
||||
}
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.components.render.TextProvider;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.components.MultiLineLabel;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
record LineWithWidth(FormattedCharSequence text, int width) {
|
||||
}
|
||||
|
||||
public class MultiLineText extends LayoutComponent<MultiLineText.MultiLineTextRenderer, MultiLineText> {
|
||||
net.minecraft.network.chat.Component text;
|
||||
int color = ColorUtil.DEFAULT_TEXT;
|
||||
protected MultiLineLabel multiLineLabel;
|
||||
int bufferedContentWidth = 0;
|
||||
List<LineWithWidth> lines = List.of();
|
||||
|
||||
public MultiLineText(
|
||||
Value width,
|
||||
Value height,
|
||||
final net.minecraft.network.chat.Component text
|
||||
) {
|
||||
super(width, height, new MultiLineTextRenderer());
|
||||
renderer.linkedComponent = this;
|
||||
this.text = text;
|
||||
updatedContentWidth();
|
||||
}
|
||||
|
||||
public MultiLineText setColor(int cl) {
|
||||
this.color = cl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Component parse(Component text) {
|
||||
String[] parts = text.getString().split("\\*\\*");
|
||||
if (parts.length > 0) {
|
||||
boolean bold = false;
|
||||
MutableComponent c = Component.literal(parts[0]);
|
||||
|
||||
for (int i = 1; i < parts.length; i++) {
|
||||
bold = !bold;
|
||||
c.append(Component.literal(parts[i]).setStyle(Style.EMPTY.withBold(bold)));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public MultiLineText setText(Component text) {
|
||||
this.text = text;
|
||||
this.updatedContentWidth();
|
||||
|
||||
if (multiLineLabel != null) {
|
||||
multiLineLabel = createVanillaComponent();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected MultiLineLabel createVanillaComponent() {
|
||||
final int wd = relativeBounds == null ? width.calculatedSize() : relativeBounds.width;
|
||||
lines = renderer.getFont()
|
||||
.split(text, wd)
|
||||
.stream()
|
||||
.map((component) -> new LineWithWidth(component, renderer.getFont().width(component)))
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
|
||||
return MultiLineLabel.create(renderer.getFont(), text, wd);
|
||||
}
|
||||
|
||||
protected void updatedContentWidth() {
|
||||
String[] lines = text.getString().split("\n");
|
||||
if (lines.length == 0) bufferedContentWidth = 0;
|
||||
else {
|
||||
String line = lines[0];
|
||||
for (int i = 1; i < lines.length; i++)
|
||||
if (lines[i].length() > line.length())
|
||||
line = lines[i];
|
||||
|
||||
bufferedContentWidth = renderer.getWidth(Component.literal(line));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChanged() {
|
||||
super.onBoundsChanged();
|
||||
multiLineLabel = createVanillaComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return bufferedContentWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return renderer.getHeight(text);
|
||||
}
|
||||
|
||||
protected static class MultiLineTextRenderer implements ComponentRenderer, TextProvider {
|
||||
MultiLineText linkedComponent;
|
||||
|
||||
@Override
|
||||
public int getWidth(Component c) {
|
||||
return getFont().width(c.getVisualOrderText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(net.minecraft.network.chat.Component c) {
|
||||
if (linkedComponent == null) return 20;
|
||||
MultiLineLabel ml;
|
||||
if (linkedComponent.multiLineLabel != null) ml = linkedComponent.multiLineLabel;
|
||||
else ml = linkedComponent.createVanillaComponent();
|
||||
return ml.getLineCount() * getLineHeight(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (linkedComponent != null && linkedComponent.multiLineLabel != null) {
|
||||
int top = bounds.height - getHeight(linkedComponent.text);
|
||||
if (linkedComponent.vAlign == Alignment.MIN) top = 0;
|
||||
if (linkedComponent.vAlign == Alignment.CENTER) top /= 2;
|
||||
|
||||
if (linkedComponent.hAlign == Alignment.CENTER) {
|
||||
linkedComponent.multiLineLabel.renderCentered(
|
||||
stack, bounds.width / 2, top,
|
||||
getLineHeight(linkedComponent.text),
|
||||
linkedComponent.color
|
||||
);
|
||||
} else if (linkedComponent.hAlign == Alignment.MAX) {
|
||||
int lineY = 0;
|
||||
int lineHeight = getLineHeight(linkedComponent.text);
|
||||
|
||||
for (Iterator<LineWithWidth> iter = linkedComponent.lines.iterator(); iter.hasNext(); lineY += lineHeight) {
|
||||
LineWithWidth textWithWidth = iter.next();
|
||||
getFont().drawShadow(
|
||||
stack,
|
||||
textWithWidth.text(),
|
||||
linkedComponent.width.calculatedSize() - textWithWidth.width(),
|
||||
lineY,
|
||||
linkedComponent.color
|
||||
);
|
||||
}
|
||||
} else {
|
||||
linkedComponent.multiLineLabel.renderLeftAligned(
|
||||
stack, 0, top,
|
||||
getLineHeight(linkedComponent.text),
|
||||
linkedComponent.color
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double d, double e) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
|
||||
import org.betterx.ui.layout.components.input.RelativeContainerEventHandler;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.components.Renderable;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Panel implements ComponentWithBounds, RelativeContainerEventHandler, NarratableEntry, Renderable {
|
||||
protected LayoutComponent<?, ?> child;
|
||||
List<? extends GuiEventListener> listeners = List.of();
|
||||
public final Rectangle bounds;
|
||||
|
||||
public Panel(int width, int height) {
|
||||
this(0, 0, width, height);
|
||||
}
|
||||
|
||||
public Panel(int left, int top, int width, int height) {
|
||||
bounds = new Rectangle(left, top, width, height);
|
||||
}
|
||||
|
||||
public void setChild(LayoutComponent<?, ?> c) {
|
||||
this.child = c;
|
||||
listeners = List.of(c);
|
||||
}
|
||||
|
||||
public void calculateLayout() {
|
||||
if (child != null) {
|
||||
child.updateContainerWidth(bounds.width);
|
||||
child.updateContainerHeight(bounds.height);
|
||||
child.setRelativeBounds(0, 0);
|
||||
child.updateScreenBounds(bounds.left, bounds.top);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getRelativeBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends GuiEventListener> children() {
|
||||
return listeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getInputBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
boolean dragging = false;
|
||||
|
||||
@Override
|
||||
public boolean isDragging() {
|
||||
return dragging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragging(boolean bl) {
|
||||
dragging = bl;
|
||||
}
|
||||
|
||||
GuiEventListener focused;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GuiEventListener getFocused() {
|
||||
return focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocused(@Nullable GuiEventListener guiEventListener) {
|
||||
focused = guiEventListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NarrationPriority narrationPriority() {
|
||||
return NarrationPriority.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNarration(NarrationElementOutput narrationElementOutput) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, int mouseX, int mouseY, float deltaTicks) {
|
||||
if (child != null) {
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(bounds.left, bounds.top, 0);
|
||||
child.render(poseStack, mouseX - bounds.left, mouseY - bounds.top, deltaTicks, bounds, bounds);
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.RangeRenderer;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
import org.betterx.ui.vanilla.Slider;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Range<N extends Number> extends AbstractVanillaComponent<Slider<N>, Range<N>> {
|
||||
@FunctionalInterface
|
||||
public interface ValueChanged<N extends Number> {
|
||||
void now(Range<N> range, N newValue);
|
||||
}
|
||||
|
||||
private ValueChanged<N> onChange;
|
||||
private final N minValue;
|
||||
private final N maxValue;
|
||||
private final N initialValue;
|
||||
|
||||
public Range(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component,
|
||||
N minValue,
|
||||
N maxValue,
|
||||
N initialValue
|
||||
) {
|
||||
super(width, height, new RangeRenderer<>(), component);
|
||||
this.onChange = (a, b) -> {
|
||||
};
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.initialValue = initialValue;
|
||||
}
|
||||
|
||||
public Range(
|
||||
Value width,
|
||||
Value height,
|
||||
N minValue,
|
||||
N maxValue,
|
||||
N initialValue
|
||||
) {
|
||||
this(width, height, null, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
public Range<N> onChange(ValueChanged<N> onChange) {
|
||||
this.onChange = onChange;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Slider<N> createVanillaComponent() {
|
||||
Range<N> self = this;
|
||||
return new Slider<>(
|
||||
0,
|
||||
0,
|
||||
relativeBounds.width,
|
||||
relativeBounds.height,
|
||||
component,
|
||||
minValue,
|
||||
maxValue,
|
||||
initialValue,
|
||||
(s, v) -> onChange.now(self, v)
|
||||
);
|
||||
}
|
||||
|
||||
public N getValue() {
|
||||
return vanillaComponent.currentValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Component contentComponent() {
|
||||
Slider<N> dummy = new Slider<>(
|
||||
0,
|
||||
0,
|
||||
100,
|
||||
20,
|
||||
component,
|
||||
minValue,
|
||||
maxValue,
|
||||
initialValue,
|
||||
(a, b) -> {
|
||||
}
|
||||
);
|
||||
return dummy.getValueComponent(maxValue);
|
||||
}
|
||||
}
|
|
@ -1,158 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Tabs extends AbstractVerticalStack<Tabs> {
|
||||
@FunctionalInterface
|
||||
public interface OnPageChange {
|
||||
void now(Tabs tabs, int pageIndex);
|
||||
}
|
||||
|
||||
private final HorizontalStack buttons;
|
||||
private final Container content;
|
||||
|
||||
private final List<Container> pageList = new LinkedList<>();
|
||||
private final List<Button> buttonList = new LinkedList<>();
|
||||
|
||||
private int initialPage = 0;
|
||||
|
||||
private OnPageChange onPageChange;
|
||||
|
||||
|
||||
public Tabs(Value width, Value height) {
|
||||
super(width, height);
|
||||
|
||||
buttons = new HorizontalStack(Value.fill(), Value.fit());
|
||||
content = new Container(Value.fill(), Value.fill());
|
||||
|
||||
this.add(buttons);
|
||||
this.add(content);
|
||||
|
||||
setBackgroundColor(0x77000000);
|
||||
setPadding(4);
|
||||
}
|
||||
|
||||
public Tabs addPage(Component title, LayoutComponent<?, ?> content) {
|
||||
final Container c = new Container(Value.fill(), Value.fill());
|
||||
c.addChild(content);
|
||||
this.content.addChild(c);
|
||||
pageList.add(c);
|
||||
if (!buttons.isEmpty()) buttons.addSpacer(4);
|
||||
Button b = new Button(Value.fit(), Value.fit(), title).alignBottom();
|
||||
b.onPress((bt) -> {
|
||||
for (Container cc : pageList) {
|
||||
cc.setVisible(cc == c);
|
||||
}
|
||||
|
||||
for (Button bb : buttonList) {
|
||||
bb.glow = bb == b;
|
||||
}
|
||||
|
||||
if (onPageChange != null) {
|
||||
for (int i = 0; i < buttonList.size(); i++) {
|
||||
if (buttonList.get(i).glow) onPageChange.now(this, i);
|
||||
}
|
||||
}
|
||||
});
|
||||
buttons.add(b);
|
||||
buttonList.add(b);
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Tabs onPageChange(OnPageChange e) {
|
||||
this.onPageChange = e;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Button getButton(int idx) {
|
||||
return buttonList.get(idx);
|
||||
}
|
||||
|
||||
public Tabs setBackgroundColor(int color) {
|
||||
content.setBackgroundColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return content.getBackgroundColor();
|
||||
}
|
||||
|
||||
public Tabs setOutlineColor(int color) {
|
||||
content.setOutlineColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getOutlineColor() {
|
||||
return content.getOutlineColor();
|
||||
}
|
||||
|
||||
public Tabs setPadding(int padding) {
|
||||
content.setPadding(padding);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Tabs setPadding(int left, int top, int right, int bottom) {
|
||||
content.setPadding(left, top, right, bottom);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return content.getContentWidth();
|
||||
}
|
||||
|
||||
public Tabs selectPage(int idx) {
|
||||
for (int i = 0; i < pageList.size(); i++) {
|
||||
pageList.get(i).setVisible(i == idx);
|
||||
buttonList.get(i).glow = i == idx;
|
||||
}
|
||||
initialPage = idx;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSelectedPage() {
|
||||
return initialPage;
|
||||
}
|
||||
|
||||
public Tabs addComponent(LayoutComponent<?, ?> title) {
|
||||
buttons.add(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onBoundsChanged() {
|
||||
super.onBoundsChanged();
|
||||
selectPage(initialPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tabs addFiller() {
|
||||
buttons.addFiller();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tabs addSpacer(int size) {
|
||||
buttons.addSpacer(size);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tabs addSpacer(float percentage) {
|
||||
buttons.addSpacer(percentage);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.render.ComponentRenderer;
|
||||
import org.betterx.ui.layout.components.render.TextProvider;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Text extends LayoutComponent<Text.TextRenderer, Text> {
|
||||
net.minecraft.network.chat.Component text;
|
||||
int color = ColorUtil.DEFAULT_TEXT;
|
||||
|
||||
public Text(
|
||||
Value width,
|
||||
Value height,
|
||||
net.minecraft.network.chat.Component text
|
||||
) {
|
||||
super(width, height, new TextRenderer());
|
||||
vAlign = Alignment.CENTER;
|
||||
renderer.linkedComponent = this;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public Text setColor(int cl) {
|
||||
this.color = cl;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Text setText(Component text) {
|
||||
this.text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return renderer.getWidth(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return renderer.getHeight(text);
|
||||
}
|
||||
|
||||
public static class TextRenderer implements ComponentRenderer, TextProvider {
|
||||
Text linkedComponent;
|
||||
|
||||
@Override
|
||||
public int getWidth(net.minecraft.network.chat.Component c) {
|
||||
return getFont().width(c.getVisualOrderText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(net.minecraft.network.chat.Component c) {
|
||||
return TextProvider.super.getLineHeight(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
if (linkedComponent != null) {
|
||||
int left = bounds.width - getWidth(linkedComponent.text);
|
||||
if (linkedComponent.hAlign == Alignment.MIN) left = 0;
|
||||
if (linkedComponent.hAlign == Alignment.CENTER) left /= 2;
|
||||
|
||||
int top = bounds.height - getLineHeight(linkedComponent.text);
|
||||
if (linkedComponent.vAlign == Alignment.MIN) top = 0;
|
||||
if (linkedComponent.vAlign == Alignment.CENTER) top = top / 2 + 1;
|
||||
|
||||
GuiComponent.drawString(stack, getFont(), linkedComponent.text, left, top, linkedComponent.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double d, double e) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.render.RenderHelper;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class VLine extends CustomRenderComponent {
|
||||
private int color = ColorUtil.DEFAULT_TEXT;
|
||||
|
||||
public VLine(Value width, Value height) {
|
||||
super(width, height);
|
||||
this.vAlign = Alignment.CENTER;
|
||||
this.hAlign = Alignment.CENTER;
|
||||
}
|
||||
|
||||
public VLine setColor(int color) {
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customRender(PoseStack stack, int x, int y, float deltaTicks, Rectangle bounds, Rectangle clipRect) {
|
||||
int left = bounds.height - getContentHeight();
|
||||
if (hAlign == Alignment.CENTER) left /= 2;
|
||||
else if (hAlign == Alignment.MIN) left = 0;
|
||||
RenderHelper.vLine(stack, left, 0, bounds.height, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double d, double e) {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,314 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
import org.betterx.ui.layout.components.render.NullRenderer;
|
||||
import org.betterx.ui.layout.components.render.ScrollerRenderer;
|
||||
import org.betterx.ui.layout.values.Alignment;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
import org.betterx.ui.vanilla.VanillaScrollerRenderer;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.components.events.ContainerEventHandler;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class VerticalScroll<RS extends ScrollerRenderer> extends LayoutComponent<NullRenderer, VerticalScroll<RS>> implements ContainerEventHandler {
|
||||
protected LayoutComponent<?, ?> child;
|
||||
protected final RS scrollerRenderer;
|
||||
|
||||
protected int dist;
|
||||
protected double scrollerY;
|
||||
protected int scrollerHeight;
|
||||
protected int travel;
|
||||
protected int topOffset;
|
||||
|
||||
protected int scrollerPadding;
|
||||
|
||||
protected boolean keepSpaceForScrollbar = true;
|
||||
|
||||
public VerticalScroll(Value width, Value height, RS scrollerRenderer) {
|
||||
super(width, height, new NullRenderer());
|
||||
this.scrollerRenderer = scrollerRenderer;
|
||||
this.scrollerPadding = scrollerRenderer.scrollerPadding();
|
||||
}
|
||||
|
||||
public static VerticalScroll<VanillaScrollerRenderer> create(LayoutComponent<?, ?> c) {
|
||||
return create(Value.relative(1), Value.relative(1), c);
|
||||
}
|
||||
|
||||
public static VerticalScroll<VanillaScrollerRenderer> create(
|
||||
Value width,
|
||||
Value height,
|
||||
LayoutComponent<?, ?> c
|
||||
) {
|
||||
VerticalScroll<VanillaScrollerRenderer> res = new VerticalScroll<>(
|
||||
width,
|
||||
height,
|
||||
VanillaScrollerRenderer.DEFAULT
|
||||
);
|
||||
res.setChild(c);
|
||||
return res;
|
||||
}
|
||||
|
||||
List<LayoutComponent<?, ?>> children = List.of();
|
||||
|
||||
public VerticalScroll<RS> setChild(LayoutComponent<?, ?> c) {
|
||||
this.child = c;
|
||||
children = List.of(child);
|
||||
return this;
|
||||
}
|
||||
|
||||
public VerticalScroll<RS> setScrollerPadding(int pad) {
|
||||
this.scrollerPadding = pad;
|
||||
return this;
|
||||
}
|
||||
|
||||
public VerticalScroll<RS> setKeepSpaceForScrollbar(boolean value) {
|
||||
keepSpaceForScrollbar = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int updateContainerWidth(int containerWidth) {
|
||||
int myWidth = width.calculateOrFill(containerWidth);
|
||||
if (child != null) {
|
||||
child.width.calculateOrFill(myWidth - scrollerWidth());
|
||||
child.updateContainerWidth(child.width.calculatedSize());
|
||||
}
|
||||
return myWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int updateContainerHeight(int containerHeight) {
|
||||
int myHeight = height.calculateOrFill(containerHeight);
|
||||
if (child != null) {
|
||||
child.height.calculateOrFill(myHeight);
|
||||
child.updateContainerHeight(child.height.calculatedSize());
|
||||
}
|
||||
return myHeight;
|
||||
}
|
||||
|
||||
protected int scrollerWidth() {
|
||||
return scrollerRenderer.scrollerWidth() + scrollerPadding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentWidth() {
|
||||
return scrollerWidth() + (child != null
|
||||
? child.getContentWidth()
|
||||
: 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentHeight() {
|
||||
return child != null ? child.getContentHeight() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setRelativeBounds(int left, int top) {
|
||||
super.setRelativeBounds(left, top);
|
||||
|
||||
if (child != null) {
|
||||
int width = relativeBounds.width;
|
||||
boolean willNeedScrollBar = keepSpaceForScrollbar || child.height.calculatedSize() > relativeBounds.height;
|
||||
if (willNeedScrollBar) width -= scrollerWidth();
|
||||
int childLeft = width - child.width.calculatedSize();
|
||||
if (child.hAlign == Alignment.MIN) childLeft = 0;
|
||||
else if (child.hAlign == Alignment.CENTER) childLeft /= 2;
|
||||
|
||||
int childTop = relativeBounds.height - child.height.calculatedSize();
|
||||
if (child.vAlign == Alignment.MIN) childTop = 0;
|
||||
else if (child.vAlign == Alignment.CENTER) childTop /= 2;
|
||||
|
||||
child.setRelativeBounds(childLeft, childTop);
|
||||
}
|
||||
|
||||
updateScrollViewMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreenBounds(int worldX, int worldY) {
|
||||
super.updateScreenBounds(worldX, worldY);
|
||||
child.updateScreenBounds(screenBounds.left, screenBounds.top);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderInBounds(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle renderBounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
super.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
|
||||
|
||||
if (showScrollBar()) {
|
||||
if (child != null) {
|
||||
poseStack.pushPose();
|
||||
poseStack.translate(0, scrollerOffset(), 0);
|
||||
setClippingRect(clipRect);
|
||||
child.render(
|
||||
poseStack, mouseX, mouseY - scrollerOffset(), deltaTicks,
|
||||
renderBounds.movedBy(0, scrollerOffset(), scrollerWidth(), 0),
|
||||
clipRect
|
||||
);
|
||||
setClippingRect(null);
|
||||
poseStack.popPose();
|
||||
}
|
||||
scrollerRenderer.renderScrollBar(renderBounds, saveScrollerY(), scrollerHeight);
|
||||
} else {
|
||||
if (child != null) {
|
||||
child.render(poseStack, mouseX, mouseY, deltaTicks, renderBounds, clipRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mouseDown = false;
|
||||
private int mouseDownY = 0;
|
||||
private int scrollerDownY = 0;
|
||||
|
||||
protected void updateScrollViewMetrics() {
|
||||
final int view = relativeBounds.height;
|
||||
final int content = child.relativeBounds.height;
|
||||
|
||||
this.dist = content - view;
|
||||
this.scrollerHeight = Math.max(scrollerRenderer.scrollerHeight(), (view * view) / content);
|
||||
this.travel = view - this.scrollerHeight;
|
||||
this.topOffset = 0;
|
||||
this.scrollerY = 0;
|
||||
}
|
||||
|
||||
protected int saveScrollerY() {
|
||||
return (int) Math.max(0, Math.min(travel, scrollerY));
|
||||
}
|
||||
|
||||
protected int scrollerOffset() {
|
||||
return -((int) (((float) saveScrollerY() / travel) * this.dist));
|
||||
}
|
||||
|
||||
public boolean showScrollBar() {
|
||||
return child.relativeBounds.height > relativeBounds.height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(double x, double y) {
|
||||
if (child != null && relativeBounds.contains(x, y))
|
||||
ContainerEventHandler.super.mouseMoved(x - relativeBounds.left, y - relativeBounds.top - scrollerOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends GuiEventListener> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double x, double y, int button) {
|
||||
Rectangle scroller = scrollerRenderer.getScrollerBounds(relativeBounds);
|
||||
Rectangle picker = scrollerRenderer.getPickerBounds(scroller, saveScrollerY(), scrollerHeight);
|
||||
if (picker.contains((int) x, (int) y)) {
|
||||
mouseDown = true;
|
||||
mouseDownY = (int) y;
|
||||
scrollerDownY = saveScrollerY();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (child != null && relativeBounds.contains(x, y))
|
||||
return ContainerEventHandler.super.mouseClicked(
|
||||
x - relativeBounds.left,
|
||||
y - relativeBounds.top - scrollerOffset(),
|
||||
button
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased(double x, double y, int button) {
|
||||
mouseDown = false;
|
||||
if (child != null && relativeBounds.contains(x, y))
|
||||
return ContainerEventHandler.super.mouseReleased(
|
||||
x - relativeBounds.left,
|
||||
y - relativeBounds.top - scrollerOffset(),
|
||||
button
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged(double x, double y, int button, double x2, double y2) {
|
||||
if (mouseDown) {
|
||||
int delta = (int) y - mouseDownY;
|
||||
scrollerY = scrollerDownY + delta;
|
||||
return true;
|
||||
}
|
||||
if (child != null && relativeBounds.contains(x, y))
|
||||
return ContainerEventHandler.super.mouseDragged(
|
||||
x - relativeBounds.left,
|
||||
y - relativeBounds.top - scrollerOffset(),
|
||||
button,
|
||||
x2,
|
||||
y2
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(double x, double y, double delta) {
|
||||
boolean didCapture = false;
|
||||
if (child != null && relativeBounds.contains(x, y)) {
|
||||
didCapture = ContainerEventHandler.super.mouseScrolled(
|
||||
x - relativeBounds.left,
|
||||
y - relativeBounds.top - scrollerOffset(),
|
||||
delta
|
||||
);
|
||||
}
|
||||
if (!didCapture) {
|
||||
scrollerY = Math.max(0, Math.min(travel, scrollerY)) + delta;
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("Child did capture scroll");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
GuiEventListener focused;
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public GuiEventListener getFocused() {
|
||||
return focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocused(@Nullable GuiEventListener guiEventListener) {
|
||||
focused = guiEventListener;
|
||||
}
|
||||
|
||||
boolean dragging;
|
||||
|
||||
@Override
|
||||
public boolean isDragging() {
|
||||
return this.dragging;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDragging(boolean bl) {
|
||||
dragging = bl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver(double x, double y) {
|
||||
if (child != null) {
|
||||
if (child.isMouseOver(x - relativeBounds.left, y - relativeBounds.top - scrollerOffset()))
|
||||
return true;
|
||||
}
|
||||
return relativeBounds.contains(x, y);
|
||||
}
|
||||
}
|
|
@ -1,217 +0,0 @@
|
|||
package org.betterx.ui.layout.components;
|
||||
|
||||
|
||||
import org.betterx.ui.layout.values.Size;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
import org.betterx.ui.vanilla.VanillaScrollerRenderer;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class VerticalStack extends AbstractVerticalStack<VerticalStack> {
|
||||
public VerticalStack(Value width, Value height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
public static VerticalStack centered(LayoutComponent<?, ?> c) {
|
||||
return new VerticalStack(Value.relative(1), Value.relative(1)).addFiller().add(c).addFiller();
|
||||
}
|
||||
|
||||
public static VerticalStack bottom(LayoutComponent<?, ?> c) {
|
||||
return new VerticalStack(Value.relative(1), Value.relative(1)).add(c).addFiller();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected VerticalStack addEmpty(Value size) {
|
||||
this.components.add(new Empty(Value.fixed(0), size));
|
||||
return this;
|
||||
}
|
||||
|
||||
public HorizontalStack indent(int width) {
|
||||
var h = new HorizontalStack(Value.fitOrFill(), Value.fit());
|
||||
h.addSpacer(width);
|
||||
add(h);
|
||||
return h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalStack addRow(Value width, Value height) {
|
||||
return super.addRow(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HorizontalStack addRow() {
|
||||
return super.addRow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalStack add(LayoutComponent<?, ?> c) {
|
||||
return super.add(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalStack addSpacer(int size) {
|
||||
return super.addSpacer(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalStack addSpacer(float percentage) {
|
||||
return super.addSpacer(percentage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalStack addFiller() {
|
||||
return super.addFiller();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Button addButton(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component
|
||||
) {
|
||||
return super.addButton(width, height, component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Checkbox addCheckbox(
|
||||
Value width,
|
||||
Value height,
|
||||
Component component,
|
||||
boolean selected
|
||||
) {
|
||||
return super.addCheckbox(width, height, component, selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorPicker addColorPicker(Value width, Value height, Component titleOrNull, int color) {
|
||||
return super.addColorPicker(width, height, titleOrNull, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ColorSwatch addColorSwatch(Value width, Value height, int color) {
|
||||
return super.addColorSwatch(width, height, color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Container addContainered(Value width, Value height, LayoutComponent<?, ?> content) {
|
||||
return super.addContainered(width, height, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HLine addHLine(Value width, Value height) {
|
||||
return super.addHLine(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HLine addHorizontalLine(int height) {
|
||||
return super.addHorizontalLine(height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HLine addHorizontalSeparator(int height) {
|
||||
return super.addHorizontalSeparator(height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image addIcon(ResourceLocation location, Size resourceSize) {
|
||||
return super.addIcon(location, resourceSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image addImage(Value width, Value height, ResourceLocation location, Size resourceSize) {
|
||||
return super.addImage(width, height, location, resourceSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Input addInput(Value width, Value height, Component titleOrNull, String initialValue) {
|
||||
return super.addInput(width, height, titleOrNull, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiLineText addMultilineText(Value width, Value height, Component text) {
|
||||
return super.addMultilineText(width, height, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Double> addRange(
|
||||
Value width,
|
||||
Value height,
|
||||
Component titleOrNull,
|
||||
double minValue,
|
||||
double maxValue,
|
||||
double initialValue
|
||||
) {
|
||||
return super.addRange(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Float> addRange(
|
||||
Value width,
|
||||
Value height,
|
||||
Component titleOrNull,
|
||||
float minValue,
|
||||
float maxValue,
|
||||
float initialValue
|
||||
) {
|
||||
return super.addRange(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Range<Integer> addRange(
|
||||
Value width,
|
||||
Value height,
|
||||
Component titleOrNull,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
int initialValue
|
||||
) {
|
||||
return super.addRange(width, height, titleOrNull, minValue, maxValue, initialValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text addText(Value width, Value height, Component text) {
|
||||
return super.addText(width, height, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalScroll<VanillaScrollerRenderer> addScrollable(LayoutComponent<?, ?> content) {
|
||||
return super.addScrollable(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VLine addVerticalLine(int width) {
|
||||
return super.addVerticalLine(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VLine addVerticalSeparator(int width) {
|
||||
return super.addVerticalSeparator(width);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VLine addVLine(Value width, Value height) {
|
||||
return super.addVLine(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerticalScroll<VanillaScrollerRenderer> addScrollable(
|
||||
Value width,
|
||||
Value height,
|
||||
LayoutComponent<?, ?> content
|
||||
) {
|
||||
return super.addScrollable(width, height, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item addItem(ItemStack stack) {
|
||||
return super.addItem(stack);
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package org.betterx.ui.layout.components.input;
|
||||
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import net.minecraft.client.gui.components.events.ContainerEventHandler;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface RelativeContainerEventHandler extends ContainerEventHandler {
|
||||
Rectangle getInputBounds();
|
||||
|
||||
default Optional<GuiEventListener> getChildAt(double d, double e) {
|
||||
Rectangle r = getInputBounds();
|
||||
return ContainerEventHandler.super.getChildAt(d, e);
|
||||
}
|
||||
|
||||
default boolean mouseClicked(double d, double e, int i) {
|
||||
if (getFocused() != null) {
|
||||
//getFocused().mouseClicked(d, e, i);
|
||||
}
|
||||
Rectangle r = getInputBounds();
|
||||
return ContainerEventHandler.super.mouseClicked(d - r.left, e - r.top, i);
|
||||
}
|
||||
|
||||
default boolean mouseReleased(double d, double e, int i) {
|
||||
Rectangle r = getInputBounds();
|
||||
return ContainerEventHandler.super.mouseReleased(d - r.left, e - r.top, i);
|
||||
}
|
||||
|
||||
default boolean mouseDragged(double d, double e, int i, double f, double g) {
|
||||
Rectangle r = getInputBounds();
|
||||
return ContainerEventHandler.super.mouseDragged(d - r.left, e - r.top, i, f - r.left, g - r.top);
|
||||
}
|
||||
|
||||
default boolean mouseScrolled(double d, double e, double f) {
|
||||
Rectangle r = getInputBounds();
|
||||
return ContainerEventHandler.super.mouseScrolled(d - r.left, e - r.top, f);
|
||||
}
|
||||
|
||||
default boolean isMouseOver(double x, double y) {
|
||||
Rectangle r = getInputBounds();
|
||||
boolean res = false;
|
||||
for (GuiEventListener c : children()) {
|
||||
res |= c.isMouseOver(x - r.left, y - r.top);
|
||||
}
|
||||
|
||||
return res || r.contains(x, y);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.AbstractVanillaComponentRenderer;
|
||||
import org.betterx.ui.layout.components.Button;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ButtonRenderer extends AbstractVanillaComponentRenderer<net.minecraft.client.gui.components.Button, Button> {
|
||||
double deltaSum = 0;
|
||||
double deltaSum2 = .34;
|
||||
double deltaSum3 = .12;
|
||||
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack poseStack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
super.renderInBounds(poseStack, mouseX, mouseY, deltaTicks, bounds, clipRect);
|
||||
deltaSum += deltaTicks * 0.03;
|
||||
deltaSum2 += deltaTicks * 0.032;
|
||||
deltaSum3 += deltaTicks * 0.028;
|
||||
if (getLinkedComponent() != null && getLinkedComponent().isGlowing()) {
|
||||
RenderHelper.outline(poseStack, 0, 0, bounds.width, bounds.height, ColorUtil.YELLOW);
|
||||
int len = 2 * bounds.width + 2 * bounds.height;
|
||||
|
||||
deltaSum = deltaSum - (int) deltaSum;
|
||||
int pos = (int) (len * deltaSum);
|
||||
|
||||
drawMoving(poseStack, bounds, pos);
|
||||
drawMoving(poseStack, bounds, pos + 2);
|
||||
drawMoving(poseStack, bounds, pos + 3);
|
||||
drawMoving(poseStack, bounds, pos + 4);
|
||||
drawMoving(poseStack, bounds, pos + 5);
|
||||
drawMoving(poseStack, bounds, pos + 7);
|
||||
|
||||
|
||||
deltaSum2 = deltaSum2 - (int) deltaSum2;
|
||||
pos = (int) (len * deltaSum2);
|
||||
|
||||
drawMoving(poseStack, bounds, pos + len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 2 + len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 3 + len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 4 + len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 5 + len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 7 + len / 3);
|
||||
|
||||
|
||||
deltaSum3 = deltaSum3 - (int) deltaSum3;
|
||||
pos = (int) (len * deltaSum3);
|
||||
|
||||
drawMoving(poseStack, bounds, pos + 2 * len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 2 + 2 * len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 3 + 2 * len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 4 + 2 * len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 5 + 2 * len / 3);
|
||||
drawMoving(poseStack, bounds, pos + 7 + 2 * len / 3);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawMoving(PoseStack poseStack, Rectangle bounds, int pos) {
|
||||
int bh = bounds.width + bounds.height;
|
||||
pos = pos % (2 * bh);
|
||||
int x, y;
|
||||
/**
|
||||
* pos <= w : x=pos, y=0
|
||||
* pos > w && pos<=w+h : x=w, y=pos-w
|
||||
* pos >w+h && pos<=2w+h : x=2w +h - pos, y=h
|
||||
* pos>2w+h : x=0, y=2w+2h-pos
|
||||
*/
|
||||
if (pos <= bounds.width) {
|
||||
x = pos;
|
||||
y = 0;
|
||||
} else if (pos <= bh) {
|
||||
x = bounds.width - 1;
|
||||
y = pos - bounds.width;
|
||||
} else if (pos <= bh + bounds.width) {
|
||||
x = bh + bounds.width - pos;
|
||||
y = bounds.height - 1;
|
||||
} else {
|
||||
x = 0;
|
||||
y = 2 * bh - pos;
|
||||
}
|
||||
GuiComponent.fill(poseStack, x, y, x + 1, y + 1, ColorUtil.BLACK);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.layout.components.AbstractVanillaComponentRenderer;
|
||||
import org.betterx.ui.layout.components.Checkbox;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class CheckboxRenderer extends AbstractVanillaComponentRenderer<net.minecraft.client.gui.components.Checkbox, Checkbox> {
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface ComponentRenderer {
|
||||
void renderInBounds(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
);
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.layout.components.AbstractVanillaComponentRenderer;
|
||||
import org.betterx.ui.layout.components.Input;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class EditBoxRenderer extends AbstractVanillaComponentRenderer<net.minecraft.client.gui.components.EditBox, Input> {
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class NullRenderer implements ComponentRenderer {
|
||||
@Override
|
||||
public void renderInBounds(
|
||||
PoseStack stack,
|
||||
int mouseX,
|
||||
int mouseY,
|
||||
float deltaTicks,
|
||||
Rectangle bounds,
|
||||
Rectangle clipRect
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.layout.components.AbstractVanillaComponentRenderer;
|
||||
import org.betterx.ui.layout.components.Range;
|
||||
import org.betterx.ui.vanilla.Slider;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class RangeRenderer<N extends Number> extends AbstractVanillaComponentRenderer<Slider<N>, Range<N>> {
|
||||
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
import org.betterx.ui.layout.values.Size;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
public class RenderHelper {
|
||||
public static void outline(PoseStack poseStack, int x0, int y0, int x1, int y1, int color) {
|
||||
outline(poseStack, x0, y0, x1, y1, color, color);
|
||||
}
|
||||
|
||||
public static void outline(PoseStack poseStack, int x0, int y0, int x1, int y1, int color1, int color2) {
|
||||
int n;
|
||||
if (x1 < x0) {
|
||||
n = x0;
|
||||
x0 = x1;
|
||||
x1 = n;
|
||||
}
|
||||
|
||||
if (y1 < y0) {
|
||||
n = y0;
|
||||
y0 = y1;
|
||||
y1 = n;
|
||||
}
|
||||
y1--;
|
||||
x1--;
|
||||
|
||||
Matrix4f transform = poseStack.last().pose();
|
||||
innerHLine(transform, x0, x1, y0, color1);
|
||||
innerVLine(transform, x0, y0 + 1, y1, color1);
|
||||
innerHLine(transform, x0 + 1, x1, y1, color2);
|
||||
innerVLine(transform, x1, y0 + 1, y1 - 1, color2);
|
||||
}
|
||||
|
||||
public static void hLine(PoseStack poseStack, int x0, int x1, int y, int color) {
|
||||
if (x1 < x0) {
|
||||
int m = x0;
|
||||
x0 = x1;
|
||||
x1 = m;
|
||||
}
|
||||
|
||||
innerHLine(poseStack.last().pose(), x0, x1, y, color);
|
||||
}
|
||||
|
||||
protected static void innerHLine(Matrix4f transform, int x0, int x1, int y, int color) {
|
||||
innerFill(transform, x0, y, x1 + 1, y + 1, color);
|
||||
}
|
||||
|
||||
public static void vLine(PoseStack poseStack, int x, int y0, int y1, int color) {
|
||||
if (y1 < y0) {
|
||||
int m = y0;
|
||||
y0 = y1;
|
||||
y1 = m;
|
||||
}
|
||||
innerVLine(poseStack.last().pose(), x, y0, y1, color);
|
||||
}
|
||||
|
||||
protected static void innerVLine(Matrix4f transform, int x, int y0, int y1, int color) {
|
||||
innerFill(transform, x, y0, x + 1, y1 + 1, color);
|
||||
}
|
||||
|
||||
private static void innerFill(Matrix4f transform, int x0, int y0, int x1, int y1, int color) {
|
||||
float[] cl = ColorUtil.toFloatArray(color);
|
||||
|
||||
BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder();
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.disableTexture();
|
||||
RenderSystem.defaultBlendFunc();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
bufferBuilder.vertex(transform, (float) x0, (float) y1, 0.0F).color(cl[0], cl[1], cl[2], cl[3]).endVertex();
|
||||
bufferBuilder.vertex(transform, (float) x1, (float) y1, 0.0F).color(cl[0], cl[1], cl[2], cl[3]).endVertex();
|
||||
bufferBuilder.vertex(transform, (float) x1, (float) y0, 0.0F).color(cl[0], cl[1], cl[2], cl[3]).endVertex();
|
||||
bufferBuilder.vertex(transform, (float) x0, (float) y0, 0.0F).color(cl[0], cl[1], cl[2], cl[3]).endVertex();
|
||||
BufferUploader.drawWithShader(bufferBuilder.end());
|
||||
RenderSystem.enableTexture();
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
public static void renderImage(
|
||||
PoseStack stack,
|
||||
int left, int top,
|
||||
ResourceLocation location,
|
||||
Size resourceSize, Rectangle uvRect,
|
||||
float alpha
|
||||
) {
|
||||
renderImage(stack, left, top, uvRect.width, uvRect.height, location, resourceSize, uvRect, alpha);
|
||||
}
|
||||
|
||||
public static void renderImage(
|
||||
PoseStack stack,
|
||||
int left, int top, int width, int height,
|
||||
ResourceLocation location,
|
||||
Size resourceSize, Rectangle uvRect,
|
||||
float alpha
|
||||
) {
|
||||
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||
RenderSystem.setShaderTexture(0, location);
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.blendFunc(
|
||||
GlStateManager.SourceFactor.SRC_ALPHA,
|
||||
GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA
|
||||
);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, alpha);
|
||||
GuiComponent.blit(
|
||||
stack,
|
||||
left, top, width, height,
|
||||
uvRect.left,
|
||||
uvRect.top,
|
||||
uvRect.width,
|
||||
uvRect.height,
|
||||
resourceSize.width(),
|
||||
resourceSize.height()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface ScrollerRenderer {
|
||||
default int scrollerHeight() {
|
||||
return 16;
|
||||
}
|
||||
default int scrollerWidth() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
default int scrollerPadding() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
default Rectangle getScrollerBounds(Rectangle renderBounds) {
|
||||
return new Rectangle(
|
||||
renderBounds.right() - this.scrollerWidth(),
|
||||
renderBounds.top,
|
||||
this.scrollerWidth(),
|
||||
renderBounds.height
|
||||
);
|
||||
}
|
||||
|
||||
default Rectangle getPickerBounds(Rectangle renderBounds, int pickerOffset, int pickerSize) {
|
||||
return new Rectangle(
|
||||
renderBounds.left,
|
||||
renderBounds.top + pickerOffset,
|
||||
renderBounds.width,
|
||||
pickerSize
|
||||
);
|
||||
}
|
||||
|
||||
void renderScrollBar(Rectangle renderBounds, int pickerOffset, int pickerSize);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package org.betterx.ui.layout.components.render;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Font;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface TextProvider {
|
||||
default Font getFont() {
|
||||
return Minecraft.getInstance().font;
|
||||
}
|
||||
|
||||
default int getWidth(net.minecraft.network.chat.Component c) {
|
||||
return getFont().width(c.getVisualOrderText()) + 24;
|
||||
}
|
||||
|
||||
default int getLineHeight(net.minecraft.network.chat.Component c) {
|
||||
return getFont().lineHeight;
|
||||
}
|
||||
|
||||
default int getHeight(net.minecraft.network.chat.Component c) {
|
||||
return getLineHeight(c) + 11;
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package org.betterx.ui.layout.values;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public enum Alignment {
|
||||
MIN, MAX, CENTER
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package org.betterx.ui.layout.values;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Rectangle {
|
||||
public static final Rectangle ZERO = new Rectangle(0, 0, 0, 0);
|
||||
public final int left;
|
||||
public final int top;
|
||||
public final int width;
|
||||
public final int height;
|
||||
|
||||
public Rectangle(int left, int top, int width, int height) {
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public float aspect() {
|
||||
return (float) width / height;
|
||||
}
|
||||
|
||||
public Size sizeFromWidth(int width) {
|
||||
return new Size(width, (int) (width / aspect()));
|
||||
}
|
||||
|
||||
public Size sizeFromHeight(int height) {
|
||||
return new Size((int) (height * aspect()), height);
|
||||
}
|
||||
|
||||
public Size size(float scale) {
|
||||
return new Size((int) (width * scale), (int) (height * scale));
|
||||
}
|
||||
|
||||
public Size size() {
|
||||
return new Size(width, height);
|
||||
}
|
||||
|
||||
public int right() {
|
||||
return left + width;
|
||||
}
|
||||
|
||||
public int bottom() {
|
||||
return top + height;
|
||||
}
|
||||
|
||||
public Rectangle movedBy(int left, int top) {
|
||||
return new Rectangle(this.left + left, this.top + top, this.width, this.height);
|
||||
}
|
||||
|
||||
public Rectangle movedBy(int left, int top, int deltaWidth, int deltaHeight) {
|
||||
return new Rectangle(this.left + left, this.top + top, this.width + deltaWidth, this.height + deltaHeight);
|
||||
}
|
||||
|
||||
public boolean overlaps(Rectangle r) {
|
||||
return this.left < r.right() && this.right() > r.left &&
|
||||
this.top < r.bottom() && this.bottom() > r.top;
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y) {
|
||||
return x >= left && x <= right() && y >= top && y <= bottom();
|
||||
}
|
||||
|
||||
public boolean contains(double x, double y) {
|
||||
return x >= left && x <= right() && y >= top && y <= bottom();
|
||||
}
|
||||
|
||||
public Rectangle intersect(Rectangle r) {
|
||||
if (!overlaps(r)) return ZERO;
|
||||
int left = Math.max(this.left, r.left);
|
||||
int top = Math.max(this.top, r.top);
|
||||
int right = Math.min(this.right(), r.right());
|
||||
int bottom = Math.min(this.bottom(), r.bottom());
|
||||
|
||||
return new Rectangle(left, top, right - left, bottom - top);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "rectangle{" +
|
||||
left +
|
||||
"x" + top +
|
||||
", " + right() +
|
||||
"x" + bottom() +
|
||||
" [" + width +
|
||||
"x" + height +
|
||||
"]}";
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package org.betterx.ui.layout.values;
|
||||
|
||||
public record Size(int width, int height) {
|
||||
public static Size of(int size) {
|
||||
return new Size(size, size);
|
||||
}
|
||||
|
||||
public static Size of(int width, int height) {
|
||||
return new Size(width, height);
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package org.betterx.ui.layout.values;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public interface SizeType {
|
||||
FitContent FIT_CONTENT = new FitContent();
|
||||
FitContentOrFill FIT_CONTENT_OR_FILL = new FitContentOrFill();
|
||||
Fill FILL = new Fill();
|
||||
|
||||
record Fill() implements SizeType {
|
||||
}
|
||||
|
||||
class FitContentOrFill extends FitContent {
|
||||
public FitContentOrFill(ContentSizeSupplier contentSize) {
|
||||
super(contentSize);
|
||||
}
|
||||
|
||||
public FitContentOrFill() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FitContentOrFill copyForSupplier(ContentSizeSupplier component) {
|
||||
return new FitContentOrFill(component);
|
||||
}
|
||||
}
|
||||
|
||||
class FitContent implements SizeType {
|
||||
private final ContentSizeSupplier contentSize;
|
||||
|
||||
public FitContent(ContentSizeSupplier contentSize) {
|
||||
this.contentSize = contentSize;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ContentSizeSupplier {
|
||||
int get();
|
||||
}
|
||||
|
||||
public FitContent() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public FitContent copyForSupplier(ContentSizeSupplier component) {
|
||||
return new FitContent(component);
|
||||
}
|
||||
|
||||
public ContentSizeSupplier contentSize() {
|
||||
return contentSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
record Fixed(int size) implements SizeType {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(" + size + ")";
|
||||
}
|
||||
}
|
||||
|
||||
record Relative(double percentage) implements SizeType {
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(" + percentage + ")";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package org.betterx.ui.layout.values;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class Value {
|
||||
private SizeType sizeType;
|
||||
private int calculatedSize;
|
||||
|
||||
public Value(SizeType sizeType) {
|
||||
this.sizeType = sizeType;
|
||||
this.calculatedSize = 0;
|
||||
}
|
||||
|
||||
public static Value fixed(int size) {
|
||||
return new Value(new SizeType.Fixed(size));
|
||||
}
|
||||
|
||||
public static Value relative(double percentage) {
|
||||
return new Value(new SizeType.Relative(percentage));
|
||||
}
|
||||
|
||||
public static Value fill() {
|
||||
return new Value(SizeType.FILL);
|
||||
}
|
||||
|
||||
public static Value fit() {
|
||||
return new Value(SizeType.FIT_CONTENT);
|
||||
}
|
||||
|
||||
public static Value fitOrFill() {
|
||||
return new Value(SizeType.FIT_CONTENT_OR_FILL);
|
||||
}
|
||||
|
||||
public int calculatedSize() {
|
||||
return calculatedSize;
|
||||
}
|
||||
|
||||
public int setCalculatedSize(int value) {
|
||||
calculatedSize = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
public Value attachComponent(SizeType.FitContent.ContentSizeSupplier c) {
|
||||
if (sizeType instanceof SizeType.FitContent fit && fit.contentSize() == null) {
|
||||
sizeType = fit.copyForSupplier(c);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public int calculateFixed() {
|
||||
return calculate(0);
|
||||
}
|
||||
|
||||
public double calculateRelative() {
|
||||
if (sizeType instanceof SizeType.Relative rel) {
|
||||
return rel.percentage();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int calculate(int parentSize) {
|
||||
calculatedSize = 0;
|
||||
if (sizeType instanceof SizeType.Fixed fixed) {
|
||||
calculatedSize = fixed.size();
|
||||
} else if (sizeType instanceof SizeType.FitContent fit) {
|
||||
calculatedSize = fit.contentSize().get();
|
||||
} else if (sizeType instanceof SizeType.Relative rel) {
|
||||
calculatedSize = (int) (parentSize * rel.percentage());
|
||||
}
|
||||
|
||||
return calculatedSize;
|
||||
}
|
||||
|
||||
public int calculateOrFill(int parentSize) {
|
||||
calculatedSize = calculate(parentSize);
|
||||
if (sizeType instanceof SizeType.Fill || sizeType instanceof SizeType.FitContentOrFill) {
|
||||
calculatedSize = Math.max(parentSize, calculatedSize);
|
||||
}
|
||||
|
||||
return calculatedSize;
|
||||
}
|
||||
|
||||
public double fillWeight() {
|
||||
if (sizeType instanceof SizeType.Fill fill || sizeType instanceof SizeType.FitContentOrFill) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int fill(int fillSize) {
|
||||
return fill(fillSize, fillWeight());
|
||||
}
|
||||
|
||||
public int fill(int fillSize, double totalFillWeight) {
|
||||
if (sizeType instanceof SizeType.Fill) {
|
||||
calculatedSize = (int) Math.round(fillSize * (fillWeight() / totalFillWeight));
|
||||
}
|
||||
return calculatedSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DynamicSize{" +
|
||||
"sizeType=" + sizeType.getClass().getSimpleName() +
|
||||
", calculatedSize=" + calculatedSize +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
package org.betterx.ui.vanilla;
|
||||
|
||||
import org.betterx.ui.ColorUtil;
|
||||
import org.betterx.ui.layout.components.*;
|
||||
import org.betterx.ui.layout.values.Value;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.ConfirmLinkScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public abstract class LayoutScreen extends Screen {
|
||||
protected final int topPadding;
|
||||
protected final int bottomPadding;
|
||||
protected final int sidePadding;
|
||||
|
||||
public LayoutScreen(Component component) {
|
||||
this(null, component, 20, 10, 20);
|
||||
}
|
||||
|
||||
public LayoutScreen(@Nullable Screen parent, Component component) {
|
||||
this(parent, component, 20, 10, 20);
|
||||
}
|
||||
|
||||
public LayoutScreen(
|
||||
@Nullable Screen parent,
|
||||
Component component,
|
||||
int topPadding,
|
||||
int bottomPadding,
|
||||
int sidePadding
|
||||
) {
|
||||
super(component);
|
||||
this.parent = parent;
|
||||
this.topPadding = topPadding;
|
||||
this.bottomPadding = topPadding;
|
||||
this.sidePadding = sidePadding;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Panel main;
|
||||
|
||||
@Nullable
|
||||
public final Screen parent;
|
||||
|
||||
protected abstract LayoutComponent<?, ?> initContent();
|
||||
|
||||
protected void openLink(String uri) {
|
||||
ConfirmLinkScreen cls = new ConfirmLinkScreen(bl -> {
|
||||
if (bl) {
|
||||
Util.getPlatform().openUri(uri);
|
||||
}
|
||||
this.minecraft.setScreen(this);
|
||||
}, uri, true);
|
||||
|
||||
Minecraft.getInstance().setScreen(cls);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void init() {
|
||||
super.init();
|
||||
main = new Panel(this.width, this.height);
|
||||
main.setChild(addTitle(initContent()));
|
||||
|
||||
main.calculateLayout();
|
||||
addRenderableWidget(main);
|
||||
}
|
||||
|
||||
protected LayoutComponent<?, ?> buildTitle() {
|
||||
var text = new Text(fit(), fit(), title).centerHorizontal()
|
||||
.setColor(ColorUtil.WHITE)
|
||||
.setDebugName("title");
|
||||
return text;
|
||||
}
|
||||
|
||||
protected LayoutComponent<?, ?> addTitle(LayoutComponent<?, ?> content) {
|
||||
VerticalStack rows = new VerticalStack(fill(), fill()).setDebugName("title stack");
|
||||
|
||||
if (topPadding > 0) rows.addSpacer(topPadding);
|
||||
rows.add(buildTitle());
|
||||
rows.addSpacer(15);
|
||||
rows.add(content);
|
||||
if (bottomPadding > 0) rows.addSpacer(bottomPadding);
|
||||
|
||||
if (sidePadding <= 0) return rows;
|
||||
|
||||
HorizontalStack cols = new HorizontalStack(fill(), fill()).setDebugName("padded side");
|
||||
cols.addSpacer(sidePadding);
|
||||
cols.add(rows);
|
||||
cols.addSpacer(sidePadding);
|
||||
|
||||
return cols;
|
||||
}
|
||||
|
||||
protected void renderBackground(PoseStack poseStack, int i, int j, float f) {
|
||||
renderDirtBackground(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, int i, int j, float f) {
|
||||
renderBackground(poseStack, i, j, f);
|
||||
super.render(poseStack, i, j, f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() {
|
||||
this.minecraft.setScreen(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Value fit() {
|
||||
return Value.fit();
|
||||
}
|
||||
|
||||
public static Value fitOrFill() {
|
||||
return Value.fitOrFill();
|
||||
}
|
||||
|
||||
public static Value fill() {
|
||||
return Value.fill();
|
||||
}
|
||||
|
||||
public static Value fixed(int size) {
|
||||
return Value.fixed(size);
|
||||
}
|
||||
|
||||
public static Value relative(double percentage) {
|
||||
return Value.relative(percentage);
|
||||
}
|
||||
|
||||
public static MutableComponent translatable(String key) {
|
||||
return Component.translatable(key);
|
||||
}
|
||||
|
||||
public static MutableComponent literal(String content) {
|
||||
return Component.literal(content);
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package org.betterx.ui.vanilla;
|
||||
|
||||
import org.betterx.ui.layout.components.HorizontalStack;
|
||||
import org.betterx.ui.layout.components.LayoutComponent;
|
||||
import org.betterx.ui.layout.values.Size;
|
||||
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class LayoutScreenWithIcon extends LayoutScreen {
|
||||
protected final ResourceLocation icon;
|
||||
|
||||
public LayoutScreenWithIcon(ResourceLocation icon, Component component) {
|
||||
this(null, icon, component);
|
||||
}
|
||||
|
||||
public LayoutScreenWithIcon(
|
||||
@Nullable Screen parent,
|
||||
ResourceLocation icon,
|
||||
Component component
|
||||
) {
|
||||
this(parent, icon, component, 20, 10, 20);
|
||||
}
|
||||
|
||||
public LayoutScreenWithIcon(
|
||||
@Nullable Screen parent,
|
||||
ResourceLocation icon,
|
||||
Component component,
|
||||
int topPadding,
|
||||
int bottomPadding,
|
||||
int sidePadding
|
||||
) {
|
||||
super(parent, component, topPadding, bottomPadding, sidePadding);
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutComponent<?, ?> buildTitle() {
|
||||
LayoutComponent<?, ?> title = super.buildTitle();
|
||||
HorizontalStack row = new HorizontalStack(fill(), fit()).setDebugName("title bar");
|
||||
row.addFiller();
|
||||
row.addIcon(icon, Size.of(512)).setDebugName("icon");
|
||||
row.addSpacer(4);
|
||||
row.add(title);
|
||||
row.addFiller();
|
||||
return row;
|
||||
}
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
package org.betterx.ui.vanilla;
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractSliderButton;
|
||||
import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
public class Slider<N extends Number> extends AbstractSliderButton {
|
||||
@FunctionalInterface
|
||||
public interface SliderValueChanged<N extends Number> {
|
||||
void now(Slider<N> slider, N newValue);
|
||||
}
|
||||
|
||||
protected final Component title;
|
||||
protected final N minValue;
|
||||
protected final N maxValue;
|
||||
|
||||
protected final SliderValueChanged<N> onChange;
|
||||
|
||||
public Slider(
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
N minValue,
|
||||
N maxValue,
|
||||
N initialValue,
|
||||
SliderValueChanged<N> onChange
|
||||
) {
|
||||
this(x, y, width, height, null, minValue, maxValue, initialValue, onChange);
|
||||
}
|
||||
|
||||
public Slider(
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
Component title,
|
||||
N minValue,
|
||||
N maxValue,
|
||||
N initialValue,
|
||||
SliderValueChanged<N> onChange
|
||||
) {
|
||||
super(
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
CommonComponents.EMPTY,
|
||||
(initialValue.doubleValue() - minValue.doubleValue()) / (maxValue.doubleValue() - minValue.doubleValue())
|
||||
);
|
||||
this.title = title;
|
||||
this.minValue = minValue;
|
||||
this.maxValue = maxValue;
|
||||
this.onChange = onChange;
|
||||
|
||||
this.updateMessage();
|
||||
}
|
||||
|
||||
public N currentValue() {
|
||||
Double res = value * (maxValue.doubleValue() - minValue.doubleValue()) + minValue.doubleValue();
|
||||
if (minValue instanceof Integer) {
|
||||
return (N) (Integer) res.intValue();
|
||||
}
|
||||
if (minValue instanceof Byte) {
|
||||
return (N) (Byte) res.byteValue();
|
||||
}
|
||||
if (minValue instanceof Short) {
|
||||
return (N) (Short) res.shortValue();
|
||||
}
|
||||
if (minValue instanceof Long) {
|
||||
return (N) (Long) res.longValue();
|
||||
}
|
||||
if (minValue instanceof Float) {
|
||||
return (N) (Float) res.floatValue();
|
||||
}
|
||||
if (minValue instanceof Double) {
|
||||
return (N) res;
|
||||
}
|
||||
throw new IllegalStateException("The Type " + minValue.getClass()
|
||||
.getSimpleName() + " is not nativley supported. Please override currentValue with an implementation ofr that type");
|
||||
}
|
||||
|
||||
protected String valueToString(N value) {
|
||||
if (minValue instanceof Float || minValue instanceof Double) {
|
||||
double v = value.doubleValue();
|
||||
double m = maxValue.doubleValue();
|
||||
if (m > 1000)
|
||||
return "" + (int) v;
|
||||
if (m > 100)
|
||||
return String.format("%.1f", v);
|
||||
if (m > 10)
|
||||
return String.format("%.2f", v);
|
||||
|
||||
return String.format("%.4f", v);
|
||||
}
|
||||
return "" + value;
|
||||
}
|
||||
|
||||
public Component getValueComponent(N value) {
|
||||
return Component.literal("" + this.valueToString(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateMessage() {
|
||||
final Component valueComponent = getValueComponent(this.currentValue());
|
||||
this.setMessage(title == null ? valueComponent : title.copy()
|
||||
.append(": ")
|
||||
.append(valueComponent));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyValue() {
|
||||
onChange.now(this, currentValue());
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package org.betterx.ui.vanilla;
|
||||
|
||||
import org.betterx.ui.layout.components.render.ScrollerRenderer;
|
||||
import org.betterx.ui.layout.values.Rectangle;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
|
||||
public class VanillaScrollerRenderer implements ScrollerRenderer {
|
||||
public static final VanillaScrollerRenderer DEFAULT = new VanillaScrollerRenderer();
|
||||
|
||||
@Override
|
||||
public void renderScrollBar(Rectangle b, int pickerOffset, int pickerSize) {
|
||||
b = this.getScrollerBounds(b);
|
||||
Rectangle p = this.getPickerBounds(b, pickerOffset, pickerSize);
|
||||
|
||||
|
||||
Tesselator tesselator = Tesselator.getInstance();
|
||||
BufferBuilder bufferBuilder = tesselator.getBuilder();
|
||||
RenderSystem.disableTexture();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
|
||||
|
||||
bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
|
||||
|
||||
//scroller background
|
||||
bufferBuilder.vertex(b.left, b.bottom(), 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
bufferBuilder.vertex(b.right(), b.bottom(), 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
bufferBuilder.vertex(b.right(), b.top, 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
bufferBuilder.vertex(b.left, b.top, 0.0D).color(0, 0, 0, 255).endVertex();
|
||||
|
||||
//scroll widget shadow
|
||||
bufferBuilder.vertex(p.left, p.bottom(), 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
bufferBuilder.vertex(p.right(), p.bottom(), 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
bufferBuilder.vertex(p.right(), p.top, 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
bufferBuilder.vertex(p.left, p.top, 0.0D).color(128, 128, 128, 255).endVertex();
|
||||
|
||||
//scroll widget
|
||||
bufferBuilder.vertex(p.left, p.bottom() - 1, 0.0D)
|
||||
.color(192, 192, 192, 255)
|
||||
.endVertex();
|
||||
bufferBuilder.vertex(p.right() - 1, p.bottom() - 1, 0.0D)
|
||||
.color(192, 192, 192, 255)
|
||||
.endVertex();
|
||||
bufferBuilder.vertex(p.right() - 1, p.top, 0.0D).color(192, 192, 192, 255).endVertex();
|
||||
bufferBuilder.vertex(p.left, p.top, 0.0D).color(192, 192, 192, 255).endVertex();
|
||||
|
||||
tesselator.end();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue