forked from Clones/Controlify
➕ D-Pad snapping + better drop key in containers (closes #124) - thanks @arnokeesman for PR and reference
This commit is contained in:
@ -49,7 +49,7 @@ public class ControllerBindings<T extends ControllerState> {
|
|||||||
JUMP, SNEAK,
|
JUMP, SNEAK,
|
||||||
ATTACK, USE,
|
ATTACK, USE,
|
||||||
SPRINT,
|
SPRINT,
|
||||||
DROP, DROP_STACK,
|
DROP_INGAME, DROP_STACK, DROP_INVENTORY,
|
||||||
NEXT_SLOT, PREV_SLOT,
|
NEXT_SLOT, PREV_SLOT,
|
||||||
PAUSE,
|
PAUSE,
|
||||||
INVENTORY,
|
INVENTORY,
|
||||||
@ -67,6 +67,7 @@ public class ControllerBindings<T extends ControllerState> {
|
|||||||
RADIAL_MENU, RADIAL_AXIS_UP, RADIAL_AXIS_DOWN, RADIAL_AXIS_LEFT, RADIAL_AXIS_RIGHT,
|
RADIAL_MENU, RADIAL_AXIS_UP, RADIAL_AXIS_DOWN, RADIAL_AXIS_LEFT, RADIAL_AXIS_RIGHT,
|
||||||
VMOUSE_MOVE_UP, VMOUSE_MOVE_DOWN, VMOUSE_MOVE_LEFT, VMOUSE_MOVE_RIGHT,
|
VMOUSE_MOVE_UP, VMOUSE_MOVE_DOWN, VMOUSE_MOVE_LEFT, VMOUSE_MOVE_RIGHT,
|
||||||
VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_SHIFT_CLICK,
|
VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_SHIFT_CLICK,
|
||||||
|
VMOUSE_SNAP_UP, VMOUSE_SNAP_DOWN, VMOUSE_SNAP_LEFT, VMOUSE_SNAP_RIGHT,
|
||||||
VMOUSE_SCROLL_UP, VMOUSE_SCROLL_DOWN,
|
VMOUSE_SCROLL_UP, VMOUSE_SCROLL_DOWN,
|
||||||
VMOUSE_SHIFT,
|
VMOUSE_SHIFT,
|
||||||
VMOUSE_TOGGLE,
|
VMOUSE_TOGGLE,
|
||||||
@ -173,7 +174,7 @@ public class ControllerBindings<T extends ControllerState> {
|
|||||||
.context(BindContexts.INGAME)
|
.context(BindContexts.INGAME)
|
||||||
.vanillaOverride(options.keyUse, () -> false)
|
.vanillaOverride(options.keyUse, () -> false)
|
||||||
.build());
|
.build());
|
||||||
register(DROP = ControllerBindingBuilder.create(controller)
|
register(DROP_INGAME = ControllerBindingBuilder.create(controller)
|
||||||
.identifier("controlify", "drop")
|
.identifier("controlify", "drop")
|
||||||
.defaultBind(GamepadBinds.DPAD_DOWN)
|
.defaultBind(GamepadBinds.DPAD_DOWN)
|
||||||
.category(GAMEPLAY_CATEGORY)
|
.category(GAMEPLAY_CATEGORY)
|
||||||
@ -187,6 +188,12 @@ public class ControllerBindings<T extends ControllerState> {
|
|||||||
.context(BindContexts.INGAME)
|
.context(BindContexts.INGAME)
|
||||||
.radialCandidate(RadialIcons.getItem(Items.TNT))
|
.radialCandidate(RadialIcons.getItem(Items.TNT))
|
||||||
.build());
|
.build());
|
||||||
|
register(DROP_INVENTORY = ControllerBindingBuilder.create(controller)
|
||||||
|
.identifier("controlify", "drop_inventory")
|
||||||
|
.defaultBind(GamepadBinds.Y_BUTTON)
|
||||||
|
.category(INVENTORY_CATEGORY)
|
||||||
|
.context(BindContexts.INVENTORY)
|
||||||
|
.build());
|
||||||
register(NEXT_SLOT = ControllerBindingBuilder.create(controller)
|
register(NEXT_SLOT = ControllerBindingBuilder.create(controller)
|
||||||
.identifier("controlify", "next_slot")
|
.identifier("controlify", "next_slot")
|
||||||
.defaultBind(GamepadBinds.RIGHT_BUMPER)
|
.defaultBind(GamepadBinds.RIGHT_BUMPER)
|
||||||
@ -396,6 +403,30 @@ public class ControllerBindings<T extends ControllerState> {
|
|||||||
.category(VMOUSE_CATEGORY)
|
.category(VMOUSE_CATEGORY)
|
||||||
.context(BindContexts.GUI_VMOUSE)
|
.context(BindContexts.GUI_VMOUSE)
|
||||||
.build());
|
.build());
|
||||||
|
register(VMOUSE_SNAP_UP = ControllerBindingBuilder.create(controller)
|
||||||
|
.identifier("controlify", "vmouse_snap_up")
|
||||||
|
.defaultBind(GamepadBinds.DPAD_UP)
|
||||||
|
.category(VMOUSE_CATEGORY)
|
||||||
|
.context(BindContexts.GUI_VMOUSE)
|
||||||
|
.build());
|
||||||
|
register(VMOUSE_SNAP_DOWN = ControllerBindingBuilder.create(controller)
|
||||||
|
.identifier("controlify", "vmouse_snap_down")
|
||||||
|
.defaultBind(GamepadBinds.DPAD_DOWN)
|
||||||
|
.category(VMOUSE_CATEGORY)
|
||||||
|
.context(BindContexts.GUI_VMOUSE)
|
||||||
|
.build());
|
||||||
|
register(VMOUSE_SNAP_LEFT = ControllerBindingBuilder.create(controller)
|
||||||
|
.identifier("controlify", "vmouse_snap_left")
|
||||||
|
.defaultBind(GamepadBinds.DPAD_LEFT)
|
||||||
|
.category(VMOUSE_CATEGORY)
|
||||||
|
.context(BindContexts.GUI_VMOUSE)
|
||||||
|
.build());
|
||||||
|
register(VMOUSE_SNAP_RIGHT = ControllerBindingBuilder.create(controller)
|
||||||
|
.identifier("controlify", "vmouse_snap_right")
|
||||||
|
.defaultBind(GamepadBinds.DPAD_RIGHT)
|
||||||
|
.category(VMOUSE_CATEGORY)
|
||||||
|
.context(BindContexts.GUI_VMOUSE)
|
||||||
|
.build());
|
||||||
register(VMOUSE_SCROLL_UP = ControllerBindingBuilder.create(controller)
|
register(VMOUSE_SCROLL_UP = ControllerBindingBuilder.create(controller)
|
||||||
.identifier("controlify", "vmouse_scroll_up")
|
.identifier("controlify", "vmouse_scroll_up")
|
||||||
.defaultBind(GamepadBinds.RIGHT_STICK_FORWARD)
|
.defaultBind(GamepadBinds.RIGHT_STICK_FORWARD)
|
||||||
|
@ -72,7 +72,7 @@ public class InGameInputHandler {
|
|||||||
if (minecraft.player.drop(true)) {
|
if (minecraft.player.drop(true)) {
|
||||||
minecraft.player.swing(InteractionHand.MAIN_HAND);
|
minecraft.player.swing(InteractionHand.MAIN_HAND);
|
||||||
}
|
}
|
||||||
} else if (dropRepeatHelper.shouldAction(controller.bindings().DROP)) {
|
} else if (dropRepeatHelper.shouldAction(controller.bindings().DROP_INGAME)) {
|
||||||
if (minecraft.player.drop(false)) {
|
if (minecraft.player.drop(false)) {
|
||||||
dropRepeatHelper.onNavigate();
|
dropRepeatHelper.onNavigate();
|
||||||
minecraft.player.swing(InteractionHand.MAIN_HAND);
|
minecraft.player.swing(InteractionHand.MAIN_HAND);
|
||||||
|
@ -45,11 +45,12 @@ public class AbstractContainerScreenProcessor<T extends AbstractContainerScreen<
|
|||||||
ContainerGuideCtx ctx = new ContainerGuideCtx(hoveredSlot.get(), screen.getMenu().getCarried(), accessor.invokeHasClickedOutside(vmouse.getCurrentX(1f), vmouse.getCurrentY(1f), accessor.getLeftPos(), accessor.getTopPos(), 0));
|
ContainerGuideCtx ctx = new ContainerGuideCtx(hoveredSlot.get(), screen.getMenu().getCarried(), accessor.invokeHasClickedOutside(vmouse.getCurrentX(1f), vmouse.getCurrentY(1f), accessor.getLeftPos(), accessor.getTopPos(), 0));
|
||||||
|
|
||||||
Slot hoveredSlot = this.hoveredSlot.get();
|
Slot hoveredSlot = this.hoveredSlot.get();
|
||||||
if (hoveredSlot != null) {
|
if (!screen.getMenu().getCarried().isEmpty()) {
|
||||||
if (controller.bindings().DROP.justPressed() && hoveredSlot.hasItem()) {
|
if (controller.bindings().DROP_INVENTORY.justPressed()) {
|
||||||
clickSlotFunction.clickSlot(hoveredSlot, hoveredSlot.index, 0, ClickType.THROW);
|
clickSlotFunction.clickSlot(null, -999, 0, ClickType.PICKUP);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (hoveredSlot != null) {
|
||||||
if (controller.bindings().INV_SELECT.justPressed()) {
|
if (controller.bindings().INV_SELECT.justPressed()) {
|
||||||
clickSlotFunction.clickSlot(hoveredSlot, hoveredSlot.index, 0, ClickType.PICKUP);
|
clickSlotFunction.clickSlot(hoveredSlot, hoveredSlot.index, 0, ClickType.PICKUP);
|
||||||
}
|
}
|
||||||
@ -147,8 +148,8 @@ public class AbstractContainerScreenProcessor<T extends AbstractContainerScreen<
|
|||||||
.rowPadding(0)
|
.rowPadding(0)
|
||||||
.elementPosition(RowLayoutComponent.ElementPosition.MIDDLE)
|
.elementPosition(RowLayoutComponent.ElementPosition.MIDDLE)
|
||||||
.element(new GuideActionRenderer<>(
|
.element(new GuideActionRenderer<>(
|
||||||
new GuideAction<>(bindings.DROP, ctx -> {
|
new GuideAction<>(bindings.DROP_INVENTORY, ctx -> {
|
||||||
if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem())
|
if (!ctx.holdingItem().isEmpty())
|
||||||
return Optional.of(Component.translatable("controlify.guide.container.drop"));
|
return Optional.of(Component.translatable("controlify.guide.container.drop"));
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}),
|
}),
|
||||||
@ -171,7 +172,7 @@ public class AbstractContainerScreenProcessor<T extends AbstractContainerScreen<
|
|||||||
))
|
))
|
||||||
.element(new GuideActionRenderer<>(
|
.element(new GuideActionRenderer<>(
|
||||||
new GuideAction<>(bindings.INV_QUICK_MOVE, ctx -> {
|
new GuideAction<>(bindings.INV_QUICK_MOVE, ctx -> {
|
||||||
if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem())
|
if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem() && ctx.holdingItem().isEmpty())
|
||||||
return Optional.of(Component.translatable("controlify.guide.container.quick_move"));
|
return Optional.of(Component.translatable("controlify.guide.container.quick_move"));
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}),
|
}),
|
||||||
|
@ -14,14 +14,18 @@ import dev.isxander.controlify.screenop.ScreenProcessorProvider;
|
|||||||
import dev.isxander.controlify.api.event.ControlifyEvents;
|
import dev.isxander.controlify.api.event.ControlifyEvents;
|
||||||
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;
|
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;
|
||||||
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
|
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
|
||||||
|
import dev.isxander.controlify.utils.HoldRepeatHelper;
|
||||||
import dev.isxander.controlify.utils.ToastUtils;
|
import dev.isxander.controlify.utils.ToastUtils;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiGraphics;
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.gui.navigation.ScreenAxis;
|
||||||
|
import net.minecraft.client.gui.navigation.ScreenDirection;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.Mth;
|
import net.minecraft.util.Mth;
|
||||||
import org.joml.RoundingMode;
|
import org.joml.RoundingMode;
|
||||||
import org.joml.Vector2d;
|
import org.joml.Vector2d;
|
||||||
|
import org.joml.Vector2dc;
|
||||||
import org.joml.Vector2i;
|
import org.joml.Vector2i;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
@ -42,6 +46,8 @@ public class VirtualMouseHandler {
|
|||||||
private Set<SnapPoint> snapPoints;
|
private Set<SnapPoint> snapPoints;
|
||||||
private SnapPoint lastSnappedPoint;
|
private SnapPoint lastSnappedPoint;
|
||||||
|
|
||||||
|
private final HoldRepeatHelper holdRepeatHelper = new HoldRepeatHelper(10, 6);
|
||||||
|
|
||||||
public VirtualMouseHandler() {
|
public VirtualMouseHandler() {
|
||||||
this.minecraft = Minecraft.getInstance();
|
this.minecraft = Minecraft.getInstance();
|
||||||
|
|
||||||
@ -92,6 +98,20 @@ public class VirtualMouseHandler {
|
|||||||
|
|
||||||
scrollY += controller.bindings().VMOUSE_SCROLL_UP.state() - controller.bindings().VMOUSE_SCROLL_DOWN.state();
|
scrollY += controller.bindings().VMOUSE_SCROLL_UP.state() - controller.bindings().VMOUSE_SCROLL_DOWN.state();
|
||||||
|
|
||||||
|
if (holdRepeatHelper.shouldAction(controller.bindings().VMOUSE_SNAP_UP)) {
|
||||||
|
snapInDirection(ScreenDirection.UP);
|
||||||
|
holdRepeatHelper.onNavigate();
|
||||||
|
} else if (holdRepeatHelper.shouldAction(controller.bindings().VMOUSE_SNAP_DOWN)) {
|
||||||
|
snapInDirection(ScreenDirection.DOWN);
|
||||||
|
holdRepeatHelper.onNavigate();
|
||||||
|
} else if (holdRepeatHelper.shouldAction(controller.bindings().VMOUSE_SNAP_LEFT)) {
|
||||||
|
snapInDirection(ScreenDirection.LEFT);
|
||||||
|
holdRepeatHelper.onNavigate();
|
||||||
|
} else if (holdRepeatHelper.shouldAction(controller.bindings().VMOUSE_SNAP_RIGHT)) {
|
||||||
|
snapInDirection(ScreenDirection.RIGHT);
|
||||||
|
holdRepeatHelper.onNavigate();
|
||||||
|
}
|
||||||
|
|
||||||
if (ScreenProcessorProvider.provide(minecraft.screen).virtualMouseBehaviour().isDefaultOr(VirtualMouseBehaviour.ENABLED)) {
|
if (ScreenProcessorProvider.provide(minecraft.screen).virtualMouseBehaviour().isDefaultOr(VirtualMouseBehaviour.ENABLED)) {
|
||||||
handleCompatibilityBinds(controller);
|
handleCompatibilityBinds(controller);
|
||||||
}
|
}
|
||||||
@ -169,14 +189,58 @@ public class VirtualMouseHandler {
|
|||||||
.orElse(new Pair<>(null, Long.MAX_VALUE)).getFirst(); // retrieve point
|
.orElse(new Pair<>(null, Long.MAX_VALUE)).getFirst(); // retrieve point
|
||||||
|
|
||||||
if (closestSnapPoint != null) {
|
if (closestSnapPoint != null) {
|
||||||
lastSnappedPoint = closestSnapPoint;
|
snapToPoint(closestSnapPoint, scaleFactor);
|
||||||
|
|
||||||
targetX = currentX = closestSnapPoint.position().x() / scaleFactor.x();
|
|
||||||
targetY = currentY = closestSnapPoint.position().y() / scaleFactor.y();
|
|
||||||
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void snapInDirection(ScreenDirection direction) {
|
||||||
|
var window = minecraft.getWindow();
|
||||||
|
var scaleFactor = new Vector2d((double)window.getGuiScaledWidth() / (double)window.getScreenWidth(), (double)window.getGuiScaledHeight() / (double)window.getScreenHeight());
|
||||||
|
var target = new Vector2d(targetX, targetY).mul(scaleFactor);
|
||||||
|
|
||||||
|
var closestSnapPoint = snapPoints.stream()
|
||||||
|
.filter(snapPoint -> !snapPoint.equals(lastSnappedPoint)) // don't snap to the point currently over snapped point
|
||||||
|
.map(snapPoint -> new Pair<>(snapPoint, new Vector2d(snapPoint.position().x() - target.x(), snapPoint.position().y() - target.y()))) // map with distance to current pos
|
||||||
|
// filter points that are not in the correct direction
|
||||||
|
.filter(pair -> {
|
||||||
|
Vector2d dist = pair.getSecond();
|
||||||
|
|
||||||
|
double axis = direction.getAxis() == ScreenAxis.HORIZONTAL ? dist.x : dist.y;
|
||||||
|
double positive = direction.isPositive() ? 1 : -1;
|
||||||
|
|
||||||
|
return axis * positive > 0;
|
||||||
|
})
|
||||||
|
.filter(pair -> {
|
||||||
|
SnapPoint snapPoint = pair.getFirst();
|
||||||
|
Vector2d dist = pair.getSecond();
|
||||||
|
|
||||||
|
double distance = Math.abs(direction.getAxis() == ScreenAxis.HORIZONTAL ? dist.x : dist.y);
|
||||||
|
double deviation = Math.abs(direction.getAxis() == ScreenAxis.HORIZONTAL ? dist.y : dist.x);
|
||||||
|
|
||||||
|
pair.getSecond().set(distance, deviation);
|
||||||
|
|
||||||
|
return distance >= snapPoint.range();
|
||||||
|
})
|
||||||
|
// pick the closest point
|
||||||
|
.min(Comparator.comparingDouble(pair -> {
|
||||||
|
Vector2d distDev = pair.getSecond();
|
||||||
|
return distDev.x + distDev.y;
|
||||||
|
}))
|
||||||
|
.map(Pair::getFirst);
|
||||||
|
|
||||||
|
closestSnapPoint.ifPresent(snapPoint -> {
|
||||||
|
snapToPoint(snapPoint, scaleFactor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void snapToPoint(SnapPoint snapPoint, Vector2dc scaleFactor) {
|
||||||
|
lastSnappedPoint = snapPoint;
|
||||||
|
|
||||||
|
targetX = currentX = snapPoint.position().x() / scaleFactor.x();
|
||||||
|
targetY = currentY = snapPoint.position().y() / scaleFactor.y();
|
||||||
|
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY);
|
||||||
|
}
|
||||||
|
|
||||||
public void onScreenChanged() {
|
public void onScreenChanged() {
|
||||||
if (minecraft.screen != null) {
|
if (minecraft.screen != null) {
|
||||||
if (requiresVirtualMouse()) {
|
if (requiresVirtualMouse()) {
|
||||||
|
@ -224,6 +224,7 @@
|
|||||||
"controlify.binding.controlify.inv_take_half": "Take Half",
|
"controlify.binding.controlify.inv_take_half": "Take Half",
|
||||||
"controlify.binding.controlify.drop": "Drop Item",
|
"controlify.binding.controlify.drop": "Drop Item",
|
||||||
"controlify.binding.controlify.drop_stack": "Drop Stack",
|
"controlify.binding.controlify.drop_stack": "Drop Stack",
|
||||||
|
"controlify.binding.controlify.drop_inventory": "Drop Item (In Containers)",
|
||||||
"controlify.binding.controlify.pick_block": "Pick Block",
|
"controlify.binding.controlify.pick_block": "Pick Block",
|
||||||
"controlify.binding.controlify.pick_block_nbt": "Pick Block (with NBT)",
|
"controlify.binding.controlify.pick_block_nbt": "Pick Block (with NBT)",
|
||||||
"controlify.binding.controlify.take_screenshot": "Take Screenshot",
|
"controlify.binding.controlify.take_screenshot": "Take Screenshot",
|
||||||
|
Reference in New Issue
Block a user