diff options
| author | shedaniel <daniel@shedaniel.me> | 2023-10-26 15:49:00 +0800 |
|---|---|---|
| committer | shedaniel <daniel@shedaniel.me> | 2024-04-16 00:38:18 +0900 |
| commit | 598dfc5c1f5e532a34f09c7d8d398ec727a33ab3 (patch) | |
| tree | 2f41015d23de0e2a18fce460619a9aeb40aceb36 /runtime | |
| parent | 881f8d146f15c2dfbe1292747f933d3c19cb429a (diff) | |
| download | RoughlyEnoughItems-598dfc5c1f5e532a34f09c7d8d398ec727a33ab3.tar.gz RoughlyEnoughItems-598dfc5c1f5e532a34f09c7d8d398ec727a33ab3.tar.bz2 RoughlyEnoughItems-598dfc5c1f5e532a34f09c7d8d398ec727a33ab3.zip | |
Localise more values and add a basic theme previewer
Diffstat (limited to 'runtime')
10 files changed, 222 insertions, 39 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigEntriesListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigEntriesListWidget.java index 6f580d3a3..de05300eb 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigEntriesListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigEntriesListWidget.java @@ -38,6 +38,7 @@ public class ConfigEntriesListWidget { WidgetWithBounds list = ListWidget.builderOf(RectangleUtils.inset(bounds, 6, 6), groups, (index, entry) -> ConfigGroupWidget.create(entry, bounds.width - 12 - 6)) .gap(7) + .calculateTotalHeightDynamically(true) .build(); return ScrollableViewWidget.create(bounds, list.withPadding(0, 5), true); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigGroupWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigGroupWidget.java index 76d41e4f1..fdad7818d 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigGroupWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigGroupWidget.java @@ -23,45 +23,70 @@ package me.shedaniel.rei.impl.client.gui.config.components; +import com.mojang.math.Matrix4f; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.util.MatrixUtils; import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption; import me.shedaniel.rei.impl.client.gui.config.options.OptionGroup; import net.minecraft.client.gui.GuiComponent; +import org.apache.commons.lang3.tuple.Triple; +import java.util.AbstractList; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; public class ConfigGroupWidget { public static WidgetWithBounds create(OptionGroup entry, int width) { - List<Widget> widgets = new ArrayList<>(); - int height = 0; + List<Triple<Widget, Supplier<Rectangle>, Matrix4f[]>> widgets = new ArrayList<>(); + int[] height = {0}; WidgetWithBounds groupTitle = Widgets.createLabel(new Point(0, 3), entry.getGroupName().copy().withStyle(style -> style.withColor(0xFFC0C0C0).withUnderlined(true))) - .leftAligned(); - groupTitle = groupTitle.withPadding(0, 0, 0, 6); - widgets.add(groupTitle); - height = Math.max(height, groupTitle.getBounds().getMaxY()); + .leftAligned() + .withPadding(0, 0, 0, 6); + widgets.add(Triple.of(groupTitle, groupTitle::getBounds, new Matrix4f[]{new Matrix4f()})); + height[0] = Math.max(height[0], groupTitle.getBounds().getMaxY()); for (CompositeOption<?> option : entry.getOptions()) { - WidgetWithBounds widget = ConfigOptionWidget.create(option, width); - widgets.add(Widgets.withTranslate(widget, 0, height, 0)); - height = Math.max(height, height + widget.getBounds().getMaxY()); + Matrix4f[] translation = new Matrix4f[]{Matrix4f.createTranslateMatrix(0, height[0], 0)}; + WidgetWithBounds widget = Widgets.withTranslate(ConfigOptionWidget.create(option, width), () -> translation[0]); + widgets.add(Triple.of(widget, () -> MatrixUtils.transform(translation[0], widget.getBounds()), translation)); + height[0] = Math.max(height[0], widget.getBounds().getMaxY()); if (entry.getOptions().get(entry.getOptions().size() - 1) != option) { - int y = height; - widgets.add(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { + Matrix4f[] translationDrawable = new Matrix4f[]{Matrix4f.createTranslateMatrix(0, height[0], 0)}; + widgets.add(Triple.of(Widgets.withTranslate(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { for (int x = 0; x <= width; x += 4) { - GuiComponent.fill(matrices, x, y + 1, x + 2, y + 2, 0xFF757575); + GuiComponent.fill(matrices, x, 1, x + 2, 2, 0xFF757575); } - })); - height += 7; + }), () -> translationDrawable[0]), () -> + MatrixUtils.transform(translationDrawable[0], new Rectangle(0, 0, 1, 7)), translationDrawable)); + height[0] += 7; } } - Rectangle bounds = new Rectangle(0, 0, width, height); - return Widgets.concatWithBounds(bounds, widgets); + widgets.add(Triple.of(Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { + int h = 0; + for (Triple<Widget, Supplier<Rectangle>, Matrix4f[]> widget : widgets) { + widget.getRight()[0] = Matrix4f.createTranslateMatrix(0, h, 0); + h = Math.max(h, widget.getMiddle().get().getMaxY()); + } + height[0] = h; + }), Rectangle::new, new Matrix4f[]{new Matrix4f()})); + + return Widgets.concatWithBounds(() -> new Rectangle(0, 0, width, height[0]), new AbstractList<>() { + @Override + public Widget get(int index) { + return widgets.get(index).getLeft(); + } + + @Override + public int size() { + return widgets.size(); + } + }); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java index f2764dd2d..e2d62eed3 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java @@ -23,6 +23,7 @@ package me.shedaniel.rei.impl.client.gui.config.components; +import com.google.common.base.MoreObjects; import com.mojang.math.Matrix4f; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; @@ -43,6 +44,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import java.util.Map; +import java.util.Objects; import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.literal; import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable; @@ -61,7 +63,7 @@ public class ConfigOptionValueWidget { text[0] = literal(value.toString()); } - if (value.equals(defaultOptions.get(option))) { + if (value.equals(Objects.requireNonNullElseGet(option.getDefaultValue(), () -> (T) defaultOptions.get(option)))) { text[0] = translatable("config.rei.value.default", text[0]); } @@ -84,7 +86,7 @@ public class ConfigOptionValueWidget { ((Map<CompositeOption<?>, Object>) options).put(option, selection.getOptions().get((selection.getOptions().indexOf((T) options.get(option)) + 1) % 2)); text[0] = selection.getOption((T) options.get(option)); - if (options.get(option).equals(defaultOptions.get(option))) { + if (options.get(option).equals(Objects.requireNonNullElseGet(option.getDefaultValue(), () -> (T) defaultOptions.get(option)))) { text[0] = translatable("config.rei.value.default", text[0]); } }); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java index 9707b3ab7..2c157767e 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java @@ -25,17 +25,25 @@ package me.shedaniel.rei.impl.client.gui.config.components; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Matrix4f; +import me.shedaniel.clothconfig2.api.ScissorsHandler; +import me.shedaniel.clothconfig2.api.animator.NumberAnimator; +import me.shedaniel.clothconfig2.api.animator.ValueAnimator; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.widgets.Label; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.util.MatrixUtils; +import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen; import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption; +import me.shedaniel.rei.impl.common.util.RectangleUtils; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.FormattedCharSequence; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -43,8 +51,9 @@ import java.util.List; import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable; public class ConfigOptionWidget { - public static WidgetWithBounds create(CompositeOption<?> option, int width) { + public static <T> WidgetWithBounds create(CompositeOption<T> option, int width) { List<Widget> widgets = new ArrayList<>(); + int[] stableHeight = {12}; int[] height = {12}; widgets.add(Widgets.createLabel(new Point(0, 0), option.getName().copy().withStyle(style -> style.withColor(0xFFC0C0C0))) .leftAligned()); @@ -54,21 +63,28 @@ public class ConfigOptionWidget { final MutableComponent description = option.getDescription().copy().withStyle(style -> style.withColor(0xFF757575)); final List<FormattedCharSequence> split = Minecraft.getInstance().font.split(description, width); final boolean hasPreview = option.hasPreview(); - final Label preview = Widgets.createLabel(new Point(), translatable("config.rei.texts.preview")) + final Label previewLabel = Widgets.createLabel(new Point(), translatable("config.rei.texts.preview")) .color(0xFFA5F4FF) .hoveredColor(0xFFD1FAFF) .noShadow() .clickable() + .onClick($ -> clickPreview()) .rightAligned(); + @Nullable + WidgetWithBounds preview = null; + boolean previewVisible = false; + Matrix4f previewTranslation = new Matrix4f(); + final NumberAnimator<Float> previewHeight = ValueAnimator.ofFloat() + .withConvention(() -> previewVisible ? preview.getBounds().getHeight() : 0f, ValueAnimator.typicalTransitionTime()); boolean nextLinePreview = false; { - height[0] += 12 * split.size(); + stableHeight[0] += 12 * split.size(); if (hasPreview) { int lastWidth = Minecraft.getInstance().font.width(split.get(split.size() - 1)); - if (lastWidth + preview.getBounds().width + 10 > width) { + if (lastWidth + this.previewLabel.getBounds().width + 10 > width) { nextLinePreview = true; - height[0] += 12; + stableHeight[0] += 12; } } } @@ -80,26 +96,48 @@ public class ConfigOptionWidget { @Override public void render(PoseStack poses, int mouseX, int mouseY, float delta) { + this.previewHeight.update(delta); + height[0] = stableHeight[0] + Math.round(this.previewHeight.value()); + for (int i = 0; i < split.size(); i++) { Minecraft.getInstance().font.draw(poses, split.get(i), 0, 12 + 12 * i, -1); } if (hasPreview) { if (nextLinePreview) { - this.preview.setPoint(new Point(width, 12 + 12 * split.size())); + this.previewLabel.setPoint(new Point(width, 12 + 12 * split.size())); } else { - this.preview.setPoint(new Point(width, 12 + 12 * split.size() - 12)); + this.previewLabel.setPoint(new Point(width, 12 + 12 * split.size() - 12)); } - this.preview.render(poses, mouseX, mouseY, delta); + this.previewLabel.render(poses, mouseX, mouseY, delta); + + if (this.preview != null && this.previewHeight.value() > 0.1f) { + ScissorsHandler.INSTANCE.scissor(MatrixUtils.transform(poses.last().pose(), new Rectangle(0, 24 + 12 * split.size() - (nextLinePreview ? 0 : 12), width, this.previewHeight.value()))); + this.previewTranslation = Matrix4f.createTranslateMatrix(0, 12 + 12 * split.size(), 100); + this.preview.render(poses, mouseX, mouseY, delta); + ScissorsHandler.INSTANCE.removeLastScissor(); + } } } + private void clickPreview() { + if (this.preview == null) { + this.preview = option.getPreviewer().preview(width, () -> (T) ((REIConfigScreen) Minecraft.getInstance().screen).getOptions().get(option)); + this.preview = Widgets.withTranslate(this.preview, () -> this.previewTranslation); + } + + this.previewVisible = !this.previewVisible; + } + @Override public List<? extends GuiEventListener> children() { - return List.of(preview); + if (this.preview != null && this.previewHeight.value() > 0.1f) return List.of(this.previewLabel, this.preview); + return List.of(this.previewLabel); } }); - return Widgets.concatWithBounds(new Rectangle(0, 0, width, height[0]), widgets); + + height[0] = stableHeight[0]; + return Widgets.concatWithBounds(() -> new Rectangle(0, 0, width, height[0]), widgets); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java index 60a78a657..87725f710 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigGroups.java @@ -53,7 +53,8 @@ interface AllREIConfigGroups { .add(CONFIG_BUTTON_LOCATION) .add(CRAFTABLE_FILTER); OptionGroup LAYOUT_PANEL = make("layout.panel") - .add(BOUNDARIES); + .add(BOUNDARIES) + .add(LOCATION); OptionGroup ACCESSIBILITY_DISPLAY = make("accessibility.display") .add(LARGER_TABS) .add(LARGER_ARROW_BUTTONS); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java index 58827c465..f418e9edd 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java @@ -25,11 +25,14 @@ package me.shedaniel.rei.impl.client.gui.config.options; import me.shedaniel.rei.api.client.gui.config.*; import me.shedaniel.rei.impl.client.config.ConfigObjectImpl; +import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen; import me.shedaniel.rei.impl.client.gui.config.options.preview.ThemePreviewer; +import net.minecraft.client.Minecraft; import java.util.function.BiConsumer; import java.util.function.Function; +import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.literal; import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable; interface AllREIConfigOptions { @@ -47,7 +50,8 @@ interface AllREIConfigOptions { CompositeOption<Boolean> REDUCED_MOTION = make("appearance.reduced_motion", i -> i.basics.reduceMotion, (i, v) -> i.basics.reduceMotion = v) .enabledDisabled(); CompositeOption<DisplayScreenType> RECIPE_LOOKUP_STYLE = make("appearance.recipe_lookup_style", i -> i.appearance.recipeScreenType, (i, v) -> i.appearance.recipeScreenType = v) - .enumOptions(); + .options(DisplayScreenType.ORIGINAL, DisplayScreenType.COMPOSITE) + .defaultValue(() -> DisplayScreenType.ORIGINAL); CompositeOption<Boolean> APPEND_MOD_NAMES = make("appearance.append_mod_names", i -> i.advanced.tooltips.appendModNames, (i, v) -> i.advanced.tooltips.appendModNames = v) .enabledDisabled(); CompositeOption<Boolean> APPEND_FAVORITES_HINT = make("appearance.append_favorites_hint", i -> i.advanced.tooltips.displayFavoritesTooltip, (i, v) -> i.advanced.tooltips.displayFavoritesTooltip = v) @@ -63,14 +67,28 @@ interface AllREIConfigOptions { .enumOptions(); CompositeOption<String> GIVE_COMMAND = make("cheats.give_command", i -> i.advanced.commands.giveCommand, (i, v) -> i.advanced.commands.giveCommand = v); CompositeOption<SearchFieldLocation> SEARCH_FIELD_LOCATION = make("layout.search_field_location", i -> i.appearance.layout.searchFieldLocation, (i, v) -> i.appearance.layout.searchFieldLocation = v) - .enumOptions(); + .entry(OptionValueEntry.<SearchFieldLocation>enumOptions().overrideText(location -> { + if (Minecraft.getInstance().screen instanceof REIConfigScreen configScreen) { + return literal(location.toString(configScreen.getOptions().get(AllREIConfigOptions.LOCATION) == DisplayPanelLocation.RIGHT)); + } else { + return literal(location.toString(true)); + } + })); CompositeOption<ConfigButtonPosition> CONFIG_BUTTON_LOCATION = make("layout.config_button_location", i -> i.appearance.layout.configButtonLocation, (i, v) -> i.appearance.layout.configButtonLocation = v) - .enumOptions(); + .entry(OptionValueEntry.<ConfigButtonPosition>enumOptions().overrideText(location -> { + if (Minecraft.getInstance().screen instanceof REIConfigScreen configScreen) { + return literal(location.toString(configScreen.getOptions().get(AllREIConfigOptions.LOCATION) == DisplayPanelLocation.RIGHT)); + } else { + return literal(location.toString(true)); + } + })); CompositeOption<Boolean> CRAFTABLE_FILTER = make("layout.craftable_filter", i -> i.appearance.layout.showCraftableOnlyButton, (i, v) -> i.appearance.layout.showCraftableOnlyButton = v) .enabledDisabled(); // TODO: BOUNDARIES CompositeOption<Boolean> BOUNDARIES = make("layout.boundaries", i -> true, (i, v) -> { }); + CompositeOption<DisplayPanelLocation> LOCATION = make("layout.location", i -> i.advanced.accessibility.displayPanelLocation, (i, v) -> i.advanced.accessibility.displayPanelLocation = v) + .enumOptions(); CompositeOption<Boolean> LARGER_TABS = make("accessibility.larger_tabs", i -> !i.advanced.accessibility.useCompactTabs, (i, v) -> i.advanced.accessibility.useCompactTabs = !v) .enabledDisabled(); CompositeOption<Boolean> LARGER_ARROW_BUTTONS = make("accessibility.larger_arrow_buttons", i -> !i.advanced.accessibility.useCompactTabButtons, (i, v) -> i.advanced.accessibility.useCompactTabButtons = !v) diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/CompositeOption.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/CompositeOption.java index 11f9126db..b0eb11a08 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/CompositeOption.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/CompositeOption.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.Supplier; public class CompositeOption<T> { private final Component name; @@ -37,6 +38,8 @@ public class CompositeOption<T> { private final BiConsumer<ConfigObjectImpl, T> save; @Nullable private ConfigPreviewer<T> previewer; + @Nullable + private Supplier<T> defaultValue = null; private OptionValueEntry<T> entry; public CompositeOption(Component name, Component description, Function<ConfigObjectImpl, T> bind, BiConsumer<ConfigObjectImpl, T> save) { @@ -67,11 +70,20 @@ public class CompositeOption<T> { return this.entry(OptionValueEntry.enumOptions(entry)); } + public CompositeOption<T> options(T... entry) { + return this.entry(OptionValueEntry.options(entry)); + } + public CompositeOption<T> previewer(ConfigPreviewer<T> previewer) { this.previewer = previewer; return this; } + public CompositeOption<T> defaultValue(Supplier<T> defaultValue) { + this.defaultValue = defaultValue; + return this; + } + public Component getName() { return name; } @@ -100,4 +112,10 @@ public class CompositeOption<T> { public boolean hasPreview() { return previewer != null; } + + @Nullable + public T getDefaultValue() { + if (defaultValue == null) return null; + return defaultValue.get(); + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionValueEntry.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionValueEntry.java index 6ec876266..303d16607 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionValueEntry.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionValueEntry.java @@ -26,7 +26,9 @@ package me.shedaniel.rei.impl.client.gui.config.options; import me.shedaniel.rei.api.common.util.CollectionUtils; import net.minecraft.network.chat.Component; +import java.util.Arrays; import java.util.List; +import java.util.function.Function; import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.literal; import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.translatable; @@ -37,7 +39,7 @@ public interface OptionValueEntry<T> { }; } - static OptionValueEntry<Boolean> ofBoolean(Component falseText, Component trueText) { + static OptionValueEntry.Selection<Boolean> ofBoolean(Component falseText, Component trueText) { return new Selection<Boolean>() { @Override public List<Boolean> getOptions() { @@ -51,17 +53,17 @@ public interface OptionValueEntry<T> { }; } - static OptionValueEntry<Boolean> trueFalse() { + static OptionValueEntry.Selection<Boolean> trueFalse() { return ofBoolean(translatable("config.rei.value.trueFalse.false"), translatable("config.rei.value.trueFalse.true")); } - static OptionValueEntry<Boolean> enabledDisabled() { + static OptionValueEntry.Selection<Boolean> enabledDisabled() { return ofBoolean(translatable("config.rei.value.enabledDisabled.false"), translatable("config.rei.value.enabledDisabled.true")); } - static <T> OptionValueEntry<T> enumOptions(T... array) { + static <T> OptionValueEntry.Selection<T> enumOptions(T... array) { Class<T> type = (Class<T>) array.getClass().getComponentType(); Object[] constants = type.getEnumConstants(); return new Selection<T>() { @@ -77,9 +79,37 @@ public interface OptionValueEntry<T> { }; } + static <T> OptionValueEntry<T> options(T... options) { + return new Selection<T>() { + @Override + public List<T> getOptions() { + return Arrays.asList(options); + } + + @Override + public Component getOption(T value) { + return literal(value.toString()); + } + }; + } + interface Selection<T> extends OptionValueEntry<T> { List<T> getOptions(); Component getOption(T value); + + default Selection<T> overrideText(Function<T, Component> textFunction) { + return new Selection<T>() { + @Override + public List<T> getOptions() { + return Selection.this.getOptions(); + } + + @Override + public Component getOption(T value) { + return textFunction.apply(value); + } + }; + } } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/preview/ThemePreviewer.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/preview/ThemePreviewer.java index df5ac9be6..42fcc9cee 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/preview/ThemePreviewer.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/preview/ThemePreviewer.java @@ -24,12 +24,16 @@ package me.shedaniel.rei.impl.client.gui.config.options.preview; import me.shedaniel.clothconfig2.api.animator.ValueAnimator; +import me.shedaniel.math.Color; +import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.gui.config.AppearanceTheme; +import me.shedaniel.rei.api.client.gui.widgets.Label; import me.shedaniel.rei.api.client.gui.widgets.Panel; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.client.gui.widgets.Widgets; import me.shedaniel.rei.impl.client.gui.config.options.ConfigPreviewer; +import me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils; import me.shedaniel.rei.impl.client.gui.widget.basewidgets.PanelWidget; import java.util.List; @@ -40,10 +44,19 @@ public enum ThemePreviewer implements ConfigPreviewer<AppearanceTheme> { @Override public WidgetWithBounds preview(int width, Supplier<AppearanceTheme> value) { - Panel base = Widgets.createCategoryBase(new Rectangle(width * 10 / 2, 3, width * 10 / 8, 20)); + Panel base = Widgets.createCategoryBase(new Rectangle(width * 5 / 20, 3, width * 5 / 10, 50)); ((PanelWidget) base).setDarkBackgroundAlpha(ValueAnimator.ofFloat() .withConvention(() -> value.get() == AppearanceTheme.DARK ? 1.0F : 0.0F, ValueAnimator.typicalTransitionTime()) .asFloat()); - return Widgets.concatWithBounds(new Rectangle(0, 0, width, 26), List.of(base)); + ValueAnimator<Color> labelColor = ValueAnimator.ofColor(value.get() == AppearanceTheme.LIGHT ? Color.ofTransparent(0xFF404040) : Color.ofTransparent(0xFFBBBBBB)) + .withConvention(() -> value.get() == AppearanceTheme.LIGHT ? Color.ofTransparent(0xFF404040) : Color.ofTransparent(0xFFBBBBBB), ValueAnimator.typicalTransitionTime()); + Label label = Widgets.createLabel(new Point(width / 2, 24), ConfigUtils.literal("Preview")) + .centered() + .noShadow() + .color(labelColor.value().getColor()); + return Widgets.concatWithBounds(new Rectangle(0, 0, width, 56), List.of(base, label, Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> { + labelColor.update(delta); + label.color(labelColor.value().getColor()); + }))); } } diff --git a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json index 883b778e2..fc0e561c1 100755 --- a/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json +++ b/runtime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json @@ -246,12 +246,19 @@ "config.rei.options.groups.appearance.interface": "Interface", "config.rei.options.appearance.theme": "Theme", "config.rei.options.appearance.theme.desc": "The global theme of Roughly Enough Items. This will be applied everywhere, including background, buttons, etc.", + "config.rei.value.appearance.theme.light": "Light", + "config.rei.value.appearance.theme.dark": "Dark", "config.rei.options.appearance.recipe_border": "Recipe Border", "config.rei.options.appearance.recipe_border.desc": "The border of each recipe. Default is the preferred REI look.", + "config.rei.value.appearance.recipe_border.default": "Default", + "config.rei.value.appearance.recipe_border.lighter": "Lighter", + "config.rei.value.appearance.recipe_border.none": "Invisible", "config.rei.options.appearance.reduced_motion": "Reduced Motion", "config.rei.options.appearance.reduced_motion.desc": "Disables animation for transitions, menus, hover states, to minimize discomfort caused by vestibular motion triggers.", "config.rei.options.appearance.recipe_lookup_style": "Recipe Lookup Style", - "config.rei.options.appearance.recipe_lookup_style.desc": "The style of how recipes are displayed. Default is for the more classic look, while Composite is for the more informative, villger-like look.", + "config.rei.options.appearance.recipe_lookup_style.desc": "The style of how recipes are displayed. Classic is the default look, while Composite is for the more informative, villger-like look.", + "config.rei.value.appearance.recipe_lookup_style.original": "Classic", + "config.rei.value.appearance.recipe_lookup_style.composite": "Composite", "config.rei.options.groups.appearance.tooltips": "Tooltips", "config.rei.options.appearance.append_mod_names": "Append Mod Names", "config.rei.options.appearance.append_mod_names.desc": "Appends the containing namespace for entries. The appended line will be in italisised light blue.", @@ -264,23 +271,40 @@ "config.rei.options.groups.cheats.cheats": "Cheats", "config.rei.options.cheats.mode": "Mode", "config.rei.options.cheats.mode.desc": "Cheats mode allows you to grab items from the side. This requires operator permission. The /give command would be used as a fallback if REI is not installed on the server.", + "config.rei.value.cheats.mode.when_creative": "When Creative", "config.rei.options.cheats.method": "Method", "config.rei.options.cheats.method.desc": "The way how cheating is achieved. Grab mode places the cheated item at your cursor, while give mode places the cheated item in your inventory.", + "config.rei.value.cheats.method.grab": "Grab", + "config.rei.value.cheats.method.give": "Give", "config.rei.options.cheats.amount": "Amount", "config.rei.options.cheats.amount.desc": "The amount of items cheated. By default, REI cheats 1 item and a stack when clicked with shift.", + "config.rei.value.cheats.amount.default": "Default", + "config.rei.value.cheats.amount.reversed": "Reversed", "config.rei.options.groups.cheats.advanced": "Advanced", "config.rei.options.cheats.give_command": "Give Command", "config.rei.options.cheats.give_command.desc": "The command invoked to cheat items when REI is not installed on the server. This may be useful if the server replaced the default /give command. Available placeholders: {item_name}, {item_identifier}, {count} and {player_name}.", "config.rei.options.groups.layout.widgets": "Widgets", "config.rei.options.layout.search_field_location": "Search Field Location", "config.rei.options.layout.search_field_location.desc": "The location of the search field. By default, the search field is placed at the bottom center, which automatically moves to the side to make way for tall container screens.", + "config.rei.value.layout.search_field_location.center": "Center", + "config.rei.value.layout.search_field_location.bottom_left": "Bottom Left", + "config.rei.value.layout.search_field_location.bottom_right": "Bottom Right", + "config.rei.value.layout.search_field_location.top_left": "Top Left", + "config.rei.value.layout.search_field_location.top_right": "Top Right", "config.rei.options.layout.config_button_location": "Config Button Location", "config.rei.options.layout.config_button_location.desc": "The location of the configuration button. By default, it is placed next to the search field. However, this can be changed to look like the legacy versions of REI, where it is placed on the top side of the screen.", + "config.rei.value.layout.config_button_location.next_to_search": "Next to Search Field", + "config.rei.value.layout.config_button_location.top_left": "Top Left", + "config.rei.value.layout.config_button_location.top_right": "Top Right", "config.rei.options.layout.craftable_filter": "Craftable Filter", "config.rei.options.layout.craftable_filter.desc": "Craftable Filter allows you to view stacks currently craftable with the ingredients in your inventory. This can be useful alongside the Ctrl+Click quick craft feature to craft quickly.", "config.rei.options.groups.layout.panel": "Panel", "config.rei.options.layout.boundaries": "Boundaries", "config.rei.options.layout.boundaries.desc": "Declare the boundaries of the panel. Useful to limit the columns / rows displayed on screen.", + "config.rei.options.layout.location": "Location", + "config.rei.options.layout.location.desc": "Change the location of the panel. The entire REI setup may be mirrored horizontally, including the list and all widgets.", + "con |
