aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2023-11-03 18:00:23 +0800
committershedaniel <daniel@shedaniel.me>2024-04-16 00:38:18 +0900
commit1be6fdd292cd5a96af8d9bc1e3432820f3737545 (patch)
tree9f8ff23e38d2db83c750b6d8314d69abdf274fdd
parentc671f024abd0eb5b0e0795ef966232a791896a0d (diff)
downloadRoughlyEnoughItems-1be6fdd292cd5a96af8d9bc1e3432820f3737545.tar.gz
RoughlyEnoughItems-1be6fdd292cd5a96af8d9bc1e3432820f3737545.tar.bz2
RoughlyEnoughItems-1be6fdd292cd5a96af8d9bc1e3432820f3737545.zip
Implement boundaries config and add option for panel alignment
Close #1502
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java6
-rw-r--r--api/src/main/java/me/shedaniel/rei/api/client/gui/config/PanelBoundary.java34
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java12
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java7
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/components/ConfigOptionValueWidget.java15
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/AllREIConfigOptions.java16
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/CompositeOption.java4
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/OptionValueEntry.java22
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/configure/PanelBoundariesConfiguration.java315
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java4
-rwxr-xr-xruntime/src/main/resources/assets/roughlyenoughitems/lang/en_us.json15
11 files changed, 434 insertions, 16 deletions
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java
index 87d242ad3..a15816f24 100644
--- a/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java
+++ b/api/src/main/java/me/shedaniel/rei/api/client/config/ConfigObject.java
@@ -373,6 +373,12 @@ public interface ConfigObject {
double getVerticalEntriesBoundariesRows();
@ApiStatus.Experimental
+ double getHorizontalEntriesBoundariesAlignments();
+
+ @ApiStatus.Experimental
+ double getVerticalEntriesBoundariesAlignments();
+
+ @ApiStatus.Experimental
double getFavoritesHorizontalEntriesBoundariesPercentage();
@ApiStatus.Experimental
diff --git a/api/src/main/java/me/shedaniel/rei/api/client/gui/config/PanelBoundary.java b/api/src/main/java/me/shedaniel/rei/api/client/gui/config/PanelBoundary.java
new file mode 100644
index 000000000..eb9e57f15
--- /dev/null
+++ b/api/src/main/java/me/shedaniel/rei/api/client/gui/config/PanelBoundary.java
@@ -0,0 +1,34 @@
+/*
+ * 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.api.client.gui.config;
+
+public record PanelBoundary(
+ double horizontalPercentage,
+ double verticalPercentage,
+ int horizontalLimit,
+ int verticalLimit,
+ double horizontalAlign,
+ double verticalAlign
+) {
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
index ceb0ed302..a1a94e88c 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/ConfigObjectImpl.java
@@ -541,6 +541,16 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
return Mth.clamp(appearance.verticalEntriesBoundariesRows, 1, 1000);
}
+ @Override
+ public double getHorizontalEntriesBoundariesAlignments() {
+ return appearance.horizontalEntriesBoundariesAlignment;
+ }
+
+ @Override
+ public double getVerticalEntriesBoundariesAlignments() {
+ return appearance.verticalEntriesBoundariesAlignment;
+ }
+
@ApiStatus.Experimental
@Override
public double getFavoritesHorizontalEntriesBoundariesPercentage() {
@@ -665,6 +675,8 @@ public class ConfigObjectImpl implements ConfigObject, ConfigData {
@UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") public double verticalEntriesBoundaries = 1.0;
public int horizontalEntriesBoundariesColumns = 50;
public int verticalEntriesBoundariesRows = 1000;
+ public double horizontalEntriesBoundariesAlignment = 1.0;
+ public double verticalEntriesBoundariesAlignment = 0.5;
@UsePercentage(min = 0.1, max = 1.0, prefix = "Limit: ") public double favoritesHorizontalEntriesBoundaries = 1.0;
public int favoritesHorizontalEntriesBoundariesColumns = 50;
@UseSpecialSearchFilterSyntaxHighlightingScreen public SyntaxHighlightingMode syntaxHighlightingMode = SyntaxHighlightingMode.COLORFUL;
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java
index 85751f649..27048fe86 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/ScreenOverlayImpl.java
@@ -269,14 +269,13 @@ public abstract class ScreenOverlayImpl extends ScreenOverlay {
private static Rectangle calculateOverlayBounds() {
Rectangle bounds = ScreenRegistry.getInstance().getOverlayBounds(ConfigObject.getInstance().getDisplayPanelLocation(), Minecraft.getInstance().screen);
+ double hAlign = ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.LEFT ? 1 - ConfigObject.getInstance().getHorizontalEntriesBoundariesAlignments() : ConfigObject.getInstance().getHorizontalEntriesBoundariesAlignments();
int widthReduction = (int) Math.round(bounds.width * (1 - ConfigObject.getInstance().getHorizontalEntriesBoundariesPercentage()));
- if (ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.RIGHT)
- bounds.x += widthReduction;
+ bounds.x += (int) Math.round(widthReduction * hAlign);
bounds.width -= widthReduction;
int maxWidth = (int) Math.ceil(entrySize() * ConfigObject.getInstance().getHorizontalEntriesBoundariesColumns() + entrySize() * 0.75);
if (bounds.width > maxWidth) {
- if (ConfigObject.getInstance().getDisplayPanelLocation() == DisplayPanelLocation.RIGHT)
- bounds.x += bounds.width - maxWidth;
+ bounds.x += (int) Math.round((bounds.width - maxWidth) * hAlign);
bounds.width = maxWidth;
}
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 81b35a47c..015804d65 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
@@ -34,7 +34,6 @@ 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.api.common.util.FormattingUtils;
import me.shedaniel.rei.impl.client.gui.config.ConfigAccess;
import me.shedaniel.rei.impl.client.gui.config.REIConfigScreen;
import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
@@ -44,14 +43,11 @@ import me.shedaniel.rei.impl.client.gui.modules.entries.ToggleMenuEntry;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
-import net.minecraft.network.chat.Style;
-import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
-import net.minecraft.util.FormattedCharSequence;
-import java.lang.ref.Reference;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
@@ -68,7 +64,7 @@ public class ConfigOptionValueWidget {
text[0] = literal("> ").withStyle(ChatFormatting.YELLOW)
.append(t.copy().withStyle(ChatFormatting.YELLOW))
.append(literal(" <").withStyle(ChatFormatting.YELLOW));
- } else if (access.get(option).equals(Objects.requireNonNullElseGet(option.getDefaultValue(), () -> access.getDefault(option)))) {
+ } else if (!(option.getEntry() instanceof OptionValueEntry.Configure<T>) && access.get(option).equals(Objects.requireNonNullElseGet(option.getDefaultValue(), () -> access.getDefault(option)))) {
text[0] = translatable("config.rei.value.default", t);
if (font.width(text[0]) > width) {
@@ -106,6 +102,13 @@ public class ConfigOptionValueWidget {
applySelection(access, option, selection, label, setText, matrix);
} else if (access.get(option) instanceof ModifierKeyCode) {
applyKeycode(access, option, label, setText, matrix);
+ } else if (option.getEntry() instanceof OptionValueEntry.Configure<T>) {
+ label.clickable().onClick($ -> {
+ ((OptionValueEntry.Configure<T>) option.getEntry()).configure(access, option, () -> {
+ Minecraft.getInstance().setScreen((Screen) access);
+ setText.accept(option.getEntry().getOption(access.get(option)));
+ });
+ });
}
return Widgets.concatWithBounds(() -> new Rectangle(-label.getBounds().width, 0, label.getBounds().width + 8, 14),
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 59636eebd..a39658806 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
@@ -27,6 +27,7 @@ import me.shedaniel.clothconfig2.api.ModifierKeyCode;
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.configure.PanelBoundariesConfiguration;
import net.minecraft.client.Minecraft;
import java.util.function.BiConsumer;
@@ -103,9 +104,18 @@ public interface AllREIConfigOptions {
}));
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<PanelBoundary> BOUNDARIES = make("layout.boundaries", i -> {
+ return new PanelBoundary(i.appearance.horizontalEntriesBoundaries, i.appearance.verticalEntriesBoundaries,
+ i.appearance.horizontalEntriesBoundariesColumns, i.appearance.verticalEntriesBoundariesRows,
+ i.appearance.horizontalEntriesBoundariesAlignment, i.appearance.verticalEntriesBoundariesAlignment);
+ }, (i, v) -> {
+ i.appearance.horizontalEntriesBoundaries = v.horizontalPercentage();
+ i.appearance.verticalEntriesBoundaries = v.verticalPercentage();
+ i.appearance.horizontalEntriesBoundariesColumns = v.horizontalLimit();
+ i.appearance.verticalEntriesBoundariesRows = v.verticalLimit();
+ i.appearance.horizontalEntriesBoundariesAlignment = v.horizontalAlign();
+ i.appearance.verticalEntriesBoundariesAlignment = v.verticalAlign();
+ }).configure(PanelBoundariesConfiguration.INSTANCE);
CompositeOption<DisplayPanelLocation> LOCATION = make("layout.location", i -> i.advanced.accessibility.displayPanelLocation, (i, v) -> i.advanced.accessibility.displayPanelLocation = v)
.enumOptions();
CompositeOption<Boolean> HIDE_LIST_IF_IDLE = make("layout.hide_when_idle", i -> i.appearance.hideEntryPanelIfIdle, (i, v) -> i.appearance.hideEntryPanelIfIdle = 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 50a982b81..5a5d8190f 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
@@ -79,6 +79,10 @@ public class CompositeOption<T> {
return this.entry(OptionValueEntry.options(entry));
}
+ public CompositeOption<T> configure(OptionValueEntry.Configurator<T> configurator) {
+ return this.entry(OptionValueEntry.configure(configurator));
+ }
+
public CompositeOption<T> previewer(ConfigPreviewer<T> previewer) {
this.previewer = previewer;
return this;
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 da457c5c8..48697d882 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
@@ -25,6 +25,7 @@ package me.shedaniel.rei.impl.client.gui.config.options;
import me.shedaniel.clothconfig2.api.ModifierKeyCode;
import me.shedaniel.rei.api.common.util.CollectionUtils;
+import me.shedaniel.rei.impl.client.gui.config.ConfigAccess;
import net.minecraft.network.chat.Component;
import java.util.Arrays;
@@ -95,10 +96,31 @@ public interface OptionValueEntry<T> {
};
}
+ static <T> OptionValueEntry.Configure<T> configure(Configurator<T> configurator) {
+ return new Configure<>() {
+ @Override
+ public void configure(ConfigAccess access, CompositeOption<T> option, Runnable onClose) {
+ configurator.configure(access, option, onClose);
+ }
+
+ @Override
+ public Component getOption(T value) {
+ return translatable("config.rei.texts.configure");
+ }
+ };
+ }
+
static OptionValueEntry<ModifierKeyCode> keybind() {
return ModifierKeyCode::getLocalizedName;
}
+ interface Configurator<T> {
+ void configure(ConfigAccess access, CompositeOption<T> option, Runnable onClose);
+ }
+
+ interface Configure<T> extends OptionValueEntry<T>, Configurator<T> {
+ }
+
interface Selection<T> extends OptionValueEntry<T> {
List<T> getOptions();
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/configure/PanelBoundariesConfiguration.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/configure/PanelBoundariesConfiguration.java
new file mode 100644
index 000000000..10c2da12e
--- /dev/null
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/config/options/configure/PanelBoundariesConfiguration.java
@@ -0,0 +1,315 @@
+/*
+ * 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.options.configure;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import me.shedaniel.clothconfig2.api.animator.NumberAnimator;
+import me.shedaniel.clothconfig2.api.animator.ValueAnimator;
+import me.shedaniel.math.FloatingRectangle;
+import me.shedaniel.math.Rectangle;
+import me.shedaniel.rei.api.client.gui.config.DisplayPanelLocation;
+import me.shedaniel.rei.api.client.gui.config.PanelBoundary;
+import me.shedaniel.rei.api.client.gui.widgets.Widgets;
+import me.shedaniel.rei.impl.client.gui.config.ConfigAccess;
+import me.shedaniel.rei.impl.client.gui.config.options.AllREIConfigOptions;
+import me.shedaniel.rei.impl.client.gui.config.options.CompositeOption;
+import me.shedaniel.rei.impl.client.gui.config.options.OptionValueEntry;
+import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.AbstractSliderButton;
+import net.minecraft.client.gui.components.Checkbox;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.network.chat.Component;
+import net.minecraft.util.Mth;
+
+import static me.shedaniel.rei.impl.client.gui.config.options.ConfigUtils.*;
+
+public enum PanelBoundariesConfiguration implements OptionValueEntry.Configurator<PanelBoundary> {
+ INSTANCE;
+
+ @Override
+ public void configure(ConfigAccess access, CompositeOption<PanelBoundary> option, Runnable onClose) {
+ Minecraft.getInstance().setScreen(new BoundariesScreen(access, option, onClose));
+ }
+
+ private static class BoundariesScreen extends Screen {
+ private final ConfigAccess access;
+ private final CompositeOption<PanelBoundary> option;
+ private final Runnable onClose;
+ private Checkbox horizontalLimit, verticalLimit;
+ private AbstractSliderButton horizontalSlider, verticalSlider;
+ private AbstractSliderButton horizontalAlignmentSlider, verticalAlignmentSlider;
+ private boolean horizontalUsePercentage, verticalUsePercentage;
+ private ValueAnimator<FloatingRectangle> boundsAnimator = ValueAnimator.ofFloatingRectangle();
+ private NumberAnimator<Float> innerAlphaAnimator = ValueAnimator.ofFloat(1.0F);
+
+ public BoundariesScreen(ConfigAccess access, CompositeOption<PanelBoundary> option, Runnable onClose) {
+ super(literal(""));
+ this.access = access;
+ this.option = option;
+ this.onClose = onClose;
+
+ this.horizontalUsePercentage = access.get(option).horizontalPercentage() != 1.0;
+ this.verticalUsePercentage = access.get(option).verticalPercentage() != 1.0;
+ }
+
+ @Override
+ public void init() {
+ super.init();
+ PanelBoundary boundary = access.get(option);
+ addRenderableWidget(horizontalLimit = new Checkbox(0, 0, 20, 20, literal("config.rei.options.layout.boundaries.desc.limit_by_percentage"), this.horizontalUsePercentage, false) {
+ @Override
+ public void onPress() {
+ horizontalUsePercentage = !horizontalUsePercentage;
+ PanelBoundary boundary = access.get(option);
+ access.set(option, new PanelBoundary(1.0, boundary.verticalPercentage(), 50, boundary.verticalLimit(), 1.0, boundary.verticalAlign()));
+ if (!isReducedMotion()) innerAlphaAnimator.setTo(-1.0F, 200);
+ init(minecraft, BoundariesScreen.this.width, BoundariesScreen.this.height);
+ }
+ });
+ double v = horizontalUsePercentage ? boundary.horizontalPercentage() : boundary.horizontalLimit() / 50.0;
+ addRenderableWidget(horizontalSlider = new AbstractSliderButton(0, 0, 20, 20, getSliderMessage("config.rei.options.layout.boundaries.desc.limit", horizontalUsePercentage, v, 50), v) {
+ @Override
+ protected void updateMessage() {
+ setMessage(getSliderMessage("config.rei.options.layout.boundaries.desc.limit", horizontalUsePercentage, value, 50));
+ }
+
+ @Override
+ protected void applyValue() {
+ PanelBoundary boundary = access.get(option);
+ if (horizontalUsePercentage) {
+ access.set(option, new PanelBoundary(value, boundary.verticalPercentage(), 50, boundary.verticalLimit(), boundary.horizontalAlign(), boundary.verticalAlign()));
+ } else {
+ access.set(option, new PanelBoundary(1.0, boundary.verticalPercentage(), valueToLimit(value, 50), boundary.verticalLimit(), boundary.horizontalAlign(), boundary.verticalAlign()));
+ }
+ if (!isReducedMotion()) innerAlphaAnimator.setTo(-1.0F, 200);
+ }
+ });
+ addRenderableWidget(horizontalAlignmentSlider = new AbstractSliderButton(0, 0, 20, 20, getHAlignmentSliderMessage(boundary.horizontalAlign()), boundary.horizontalAlign()) {
+ @Override
+ protected void updateMessage() {
+ setMessage(getHAlignmentSliderMessage(value));
+ }
+
+ @Override
+ protected void applyValue() {
+ PanelBoundary boundary = access.get(option);
+ access.set(option, new PanelBoundary(boundary.horizontalPercentage(), boundary.verticalPercentage(), boundary.horizontalLimit(), boundary.verticalLimit(), snapPercentage(value), boundary.verticalAlign()));
+ if (!isReducedMotion()) innerAlphaAnimator.setTo(-1.0F, 200);
+ }
+ });
+ addRenderableWidget(verticalLimit = new Checkbox(0, 0, 20, 20, literal("config.rei.options.layout.boundaries.desc.limit_by_percentage"), this.verticalUsePercentage, false) {
+ @Override
+ public void onPress() {
+ verticalUsePercentage = !verticalUsePercentage;
+ PanelBoundary boundary = access.get(option);
+ access.set(option, new PanelBoundary(boundary.horizontalPercentage(), 1.0, boundary.horizontalLimit(), 1000, boundary.horizontalAlign(), 0.5));
+ if (!isReducedMotion()) innerAlphaAnimator.setTo(-1.0F, 200);
+ init(minecraft, BoundariesScreen.this.width, BoundariesScreen.this.height);
+ }
+ });
+ v = verticalUsePercentage ? boundary.verticalPercentage() : boundary.verticalLimit() / 1000.0;
+ addRenderableWidget(verticalSlider = new AbstractSliderButton(0, 0, 20, 20, getSliderMessage("config.rei.options.layout.boundaries.desc.limit", verticalUsePercentage, v, 1000), v) {
+ @Override
+ protected void updateMessage() {
+ setMessage(getSliderMessage("config.rei.options.layout.boundaries.desc.limit", verticalUsePercentage, value, 1000));
+ }
+
+ @Override
+ protected void applyValue() {
+ PanelBoundary boundary = access.get(option);
+ if (verticalUsePercentage) {
+ access.set(option, new PanelBoundary(boundary.horizontalPercentage(), value, boundary.horizontalLimit(), 1000, boundary.horizontalAlign(), boundary.verticalAlign()));
+ } else {
+ access.set(option, new PanelBoundary(boundary.horizontalPercentage(), 1.0, boundary.horizontalLimit(), valueToLimit(value, 1000), boundary.horizontalAlign(), boundary.verticalAlign()));
+ }
+ if (!isReducedMotion()) innerAlphaAnimator.setTo(-1.0F, 200);
+ }
+ });
+ addRenderableWidget(verticalAlignmentSlider = new AbstractSliderButton(0, 0, 20, 20, getVAlignmentSliderMessage(boundary.verticalAlign()), boundary.verticalAlign()) {
+ @Override
+ protected void updateMessage() {
+ setMessage(getVAlignmentSliderMessage(value));
+ }
+
+ @Override
+ protected void applyValue() {
+ PanelBoundary boundary = access.get(option);
+ access.set(option, new PanelBoundary(boundary.horizontalPercentage(), boundary.verticalPercentage(), boundary.horizontalLimit(), boundary.verticalLimit(), boundary.horizontalAlign(), snapPercentage(value)));
+ if (!isReducedMotion()) innerAlphaAnimator.setTo(-1.0F, 200);
+ }
+ });
+ }
+
+ private Component getSliderMessage(String translationKey, boolean usePercentage, double percentage, int max) {
+ if (usePercentage) {
+ return translatable(translationKey, String.format("%.1f%%", percentage * 100));
+ } else if (valueToLimit(percentage, max) == max) {
+ return translatable(translationKey, translatable("config.rei.value.default", valueToLimit(percentage, max) + ""));
+ } else {
+ return translatable(translationKey, valueToLimit(percentage, max) + "");
+ }
+ }
+
+ private int valueToLimit(double v, int max) {
+ return Mth.clamp((int) Math.round(v * max), 1, max);
+ }
+
+ private Component getHAlignmentSliderMessage(double percentage) {
+ String translationKey = "config.rei.options.layout.boundaries.desc.alignment";
+ DisplayPanelLocation location = access.get(AllREIConfigOptions.LOCATION);
+ if (percentage <= 0.02) {
+ Component component = translatable(translationKey, translatable("config.rei.options.layout.boundaries.desc.horizontal_alignment.left"));
+ if (location == DisplayPanelLocation.LEFT) return translatable("config.rei.value.default", component);
+ return component;
+ } else if (percentage >= 0.98) {
+ Component component = translatable(translationKey, translatable("config.rei.options.layout.boundaries.desc.horizontal_alignment.right"));
+ if (location == DisplayPanelLocation.RIGHT) return translatable("config.rei.value.default", component);
+ return component;
+ } else if (percentage >= 0.45 && percentage <= 0.55) {
+ return translatable(translationKey, translatable("config.rei.options.layout.boundaries.desc.horizontal_alignment.center"));
+ } else {
+ return translatable(translationKey, String.format("%.1f%%", percentage * 100));
+ }
+ }
+
+ private Component getVAlignmentSliderMessage(double percentage) {
+ String translationKey = "config.rei.options.layout.boundaries.desc.alignment";
+ if (percentage <= 0.02) {
+ return translatable(translationKey, translatable("config.rei.options.layout.boundaries.desc.vertical_alignment.top"));
+ } else if (percentage >= 0.98) {
+ return translatable(translationKey, translatable("config.rei.options.layout.boundaries.desc.vertical_alignment.bottom"));
+ } else if (percentage >= 0.45 && percentage <= 0.55) {
+ return translatable(translationKey, translatable("config.rei.value.default", translatable("config.rei.options.layout.boundaries.desc.vertical_alignment.center")));
+ } else {
+ return translatable(translationKey, String.format("%.1f%%", percentage * 100));
+ }
+ }
+
+ private double snapPercentage(double percentage) {
+ if (percentage <= 0.02) {
+ return 0;
+ } else if (percentage >= 0.98) {
+ return 1;
+ } else if (percentage >= 0.45 && percentage <= 0.55) {
+ return 0.5;
+ } else {
+ return percentage;
+ }
+ }
+
+ @Override
+ public void render(PoseStack poses, int mouseX, int mouseY, float delta) {
+ this.boundsAnimator.update(delta);
+ this.innerAlphaAnimator.setTarget(this.innerAlphaAnimator.target() + (1.0F - this.innerAlphaAnimator.target()) * 0.06F);
+ this.innerAlphaAnimator.update(delta);
+ this.renderBackground(poses);
+ Rectangle panelBounds = new Rectangle(this.width * 3 / 10, this.height * 4 / 40, this.width * 4 / 10, this.height * 32 / 40);
+ Widgets.createCategoryBase(panelBounds).render(poses, mouseX, mouseY, delta);
+ int y = panelBounds.y + 6;
+ this.font.draw(poses, translatable("config.rei.options.layout.boundaries.desc.configure").withStyle(ChatFormatting.UNDERLINE), panelBounds.x + 6, y, 0xff404040);
+ y += 14;
+ this.font.draw(poses, translatable("config.rei.options.layout.boundaries.desc.horizontal"), panelBounds.x + 6, y, 0xff404040);
+ this.horizontalLimit.x = panelBounds.x + 6;
+ this.horizontalLimit.y = y + 10;
+ this.font.draw(poses, translatable("config.rei.options.layout.boundaries.desc.limit_by_percentage"), horizontalLimit.x + 24, horizontalLimit.y + 6, 0xff404040);
+ y += 32;
+ this.horizontalSlider.x = panelBounds.x + 6;
+ this.horizontalSlider.y = y;
+ this.horizontalSlider.setWidth(panelBounds.width - 12);
+ y += 22;
+ this.horizontalAlignmentSlider.x = panelBounds.x + 6;
+ this.horizontalAlignmentSlider.y = y;
+ this.horizontalAlignmentSlider.setWidth(panelBounds.width - 12);
+ y += 28;
+
+ this.font.draw(poses, translatable("config.rei.options.layout.boundaries.desc.vertical"), panelBounds.x + 6, y, 0xff404040);
+ this.verticalLimit.x = panelBounds.x + 6;
+ this.verticalLimit.y = y + 10;
+ this.font.draw(poses, translatable("config.rei.options.layout.boundaries.desc.limit_by_percentage"), verticalLimit.x + 24, verticalLimit.y + 6, 0xff404040);
+ y += 32;
+ this.verticalSlider.x = panelBounds.x + 6;
+ this.verticalSlider.y = y;
+ this.verticalSlider.setWidth(panelBounds.width - 12);
+ y += 22;
+ this.verticalAlignmentSlider.x = panelBounds.x + 6;
+ this.verticalAlignmentSlider.y = y;
+ this.verticalAlignmentSlider.setWidth(panelBounds.width - 12);
+
+ super.render(poses, mouseX, mouseY, delta);
+ renderPreview(poses, panelBounds);
+ }
+
+ private void renderPreview(PoseStack poses, Rectangle panelBounds) {
+ int entrySize = Mth.ceil(18 * access.get(AllREIConfigOptions.ZOOM));
+ Rectangle overlayBounds;
+ DisplayPanelLocation location = access.get(AllREIConfigOptions.LOCATION);
+ PanelBoundary boundary = access.get(option);
+ if (location == DisplayPanelLocation.LEFT) {
+ overlayBounds = new Rectangle(2, 0, panelBounds.x - 2, height);
+ } else {
+ overlayBounds = new Rectangle(panelBounds.getMaxX() + 2, 0, width - panelBounds.getMaxX() - 4, height);
+ }
+
+ double hAlign = location == DisplayPanelLocation.LEFT ? 1 - boundary.horizontalAlign() : boundary.horizontalAlign();
+ int widthReduction = (int) Math.round(overlayBounds.width * (1 - boundary.horizontalPercentage()));
+ overlayBounds.x += (int) Math.round(widthReduction * hAlign);
+ overlayBounds.width -= widthReduction;
+ int maxWidth = (int) Math.ceil(entrySize * boundary.horizontalLimit() + entrySize * 0.75);
+ if (overlayBounds.width > maxWidth) {
+ overlayBounds.x += (int) Math.round((overlayBounds.width - maxWidth) * hAlign);
+ overlayBounds.width = maxWidth;
+ }
+ int heightReduction = (int) Math.round(overlayBounds.height * (1 - boundary.verticalPercentage()));
+ overlayBounds.height -= heightReduction;
+ overlayBounds.y += (int) Math.round(heightReduction * boundary.verticalAlign());
+ int maxHeight = entrySize * boundary.verticalLimit();
+ if (overlayBounds.height > maxHeight) {
+ overlayBounds.y += (int) Math.round((overlayBounds.height - maxHeight) * boundary.verticalAlign());
+ overlayBounds.height = maxHeight;
+ }
+ this.boundsAnimator.setTo(overlayBounds.getFloatingBounds(), isReducedMotion() ? 0 : 200);
+ overlayBounds = this.boundsAnimator.value().getBounds();
+
+ this.fillGradient(poses, overlayBounds.x, overlayBounds.y, overlayBounds.getMaxX(), overlayBounds.getMaxY(), 0x80ff0000, 0x80ff0000);
+
+ int width = Math.max(Mth.floor((overlayBounds.width - 2) / (float) entrySize), 1);
+ int height = Math.max(Mth.floor((overlayBounds.height - 2) / (float) entrySize), 1);
+ Rectangle innerBounds = new Rectangle((int) (overlayBounds.getCenterX() - width * (entrySize / 2f)), (int) (overlayBounds.getCenterY() - height * (entrySize / 2f)), width * entrySize, height * entrySize);
+ int color = 0x00ff00 | ((int) (Math.ceil(Mth.clamp(innerAlphaAnimator.floatValue(), 0, 1) * 0x80))) << 24;
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
+ int slotX = innerBounds.x + i * entrySize + 1;
+ int slotY = innerBounds.y + j * entrySize + 1;
+ this.fillGradient(poses, slotX, slotY, slotX + entrySize - 2, slotY + entrySize - 2, color, color);
+ }
+ }
+ }
+
+ @Override
+ public void onClose() {
+ this.onClose.run();
+ }
+ }
+}
diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java
index a3c60fc20..c4cd6d064 100644
--- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java
+++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/entrylist/EntryListWidget.java
@@ -135,11 +135,11 @@ public abstract class EntryListWidget extends WidgetWithBounds implements Overla
private static Rectangle updateInnerBounds(Rectangle bounds) {
bounds = bounds.clone();
int heightReduction = (int) Math.round(bounds.height * (1 - ConfigObject.getInstance().getVerticalEntriesBoundariesPercentage()));
- bounds.y += heightReduction / 2;
+ bounds.y += (int) Math.round(heightReduction * ConfigObject.getInstance().getVerticalEntriesBoundariesAlignments());