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,
ATTACK, USE,
SPRINT,
DROP, DROP_STACK,
DROP_INGAME, DROP_STACK, DROP_INVENTORY,
NEXT_SLOT, PREV_SLOT,
PAUSE,
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,
VMOUSE_MOVE_UP, VMOUSE_MOVE_DOWN, VMOUSE_MOVE_LEFT, VMOUSE_MOVE_RIGHT,
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_SHIFT,
VMOUSE_TOGGLE,
@ -173,7 +174,7 @@ public class ControllerBindings<T extends ControllerState> {
.context(BindContexts.INGAME)
.vanillaOverride(options.keyUse, () -> false)
.build());
register(DROP = ControllerBindingBuilder.create(controller)
register(DROP_INGAME = ControllerBindingBuilder.create(controller)
.identifier("controlify", "drop")
.defaultBind(GamepadBinds.DPAD_DOWN)
.category(GAMEPLAY_CATEGORY)
@ -187,6 +188,12 @@ public class ControllerBindings<T extends ControllerState> {
.context(BindContexts.INGAME)
.radialCandidate(RadialIcons.getItem(Items.TNT))
.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)
.identifier("controlify", "next_slot")
.defaultBind(GamepadBinds.RIGHT_BUMPER)
@ -396,6 +403,30 @@ public class ControllerBindings<T extends ControllerState> {
.category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.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)
.identifier("controlify", "vmouse_scroll_up")
.defaultBind(GamepadBinds.RIGHT_STICK_FORWARD)

View File

@ -72,7 +72,7 @@ public class InGameInputHandler {
if (minecraft.player.drop(true)) {
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)) {
dropRepeatHelper.onNavigate();
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));
Slot hoveredSlot = this.hoveredSlot.get();
if (hoveredSlot != null) {
if (controller.bindings().DROP.justPressed() && hoveredSlot.hasItem()) {
clickSlotFunction.clickSlot(hoveredSlot, hoveredSlot.index, 0, ClickType.THROW);
if (!screen.getMenu().getCarried().isEmpty()) {
if (controller.bindings().DROP_INVENTORY.justPressed()) {
clickSlotFunction.clickSlot(null, -999, 0, ClickType.PICKUP);
}
}
if (hoveredSlot != null) {
if (controller.bindings().INV_SELECT.justPressed()) {
clickSlotFunction.clickSlot(hoveredSlot, hoveredSlot.index, 0, ClickType.PICKUP);
}
@ -147,8 +148,8 @@ public class AbstractContainerScreenProcessor<T extends AbstractContainerScreen<
.rowPadding(0)
.elementPosition(RowLayoutComponent.ElementPosition.MIDDLE)
.element(new GuideActionRenderer<>(
new GuideAction<>(bindings.DROP, ctx -> {
if (ctx.hoveredSlot() != null && ctx.hoveredSlot().hasItem())
new GuideAction<>(bindings.DROP_INVENTORY, ctx -> {
if (!ctx.holdingItem().isEmpty())
return Optional.of(Component.translatable("controlify.guide.container.drop"));
return Optional.empty();
}),
@ -171,7 +172,7 @@ public class AbstractContainerScreenProcessor<T extends AbstractContainerScreen<
))
.element(new GuideActionRenderer<>(
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.empty();
}),

View File

@ -14,14 +14,18 @@ import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
import dev.isxander.controlify.utils.HoldRepeatHelper;
import dev.isxander.controlify.utils.ToastUtils;
import net.minecraft.client.Minecraft;
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.resources.ResourceLocation;
import net.minecraft.util.Mth;
import org.joml.RoundingMode;
import org.joml.Vector2d;
import org.joml.Vector2dc;
import org.joml.Vector2i;
import org.lwjgl.glfw.GLFW;
@ -42,6 +46,8 @@ public class VirtualMouseHandler {
private Set<SnapPoint> snapPoints;
private SnapPoint lastSnappedPoint;
private final HoldRepeatHelper holdRepeatHelper = new HoldRepeatHelper(10, 6);
public VirtualMouseHandler() {
this.minecraft = Minecraft.getInstance();
@ -92,6 +98,20 @@ public class VirtualMouseHandler {
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)) {
handleCompatibilityBinds(controller);
}
@ -169,14 +189,58 @@ public class VirtualMouseHandler {
.orElse(new Pair<>(null, Long.MAX_VALUE)).getFirst(); // retrieve point
if (closestSnapPoint != null) {
lastSnappedPoint = closestSnapPoint;
targetX = currentX = closestSnapPoint.position().x() / scaleFactor.x();
targetY = currentY = closestSnapPoint.position().y() / scaleFactor.y();
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY);
snapToPoint(closestSnapPoint, scaleFactor);
}
}
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() {
if (minecraft.screen != null) {
if (requiresVirtualMouse()) {

View File

@ -224,6 +224,7 @@
"controlify.binding.controlify.inv_take_half": "Take Half",
"controlify.binding.controlify.drop": "Drop Item",
"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_nbt": "Pick Block (with NBT)",
"controlify.binding.controlify.take_screenshot": "Take Screenshot",