diff options
5 files changed, 112 insertions, 52 deletions
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java b/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java index 97b3cfc..b8abd22 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/client/modmenu/ConfigGui.java @@ -3,11 +3,8 @@ package io.github.cottonmc.cotton.gui.client.modmenu; import io.github.cottonmc.cotton.gui.client.BackgroundPainter; import io.github.cottonmc.cotton.gui.client.LibGuiClient; import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription; -import io.github.cottonmc.cotton.gui.widget.Axis; import io.github.cottonmc.cotton.gui.widget.WButton; import io.github.cottonmc.cotton.gui.widget.WGridPanel; -import io.github.cottonmc.cotton.gui.widget.WLabeledSlider; -import io.github.cottonmc.cotton.gui.widget.WSlider; import io.github.cottonmc.cotton.gui.widget.WTextField; import io.github.cottonmc.cotton.gui.widget.WToggleButton; import net.minecraft.client.MinecraftClient; @@ -33,8 +30,20 @@ public class ConfigGui extends LightweightGuiDescription { WTextField testField = new WTextField(); testField.setSuggestion("test"); root.add(testField, 0, 3, 4, 1); - root.add(new WSlider(-100, 100, Axis.VERTICAL).setValueChangeListener(System.out::println), 6, 0, 1, 3); - root.add(new WLabeledSlider(1, 100).setValueChangeListener(System.out::println), 1, 4, 4, 1); + + /* + WSlider verticalSlider = new WSlider(-100, 100, Axis.VERTICAL); + verticalSlider.setDraggingFinishedListener(() -> System.out.println("Mouse released")); + verticalSlider.setValueChangeListener(System.out::println); + + WLabeledSlider horizontalSlider = new WLabeledSlider(0, 500); + horizontalSlider.setLabelUpdater(value -> new LiteralText(value + "!")); + horizontalSlider.setDraggingFinishedListener(() -> System.out.println("Mouse released")); + horizontalSlider.setValue(250); + + root.add(verticalSlider, 6, 0, 1, 3); + root.add(horizontalSlider, 1, 4, 4, 1); + */ root.add(new WKirbSprite(), 5, 4); diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java index bfa455e..074371f 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WAbstractSlider.java @@ -12,10 +12,11 @@ import java.util.function.IntConsumer; * <p>You can set two listeners on a slider: * <ul> * <li> - * A value change listener that gets all value changes (except direct setValue calls). + * A value change listener that gets all value changes (including direct setValue calls). * </li> * <li> - * A focus release listener that gets called when the player stops dragging the slider. + * A dragging finished listener that gets called when the player stops dragging the slider + * or modifies the value with the keyboard. * For example, this can be used for sending sync packets to the server * when the player has selected a value. * </li> @@ -43,8 +44,13 @@ public abstract class WAbstractSlider extends WWidget { */ protected float coordToValueRatio; + /** + * True if there is a pending dragging finished event caused by the keyboard. + */ + private boolean valueChangedWithKeys = false; + @Nullable private IntConsumer valueChangeListener = null; - @Nullable private Runnable focusReleaseListener = null; + @Nullable private Runnable draggingFinishedListener = null; protected WAbstractSlider(int min, int max, Axis axis) { if (max <= min) @@ -73,7 +79,7 @@ public abstract class WAbstractSlider extends WWidget { @Override public void setSize(int x, int y) { super.setSize(x, y); - int trackHeight = (axis == Axis.HORIZONTAL ? x : y) - getThumbWidth() + 1; + int trackHeight = (axis == Axis.HORIZONTAL ? x : y) - getThumbWidth(); valueToCoordRatio = (float) (max - min) / trackHeight; coordToValueRatio = 1 / valueToCoordRatio; } @@ -108,6 +114,7 @@ public abstract class WAbstractSlider extends WWidget { @Override public void onClick(int x, int y, int button) { moveSlider(x, y); + if (draggingFinishedListener != null) draggingFinishedListener.run(); } private void moveSlider(int x, int y) { @@ -115,36 +122,31 @@ public abstract class WAbstractSlider extends WWidget { int rawValue = min + Math.round(valueToCoordRatio * pos); int previousValue = value; value = MathHelper.clamp(rawValue, min, max); - if (value != previousValue && valueChangeListener != null) valueChangeListener.accept(value); + if (value != previousValue) onValueChanged(value); } @Override public WWidget onMouseUp(int x, int y, int button) { dragging = false; + if (draggingFinishedListener != null) draggingFinishedListener.run(); return super.onMouseUp(x, y, button); } - @Override - public void onFocusLost() { - if (focusReleaseListener != null) focusReleaseListener.run(); - } - public int getValue() { return value; } public void setValue(int value) { this.value = value; + onValueChanged(value); } - public WAbstractSlider setValueChangeListener(@Nullable IntConsumer valueChangeListener) { + public void setValueChangeListener(@Nullable IntConsumer valueChangeListener) { this.valueChangeListener = valueChangeListener; - return this; } - public WAbstractSlider setFocusReleaseListener(@Nullable Runnable focusReleaseListener) { - this.focusReleaseListener = focusReleaseListener; - return this; + public void setDraggingFinishedListener(@Nullable Runnable draggingFinishedListener) { + this.draggingFinishedListener = draggingFinishedListener; } public int getMinValue() { @@ -159,27 +161,50 @@ public abstract class WAbstractSlider extends WWidget { return axis; } + protected void onValueChanged(int value) { + if (valueChangeListener != null) valueChangeListener.accept(value); + } + @Override public void onKeyPressed(int ch, int key, int modifiers) { boolean valueChanged = false; if (modifiers == 0) { - if ((ch == GLFW.GLFW_KEY_LEFT || ch == GLFW.GLFW_KEY_DOWN) && value > min) { + if (isDecreasingKey(ch) && value > min) { value--; valueChanged = true; - } else if ((ch == GLFW.GLFW_KEY_RIGHT || ch == GLFW.GLFW_KEY_UP) && value < max) { + } else if (isIncreasingKey(ch) && value < max) { value++; valueChanged = true; } } else if (modifiers == GLFW.GLFW_MOD_CONTROL) { - if ((ch == GLFW.GLFW_KEY_LEFT || ch == GLFW.GLFW_KEY_DOWN) && value != min) { + if (isDecreasingKey(ch) && value != min) { value = min; valueChanged = true; - } else if ((ch == GLFW.GLFW_KEY_RIGHT || ch == GLFW.GLFW_KEY_UP) && value != max) { + } else if (isIncreasingKey(ch) && value != max) { value = max; valueChanged = true; } } - if (valueChanged && valueChangeListener != null) valueChangeListener.accept(value); + if (valueChanged) { + onValueChanged(value); + valueChangedWithKeys = true; + } + } + + @Override + public void onKeyReleased(int ch, int key, int modifiers) { + if (valueChangedWithKeys && (isDecreasingKey(ch) || isIncreasingKey(ch))) { + if (draggingFinishedListener != null) draggingFinishedListener.run(); + valueChangedWithKeys = false; + } + } + + private static boolean isDecreasingKey(int ch) { + return ch == GLFW.GLFW_KEY_LEFT || ch == GLFW.GLFW_KEY_DOWN; + } + + private static boolean isIncreasingKey(int ch) { + return ch == GLFW.GLFW_KEY_RIGHT || ch == GLFW.GLFW_KEY_UP; } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java index 77a3325..37fe464 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabeledSlider.java @@ -4,38 +4,62 @@ import io.github.cottonmc.cotton.gui.client.ScreenDrawing; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.gui.widget.AbstractButtonWidget; -import net.minecraft.util.Identifier; +import net.minecraft.text.Text; + +import javax.annotation.Nullable; /** * A vanilla-style labeled slider widget. * + * <p>In addition to the standard slider listeners, + * labeled sliders also support "label updaters" that can update the label + * when the value is changed. + * * @see WAbstractSlider for more information about listeners */ -/* - TODO: - - Add the labels - - Better textures for thumbs when dragging - - The thumb goes 1px outside the track on the right side - */ public class WLabeledSlider extends WAbstractSlider { - private static final Identifier TEXTURE = AbstractButtonWidget.WIDGETS_LOCATION; + @Nullable private Text label = null; + @Nullable private LabelUpdater labelUpdater = null; public WLabeledSlider(int min, int max) { super(min, max, Axis.HORIZONTAL); } - public WLabeledSlider(int max) { - this(0, max); + public WLabeledSlider(int min, int max, Text label) { + this(min, max); + this.label = label; } + @Override public void setSize(int x, int y) { super.setSize(x, 20); } + @Nullable + public Text getLabel() { + return label; + } + + public void setLabel(@Nullable Text label) { + this.label = label; + } + + @Override + protected void onValueChanged(int value) { + super.onValueChanged(value); + if (labelUpdater != null) { + label = labelUpdater.updateLabel(value); + } + } + + public void setLabelUpdater(@Nullable LabelUpdater labelUpdater) { + this.labelUpdater = labelUpdater; + } + @Override protected int getThumbWidth() { - return 6; + return 8; } @Override @@ -49,16 +73,23 @@ public class WLabeledSlider extends WAbstractSlider { drawButton(x, y, 0, width); // 1: regular, 2: hovered, 0: disabled/dragging - int thumbX = (int) (coordToValueRatio * (value - min)); + int thumbX = Math.round(coordToValueRatio * (value - min)); int thumbY = 0; int thumbWidth = getThumbWidth(); int thumbHeight = height; - int thumbState = dragging ? 0 : (mouseX >= thumbX && mouseX <= thumbX + thumbWidth && mouseY >= thumbY && mouseY <= thumbY + thumbHeight ? 2 : 1); + boolean hovering = mouseX >= thumbX && mouseX <= thumbX + thumbWidth && mouseY >= thumbY && mouseY <= thumbY + thumbHeight; + int thumbState = dragging || hovering ? 2 : 1; drawButton(x + thumbX, y + thumbY, thumbState, thumbWidth); if (thumbState == 1 && isFocused()) { - // TODO: draw the focus border + float px = 1 / 32f; + ScreenDrawing.rect(WSlider.TEXTURE, x + thumbX, y + thumbY, thumbWidth, thumbHeight, 24*px, 0*px, 32*px, 20*px, 0xFFFFFFFF); + } + + if (label != null) { + int color = isMouseInsideBounds(mouseX, mouseY) ? 0xFFFFA0 : 0xE0E0E0; + ScreenDrawing.drawCenteredWithShadow(label.asFormattedString(), x + width / 2, y + height / 2 - 4, color); } } @@ -77,4 +108,9 @@ public class WLabeledSlider extends WAbstractSlider { ScreenDrawing.rect(AbstractButtonWidget.WIDGETS_LOCATION, x, y, halfWidth, 20, buttonLeft, buttonTop, buttonLeft + buttonWidth, buttonTop + buttonHeight, 0xFFFFFFFF); ScreenDrawing.rect(AbstractButtonWidget.WIDGETS_LOCATION, x + halfWidth, y, halfWidth, 20, buttonEndLeft, buttonTop, 200 * px, buttonTop + buttonHeight, 0xFFFFFFFF); } + + @FunctionalInterface + public interface LabelUpdater { + Text updateLabel(int value); + } } diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java index 14e9972..c57b705 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WSlider.java @@ -9,19 +9,9 @@ import net.minecraft.util.Identifier; import javax.annotation.Nullable; /** - * A slider widget that can be used to select int values. + * A simple slider widget that can be used to select int values. * - * <p>You can set two listeners on a slider: - * <ul> - * <li> - * A value change listener that gets all value changes (except direct setValue calls). - * </li> - * <li> - * A focus release listener that gets called when the player stops dragging the slider. - * For example, this can be used for sending sync packets to the server - * when the player has selected a value. - * </li> - * </ul> + * @see WAbstractSlider for supported listeners */ public class WSlider extends WAbstractSlider { public static final int TRACK_WIDTH = 6; @@ -78,7 +68,7 @@ public class WSlider extends WAbstractSlider { ScreenDrawing.rect(TEXTURE, trackX, y + height, TRACK_WIDTH, 1, 16*px, 2*px, 22*px, 3*px, 0xFFFFFFFF); } else { int trackY = y + height / 2 - TRACK_WIDTH / 2; - thumbX = (int) (coordToValueRatio * (value - min)); + thumbX = Math.round(coordToValueRatio * (value - min)); thumbY = height / 2 - THUMB_SIZE / 2; thumbXOffset = 8; diff --git a/src/main/resources/assets/libgui/textures/widget/slider.png b/src/main/resources/assets/libgui/textures/widget/slider.png Binary files differindex ce8f434..e41250e 100644 --- a/src/main/resources/assets/libgui/textures/widget/slider.png +++ b/src/main/resources/assets/libgui/textures/widget/slider.png |