diff --git a/src/main/java/org/saturnclient/ui2/components/ElementRenderer.java b/src/main/java/org/saturnclient/ui2/components/ElementRenderer.java index abd905c..d7b9a02 100644 --- a/src/main/java/org/saturnclient/ui2/components/ElementRenderer.java +++ b/src/main/java/org/saturnclient/ui2/components/ElementRenderer.java @@ -44,7 +44,7 @@ public class ElementRenderer { int adjustedMouseX = (int) mouseX - element.x; int adjustedMouseY = (int) mouseY - element.y; - if (Utils.isHovering(adjustedMouseX, adjustedMouseY, element.width, element.height, element.scale)) { + if (element.opacity > 0 && Utils.isHovering(adjustedMouseX, adjustedMouseY, element.width, element.height, element.scale)) { element.focused = true; element.click((int) (adjustedMouseX * element.scale), (int) (adjustedMouseY * element.scale)); } @@ -71,7 +71,7 @@ public class ElementRenderer { public static void keyPressed(List elements, int keyCode, int scanCode, int modifiers) { for (Element element : new ArrayList<>(elements)) { - if (element.focused) { + if (element.focused && element.opacity > 0) { element.keyPressed(keyCode, scanCode, modifiers); char typedChar = Utils.getCharFromKey(keyCode, modifiers); diff --git a/src/main/java/org/saturnclient/ui2/components/dialog/ColorDialog.java b/src/main/java/org/saturnclient/ui2/components/dialog/ColorDialog.java new file mode 100644 index 0000000..f478943 --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/components/dialog/ColorDialog.java @@ -0,0 +1,167 @@ +package org.saturnclient.ui2.components.dialog; + +import java.awt.Color; + +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.ui2.SaturnScreen; + +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; + +public class ColorDialog extends Screen { + private Property prop; + private SaturnScreen parent; + private static final int PICKER_WIDTH = 200; + private static final int PICKER_HEIGHT = 200; + private static final int SLIDER_WIDTH = 200; + private static final int SLIDER_HEIGHT = 10; + + private int selectedX = 0; + private int selectedY = 0; + + private float opacity = 1.0f; + private boolean dragging = false; + + public ColorDialog(Property prop , SaturnScreen parent) { + super(Text.literal("Color Dialog")); + this.prop = prop; + this.parent = parent; + + int alpha = (prop.value >> 24) & 0xFF; + if (alpha == 0) alpha = 255; // fallback if no alpha specified + this.opacity = alpha / 255.0f; + } + + @Override + public void close() { + SaturnClient.client.setScreen(parent); + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + renderBackground(context, mouseX, mouseY, delta); + + int xStart = (width - PICKER_WIDTH) / 2; + int yStart = (height - PICKER_HEIGHT) / 2; + + // Draw the HSV hue/saturation square (brightness fixed at 1) + for (int x = 0; x < PICKER_WIDTH; x++) { + for (int y = 0; y < PICKER_HEIGHT; y++) { + float hue = x / (float) PICKER_WIDTH; + float saturation = y / (float) PICKER_HEIGHT; + int color = Color.HSBtoRGB(hue, saturation, 1.0f); + context.fill(xStart + x, yStart + y, xStart + x + 1, yStart + y + 1, 0xFF000000 | color); + } + } + + int x = (xStart + selectedX) - 4; + int y = (yStart + selectedY) - 4; + context.fill(x, y, x+8, y+8, 0xFF000000 | prop.value); + context.drawBorder(x, y, 8, 8, 0xFFffffff); + + renderSlider(context, mouseX, mouseY, delta); + } + + public void renderSlider(DrawContext context, int mouseX, int mouseY, float delta) { + int xStart = (width - SLIDER_WIDTH) / 2; + int yStart = (height - SLIDER_HEIGHT - PICKER_HEIGHT) / 2 - 10; + + // Draw slider background (left = transparent, right = white) + for (int x = 0; x < SLIDER_WIDTH; x++) { + float localOpacity = x / (float) SLIDER_WIDTH; + int alpha = (int)(localOpacity * 255) & 0xFF; + int color = (alpha << 24) | (prop.value & 0xFFFFFF); + context.fill(xStart + x, yStart, xStart + x + 1, yStart + SLIDER_HEIGHT, color); + } + + // Draw current value as a marker (thin black line) + int knobX = xStart + (int)(opacity * SLIDER_WIDTH); + context.fill(knobX - 1, yStart - 2, knobX + 1, yStart + SLIDER_HEIGHT + 2, 0xFF000000); + + // Draw opacity text + // context.drawText(textRenderer, String.format("Opacity: %.2f", opacity), xStart, yStart - 15, 0xFFFFFF, false); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + int xStart = (width - PICKER_WIDTH) / 2; + int yStart = (height - PICKER_HEIGHT) / 2; + + int relX = (int) mouseX - xStart; + int relY = (int) mouseY - yStart; + + if (relX >= 0 && relX < PICKER_WIDTH && relY >= 0 && relY < PICKER_HEIGHT) { + float hue = relX / (float) PICKER_WIDTH; + float saturation = relY / (float) PICKER_HEIGHT; + prop.value = Color.HSBtoRGB(hue, saturation, 1.0f); + + int alpha = (int)(opacity * 255) & 0xFF; + prop.value = (alpha << 24) | (prop.value & 0xFFFFFF); + + selectedX = relX; + selectedY = relY; + + return true; + } else if (isInSlider(mouseX, mouseY)) { + updateOpacity(mouseX); + dragging = true; + return true; + } + + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + dragging = false; + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) { + if (dragging) { + updateOpacity(mouseX); + return true; + } else { + int xStart = (width - PICKER_WIDTH) / 2; + int yStart = (height - PICKER_HEIGHT) / 2; + + int relX = (int) mouseX - xStart; + int relY = (int) mouseY - yStart; + + if (relX >= 0 && relX < PICKER_WIDTH && relY >= 0 && relY < PICKER_HEIGHT) { + float hue = relX / (float) PICKER_WIDTH; + float saturation = relY / (float) PICKER_HEIGHT; + prop.value = Color.HSBtoRGB(hue, saturation, 1.0f); + + int alpha = (int)(opacity * 255) & 0xFF; + prop.value = (alpha << 24) | (prop.value & 0xFFFFFF); + + selectedX = relX; + selectedY = relY; + + return true; + } + } + + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY); + } + + private boolean isInSlider(double mouseX, double mouseY) { + int xStart = (width - SLIDER_WIDTH) / 2; + int yStart = (height - SLIDER_HEIGHT - PICKER_HEIGHT) / 2 - 10; + return mouseX >= xStart && mouseX <= xStart + SLIDER_WIDTH && + mouseY >= yStart && mouseY <= yStart + SLIDER_HEIGHT; + } + + private void updateOpacity(double mouseX) { + int xStart = (width - SLIDER_WIDTH) / 2; + float newOpacity = (float)((mouseX - xStart) / SLIDER_WIDTH); + opacity = Math.max(0.0f, Math.min(1.0f, newOpacity)); + + int alpha = (int)(opacity * 255) & 0xFF; + prop.value = (alpha << 24) | (prop.value & 0xFFFFFF); + } +} diff --git a/src/main/java/org/saturnclient/ui2/components/inputs/FloatInput.java b/src/main/java/org/saturnclient/ui2/components/inputs/FloatInput.java index 7c9c03f..7023172 100644 --- a/src/main/java/org/saturnclient/ui2/components/inputs/FloatInput.java +++ b/src/main/java/org/saturnclient/ui2/components/inputs/FloatInput.java @@ -1,22 +1,11 @@ package org.saturnclient.ui2.components.inputs; -import org.lwjgl.glfw.GLFW; -import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.config.ConfigManager; import org.saturnclient.saturnclient.config.Property; -import org.saturnclient.ui.SaturnUi; -import org.saturnclient.ui2.Element; -import org.saturnclient.ui2.ElementContext; -import org.saturnclient.ui2.RenderScope; import org.saturnclient.ui2.resources.Fonts; -import net.minecraft.client.font.TextRenderer; - -public class FloatInput extends Element { - String text = ""; +public class FloatInput extends Input { public Property prop; - public int cursorPosition = 0; - private TextRenderer textRenderer = SaturnClient.client.textRenderer; public FloatInput(Property prop) { this.width = 120; @@ -25,27 +14,6 @@ public class FloatInput extends Element { this.text = String.valueOf(prop.value); } - @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) { - break; - } - - newCursorPos++; - } - - cursorPosition = newCursorPos; - } - @Override public void charTyped(char chr) { if ((Character.isDigit(chr) || chr == '.') && text.length() < 10) { @@ -65,83 +33,21 @@ public class FloatInput extends Element { } @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 = Float.parseFloat(text); - ConfigManager.save(); - } - } else if (keyCode == GLFW.GLFW_KEY_LEFT) { - if (cursorPosition > 0) { - cursorPosition--; - } - } else if (keyCode == GLFW.GLFW_KEY_RIGHT) { - if (cursorPosition < text.length()) { - cursorPosition++; - } + public void backspace() { + if (text.length() == 0) { + text = "0"; + cursorPosition = 1; } + prop.value = Float.parseFloat(text); + ConfigManager.save(); } @Override - public void render(RenderScope renderScope, ElementContext ctx) { + public void checkReset() { if (prop.isReset) { this.text = String.valueOf(prop.value); this.cursorPosition = 0; prop.isReset = false; } - - renderScope.drawRoundedRectangle(0, 0, width, height, 10, 0xFF000000); - - int scrollOffset = getScrollOffset(); - String visibleText = getVisibleText(scrollOffset); - int textColor = focused ? 0xFFFFFF : 0xAAAAAA; - renderScope.drawText(visibleText, 2, 2, false, textColor); - - if (focused) { - int cursorX = 2 + - textRenderer.getWidth( - SaturnUi.text( - visibleText.substring(0, cursorPosition - scrollOffset))); - - renderScope.drawRect(cursorX, 2, 1, height - 1, 0xFFFFFFFF); - } - } - - 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/ui2/components/inputs/HexInput.java b/src/main/java/org/saturnclient/ui2/components/inputs/HexInput.java new file mode 100644 index 0000000..fc3dd0e --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/components/inputs/HexInput.java @@ -0,0 +1,33 @@ +package org.saturnclient.ui2.components.inputs; + +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.config.Property; +import org.saturnclient.ui2.Element; +import org.saturnclient.ui2.ElementContext; +import org.saturnclient.ui2.RenderScope; +import org.saturnclient.ui2.SaturnScreen; +import org.saturnclient.ui2.components.dialog.ColorDialog; +import org.saturnclient.ui2.resources.Fonts; + +public class HexInput extends Element { + public Property prop; + public SaturnScreen screen; + + public HexInput(Property prop, SaturnScreen screen) { + this.width = 50; + this.prop = prop; + this.height = Fonts.getHeight() + 8; + this.scale = 0.8f; + this.screen = screen; + } + + @Override + public void click(int mouseX, int mouseY) { + SaturnClient.client.setScreen(new ColorDialog(prop, screen)); + } + + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + renderScope.drawRoundedRectangle(0, 0, width, height, 10, prop.value); + } +} diff --git a/src/main/java/org/saturnclient/ui2/components/inputs/Input.java b/src/main/java/org/saturnclient/ui2/components/inputs/Input.java new file mode 100644 index 0000000..da7bc5f --- /dev/null +++ b/src/main/java/org/saturnclient/ui2/components/inputs/Input.java @@ -0,0 +1,111 @@ +package org.saturnclient.ui2.components.inputs; + +import org.lwjgl.glfw.GLFW; +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.ui.SaturnUi; +import org.saturnclient.ui2.Element; +import org.saturnclient.ui2.ElementContext; +import org.saturnclient.ui2.RenderScope; + +public abstract class Input extends Element { + String text = ""; + public int cursorPosition = 0; + public abstract void checkReset(); + public abstract void backspace(); + public boolean validateBackspace() { + return true; + } + + @Override + public void keyPressed(int keyCode, int scanCode, int modifiers) { + if (keyCode == GLFW.GLFW_KEY_BACKSPACE) { + if (cursorPosition > 0 && validateBackspace()) { + text = text.substring(0, cursorPosition - 1) + + text.substring(cursorPosition); + cursorPosition--; + backspace(); + } + } 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 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 = SaturnClient.client.textRenderer.getWidth(visibleText.substring(0, i + 1)); + + if (textWidth > mouseX) { + break; + } + + newCursorPos++; + } + + cursorPosition = newCursorPos; + } + + @Override + public void render(RenderScope renderScope, ElementContext ctx) { + checkReset(); + + renderScope.drawRoundedRectangle(0, 0, width, height, 10, 0xFF000000); + + int scrollOffset = getScrollOffset(); + String visibleText = getVisibleText(scrollOffset); + int textColor = focused ? 0xFFFFFF : 0xAAAAAA; + renderScope.drawText(visibleText, 2, 2, false, textColor); + + if (focused) { + int cursorX = 2 + + SaturnClient.client.textRenderer.getWidth( + SaturnUi.text( + visibleText.substring(0, cursorPosition - scrollOffset))); + + renderScope.drawRect(cursorX, 2, 1, height - 1, 0xFFFFFFFF); + } + } + + protected 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 (SaturnClient.client.textRenderer.getWidth(SaturnUi.text(visibleText)) > maxWidth) { + offset++; + } else { + break; + } + } + return offset; + } + + protected 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 (SaturnClient.client.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/ui2/screens/TitleMenu.java b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java index bd94827..48c9164 100644 --- a/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java +++ b/src/main/java/org/saturnclient/ui2/screens/TitleMenu.java @@ -2,13 +2,11 @@ package org.saturnclient.ui2.screens; import org.saturnclient.saturnclient.SaturnClient; import org.saturnclient.saturnclient.SaturnClientConfig; -import org.saturnclient.saturnclient.config.Property; import org.saturnclient.saturnclient.menus.HudEditor; import org.saturnclient.ui.Textures; import org.saturnclient.ui2.SaturnScreen; import org.saturnclient.ui2.anim.Fade; import org.saturnclient.ui2.anim.SlideY; -import org.saturnclient.ui2.components.inputs.FloatInput; import org.saturnclient.ui2.elements.Button; import org.saturnclient.ui2.elements.ImageTexture; import org.saturnclient.ui2.elements.TextureButton; @@ -27,8 +25,6 @@ public class TitleMenu extends SaturnScreen { public void ui() { backgroundBlur = 0; - draw(new FloatInput(new Property(1.0f))); - draw(new ImageTexture(Textures.LOGO_TEXT).dimensions(98, 10).centerOffset(width, height, 0, -36).animation(new Fade(700))); draw(new ImageTexture(SaturnClientConfig.getLogo()).dimensions(98, 98).centerOffset(width, height, 0, -82).animation(new SlideY(700, -40)));