Files
Client/src/main/java/de/fullrisk/citrusDev/UIHelper/DraggableHud.java
T
2026-07-11 19:06:59 +02:00

222 lines
7.6 KiB
Java

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<FlowLayout> containerGetter;
int hitW, hitH;
IntSupplier getX;
IntConsumer setX;
IntSupplier getY;
IntConsumer setY;
BooleanSupplier isVisible;
ModuleDragConfig(Supplier<FlowLayout> 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;
}
}
}