diff --git a/common/src/api/java/net/caffeinemc/mods/sodium/api/config/option/Range.java b/common/src/api/java/net/caffeinemc/mods/sodium/api/config/option/Range.java index 8237ac0cc9..5bac75b144 100644 --- a/common/src/api/java/net/caffeinemc/mods/sodium/api/config/option/Range.java +++ b/common/src/api/java/net/caffeinemc/mods/sodium/api/config/option/Range.java @@ -13,4 +13,8 @@ public record Range(int min, int max, int step) { public boolean isValueValid(int value) { return value >= this.min && value <= this.max && (value - this.min) % this.step == 0; } + + public int getSpread() { + return this.max - this.min; + } } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Config.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Config.java index 57010772a6..bbc3c82c23 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Config.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Config.java @@ -7,6 +7,7 @@ import net.caffeinemc.mods.sodium.api.config.ConfigState; import net.caffeinemc.mods.sodium.api.config.StorageEventHandler; import net.caffeinemc.mods.sodium.api.config.option.OptionFlag; +import net.caffeinemc.mods.sodium.client.config.value.DynamicValue; import net.caffeinemc.mods.sodium.client.console.Console; import net.caffeinemc.mods.sodium.client.console.message.MessageLevel; import net.minecraft.client.Minecraft; @@ -29,6 +30,9 @@ public Config(ImmutableList modOptions) { this.validateDependencies(); // load options initially from their bindings + for (var option : this.options.values()) { + option.loadValueInitial(); + } resetAllOptions(); } @@ -93,6 +97,18 @@ private void validateDependencies() { throw new IllegalArgumentException("Option " + option.id + " depends on non-existent option " + dependency); } } + + // link dependents + option.visitDependentValues(dependent -> { + if (dependent instanceof DynamicValue dynamicValue) { + for (var dependency : dependent.getDependencies()) { + var dependencyOption = this.options.get(dependency); + if (dependencyOption instanceof StatefulOption statefulOption) { + statefulOption.registerDependent(dynamicValue); + } + } + } + }); } // make sure there are no cycles @@ -103,6 +119,11 @@ private void validateDependencies() { } } + void invalidateDependents(Collection> dependents) { + for (var dependent : dependents) { + dependent.invalidateCache(); + } + } private void checkDependencyCycles(Option option, ObjectOpenHashSet stack, ObjectOpenHashSet finished) { if (!stack.add(option.id)) { diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/EnumOption.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/EnumOption.java index e20357c3f9..5b3346bf6d 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/EnumOption.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/EnumOption.java @@ -13,10 +13,11 @@ import java.util.Collection; import java.util.EnumSet; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Function; public class EnumOption> extends StatefulOption { - final Class enumClass; + public final Class enumClass; private final DependentValue> allowedValues; private final Function elementNameProvider; @@ -28,6 +29,12 @@ public class EnumOption> extends StatefulOption { this.elementNameProvider = elementNameProvider; } + @Override + void visitDependentValues(Consumer> visitor) { + super.visitDependentValues(visitor); + visitor.accept(this.allowedValues); + } + @Override public boolean isValueValid(E value) { return this.allowedValues.get(this.state).contains(value); @@ -35,7 +42,14 @@ public boolean isValueValid(E value) { @Override Control createControl() { - // TODO: doesn't update allowed values when dependencies change - return new CyclingControl<>(this, this.enumClass, this.elementNameProvider, this.allowedValues.get(this.state).toArray(this.enumClass.getEnumConstants())); + return new CyclingControl<>(this, this.enumClass); + } + + public boolean isValueAllowed(E value) { + return this.allowedValues.get(this.state).contains(value); + } + + public Component getElementName(E element) { + return this.elementNameProvider.apply(element); } } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/IntegerOption.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/IntegerOption.java index 41b0e14bd2..cb02813608 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/IntegerOption.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/IntegerOption.java @@ -10,6 +10,7 @@ import java.util.Collection; import java.util.EnumSet; +import java.util.function.Consumer; import java.util.function.Function; public class IntegerOption extends StatefulOption { @@ -22,6 +23,12 @@ public class IntegerOption extends StatefulOption { this.valueFormatter = valueFormatter; } + @Override + void visitDependentValues(Consumer> visitor) { + super.visitDependentValues(visitor); + visitor.accept(this.range); + } + @Override public boolean isValueValid(Integer value) { return this.range.get(this.state).isValueValid(value); @@ -30,11 +37,15 @@ public boolean isValueValid(Integer value) { @Override Control createControl() { var range = this.range.get(this.state); - return new SliderControl(this, range.min(), range.max(), range.step(), this.valueFormatter); + return new SliderControl(this, range.min(), range.max(), range.step()); } public Range getRange() { return this.range.get(this.state); } + + public Component formatValue(int value) { + return this.valueFormatter.format(value); + } } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Option.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Option.java index 4c6996cc8b..0479f431fe 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Option.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/Option.java @@ -9,6 +9,7 @@ import java.util.Collection; import java.util.EnumSet; +import java.util.function.Consumer; public abstract class Option { final ResourceLocation id; @@ -45,6 +46,14 @@ void setParentConfig(Config state) { this.state = state; } + void visitDependentValues(Consumer> visitor) { + visitor.accept(this.enabled); + } + + void loadValueInitial() { + // no-op + } + void resetFromBinding() { // no-op } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/StatefulOption.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/StatefulOption.java index 43f8b126f0..53107ce845 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/StatefulOption.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/structure/StatefulOption.java @@ -1,15 +1,18 @@ package net.caffeinemc.mods.sodium.client.config.structure; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.caffeinemc.mods.sodium.api.config.StorageEventHandler; import net.caffeinemc.mods.sodium.api.config.option.OptionBinding; import net.caffeinemc.mods.sodium.api.config.option.OptionFlag; import net.caffeinemc.mods.sodium.api.config.option.OptionImpact; import net.caffeinemc.mods.sodium.client.config.value.DependentValue; +import net.caffeinemc.mods.sodium.client.config.value.DynamicValue; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import java.util.Collection; import java.util.EnumSet; +import java.util.function.Consumer; import java.util.function.Function; public abstract class StatefulOption extends Option { @@ -20,6 +23,8 @@ public abstract class StatefulOption extends Option { final DependentValue defaultValue; final OptionBinding binding; + private final Collection> dependents = new ObjectOpenHashSet<>(0); + private V value; private V modifiedValue; @@ -33,12 +38,32 @@ public abstract class StatefulOption extends Option { this.binding = binding; } + @Override + void visitDependentValues(Consumer> visitor) { + super.visitDependentValues(visitor); + visitor.accept(this.defaultValue); + } + + void registerDependent(DynamicValue dependent) { + this.dependents.add(dependent); + } + public void modifyValue(V value) { - this.modifiedValue = value; + if (this.modifiedValue != value) { + this.modifiedValue = value; + this.state.invalidateDependents(this.dependents); + } + } + + @Override + void loadValueInitial() { + this.value = this.binding.load(); + this.modifiedValue = this.value; } @Override void resetFromBinding() { + var previousValue = this.modifiedValue; this.value = this.binding.load(); if (!isValueValid(this.value)) { @@ -51,11 +76,18 @@ void resetFromBinding() { } this.modifiedValue = this.value; + if (this.value != previousValue) { + this.state.invalidateDependents(this.dependents); + } } public V getValidatedValue() { if (!isValueValid(this.modifiedValue)) { + var previousValue = this.modifiedValue; this.modifiedValue = this.defaultValue.get(this.state); + if (this.modifiedValue != previousValue) { + this.state.invalidateDependents(this.dependents); + } } return this.modifiedValue; diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/value/DynamicValue.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/value/DynamicValue.java index fa72d1b657..bf15c43c49 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/config/value/DynamicValue.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/config/value/DynamicValue.java @@ -12,6 +12,7 @@ public class DynamicValue implements DependentValue, ConfigState { private final Set dependencies; private final Function provider; private Config state; + private V valueCache; public DynamicValue(Function provider, ResourceLocation[] dependencies) { this.provider = provider; @@ -20,10 +21,14 @@ public DynamicValue(Function provider, ResourceLocation[] depend @Override public V get(Config state) { + if (this.valueCache != null) { + return this.valueCache; + } + this.state = state; - var result = this.provider.apply(this); + this.valueCache = this.provider.apply(this); this.state = null; - return result; + return this.valueCache; } @Override @@ -31,6 +36,10 @@ public Collection getDependencies() { return this.dependencies; } + public void invalidateCache() { + this.valueCache = null; + } + private void validateRead(ResourceLocation id) { if (!this.dependencies.contains(id)) { throw new IllegalStateException("Attempted to read option value that is not a declared dependency"); diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumConfigBuilder.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumConfigBuilder.java index b3c85e028e..4031aea4fd 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumConfigBuilder.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/SodiumConfigBuilder.java @@ -3,11 +3,13 @@ import com.mojang.blaze3d.platform.Monitor; import com.mojang.blaze3d.platform.VideoMode; import com.mojang.blaze3d.platform.Window; -import net.caffeinemc.mods.sodium.api.config.*; -import net.caffeinemc.mods.sodium.api.config.structure.*; +import net.caffeinemc.mods.sodium.api.config.ConfigEntryPoint; +import net.caffeinemc.mods.sodium.api.config.StorageEventHandler; import net.caffeinemc.mods.sodium.api.config.option.OptionBinding; import net.caffeinemc.mods.sodium.api.config.option.OptionFlag; import net.caffeinemc.mods.sodium.api.config.option.OptionImpact; +import net.caffeinemc.mods.sodium.api.config.option.Range; +import net.caffeinemc.mods.sodium.api.config.structure.*; import net.caffeinemc.mods.sodium.client.SodiumClientMod; import net.caffeinemc.mods.sodium.client.compatibility.environment.OsUtils; import net.caffeinemc.mods.sodium.client.compatibility.workarounds.Workarounds; @@ -26,6 +28,8 @@ import org.lwjgl.opengl.GLCapabilities; import java.io.IOException; +import java.util.Arrays; +import java.util.EnumSet; import java.util.Optional; // TODO: get initialValue from the vanilla options (it's private) @@ -158,13 +162,45 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { builder.createIntegerOption(ResourceLocation.parse("foo:baz")) .setStorageHandler(() -> { }) - .setName(Component.literal("Hello")) - .setTooltip(Component.literal("Bla")) + .setName(Component.literal("Baz")) + .setTooltip(Component.literal("Baz")) .setValueFormatter(ControlValueFormatterImpls.number()) .setDefaultValue(5) .setRange(0, 10, 1) .setBinding(new LocalBinding<>(5)) - .setEnabledProvider((state) -> state.readBooleanOption(ResourceLocation.parse("foo:bar")), ResourceLocation.parse("foo:bar")) + .setEnabledProvider(state -> state.readBooleanOption(ResourceLocation.parse("foo:bar")), ResourceLocation.parse("foo:bar")) + ) + .addOption( + builder.createIntegerOption(ResourceLocation.parse("foo:bla")) + .setStorageHandler(() -> { + }) + .setName(Component.literal("Bla")) + .setTooltip(Component.literal("hello")) + .setValueFormatter(ControlValueFormatterImpls.number()) + .setDefaultValue(5) + .setRangeProvider( + state -> new Range(state.readBooleanOption(ResourceLocation.parse("foo:bar")) ? 0 : 1, 5, 1), + ResourceLocation.parse("foo:bar")) + .setBinding(new LocalBinding<>(5)) + ) + .addOption( + builder.createEnumOption(ResourceLocation.parse("foo:zot"), OptionImpact.class) + .setStorageHandler(() -> { + }) + .setName(Component.literal("Zot")) + .setTooltip(Component.literal("hello")) + .setDefaultValue(OptionImpact.LOW) + .setAllowedValuesProvider( + state -> { + var set = EnumSet.noneOf(OptionImpact.class); + var value = state.readIntOption(ResourceLocation.parse("foo:bla")); + var list = Arrays.asList(OptionImpact.values()); + set.addAll(list.subList(0, Math.min(value + 1, list.size()))); + return set; + }, + ResourceLocation.parse("foo:bla")) + .setElementNameProvider(value -> Component.literal(value.name())) + .setBinding(new LocalBinding<>(OptionImpact.LOW)) ) .addOption( builder.createExternalButtonOption(ResourceLocation.parse("foo:button")) diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/VideoSettingsScreen.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/VideoSettingsScreen.java index 90a4639085..3c78acc96a 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/VideoSettingsScreen.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/VideoSettingsScreen.java @@ -47,8 +47,6 @@ // TODO: show option group's names somewhere // TODO: add button or some other way for user to reset a specific option, all options on a page, and all options of a mod to their default values (not just "reset" changes, but reset to default value) // TODO: make RD option respect Vanilla's >16 RD only allowed if memory >1GB constraint -// TODO: use update tag in stateful options to prevent multiple calls to dependencies -// TODO: make sure value constraints are actually dynamic (the controls receive them statically) public class VideoSettingsScreen extends Screen implements ScreenPromptable { private final List controls = new ArrayList<>(); diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java index fc1f26a64a..62946e3134 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/CyclingControl.java @@ -1,7 +1,7 @@ package net.caffeinemc.mods.sodium.client.gui.options.control; +import net.caffeinemc.mods.sodium.client.config.structure.EnumOption; import net.caffeinemc.mods.sodium.client.config.structure.Option; -import net.caffeinemc.mods.sodium.client.config.structure.StatefulOption; import net.caffeinemc.mods.sodium.client.gui.ColorTheme; import net.caffeinemc.mods.sodium.client.gui.Colors; import net.caffeinemc.mods.sodium.client.gui.widgets.OptionListWidget; @@ -12,21 +12,15 @@ import net.minecraft.network.chat.Component; import org.apache.commons.lang3.Validate; -import java.util.function.Function; - public class CyclingControl> implements Control { - private final StatefulOption option; - private final T[] allowedValues; - private final Function elementNameProvider; + private final EnumOption option; - public CyclingControl(StatefulOption option, Class enumType, Function elementNameProvider, T[] allowedValues) { + public CyclingControl(EnumOption option, Class enumType) { T[] universe = enumType.getEnumConstants(); Validate.notEmpty(universe, "The enum universe must contain at least one item"); this.option = option; - this.allowedValues = allowedValues; - this.elementNameProvider = elementNameProvider; } @Override @@ -36,7 +30,7 @@ public Option getOption() { @Override public ControlElement createElement(Screen screen, OptionListWidget list, Dim2i dim, ColorTheme theme) { - return new CyclingControlElement<>(list, this.option, dim, this.allowedValues, this.elementNameProvider); + return new CyclingControlElement<>(list, this.option, dim); } @Override @@ -44,25 +38,20 @@ public int getMaxWidth() { return 70; } - private static class CyclingControlElement> extends StatefulControlElement { - private final T[] allowedValues; - private final Function elementNameProvider; - private int currentIndex; + private static class CyclingControlElement> extends ControlElement { + private final EnumOption option; + private final T[] baseValues; - public CyclingControlElement(OptionListWidget list, StatefulOption option, Dim2i dim, T[] allowedValues, Function elementNameProvider) { - super(list, dim, option); + public CyclingControlElement(OptionListWidget list, EnumOption option, Dim2i dim) { + super(list, dim); - this.allowedValues = allowedValues; - this.elementNameProvider = elementNameProvider; - this.currentIndex = 0; + this.option = option; + this.baseValues = option.enumClass.getEnumConstants(); + } - var optionValue = option.getValidatedValue(); - for (int i = 0; i < allowedValues.length; i++) { - if (allowedValues[i] == optionValue) { - this.currentIndex = i; - break; - } - } + @Override + public Option getOption() { + return this.option; } @Override @@ -70,7 +59,7 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { super.render(graphics, mouseX, mouseY, delta); var value = this.option.getValidatedValue(); - Component name = this.elementNameProvider.apply(value); + Component name = this.option.getElementName(value); int strWidth = this.getStringWidth(name); this.drawString(graphics, name, this.getLimitX() - strWidth - 6, this.getCenterY() - 4, Colors.FOREGROUND); @@ -101,12 +90,26 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) { } public void cycleControl(boolean reverse) { - if (reverse) { - this.currentIndex = (this.currentIndex + this.allowedValues.length - 1) % this.allowedValues.length; - } else { - this.currentIndex = (this.currentIndex + 1) % this.allowedValues.length; + var currentValue = this.option.getValidatedValue(); + int startIndex = 0; + for (; startIndex < this.baseValues.length; startIndex++) { + if (this.baseValues[startIndex] == currentValue) { + break; + } } - this.option.modifyValue(this.allowedValues[this.currentIndex]); + + // step through values in the specified direction until a valid one is found + var currentIndex = startIndex; + do { + if (reverse) { + currentIndex = (currentIndex + this.baseValues.length - 1) % this.baseValues.length; + } else { + currentIndex = (currentIndex + 1) % this.baseValues.length; + } + + currentValue = this.baseValues[currentIndex]; + } while (!this.option.isValueAllowed(currentValue)); + this.option.modifyValue(currentValue); } } } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java index 7b82fa7538..daf3b5e56d 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/SliderControl.java @@ -1,7 +1,8 @@ package net.caffeinemc.mods.sodium.client.gui.options.control; import com.mojang.blaze3d.platform.InputConstants; -import net.caffeinemc.mods.sodium.api.config.option.ControlValueFormatter; +import net.caffeinemc.mods.sodium.client.config.structure.IntegerOption; +import net.caffeinemc.mods.sodium.client.config.structure.Option; import net.caffeinemc.mods.sodium.client.config.structure.StatefulOption; import net.caffeinemc.mods.sodium.client.gui.ColorTheme; import net.caffeinemc.mods.sodium.client.gui.Colors; @@ -13,28 +14,19 @@ import org.apache.commons.lang3.Validate; public class SliderControl implements Control { - private final StatefulOption option; + private final IntegerOption option; - private final int min, max, interval; - - private final ControlValueFormatter mode; - - public SliderControl(StatefulOption option, int min, int max, int interval, ControlValueFormatter mode) { + public SliderControl(IntegerOption option, int min, int max, int interval) { Validate.isTrue(max > min, "The maximum value must be greater than the minimum value"); Validate.isTrue(interval > 0, "The slider interval must be greater than zero"); Validate.isTrue(((max - min) % interval) == 0, "The maximum value must be divisible by the interval"); - Validate.notNull(mode, "The slider mode must not be null"); this.option = option; - this.min = min; - this.max = max; - this.interval = interval; - this.mode = mode; } @Override public ControlElement createElement(Screen screen, OptionListWidget list, Dim2i dim, ColorTheme theme) { - return new Button(list, this.option, dim, this.min, this.max, this.interval, this.mode, theme); + return new SliderControlElement(list, this.option, dim, theme); } @Override @@ -47,36 +39,31 @@ public int getMaxWidth() { throw new UnsupportedOperationException("Not implemented"); } - private static class Button extends StatefulControlElement { + private static class SliderControlElement extends ControlElement { private static final int THUMB_WIDTH = 2, TRACK_HEIGHT = 1; - private int contentWidth; - private final ControlValueFormatter formatter; + private final IntegerOption option; private final ColorTheme theme; - private final int min; - private final int max; - private final int range; - private final int interval; - private double thumbPosition; - private boolean sliderHeld; + private int contentWidth; - public Button(OptionListWidget list, StatefulOption option, Dim2i dim, int min, int max, int interval, ControlValueFormatter formatter, ColorTheme theme) { - super(list, dim, option); + public SliderControlElement(OptionListWidget list, IntegerOption option, Dim2i dim, ColorTheme theme) { + super(list, dim); - this.min = min; - this.max = max; - this.range = max - min; - this.interval = interval; - this.thumbPosition = this.getThumbPositionForValue(option.getValidatedValue()); - this.formatter = formatter; + this.option = option; this.theme = theme; + this.thumbPosition = this.getThumbPositionForValue(option.getValidatedValue()); this.sliderHeld = false; } + @Override + public Option getOption() { + return this.option; + } + @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { int sliderX = this.getSliderX(); @@ -87,7 +74,7 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { var value = this.option.getValidatedValue(); var isEnabled = this.option.isEnabled(); - var label = this.formatter.format(value); + var label = this.option.formatValue(value); if (!isEnabled) { label = this.formatDisabledControlValue(label); @@ -108,7 +95,8 @@ public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { if (drawSlider) { this.thumbPosition = this.getThumbPositionForValue(value); - double thumbOffset = Mth.clamp((double) (this.getIntValue() - this.min) / this.range * sliderWidth, 0, sliderWidth); + var range = this.option.getRange(); + double thumbOffset = Mth.clamp((double) (this.getIntValue() - range.min()) / range.getSpread() * sliderWidth, 0, sliderWidth); int thumbX = (int) (sliderX + thumbOffset - THUMB_WIDTH); int trackY = (int) (sliderY + (sliderHeight / 2f) - ((double) TRACK_HEIGHT / 2)); @@ -148,15 +136,13 @@ public int getContentWidth() { } public int getIntValue() { - return this.min + (this.interval * (int) Math.round(this.getSnappedThumbPosition() / this.interval)); - } - - public double getSnappedThumbPosition() { - return this.thumbPosition / (1.0D / this.range); + var range = this.option.getRange(); + return range.min() + (range.step() * (int) Math.round((this.thumbPosition / (1.0D / range.getSpread())) / range.step())); } public double getThumbPositionForValue(int value) { - return (value - this.min) * (1.0D / this.range); + var range = this.option.getRange(); + return (value - range.min()) * (1.0D / range.getSpread()); } @Override @@ -193,11 +179,12 @@ public void setValue(double d) { public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (!isFocused()) return false; + var range = this.option.getRange(); if (keyCode == InputConstants.KEY_LEFT) { - this.option.modifyValue(Mth.clamp(this.option.getValidatedValue() - this.interval, this.min, this.max)); + this.option.modifyValue(Mth.clamp(this.option.getValidatedValue() - range.step(), range.max(), range.max())); return true; } else if (keyCode == InputConstants.KEY_RIGHT) { - this.option.modifyValue(Mth.clamp(this.option.getValidatedValue() + this.interval, this.min, this.max)); + this.option.modifyValue(Mth.clamp(this.option.getValidatedValue() + range.step(), range.min(), range.max())); return true; } diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/StatefulControlElement.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/StatefulControlElement.java deleted file mode 100644 index 55f6736296..0000000000 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/StatefulControlElement.java +++ /dev/null @@ -1,19 +0,0 @@ -package net.caffeinemc.mods.sodium.client.gui.options.control; - -import net.caffeinemc.mods.sodium.client.config.structure.StatefulOption; -import net.caffeinemc.mods.sodium.client.gui.widgets.OptionListWidget; -import net.caffeinemc.mods.sodium.client.util.Dim2i; - -public class StatefulControlElement extends ControlElement { - final StatefulOption option; - - public StatefulControlElement(OptionListWidget list, Dim2i dim, StatefulOption option) { - super(list, dim); - this.option = option; - } - - @Override - public StatefulOption getOption() { - return this.option; - } -} diff --git a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java index c60d9821f5..caaf036ea2 100644 --- a/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java +++ b/common/src/main/java/net/caffeinemc/mods/sodium/client/gui/options/control/TickBoxControl.java @@ -1,5 +1,7 @@ package net.caffeinemc.mods.sodium.client.gui.options.control; +import net.caffeinemc.mods.sodium.client.config.structure.BooleanOption; +import net.caffeinemc.mods.sodium.client.config.structure.Option; import net.caffeinemc.mods.sodium.client.config.structure.StatefulOption; import net.caffeinemc.mods.sodium.client.gui.ColorTheme; import net.caffeinemc.mods.sodium.client.gui.Colors; @@ -10,9 +12,9 @@ import net.minecraft.client.gui.screens.Screen; public class TickBoxControl implements Control { - private final StatefulOption option; + private final BooleanOption option; - public TickBoxControl(StatefulOption option) { + public TickBoxControl(BooleanOption option) { this.option = option; } @@ -31,15 +33,22 @@ public StatefulOption getOption() { return this.option; } - private static class TickBoxControlElement extends StatefulControlElement { + private static class TickBoxControlElement extends ControlElement { + private final BooleanOption option; private final ColorTheme theme; - public TickBoxControlElement(OptionListWidget list, StatefulOption option, Dim2i dim, ColorTheme theme) { - super(list, dim, option); + public TickBoxControlElement(OptionListWidget list, BooleanOption option, Dim2i dim, ColorTheme theme) { + super(list, dim); + this.option = option; this.theme = theme; } + @Override + public Option getOption() { + return this.option; + } + @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { super.render(graphics, mouseX, mouseY, delta);