Drag UI
This commit is contained in:
@@ -56,6 +56,10 @@ public class Module_Coords {
|
|||||||
coordinates.padding(Insets.of(padding));
|
coordinates.padding(Insets.of(padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FlowLayout getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "coords_display"), () -> {
|
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "coords_display"), () -> {
|
||||||
if (coordinates == null) {
|
if (coordinates == null) {
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ public class Module_FPS {
|
|||||||
fpsContainer.padding(Insets.of(padding));
|
fpsContainer.padding(Insets.of(padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FlowLayout getFpsContainer() {
|
||||||
|
return fpsContainer;
|
||||||
|
}
|
||||||
|
|
||||||
public static void register() {
|
public static void register() {
|
||||||
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "fps_display"), () -> {
|
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "fps_display"), () -> {
|
||||||
if (fpsContainer == null) {
|
if (fpsContainer == null) {
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ public class Module_KeyStrokes {
|
|||||||
static boolean toggle = CONFIG.keyEnabled;
|
static boolean toggle = CONFIG.keyEnabled;
|
||||||
private static boolean shown = false;
|
private static boolean shown = false;
|
||||||
|
|
||||||
|
public static FlowLayout getKeyContainer() {
|
||||||
|
return keyContainer;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isEnabled() {
|
public static boolean isEnabled() {
|
||||||
return toggle;
|
return toggle;
|
||||||
}
|
}
|
||||||
@@ -61,7 +65,7 @@ public class Module_KeyStrokes {
|
|||||||
public static void register() {
|
public static void register() {
|
||||||
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "keystrokes_display"), () -> {
|
Hud.add(Identifier.fromNamespaceAndPath("citrus-dev", "keystrokes_display"), () -> {
|
||||||
if (keyContainer == null) {
|
if (keyContainer == null) {
|
||||||
keySize = CONFIG.keySize > 0 ? CONFIG.keySize : 16; // load saved size, fallback to default
|
keySize = CONFIG.keySize > 0 ? CONFIG.keySize : 16;
|
||||||
|
|
||||||
wLabel = new ScalableLabel(Component.literal("W"));
|
wLabel = new ScalableLabel(Component.literal("W"));
|
||||||
aLabel = new ScalableLabel(Component.literal("A"));
|
aLabel = new ScalableLabel(Component.literal("A"));
|
||||||
|
|||||||
@@ -321,7 +321,26 @@ public class MyScreen extends BaseOwoScreen<FlowLayout> {
|
|||||||
|
|
||||||
|
|
||||||
private void buildSettingsPanel(FlowLayout content) {
|
private void buildSettingsPanel(FlowLayout content) {
|
||||||
content.child(UIComponents.label(Component.literal("Settings")));
|
FlowLayout rowsContainer = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content());
|
||||||
|
rowsContainer.gap(2);
|
||||||
|
rowsContainer.verticalAlignment(VerticalAlignment.TOP);
|
||||||
|
rowsContainer.horizontalAlignment(HorizontalAlignment.LEFT);
|
||||||
|
rowsContainer.padding(Insets.of(0));
|
||||||
|
|
||||||
|
FlowLayout editButton = SettingsControls.makeTextButton(GLASS_PANEL, "Edit Positions", () -> {
|
||||||
|
DraggableHud.setEditMode(true);
|
||||||
|
Minecraft.getInstance().setScreen(null);
|
||||||
|
});
|
||||||
|
editButton.horizontalSizing(Sizing.fixed(CONTENT_WIDTH - 8));
|
||||||
|
rowsContainer.child(editButton);
|
||||||
|
|
||||||
|
FlowLayout hintRow = UIContainers.verticalFlow(Sizing.fixed(CONTENT_WIDTH - 8), Sizing.content());
|
||||||
|
hintRow.padding(Insets.of(4, 0, 0, 0));
|
||||||
|
hintRow.child(UIComponents.label(Component.literal("Drag HUD modules to reposition. Press ESC to stop."))
|
||||||
|
.color(Color.ofRgb(0x797b86)));
|
||||||
|
rowsContainer.child(hintRow);
|
||||||
|
|
||||||
|
content.child(rowsContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openModuleSettings(String title, List<SettingRow> rows) {
|
private void openModuleSettings(String title, List<SettingRow> rows) {
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package de.fullrisk.citrusDev.client;
|
|||||||
|
|
||||||
import de.fullrisk.citrusDev.Config;
|
import de.fullrisk.citrusDev.Config;
|
||||||
import de.fullrisk.citrusDev.UI.*;
|
import de.fullrisk.citrusDev.UI.*;
|
||||||
|
import de.fullrisk.citrusDev.UIHelper.DraggableHud;
|
||||||
import io.wispforest.owo.ui.hud.Hud;
|
import io.wispforest.owo.ui.hud.Hud;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
@@ -31,13 +32,17 @@ public class CitrusDevClient implements ClientModInitializer {
|
|||||||
));
|
));
|
||||||
|
|
||||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||||
|
/*
|
||||||
if (client.player != null && !client.isPaused()) {
|
if (client.player != null && !client.isPaused()) {
|
||||||
PlaytimeTracker.tick();
|
PlaytimeTracker.tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
Module_FPS.tick();
|
Module_FPS.tick();
|
||||||
Module_KeyStrokes.tick();
|
Module_KeyStrokes.tick();
|
||||||
Module_Coords.tick();
|
Module_Coords.tick();
|
||||||
|
DraggableHud.tick();
|
||||||
|
|
||||||
while (openScreenKey.consumeClick()) {
|
while (openScreenKey.consumeClick()) {
|
||||||
if (client.player != null && client.player.isShiftKeyDown()) {
|
if (client.player != null && client.player.isShiftKeyDown()) {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package de.fullrisk.citrusDev.mixin;
|
||||||
|
|
||||||
|
import de.fullrisk.citrusDev.UIHelper.DraggableHud;
|
||||||
|
import net.minecraft.client.MouseHandler;
|
||||||
|
import net.minecraft.client.input.MouseButtonInfo;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(MouseHandler.class)
|
||||||
|
public class MouseHandlerMixin {
|
||||||
|
|
||||||
|
@Inject(method = "turnPlayer", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void citrusDev$cancelTurnInEditMode(double cursorDelta, CallbackInfo ci) {
|
||||||
|
if (DraggableHud.isEditMode()) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onButton", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void citrusDev$cancelClickInEditMode(long windowHandle, MouseButtonInfo buttonInfo, int action, CallbackInfo ci) {
|
||||||
|
if (DraggableHud.isEditMode() && buttonInfo.button() == 0) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,8 @@
|
|||||||
"mixins": [
|
"mixins": [
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"SliderComponentMixin"
|
"SliderComponentMixin",
|
||||||
|
"MouseHandlerMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|||||||
Reference in New Issue
Block a user