1
0
forked from Clones/Controlify

Controller conflict detection

This commit is contained in:
isXander
2023-05-07 12:47:32 +01:00
parent 63ebf2dc61
commit fa1e1293c7
10 changed files with 258 additions and 44 deletions

View File

@ -1,12 +1,15 @@
package dev.isxander.controlify.api.bind; package dev.isxander.controlify.api.bind;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import dev.isxander.controlify.bindings.BindContext;
import dev.isxander.controlify.bindings.IBind;
import dev.isxander.yacl.api.Option; import dev.isxander.yacl.api.Option;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Set;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
public interface ControllerBinding { public interface ControllerBinding {
@ -46,17 +49,20 @@ public interface ControllerBinding {
ResourceLocation id(); ResourceLocation id();
Set<BindContext> contexts();
/** /**
* The vanilla override of the binding. Null if there is no override. * The vanilla override of the binding. Null if there is no override.
*/ */
@Nullable KeyMappingOverride override(); @Nullable KeyMappingOverride override();
IBind<?> getBind();
void resetBind(); void resetBind();
boolean isUnbound(); boolean isUnbound();
BindRenderer renderer(); BindRenderer renderer();
Option<?> generateYACLOption(); Option.Builder<?> startYACLOption();
JsonObject toJson(); JsonObject toJson();

View File

@ -1,5 +1,6 @@
package dev.isxander.controlify.api.bind; package dev.isxander.controlify.api.bind;
import dev.isxander.controlify.bindings.BindContext;
import dev.isxander.controlify.bindings.ControllerBindingImpl; import dev.isxander.controlify.bindings.ControllerBindingImpl;
import dev.isxander.controlify.bindings.GamepadBinds; import dev.isxander.controlify.bindings.GamepadBinds;
import dev.isxander.controlify.bindings.IBind; import dev.isxander.controlify.bindings.IBind;
@ -73,6 +74,8 @@ public interface ControllerBindingBuilder<T extends ControllerState> {
*/ */
ControllerBindingBuilder<T> category(Component category); ControllerBindingBuilder<T> category(Component category);
ControllerBindingBuilder<T> context(BindContext... contexts);
/** /**
* Specifies are vanilla override for the binding. * Specifies are vanilla override for the binding.
* Will emulate presses of the vanilla keybind when the controller binding is pressed. * Will emulate presses of the vanilla keybind when the controller binding is pressed.

View File

@ -0,0 +1,64 @@
package dev.isxander.controlify.bindings;
import com.google.common.collect.ImmutableSet;
import net.minecraft.resources.ResourceLocation;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
public final class BindContext {
private final ResourceLocation context;
private final Set<BindContext> parents;
private final Set<ResourceLocation> flattened;
public BindContext(ResourceLocation context, Set<BindContext> parents) {
this.context = context;
this.parents = parents;
Set<ResourceLocation> flattened = new HashSet<>();
flattened.add(context());
parents().forEach(p -> flattened.addAll(p.flattened()));
this.flattened = ImmutableSet.copyOf(flattened);
}
public ResourceLocation context() {
return context;
}
public Set<BindContext> parents() {
return parents;
}
public Set<ResourceLocation> flattened() {
return flattened;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (BindContext) obj;
return Objects.equals(this.context, that.context) &&
Objects.equals(this.parents, that.parents);
}
@Override
public int hashCode() {
return Objects.hash(context, parents);
}
@Override
public String toString() {
return "BindContext[" +
"context=" + context + ", " +
"parents=" + parents + ']';
}
public static Set<ResourceLocation> flatten(Set<BindContext> contexts) {
return contexts.stream()
.flatMap(ctx -> ctx.flattened.stream())
.collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,18 @@
package dev.isxander.controlify.bindings;
import dev.isxander.controlify.Controlify;
import java.util.Set;
public final class BindContexts {
public static final BindContext
INGAME = ctx("ingame"),
GUI = ctx("gui"),
GUI_VMOUSE = ctx("gui_vmouse"),
CONTROLIFY_CONFIG = ctx("controlify_config", GUI),
INVENTORY = ctx("inventory", GUI_VMOUSE);
private static BindContext ctx(String path, BindContext... parents) {
return new BindContext(Controlify.id(path), Set.of(parents));
}
}

View File

@ -1,5 +1,6 @@
package dev.isxander.controlify.bindings; package dev.isxander.controlify.bindings;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
@ -36,11 +37,12 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
private BindRenderer renderer; private BindRenderer renderer;
private final ResourceLocation id; private final ResourceLocation id;
private final Component name, description, category; private final Component name, description, category;
private final Set<BindContext> contexts;
private final KeyMappingOverride override; private final KeyMappingOverride override;
private static final Map<Controller<?, ?>, Set<IBind<?>>> pressedBinds = new HashMap<>(); private static final Map<Controller<?, ?>, Set<IBind<?>>> pressedBinds = new HashMap<>();
private ControllerBindingImpl(Controller<T, ?> controller, IBind<T> defaultBind, ResourceLocation id, KeyMappingOverride vanillaOverride, Component name, Component description, Component category) { private ControllerBindingImpl(Controller<T, ?> controller, IBind<T> defaultBind, ResourceLocation id, KeyMappingOverride vanillaOverride, Component name, Component description, Component category, Set<BindContext> contexts) {
this.controller = controller; this.controller = controller;
this.bind = this.defaultBind = defaultBind; this.bind = this.defaultBind = defaultBind;
this.renderer = new BindRendererImpl(bind); this.renderer = new BindRendererImpl(bind);
@ -49,6 +51,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
this.name = name; this.name = name;
this.description = description; this.description = description;
this.category = category; this.category = category;
this.contexts = ImmutableSet.copyOf(contexts);
} }
@Override @Override
@ -133,6 +136,16 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
return category; return category;
} }
@Override
public Set<BindContext> contexts() {
return contexts;
}
@Override
public IBind<T> getBind() {
return bind;
}
@Override @Override
public boolean isUnbound() { public boolean isUnbound() {
return bind instanceof EmptyBind; return bind instanceof EmptyBind;
@ -154,7 +167,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
} }
@Override @Override
public Option<?> generateYACLOption() { public Option.Builder<?> startYACLOption() {
Option.Builder<IBind<T>> option = Option.createBuilder((Class<IBind<T>>) (Class<?>) IBind.class) Option.Builder<IBind<T>> option = Option.createBuilder((Class<IBind<T>>) (Class<?>) IBind.class)
.name(name()) .name(name())
.binding(defaultBind(), this::currentBind, this::setCurrentBind) .binding(defaultBind(), this::currentBind, this::setCurrentBind)
@ -166,7 +179,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
((Option.Builder<IBind<JoystickState>>) (Object) option).controller(opt -> new JoystickBindController(opt, joystick)); ((Option.Builder<IBind<JoystickState>>) (Object) option).controller(opt -> new JoystickBindController(opt, joystick));
} }
return option.build(); return option;
} }
// FIXME: very hack solution please remove me // FIXME: very hack solution please remove me
@ -197,6 +210,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
private ResourceLocation id; private ResourceLocation id;
private Component name = null, description = null, category = null; private Component name = null, description = null, category = null;
private KeyMappingOverride override = null; private KeyMappingOverride override = null;
private final Set<BindContext> contexts = new HashSet<>();
public ControllerBindingBuilderImpl(Controller<T, ?> controller) { public ControllerBindingBuilderImpl(Controller<T, ?> controller) {
this.controller = controller; this.controller = controller;
@ -248,6 +262,12 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
return this; return this;
} }
@Override
public ControllerBindingBuilder<T> context(BindContext... contexts) {
this.contexts.addAll(Set.of(contexts));
return this;
}
@Override @Override
public ControllerBindingBuilder<T> vanillaOverride(KeyMapping keyMapping, BooleanSupplier toggleable) { public ControllerBindingBuilder<T> vanillaOverride(KeyMapping keyMapping, BooleanSupplier toggleable) {
this.override = new KeyMappingOverride(keyMapping, toggleable); this.override = new KeyMappingOverride(keyMapping, toggleable);
@ -276,7 +296,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
} }
} }
return new ControllerBindingImpl<>(controller, bind, id, override, name, description, category); return new ControllerBindingImpl<>(controller, bind, id, override, name, description, category, contexts);
} }
} }

View File

@ -78,47 +78,56 @@ public class ControllerBindings<T extends ControllerState> {
.identifier("controlify", "walk_forward") .identifier("controlify", "walk_forward")
.defaultBind(GamepadBinds.LEFT_STICK_FORWARD) .defaultBind(GamepadBinds.LEFT_STICK_FORWARD)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(WALK_BACKWARD = ControllerBindingBuilder.create(controller) register(WALK_BACKWARD = ControllerBindingBuilder.create(controller)
.identifier("controlify", "walk_backward") .identifier("controlify", "walk_backward")
.defaultBind(GamepadBinds.LEFT_STICK_BACKWARD) .defaultBind(GamepadBinds.LEFT_STICK_BACKWARD)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(WALK_LEFT = ControllerBindingBuilder.create(controller) register(WALK_LEFT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "strafe_left") .identifier("controlify", "strafe_left")
.defaultBind(GamepadBinds.LEFT_STICK_LEFT) .defaultBind(GamepadBinds.LEFT_STICK_LEFT)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(WALK_RIGHT = ControllerBindingBuilder.create(controller) register(WALK_RIGHT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "strafe_right") .identifier("controlify", "strafe_right")
.defaultBind(GamepadBinds.LEFT_STICK_RIGHT) .defaultBind(GamepadBinds.LEFT_STICK_RIGHT)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(LOOK_UP = ControllerBindingBuilder.create(controller) register(LOOK_UP = ControllerBindingBuilder.create(controller)
.identifier("controlify", "look_up") .identifier("controlify", "look_up")
.defaultBind(GamepadBinds.RIGHT_STICK_FORWARD) .defaultBind(GamepadBinds.RIGHT_STICK_FORWARD)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(LOOK_DOWN = ControllerBindingBuilder.create(controller) register(LOOK_DOWN = ControllerBindingBuilder.create(controller)
.identifier("controlify", "look_down") .identifier("controlify", "look_down")
.defaultBind(GamepadBinds.RIGHT_STICK_BACKWARD) .defaultBind(GamepadBinds.RIGHT_STICK_BACKWARD)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(LOOK_LEFT = ControllerBindingBuilder.create(controller) register(LOOK_LEFT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "look_left") .identifier("controlify", "look_left")
.defaultBind(GamepadBinds.RIGHT_STICK_LEFT) .defaultBind(GamepadBinds.RIGHT_STICK_LEFT)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(LOOK_RIGHT = ControllerBindingBuilder.create(controller) register(LOOK_RIGHT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "look_right") .identifier("controlify", "look_right")
.defaultBind(GamepadBinds.RIGHT_STICK_RIGHT) .defaultBind(GamepadBinds.RIGHT_STICK_RIGHT)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
if (controller instanceof GamepadController gamepad && gamepad.hasGyro()) { if (controller instanceof GamepadController gamepad && gamepad.hasGyro()) {
register(GAMEPAD_GYRO_BUTTON = ControllerBindingBuilder.create(controller) register(GAMEPAD_GYRO_BUTTON = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gamepad_gyro_button") .identifier("controlify", "gamepad_gyro_button")
.defaultBind(new EmptyBind<>()) .defaultBind(new EmptyBind<>())
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
} else { } else {
GAMEPAD_GYRO_BUTTON = null; GAMEPAD_GYRO_BUTTON = null;
@ -127,209 +136,249 @@ public class ControllerBindings<T extends ControllerState> {
.identifier("controlify", "jump") .identifier("controlify", "jump")
.defaultBind(GamepadBinds.A_BUTTON) .defaultBind(GamepadBinds.A_BUTTON)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(SPRINT = ControllerBindingBuilder.create(controller) register(SPRINT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "sprint") .identifier("controlify", "sprint")
.defaultBind(GamepadBinds.LEFT_STICK_PRESS) .defaultBind(GamepadBinds.LEFT_STICK_PRESS)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keySprint, () -> controller.config().toggleSprint) .vanillaOverride(options.keySprint, () -> controller.config().toggleSprint)
.build()); .build());
register(SNEAK = ControllerBindingBuilder.create(controller) register(SNEAK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "sneak") .identifier("controlify", "sneak")
.defaultBind(GamepadBinds.RIGHT_STICK_PRESS) .defaultBind(GamepadBinds.RIGHT_STICK_PRESS)
.category(MOVEMENT_CATEGORY) .category(MOVEMENT_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(ATTACK = ControllerBindingBuilder.create(controller) register(ATTACK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "attack") .identifier("controlify", "attack")
.defaultBind(GamepadBinds.RIGHT_TRIGGER) .defaultBind(GamepadBinds.RIGHT_TRIGGER)
.category(GAMEPLAY_CATEGORY) .category(GAMEPLAY_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keyAttack, () -> false) .vanillaOverride(options.keyAttack, () -> false)
.build()); .build());
register(USE = ControllerBindingBuilder.create(controller) register(USE = ControllerBindingBuilder.create(controller)
.identifier("controlify", "use") .identifier("controlify", "use")
.defaultBind(GamepadBinds.LEFT_TRIGGER) .defaultBind(GamepadBinds.LEFT_TRIGGER)
.category(GAMEPLAY_CATEGORY) .category(GAMEPLAY_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keyUse, () -> false) .vanillaOverride(options.keyUse, () -> false)
.build()); .build());
register(DROP = ControllerBindingBuilder.create(controller) register(DROP = ControllerBindingBuilder.create(controller)
.identifier("controlify", "drop") .identifier("controlify", "drop")
.defaultBind(GamepadBinds.DPAD_DOWN) .defaultBind(GamepadBinds.DPAD_DOWN)
.category(GAMEPLAY_CATEGORY) .category(GAMEPLAY_CATEGORY)
.context(BindContexts.INGAME, BindContexts.INVENTORY)
.build()); .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)
.category(INVENTORY_CATEGORY) .category(INVENTORY_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(PREV_SLOT = ControllerBindingBuilder.create(controller) register(PREV_SLOT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "prev_slot") .identifier("controlify", "prev_slot")
.defaultBind(GamepadBinds.LEFT_BUMPER) .defaultBind(GamepadBinds.LEFT_BUMPER)
.category(INVENTORY_CATEGORY) .category(INVENTORY_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(PAUSE = ControllerBindingBuilder.create(controller) register(PAUSE = ControllerBindingBuilder.create(controller)
.identifier("controlify", "pause") .identifier("controlify", "pause")
.defaultBind(GamepadBinds.START) .defaultBind(GamepadBinds.START)
.category(GAMEPLAY_CATEGORY) .category(GAMEPLAY_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(INVENTORY = ControllerBindingBuilder.create(controller) register(INVENTORY = ControllerBindingBuilder.create(controller)
.identifier("controlify", "inventory") .identifier("controlify", "inventory")
.defaultBind(GamepadBinds.Y_BUTTON) .defaultBind(GamepadBinds.Y_BUTTON)
.category(INVENTORY_CATEGORY) .category(INVENTORY_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keyInventory, () -> false) .vanillaOverride(options.keyInventory, () -> false)
.build()); .build());
register(CHANGE_PERSPECTIVE = ControllerBindingBuilder.create(controller) register(CHANGE_PERSPECTIVE = ControllerBindingBuilder.create(controller)
.identifier("controlify", "change_perspective") .identifier("controlify", "change_perspective")
.defaultBind(GamepadBinds.BACK) .defaultBind(GamepadBinds.BACK)
.category(GAMEPLAY_CATEGORY) .category(GAMEPLAY_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keyTogglePerspective, () -> false) .vanillaOverride(options.keyTogglePerspective, () -> false)
.build()); .build());
register(SWAP_HANDS = ControllerBindingBuilder.create(controller) register(SWAP_HANDS = ControllerBindingBuilder.create(controller)
.identifier("controlify", "swap_hands") .identifier("controlify", "swap_hands")
.defaultBind(GamepadBinds.X_BUTTON) .defaultBind(GamepadBinds.X_BUTTON)
.category(INVENTORY_CATEGORY) .category(INVENTORY_CATEGORY)
.context(BindContexts.INGAME, BindContexts.INVENTORY)
.vanillaOverride(options.keySwapOffhand, () -> false) .vanillaOverride(options.keySwapOffhand, () -> false)
.build()); .build());
register(OPEN_CHAT = ControllerBindingBuilder.create(controller) register(OPEN_CHAT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "open_chat") .identifier("controlify", "open_chat")
.defaultBind(GamepadBinds.DPAD_UP) .defaultBind(GamepadBinds.DPAD_UP)
.category(MISC_CATEGORY) .category(MISC_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keyChat, () -> false) .vanillaOverride(options.keyChat, () -> false)
.build()); .build());
register(GUI_PRESS = ControllerBindingBuilder.create(controller) register(GUI_PRESS = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_press") .identifier("controlify", "gui_press")
.defaultBind(GamepadBinds.A_BUTTON) .defaultBind(GamepadBinds.A_BUTTON)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(GUI_BACK = ControllerBindingBuilder.create(controller) register(GUI_BACK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_back") .identifier("controlify", "gui_back")
.defaultBind(GamepadBinds.B_BUTTON) .defaultBind(GamepadBinds.B_BUTTON)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI, BindContexts.GUI_VMOUSE)
.build()); .build());
register(GUI_NEXT_TAB = ControllerBindingBuilder.create(controller) register(GUI_NEXT_TAB = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_next_tab") .identifier("controlify", "gui_next_tab")
.defaultBind(GamepadBinds.RIGHT_BUMPER) .defaultBind(GamepadBinds.RIGHT_BUMPER)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI, BindContexts.GUI_VMOUSE)
.build()); .build());
register(GUI_PREV_TAB = ControllerBindingBuilder.create(controller) register(GUI_PREV_TAB = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_prev_tab") .identifier("controlify", "gui_prev_tab")
.defaultBind(GamepadBinds.LEFT_BUMPER) .defaultBind(GamepadBinds.LEFT_BUMPER)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI, BindContexts.GUI_VMOUSE)
.build()); .build());
register(GUI_ABSTRACT_ACTION_1 = ControllerBindingBuilder.create(controller) register(GUI_ABSTRACT_ACTION_1 = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_abstract_action_1") .identifier("controlify", "gui_abstract_action_1")
.defaultBind(GamepadBinds.X_BUTTON) .defaultBind(GamepadBinds.X_BUTTON)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(GUI_ABSTRACT_ACTION_2 = ControllerBindingBuilder.create(controller) register(GUI_ABSTRACT_ACTION_2 = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_abstract_action_2") .identifier("controlify", "gui_abstract_action_2")
.defaultBind(GamepadBinds.Y_BUTTON) .defaultBind(GamepadBinds.Y_BUTTON)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(PICK_BLOCK = ControllerBindingBuilder.create(controller) register(PICK_BLOCK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "pick_block") .identifier("controlify", "pick_block")
.defaultBind(GamepadBinds.DPAD_LEFT) .defaultBind(GamepadBinds.DPAD_LEFT)
.category(GAMEPLAY_CATEGORY) .category(GAMEPLAY_CATEGORY)
.context(BindContexts.INGAME)
.vanillaOverride(options.keyPickItem, () -> false) .vanillaOverride(options.keyPickItem, () -> false)
.build()); .build());
register(TOGGLE_HUD_VISIBILITY = ControllerBindingBuilder.create(controller) register(TOGGLE_HUD_VISIBILITY = ControllerBindingBuilder.create(controller)
.identifier("controlify", "toggle_hud_visibility") .identifier("controlify", "toggle_hud_visibility")
.defaultBind(new EmptyBind<>()) .defaultBind(new EmptyBind<>())
.category(MISC_CATEGORY) .category(MISC_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(SHOW_PLAYER_LIST = ControllerBindingBuilder.create(controller) register(SHOW_PLAYER_LIST = ControllerBindingBuilder.create(controller)
.identifier("controlify", "show_player_list") .identifier("controlify", "show_player_list")
.defaultBind(GamepadBinds.DPAD_RIGHT) .defaultBind(GamepadBinds.DPAD_RIGHT)
.category(MISC_CATEGORY) .category(MISC_CATEGORY)
.context(BindContexts.INGAME)
.build()); .build());
register(VMOUSE_MOVE_UP = ControllerBindingBuilder.create(controller) register(VMOUSE_MOVE_UP = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_move_up") .identifier("controlify", "vmouse_move_up")
.defaultBind(GamepadBinds.LEFT_STICK_FORWARD) .defaultBind(GamepadBinds.LEFT_STICK_FORWARD)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_MOVE_DOWN = ControllerBindingBuilder.create(controller) register(VMOUSE_MOVE_DOWN = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_move_down") .identifier("controlify", "vmouse_move_down")
.defaultBind(GamepadBinds.LEFT_STICK_BACKWARD) .defaultBind(GamepadBinds.LEFT_STICK_BACKWARD)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_MOVE_LEFT = ControllerBindingBuilder.create(controller) register(VMOUSE_MOVE_LEFT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_move_left") .identifier("controlify", "vmouse_move_left")
.defaultBind(GamepadBinds.LEFT_STICK_LEFT) .defaultBind(GamepadBinds.LEFT_STICK_LEFT)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_MOVE_RIGHT = ControllerBindingBuilder.create(controller) register(VMOUSE_MOVE_RIGHT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_move_right") .identifier("controlify", "vmouse_move_right")
.defaultBind(GamepadBinds.LEFT_STICK_RIGHT) .defaultBind(GamepadBinds.LEFT_STICK_RIGHT)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_LCLICK = ControllerBindingBuilder.create(controller) register(VMOUSE_LCLICK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_lclick") .identifier("controlify", "vmouse_lclick")
.defaultBind(GamepadBinds.A_BUTTON) .defaultBind(GamepadBinds.A_BUTTON)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_RCLICK = ControllerBindingBuilder.create(controller) register(VMOUSE_RCLICK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_rclick") .identifier("controlify", "vmouse_rclick")
.defaultBind(GamepadBinds.X_BUTTON) .defaultBind(GamepadBinds.X_BUTTON)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_SHIFT_CLICK = ControllerBindingBuilder.create(controller) register(VMOUSE_SHIFT_CLICK = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_shift_click") .identifier("controlify", "vmouse_shift_click")
.defaultBind(GamepadBinds.Y_BUTTON) .defaultBind(GamepadBinds.Y_BUTTON)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .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)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_SCROLL_DOWN = ControllerBindingBuilder.create(controller) register(VMOUSE_SCROLL_DOWN = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_scroll_down") .identifier("controlify", "vmouse_scroll_down")
.defaultBind(GamepadBinds.RIGHT_STICK_BACKWARD) .defaultBind(GamepadBinds.RIGHT_STICK_BACKWARD)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_SHIFT = ControllerBindingBuilder.create(controller) register(VMOUSE_SHIFT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_shift") .identifier("controlify", "vmouse_shift")
.defaultBind(GamepadBinds.LEFT_STICK_PRESS) .defaultBind(GamepadBinds.LEFT_STICK_PRESS)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(VMOUSE_TOGGLE = ControllerBindingBuilder.create(controller) register(VMOUSE_TOGGLE = ControllerBindingBuilder.create(controller)
.identifier("controlify", "vmouse_toggle") .identifier("controlify", "vmouse_toggle")
.defaultBind(GamepadBinds.BACK) .defaultBind(GamepadBinds.BACK)
.category(VMOUSE_CATEGORY) .category(VMOUSE_CATEGORY)
.context(BindContexts.GUI_VMOUSE)
.build()); .build());
register(GUI_NAVI_UP = ControllerBindingBuilder.create(controller) register(GUI_NAVI_UP = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_navi_up") .identifier("controlify", "gui_navi_up")
.defaultBind(GamepadBinds.LEFT_STICK_FORWARD) .defaultBind(GamepadBinds.LEFT_STICK_FORWARD)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(GUI_NAVI_DOWN = ControllerBindingBuilder.create(controller) register(GUI_NAVI_DOWN = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_navi_down") .identifier("controlify", "gui_navi_down")
.defaultBind(GamepadBinds.LEFT_STICK_BACKWARD) .defaultBind(GamepadBinds.LEFT_STICK_BACKWARD)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(GUI_NAVI_LEFT = ControllerBindingBuilder.create(controller) register(GUI_NAVI_LEFT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_navi_left") .identifier("controlify", "gui_navi_left")
.defaultBind(GamepadBinds.LEFT_STICK_LEFT) .defaultBind(GamepadBinds.LEFT_STICK_LEFT)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(GUI_NAVI_RIGHT = ControllerBindingBuilder.create(controller) register(GUI_NAVI_RIGHT = ControllerBindingBuilder.create(controller)
.identifier("controlify", "gui_navi_right") .identifier("controlify", "gui_navi_right")
.defaultBind(GamepadBinds.LEFT_STICK_RIGHT) .defaultBind(GamepadBinds.LEFT_STICK_RIGHT)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(CYCLE_OPT_FORWARD = ControllerBindingBuilder.create(controller) register(CYCLE_OPT_FORWARD = ControllerBindingBuilder.create(controller)
.identifier("controlify", "cycle_opt_forward") .identifier("controlify", "cycle_opt_forward")
.defaultBind(GamepadBinds.RIGHT_STICK_RIGHT) .defaultBind(GamepadBinds.RIGHT_STICK_RIGHT)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(CYCLE_OPT_BACKWARD = ControllerBindingBuilder.create(controller) register(CYCLE_OPT_BACKWARD = ControllerBindingBuilder.create(controller)
.identifier("controlify", "cycle_opt_backward") .identifier("controlify", "cycle_opt_backward")
.defaultBind(GamepadBinds.RIGHT_STICK_LEFT) .defaultBind(GamepadBinds.RIGHT_STICK_LEFT)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.GUI)
.build()); .build());
register(CLEAR_BINDING = ControllerBindingBuilder.create(controller) register(CLEAR_BINDING = ControllerBindingBuilder.create(controller)
.identifier("controlify", "clear_binding") .identifier("controlify", "clear_binding")
.defaultBind(GamepadBinds.RIGHT_STICK_PRESS) .defaultBind(GamepadBinds.RIGHT_STICK_PRESS)
.category(GUI_CATEGORY) .category(GUI_CATEGORY)
.context(BindContexts.CONTROLIFY_CONFIG)
.build()); .build());
for (var constructor : CUSTOM_BINDS.values()) { for (var constructor : CUSTOM_BINDS.values()) {

View File

@ -13,11 +13,10 @@ public class YACLScreenProcessor extends ScreenProcessor<YACLScreen> {
} }
@Override @Override
protected void handleComponentNavigation(Controller<?, ?> controller) { protected void handleButtons(Controller<?, ?> controller) {
if (controller.bindings().GUI_ABSTRACT_ACTION_1.justPressed()) { if (controller.bindings().GUI_ABSTRACT_ACTION_1.justPressed()) {
this.playClackSound(); this.playClackSound();
screen.finishedSaveButton.onPress(); screen.finishedSaveButton.onPress();
return;
} }
if (controller.bindings().GUI_NEXT_TAB.justPressed()) { if (controller.bindings().GUI_NEXT_TAB.justPressed()) {
@ -31,12 +30,11 @@ public class YACLScreenProcessor extends ScreenProcessor<YACLScreen> {
screen.changeCategory(idx); screen.changeCategory(idx);
} }
super.handleComponentNavigation(controller); super.handleButtons(controller);
} }
@Override @Override
public void onWidgetRebuild() { public void onWidgetRebuild() {
// currently doesn't work because TextScaledButtonWidget overrides renderString
ButtonGuideApi.addGuideToButton(screen.finishedSaveButton, bindings -> bindings.GUI_ABSTRACT_ACTION_1, ButtonRenderPosition.TEXT, ButtonGuidePredicate.ALWAYS); ButtonGuideApi.addGuideToButton(screen.finishedSaveButton, bindings -> bindings.GUI_ABSTRACT_ACTION_1, ButtonRenderPosition.TEXT, ButtonGuidePredicate.ALWAYS);
} }

View File

@ -12,6 +12,7 @@ import dev.isxander.yacl.api.Option;
import dev.isxander.yacl.api.utils.Dimension; import dev.isxander.yacl.api.utils.Dimension;
import dev.isxander.yacl.gui.YACLScreen; import dev.isxander.yacl.gui.YACLScreen;
import dev.isxander.yacl.gui.controllers.ControllerWidget; import dev.isxander.yacl.gui.controllers.ControllerWidget;
import dev.isxander.yacl.gui.utils.GuiUtils;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
@ -21,6 +22,7 @@ import java.util.Optional;
public abstract class AbstractBindController<T extends ControllerState> implements Controller<IBind<T>> { public abstract class AbstractBindController<T extends ControllerState> implements Controller<IBind<T>> {
private final Option<IBind<T>> option; private final Option<IBind<T>> option;
public final dev.isxander.controlify.controller.Controller<T, ?> controller; public final dev.isxander.controlify.controller.Controller<T, ?> controller;
private boolean conflicting;
public AbstractBindController(Option<IBind<T>> option, dev.isxander.controlify.controller.Controller<T, ?> controller) { public AbstractBindController(Option<IBind<T>> option, dev.isxander.controlify.controller.Controller<T, ?> controller) {
this.option = option; this.option = option;
@ -37,6 +39,14 @@ public abstract class AbstractBindController<T extends ControllerState> implemen
return Component.empty(); return Component.empty();
} }
public void setConflicting(boolean conflicting) {
this.conflicting = conflicting;
}
public boolean getConflicting() {
return this.conflicting;
}
@Override @Override
public abstract AbstractBindControllerElement<T> provideWidget(YACLScreen yaclScreen, Dimension<Integer> dimension); public abstract AbstractBindControllerElement<T> provideWidget(YACLScreen yaclScreen, Dimension<Integer> dimension);
@ -85,14 +95,16 @@ public abstract class AbstractBindController<T extends ControllerState> implemen
public boolean overrideControllerButtons(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller<?, ?> controller) { public boolean overrideControllerButtons(ScreenProcessor<?> screen, dev.isxander.controlify.controller.Controller<?, ?> controller) {
if (controller != control.controller) return true; if (controller != control.controller) return true;
if (controller.bindings().CLEAR_BINDING.justPressed()) { if (!justTookInput && !awaitingControllerInput) {
control.option().requestSet(new EmptyBind<>()); if (controller.bindings().CLEAR_BINDING.justPressed()) {
return true; control.option().requestSet(new EmptyBind<>());
} return true;
}
if (controller.bindings().GUI_PRESS.justPressed() && !awaitingControllerInput) { if (controller.bindings().GUI_PRESS.justPressed()) {
ControllerBindHandler.setBindListener(this); ControllerBindHandler.setBindListener(this);
return awaitingControllerInput = true; return awaitingControllerInput = true;
}
} }
if (justTookInput) { if (justTookInput) {
@ -136,6 +148,11 @@ public abstract class AbstractBindController<T extends ControllerState> implemen
return control.option().pendingValue().drawSize().width(); return control.option().pendingValue().drawSize().width();
} }
@Override
protected int getValueColor() {
return control.conflicting ? 0xFF5555 : super.getValueColor();
}
public abstract Optional<IBind<T>> getPressedBind(); public abstract Optional<IBind<T>> getPressedBind();
} }
} }

View File

@ -1,21 +1,16 @@
package dev.isxander.controlify.config.gui; package dev.isxander.controlify.config.gui;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.api.bind.ControllerBinding; import dev.isxander.controlify.api.bind.ControllerBinding;
import dev.isxander.controlify.bindings.ControllerBindingImpl; import dev.isxander.controlify.bindings.BindContext;
import dev.isxander.controlify.bindings.IBind;
import dev.isxander.controlify.config.GlobalSettings; import dev.isxander.controlify.config.GlobalSettings;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerConfig; import dev.isxander.controlify.controller.ControllerConfig;
import dev.isxander.controlify.controller.ControllerState; import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.controller.gamepad.GamepadController; import dev.isxander.controlify.controller.gamepad.GamepadController;
import dev.isxander.controlify.controller.gamepad.GamepadState;
import dev.isxander.controlify.controller.gamepad.BuiltinGamepadTheme; import dev.isxander.controlify.controller.gamepad.BuiltinGamepadTheme;
import dev.isxander.controlify.controller.joystick.JoystickController;
import dev.isxander.controlify.controller.joystick.SingleJoystickController; import dev.isxander.controlify.controller.joystick.SingleJoystickController;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.mapping.JoystickMapping; import dev.isxander.controlify.controller.joystick.mapping.JoystickMapping;
import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen; import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen;
import dev.isxander.controlify.reacharound.ReachAroundMode; import dev.isxander.controlify.reacharound.ReachAroundMode;
@ -29,7 +24,6 @@ import dev.isxander.yacl.gui.controllers.TickBoxController;
import dev.isxander.yacl.gui.controllers.cycling.CyclingListController; import dev.isxander.yacl.gui.controllers.cycling.CyclingListController;
import dev.isxander.yacl.gui.controllers.cycling.EnumController; import dev.isxander.yacl.gui.controllers.cycling.EnumController;
import dev.isxander.yacl.gui.controllers.slider.FloatSliderController; import dev.isxander.yacl.gui.controllers.slider.FloatSliderController;
import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController;
import dev.isxander.yacl.gui.controllers.string.StringController; import dev.isxander.yacl.gui.controllers.string.StringController;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.Util; import net.minecraft.Util;
@ -39,6 +33,7 @@ import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@ -69,7 +64,7 @@ public class YACLHelper {
.name(Component.translatable("controlify.gui.load_vibration_natives")) .name(Component.translatable("controlify.gui.load_vibration_natives"))
.tooltip(Component.translatable("controlify.gui.load_vibration_natives.tooltip")) .tooltip(Component.translatable("controlify.gui.load_vibration_natives.tooltip"))
.tooltip(Component.translatable("controlify.gui.load_vibration_natives.tooltip.warning").withStyle(ChatFormatting.RED)) .tooltip(Component.translatable("controlify.gui.load_vibration_natives.tooltip.warning").withStyle(ChatFormatting.RED))
.binding(GlobalSettings.DEFAULT.loadVibrationNatives, () -> globalSettings.loadVibrationNatives, v -> globalSettings.loadVibrationNatives = v) .binding(true, () -> globalSettings.loadVibrationNatives, v -> globalSettings.loadVibrationNatives = v)
.controller(opt -> new BooleanController(opt, BooleanController.YES_NO_FORMATTER, false)) .controller(opt -> new BooleanController(opt, BooleanController.YES_NO_FORMATTER, false))
.flag(OptionFlag.GAME_RESTART) .flag(OptionFlag.GAME_RESTART)
.build()) .build())
@ -114,7 +109,7 @@ public class YACLHelper {
return yacl.build().generateScreen(parent); return yacl.build().generateScreen(parent);
} }
private static ConfigCategory createControllerCategory(Controller<?, ?> controller, Option<Boolean> globalVibrationOption) { private static <S extends ControllerState, C extends ControllerConfig> ConfigCategory createControllerCategory(Controller<S, C> controller, Option<Boolean> globalVibrationOption) {
if (!controller.canBeUsed()) { if (!controller.canBeUsed()) {
return PlaceholderCategory.createBuilder() return PlaceholderCategory.createBuilder()
.name(Component.literal(controller.name())) .name(Component.literal(controller.name()))
@ -245,16 +240,45 @@ public class YACLHelper {
var controlsGroup = OptionGroup.createBuilder() var controlsGroup = OptionGroup.createBuilder()
.name(Component.translatable("controlify.gui.group.controls")); .name(Component.translatable("controlify.gui.group.controls"));
List<OptionBindPair> optionBinds = new ArrayList<>();
groupBindings(controller.bindings().registry().values()).forEach((categoryName, bindGroup) -> { groupBindings(controller.bindings().registry().values()).forEach((categoryName, bindGroup) -> {
controlsGroup.option(LabelOption.create(categoryName)); controlsGroup.option(LabelOption.create(categoryName));
controlsGroup.options(bindGroup.stream().map(ControllerBinding::generateYACLOption).toList()); controlsGroup.options(bindGroup.stream().map(binding -> {
Option.Builder<?> option = binding.startYACLOption()
.listener((opt, val) -> updateConflictingBinds(optionBinds));
Option<?> built = option.build();
optionBinds.add(new OptionBindPair(built, binding));
return built;
}).toList());
}); });
updateConflictingBinds(optionBinds);
category.group(controlsGroup.build()); category.group(controlsGroup.build());
return category.build(); return category.build();
} }
private static void updateConflictingBinds(List<OptionBindPair> all) {
all.forEach(pair -> ((AbstractBindController<?>) pair.option().controller()).setConflicting(false));
for (OptionBindPair opt : all) {
var ctxs = BindContext.flatten(opt.binding().contexts());
List<OptionBindPair> conflicting = all.stream()
.filter(pair -> pair.binding() != opt.binding())
.filter(pair -> {
boolean contextsMatch = BindContext.flatten(pair.binding().contexts())
.stream()
.anyMatch(ctxs::contains);
boolean bindMatches = pair.option().pendingValue().equals(opt.option().pendingValue());
return contextsMatch && bindMatches;
}).toList();
conflicting.forEach(conflict -> ((AbstractBindController<?>) conflict.option().controller()).setConflicting(true));
}
}
private static OptionGroup makeVibrationGroup(Option<Boolean> globalVibrationOption, Controller<?, ?> controller) { private static OptionGroup makeVibrationGroup(Option<Boolean> globalVibrationOption, Controller<?, ?> controller) {
boolean canRumble = controller.supportsRumble(); boolean canRumble = controller.supportsRumble();
var config = controller.config(); var config = controller.config();
@ -428,8 +452,11 @@ public class YACLHelper {
} }
} }
private static <T extends ControllerState> Map<Component, List<ControllerBinding>> groupBindings(Collection<ControllerBinding> bindings) { private static Map<Component, List<ControllerBinding>> groupBindings(Collection<ControllerBinding> bindings) {
return bindings.stream() return bindings.stream()
.collect(Collectors.groupingBy(ControllerBinding::category, LinkedHashMap::new, Collectors.toList())); .collect(Collectors.groupingBy(ControllerBinding::category, LinkedHashMap::new, Collectors.toList()));
} }
private record OptionBindPair(Option<?> option, ControllerBinding binding) {
}
} }

View File

@ -34,8 +34,11 @@ public class ScreenProcessor<T extends Screen> {
public void onControllerUpdate(Controller<?, ?> controller) { public void onControllerUpdate(Controller<?, ?> controller) {
if (!Controlify.instance().virtualMouseHandler().isVirtualMouseEnabled()) { if (!Controlify.instance().virtualMouseHandler().isVirtualMouseEnabled()) {
handleComponentNavigation(controller); if (!handleComponentNavOverride(controller))
handleButtons(controller); handleComponentNavigation(controller);
if (!handleComponentButtonOverride(controller))
handleButtons(controller);
} else { } else {
handleScreenVMouse(controller); handleScreenVMouse(controller);
} }
@ -58,13 +61,7 @@ public class ScreenProcessor<T extends Screen> {
if (screen.getFocused() == null) if (screen.getFocused() == null)
setInitialFocus(); setInitialFocus();
var focusTree = getFocusTree(); var focuses = List.copyOf(getFocusTree());
var focuses = List.copyOf(focusTree);
while (!focusTree.isEmpty()) {
var focused = focusTree.poll();
var processor = ComponentProcessorProvider.provide(focused);
if (processor.overrideControllerNavigation(this, controller)) return;
}
var accessor = (ScreenAccessor) screen; var accessor = (ScreenAccessor) screen;
@ -114,15 +111,9 @@ public class ScreenProcessor<T extends Screen> {
} }
protected void handleButtons(Controller<?, ?> controller) { protected void handleButtons(Controller<?, ?> controller) {
var focusTree = getFocusTree(); if (controller.bindings().GUI_PRESS.justPressed()) {
while (!focusTree.isEmpty()) {
var focused = focusTree.poll();
var processor = ComponentProcessorProvider.provide(focused);
if (processor.overrideControllerButtons(this, controller)) return;
}
if (controller.bindings().GUI_PRESS.justPressed())
screen.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0); screen.keyPressed(GLFW.GLFW_KEY_ENTER, 0, 0);
}
if (controller.bindings().GUI_BACK.justPressed()) { if (controller.bindings().GUI_BACK.justPressed()) {
this.playClackSound(); this.playClackSound();
screen.onClose(); screen.onClose();
@ -133,6 +124,27 @@ public class ScreenProcessor<T extends Screen> {
} }
protected boolean handleComponentButtonOverride(Controller<?, ?> controller) {
var focusTree = getFocusTree();
while (!focusTree.isEmpty()) {
var focused = focusTree.poll();
var processor = ComponentProcessorProvider.provide(focused);
if (processor.overrideControllerButtons(this, controller)) return true;
}
return false;
}
protected boolean handleComponentNavOverride(Controller<?, ?> controller) {
var focusTree = getFocusTree();
while (!focusTree.isEmpty()) {
var focused = focusTree.poll();
var processor = ComponentProcessorProvider.provide(focused);
if (processor.overrideControllerNavigation(this, controller)) return true;
}
return false;
}
protected void handleTabNavigation(Controller<?, ?> controller) { protected void handleTabNavigation(Controller<?, ?> controller) {
var nextTab = controller.bindings().GUI_NEXT_TAB.justPressed(); var nextTab = controller.bindings().GUI_NEXT_TAB.justPressed();
var prevTab = controller.bindings().GUI_PREV_TAB.justPressed(); var prevTab = controller.bindings().GUI_PREV_TAB.justPressed();