From 60f1c29872465a25be4f2c4ca8c5eb1abf69f988 Mon Sep 17 00:00:00 2001 From: nextdaydelivery <79922345+nxtdaydelivery@users.noreply.github.com> Date: Sun, 1 May 2022 12:36:32 +0100 Subject: config elements --- .../oneconfig/config/OneConfigConfig.java | 3 +- .../oneconfig/config/annotations/Option.java | 18 ++- .../oneconfig/config/interfaces/Config.java | 4 +- .../io/polyfrost/oneconfig/gui/OneConfigGui.java | 1 + .../oneconfig/gui/elements/TextInputField.java | 58 ++++++- .../gui/elements/config/ConfigDualOption.java | 6 +- .../gui/elements/config/ConfigSlider.java | 178 +++++++++++++++++++++ .../io/polyfrost/oneconfig/test/TestConfig.java | 14 +- .../io/polyfrost/oneconfig/utils/ColorUtils.java | 3 + 9 files changed, 259 insertions(+), 26 deletions(-) create mode 100644 src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigSlider.java (limited to 'src/main/java/io/polyfrost/oneconfig') diff --git a/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java b/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java index d812f89..da6b4c2 100644 --- a/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java +++ b/src/main/java/io/polyfrost/oneconfig/config/OneConfigConfig.java @@ -19,7 +19,6 @@ public class OneConfigConfig extends Config { public static final int GRAY_900 = new Color(13, 14, 15, 255).getRGB(); // Gray 900 public static final int GRAY_900_80 = new Color(13, 14, 15, 204).getRGB(); // Gray 900 80% - // im waiting for u to say the gray button colors public static final int GRAY_800 = new Color(21, 22, 23, 255).getRGB(); // Gray 800 public static final int GRAY_700 = new Color(34, 35, 38, 255).getRGB(); // Gray 700 public static final int GRAY_600 = new Color(42, 44, 48, 255).getRGB(); // Gray 600 @@ -42,6 +41,8 @@ public class OneConfigConfig extends Config { public static final int WHITE_90 = new Color(255, 255, 255, 229).getRGB(); // White 90% public static final int WHITE = new Color(255, 255, 255, 255).getRGB(); // White 100% + public static final int ERROR_700 = new Color(180, 24, 24, 255).getRGB(); // Red 700 + public static boolean ROUNDED_CORNERS = true; public static float CORNER_RADIUS_WIN = 20f; public static float CORNER_RADIUS = 12f; diff --git a/src/main/java/io/polyfrost/oneconfig/config/annotations/Option.java b/src/main/java/io/polyfrost/oneconfig/config/annotations/Option.java index fe61a02..05505a9 100644 --- a/src/main/java/io/polyfrost/oneconfig/config/annotations/Option.java +++ b/src/main/java/io/polyfrost/oneconfig/config/annotations/Option.java @@ -31,13 +31,11 @@ public @interface Option { */ String subcategory(); - /** The name shown on the Left option of a DualOption slider. */ - String optionLeft() default "Option 1"; - /** The name shown on the Right option of a DualOption slider. */ - String optionRight() default "Option 2"; - - /** A String array of all the possible values for the UniSelector, dropdownList, and ComboBox */ + /** A String array of all the possible values for the UniSelector, dropdownList, and ComboBox. + * Also used in the DualOption slider, index 0 is the left, index 1 is the right; for example: + * {"Option 1", "Option 2"} + * */ String[] options() default {}; /** @@ -64,6 +62,14 @@ public @interface Option { * Steps of slider (0 for no steps) */ int step() default 0; + /** + * Minimum value of slider + */ + float min() default 0; + /** + * The maximum value of the slider + */ + float max() default 0; /** * Option for info option type diff --git a/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java b/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java index af3d037..35b299b 100644 --- a/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java +++ b/src/main/java/io/polyfrost/oneconfig/config/interfaces/Config.java @@ -110,11 +110,13 @@ public class Config { options.add(new ConfigTextBox(field, option.name(), option.size(), option.placeholder(), option.secure(), option.multiLine())); break; case DUAL_OPTION: - options.add(new ConfigDualOption(field, option.name(), option.size(), option.optionLeft(), option.optionRight())); + options.add(new ConfigDualOption(field, option.name(), option.size(), option.options())); break; case UNI_SELECTOR: options.add(new ConfigUniSelector(field, option.name(), option.size(), option.options())); break; + case SLIDER: + options.add(new ConfigSlider(field, option.name(), option.size(), option.min(), option.max(), option.step())); } } } diff --git a/src/main/java/io/polyfrost/oneconfig/gui/OneConfigGui.java b/src/main/java/io/polyfrost/oneconfig/gui/OneConfigGui.java index 0a4acd6..77d30bd 100644 --- a/src/main/java/io/polyfrost/oneconfig/gui/OneConfigGui.java +++ b/src/main/java/io/polyfrost/oneconfig/gui/OneConfigGui.java @@ -93,6 +93,7 @@ public class OneConfigGui extends GuiScreen { } public void openPage(@NotNull Page page) { + if(page == currentPage) return; currentPage.finishUpAndClose(); if (prevPage == null) { prevPage = currentPage; diff --git a/src/main/java/io/polyfrost/oneconfig/gui/elements/TextInputField.java b/src/main/java/io/polyfrost/oneconfig/gui/elements/TextInputField.java index 8f7f77c..081c99b 100644 --- a/src/main/java/io/polyfrost/oneconfig/gui/elements/TextInputField.java +++ b/src/main/java/io/polyfrost/oneconfig/gui/elements/TextInputField.java @@ -28,6 +28,9 @@ public class TextInputField extends BasicElement { protected long vg; protected int prevCaret = 0; protected boolean isDoubleClick = false; + protected boolean onlyNums = false; + protected boolean errored = false; + protected boolean centered = false; public TextInputField(int width, int height, String defaultText, boolean multiLine, boolean password) { super(width, height, false); @@ -37,6 +40,10 @@ public class TextInputField extends BasicElement { this.input = ""; } + public void onlyAcceptNumbers(boolean state) { + onlyNums = state; + } + public void setInput(String input) { this.input = input; } @@ -53,18 +60,32 @@ public class TextInputField extends BasicElement { return password; } + public void setErrored(boolean errored) { + this.errored = errored; + } + + public void setCentered(boolean centered) { + this.centered = centered; + } + + public boolean isErrored() { + return errored; + } + @Override public void draw(long vg, int x, int y) { this.x = x; this.y = y; this.vg = vg; try { - RenderManager.drawHollowRoundRect(vg, x, y, width, height, OneConfigConfig.GRAY_700, 12f, 2f); + int colorOutline = errored ? OneConfigConfig.ERROR_700 : OneConfigConfig.GRAY_700; + RenderManager.drawHollowRoundRect(vg, x, y, width, height, colorOutline, 12f, 2f); super.update(x, y); if (Mouse.isButtonDown(0) && !InputUtils.isAreaHovered(x - 40, y - 20, width + 90, height + 20)) { toggled = false; } int color = toggled ? OneConfigConfig.WHITE : OneConfigConfig.WHITE_60; + if(!toggled) caretPos = input.length(); float width; StringBuilder s = new StringBuilder(); if (!password) { @@ -102,6 +123,7 @@ public class TextInputField extends BasicElement { } } } + float halfTextWidth = this.getTextWidth(vg, input) / 2f; if (start != 0f && end != 0f && toggled) { RenderManager.drawRect(vg, start, y + height / 2f - 10, end, 20, OneConfigConfig.GRAY_300); } @@ -109,11 +131,13 @@ public class TextInputField extends BasicElement { if (Mouse.isButtonDown(0) && !isDoubleClick) { caretPos = calculatePos(Mouse.getX()); if (caretPos > prevCaret) { - start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + if(!centered) start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + else start = x + this.width / 2f - halfTextWidth + this.getTextWidth(vg, input.substring(0, prevCaret)); end = this.getTextWidth(vg, input.substring(prevCaret, caretPos)); selectedText = input.substring(prevCaret, caretPos); } else { - start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + if(!centered) start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + else start = x + this.width / 2f - halfTextWidth + this.getTextWidth(vg, input.substring(0, prevCaret)); end = -this.getTextWidth(vg, input.substring(caretPos, prevCaret)); selectedText = input.substring(caretPos, prevCaret); } @@ -122,16 +146,28 @@ public class TextInputField extends BasicElement { if (toggled) { - RenderManager.drawLine(vg, x + width + 12, (float) y + height / 2f - 10, x + width + 12, (float) y + height / 2f + 10, 1, OneConfigConfig.WHITE); + if(!centered) { + RenderManager.drawLine(vg, x + width + 12, (float) y + height / 2f - 10, x + width + 12, (float) y + height / 2f + 10, 1, OneConfigConfig.WHITE); + } else { + RenderManager.drawLine(vg, x + this.width / 2f - halfTextWidth + width, (float) y + height / 2f - 10, x + this.width / 2f - halfTextWidth + width, (float) y + height / 2f + 10, 1, OneConfigConfig.WHITE); + } } if (input.equals("")) { - RenderManager.drawString(vg, defaultText, x + 12, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); + if(!centered) { + RenderManager.drawString(vg, defaultText, x + 12, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); + } else { + RenderManager.drawString(vg, defaultText, x + this.width / 2f - halfTextWidth, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); + } } if (!password) { - RenderManager.drawString(vg, input, x + 12, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); + if(!centered) { + RenderManager.drawString(vg, input, x + 12, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); + } else { + RenderManager.drawString(vg, input, x + this.width / 2f - halfTextWidth, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); + } } else { RenderManager.drawString(vg, s.toString(), x + 12, y + height / 2f + 1, color, 14f, Fonts.INTER_REGULAR); } @@ -178,7 +214,7 @@ public class TextInputField extends BasicElement { if (GuiScreen.isKeyComboCtrlA(key)) { prevCaret = 0; caretPos = input.length(); - start = x + 12; + start = !centered ? x + 12 : x + this.width / 2f - this.getTextWidth(vg, input) / 2f; selectedText = input; end = this.getTextWidth(vg, input); return; @@ -222,6 +258,7 @@ public class TextInputField extends BasicElement { return; } if (key == Keyboard.KEY_TAB) { + if(onlyNums) return; input += " "; caretPos += 4; return; @@ -282,6 +319,9 @@ public class TextInputField extends BasicElement { if (key == Keyboard.KEY_LCONTROL || key == Keyboard.KEY_RCONTROL || key == Keyboard.KEY_LMENU || key == Keyboard.KEY_RMENU || key == Keyboard.KEY_LMETA || key == Keyboard.KEY_RMETA || key == Keyboard.KEY_LSHIFT || key == Keyboard.KEY_RSHIFT || key == Keyboard.KEY_RETURN || key == Keyboard.KEY_CAPITAL || key == 221 || key == Keyboard.KEY_HOME) { return; } + if(onlyNums) { + if(!Character.isDigit(c) && key != 52) return; + } if (!Character.isDefined(key)) return; if (!Character.isDefined(c)) return; if(GuiScreen.isCtrlKeyDown()) return; @@ -329,11 +369,13 @@ public class TextInputField extends BasicElement { caretPos = input.indexOf(' ', caretPos); if(caretPos == -1) caretPos = input.length(); selectedText = input.substring(prevCaret, caretPos); - start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + if(!centered) start = x + 12 + this.getTextWidth(vg, input.substring(0, prevCaret)); + else start = x + this.width / 2f - this.getTextWidth(vg, input) / 2f + this.getTextWidth(vg, input.substring(0, prevCaret)); end = this.getTextWidth(vg, input.substring(prevCaret, caretPos)); } private int calculatePos(int pos) { + if(centered) pos -= 12; String s1 = ""; int i; for (char c : input.toCharArray()) { diff --git a/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigDualOption.java b/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigDualOption.java index 705ab1a..3e90e57 100644 --- a/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigDualOption.java +++ b/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigDualOption.java @@ -13,10 +13,10 @@ public class ConfigDualOption extends BasicOption { private float percentMove = 0f; private final String left, right; - public ConfigDualOption(Field field, String name, int size, String left, String right) { + public ConfigDualOption(Field field, String name, int size, String[] options) { super(field, name, size); - this.left = left; - this.right = right; + this.left = options[0]; + this.right = options[1]; } diff --git a/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigSlider.java b/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigSlider.java new file mode 100644 index 0000000..54df53e --- /dev/null +++ b/src/main/java/io/polyfrost/oneconfig/gui/elements/config/ConfigSlider.java @@ -0,0 +1,178 @@ +package io.polyfrost.oneconfig.gui.elements.config; + +import io.polyfrost.oneconfig.config.OneConfigConfig; +import io.polyfrost.oneconfig.config.interfaces.BasicOption; +import io.polyfrost.oneconfig.gui.elements.BasicElement; +import io.polyfrost.oneconfig.gui.elements.TextInputField; +import io.polyfrost.oneconfig.lwjgl.RenderManager; +import io.polyfrost.oneconfig.lwjgl.font.Fonts; +import io.polyfrost.oneconfig.utils.ColorUtils; +import io.polyfrost.oneconfig.utils.InputUtils; +import io.polyfrost.oneconfig.utils.MathUtils; +import org.lwjgl.input.Mouse; +import org.lwjgl.nanovg.NanoVG; + +import java.lang.reflect.Field; + +public class ConfigSlider extends BasicOption { + private final BasicElement slideYBoi = new BasicElement(24, 24, false); + private final TextInputField inputField = new TextInputField(84, 24, "", false, false); + private final BasicElement upArrow = new BasicElement(12, 14, false); + private final BasicElement downArrow = new BasicElement(12, 14, false); + private final float min, max; + private final int step; + private float current; + private int colorTop, colorBottom; + + public ConfigSlider(Field field, String name, int size, float min, float max, int step) { + super(field, name, size); + this.min = min; + this.max = max; + this.step = step - 1; // it adds one more step than actual + slideYBoi.setCustomHitbox(28, 8); + inputField.onlyAcceptNumbers(true); + inputField.setCentered(true); + try { + inputField.setInput(String.valueOf(get())); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + @Override + public int getHeight() { + return 32; + } + + @Override + public void draw(long vg, int x, int y) { + RenderManager.drawString(vg, name, x, y + 15, OneConfigConfig.WHITE_90, 18f, Fonts.INTER_MEDIUM); + RenderManager.drawRoundedRect(vg, x + 352, y + 13, 512, 6, OneConfigConfig.GRAY_300, 4f); + slideYBoi.update(x + 340 + (int) (current * 512), y + 4); + if(step != 0) { + for(float i = 0; i <= 1.005f; i += 1f / step) { // sometimes it's just more than 1, so we add a little + int color = current > i ? OneConfigConfig.BLUE_500 : OneConfigConfig.GRAY_300; + RenderManager.drawRoundedRect(vg, x + 351 + (int) (i * 512), y + 9, 4, 14, color, 2f); + } + } + RenderManager.drawRoundedRect(vg, x + 352, y + 13, (int) (current * 512), 6, OneConfigConfig.BLUE_500, 4f); + if(step == 0) RenderManager.drawRoundedRect(vg, x + 340 + (int) (current * 512), y + 4, 24, 24, OneConfigConfig.WHITE, 12f); + else RenderManager.drawRoundedRect(vg, x + 346 + (int) (current * 512), y + 4, 8, 24, OneConfigConfig.WHITE, 4f); + + + int mouseX = InputUtils.mouseX() - (x + 352); + if(InputUtils.isAreaClicked(x + 332, y + 9, 542, 10) && !slideYBoi.isHovered()) { + if(step == 0) { + current = MathUtils.clamp(mouseX / 512f); + } else current = MathUtils.clamp(toNearestStep(mouseX / 512f)); + } + if(slideYBoi.isHovered() && Mouse.isButtonDown(0)) { + if(step == 0) { + current = MathUtils.clamp(mouseX / 512f); + } else current = MathUtils.clamp(toNearestStep(mouseX / 512f)); + } + float currentAsNum = current * (max - min) + min; + + if(!inputField.isToggled()) inputField.setInput(String.format("%.01f", currentAsNum)); + inputField.setErrored(false); + if(inputField.isToggled()) { + try { + float input = Float.parseFloat(inputField.getInput()); + if(input < min) { + inputField.setErrored(true); + input = min; + } + if(input > max) { + inputField.setErrored(true); + input = max; + } + if(step == 0) { + current = MathUtils.clamp((input - min) / (max - min)); + } else { + current = toNearestStep(MathUtils.clamp((input - min) / (max - min))); + } + } catch (NumberFormatException ignored) { + inputField.setErrored(true); + } + } + inputField.draw(vg, x + 892, y); + + RenderManager.drawRoundedRect(vg, x + 980, y, 12, 28, OneConfigConfig.GRAY_500, 6f); + upArrow.update(x + 980, y); + downArrow.update(x + 980, y + 14); + if(current == 1f) colorTop = OneConfigConfig.GRAY_500_80; + if(current == 0f) colorBottom = OneConfigConfig.GRAY_500_80; + colorTop = ColorUtils.getColor(colorTop, 2, upArrow.isHovered(), upArrow.isClicked()); + colorBottom = ColorUtils.getColor(colorBottom, 2, downArrow.isHovered(), downArrow.isClicked()); + if(upArrow.isClicked()) { + if(step == 0) { + currentAsNum += 1; + current = MathUtils.clamp((currentAsNum - min) / (max - min)); + } else { + for(float i1 = 0f; i1 <= 1f; i1 += 1f / step) { + if(i1 > current) { + current = i1; + break; + } + } + } + } + if(downArrow.isClicked()) { + if(step == 0) { + currentAsNum -= 1; + current = MathUtils.clamp((currentAsNum - min) / (max - min)); + } else { + for(float i1 = 1f; i1 >= 0f; i1 -= 1f / step) { + if(i1 < current) { + current = i1; + break; + } + } + } + } + if(current == 1f) NanoVG.nvgGlobalAlpha(vg, 0.3f); + RenderManager.drawRoundedRectVaried(vg, x + 980, y, 12, 14, colorTop,6f, 6f, 0f, 0f); + RenderManager.drawImage(vg, "/assets/oneconfig/textures/smallUpArrow.png", x + 981, y + 2, 10, 10); + if(current == 1f) NanoVG.nvgGlobalAlpha(vg, 1f); + + if(current == 0f) NanoVG.nvgGlobalAlpha(vg, 0.3f); + RenderManager.drawRoundedRectVaried(vg, x + 980, y + 14, 12, 14, colorBottom,0f, 0f, 6f, 6f); + NanoVG.nvgTranslate(vg, x + 991, y + 25); + NanoVG.nvgRotate(vg, (float) Math.toRadians(180)); + RenderManager.drawImage(vg, "/assets/oneconfig/textures/smallUpArrow.png", 0, 0, 10, 10); + NanoVG.nvgResetTransform(vg); + NanoVG.nvgGlobalAlpha(vg, 1f); + } + + private float toNearestStep(float input) { + float stepF = 1f / step; + float stepAbove = 1f, stepBelow = 0f; + for(float a = 0f; a <= 1f; a += stepF) { + if(a > input) { + stepAbove = a; + break; + } + } + for(float a = 1f; a >= 0f; a -= stepF) { + if(a <= input) { + stepBelow = a; + break; + } + } + if(stepAbove - input > input - stepBelow) { + return stepBelow; + } else { + return stepAbove; + } + } + + @Override + public boolean hasHalfSize() { + return false; + } + + @Override + public void keyTyped(char key, int keyCode) { + inputField.keyTyped(key, keyCode); + } +} diff --git a/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java b/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java index 7b99cc1..3ac04bf 100644 --- a/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java +++ b/src/main/java/io/polyfrost/oneconfig/test/TestConfig.java @@ -13,15 +13,15 @@ public class TestConfig extends Config { @Option( name = "Test dual thing", subcategory = "Test", - optionLeft = "FUNNY", optionRight = "not funny", - type = OptionType.DUAL_OPTION + min = 3f, max = 127f, + type = OptionType.SLIDER ) - public static boolean switchTest; + public static float sliderText; @Option( name = "Test string", subcategory = "Test", - optionLeft = "HI", optionRight = "BYE", + options = {"NO", "YES"}, type = OptionType.DUAL_OPTION ) public static boolean switchTest1; @@ -29,12 +29,12 @@ public class TestConfig extends Config { @Option( name = "Test dual option", subcategory = "Test", - optionRight = "cool", optionLeft = "not cool", - type = OptionType.DUAL_OPTION, - size = 2 + options = {"HI", "BYE"}, + type = OptionType.DUAL_OPTION ) public static boolean switchTest2; + @Option( name = "Test option", subcategory = "Test", diff --git a/src/main/java/io/polyfrost/oneconfig/utils/ColorUtils.java b/src/main/java/io/polyfrost/oneconfig/utils/ColorUtils.java index abc36a5..499e59b 100644 --- a/src/main/java/io/polyfrost/oneconfig/utils/ColorUtils.java +++ b/src/main/java/io/polyfrost/oneconfig/utils/ColorUtils.java @@ -17,6 +17,7 @@ public class ColorUtils { case -1: return OneConfigConfig.GRAY_500_80; default: + case 2: case 0: return OneConfigConfig.GRAY_400_80; case 1: @@ -34,6 +35,8 @@ public class ColorUtils { return getColorComponents(color, splitColor(OneConfigConfig.GRAY_600), splitColor(OneConfigConfig.GRAY_300), hover, 25f); case 1: return getColorComponents(color, splitColor(OneConfigConfig.BLUE_600), splitColor(OneConfigConfig.BLUE_500), hover, 150f); + case 2: + return getColorComponents(color, splitColor(OneConfigConfig.GRAY_500), splitColor(OneConfigConfig.GRAY_300), hover, 50f); } -- cgit