Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/main/java/com/cleanroommc/modularui/utils/MathUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,16 @@ public static long percentOrSelf(double value, long maxValue) {
return Math.round(value * maxValue);
}

/**
* Resolves a parsed bounded value while preserving an explicit percentage in the source expression.
*/
public static long percentOrSelf(String expression, double value, long maxValue) {
if (expression != null && expression.indexOf('%') >= 0) {
return Math.round(value * maxValue);
}
return percentOrSelf(value, maxValue);
}

public static int castToIntSaturated(long l) {
if (l >= Integer.MAX_VALUE) return Integer.MAX_VALUE;
if (l <= Integer.MIN_VALUE) return Integer.MIN_VALUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,16 @@ public TextFieldWidget numberParser(INumberParser parser) {
}

public TextFieldWidget numbersDouble(DAM.UnaryDoubleOperator validator) {
return numbersDouble((input, num) -> validator.apply(num));
}

@FunctionalInterface
public interface NumberValidator {

double apply(String input, double value);
}

public TextFieldWidget numbersDouble(NumberValidator validator) {
this.numbers = true;
return setValidator(val -> {
double num;
Expand All @@ -253,7 +263,7 @@ public TextFieldWidget numbersDouble(DAM.UnaryDoubleOperator validator) {
} else {
num = parse(val);
}
return format.format(validator.apply(num));
return format.format(validator.apply(val, num));
});
}

Expand Down Expand Up @@ -289,17 +299,18 @@ public TextFieldWidget numbersLong(MathUtils.UnaryLongOperator validator) {
*
* @param validator allow further validation of the number
* @param min optional lower limit
* @param max optional upper limit, if this is specified, then values that evaluate to a noninteger are multiplied by the max
* @param max optional upper limit, if this is specified, then explicit percentages and fractional values are
* multiplied by the max
*/
public TextFieldWidget numbersLong(MathUtils.UnaryLongOperator validator, @Nullable LongSupplier min, @Nullable LongSupplier max) {
formatAsInteger(true);
defaultWholeNumberScrollValues();
numberParser(MathUtils.PARSER_WHOLE_NUMBER);
return numbersDouble(d -> {
return numbersDouble((val, d) -> {
long l;
if (max != null) {
long maxValue = max.getAsLong();
l = MathUtils.percentOrSelf(d, maxValue);
l = MathUtils.percentOrSelf(val, d, maxValue);
l = Math.min(validator.apply(l), maxValue);
} else {
l = validator.apply(Math.round(d));
Expand Down
17 changes: 17 additions & 0 deletions src/test/java/com/cleanroommc/modularui/utils/MathUtilsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.cleanroommc.modularui.utils;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class MathUtilsTest {

@Test
void testExplicitPercentageRelativeToMaximum() {
assertEquals(1, MathUtils.percentOrSelf("1", 1, 256));
assertEquals(128, MathUtils.percentOrSelf("0.5", 0.5, 256));
assertEquals(128, MathUtils.percentOrSelf("50%", 0.5, 256));
assertEquals(256, MathUtils.percentOrSelf("100%", 1, 256));
assertEquals(512, MathUtils.percentOrSelf("200%", 2, 256));
}
}