1
0
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:
Xander
2023-10-25 17:11:43 +01:00
parent 7e23b018c1
commit 29eec1e411
5 changed files with 112 additions and 15 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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();
}), }),

View File

@ -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()) {

View File

@ -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",