diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java b/common/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java index b86a890..55793ce 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/MidnightControls.java @@ -10,6 +10,7 @@ package eu.midnightdust.midnightcontrols; import eu.midnightdust.lib.util.PlatformFunctions; +import net.minecraft.util.Identifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -29,6 +30,9 @@ public class MidnightControls { isExtrasLoaded = PlatformFunctions.isModLoaded("midnightcontrols-extra"); log("Initializing MidnightControls..."); } + public static Identifier id(String path) { + return Identifier.of(MidnightControlsConstants.NAMESPACE, path); + } /** * Prints a message to the terminal. diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java index e93736c..19e57bc 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java @@ -12,7 +12,6 @@ package eu.midnightdust.midnightcontrols.client; import eu.midnightdust.lib.util.PlatformFunctions; import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.MidnightControls; -import eu.midnightdust.midnightcontrols.MidnightControlsConstants; import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; @@ -51,25 +50,27 @@ import java.util.concurrent.atomic.AtomicReference; */ public class MidnightControlsClient extends MidnightControls { public static boolean lateInitDone = false; - public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_up"), + public static final KeyBinding BINDING_LOOK_UP = InputManager.makeKeyBinding(id("look_up"), InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_8, "key.categories.movement"); - public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_right"), + public static final KeyBinding BINDING_LOOK_RIGHT = InputManager.makeKeyBinding(id("look_right"), InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_6, "key.categories.movement"); - public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_down"), + public static final KeyBinding BINDING_LOOK_DOWN = InputManager.makeKeyBinding(id("look_down"), InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_2, "key.categories.movement"); - public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "look_left"), + public static final KeyBinding BINDING_LOOK_LEFT = InputManager.makeKeyBinding(id("look_left"), InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_KP_4, "key.categories.movement"); - public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(Identifier.of(MidnightControlsConstants.NAMESPACE, "ring"), + public static final KeyBinding BINDING_RING = InputManager.makeKeyBinding(id("ring"), InputUtil.Type.KEYSYM, InputUtil.UNKNOWN_KEY.getCode(), "key.categories.misc"); - public static final Identifier CONTROLLER_BUTTONS = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_buttons.png"); - public static final Identifier CONTROLLER_EXPANDED = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_expanded.png"); - public static final Identifier CONTROLLER_AXIS = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/controller_axis.png"); - public static final Identifier CURSOR_TEXTURE = Identifier.of(MidnightControlsConstants.NAMESPACE, "textures/gui/cursor.png"); + public static final Identifier CONTROLLER_BUTTONS = id("textures/gui/controller_buttons.png"); + public static final Identifier CONTROLLER_EXPANDED = id("textures/gui/controller_expanded.png"); + public static final Identifier CONTROLLER_AXIS = id("textures/gui/controller_axis.png"); + public static final Identifier WAYLAND_CURSOR_TEXTURE_LIGHT = id("cursor/light/mouse_pointer"); + public static final Identifier WAYLAND_CURSOR_TEXTURE_DARK = id("cursor/dark/mouse_pointer"); public static final File MAPPINGS_FILE = new File("config/gamecontrollercustommappings.txt"); public static final MinecraftClient client = MinecraftClient.getInstance(); public static final MidnightInput input = new MidnightInput(); public static final MidnightRing ring = new MidnightRing(); public static final MidnightReacharound reacharound = new MidnightReacharound(); + public static boolean isWayland; private static MidnightControlsHud hud; private static ControlsMode previousControlsMode; @@ -87,6 +88,7 @@ public class MidnightControlsClient extends MidnightControls { }, delay, period); HudManager.register(hud = new MidnightControlsHud()); + isWayland = GLFW.glfwGetVersionString().contains("Wayland"); } /** diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java index d5a4311..3069d0d 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/enums/VirtualMouseSkin.java @@ -81,4 +81,12 @@ public enum VirtualMouseSkin implements Nameable { public static @NotNull Optional byId(@NotNull String id) { return Arrays.stream(values()).filter(mode -> mode.getName().equalsIgnoreCase(id)).findFirst(); } + public String getSpritePath() { + return switch (this) { + case DEFAULT_LIGHT -> "cursor/light/default"; + case DEFAULT_DARK -> "cursor/dark/default"; + case SECOND_LIGHT -> "cursor/light/secondary"; + case SECOND_DARK -> "cursor/dark/secondary"; + }; + } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java index 90b97ab..2886a12 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsRenderer.java @@ -10,21 +10,34 @@ package eu.midnightdust.midnightcontrols.client.gui; import com.mojang.blaze3d.systems.RenderSystem; +import eu.midnightdust.midnightcontrols.ControlsMode; import eu.midnightdust.midnightcontrols.client.enums.ControllerType; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.MidnightInput; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; +import eu.midnightdust.midnightcontrols.client.enums.VirtualMouseSkin; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.BufferRenderer; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexFormat; +import net.minecraft.client.render.VertexFormats; import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.texture.Sprite; import net.minecraft.screen.slot.Slot; +import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; +import org.joml.Matrix4f; import org.lwjgl.glfw.GLFW; +import static eu.midnightdust.midnightcontrols.MidnightControls.id; + /** * Represents the midnightcontrols renderer. * @@ -192,14 +205,28 @@ public class MidnightControlsRenderer { private static int getButtonTipWidth(@NotNull String action, @NotNull TextRenderer textRenderer) { return 15 + 5 + textRenderer.getWidth(action); } + public static void renderWaylandCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) { + if (MidnightControlsConfig.virtualMouse || client.currentScreen == null || MidnightControlsConfig.controlsMode != ControlsMode.CONTROLLER) return; + + float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth(); + float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight(); + + try { + Identifier spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_LIGHT; + if (MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.DEFAULT_DARK || MidnightControlsConfig.virtualMouseSkin == VirtualMouseSkin.SECOND_DARK) + spritePath = MidnightControlsClient.WAYLAND_CURSOR_TEXTURE_DARK; + Sprite sprite = client.getGuiAtlasManager().getSprite(spritePath); + drawUnalignedTexturedQuad(sprite.getAtlasId(), context, mouseX, mouseX + 8, mouseY, mouseY + 8, 999, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV()); + } catch (IllegalStateException ignored) {} + } public static void renderVirtualCursor(@NotNull DrawContext context, @NotNull MinecraftClient client) { if (!MidnightControlsConfig.virtualMouse || (client.currentScreen == null || MidnightInput.isScreenInteractive(client.currentScreen))) return; - int mouseX = (int) (client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()); - int mouseY = (int) (client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()); + float mouseX = (float) client.mouse.getX() * client.getWindow().getScaledWidth() / client.getWindow().getWidth(); + float mouseY = (float) client.mouse.getY() * client.getWindow().getScaledHeight() / client.getWindow().getHeight(); boolean hoverSlot = false; @@ -217,7 +244,7 @@ public class MidnightControlsRenderer { } if (!hoverSlot && client.currentScreen != null) { - var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, mouseX, mouseY); + var slot = MidnightControlsCompat.getSlotAt(client.currentScreen, (int) mouseX, (int) mouseY); if (slot != null) { mouseX = slot.x(); @@ -231,32 +258,21 @@ public class MidnightControlsRenderer { mouseY -= 8; } - //context.getMatrices().push(); - context.getMatrices().translate(0f, 0f, 999f); - drawCursor(context, mouseX, mouseY, hoverSlot, client); - //context.getMatrices().pop(); + try { + Sprite sprite = client.getGuiAtlasManager().getSprite(id(MidnightControlsConfig.virtualMouseSkin.getSpritePath() + (hoverSlot ? "_slot" : ""))); + drawUnalignedTexturedQuad(sprite.getAtlasId(), context, mouseX, mouseX + 16, mouseY, mouseY + 16, 999, sprite.getMinU(), sprite.getMaxU(), sprite.getMinV(), sprite.getMaxV()); + } catch (IllegalStateException ignored) {} } - - /** - * Draws the virtual cursor. - * - * @param context the context - * @param x x coordinate - * @param y y coordinate - * @param hoverSlot true if hovering a slot, else false - * @param client the client instance - */ - public static void drawCursor(@NotNull DrawContext context, int x, int y, boolean hoverSlot, @NotNull MinecraftClient client) { - //RenderSystem.disableDepthTest(); - //RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f); - //RenderSystem.disableBlend(); - //RenderSystem.setShaderTexture(0, MidnightControlsClient.CURSOR_TEXTURE); - context.drawTexture(MidnightControlsClient.CURSOR_TEXTURE, x, y, - hoverSlot ? 16.f : 0.f, MidnightControlsConfig.virtualMouseSkin.ordinal() * 16.f, - 16, 16, 32, 64); - context.fill(1, 1, x, y, 0xFFFFFF); - context.draw(); - //RenderSystem.enableDepthTest(); + private static void drawUnalignedTexturedQuad(Identifier texture, DrawContext context, float x1, float x2, float y1, float y2, float z, float u1, float u2, float v1, float v2) { + RenderSystem.setShaderTexture(0, texture); + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + Matrix4f matrix4f = context.getMatrices().peek().getPositionMatrix(); + BufferBuilder bufferBuilder = Tessellator.getInstance().begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE); + bufferBuilder.vertex(matrix4f, x1, y1, z).texture(u1, v1); + bufferBuilder.vertex(matrix4f, x1, y2, z).texture(u1, v2); + bufferBuilder.vertex(matrix4f, x2, y2, z).texture(u2, v2); + bufferBuilder.vertex(matrix4f, x2, y1, z).texture(u2, v1); + BufferRenderer.drawWithGlobalProgram(bufferBuilder.end()); } public record ButtonSize(int length, int height) { diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java index 94f1402..e7dcf78 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java @@ -42,6 +42,7 @@ public abstract class GameRendererMixin { @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE)) private void renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) { MidnightControlsRenderer.renderVirtualCursor(drawContext, client); + if (MidnightControlsClient.isWayland) MidnightControlsRenderer.renderWaylandCursor(drawContext, client); drawContext.draw(); } @Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"), method = "renderWorld") diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/cursor.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/cursor.png deleted file mode 100644 index 78fabc4..0000000 Binary files a/common/src/main/resources/assets/midnightcontrols/textures/gui/cursor.png and /dev/null differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/default.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/default.png new file mode 100644 index 0000000..1fe04ed Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/default.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/default_slot.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/default_slot.png new file mode 100644 index 0000000..b444861 Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/default_slot.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/mouse_pointer.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/mouse_pointer.png new file mode 100644 index 0000000..dd957f0 Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/mouse_pointer.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/secondary.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/secondary.png new file mode 100644 index 0000000..0f9ee0e Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/secondary.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/secondary_slot.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/secondary_slot.png new file mode 100644 index 0000000..5bcb9bc Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/dark/secondary_slot.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/default.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/default.png new file mode 100644 index 0000000..f1c12db Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/default.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/default_slot.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/default_slot.png new file mode 100644 index 0000000..636545f Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/default_slot.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/mouse_pointer.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/mouse_pointer.png new file mode 100644 index 0000000..c12dff5 Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/mouse_pointer.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/secondary.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/secondary.png new file mode 100644 index 0000000..e62b6cd Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/secondary.png differ diff --git a/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/secondary_slot.png b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/secondary_slot.png new file mode 100644 index 0000000..45259ef Binary files /dev/null and b/common/src/main/resources/assets/midnightcontrols/textures/gui/sprites/cursor/light/secondary_slot.png differ