diff --git a/.factorypath b/.factorypath new file mode 100644 index 0000000..d0b65a4 --- /dev/null +++ b/.factorypath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/main/java/org/saturnclient/saturnclient/menus/ConfigEditor.java b/src/main/java/org/saturnclient/saturnclient/menus/ConfigEditor.java index 0c97e2a..8f0783a 100644 --- a/src/main/java/org/saturnclient/saturnclient/menus/ConfigEditor.java +++ b/src/main/java/org/saturnclient/saturnclient/menus/ConfigEditor.java @@ -7,6 +7,7 @@ import org.saturnclient.saturnclient.config.Property; import org.saturnclient.ui.SaturnUi; import org.saturnclient.ui.Textures; import org.saturnclient.ui.animations.Slide; +import org.saturnclient.ui.components.SaturnInteger; import org.saturnclient.ui.components.SaturnToggle; import org.saturnclient.ui.widgets.SaturnScroll; import org.saturnclient.ui.widgets.SaturnSprite; @@ -29,14 +30,14 @@ public class ConfigEditor extends SaturnUi { int rectX = (width - rectWidth) / 2; int rectY = (height - rectHeight + 15) / 2; - draw( - new SaturnSprite(Textures.SETTINGS_BG) - .setX(rectX) - .setY(rectY) - .setWidth(rectWidth) - .setHeight(rectHeight) - .setAnimations(new Slide(1, 10)) - ); + // draw( + // new SaturnSprite(Textures.SETTINGS_BG) + // .setX(rectX) + // .setY(rectY) + // .setWidth(rectWidth) + // .setHeight(rectHeight) + // .setAnimations(new Slide(1, 10)) + // ); int tabsX = (width - 43) / 2; int tabsY = rectY - 17; @@ -100,9 +101,12 @@ public class ConfigEditor extends SaturnUi { ); configScroll.draw( - new SaturnText("" + prop.value) - .setX((rectWidth / 2) - 17) - .setY(modY) + new SaturnInteger( + (Property) prop, + (rectWidth / 2) - 17, + modY, + 40 + ) ); break; } diff --git a/src/main/java/org/saturnclient/ui/SaturnUi.java b/src/main/java/org/saturnclient/ui/SaturnUi.java index 7de6326..354667d 100644 --- a/src/main/java/org/saturnclient/ui/SaturnUi.java +++ b/src/main/java/org/saturnclient/ui/SaturnUi.java @@ -5,21 +5,23 @@ import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; - -import org.lwjgl.glfw.GLFW; - import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.MutableText; import net.minecraft.text.Style; import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import org.lwjgl.glfw.GLFW; public class SaturnUi extends Screen { - private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + + private final ScheduledExecutorService scheduler = + Executors.newSingleThreadScheduledExecutor(); public static MutableText text(String text) { - return Text.literal(text).setStyle(Style.EMPTY.withFont(Identifier.of("saturnclient:panton"))); + return Text.literal(text).setStyle( + Style.EMPTY.withFont(Identifier.of("saturnclient:panton")) + ); } public List widgets = new ArrayList<>(); @@ -31,7 +33,12 @@ public class SaturnUi extends Screen { @Override protected void init() { - scheduler.scheduleAtFixedRate(this::saturnTick, 0, 7, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate( + this::saturnTick, + 0, + 7, + TimeUnit.MILLISECONDS + ); super.init(); } @@ -43,16 +50,22 @@ public class SaturnUi extends Screen { } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { + public void render( + DrawContext context, + int mouseX, + int mouseY, + float delta + ) { renderBackground(context, mouseX, mouseY, delta); for (SaturnWidget widget : new ArrayList<>(widgets)) { - if (!widget.visible) { - continue; - } + if (!widget.visible) continue; - boolean isMouseInside = widget.x < mouseX && widget.x + widget.width > mouseX - && widget.y < mouseY && widget.y + widget.height > mouseY; + boolean isMouseInside = + widget.x < mouseX && + widget.x + widget.width > mouseX && + widget.y < mouseY && + widget.y + widget.height > mouseY; widget.render(context, isMouseInside, mouseX, mouseY); } } @@ -61,13 +74,16 @@ public class SaturnUi extends Screen { public boolean mouseClicked(double mouseX, double mouseY, int button) { if (button == 0) { for (SaturnWidget widget : new ArrayList<>(widgets)) { - if (!widget.visible) { - continue; - } + widget.focused = false; + if (!widget.visible) continue; - boolean isMouseInside = widget.x < mouseX && widget.x + widget.width > mouseX - && widget.y < mouseY && widget.y + widget.height > mouseY; + boolean isMouseInside = + widget.x < mouseX && + widget.x + widget.width > mouseX && + widget.y < mouseY && + widget.y + widget.height > mouseY; if (isMouseInside) { + widget.focused = true; widget.click((int) mouseX, (int) mouseY); } } @@ -79,9 +95,7 @@ public class SaturnUi extends Screen { @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { for (SaturnWidget widget : new ArrayList<>(widgets)) { - if (!widget.visible) { - continue; - } + if (!widget.visible && !widget.focused) continue; widget.keyPressed(keyCode, scanCode, modifiers); @@ -94,17 +108,35 @@ public class SaturnUi extends Screen { } @Override - public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + public boolean mouseScrolled( + double mouseX, + double mouseY, + double horizontalAmount, + double verticalAmount + ) { for (SaturnWidget widget : new ArrayList<>(widgets)) { - boolean isMouseInside = widget.x < mouseX && widget.x + widget.width > mouseX - && widget.y < mouseY && widget.y + widget.height > mouseY; + boolean isMouseInside = + widget.x < mouseX && + widget.x + widget.width > mouseX && + widget.y < mouseY && + widget.y + widget.height > mouseY; if (isMouseInside) { - widget.mouseScrolled((int) mouseX, (int) mouseY, horizontalAmount, verticalAmount); + widget.mouseScrolled( + (int) mouseX, + (int) mouseY, + horizontalAmount, + verticalAmount + ); } } - return super.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + return super.mouseScrolled( + mouseX, + mouseY, + horizontalAmount, + verticalAmount + ); } private char getCharFromKey(int keyCode, int modifiers) { @@ -112,12 +144,16 @@ public class SaturnUi extends Screen { // A-Z if (keyCode >= GLFW.GLFW_KEY_A && keyCode <= GLFW.GLFW_KEY_Z) { - return (char) (shift ? 'A' + (keyCode - GLFW.GLFW_KEY_A) : 'a' + (keyCode - GLFW.GLFW_KEY_A)); + return (char) (shift + ? 'A' + (keyCode - GLFW.GLFW_KEY_A) + : 'a' + (keyCode - GLFW.GLFW_KEY_A)); } // 0-9 if (keyCode >= GLFW.GLFW_KEY_0 && keyCode <= GLFW.GLFW_KEY_9) { - return shift ? ")!@#$%^&*(".charAt(keyCode - GLFW.GLFW_KEY_0) : (char) ('0' + (keyCode - GLFW.GLFW_KEY_0)); + return shift + ? ")!@#$%^&*(".charAt(keyCode - GLFW.GLFW_KEY_0) + : (char) ('0' + (keyCode - GLFW.GLFW_KEY_0)); } // Special characters @@ -143,7 +179,10 @@ public class SaturnUi extends Screen { for (SaturnWidget widget : widgets) { if (widget.visible && widget.animations != null) { for (SaturnAnimation animation : widget.animations) { - if (animation != null && tick - animation.lastTick == animation.delay) { + if ( + animation != null && + tick - animation.lastTick == animation.delay + ) { if (animation.run(widget, tick)) { animation = null; } else { diff --git a/src/main/java/org/saturnclient/ui/SaturnWidget.java b/src/main/java/org/saturnclient/ui/SaturnWidget.java index efaf8f1..a5ba0b2 100644 --- a/src/main/java/org/saturnclient/ui/SaturnWidget.java +++ b/src/main/java/org/saturnclient/ui/SaturnWidget.java @@ -11,6 +11,7 @@ public class SaturnWidget { public float alpha = 1.0f; public SaturnAnimation[] animations = null; public boolean visible = true; + public boolean focused = false; public void init() {} diff --git a/src/main/java/org/saturnclient/ui/components/SaturnInteger.java b/src/main/java/org/saturnclient/ui/components/SaturnInteger.java new file mode 100644 index 0000000..34c968e --- /dev/null +++ b/src/main/java/org/saturnclient/ui/components/SaturnInteger.java @@ -0,0 +1,185 @@ +package org.saturnclient.ui.components; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.RenderLayer; +import org.lwjgl.glfw.GLFW; +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.ui.SaturnUi; +import org.saturnclient.ui.SaturnWidget; +import org.saturnclient.ui.Textures; + +public class SaturnInteger extends SaturnWidget { + + String text = ""; + public Property prop; + public int cursorPosition = 0; + private TextRenderer textRenderer = MinecraftClient.getInstance() + .textRenderer; + + public SaturnInteger(Property prop, int x, int y, int width) { + this.x = x; + this.y = y; + this.width = width; + this.prop = prop; + this.text = String.valueOf(prop.value); + this.height = textRenderer.fontHeight + 4; + } + + @Override + public void click(int mouseX, int mouseY) { + int scrollOffset = getScrollOffset(); + String visibleText = text.substring(scrollOffset); + + int newCursorPos = scrollOffset; + int textWidth = 0; + + for (int i = 0; i < visibleText.length(); i++) { + textWidth = textRenderer.getWidth(visibleText.substring(0, i + 1)); + + if (textWidth > (mouseX - x)) { + break; + } + + newCursorPos++; + } + + cursorPosition = newCursorPos; + } + + @Override + public void charTyped(char chr) { + SaturnClient.LOGGER.info("current digit: " + chr); + if (Character.isDigit(chr) && text.length() < 10) { + if (text.equals("0") && cursorPosition == 1) { + text = "" + chr; + } else { + text = + text.substring(0, cursorPosition) + + chr + + text.substring(cursorPosition); + + prop.value = text.isEmpty() ? 0 : Integer.parseInt(text); + + cursorPosition++; + } + } + } + + @Override + public void keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == GLFW.GLFW_KEY_BACKSPACE) { + if (cursorPosition > 0) { + text = + text.substring(0, cursorPosition - 1) + + text.substring(cursorPosition); + cursorPosition--; + if (text.length() == 0) { + text = "0"; + cursorPosition = 1; + } + prop.value = Integer.parseInt(text); + } + } else if (keyCode == GLFW.GLFW_KEY_LEFT) { + if (cursorPosition > 0) { + cursorPosition--; + } + } else if (keyCode == GLFW.GLFW_KEY_RIGHT) { + if (cursorPosition < text.length()) { + cursorPosition++; + } + } + } + + @Override + public void render( + DrawContext context, + boolean hovering, + int mouseX, + int mouseY + ) { + context.drawGuiTexture( + RenderLayer::getGuiTextured, + Textures.BUTTON, + this.x, + this.y, + this.width, + this.height, + SaturnClient.getWhite(this.alpha) + ); + + int scrollOffset = getScrollOffset(); + String visibleText = getVisibleText(scrollOffset); + + int textColor = focused ? 0xFFFFFF : 0xAAAAAA; + context.drawText( + textRenderer, + SaturnUi.text(visibleText), + x + 2, + y + 2, + textColor, + false + ); + + if (focused) { + int cursorX = + x + + 2 + + textRenderer.getWidth( + SaturnUi.text( + visibleText.substring(0, cursorPosition - scrollOffset) + ) + ); + context.fill( + cursorX, + y + 2, + cursorX + 1, + y + textRenderer.fontHeight + 4, + 0xFFFFFFFF + ); + } + } + + public void clearText() { + text = "0"; + cursorPosition = 1; + prop.value = 0; + } + + private int getScrollOffset() { + if (text.isEmpty()) { + return 0; + } + + int offset = 0; + int maxWidth = width - 4; // Available width for text + while (offset < cursorPosition) { // Ensure cursor remains visible + String visibleText = text.substring(offset, cursorPosition); + if (textRenderer.getWidth(SaturnUi.text(visibleText)) > maxWidth) { + offset++; + } else { + break; + } + } + return offset; + } + + private String getVisibleText(int scrollOffset) { + String visibleText = text.substring(scrollOffset); + + // Ensure text does not overflow past the available width + for (int i = 1; i <= visibleText.length(); i++) { + if ( + textRenderer.getWidth( + SaturnUi.text(visibleText.substring(0, i)) + ) > + width - 4 + ) { + return visibleText.substring(0, i - 1); // Trim overflow + } + } + return visibleText; + } +} diff --git a/src/main/java/org/saturnclient/ui/widgets/SaturnScroll.java b/src/main/java/org/saturnclient/ui/widgets/SaturnScroll.java index ae5a550..5376135 100644 --- a/src/main/java/org/saturnclient/ui/widgets/SaturnScroll.java +++ b/src/main/java/org/saturnclient/ui/widgets/SaturnScroll.java @@ -2,19 +2,22 @@ package org.saturnclient.ui.widgets; import java.util.ArrayList; import java.util.List; - +import net.minecraft.client.gui.DrawContext; import org.saturnclient.ui.SaturnWidget; -import net.minecraft.client.gui.DrawContext; - public class SaturnScroll extends SaturnWidget { + private int scroll = 0; private int maxScroll = 0; private List children = new ArrayList<>(); @Override - public void mouseScrolled(int mouseX, int mouseY, double horizontalAmount, - double verticalAmount) { + public void mouseScrolled( + int mouseX, + int mouseY, + double horizontalAmount, + double verticalAmount + ) { if (scroll - verticalAmount <= 0) { scroll = 0; } else if (scroll - verticalAmount >= maxScroll) { @@ -25,18 +28,28 @@ public class SaturnScroll extends SaturnWidget { } @Override - public void render(DrawContext context, boolean hovering, int mouseX, int mouseY) { + public void render( + DrawContext context, + boolean hovering, + int mouseX, + int mouseY + ) { context.enableScissor(x, y, x + width, y + height); for (SaturnWidget child : children) { + if (!child.visible) continue; + int xx = child.x; int yy = child.y; child.x += x; child.y += y - scroll; - boolean isMouseInside = child.x < mouseX && child.x + child.width > mouseX - && child.y < mouseY && child.y + child.height > mouseY; + boolean isMouseInside = + child.x < mouseX && + child.x + child.width > mouseX && + child.y < mouseY && + child.y + child.height > mouseY; if (child.y < y + height && child.y + child.height > y) { child.render(context, isMouseInside, mouseX, mouseY); @@ -49,21 +62,6 @@ public class SaturnScroll extends SaturnWidget { context.disableScissor(); } - @Override - public void click(int mouseX, int mouseY) { - mouseX = mouseX - x; - mouseY = mouseY - y; - for (SaturnWidget child : children) { - boolean isMouseInside = child.x < mouseX && child.x + child.width > mouseX - && child.y < mouseY && child.y + child.height > mouseY; - - if (isMouseInside) { - child.click(mouseX, mouseY); - return; - } - } - } - @Override public void init() { if (isScrollable()) { @@ -88,4 +86,88 @@ public class SaturnScroll extends SaturnWidget { } return false; } + + @Override + public void keyPressed(int keyCode, int scanCode, int modifiers) { + System.out.println( + "[SaturnScroll] Key Pressed: keyCode=" + + keyCode + + ", scanCode=" + + scanCode + + ", modifiers=" + + modifiers + ); + + for (SaturnWidget child : children) { + if (!child.visible || !child.focused) { + System.out.println( + "[SaturnScroll] Skipping child " + + child + + " (Not visible or focused)" + ); + continue; + } + + System.out.println( + "[SaturnScroll] Passing key event to child: " + child + ); + child.keyPressed(keyCode, scanCode, modifiers); + break; + } + } + + @Override + public void charTyped(char typedChar) { + System.out.println("[SaturnScroll] Char Typed: '" + typedChar + "'"); + + for (SaturnWidget child : children) { + if (!child.visible || !child.focused) { + System.out.println( + "[SaturnScroll] Skipping child " + + child + + " (Not visible or focused)" + ); + continue; + } + + System.out.println( + "[SaturnScroll] Passing char event to child: " + child + ); + child.charTyped(typedChar); + break; + } + } + + @Override + public void click(int mouseX, int mouseY) { + System.out.println( + "[SaturnScroll] Click at: x=" + mouseX + ", y=" + mouseY + ); + + mouseX -= x; + mouseY -= (y - scroll); + + for (SaturnWidget widget : children) { + widget.focused = false; + if (!widget.visible) { + System.out.println( + "[SaturnScroll] Skipping hidden child: " + widget + ); + continue; + } + + boolean isMouseInside = + widget.x < mouseX && + widget.x + widget.width > mouseX && + widget.y < mouseY && + widget.y + widget.height > mouseY; + + if (isMouseInside) { + System.out.println("[SaturnScroll] Child clicked: " + widget); + widget.focused = true; + widget.click(mouseX, mouseY); + break; + } + } + } }