color picker
This commit is contained in:
@@ -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<Element> 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);
|
||||
|
||||
@@ -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<Integer> 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<Integer> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<Float> prop;
|
||||
public int cursorPosition = 0;
|
||||
private TextRenderer textRenderer = SaturnClient.client.textRenderer;
|
||||
|
||||
public FloatInput(Property<Float> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Integer> prop;
|
||||
public SaturnScreen screen;
|
||||
|
||||
public HexInput(Property<Integer> 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<Float>(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)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user