From cd052a3d42fae2c80c58b28741dd66e9da1a6fcd Mon Sep 17 00:00:00 2001 From: Juuxel Date: Tue, 27 Aug 2019 11:10:30 +0300 Subject: Add sliders, WIP --- .../resources/assets/libgui/textures/widget/slider.png | Bin 0 -> 668 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/assets/libgui/textures/widget/slider.png (limited to 'src/main/resources/assets') diff --git a/src/main/resources/assets/libgui/textures/widget/slider.png b/src/main/resources/assets/libgui/textures/widget/slider.png new file mode 100644 index 0000000..8fbf16f Binary files /dev/null and b/src/main/resources/assets/libgui/textures/widget/slider.png differ -- cgit From 5f3e03cba9fe46791c717071b2b209129099d35b Mon Sep 17 00:00:00 2001 From: Juuxel Date: Tue, 27 Aug 2019 17:10:06 +0300 Subject: More work on sliders --- build.gradle | 4 ++-- .../cotton/gui/client/modmenu/ConfigGui.java | 9 ++++---- .../github/cottonmc/cotton/gui/widget/WButton.java | 2 +- .../github/cottonmc/cotton/gui/widget/WSlider.java | 25 +++++++++++++-------- .../assets/libgui/textures/widget/slider.png | Bin 668 -> 1831 bytes 5 files changed, 23 insertions(+), 17 deletions(-) (limited to 'src/main/resources/assets') diff --git a/build.gradle b/build.gradle index c453a51..580618e 100644 --- a/build.gradle +++ b/build.gradle @@ -17,13 +17,13 @@ buildscript { } plugins { - //id 'fabric-loom' version '0.2.4-SNAPSHOT' + id 'fabric-loom' version '0.2.4-SNAPSHOT' id 'maven-publish' id "com.jfrog.artifactory" version "4.9.0" } -apply plugin: "fabric-loom"; +//apply plugin: "fabric-loom"; sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 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 23c5b6f..454df9d 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,10 +3,7 @@ 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.WButton; -import io.github.cottonmc.cotton.gui.widget.WGridPanel; -import io.github.cottonmc.cotton.gui.widget.WTextField; -import io.github.cottonmc.cotton.gui.widget.WToggleButton; +import io.github.cottonmc.cotton.gui.widget.*; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.TranslatableText; @@ -30,7 +27,9 @@ public class ConfigGui extends LightweightGuiDescription { WTextField testField = new WTextField(); testField.setSuggestion("test"); root.add(testField, 0, 3, 4, 1); - + root.add(new WSlider(100, 0, Axis.VERTICAL).setValueChangeListener(System.out::println), 0, 4, 1, 4); + root.add(new WSlider(0, 123, Axis.HORIZONTAL).setValueChangeListener(System.out::println), 1, 4, 4, 1); + root.add(new WKirbSprite(), 5, 4); WButton doneButton = new WButton(new TranslatableText("gui.done")); diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java index 0f5159c..16a8d71 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java @@ -31,7 +31,7 @@ public class WButton extends WWidget { @Override public void paintForeground(int x, int y, int mouseX, int mouseY) { - System.out.println("Mouse: { "+mouseX+", "+mouseY+" }"); + //System.out.println("Mouse: { "+mouseX+", "+mouseY+" }"); boolean hovered = (mouseX>=x && mouseY>=y && mouseX= min) + throw new IllegalArgumentException("Minimum value must be smaller than the maximum!"); + this.min = min; this.max = max; this.valueRange = max - min + 1; @@ -37,8 +44,7 @@ public class WSlider extends WWidget { @Override public void setSize(int x, int y) { super.setSize(x, y); - // FIXME: that - and + stuff fixes the rendering but causes range issues (too large for X and too small for Y) - int trackHeight = (axis == Axis.HORIZONTAL ? (x - THUMB_SIZE) : (y + THUMB_SIZE)); + int trackHeight = (axis == Axis.HORIZONTAL ? x : y) - THUMB_SIZE + 1; valueToCoordRatio = (float) valueRange / trackHeight; coordToValueRatio = 1 / valueToCoordRatio; } @@ -58,8 +64,9 @@ public class WSlider extends WWidget { int aoCenter = (axis == Axis.HORIZONTAL ? height : width) / 2; if (dragging || ao >= aoCenter - TRACK_WIDTH / 2 && ao <= aoCenter + TRACK_WIDTH / 2) { dragging = true; - int pos = axis == Axis.VERTICAL ? (axisWidth - a + THUMB_SIZE / 2) : (a - THUMB_SIZE / 2); - value = min + (int) (valueToCoordRatio * pos); + int pos = (axis == Axis.VERTICAL ? (axisWidth - a) : a) - THUMB_SIZE / 2; + int futureValue = min + (int) (valueToCoordRatio * pos); + value = MathHelper.clamp(futureValue, min, max); if (valueChangeListener != null) valueChangeListener.accept(value); } } @@ -83,7 +90,7 @@ public class WSlider extends WWidget { float px = 1 / 16f; if (axis == Axis.VERTICAL) { int trackX = x + width / 2 - TRACK_WIDTH / 2; - int thumbY = y + height - (int) (coordToValueRatio * (value - min)); + int thumbY = y + height - THUMB_SIZE + 1 - (int) (coordToValueRatio * (value - min)); ScreenDrawing.rect(TEXTURE, trackX, y + 1, TRACK_WIDTH, 1, 0*px, 8*px, 6*px, 9*px, 0xFFFFFFFF); ScreenDrawing.rect(TEXTURE, trackX, y + 2, TRACK_WIDTH, height - 2, 0*px, 9*px, 6*px, 10*px, 0xFFFFFFFF); @@ -94,11 +101,11 @@ public class WSlider extends WWidget { int trackY = y + height / 2 - TRACK_WIDTH / 2; int thumbX = x + (int) (coordToValueRatio * (value - min)); - ScreenDrawing.rect(x, trackY, 1, TRACK_WIDTH, 0xFFFF0000); - ScreenDrawing.rect(x + 1, trackY, width - 2, TRACK_WIDTH, 0xFFFF0000); - ScreenDrawing.rect(x + width - 1, trackY, 1, TRACK_WIDTH, 0xFFFF0000); + ScreenDrawing.rect(TEXTURE, x, trackY, 1, TRACK_WIDTH, 8*px, 0*px, 9*px, 6*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, x + 1, trackY, width - 2, TRACK_WIDTH, 9*px, 0*px, 10*px, 6*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, x + width - 1, trackY, 1, TRACK_WIDTH, 10*px, 0*px, 11*px, 6*px, 0xFFFFFFFF); - ScreenDrawing.rect(thumbX, y + height / 2 - THUMB_SIZE / 2, THUMB_SIZE, THUMB_SIZE, 0xFF00FFFF); + ScreenDrawing.rect(TEXTURE, thumbX, y + height / 2 - THUMB_SIZE / 2, THUMB_SIZE, THUMB_SIZE, 8*px, 8*px, 16*px, 16*px, 0xFFFFFFFF); } } diff --git a/src/main/resources/assets/libgui/textures/widget/slider.png b/src/main/resources/assets/libgui/textures/widget/slider.png index 8fbf16f..d4e2eda 100644 Binary files a/src/main/resources/assets/libgui/textures/widget/slider.png and b/src/main/resources/assets/libgui/textures/widget/slider.png differ -- cgit From c1cdad568698afbb2b0a938840fe4193cb8d1d9f Mon Sep 17 00:00:00 2001 From: Juuxel Date: Tue, 27 Aug 2019 19:06:47 +0300 Subject: Almost working sliders --- .../github/cottonmc/cotton/gui/widget/WSlider.java | 77 ++++++++++++++++----- .../assets/libgui/textures/widget/slider.png | Bin 1831 -> 2295 bytes 2 files changed, 59 insertions(+), 18 deletions(-) (limited to 'src/main/resources/assets') 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 c08d1bc..5aae891 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 @@ -1,12 +1,27 @@ package io.github.cottonmc.cotton.gui.widget; import io.github.cottonmc.cotton.gui.client.ScreenDrawing; +import net.minecraft.client.MinecraftClient; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; import javax.annotation.Nullable; import java.util.function.IntConsumer; +/** + * A slider widget that can be used to select int values. + * + *

You can set two listeners on a slider: + *

    + *
  • A value change listener that gets all value changes (except direct setValue calls)
  • + *
  • + * A mouse 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. + *
  • + *
+ */ public class WSlider extends WWidget { private static final int TRACK_WIDTH = 6; private static final int THUMB_SIZE = 8; @@ -22,12 +37,12 @@ public class WSlider extends WWidget { @Nullable private IntConsumer valueChangeListener = null; @Nullable private Runnable mouseReleaseListener = null; - // Used for detecting dragging after the user starts dragging + // Used for visuals and detecting dragging after the user starts dragging // on top of the slider, but then moves the mouse out but still within the widget's boundary. private boolean dragging = false; public WSlider(int min, int max, Axis axis) { - if (max >= min) + if (max <= min) throw new IllegalArgumentException("Minimum value must be smaller than the maximum!"); this.min = min; @@ -56,15 +71,14 @@ public class WSlider extends WWidget { @Override public void onMouseDrag(int x, int y, int button) { - // a = mouse coordinate on slider axis, axisWidth = width of slider axis + // a = mouse coordinate on slider axis // ao = axis-opposite mouse coordinate, aoCenter = center of ao's axis int a = axis == Axis.HORIZONTAL ? x : y; - int axisWidth = axis == Axis.HORIZONTAL ? width : height; int ao = axis == Axis.HORIZONTAL ? y : x; int aoCenter = (axis == Axis.HORIZONTAL ? height : width) / 2; - if (dragging || ao >= aoCenter - TRACK_WIDTH / 2 && ao <= aoCenter + TRACK_WIDTH / 2) { + if (dragging || ao >= aoCenter - TRACK_WIDTH / 2 - 2 && ao <= aoCenter + TRACK_WIDTH / 2 + 2) { dragging = true; - int pos = (axis == Axis.VERTICAL ? (axisWidth - a) : a) - THUMB_SIZE / 2; + int pos = (axis == Axis.VERTICAL ? (height - a) : a) - THUMB_SIZE / 2; int futureValue = min + (int) (valueToCoordRatio * pos); value = MathHelper.clamp(futureValue, min, max); if (valueChangeListener != null) valueChangeListener.accept(value); @@ -87,26 +101,53 @@ public class WSlider extends WWidget { @Override public void paintBackground(int x, int y) { - float px = 1 / 16f; + float px = 1 / 32f; + if (axis == Axis.VERTICAL) { int trackX = x + width / 2 - TRACK_WIDTH / 2; - int thumbY = y + height - THUMB_SIZE + 1 - (int) (coordToValueRatio * (value - min)); - - ScreenDrawing.rect(TEXTURE, trackX, y + 1, TRACK_WIDTH, 1, 0*px, 8*px, 6*px, 9*px, 0xFFFFFFFF); - ScreenDrawing.rect(TEXTURE, trackX, y + 2, TRACK_WIDTH, height - 2, 0*px, 9*px, 6*px, 10*px, 0xFFFFFFFF); - ScreenDrawing.rect(TEXTURE, trackX, y + height, TRACK_WIDTH, 1, 0*px, 10*px, 6*px, 11*px, 0xFFFFFFFF); - ScreenDrawing.rect(TEXTURE, x + width / 2 - THUMB_SIZE / 2, thumbY, THUMB_SIZE, THUMB_SIZE, 0*px, 0*px, 8*px, 8*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, trackX, y + 1, TRACK_WIDTH, 1, 16*px, 0*px, 22*px, 1*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, trackX, y + 2, TRACK_WIDTH, height - 2, 16*px, 1*px, 22*px, 2*px, 0xFFFFFFFF); + 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; - int thumbX = x + (int) (coordToValueRatio * (value - min)); - ScreenDrawing.rect(TEXTURE, x, trackY, 1, TRACK_WIDTH, 8*px, 0*px, 9*px, 6*px, 0xFFFFFFFF); - ScreenDrawing.rect(TEXTURE, x + 1, trackY, width - 2, TRACK_WIDTH, 9*px, 0*px, 10*px, 6*px, 0xFFFFFFFF); - ScreenDrawing.rect(TEXTURE, x + width - 1, trackY, 1, TRACK_WIDTH, 10*px, 0*px, 11*px, 6*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, x, trackY, 1, TRACK_WIDTH, 16*px, 3*px, 17*px, 9*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, x + 1, trackY, width - 2, TRACK_WIDTH, 17*px, 3*px, 18*px, 9*px, 0xFFFFFFFF); + ScreenDrawing.rect(TEXTURE, x + width - 1, trackY, 1, TRACK_WIDTH, 18*px, 3*px, 19*px, 9*px, 0xFFFFFFFF); + } + } + + @Override + public void paintForeground(int x, int y, int mouseX, int mouseY) { + float px = 1 / 32f; + int thumbX, thumbY, thumbXOffset; + + if (axis == Axis.VERTICAL) { + thumbX = x + width / 2 - THUMB_SIZE / 2; + thumbY = y + height - THUMB_SIZE + 1 - (int) (coordToValueRatio * (value - min)); + thumbXOffset = 0; + } else { + thumbX = x + (int) (coordToValueRatio * (value - min)); + thumbY = y + height / 2 - THUMB_SIZE / 2; + thumbXOffset = 8; + } - ScreenDrawing.rect(TEXTURE, thumbX, y + height / 2 - THUMB_SIZE / 2, THUMB_SIZE, THUMB_SIZE, 8*px, 8*px, 16*px, 16*px, 0xFFFFFFFF); + // FIXME: Ugly, I really should remove this + if (dragging) { + if (GLFW.glfwGetMouseButton(MinecraftClient.getInstance().window.getHandle(), GLFW.GLFW_MOUSE_BUTTON_1) == GLFW.GLFW_PRESS) { + onMouseDrag(mouseX - x, mouseY - y, 0); + } else { + onMouseUp(mouseX - x, mouseY - y, 0); + } } + + // thumbState values: + // 0: default, 1: dragging, 2: hovered + int thumbState = dragging ? 1 : (mouseX >= thumbX && mouseX <= thumbX + THUMB_SIZE && mouseY >= thumbY && mouseY <= thumbY + THUMB_SIZE ? 2 : 0); + ScreenDrawing.rect(TEXTURE, thumbX, thumbY, THUMB_SIZE, THUMB_SIZE, thumbXOffset*px, 0*px + thumbState * 8*px, (thumbXOffset + 8)*px, 8*px + thumbState * 8*px, 0xFFFFFFFF); + + super.paintForeground(x, y, mouseX, mouseY); } public int getValue() { diff --git a/src/main/resources/assets/libgui/textures/widget/slider.png b/src/main/resources/assets/libgui/textures/widget/slider.png index d4e2eda..d118877 100644 Binary files a/src/main/resources/assets/libgui/textures/widget/slider.png and b/src/main/resources/assets/libgui/textures/widget/slider.png differ -- cgit From e71d2283b1eb16bc769e51910e2a400817021819 Mon Sep 17 00:00:00 2001 From: Juuxel Date: Wed, 28 Aug 2019 20:56:47 +0300 Subject: Sliders: Add keyboard support, fix clicking, highlight when focused --- .../cotton/gui/client/modmenu/ConfigGui.java | 2 +- .../github/cottonmc/cotton/gui/widget/WSlider.java | 80 ++++++++++++++++----- .../assets/libgui/textures/widget/slider.png | Bin 2295 -> 2597 bytes 3 files changed, 62 insertions(+), 20 deletions(-) (limited to 'src/main/resources/assets') 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 2bca040..fc3e3b5 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 @@ -33,7 +33,7 @@ public class ConfigGui extends LightweightGuiDescription { testField.setSuggestion("test"); root.add(testField, 0, 3, 4, 1); root.add(new WSlider(-1, 1, Axis.VERTICAL).setValueChangeListener(System.out::println), 6, 0, 1, 3); - root.add(new WSlider(-1, 0, Axis.HORIZONTAL).setValueChangeListener(System.out::println), 1, 4, 4, 1); + root.add(new WSlider(1, 2, Axis.HORIZONTAL).setValueChangeListener(System.out::println), 1, 4, 4, 1); root.add(new WKirbSprite(), 5, 4); 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 26574dd..d981304 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 @@ -6,6 +6,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; +import org.lwjgl.glfw.GLFW; import javax.annotation.Nullable; import java.util.function.IntConsumer; @@ -15,7 +16,9 @@ import java.util.function.IntConsumer; * *

You can set two listeners on a slider: *

    - *
  • A value change listener that gets all value changes (except direct setValue calls)
  • + *
  • + * A value change listener that gets all value changes (except direct setValue calls). + *
  • *
  • * 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 @@ -29,11 +32,16 @@ public class WSlider extends WWidget { public static final Identifier TEXTURE = new Identifier("libgui", "textures/widget/slider.png"); private final int min, max; - private final int valueRange; private final Axis axis; private int value; + /** + * True if the user is currently dragging the thumb. + * Used for visuals. + */ + private boolean dragging = false; + /** * A value:coordinate ratio. Used for converting user input into values. */ @@ -57,7 +65,6 @@ public class WSlider extends WWidget { this.min = min; this.max = max; - this.valueRange = max - min; this.axis = axis; this.value = min; } @@ -70,7 +77,7 @@ public class WSlider extends WWidget { public void setSize(int x, int y) { super.setSize(x, y); int trackHeight = (axis == Axis.HORIZONTAL ? x : y) - THUMB_SIZE + 1; - valueToCoordRatio = (float) valueRange / trackHeight; + valueToCoordRatio = (float) (max - min) / trackHeight; coordToValueRatio = 1 / valueToCoordRatio; } @@ -100,23 +107,27 @@ public class WSlider extends WWidget { @Override public void onMouseDrag(int x, int y, int button) { if (isFocused()) { - int pos = (axis == Axis.VERTICAL ? (height - y) : x) - THUMB_SIZE / 2; - int rawValue = min + (int) (valueToCoordRatio * pos); - int previousValue = value; - value = MathHelper.clamp(rawValue, min, max); - if (value != previousValue && valueChangeListener != null) valueChangeListener.accept(value); + dragging = true; + moveSlider(x, y); } } @Override public void onClick(int x, int y, int button) { - onMouseDrag(x, y, button); - onMouseUp(x, y, button); + moveSlider(x, y); + } + + private void moveSlider(int x, int y) { + int pos = (axis == Axis.VERTICAL ? (height - y) : x) - THUMB_SIZE / 2; + int rawValue = min + Math.round(valueToCoordRatio * pos); + int previousValue = value; + value = MathHelper.clamp(rawValue, min, max); + if (value != previousValue && valueChangeListener != null) valueChangeListener.accept(value); } @Override public WWidget onMouseUp(int x, int y, int button) { - releaseFocus(); + dragging = false; return super.onMouseUp(x, y, button); } @@ -132,12 +143,15 @@ public class WSlider extends WWidget { backgroundPainter.paintBackground(x, y, this); } else { float px = 1 / 32f; - int thumbX, thumbY, thumbXOffset; + // thumbX/Y: thumb position in widget-space + int thumbX, thumbY; + // thumbXOffset: thumb texture x offset in pixels + int thumbXOffset; if (axis == Axis.VERTICAL) { int trackX = x + width / 2 - TRACK_WIDTH / 2; - thumbX = x + width / 2 - THUMB_SIZE / 2; - thumbY = y + height - THUMB_SIZE + 1 - (int) (coordToValueRatio * (value - min)); + thumbX = width / 2 - THUMB_SIZE / 2; + thumbY = height - THUMB_SIZE + 1 - (int) (coordToValueRatio * (value - min)); thumbXOffset = 0; ScreenDrawing.rect(TEXTURE, trackX, y + 1, TRACK_WIDTH, 1, 16*px, 0*px, 22*px, 1*px, 0xFFFFFFFF); @@ -145,8 +159,8 @@ public class WSlider extends WWidget { 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 = x + (int) (coordToValueRatio * (value - min)); - thumbY = y + height / 2 - THUMB_SIZE / 2; + thumbX = (int) (coordToValueRatio * (value - min)); + thumbY = height / 2 - THUMB_SIZE / 2; thumbXOffset = 8; ScreenDrawing.rect(TEXTURE, x, trackY, 1, TRACK_WIDTH, 16*px, 3*px, 17*px, 9*px, 0xFFFFFFFF); @@ -156,8 +170,12 @@ public class WSlider extends WWidget { // thumbState values: // 0: default, 1: dragging, 2: hovered - int thumbState = isFocused() ? 1 : (mouseX >= thumbX && mouseX <= thumbX + THUMB_SIZE && mouseY >= thumbY && mouseY <= thumbY + THUMB_SIZE ? 2 : 0); - ScreenDrawing.rect(TEXTURE, thumbX, thumbY, THUMB_SIZE, THUMB_SIZE, thumbXOffset*px, 0*px + thumbState * 8*px, (thumbXOffset + 8)*px, 8*px + thumbState * 8*px, 0xFFFFFFFF); + int thumbState = dragging ? 1 : (mouseX >= thumbX && mouseX <= thumbX + THUMB_SIZE && mouseY >= thumbY && mouseY <= thumbY + THUMB_SIZE ? 2 : 0); + ScreenDrawing.rect(TEXTURE, x + thumbX, y + thumbY, THUMB_SIZE, THUMB_SIZE, thumbXOffset*px, 0*px + thumbState * 8*px, (thumbXOffset + 8)*px, 8*px + thumbState * 8*px, 0xFFFFFFFF); + + if (thumbState == 0 && isFocused()) { + ScreenDrawing.rect(TEXTURE, x + thumbX, y + thumbY, THUMB_SIZE, THUMB_SIZE, 0*px, 24*px, 8*px, 32*px, 0xFFFFFFFF); + } } } @@ -195,4 +213,28 @@ public class WSlider extends WWidget { public void setBackgroundPainter(BackgroundPainter backgroundPainter) { this.backgroundPainter = backgroundPainter; } + + @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) { + value--; + valueChanged = true; + } else if ((ch == GLFW.GLFW_KEY_RIGHT || ch == GLFW.GLFW_KEY_UP) && 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) { + value = min; + valueChanged = true; + } else if ((ch == GLFW.GLFW_KEY_RIGHT || ch == GLFW.GLFW_KEY_UP) && value != max) { + value = max; + valueChanged = true; + } + } + + if (valueChanged && valueChangeListener != null) valueChangeListener.accept(value); + } } diff --git a/src/main/resources/assets/libgui/textures/widget/slider.png b/src/main/resources/assets/libgui/textures/widget/slider.png index d118877..ce8f434 100644 Binary files a/src/main/resources/assets/libgui/textures/widget/slider.png and b/src/main/resources/assets/libgui/textures/widget/slider.png differ -- cgit From 4c7158c99f0186a8ed7dd2fd37db4b6df4164f4c Mon Sep 17 00:00:00 2001 From: Juuxel Date: Thu, 29 Aug 2019 12:11:03 +0300 Subject: Sliders are done! --- .../cotton/gui/client/modmenu/ConfigGui.java | 19 ++++-- .../cotton/gui/widget/WAbstractSlider.java | 65 ++++++++++++++------- .../cottonmc/cotton/gui/widget/WLabeledSlider.java | 64 +++++++++++++++----- .../github/cottonmc/cotton/gui/widget/WSlider.java | 16 +---- .../assets/libgui/textures/widget/slider.png | Bin 2597 -> 2978 bytes 5 files changed, 112 insertions(+), 52 deletions(-) (limited to 'src/main/resources/assets') 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; *

    You can set two listeners on a slider: *

      *
    • - * 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). *
    • *
    • - * 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. *
    • @@ -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. * + *

      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. * - *

      You can set two listeners on a slider: - *

        - *
      • - * A value change listener that gets all value changes (except direct setValue calls). - *
      • - *
      • - * 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. - *
      • - *
      + * @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 index ce8f434..e41250e 100644 Binary files a/src/main/resources/assets/libgui/textures/widget/slider.png and b/src/main/resources/assets/libgui/textures/widget/slider.png differ -- cgit