texting numbers

This commit is contained in:
zelophed 2021-04-13 23:54:26 +02:00
parent 5b04e82163
commit bb8153f140
10 changed files with 300 additions and 49 deletions

View file

@ -35,7 +35,7 @@ public class BaseConfigScreen extends ConfigScreen {
.withCallback(() -> ScreenOpener.transitionTo(new SubMenuConfigScreen(this, AllConfigs.CLIENT.specification)))
);
StencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("COMMON CONFIG").formatted(TextFormatting.BOLD)).centered(false, true).at(0, 11, 0);
StencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("COMMON CONFIG").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(commonConfigWidget = ConfigButton.createFromStencilElement(
width / 2 - 100,
height / 2 - 15,
@ -46,7 +46,7 @@ public class BaseConfigScreen extends ConfigScreen {
commonConfigWidget.active = false;
commonConfigWidget.updateColorsFromState();
StencilElement text3 = new TextStencilElement.Centered(client.fontRenderer, new StringTextComponent("SERVER CONFIG").formatted(TextFormatting.BOLD), 200).at(0, 11, 0);
StencilElement text3 = new TextStencilElement(client.fontRenderer, new StringTextComponent("SERVER CONFIG").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(serverConfigWidget = ConfigButton.createFromStencilElement(
width / 2 - 100,
height / 2 - 15 + 50,

View file

@ -104,6 +104,14 @@ public class ConfigButton extends StencilWidget {
gradientColor2 = Palette.getColorForButtonState(false, active, hovered);
}
public void animateGradientFromState() {
startGradientAnimation(
Palette.getColorForButtonState(true, active, hovered),
Palette.getColorForButtonState(false, active, hovered),
true
);
}
private void startGradientAnimation(int c1, int c2, boolean positive, double expSpeed) {
colorAnimation.startWithValue(positive ? 1 : -1);
colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP);

View file

@ -110,8 +110,8 @@ public abstract class ConfigScreen extends NavigatableSimiScreen {
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
int x = (int) (width * 0.5f);
int y = (int) (height * 0.5f);
this.drawHorizontalLine(ms, x-25, x+25, y, 0xff_807060);
this.drawVerticalLine(ms, x, y-25, y+25, 0xff_90a0b0);
//this.drawHorizontalLine(ms, x-25, x+25, y, 0xff_807060);
//this.drawVerticalLine(ms, x, y-25, y+25, 0xff_90a0b0);
//this.testStencil.render(ms);

View file

@ -1,12 +1,18 @@
package com.simibubi.create.foundation.config.ui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.StencilElement;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.widget.list.ExtendedList;
import net.minecraft.util.text.IFormattableTextComponent;
@ -17,6 +23,7 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
super(client, width, height, top, bottom, elementHeight);
func_244605_b(false);
func_244606_c(false);
setRenderSelection(false);
}
@Override
@ -27,6 +34,15 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
super.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderList(MatrixStack p_238478_1_, int p_238478_2_, int p_238478_3_, int p_238478_4_, int p_238478_5_, float p_238478_6_) {
MainWindow window = Minecraft.getInstance().getWindow();
double d0 = window.getGuiScaleFactor();
RenderSystem.enableScissor((int) (this.left * d0), (int) (window.getFramebufferHeight() - (this.bottom* d0)), (int)(this.width * d0), (int)(this.height * d0));
super.renderList(p_238478_1_, p_238478_2_, p_238478_3_, p_238478_4_, p_238478_5_, p_238478_6_);
RenderSystem.disableScissor();
}
@Override
public int getRowWidth() {
return width-18;
@ -42,10 +58,38 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
}
public static abstract class Entry extends ExtendedList.AbstractListEntry<Entry> {
protected List<IGuiEventListener> listeners;
protected Entry() {
listeners = new ArrayList<>();
}
public void tick() {}
public List<IGuiEventListener> getGuiListeners() {
return listeners;
}
@Override
public boolean mouseClicked(double x, double y, int button) {
return getGuiListeners().stream().anyMatch(l -> l.mouseClicked(x, y, button));
}
@Override
public boolean keyPressed(int code, int keyPressed_2_, int keyPressed_3_) {
return getGuiListeners().stream().anyMatch(l -> l.keyPressed(code, keyPressed_2_, keyPressed_3_));
}
@Override
public boolean charTyped(char ch, int code) {
return getGuiListeners().stream().anyMatch(l -> l.charTyped(ch, code));
}
}
public static class LabeledEntry extends Entry {
protected static final float labelWidthMult = 0.4f;
protected TextStencilElement label;
public LabeledEntry(String label) {
@ -54,13 +98,17 @@ public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
UIRenderHelper.streak(ms, 0, x, y+height/2, height, width/2, 0x0);
UIRenderHelper.streak(ms, 0, x, y+height/2, height - 10, width/2, 0x0);
IFormattableTextComponent component = label.getComponent();
if (Minecraft.getInstance().fontRenderer.getWidth(component) > width/2 - 10) {
label.withText(Minecraft.getInstance().fontRenderer.trimToWidth(component, width / 2 - 15).getString() + "...");
if (Minecraft.getInstance().fontRenderer.getWidth(component) > getLabelWidth(width) - 10) {
label.withText(Minecraft.getInstance().fontRenderer.trimToWidth(component, getLabelWidth(width) - 15).getString() + "...");
}
label.at(x + 5, y + height/2 - 4, 0).render(ms);
}
protected static int getLabelWidth(int totalWidth) {
return (int) (totalWidth * labelWidthMult);
}
}
public static class WrappedEntry extends Entry {

View file

@ -11,6 +11,7 @@ import com.electronwill.nightconfig.core.AbstractConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.entries.BooleanEntry;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.TextStencilElement;
@ -69,12 +70,15 @@ public class SubMenuConfigScreen extends ConfigScreen {
if (value instanceof Boolean) {
BooleanEntry entry = new BooleanEntry(humanKey, (ForgeConfigSpec.ConfigValue<Boolean>) configValue, valueSpec);
list.children().add(entry);
} else if (value instanceof Number) {
NumberEntry<? extends Number> entry = NumberEntry.create(value, humanKey, configValue, valueSpec);
if (entry != null) {
list.children().add(entry);
} else {
list.children().add(new ConfigScreenList.LabeledEntry("n-" + o.getClass().getSimpleName() + " " + humanKey + " : " + value));
}
} else {
AbstractSimiWidget widget = createWidgetForValue(configValue, valueSpec, value, s, this);
widget.y = y.getValue();
//list.children().add(new ConfigScreenList.WrappedEntry(widget));
list.children().add(new ConfigScreenList.LabeledEntry(humanKey + " : " + value));
//widgets.add(widget);
}
}

View file

@ -31,11 +31,15 @@ public class BooleanEntry extends ValueEntry<Boolean> {
.withCallback(() -> {
value.set(!value.get());
buttonStencil.withSecond(value.get() ? enabled : disabled);
onValueChange();
});
buttonStencil = ((CombinedStencilElement) button.getStencilElement())
.withMode(CombinedStencilElement.ElementMode.BOTH)
.withSecond(value.get() ? enabled : disabled);
listeners.add(button);
onReset();
}
@Override
@ -48,18 +52,19 @@ public class BooleanEntry extends ValueEntry<Boolean> {
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
button.x = x + width/2;
button.x = x + getLabelWidth(width);
button.y = y;
button.withBounds(width/2 - 34, height).render(ms, mouseX, mouseY, partialTicks);
button.withBounds(width - getLabelWidth(width) - resetWidth, height).render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void onReset() {
super.onReset();
buttonStencil.withSecond(value.get() ? enabled : disabled);
}
@Override
/*@Override
public boolean mouseClicked(double mX, double mY, int button) {
return this.button.mouseClicked(mX, mY, button) || super.mouseClicked(mX, mY, button);
}
}*/
}

View file

@ -0,0 +1,197 @@
package com.simibubi.create.foundation.config.ui.entries;
import java.lang.reflect.Field;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.TextStencilElement;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.common.ForgeConfigSpec;
public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
protected int minOffset = 0, maxOffset = 0;
protected TextStencilElement minText = null, maxText = null;
@Nullable
public static NumberEntry<? extends Number> create(Object type, String label, ForgeConfigSpec.ConfigValue<?> value, ForgeConfigSpec.ValueSpec spec) {
if (type instanceof Integer) {
return new IntegerEntry(label, (ForgeConfigSpec.ConfigValue<Integer>) value, spec);
} else if (type instanceof Float) {
return new FloatEntry(label, (ForgeConfigSpec.ConfigValue<Float>) value, spec);
} else if (type instanceof Double) {
return new DoubleEntry(label, (ForgeConfigSpec.ConfigValue<Double>) value, spec);
}
return null;
}
protected TextFieldWidget textField;
public NumberEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
textField = new TextFieldWidget(Minecraft.getInstance().fontRenderer, 0, 0, 200, 30, StringTextComponent.EMPTY);
textField.setText(String.valueOf(value.get()));
Object range = spec.getRange();
try {
Field minField = range.getClass().getDeclaredField("min");
Field maxField = range.getClass().getDeclaredField("max");
minField.setAccessible(true);
maxField.setAccessible(true);
T min = (T) minField.get(range);
T max = (T) maxField.get(range);
FontRenderer font = Minecraft.getInstance().fontRenderer;
if (!min.equals(getTypeMin())) {
StringTextComponent t = new StringTextComponent(formatBound(min) + " < ");
minText = new TextStencilElement(font, t).centered(true, false);
minOffset = font.getWidth(t);
}
if (!max.equals(getTypeMax())) {
StringTextComponent t = new StringTextComponent(" < " + formatBound(max));
maxText = new TextStencilElement(font, t).centered(true, false);
maxOffset = font.getWidth(t);
}
} catch (NoSuchFieldException | IllegalAccessException | ClassCastException e) {
e.printStackTrace();
}
textField.setResponder(s -> {
try {
T number = getParser().apply(s);
if (!spec.test(number))
throw new IllegalArgumentException();
textField.setTextColor(0xff_20cc20);
value.set(number);
onValueChange();
} catch (IllegalArgumentException ignored) {
textField.setTextColor(0xff_cc2020);
}
});
listeners.add(textField);
onReset();
}
protected String formatBound(T bound) {
String sci = String.format("%.2E", bound);
String str = String.valueOf(bound);
return sci.length() < str.length() ? sci : str;
}
protected abstract T getTypeMin();
protected abstract T getTypeMax();
protected abstract Function<String, T> getParser();
@Override
protected void onReset() {
super.onReset();
textField.setText(String.valueOf(value.get()));
}
@Override
public void tick() {
super.tick();
textField.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
textField.x = x + getLabelWidth(width) + minOffset;
textField.y = y + 10;
textField.setWidth(width - getLabelWidth(width) - resetWidth - minOffset - maxOffset);
textField.setHeight(30);
textField.render(ms, mouseX, mouseY, partialTicks);
if (minText != null)
minText
.at(textField.x - minOffset, textField.y, 0)
.withBounds(minOffset, textField.unusedGetHeight())
.render(ms);
if (maxText != null)
maxText
.at(textField.x + textField.getWidth(), textField.y, 0)
.withBounds(maxOffset, textField.unusedGetHeight())
.render(ms);
}
public static class IntegerEntry extends NumberEntry<Integer> {
public IntegerEntry(String label, ForgeConfigSpec.ConfigValue<Integer> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Integer getTypeMin() {
return Integer.MIN_VALUE;
}
@Override
protected Integer getTypeMax() {
return Integer.MAX_VALUE;
}
@Override
protected Function<String, Integer> getParser() {
return Integer::parseInt;
}
}
public static class FloatEntry extends NumberEntry<Float> {
public FloatEntry(String label, ForgeConfigSpec.ConfigValue<Float> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Float getTypeMin() {
return Float.MIN_VALUE;
}
@Override
protected Float getTypeMax() {
return Float.MAX_VALUE;
}
@Override
protected Function<String, Float> getParser() {
return Float::parseFloat;
}
}
public static class DoubleEntry extends NumberEntry<Double> {
public DoubleEntry(String label, ForgeConfigSpec.ConfigValue<Double> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Double getTypeMin() {
return Double.MIN_VALUE;
}
@Override
protected Double getTypeMax() {
return Double.MAX_VALUE;
}
@Override
protected Function<String, Double> getParser() {
return Double::parseDouble;
}
}
}

View file

@ -21,6 +21,8 @@ public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
TextStencilElement text = new TextStencilElement(Minecraft.getInstance().fontRenderer, "Click to open").centered(true, true);
button = ConfigButton.createFromStencilElement(0, 0, text)
.withCallback(() -> ScreenOpener.transitionTo(new SubMenuConfigScreen(parent, spec, config)));
listeners.add(button);
}
@Override
@ -33,14 +35,14 @@ public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
button.x = x + width/2;
button.x = x + getLabelWidth(width);
button.y = y;
button.withBounds(width/2, height);
button.withBounds(width - getLabelWidth(width), height);
button.render(ms, mouseX, mouseY, partialTicks);
}
@Override
/*@Override
public boolean mouseClicked(double p_231044_1_, double p_231044_3_, int p_231044_5_) {
return button.mouseClicked(p_231044_1_, p_231044_3_, p_231044_5_);
}
}*/
}

View file

@ -10,6 +10,8 @@ import net.minecraftforge.common.ForgeConfigSpec;
public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
protected static final int resetWidth = 24;//including 2px offset on each side
protected ForgeConfigSpec.ConfigValue<T> value;
protected ForgeConfigSpec.ValueSpec spec;
protected ConfigButton reset;
@ -21,11 +23,13 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
TextStencilElement text = new TextStencilElement(Minecraft.getInstance().fontRenderer, "R").centered(true, true);
reset = ConfigButton.createFromStencilElement(0, 0, text)
.withBounds(30, 30)
.withBounds(resetWidth - 4, 20)
.withCallback(() -> {
value.set((T) spec.getDefault());
this.onReset();
});
listeners.add(reset);
}
@Override
@ -37,15 +41,22 @@ public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
reset.x = x + width - 32;
reset.y = y + 10;
reset.x = x + width - resetWidth + 2;
reset.y = y + 15;
reset.render(ms, mouseX, mouseY, partialTicks);
}
@Override
/*@Override
public boolean mouseClicked(double mX, double mY, int button) {
return reset.mouseClicked(mX, mY, button);
}*/
protected void onReset() {
onValueChange();
}
protected void onReset() {}
protected void onValueChange() {
reset.active = !value.get().equals(spec.getDefault());
reset.animateGradientFromState();
}
}

View file

@ -77,28 +77,4 @@ public class TextStencilElement extends DelegatedStencilElement {
public IFormattableTextComponent getComponent() {
return component;
}
public static class Centered extends TextStencilElement {
public Centered(FontRenderer font, String text, int width) {
super(font, text);
this.width = width;
}
public Centered(FontRenderer font, IFormattableTextComponent component, int width) {
super(font, component);
this.width = width;
}
@Override
protected void renderStencil(MatrixStack ms) {
int textWidth = font.getWidth(component);
font.draw(ms, component, width / 2f - textWidth / 2f, 0, 0xff_000000);
}
@Override
protected void renderElement(MatrixStack ms) {
element.render(ms, width, 10);
}
}
}