mirror of
https://github.com/chylex/Better-Controls.git
synced 2025-05-15 19:34:05 +02:00
318 lines
13 KiB
Java
318 lines
13 KiB
Java
package chylex.bettercontrols.gui;
|
|
import chylex.bettercontrols.BetterControlsMod;
|
|
import chylex.bettercontrols.config.BetterControlsConfig;
|
|
import chylex.bettercontrols.gui.elements.BooleanValueWidget;
|
|
import chylex.bettercontrols.gui.elements.CycleButtonWidget;
|
|
import chylex.bettercontrols.gui.elements.DiscreteValueSliderWidget;
|
|
import chylex.bettercontrols.gui.elements.KeyBindingWidget;
|
|
import chylex.bettercontrols.gui.elements.Option;
|
|
import chylex.bettercontrols.gui.elements.TextWidget;
|
|
import chylex.bettercontrols.input.KeyBindingWithModifier;
|
|
import chylex.bettercontrols.input.ModifierKey;
|
|
import chylex.bettercontrols.input.SprintMode;
|
|
import com.mojang.blaze3d.platform.InputConstants;
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import net.minecraft.client.KeyMapping;
|
|
import net.minecraft.client.gui.components.Button;
|
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
|
import net.minecraft.client.gui.screens.OptionsSubScreen;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.TextComponent;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.lwjgl.glfw.GLFW;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import static chylex.bettercontrols.gui.OptionListWidget.COL2_W;
|
|
import static chylex.bettercontrols.gui.OptionListWidget.COL4_W;
|
|
import static chylex.bettercontrols.gui.OptionListWidget.ROW_WIDTH;
|
|
import static chylex.bettercontrols.gui.OptionListWidget.col2;
|
|
import static chylex.bettercontrols.gui.OptionListWidget.col4;
|
|
import static chylex.bettercontrols.gui.elements.TextWidget.CENTER;
|
|
import static chylex.bettercontrols.util.Statics.OPTIONS;
|
|
|
|
public class BetterControlsScreen extends OptionsSubScreen {
|
|
private static TextComponent text(final String text) {
|
|
return new TextComponent(text);
|
|
}
|
|
|
|
public static final Component TITLE = text("Better Controls");
|
|
|
|
private static final int BOTTOM_PADDING = 3;
|
|
private static final int TEXT_PADDING_RIGHT = 4;
|
|
private static final int TITLE_MARGIN_TOP = 3;
|
|
private static final int ROW_HEIGHT = 22;
|
|
|
|
private final List<Option<SprintMode>> SPRINT_MODE_OPTIONS = Arrays.asList(
|
|
new Option<>(SprintMode.TAP_TO_START, text("Tap To Start Sprinting")),
|
|
new Option<>(SprintMode.TAP_TO_TOGGLE, text("Tap To Start / Stop Sprinting")),
|
|
new Option<>(SprintMode.HOLD, text("Hold To Sprint"))
|
|
);
|
|
|
|
// Options
|
|
|
|
private int generateSprintingOptions(int y, final List<GuiEventListener> elements) {
|
|
final BetterControlsConfig cfg = BetterControlsMod.config;
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Toggle Sprint"), cfg.keyToggleSprint);
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Sprint Key Mode"));
|
|
elements.add(new CycleButtonWidget<>(col2(1), y, COL2_W, SPRINT_MODE_OPTIONS, cfg.sprintMode, value -> cfg.sprintMode = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Double Tap 'Walk Forwards' To Sprint"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.doubleTapForwardToSprint, value -> cfg.doubleTapForwardToSprint = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Resume Sprinting After Hitting Obstacle"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.resumeSprintingAfterHittingObstacle, value -> cfg.resumeSprintingAfterHittingObstacle = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
return y;
|
|
}
|
|
|
|
private int generateSneakingOptions(int y, final List<GuiEventListener> elements) {
|
|
final BetterControlsConfig cfg = BetterControlsMod.config;
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Toggle Sneak"), cfg.keyToggleSneak);
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Move Camera Smoothly"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.sneakingMovesCameraSmoothly, value -> cfg.sneakingMovesCameraSmoothly = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
return y;
|
|
}
|
|
|
|
@SuppressWarnings({ "AutoBoxing", "AutoUnboxing" })
|
|
private int generateFlightOptions(int y, final List<GuiEventListener> elements) {
|
|
final BetterControlsConfig cfg = BetterControlsMod.config;
|
|
|
|
final List<Option<Float>> flightSpeedOptions = Arrays.asList(
|
|
new Option<>(Float.valueOf(0.25F), text("0.25x")),
|
|
new Option<>(Float.valueOf(0.50F), text("0.5x")),
|
|
new Option<>(Float.valueOf(0.75F), text("0.75x")),
|
|
new Option<>(Float.valueOf(1.00F), text("1x")),
|
|
new Option<>(Float.valueOf(1.50F), text("1.5x")),
|
|
new Option<>(Float.valueOf(2.00F), text("2x")),
|
|
new Option<>(Float.valueOf(3.00F), text("3x")),
|
|
new Option<>(Float.valueOf(4.00F), text("4x")),
|
|
new Option<>(Float.valueOf(5.00F), text("5x")),
|
|
new Option<>(Float.valueOf(6.00F), text("6x")),
|
|
new Option<>(Float.valueOf(7.00F), text("7x")),
|
|
new Option<>(Float.valueOf(8.00F), text("8x"))
|
|
);
|
|
|
|
final List<Option<Float>> flightVerticalBoostOptions = Arrays.asList(
|
|
new Option<>(Float.valueOf(0.00F), text("None")),
|
|
new Option<>(Float.valueOf(0.25F), text("+25%")),
|
|
new Option<>(Float.valueOf(0.50F), text("+50%")),
|
|
new Option<>(Float.valueOf(0.75F), text("+75%")),
|
|
new Option<>(Float.valueOf(1.00F), text("+100%")),
|
|
new Option<>(Float.valueOf(1.50F), text("+150%")),
|
|
new Option<>(Float.valueOf(2.00F), text("+200%")),
|
|
new Option<>(Float.valueOf(2.50F), text("+250%")),
|
|
new Option<>(Float.valueOf(3.00F), text("+300%"))
|
|
);
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Toggle Flight (Creative)"), cfg.keyToggleFlight);
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Double Tap 'Jump' To Fly (Creative)"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.doubleTapJumpToToggleFlight, value -> cfg.doubleTapJumpToToggleFlight = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Disable Flight Inertia"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.disableFlightInertia, value -> cfg.disableFlightInertia = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Disable Field Of View Changing"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.disableChangingFovWhileFlying, value -> cfg.disableChangingFovWhileFlying = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Fly On Ground (Creative Mode)"));
|
|
elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.flyOnGroundInCreative, value -> cfg.flyOnGroundInCreative = value));
|
|
|
|
y += ROW_HEIGHT * 4 / 3;
|
|
|
|
elements.add(new TextWidget(col4(2), y, COL4_W - TEXT_PADDING_RIGHT, text("Creative"), CENTER));
|
|
elements.add(new TextWidget(col4(3), y, COL4_W - TEXT_PADDING_RIGHT, text("Spectator"), CENTER));
|
|
|
|
y += ROW_HEIGHT * 7 / 8;
|
|
|
|
generateLeftSideText(y, elements, text("Speed Multiplier (Default)"));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(2), y, COL4_W, flightSpeedOptions, cfg.flightSpeedMpCreativeDefault, value -> cfg.flightSpeedMpCreativeDefault = value));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(3), y, COL4_W, flightSpeedOptions, cfg.flightSpeedMpSpectatorDefault, value -> cfg.flightSpeedMpSpectatorDefault = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Speed Multiplier (Sprinting)"));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(2), y, COL4_W, flightSpeedOptions, cfg.flightSpeedMpCreativeSprinting, value -> cfg.flightSpeedMpCreativeSprinting = value));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(3), y, COL4_W, flightSpeedOptions, cfg.flightSpeedMpSpectatorSprinting, value -> cfg.flightSpeedMpSpectatorSprinting = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Vertical Speed Boost (Default)"));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(2), y, COL4_W, flightVerticalBoostOptions, cfg.flightVerticalBoostCreativeDefault, value -> cfg.flightVerticalBoostCreativeDefault = value));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(3), y, COL4_W, flightVerticalBoostOptions, cfg.flightVerticalBoostSpectatorDefault, value -> cfg.flightVerticalBoostSpectatorDefault = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateLeftSideText(y, elements, text("Vertical Speed Boost (Sprinting)"));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(2), y, COL4_W, flightVerticalBoostOptions, cfg.flightVerticalBoostCreativeSprinting, value -> cfg.flightVerticalBoostCreativeSprinting = value));
|
|
elements.add(new DiscreteValueSliderWidget<>(col4(3), y, COL4_W, flightVerticalBoostOptions, cfg.flightVerticalBoostSpectatorSprinting, value -> cfg.flightVerticalBoostSpectatorSprinting = value));
|
|
|
|
y += ROW_HEIGHT;
|
|
return y;
|
|
}
|
|
|
|
private int generateMiscellaneousOptions(int y, final List<GuiEventListener> elements) {
|
|
final BetterControlsConfig cfg = BetterControlsMod.config;
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Toggle Walk Forwards"), cfg.keyToggleWalkForward);
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Toggle Jump"), cfg.keyToggleJump);
|
|
|
|
y += ROW_HEIGHT;
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Reset All Toggles"), cfg.keyResetAllToggles);
|
|
|
|
y += ROW_HEIGHT * 4 / 3;
|
|
|
|
generateKeyBindingWithModifierOption(y, elements, text("Open Better Controls Menu"), cfg.keyOpenMenu);
|
|
|
|
y += ROW_HEIGHT;
|
|
return y;
|
|
}
|
|
|
|
// Helpers
|
|
|
|
private static final List<Option<ModifierKey>> MODIFIER_OPTIONS = Arrays.asList(
|
|
new Option<>(null, text("(No Modifier)")),
|
|
new Option<>(ModifierKey.CONTROL, text("Control")),
|
|
new Option<>(ModifierKey.SHIFT, text("Shift")),
|
|
new Option<>(ModifierKey.ALT, text("Alt"))
|
|
);
|
|
|
|
private void generateKeyBindingWithModifierOption(final int y, final List<GuiEventListener> elements, final Component text, final KeyBindingWithModifier binding) {
|
|
final CycleButtonWidget<ModifierKey> modifierButton = new CycleButtonWidget<>(col4(2), y, COL4_W, MODIFIER_OPTIONS, binding.getModifier(), binding::setModifier);
|
|
final KeyBindingWidget bindingButton = new KeyBindingWidget(col4(3), y, COL4_W, binding, this::startEditingKeyBinding);
|
|
bindingButton.linkButtonToBoundState(modifierButton);
|
|
|
|
generateLeftSideText(y, elements, text);
|
|
elements.add(modifierButton);
|
|
elements.add(bindingButton);
|
|
allKeyBindings.add(bindingButton);
|
|
}
|
|
|
|
private static void generateLeftSideText(final int y, final List<GuiEventListener> elements, final Component text) {
|
|
elements.add(new TextWidget(col2(0), y, COL2_W - TEXT_PADDING_RIGHT, text));
|
|
}
|
|
|
|
// Instance
|
|
|
|
private OptionListWidget optionsWidget;
|
|
private KeyBindingWidget editingKeyBinding;
|
|
private final List<KeyBindingWidget> allKeyBindings = new ArrayList<>();
|
|
|
|
public BetterControlsScreen(@Nullable final Screen parentScreen) {
|
|
super(parentScreen, OPTIONS, TITLE);
|
|
}
|
|
|
|
@Override
|
|
public void init() {
|
|
allKeyBindings.clear();
|
|
|
|
final List<GuiEventListener> elements = new ArrayList<>();
|
|
int y = 0;
|
|
|
|
elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Sprinting"), CENTER));
|
|
y = generateSprintingOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
|
|
|
|
elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Sneaking"), CENTER));
|
|
y = generateSneakingOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
|
|
|
|
elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Flying"), CENTER));
|
|
y = generateFlightOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
|
|
|
|
elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Miscellaneous"), CENTER));
|
|
y = generateMiscellaneousOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
|
|
|
|
addRenderableWidget(new Button(width / 2 - 99, height - 29, 200, 20, CommonComponents.GUI_DONE, btn -> minecraft.setScreen(lastScreen)));
|
|
addWidget(optionsWidget = new OptionListWidget(21, height - 32, width, height, elements, y - TITLE_MARGIN_TOP + BOTTOM_PADDING));
|
|
}
|
|
|
|
@Override
|
|
public void removed() {
|
|
BetterControlsMod.config.save();
|
|
}
|
|
|
|
@Override
|
|
public void render(final PoseStack matrices, final int mouseX, final int mouseY, final float delta) {
|
|
renderBackground(matrices);
|
|
optionsWidget.render(matrices, mouseX, mouseY, delta);
|
|
drawCenteredString(matrices, font, title, width / 2, 8, (255 << 16) | (255 << 8) | 255);
|
|
super.render(matrices, mouseX, mouseY, delta);
|
|
}
|
|
|
|
private void startEditingKeyBinding(final KeyBindingWidget widget) {
|
|
if (editingKeyBinding != null) {
|
|
editingKeyBinding.stopEditing();
|
|
}
|
|
|
|
editingKeyBinding = widget;
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseClicked(final double mouseX, final double mouseY, final int button) {
|
|
if (editingKeyBinding != null) {
|
|
editingKeyBinding.bindAndStopEditing(InputConstants.Type.MOUSE.getOrCreate(button));
|
|
onKeyBindingEditingFinished();
|
|
return true;
|
|
}
|
|
else {
|
|
return super.mouseClicked(mouseX, mouseY, button);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean keyPressed(final int keyCode, final int scanCode, final int modifiers) {
|
|
if (editingKeyBinding != null) {
|
|
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
|
|
editingKeyBinding.bindAndStopEditing(InputConstants.UNKNOWN);
|
|
}
|
|
else {
|
|
editingKeyBinding.bindAndStopEditing(InputConstants.getKey(keyCode, scanCode));
|
|
}
|
|
|
|
onKeyBindingEditingFinished();
|
|
return true;
|
|
}
|
|
else {
|
|
return super.keyPressed(keyCode, scanCode, modifiers);
|
|
}
|
|
}
|
|
|
|
private void onKeyBindingEditingFinished() {
|
|
editingKeyBinding = null;
|
|
KeyMapping.resetMapping();
|
|
|
|
for (final KeyBindingWidget widget : allKeyBindings) {
|
|
widget.updateKeyBindingText();
|
|
}
|
|
}
|
|
}
|