From 50227e38683cae39b00e6585362aabc06f622d66 Mon Sep 17 00:00:00 2001 From: LambdAurora Date: Thu, 12 Dec 2019 12:04:18 +0100 Subject: [PATCH] :sparkles: Add clickable link, more options, and fixes! --- .../lambdacontrols/ButtonBinding.java | 1 - .../lambdacontrols/Controller.java | 5 +- .../lambdacontrols/LambdaControls.java | 22 +++ .../lambdacontrols/LambdaControlsConfig.java | 20 +++ .../lambdacontrols/gui/LabelWidget.java | 128 ++++++++++++++++++ .../gui/LambdaControlsSettingsScreen.java | 37 +++-- .../gui/ReloadControllerMappingsOption.java | 50 +++++++ .../assets/lambdacontrols/lang/en_us.json | 9 +- .../assets/lambdacontrols/lang/fr_fr.json | 9 +- src/main/resources/config.toml | 2 + 10 files changed, 262 insertions(+), 21 deletions(-) create mode 100644 src/main/java/me/lambdaurora/lambdacontrols/gui/LabelWidget.java create mode 100644 src/main/java/me/lambdaurora/lambdacontrols/gui/ReloadControllerMappingsOption.java diff --git a/src/main/java/me/lambdaurora/lambdacontrols/ButtonBinding.java b/src/main/java/me/lambdaurora/lambdacontrols/ButtonBinding.java index f110834..a9d149b 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/ButtonBinding.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/ButtonBinding.java @@ -468,7 +468,6 @@ public class ButtonBinding implements Nameable */ public @NotNull String get_translated_name() { - System.out.println(id.toString()); if (this.id.get_namespace().equals("minecraft")) return I18n.translate(this.id.get_name()); else diff --git a/src/main/java/me/lambdaurora/lambdacontrols/Controller.java b/src/main/java/me/lambdaurora/lambdacontrols/Controller.java index 30f32ae..9bcb685 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/Controller.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/Controller.java @@ -80,7 +80,7 @@ public class Controller implements Nameable */ public boolean is_gamepad() { - return GLFW.glfwJoystickIsGamepad(this.id); + return this.is_connected() && GLFW.glfwJoystickIsGamepad(this.id); } /** @@ -147,7 +147,7 @@ public class Controller implements Nameable if (Files.isReadable(path)) { try (SeekableByteChannel fc = Files.newByteChannel(path)) { buffer = createByteBuffer((int) fc.size() + 2); - while (fc.read(buffer) != -1); + while (fc.read(buffer) != -1) ; buffer.put((byte) 0); } } @@ -165,6 +165,7 @@ public class Controller implements Nameable File mappings_file = new File("config/gamecontrollerdb.txt"); if (!mappings_file.exists()) return; + LambdaControls.get().log("Updating controller mappings..."); ByteBuffer buffer = io_resource_to_buffer(mappings_file.getPath(), 1024); GLFW.glfwUpdateGamepadMappings(buffer); } catch (IOException e) { diff --git a/src/main/java/me/lambdaurora/lambdacontrols/LambdaControls.java b/src/main/java/me/lambdaurora/lambdacontrols/LambdaControls.java index 08fdc56..13c6106 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/LambdaControls.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/LambdaControls.java @@ -34,6 +34,7 @@ public class LambdaControls implements ClientModInitializer public final Logger logger = LogManager.getLogger("LambdaControls"); public final LambdaControlsConfig config = new LambdaControlsConfig(this); public final ControllerInput controller_input = new ControllerInput(this); + private ControlsMode previous_controls_mode; @Override public void onInitializeClient() @@ -59,6 +60,8 @@ public class LambdaControls implements ClientModInitializer client.getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.disconnected", jid), null)); } + + this.switch_controls_mode(); }); } @@ -78,6 +81,25 @@ public class LambdaControls implements ClientModInitializer this.controller_input.on_render(client); } + /** + * Switches the controls mode if the auto switch is enabled. + */ + public void switch_controls_mode() + { + if (this.config.has_auto_switch_mode()) { + if (this.config.get_controller().is_gamepad()) { + this.previous_controls_mode = this.config.get_controls_mode(); + this.config.set_controls_mode(ControlsMode.CONTROLLER); + } else { + if (this.previous_controls_mode == null) { + this.previous_controls_mode = ControlsMode.DEFAULT; + } + + this.config.set_controls_mode(this.previous_controls_mode); + } + } + } + /** * Prints a message to the terminal. * diff --git a/src/main/java/me/lambdaurora/lambdacontrols/LambdaControlsConfig.java b/src/main/java/me/lambdaurora/lambdacontrols/LambdaControlsConfig.java index 83a53e2..0cf716b 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/LambdaControlsConfig.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/LambdaControlsConfig.java @@ -89,6 +89,26 @@ public class LambdaControlsConfig this.config.set("controls", controls_mode.get_name()); } + /** + * Returns whether the auto switch mode is enabled or not. + * + * @return True if the auto switch mode is enabled, else false. + */ + public boolean has_auto_switch_mode() + { + return this.config.getOrElse("auto_switch_mode", false); + } + + /** + * Sets whether the auto switch mode is enabled or not. + * + * @param auto_switch_mode True if the auto switch mode is enabled, else false. + */ + public void set_auto_switch_mode(boolean auto_switch_mode) + { + this.config.set("auto_switch_mode", auto_switch_mode); + } + /** * Returns whether the HUD is enabled. * diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/LabelWidget.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/LabelWidget.java new file mode 100644 index 0000000..4c13699 --- /dev/null +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/LabelWidget.java @@ -0,0 +1,128 @@ +/* + * Copyright © 2019 LambdAurora + * + * This file is part of LambdaControls. + * + * Licensed under the MIT license. For more information, + * see the LICENSE file. + */ + +package me.lambdaurora.lambdacontrols.gui; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Drawable; +import net.minecraft.client.gui.DrawableHelper; +import net.minecraft.client.gui.Element; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; + +import java.util.function.Consumer; + +/** + * Represents a label widget. + */ +// @TODO move this to a GUI library. +public class LabelWidget extends DrawableHelper implements Element, Drawable +{ + public static final Consumer DEFAULT_ACTION = label -> { + }; + + private final MinecraftClient client = MinecraftClient.getInstance(); + private final Consumer click_action; + private final int x; + private final int y; + private final int max_width; + //private final int max_height; + private String text; + public boolean visible; + private int width; + private int height; + private boolean centered; + + public LabelWidget(int x, int y, @NotNull String text, int max_width, @NotNull Consumer click_action, boolean centered) + { + this.visible = true; + this.x = x; + this.y = y; + this.max_width = max_width; + this.click_action = click_action; + this.centered = centered; + this.set_text(text); + } + + public LabelWidget(int x, int y, @NotNull String text, int max_width, @NotNull Consumer click_action) + { + this(x, y, text, max_width, click_action, false); + } + + public LabelWidget(int x, int y, @NotNull String text, int max_width, boolean centered) + { + this(x, y, text, max_width, DEFAULT_ACTION, centered); + } + + public LabelWidget(int x, int y, @NotNull String text, int max_width) + { + this(x, y, text, max_width, DEFAULT_ACTION); + } + + /** + * Sets the text of this label. + * + * @param text The text to set. + */ + public void set_text(@NotNull String text) + { + int width = this.client.textRenderer.getStringWidth(text); + if (width > this.max_width) { + while (width > this.max_width) { + text = text.substring(0, text.length() - 1); + width = this.client.textRenderer.getStringWidth(text); + } + } + + this.text = text; + this.width = width; + this.height = this.client.textRenderer.fontHeight; + } + + /** + * Gets the width of this label widget. + * + * @return The width of this label widget. + */ + public int get_width() + { + return this.width; + } + + /** + * Gets the height of this label widget. + * + * @return The height of this label widget. + */ + public int get_height() + { + return this.height; + } + + @Override + public void render(int mouse_x, int mouse_y, float delta) + { + if (this.centered) + this.drawCenteredString(this.client.textRenderer, this.text, this.x, this.y, 10526880); + else + this.drawString(this.client.textRenderer, this.text, this.x, this.y, 10526880); + } + + @Override + public boolean mouseClicked(double mouse_x, double mouse_y, int button) + { + if (this.visible && button == GLFW.GLFW_MOUSE_BUTTON_1) { + if (mouse_x >= (double) this.x && mouse_y >= (double) this.y && mouse_x < (double) (this.x + this.width) && mouse_y < (double) (this.y + this.height)) { + this.click_action.accept(this); + return true; + } + } + return false; + } +} diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java index df0f8af..de1cf26 100644 --- a/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/LambdaControlsSettingsScreen.java @@ -20,6 +20,7 @@ import net.minecraft.client.options.*; import net.minecraft.client.resource.language.I18n; import net.minecraft.text.TranslatableText; import net.minecraft.util.Formatting; +import net.minecraft.util.Util; import org.jetbrains.annotations.NotNull; import org.lwjgl.glfw.GLFW; @@ -28,17 +29,21 @@ import org.lwjgl.glfw.GLFW; */ public class LambdaControlsSettingsScreen extends Screen { - final LambdaControls mod; - private final Screen parent; - private final GameOptions options; - private final Option controller_option; - private final Option controller_type_option; - private final Option hud_enable_option; - private final Option hud_side_option; - private final Option dead_zone_option; - private final Option rotation_speed_option; - private final Option mouse_speed_option; - private ButtonListWidget list; + public static final String GAMEPAD_TOOL_URL = "http://generalarcade.com/gamepadtool/"; + final LambdaControls mod; + private final Screen parent; + private final GameOptions options; + private final Option auto_switch_mode_option; + private final Option controller_option; + private final Option controller_type_option; + private final Option dead_zone_option; + private final Option hud_enable_option; + private final Option hud_side_option; + private final Option mouse_speed_option; + private final Option rotation_speed_option; + private final String controller_mappings_url_text = I18n.translate("lambdacontrols.controller.mappings.2", Formatting.GOLD.toString(), GAMEPAD_TOOL_URL, Formatting.RESET.toString()); + private ButtonListWidget list; + private LabelWidget gamepad_tool_url_label; public LambdaControlsSettingsScreen(Screen parent, @NotNull GameOptions options) { @@ -46,6 +51,8 @@ public class LambdaControlsSettingsScreen extends Screen this.mod = LambdaControls.get(); this.parent = parent; this.options = options; + this.auto_switch_mode_option = new BooleanOption("lambdacontrols.menu.auto_switch_mode", game_options -> this.mod.config.has_auto_switch_mode(), + (game_options, new_value) -> this.mod.config.set_auto_switch_mode(new_value)); this.controller_option = new CyclingOption("lambdacontrols.menu.controller", (game_options, amount) -> { int current_id = this.mod.config.get_controller().get_id(); current_id += amount; @@ -134,8 +141,14 @@ public class LambdaControlsSettingsScreen extends Screen this.list.addOptionEntry(this.controller_type_option, this.dead_zone_option); this.list.addOptionEntry(this.hud_enable_option, this.hud_side_option); this.list.addOptionEntry(this.rotation_speed_option, this.mouse_speed_option); + this.list.addSingleOptionEntry(this.auto_switch_mode_option); + this.list.addSingleOptionEntry(new ReloadControllerMappingsOption()); this.children.add(this.list); + this.gamepad_tool_url_label = new LabelWidget(this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 2, this.controller_mappings_url_text, this.width, + label -> Util.getOperatingSystem().open(GAMEPAD_TOOL_URL), true); + this.children.add(this.gamepad_tool_url_label); + this.addButton(new ButtonWidget(this.width / 2 - 155, this.height - 29, 300, button_height, I18n.translate("gui.done"), (buttonWidget) -> this.minecraft.openScreen(this.parent))); } @@ -148,7 +161,7 @@ public class LambdaControlsSettingsScreen extends Screen super.render(mouse_x, mouse_y, delta); this.drawCenteredString(this.font, I18n.translate("lambdacontrols.menu.title"), this.width / 2, 8, 16777215); this.drawCenteredString(this.font, I18n.translate("lambdacontrols.controller.mappings.1", Formatting.GREEN.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 3, 10526880); - this.drawCenteredString(this.font, I18n.translate("lambdacontrols.controller.mappings.2", Formatting.GOLD.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.font.fontHeight) * 2, 10526880); + this.gamepad_tool_url_label.render(mouse_x, mouse_y, delta); this.drawCenteredString(this.font, I18n.translate("lambdacontrols.controller.mappings.3", Formatting.GREEN.toString(), Formatting.RESET.toString()), this.width / 2, this.height - 29 - (5 + this.font.fontHeight), 10526880); } } diff --git a/src/main/java/me/lambdaurora/lambdacontrols/gui/ReloadControllerMappingsOption.java b/src/main/java/me/lambdaurora/lambdacontrols/gui/ReloadControllerMappingsOption.java new file mode 100644 index 0000000..c5db474 --- /dev/null +++ b/src/main/java/me/lambdaurora/lambdacontrols/gui/ReloadControllerMappingsOption.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2019 LambdAurora + * + * This file is part of LambdaControls. + * + * Licensed under the MIT license. For more information, + * see the LICENSE file. + */ + +package me.lambdaurora.lambdacontrols.gui; + +import me.lambdaurora.lambdacontrols.Controller; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.widget.AbstractButtonWidget; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.options.GameOptions; +import net.minecraft.client.options.Option; +import net.minecraft.client.resource.language.I18n; +import net.minecraft.client.toast.SystemToast; +import net.minecraft.text.TranslatableText; +import org.aperlambda.lambdacommon.utils.Nameable; +import org.jetbrains.annotations.NotNull; + +/** + * Represents the option to reload the controller mappings. + */ +public class ReloadControllerMappingsOption extends Option implements Nameable +{ + private static final String KEY = "lambdacontrols.menu.reload_controller_mappings"; + + public ReloadControllerMappingsOption() + { + super(KEY); + } + + @Override + public AbstractButtonWidget createButton(GameOptions options, int x, int y, int width) + { + return new ButtonWidget(x, y, width, 20, this.get_name(), btn -> { + Controller.update_mappings(); + MinecraftClient.getInstance().getToastManager().add(new SystemToast(SystemToast.Type.TUTORIAL_HINT, new TranslatableText("lambdacontrols.controller.mappings.updated"), null)); + }); + } + + @Override + public @NotNull String get_name() + { + return I18n.translate(KEY); + } +} diff --git a/src/main/resources/assets/lambdacontrols/lang/en_us.json b/src/main/resources/assets/lambdacontrols/lang/en_us.json index 84fca5d..f04c3c9 100644 --- a/src/main/resources/assets/lambdacontrols/lang/en_us.json +++ b/src/main/resources/assets/lambdacontrols/lang/en_us.json @@ -52,8 +52,9 @@ "lambdacontrols.controller.connected": "Controller %d connected.", "lambdacontrols.controller.disconnected": "Controller %d disconnected.", "lambdacontrols.controller.mappings.1": "To configure the controller mappings, please use %sSDL2 Gamepad Tool%s", - "lambdacontrols.controller.mappings.2": "(%shttp://generalarcade.com/gamepadtool/%s),", - "lambdacontrols.controller.mappings.3": "and put the mapping in `%sconfig/gamecontrollerdb.txt%s`.", + "lambdacontrols.controller.mappings.2": "(%s%s%s),", + "lambdacontrols.controller.mappings.3": "and put the mapping in `%s.minecraft/config/gamecontrollerdb.txt%s`.", + "lambdacontrols.controller.mappings.updated": "Updated mappings!", "lambdacontrols.controller_type.default": "default", "lambdacontrols.controller_type.dualshock": "DualShock", "lambdacontrols.controller_type.switch": "Switch", @@ -65,15 +66,17 @@ "lambdacontrols.controls_mode.touchscreen": "Touchscreen", "lambdacontrols.hud_side.left": "left", "lambdacontrols.hud_side.right": "right", + "lambdacontrols.menu.auto_switch_mode": "Auto switch mode", "lambdacontrols.menu.controller": "Controller", "lambdacontrols.menu.controller_type": "Controller type", - "lambdacontrols.menu.controls_mode": "Controls mode", + "lambdacontrols.menu.controls_mode": "Mode", "lambdacontrols.menu.dead_zone": "Dead zone", "lambdacontrols.menu.hud_enable": "Enable HUD", "lambdacontrols.menu.hud_side": "HUD side", "lambdacontrols.menu.invert_right_x_axis": "Invert right X", "lambdacontrols.menu.invert_right_y_axis": "Invert right Y", "lambdacontrols.menu.mouse_speed": "Mouse speed", + "lambdacontrols.menu.reload_controller_mappings": "Reload controller mappings", "lambdacontrols.menu.rotation_speed": "Rotation speed", "lambdacontrols.menu.title": "LambdaControls - Settings", "lambdacontrols.menu.title.controller_controls": "Controller controls" diff --git a/src/main/resources/assets/lambdacontrols/lang/fr_fr.json b/src/main/resources/assets/lambdacontrols/lang/fr_fr.json index 28aa8ed..90bc8fc 100644 --- a/src/main/resources/assets/lambdacontrols/lang/fr_fr.json +++ b/src/main/resources/assets/lambdacontrols/lang/fr_fr.json @@ -52,8 +52,9 @@ "lambdacontrols.controller.connected": "Manette %d connecté.", "lambdacontrols.controller.disconnected": "Manette %d déconnecté.", "lambdacontrols.controller.mappings.1": "Pour configurer les correspondances de la manette, veuillez utiliser %sSDL2 Gamepad Tool%s", - "lambdacontrols.controller.mappings.2": "(%shttp://generalarcade.com/gamepadtool/%s),", - "lambdacontrols.controller.mappings.3": "et mettez les correspondances dans le fichier `%sconfig/gamecontrollerdb.txt%s`.", + "lambdacontrols.controller.mappings.2": "(%s%s%s),", + "lambdacontrols.controller.mappings.3": "et mettez les correspondances dans le fichier `%s.minecraft/config/gamecontrollerdb.txt%s`.", + "lambdacontrols.controller.mappings.updated": "Configuration des manettes mise à jour!", "lambdacontrols.controller_type.default": "default", "lambdacontrols.controller_type.dualshock": "DualShock", "lambdacontrols.controller_type.switch": "Switch", @@ -65,15 +66,17 @@ "lambdacontrols.controls_mode.touchscreen": "Tactile", "lambdacontrols.hud_side.left": "gauche", "lambdacontrols.hud_side.right": "droit", + "lambdacontrols.menu.auto_switch_mode": "Changement auto de mode", "lambdacontrols.menu.controller": "Manette", "lambdacontrols.menu.controller_type": "Type de manette", - "lambdacontrols.menu.controls_mode": "Mode de contrôle", + "lambdacontrols.menu.controls_mode": "Mode", "lambdacontrols.menu.dead_zone": "Zone morte", "lambdacontrols.menu.hud_enable": "Activer le HUD", "lambdacontrols.menu.hud_side": "Côté du HUD", "lambdacontrols.menu.invert_right_x_axis": "Inverser le joystick droit (X)", "lambdacontrols.menu.invert_right_y_axis": "Inverser le joystick droit (Y)", "lambdacontrols.menu.mouse_speed": "Vitesse de la souris", + "lambdacontrols.menu.reload_controller_mappings": "Recharge la configuration des manettes", "lambdacontrols.menu.rotation_speed": "Vitesse de rotation", "lambdacontrols.menu.title": "LambdaControls - Paramètres", "lambdacontrols.menu.title.controller_controls": "Contrôles de la manette" diff --git a/src/main/resources/config.toml b/src/main/resources/config.toml index d790241..2ade73b 100644 --- a/src/main/resources/config.toml +++ b/src/main/resources/config.toml @@ -2,6 +2,8 @@ # The controls mode. Available modes: default, controller, touchscreen controls = "default" +# Auto switch mode. +auto_switch_mode = false [hud] # Enables the HUD.