package de.fullrisk.citrusDev.UIHelper; import de.fullrisk.citrusDev.Config; import de.fullrisk.citrusDev.UI.Module_Coords; import de.fullrisk.citrusDev.UI.Module_FPS; import de.fullrisk.citrusDev.UI.Module_KeyStrokes; import io.wispforest.owo.ui.container.FlowLayout; import io.wispforest.owo.ui.core.Positioning; import net.minecraft.client.Minecraft; import org.lwjgl.BufferUtils; import org.lwjgl.glfw.GLFW; import java.nio.DoubleBuffer; import java.util.function.BooleanSupplier; import java.util.function.IntConsumer; import java.util.function.IntSupplier; import java.util.function.Supplier; public class DraggableHud { private static boolean editMode = false; private static boolean dragging = false; private static FlowLayout dragTarget = null; private static double dragStartMouseX, dragStartMouseY; private static int dragModuleStartX, dragModuleStartY; private static ModuleDragConfig currentConfig; private static boolean wasLeftDown = false; private static boolean cursorEnabled = false; private static final DoubleBuffer cursorXBuf = BufferUtils.createDoubleBuffer(1); private static final DoubleBuffer cursorYBuf = BufferUtils.createDoubleBuffer(1); public static boolean isEditMode() { return editMode; } public static void setEditMode(boolean enabled) { editMode = enabled; if (!enabled) { wasLeftDown = false; } } public static void tick() { Minecraft mc = Minecraft.getInstance(); if (mc.getWindow() == null) return; long window = mc.getWindow().handle(); if (mc.screen != null) { if (dragging) endDrag(); if (editMode) { editMode = false; disableCursor(window); } wasLeftDown = false; return; } if (editMode && GLFW.glfwGetKey(window, GLFW.GLFW_KEY_ESCAPE) == GLFW.GLFW_PRESS) { editMode = false; disableCursor(window); wasLeftDown = false; return; } boolean leftDown = GLFW.glfwGetMouseButton(window, GLFW.GLFW_MOUSE_BUTTON_LEFT) == GLFW.GLFW_PRESS; if (editMode && !cursorEnabled) { int ww = mc.getWindow().getWidth(); int wh = mc.getWindow().getHeight(); GLFW.glfwSetCursorPos(window, ww / 2.0, wh / 2.0); GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL); cursorEnabled = true; } else if (!editMode && cursorEnabled) { disableCursor(window); wasLeftDown = leftDown; return; } if (cursorEnabled) { cursorXBuf.clear(); cursorYBuf.clear(); GLFW.glfwGetCursorPos(window, cursorXBuf, cursorYBuf); double mouseX = cursorXBuf.get(0); double mouseY = cursorYBuf.get(0); if (leftDown && !wasLeftDown) { tryStartDrag(mouseX, mouseY); } else if (dragging && leftDown) { updateDrag(mouseX, mouseY); } else if (dragging && !leftDown) { endDrag(); } } wasLeftDown = leftDown; } private static void disableCursor(long window) { if (cursorEnabled) { GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); cursorEnabled = false; } } private static void tryStartDrag(double mouseX, double mouseY) { Minecraft mc = Minecraft.getInstance(); var win = mc.getWindow(); int sw = win.getWidth(); int sh = win.getHeight(); int gw = win.getGuiScaledWidth(); int gh = win.getGuiScaledHeight(); double guiMouseX = mouseX * gw / sw; double guiMouseY = mouseY * gh / sh; for (ModuleDragConfig mod : getModules()) { FlowLayout container = mod.containerGetter.get(); if (container == null || !mod.isVisible.getAsBoolean()) continue; int modX = mod.getX.getAsInt(); int modY = mod.getY.getAsInt(); int left = (int) ((gw - mod.hitW) * modX / 100.0); int top = (int) ((gh - mod.hitH) * modY / 100.0); if (guiMouseX >= left && guiMouseX <= left + mod.hitW && guiMouseY >= top && guiMouseY <= top + mod.hitH) { dragging = true; dragTarget = container; dragStartMouseX = mouseX; dragStartMouseY = mouseY; dragModuleStartX = modX; dragModuleStartY = modY; currentConfig = mod; return; } } } private static void updateDrag(double mouseX, double mouseY) { if (!dragging || dragTarget == null || currentConfig == null) return; Minecraft mc = Minecraft.getInstance(); var win = mc.getWindow(); int sw = win.getWidth(); int sh = win.getHeight(); int gw = win.getGuiScaledWidth(); int gh = win.getGuiScaledHeight(); double deltaX = mouseX - dragStartMouseX; double deltaY = mouseY - dragStartMouseY; double guiDeltaX = deltaX * gw / sw; double guiDeltaY = deltaY * gh / sh; int newX = dragModuleStartX + (int) (guiDeltaX / (gw - currentConfig.hitW) * 100); int newY = dragModuleStartY + (int) (guiDeltaY / (gh - currentConfig.hitH) * 100); newX = Math.max(0, Math.min(100, newX)); newY = Math.max(0, Math.min(100, newY)); dragTarget.positioning(Positioning.relative(newX, newY)); currentConfig.setX.accept(newX); currentConfig.setY.accept(newY); } private static void endDrag() { if (currentConfig != null) { Config.get().save(); } dragging = false; dragTarget = null; currentConfig = null; } private static ModuleDragConfig[] getModules() { Config c = Config.get(); return new ModuleDragConfig[]{ new ModuleDragConfig( Module_Coords::getCoordinates, 120, 50, () -> c.coordsX, v -> c.coordsX = v, () -> c.coordsY, v -> c.coordsY = v, Module_Coords::isEnabled ), new ModuleDragConfig( Module_KeyStrokes::getKeyContainer, c.keySize * 3 + 20, c.keySize * 2 + 20, () -> c.keyX, v -> c.keyX = v, () -> c.keyY, v -> c.keyY = v, Module_KeyStrokes::isEnabled ), new ModuleDragConfig( Module_FPS::getFpsContainer, 100, 30, () -> c.fpsX, v -> c.fpsX = v, () -> c.fpsY, v -> c.fpsY = v, Module_FPS::isEnabled ) }; } private static class ModuleDragConfig { Supplier containerGetter; int hitW, hitH; IntSupplier getX; IntConsumer setX; IntSupplier getY; IntConsumer setY; BooleanSupplier isVisible; ModuleDragConfig(Supplier containerGetter, int hitW, int hitH, IntSupplier getX, IntConsumer setX, IntSupplier getY, IntConsumer setY, BooleanSupplier isVisible) { this.containerGetter = containerGetter; this.hitW = hitW; this.hitH = hitH; this.getX = getX; this.setX = setX; this.getY = getY; this.setY = setY; this.isVisible = isVisible; } } }