aboutsummaryrefslogtreecommitdiff
path: root/runtime
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2023-10-22 22:32:24 +0800
committershedaniel <daniel@shedaniel.me>2024-04-16 00:38:18 +0900
commit03fc341975d5bfe4d09b56fe2523ddc91d702b2a (patch)
treec1038c5e7b147c891225acdae81fc2e6a3d0489f /runtime
parent51d84c0f80e6a459b933add343fc07e9e36a8a7f (diff)
downloadRoughlyEnoughItems-03fc341975d5bfe4d09b56fe2523ddc91d702b2a.tar.gz
RoughlyEnoughItems-03fc341975d5bfe4d09b56fe2523ddc91d702b2a.tar.bz2
RoughlyEnoughItems-03fc341975d5bfe4d09b56fe2523ddc91d702b2a.zip
Implement some of the config ui
Diffstat (limited to 'runtime')
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/REIConfigScreen.java57
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoriesListWidget.java1
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoryEntryWidget.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigEntriesListWidget.java44
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigGroupWidget.java67
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java94
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java105
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java8
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/CompositeOption.java42
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/ConfigPreviewer.java32
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/ConfigUtils.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionCategory.java4
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionGroup.java8
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionValueEntry.java15
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/preview/ThemePreviewer.java49
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/ListWidget.java2
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/basewidgets/PanelWidget.java8
-rwxr-xr-xruntime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json3
18 files changed, 523 insertions, 20 deletions
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/REIConfigScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/REIConfigScreen.java
index 3705e4aeb..f8262de4c 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/REIConfigScreen.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/REIConfigScreen.java
@@ -28,26 +28,37 @@ import com.mojang.blaze3d.vertex.PoseStack;
import dev.architectury.utils.value.IntValue;
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.Widgets;
+import me.shedaniel.rei.impl.client.config.ConfigManagerImpl;
+import me.shedaniel.rei.impl.client.config.ConfigObjectImpl;
import me.shedaniel.rei.impl.client.gui.config.components.ConfigCategoriesListWidget;
+import me.shedaniel.rei.impl.client.gui.config.components.ConfigEntriesListWidget;
import me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigCategories;
+import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
import me.shedaniel.rei.impl.client.gui.config.options.OptionCategory;
+import me.shedaniel.rei.impl.client.gui.config.options.OptionGroup;
import me.shedaniel.rei.impl.client.gui.credits.CreditsScreen;
-import me.shedaniel.rei.impl.client.gui.widget.HoleWidget;
+import me.shedaniel.rei.impl.client.gui.modules.Menu;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.TranslatableComponent;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class REIConfigScreen extends Screen {
private final Screen parent;
private final List<OptionCategory> categories;
private final List<Widget> widgets = new ArrayList<>();
+ private final Map<CompositeOption<?>, ?> options = new HashMap<>();
private OptionCategory activeCategory;
+ @Nullable
+ private Menu menu;
public REIConfigScreen(Screen parent) {
this(parent, AllREIConfigCategories.CATEGORIES);
@@ -59,6 +70,15 @@ public class REIConfigScreen extends Screen {
this.categories = categories;
Preconditions.checkArgument(!categories.isEmpty(), "Categories cannot be empty!");
this.activeCategory = categories.get(0);
+
+ ConfigObjectImpl config = ConfigManagerImpl.getInstance().getConfig();
+ for (OptionCategory category : categories) {
+ for (OptionGroup group : category.getGroups()) {
+ for (CompositeOption<?> option : group.getOptions()) {
+ ((Map<CompositeOption<?>, Object>) this.options).put(option, option.getBind().apply(config));
+ }
+ }
+ }
}
@Override
@@ -71,10 +91,12 @@ public class REIConfigScreen extends Screen {
}));
this.widgets.add(Widgets.createLabel(new Point(width / 2, 12), this.title));
int sideWidth = (int) (width / 3.8);
+ Widget[] list = {ConfigEntriesListWidget.create(new Rectangle(12 + sideWidth, 32, width - 20 - sideWidth, height - 32 - 32), activeCategory.getGroups())};
this.widgets.add(ConfigCategoriesListWidget.create(new Rectangle(8, 32, sideWidth, height - 32 - 32), categories, new IntValue() {
@Override
public void accept(int i) {
REIConfigScreen.this.activeCategory = categories.get(i);
+ list[0] = ConfigEntriesListWidget.create(new Rectangle(12 + sideWidth, 32, width - 20 - sideWidth, height - 32 - 32), activeCategory.getGroups());
}
@Override
@@ -82,7 +104,11 @@ public class REIConfigScreen extends Screen {
return categories.indexOf(activeCategory);
}
}));
- this.widgets.add(HoleWidget.create(new Rectangle(12 + sideWidth, 32, width - 20 - sideWidth, height - 32 - 32), () -> 0, 32));
+ this.widgets.add(Widgets.delegate(() -> list[0]));
+ }
+
+ public Map<CompositeOption<?>, ?> getOptions() {
+ return options;
}
@Override
@@ -106,6 +132,8 @@ public class REIConfigScreen extends Screen {
@Override
public boolean charTyped(char character, int modifiers) {
+ if (menu != null && menu.charTyped(character, modifiers))
+ return true;
for (GuiEventListener listener : children())
if (listener.charTyped(character, modifiers))
return true;
@@ -114,6 +142,8 @@ public class REIConfigScreen extends Screen {
@Override
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
+ if (menu != null && menu.mouseDragged(mouseX, mouseY, button, deltaX, deltaY))
+ return true;
for (GuiEventListener entry : children())
if (entry.mouseDragged(mouseX, mouseY, button, deltaX, deltaY))
return true;
@@ -121,7 +151,16 @@ public class REIConfigScreen extends Screen {
}
@Override
+ public boolean mouseClicked(double mouseX, double mouseY, int button) {
+ if (menu != null && menu.mouseClicked(mouseX, mouseY, button))
+ return true;
+ return super.mouseClicked(mouseX, mouseY, button);
+ }
+
+ @Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
+ if (menu != null && menu.mouseReleased(mouseX, mouseY, button))
+ return true;
for (GuiEventListener entry : children())
if (entry.mouseReleased(mouseX, mouseY, button))
return true;
@@ -130,9 +169,21 @@ public class REIConfigScreen extends Screen {
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
+ if (menu != null && menu.mouseScrolled(mouseX, mouseY, amount))
+ return true;
for (GuiEventListener listener : children())
if (listener.mouseScrolled(mouseX, mouseY, amount))
return true;
return super.mouseScrolled(mouseX, mouseY, amount);
}
+
+ public void openMenu(Menu menu) {
+ this.menu = menu;
+ this.widgets.add(menu);
+ }
+
+ public void closeMenu() {
+ this.widgets.remove(menu);
+ this.menu = null;
+ }
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoriesListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoriesListWidget.java
index e56e04f5f..cfacac0ac 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoriesListWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoriesListWidget.java
@@ -24,7 +24,6 @@
package me.shedaniel.rei.impl.client.gui.config.components;
import dev.architectury.utils.value.IntValue;
-import me.shedaniel.clothconfig2.api.scroll.ScrollingContainer;
import me.shedaniel.math.Rectangle;
import me.shedaniel.rei.api.client.gui.widgets.Widget;
import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds;
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoryEntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoryEntryWidget.java
index 177c0104d..190d90cf2 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoryEntryWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigCategoryEntryWidget.java
@@ -34,7 +34,7 @@ import net.minecraft.client.gui.Font;
public class ConfigCategoryEntryWidget {
public static WidgetWithBounds create(OptionCategory category) {
- Label label = Widgets.createLabel(new Point(21, 7), category.getName().copy().withStyle(style -> style.withColor(0xFFD0D0D0)))
+ Label label = Widgets.createLabel(new Point(21, 7), category.getName().copy().withStyle(style -> style.withColor(0xFFC0C0C0)))
.leftAligned();
Font font = Minecraft.getInstance().font;
Rectangle bounds = new Rectangle(0, 0, label.getBounds().getMaxX(), 7 * 3);
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
new file mode 100644
index 000000000..6f580d3a3
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigEntriesListWidget.java
@@ -0,0 +1,44 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.impl.client.gui.config.components;
+
+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.impl.client.gui.config.options.OptionGroup;
+import me.shedaniel.rei.impl.client.gui.widget.ListWidget;
+import me.shedaniel.rei.impl.client.gui.widget.ScrollableViewWidget;
+import me.shedaniel.rei.impl.common.util.RectangleUtils;
+
+import java.util.List;
+
+public class ConfigEntriesListWidget {
+ public static Widget create(Rectangle bounds, List<OptionGroup> groups) {
+ WidgetWithBounds list = ListWidget.builderOf(RectangleUtils.inset(bounds, 6, 6), groups,
+ (index, entry) -> ConfigGroupWidget.create(entry, bounds.width - 12 - 6))
+ .gap(7)
+ .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
new file mode 100644
index 000000000..76d41e4f1
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigGroupWidget.java
@@ -0,0 +1,67 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.impl.client.gui.config.components;
+
+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.impl.client.gui.config.options.CompositeOption;
+import me.shedaniel.rei.impl.client.gui.config.options.OptionGroup;
+import net.minecraft.client.gui.GuiComponent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ConfigGroupWidget {
+ public static WidgetWithBounds create(OptionGroup entry, int width) {
+ List<Widget> 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());
+
+ 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());
+
+ if (entry.getOptions().get(entry.getOptions().size() - 1) != option) {
+ int y = height;
+ widgets.add(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);
+ }
+ }));
+ height += 7;
+ }
+ }
+
+ Rectangle bounds = new Rectangle(0, 0, width, height);
+ return Widgets.concatWithBounds(bounds, widgets);
+ }
+}
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
new file mode 100644
index 000000000..bfa7d66b7
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java
@@ -0,0 +1,94 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+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.Label;
+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.api.common.util.CollectionUtils;
+import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen;
+import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
+import me.shedaniel.rei.impl.client.gui.config.options.OptionValueEntry;
+import me.shedaniel.rei.impl.client.gui.modules.Menu;
+import me.shedaniel.rei.impl.client.gui.modules.entries.ToggleMenuEntry;
+import net.minecraft.client.Minecraft;
+import net.minecraft.network.chat.Component;
+import net.minecraft.resources.ResourceLocation;
+
+import java.util.Map;
+
+import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.literal;
+
+public class ConfigOptionValueWidget {
+ public static <T> WidgetWithBounds create(CompositeOption<T> option) {
+ Map<CompositeOption<?>, ?> options = ((REIConfigScreen) Minecraft.getInstance().screen).getOptions();
+ OptionValueEntry<T> entry = option.getEntry();
+ T value = (T) options.get(option);
+ Component text;
+
+ if (entry instanceof OptionValueEntry.Selection<T> selection) {
+ text = selection.getOption(value);
+ } else {
+ text = literal(value.toString());
+ }
+
+ Label label = Widgets.createLabel(new Point(), text).rightAligned()
+ .color(0xFFE0E0E0)
+ .hoveredColor(0xFFE0E0E0);
+ Matrix4f[] matrix = {new Matrix4f()};
+
+ if (entry instanceof OptionValueEntry.Selection<T> selection) {
+ int noOfOptions = selection.getOptions().size();
+ if (noOfOptions == 2) {
+ label.clickable().onClick($ -> {
+ ((Map<CompositeOption<?>, Object>) options).put(option, selection.getOptions().get((selection.getOptions().indexOf((T) options.get(option)) + 1) % 2));
+ label.setMessage(selection.getOption((T) options.get(option)));
+ });
+ } else if (noOfOptions >= 2) {
+ label.clickable().onClick($ -> {
+ Menu menu = new Menu(MatrixUtils.transform(matrix[0], label.getBounds()), CollectionUtils.map(selection.getOptions(),
+ opt -> ToggleMenuEntry.of(selection.getOption(opt), () -> false, o -> {
+ ((REIConfigScreen) Minecraft.getInstance().screen).closeMenu();
+ ((Map<CompositeOption<?>, Object>) options).put(option, opt);
+ label.setMessage(selection.getOption(opt));
+ })
+ .withActive(() -> true)), false);
+ ((REIConfigScreen) Minecraft.getInstance().screen).closeMenu();
+ ((REIConfigScreen) Minecraft.getInstance().screen).openMenu(menu);
+ });
+ }
+ }
+
+ return Widgets.concatWithBounds(() -> new Rectangle(-label.getBounds().width, 0, label.getBounds().width + 8, 14),
+ label,
+ Widgets.createDrawableWidget((helper, matrices, mouseX, mouseY, delta) -> matrix[0] = matrices.last().pose()),
+ Widgets.withTranslate(Widgets.createTexturedWidget(new ResourceLocation("roughlyenoughitems:textures/gui/config/selector.png"),
+ new Rectangle(1, 1, 4, 6), 0, 0, 1, 1, 1, 1), 0, 0.5, 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
new file mode 100644
index 000000000..9707b3ab7
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionWidget.java
@@ -0,0 +1,105 @@
+/*
+ * This file is licensed under the MIT License, part of Roughly Enough Items.
+ * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package me.shedaniel.rei.impl.client.gui.config.components;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import com.mojang.math.Matrix4f;
+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.impl.client.gui.config.options.CompositeOption;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.network.chat.MutableComponent;
+import net.minecraft.util.FormattedCharSequence;
+
+import java.util.ArrayList;
+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) {
+ List<Widget> widgets = new ArrayList<>();
+ int[] height = {12};
+ widgets.add(Widgets.createLabel(new Point(0, 0), option.getName().copy().withStyle(style -> style.withColor(0xFFC0C0C0)))
+ .leftAligned());
+ WidgetWithBounds optionValue = ConfigOptionValueWidget.create(option);
+ widgets.add(Widgets.withTranslate(optionValue, () -> Matrix4f.createTranslateMatrix(width - optionValue.getBounds().width - optionValue.getBounds().x, 0, 0)));
+ widgets.add(new WidgetWithBounds() {
+ 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"))
+ .color(0xFFA5F4FF)
+ .hoveredColor(0xFFD1FAFF)
+ .noShadow()
+ .clickable()
+ .rightAligned();
+ boolean nextLinePreview = false;
+
+ {
+ height[0] += 12 * split.size();
+ if (hasPreview) {
+ int lastWidth = Minecraft.getInstance().font.width(split.get(split.size() - 1));
+ if (lastWidth + preview.getBounds().width + 10 > width) {
+ nextLinePreview = true;
+ height[0] += 12;
+ }
+ }
+ }
+
+ @Override
+ public Rectangle getBounds() {
+ return new Rectangle(0, 12, width, 12 + 12 * split.size());
+ }
+
+ @Override
+ public void render(PoseStack poses, int mouseX, int mouseY, float delta) {
+ 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()));
+ } else {
+ this.preview.setPoint(new Point(width, 12 + 12 * split.size() - 12));
+ }
+
+ this.preview.render(poses, mouseX, mouseY, delta);
+ }
+ }
+
+ @Override
+ public List<? extends GuiEventListener> children() {
+ return List.of(preview);
+ }
+ });
+ 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/AllREIConfigOptions.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java
index 706d41200..58827c465 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,6 +25,7 @@ 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.options.preview.ThemePreviewer;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -35,11 +36,12 @@ interface AllREIConfigOptions {
static <T> CompositeOption<T> make(String id, Function<ConfigObjectImpl, T> bind,
BiConsumer<ConfigObjectImpl, T> save) {
return new CompositeOption<>(translatable("config.rei.options." + id),
- translatable("config.rei.options." + id + ".desc"), bind);
+ translatable("config.rei.options." + id + ".desc"), bind, save);
}
CompositeOption<AppearanceTheme> THEME = make("appearance.theme", i -> i.appearance.theme, (i, v) -> i.appearance.theme = v)
- .enumOptions();
+ .enumOptions()
+ .previewer(ThemePreviewer.INSTANCE);
CompositeOption<RecipeBorderType> RECIPE_BORDER = make("appearance.recipe_border", i -> i.appearance.recipeBorder, (i, v) -> i.appearance.recipeBorder = v)
.enumOptions();
CompositeOption<Boolean> REDUCED_MOTION = make("appearance.reduced_motion", i -> i.basics.reduceMotion, (i, v) -> i.basics.reduceMotion = v)
@@ -53,7 +55,7 @@ interface AllREIConfigOptions {
// TODO: NATIVE KEYBINDS
CompositeOption<Boolean> USE_NATIVE_KEYBINDS = make("keybinds.use_native_keybinds", i -> i.basics.keyBindings.useNativeKeybinds, (i, v) -> i.basics.keyBindings.useNativeKeybinds = v)
.enabledDisabled();
- CompositeOption<CheatingMode> CHEATS_MODE = make("cheats.cheats", i -> i.basics.cheating, (i, v) -> i.basics.cheating = v)
+ CompositeOption<CheatingMode> CHEATS_MODE = make("cheats.mode", i -> i.basics.cheating, (i, v) -> i.basics.cheating = v)
.enumOptions();
CompositeOption<ItemCheatingStyle> CHEATS_METHOD = make("cheats.method", i -> i.basics.cheatingStyle, (i, v) -> i.basics.cheatingStyle = v)
.enumOptions();
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 7d7eb46af..11f9126db 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
@@ -25,19 +25,25 @@ package me.shedaniel.rei.impl.client.gui.config.options;
import me.shedaniel.rei.impl.client.config.ConfigObjectImpl;
import net.minecraft.network.chat.Component;
+import org.jetbrains.annotations.Nullable;
+import java.util.function.BiConsumer;
import java.util.function.Function;
public class CompositeOption<T> {
private final Component name;
private final Component description;
private final Function<ConfigObjectImpl, T> bind;
+ private final BiConsumer<ConfigObjectImpl, T> save;
+ @Nullable
+ private ConfigPreviewer<T> previewer;
private OptionValueEntry<T> entry;
- public CompositeOption(Component name, Component description, Function<ConfigObjectImpl, T> bind) {
+ public CompositeOption(Component name, Component description, Function<ConfigObjectImpl, T> bind, BiConsumer<ConfigObjectImpl, T> save) {
this.name = name;
this.description = description;
this.bind = bind;
+ this.save = save;
}
public CompositeOption<T> entry(OptionValueEntry<T> entry) {
@@ -60,4 +66,38 @@ public class CompositeOption<T> {
public CompositeOption<T> enumOptions(T... entry) {
return this.entry(OptionValueEntry.enumOptions(entry));
}
+
+ public CompositeOption<T> previewer(ConfigPreviewer<T> previewer) {
+ this.previewer = previewer;
+ return this;
+ }
+
+ public Component getName() {
+ return name;
+ }
+
+ public Component getDescription() {
+ return description;
+ }
+
+ public Function<ConfigObjectImpl, T> getBind() {
+ return bind;
+ }
+
+ public BiConsumer<ConfigObjectImpl, T> getSave() {
+ return save;
+ }
+
+ public OptionValueEntry<T> getEntry() {
+ return entry;
+ }
+
+ @Nullable
+ public ConfigPreviewer<T> getPreviewer() {
+ return previewer;
+ }
+
+ public boolean hasPreview() {
+ return previewer != null;
+ }
}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/ConfigPreviewer.java b/runtime/src/main/java/me/shedaniel/rei/imp