From 647e03134f0976707c069eb3318f0eb133cfe3e9 Mon Sep 17 00:00:00 2001 From: LambdAurora Date: Thu, 2 Jan 2020 00:31:00 +0100 Subject: [PATCH] :sparkles: Add chording and new button assignment system. --- .../lambdacontrols/LambdaInput.java | 108 +++++++++++------- .../compat/LambdaControlsCompat.java | 4 +- .../lambdacontrols/compat/OkZoomerCompat.java | 2 + .../controller/ButtonBinding.java | 2 +- .../gui/ControllerButtonWidget.java | 24 +++- .../gui/ControlsListWidget.java | 39 +++++-- .../gui/LambdaControlsControlsScreen.java | 1 + .../lambdacontrols/gui/LambdaControlsHud.java | 8 +- .../gui/LambdaControlsSettingsScreen.java | 1 - .../mixin/SettingsScreenMixin.java | 6 - .../assets/lambdacontrols/lang/en_us.json | 3 + .../assets/lambdacontrols/lang/fr_ca.json | 3 + .../assets/lambdacontrols/lang/fr_fr.json | 3 + 13 files changed, 135 insertions(+), 69 deletions(-) diff --git a/src/main/java/me/lambdaurora/lambdacontrols/LambdaInput.java b/src/main/java/me/lambdaurora/lambdacontrols/LambdaInput.java index 47bdfac..1c52de0 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/LambdaInput.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/LambdaInput.java @@ -47,8 +47,7 @@ import java.util.Map; import java.util.Optional; import static me.lambdaurora.lambdacontrols.controller.ButtonBinding.axis_as_button; -import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_X; -import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_RIGHT_Y; +import static org.lwjgl.glfw.GLFW.*; /** * Represents the LambdaControls' input handler. @@ -135,15 +134,20 @@ public class LambdaInput this.fetch_axe_input(client, state, true); }); - InputManager.update_bindings(client); + boolean allow_input = true; + + if (client.currentScreen instanceof LambdaControlsControlsScreen && ((LambdaControlsControlsScreen) client.currentScreen).focused_binding != null) + allow_input = false; + + if (allow_input) + InputManager.update_bindings(client); if (this.ignore_next_a > 0) this.ignore_next_a--; - if (client.currentScreen instanceof LambdaControlsControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::is_unpressed)) - { + if (client.currentScreen instanceof LambdaControlsControlsScreen && InputManager.STATES.entrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::is_unpressed)) { LambdaControlsControlsScreen controls_screen = (LambdaControlsControlsScreen) client.currentScreen; - if (controls_screen.focused_binding != null) { + if (controls_screen.focused_binding != null && !controls_screen.waiting) { int[] buttons = new int[controls_screen.current_buttons.size()]; for (int i = 0; i < controls_screen.current_buttons.size(); i++) buttons[i] = controls_screen.current_buttons.get(i); @@ -253,10 +257,19 @@ public class LambdaInput private void handle_button(@NotNull MinecraftClient client, int button, int action, boolean state) { - if (client.currentScreen instanceof LambdaControlsControlsScreen && action == 0) { + if (client.currentScreen instanceof LambdaControlsControlsScreen) { LambdaControlsControlsScreen controls_screen = (LambdaControlsControlsScreen) client.currentScreen; if (controls_screen.focused_binding != null) { - controls_screen.current_buttons.add(button); + if (action == 0 && !controls_screen.current_buttons.contains(button)) { + controls_screen.current_buttons.add(button); + + int[] buttons = new int[controls_screen.current_buttons.size()]; + for (int i = 0; i < controls_screen.current_buttons.size(); i++) + buttons[i] = controls_screen.current_buttons.get(i); + controls_screen.focused_binding.set_button(buttons); + + controls_screen.waiting = false; + } return; } } @@ -335,47 +348,60 @@ public class LambdaInput { int as_button_state = value > 0.5F ? 1 : (value < -0.5F ? 2 : 0); - if (client.currentScreen instanceof LambdaControlsControlsScreen && as_button_state != 0 - && !(as_button_state == 2 && (axis == GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER || - axis == ButtonBinding.controller2_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) || axis == ButtonBinding.controller2_button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)))) { + if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER || axis == ButtonBinding.controller2_button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) || + axis == ButtonBinding.controller2_button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) + if (as_button_state == 2) + as_button_state = 0; + + { + boolean current_plus_state = as_button_state == 1; + boolean current_minus_state = as_button_state == 2; + ButtonState previous_plus_state = InputManager.STATES.getOrDefault(axis_as_button(axis, true), ButtonState.NONE); + ButtonState previous_minus_state = InputManager.STATES.getOrDefault(axis_as_button(axis, false), ButtonState.NONE); + + if (current_plus_state != previous_plus_state.is_pressed()) { + InputManager.STATES.put(axis_as_button(axis, true), current_plus_state ? ButtonState.PRESS : ButtonState.RELEASE); + if (current_plus_state) + BUTTON_COOLDOWNS.put(axis_as_button(axis, true), 5); + } else if (current_plus_state) { + InputManager.STATES.put(axis_as_button(axis, true), ButtonState.REPEAT); + if (BUTTON_COOLDOWNS.getOrDefault(axis_as_button(axis, true), 0) == 0) { + BUTTON_COOLDOWNS.put(axis_as_button(axis, true), 5); + } + } + + if (current_minus_state != previous_minus_state.is_pressed()) { + InputManager.STATES.put(axis_as_button(axis, false), current_minus_state ? ButtonState.PRESS : ButtonState.RELEASE); + if (current_minus_state) + BUTTON_COOLDOWNS.put(axis_as_button(axis, false), 5); + } else if (current_minus_state) { + InputManager.STATES.put(axis_as_button(axis, false), ButtonState.REPEAT); + if (BUTTON_COOLDOWNS.getOrDefault(axis_as_button(axis, false), 0) == 0) { + BUTTON_COOLDOWNS.put(axis_as_button(axis, false), 5); + } + } + } + + if (client.currentScreen instanceof LambdaControlsControlsScreen) { LambdaControlsControlsScreen controls_screen = (LambdaControlsControlsScreen) client.currentScreen; if (controls_screen.focused_binding != null) { - controls_screen.current_buttons.add(axis_as_button(axis, as_button_state == 1)); + if (as_button_state != 0 && !controls_screen.current_buttons.contains(axis_as_button(axis, as_button_state == 1))) { + + controls_screen.current_buttons.add(axis_as_button(axis, as_button_state == 1)); + + int[] buttons = new int[controls_screen.current_buttons.size()]; + for (int i = 0; i < controls_screen.current_buttons.size(); i++) + buttons[i] = controls_screen.current_buttons.get(i); + controls_screen.focused_binding.set_button(buttons); + + controls_screen.waiting = false; + } return; } } double dead_zone = this.config.get_dead_zone(); if (client.currentScreen == null) { - { - boolean current_plus_state = as_button_state == 1; - boolean current_minus_state = as_button_state == 2; - ButtonState previous_plus_state = InputManager.STATES.getOrDefault(axis_as_button(axis, true), ButtonState.NONE); - ButtonState previous_minus_state = InputManager.STATES.getOrDefault(axis_as_button(axis, false), ButtonState.NONE); - - if (current_plus_state != previous_plus_state.is_pressed()) { - InputManager.STATES.put(axis_as_button(axis, true), current_plus_state ? ButtonState.PRESS : ButtonState.RELEASE); - if (current_plus_state) - BUTTON_COOLDOWNS.put(axis_as_button(axis, true), 5); - } else if (current_plus_state) { - InputManager.STATES.put(axis_as_button(axis, true), ButtonState.REPEAT); - if (BUTTON_COOLDOWNS.getOrDefault(axis_as_button(axis, true), 0) == 0) { - BUTTON_COOLDOWNS.put(axis_as_button(axis, true), 5); - } - } - - if (current_minus_state != previous_minus_state.is_pressed()) { - InputManager.STATES.put(axis_as_button(axis, false), current_minus_state ? ButtonState.PRESS : ButtonState.RELEASE); - if (current_minus_state) - BUTTON_COOLDOWNS.put(axis_as_button(axis, false), 5); - } else if (current_minus_state) { - InputManager.STATES.put(axis_as_button(axis, false), ButtonState.REPEAT); - if (BUTTON_COOLDOWNS.getOrDefault(axis_as_button(axis, false), 0) == 0) { - BUTTON_COOLDOWNS.put(axis_as_button(axis, false), 5); - } - } - } - // Handles the look direction. this.handle_look(client, axis, (float) (abs_value / (1.0 - this.config.get_dead_zone())), state); } else { diff --git a/src/main/java/me/lambdaurora/lambdacontrols/compat/LambdaControlsCompat.java b/src/main/java/me/lambdaurora/lambdacontrols/compat/LambdaControlsCompat.java index 7ab1f93..de25272 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/compat/LambdaControlsCompat.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/compat/LambdaControlsCompat.java @@ -24,8 +24,6 @@ import org.jetbrains.annotations.NotNull; */ public class LambdaControlsCompat { - private static final String OKZOOMER_CLASS_PATH = "io.github.joaoh1.okzoomer.OkZoomer"; - /** * Initializes compatibility with other mods if needed. * @@ -33,7 +31,7 @@ public class LambdaControlsCompat */ public static void init(@NotNull LambdaControls mod) { - if (FabricLoader.getInstance().isModLoaded("okzoomer") && LambdaReflection.does_class_exist(OKZOOMER_CLASS_PATH)) { + if (FabricLoader.getInstance().isModLoaded("okzoomer") && LambdaReflection.does_class_exist(OkZoomerCompat.OKZOOMER_CLASS_PATH)) { mod.log("Adding okzoomer compatibility..."); new OkZoomerCompat().handle(mod); } diff --git a/src/main/java/me/lambdaurora/lambdacontrols/compat/OkZoomerCompat.java b/src/main/java/me/lambdaurora/lambdacontrols/compat/OkZoomerCompat.java index 31a6901..ecfa571 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/compat/OkZoomerCompat.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/compat/OkZoomerCompat.java @@ -26,6 +26,8 @@ import org.lwjgl.glfw.GLFW; */ public class OkZoomerCompat implements CompatHandler { + public static final String OKZOOMER_CLASS_PATH = "io.github.joaoh1.okzoomer.OkZoomer"; + @Override public void handle(@NotNull LambdaControls mod) { diff --git a/src/main/java/me/lambdaurora/lambdacontrols/controller/ButtonBinding.java b/src/main/java/me/lambdaurora/lambdacontrols/controller/ButtonBinding.java index 28c30c3..52d04af 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/controller/ButtonBinding.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/controller/ButtonBinding.java @@ -140,7 +140,7 @@ public class ButtonBinding implements Nameable */ public boolean is_not_bound() { - return this.button[0] == -1; + return this.button.length == 0 || this.button[0] == -1; } /** diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/ControllerButtonWidget.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/ControllerButtonWidget.java index a055c2c..422c401 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/gui/ControllerButtonWidget.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/ControllerButtonWidget.java @@ -9,10 +9,12 @@ package me.lambdaurora.lambdacontrols.gui; -import me.lambdaurora.lambdacontrols.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.LambdaControls; +import me.lambdaurora.lambdacontrols.controller.ButtonBinding; import me.lambdaurora.spruceui.AbstractIconButtonWidget; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.resource.language.I18n; +import org.aperlambda.lambdacommon.utils.Pair; import org.jetbrains.annotations.NotNull; /** @@ -21,6 +23,7 @@ import org.jetbrains.annotations.NotNull; public class ControllerButtonWidget extends AbstractIconButtonWidget { private ButtonBinding binding; + private int icon_width; public ControllerButtonWidget(int x, int y, int width, @NotNull ButtonBinding button_binding, @NotNull PressAction on_press) { @@ -30,12 +33,27 @@ public class ControllerButtonWidget extends AbstractIconButtonWidget public void update() { - this.setMessage(ButtonBinding.get_localized_button_name(binding.get_button()[0])); + int length = binding.get_button().length; + this.setMessage(this.binding.is_not_bound() ? I18n.translate("lambdacontrols.not_bound") : + (length > 0 ? ButtonBinding.get_localized_button_name(binding.get_button()[0]) : "<>")); + } + + @Override + public String getMessage() + { + if (this.binding.get_button().length > 1) + return ""; + return super.getMessage(); } @Override protected int render_icon(int mouse_x, int mouse_y, float delta, int x, int y) { - return LambdaControls.draw_button(x, y, this.binding, MinecraftClient.getInstance()).get_value(); + if (this.binding.get_button().length > 1) { + x += (this.width / 2 - this.icon_width / 2) - 4; + } + Pair size = LambdaControls.draw_button(x, y, this.binding, MinecraftClient.getInstance()); + this.icon_width = size.get_key(); + return size.get_value(); } } diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/ControlsListWidget.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/ControlsListWidget.java index ee69f4e..94d0946 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/gui/ControlsListWidget.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/ControlsListWidget.java @@ -33,8 +33,9 @@ import java.util.List; */ public class ControlsListWidget extends ElementListWidget { - private final LambdaControlsControlsScreen gui; - private int field_2733; + private static final int[] UNBOUND = new int[0]; + private final LambdaControlsControlsScreen gui; + private int field_2733; public ControlsListWidget(@NotNull LambdaControlsControlsScreen gui, @NotNull MinecraftClient client) { @@ -75,6 +76,7 @@ public class ControlsListWidget extends ElementListWidget { gui.focused_binding = binding; gui.current_buttons.clear(); + gui.waiting = true; }) { protected String getNarrationMessage() @@ -98,6 +101,17 @@ public class ControlsListWidget extends ElementListWidget { + gui.mod.config.set_button_binding(binding, UNBOUND); + gui.focused_binding = null; + }) + { + protected String getNarrationMessage() + { + return I18n.translate("lambdacontrols.narrator.unbound", binding_name); + } + }; } @Override @@ -115,10 +129,13 @@ public class ControlsListWidget extends ElementListWidget current_buttons = new ArrayList<>(); public LambdaControlsControlsScreen(@NotNull Screen parent, boolean hide_settings) diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsHud.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsHud.java index a6683ad..c5e4c41 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsHud.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsHud.java @@ -9,10 +9,10 @@ package me.lambdaurora.lambdacontrols.gui; -import me.lambdaurora.lambdacontrols.HudSide; -import me.lambdaurora.lambdacontrols.controller.ButtonBinding; import me.lambdaurora.lambdacontrols.ControlsMode; +import me.lambdaurora.lambdacontrols.HudSide; import me.lambdaurora.lambdacontrols.LambdaControls; +import me.lambdaurora.lambdacontrols.controller.ButtonBinding; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawableHelper; import net.minecraft.util.hit.HitResult; @@ -29,8 +29,8 @@ public class LambdaControlsHud extends DrawableHelper { private final MinecraftClient client; private final LambdaControls mod; - private int width_bottom = 0; - private int width_top = 0; + private int width_bottom = 0; + private int width_top = 0; public LambdaControlsHud(@NotNull MinecraftClient client, @NotNull LambdaControls mod) { diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java index 2447fb5..e99be6a 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java @@ -21,7 +21,6 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.options.ControlsOptionsScreen; import net.minecraft.client.gui.widget.ButtonListWidget; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.options.BooleanOption; import net.minecraft.client.options.CyclingOption; import net.minecraft.client.options.GameOptions; import net.minecraft.client.options.Option; diff --git a/src/main/java/me/lambdaurora/lambdacontrols/mixin/SettingsScreenMixin.java b/src/main/java/me/lambdaurora/lambdacontrols/mixin/SettingsScreenMixin.java index 86c45aa..02d713e 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/mixin/SettingsScreenMixin.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/mixin/SettingsScreenMixin.java @@ -12,18 +12,12 @@ package me.lambdaurora.lambdacontrols.mixin; import me.lambdaurora.lambdacontrols.ControlsMode; import me.lambdaurora.lambdacontrols.LambdaControls; import me.lambdaurora.lambdacontrols.gui.LambdaControlsControlsScreen; -import me.lambdaurora.lambdacontrols.gui.LambdaControlsSettingsScreen; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.SettingsScreen; -import net.minecraft.client.gui.screen.options.ControlsOptionsScreen; import net.minecraft.client.gui.widget.AbstractButtonWidget; import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.options.GameOptions; -import net.minecraft.client.resource.language.I18n; import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; diff --git a/src/main/resources/assets/lambdacontrols/lang/en_us.json b/src/main/resources/assets/lambdacontrols/lang/en_us.json index 8f1d1a4..fd624db 100644 --- a/src/main/resources/assets/lambdacontrols/lang/en_us.json +++ b/src/main/resources/assets/lambdacontrols/lang/en_us.json @@ -92,6 +92,9 @@ "lambdacontrols.menu.title.controller_controls": "Controller controls", "lambdacontrols.menu.title.general": "General options", "lambdacontrols.menu.title.hud": "HUD options", + "lambdacontrols.menu.unbound": "Unbound", + "lambdacontrols.narrator.unbound": "Unbound %s", + "lambdacontrols.not_bound": "Not bound", "lambdacontrols.tooltip.auto_switch_mode": "Sets whether the controls mode should be switched automatically to Controller if a controller is connected.", "lambdacontrols.tooltip.controller2": "Defines a second controller to use, which allow Joy-Cons support for example.", "lambdacontrols.tooltip.controller_type": "Changes the controller type to displays the correct buttons.", diff --git a/src/main/resources/assets/lambdacontrols/lang/fr_ca.json b/src/main/resources/assets/lambdacontrols/lang/fr_ca.json index 48a7ab6..f759a2b 100644 --- a/src/main/resources/assets/lambdacontrols/lang/fr_ca.json +++ b/src/main/resources/assets/lambdacontrols/lang/fr_ca.json @@ -92,6 +92,9 @@ "lambdacontrols.menu.title.controller_controls": "Contrôles de la manette", "lambdacontrols.menu.title.general": "Options générales", "lambdacontrols.menu.title.hud": "Options du HUD", + "lambdacontrols.menu.unbound": "Délier", + "lambdacontrols.narrator.unbound": "Délier %s", + "lambdacontrols.not_bound": "Non défini", "lambdacontrols.tooltip.auto_switch_mode": "Détermine si le mode de contrôle doit automatiquement changer sur Manette si une manette est connectée et inversement.", "lambdacontrols.tooltip.controller2": "Défini une deuxième manette, utile dans le cas d'utilisation de Joy-Cons.", "lambdacontrols.tooltip.controller_type": "Le type de contrôle n'influe que sur les boutons affichés.", diff --git a/src/main/resources/assets/lambdacontrols/lang/fr_fr.json b/src/main/resources/assets/lambdacontrols/lang/fr_fr.json index 48a7ab6..f759a2b 100644 --- a/src/main/resources/assets/lambdacontrols/lang/fr_fr.json +++ b/src/main/resources/assets/lambdacontrols/lang/fr_fr.json @@ -92,6 +92,9 @@ "lambdacontrols.menu.title.controller_controls": "Contrôles de la manette", "lambdacontrols.menu.title.general": "Options générales", "lambdacontrols.menu.title.hud": "Options du HUD", + "lambdacontrols.menu.unbound": "Délier", + "lambdacontrols.narrator.unbound": "Délier %s", + "lambdacontrols.not_bound": "Non défini", "lambdacontrols.tooltip.auto_switch_mode": "Détermine si le mode de contrôle doit automatiquement changer sur Manette si une manette est connectée et inversement.", "lambdacontrols.tooltip.controller2": "Défini une deuxième manette, utile dans le cas d'utilisation de Joy-Cons.", "lambdacontrols.tooltip.controller_type": "Le type de contrôle n'influe que sur les boutons affichés.",