forked from Clones/Controlify
More radial changes
This commit is contained in:
@ -68,6 +68,8 @@ public interface ControllerBinding {
|
||||
|
||||
JsonObject toJson();
|
||||
|
||||
void tick();
|
||||
|
||||
record KeyMappingOverride(KeyMapping keyMapping, BooleanSupplier toggleable) {
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
|
||||
|
||||
private static final Map<Controller<?, ?>, Set<IBind<?>>> pressedBinds = new HashMap<>();
|
||||
|
||||
private boolean fakePress, fakeRelease;
|
||||
private int fakePressState = 0;
|
||||
|
||||
private ControllerBindingImpl(Controller<T, ?> controller, IBind<T> defaultBind, ResourceLocation id, KeyMappingOverride vanillaOverride, Component name, Component description, Component category, Set<BindContext> contexts) {
|
||||
this.controller = controller;
|
||||
@ -59,35 +59,33 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
|
||||
|
||||
@Override
|
||||
public float state() {
|
||||
if (fakePressState == 1)
|
||||
return 1f;
|
||||
return bind.state(controller.state());
|
||||
}
|
||||
|
||||
@Override
|
||||
public float prevState() {
|
||||
if (fakePressState == 2)
|
||||
return 1f;
|
||||
return bind.state(controller.prevState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean held() {
|
||||
if (fakePress) {
|
||||
fakePress = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return bind.held(controller.state());
|
||||
return fakePressState == 2 || bind.held(controller.state());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prevHeld() {
|
||||
return bind.held(controller.prevState());
|
||||
return fakePressState == 3 || bind.held(controller.prevState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean justPressed() {
|
||||
if (hasBindPressed(this)) return false;
|
||||
|
||||
if ((held() && !prevHeld()) || fakePress) {
|
||||
fakePress = false;
|
||||
if ((held() && !prevHeld()) || fakePressState == 2) {
|
||||
addPressedBind(this);
|
||||
return true;
|
||||
} else {
|
||||
@ -99,7 +97,7 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
|
||||
public boolean justReleased() {
|
||||
if (hasBindPressed(this)) return false;
|
||||
|
||||
if (!held() && prevHeld()) {
|
||||
if ((!held() && prevHeld()) || fakePressState == 3) {
|
||||
addPressedBind(this);
|
||||
return true;
|
||||
} else {
|
||||
@ -109,7 +107,15 @@ public class ControllerBindingImpl<T extends ControllerState> implements Control
|
||||
|
||||
@Override
|
||||
public void fakePress() {
|
||||
this.fakePress = true;
|
||||
this.fakePressState = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (fakePressState > 0)
|
||||
fakePressState++;
|
||||
if (fakePressState >= 4)
|
||||
fakePressState = 0;
|
||||
}
|
||||
|
||||
public IBind<T> currentBind() {
|
||||
|
@ -422,6 +422,9 @@ public class ControllerBindings<T extends ControllerState> {
|
||||
this.imitateVanillaClick();
|
||||
}
|
||||
});
|
||||
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||
registry().values().forEach(ControllerBinding::tick);
|
||||
});
|
||||
|
||||
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> KeyMapping.releaseAll());
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public record RadialAction(ResourceLocation binding, ResourceLocation icon) {
|
||||
public static final RadialAction EMPTY = new RadialAction(
|
||||
RadialMenuScreen.EMPTY,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialIcons.EMPTY
|
||||
);
|
||||
}
|
||||
|
@ -316,10 +316,10 @@ public class ControllerConfigScreenFactory {
|
||||
int action = i;
|
||||
radialMenuGroup.option(Option.<ResourceLocation>createBuilder()
|
||||
.name(Component.translatable("controlify.gui.radial_menu_action", i + 1))
|
||||
.binding(RadialMenuScreen.EMPTY, () -> controller.config().radialActions[action].binding(), v -> controller.config().radialActions[action] = new RadialAction(v, controller.config().radialActions[action].icon()))
|
||||
.binding(RadialMenuScreen.EMPTY_ACTION, () -> controller.config().radialActions[action].binding(), v -> controller.config().radialActions[action] = new RadialAction(v, controller.config().radialActions[action].icon()))
|
||||
.controller(opt -> CyclingListControllerBuilder.create(opt)
|
||||
.values(Iterables.concat(Collections.singleton(RadialMenuScreen.EMPTY), controller.bindings().registry().keySet()))
|
||||
.valueFormatter(id -> !RadialMenuScreen.EMPTY.equals(id) ? controller.bindings().get(id).name() : Component.literal("None")))
|
||||
.values(Iterables.concat(Collections.singleton(RadialMenuScreen.EMPTY_ACTION), controller.bindings().registry().keySet()))
|
||||
.valueFormatter(id -> !RadialMenuScreen.EMPTY_ACTION.equals(id) ? controller.bindings().get(id).name() : Component.literal("None")))
|
||||
.build());
|
||||
}
|
||||
category.group(radialMenuGroup.build());
|
||||
|
@ -2,18 +2,17 @@ package dev.isxander.controlify.gui.screen;
|
||||
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.api.bind.ControllerBinding;
|
||||
import dev.isxander.controlify.api.guide.GuideActionNameSupplier;
|
||||
import dev.isxander.controlify.bindings.GamepadBinds;
|
||||
import dev.isxander.controlify.bindings.RadialAction;
|
||||
import dev.isxander.controlify.bindings.RadialIcons;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.gamepad.GamepadController;
|
||||
import dev.isxander.controlify.controller.gamepad.GamepadState;
|
||||
import dev.isxander.controlify.gui.guide.GuideAction;
|
||||
import dev.isxander.controlify.gui.guide.GuideActionRenderer;
|
||||
import dev.isxander.controlify.gui.layout.AnchorPoint;
|
||||
import dev.isxander.controlify.gui.layout.PositionedComponent;
|
||||
import dev.isxander.controlify.screenop.ComponentProcessor;
|
||||
import dev.isxander.controlify.screenop.ScreenControllerEventListener;
|
||||
import dev.isxander.controlify.screenop.ScreenProcessor;
|
||||
import dev.isxander.controlify.sound.ControlifySounds;
|
||||
import dev.isxander.controlify.utils.Animator;
|
||||
import dev.isxander.controlify.utils.Easings;
|
||||
@ -33,7 +32,6 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.Mth;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -41,7 +39,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class RadialMenuScreen extends Screen implements ScreenControllerEventListener {
|
||||
public static final ResourceLocation EMPTY = new ResourceLocation("controlify", "empty_action");
|
||||
public static final ResourceLocation EMPTY_ACTION = new ResourceLocation("controlify", "empty_action");
|
||||
|
||||
private final Controller<?, ?> controller;
|
||||
|
||||
@ -76,8 +74,8 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
Animator.AnimationInstance animation = new Animator.AnimationInstance(5, Easings::easeOutQuad);
|
||||
for (RadialButton radialButton : buttons) {
|
||||
animation.addConsumer(radialButton::setX, centerX - 16, radialButton.getX());
|
||||
animation.addConsumer(radialButton::setY, centerY - 16, radialButton.getY());
|
||||
animation.addConsumer(radialButton::setX, centerX - 16, (float) radialButton.getX());
|
||||
animation.addConsumer(radialButton::setY, centerY - 16, (float) radialButton.getY());
|
||||
}
|
||||
Animator.INSTANCE.play(animation);
|
||||
|
||||
@ -104,21 +102,12 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
if (this.controller != controller) return;
|
||||
|
||||
if (!controller.bindings().RADIAL_MENU.held()) {
|
||||
if (!isEditing) {
|
||||
if (!editMode) {
|
||||
if (selectedButton != -1 && buttons[selectedButton].invoke()) {
|
||||
playClickSound();
|
||||
}
|
||||
|
||||
onClose();
|
||||
} else {
|
||||
RadialButton button = buttons[selectedButton];
|
||||
int x = button.x < width / 2 ? button.x - 110 : button.x + 42;
|
||||
actionSelectList = new ActionSelectList(selectedButton, x, button.y, 100, 80);
|
||||
addRenderableWidget(actionSelectList);
|
||||
setFocused(actionSelectList);
|
||||
isEditing = true;
|
||||
if (!isEditing && !editMode) {
|
||||
if (selectedButton != -1 && buttons[selectedButton].invoke()) {
|
||||
playClickSound();
|
||||
}
|
||||
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,15 +122,9 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
}
|
||||
}
|
||||
|
||||
if (isEditing) {
|
||||
if (controller.bindings().GUI_PRESS.justPressed() || controller.bindings().GUI_BACK.justPressed()) {
|
||||
finishEditing();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEditing && controller.state() instanceof GamepadState state) {
|
||||
float x = state.gamepadAxes().leftStickX();
|
||||
float y = state.gamepadAxes().leftStickY();
|
||||
float x = state.gamepadAxes().rightStickX();
|
||||
float y = state.gamepadAxes().rightStickY();
|
||||
float threshold = controller.config().buttonActivationThreshold;
|
||||
|
||||
if (Math.abs(x) >= threshold || Math.abs(y) >= threshold) {
|
||||
@ -155,11 +138,15 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
}
|
||||
|
||||
for (int i = 0; i < buttons.length; i++) {
|
||||
buttons[i].setFocused(i == selectedButton);
|
||||
boolean selected = i == selectedButton;
|
||||
buttons[i].setFocused(selected);
|
||||
if (selected) {
|
||||
this.setFocused(buttons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
idleTicks = 0;
|
||||
} else {
|
||||
} else if (!editMode) {
|
||||
idleTicks++;
|
||||
if (idleTicks >= 20) {
|
||||
selectedButton = -1;
|
||||
@ -177,7 +164,8 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
private void finishEditing() {
|
||||
isEditing = false;
|
||||
onClose();
|
||||
removeWidget(actionSelectList);
|
||||
actionSelectList = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -186,10 +174,11 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
public class RadialButton implements Renderable, GuiEventListener, NarratableEntry {
|
||||
public class RadialButton implements Renderable, GuiEventListener, NarratableEntry, ComponentProcessor {
|
||||
public static final ResourceLocation TEXTURE = Controlify.id("textures/gui/radial-buttons.png");
|
||||
|
||||
private int x, y;
|
||||
private float translateX, translateY;
|
||||
private boolean focused;
|
||||
private final ControllerBinding binding;
|
||||
private final MultiLineLabel name;
|
||||
@ -200,7 +189,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
this.y = y;
|
||||
|
||||
RadialAction action = controller.config().radialActions[index];
|
||||
if (!EMPTY.equals(action.binding())) {
|
||||
if (!EMPTY_ACTION.equals(action.binding())) {
|
||||
this.binding = controller.bindings().get(action.binding());
|
||||
this.name = MultiLineLabel.create(font, this.binding.name(), 76);
|
||||
} else {
|
||||
@ -213,13 +202,13 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
@Override
|
||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().translate(x, y, 0);
|
||||
graphics.pose().translate(x + translateX, y + translateY, 0);
|
||||
graphics.pose().scale(2, 2, 1);
|
||||
graphics.blit(TEXTURE, 0, 0, focused ? 16 : 0, 0, 16, 16, 32, 16);
|
||||
graphics.pose().popPose();
|
||||
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().translate(x + 4, y + 4, 0);
|
||||
graphics.pose().translate(x + translateX + 4, y + translateY + 4, 0);
|
||||
graphics.pose().scale(1.5f, 1.5f, 1);
|
||||
this.icon.draw(graphics, 0, 0);
|
||||
graphics.pose().popPose();
|
||||
@ -244,12 +233,14 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
public void setX(float x) {
|
||||
this.x = (int) x;
|
||||
this.translateX = x - this.x;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
public void setY(float y) {
|
||||
this.y = (int) y;
|
||||
this.translateY = y - this.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -262,6 +253,22 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
this.focused = focused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overrideControllerButtons(ScreenProcessor<?> screen, Controller<?, ?> controller) {
|
||||
if (controller == RadialMenuScreen.this.controller) {
|
||||
if (controller.bindings().GUI_PRESS.justPressed()) {
|
||||
RadialButton button = buttons[selectedButton];
|
||||
int x = button.x < width / 2 ? button.x - 110 : button.x + 42;
|
||||
actionSelectList = new ActionSelectList(selectedButton, x, button.y, 100, 80);
|
||||
addRenderableWidget(actionSelectList);
|
||||
RadialMenuScreen.this.setFocused(actionSelectList);
|
||||
isEditing = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NarrationPriority narrationPriority() {
|
||||
return isFocused() ? NarrationPriority.FOCUSED : NarrationPriority.NONE;
|
||||
@ -278,7 +285,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionSelectList implements Renderable, ContainerEventHandler, NarratableEntry {
|
||||
public class ActionSelectList implements Renderable, ContainerEventHandler, NarratableEntry, ComponentProcessor {
|
||||
private final int radialIndex;
|
||||
|
||||
private int x, y;
|
||||
@ -301,6 +308,13 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
controller.bindings().registry().forEach((id, binding) -> {
|
||||
children.add(new ActionEntry(id));
|
||||
});
|
||||
|
||||
var selectedBind = controller.config().radialActions[radialIndex].binding();
|
||||
children.stream()
|
||||
.filter(action -> action.binding.equals(selectedBind))
|
||||
.findAny()
|
||||
.ifPresent(this::setFocused);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -318,6 +332,18 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
graphics.renderOutline(x - 1, this.y - 1, width + 2, height + 2, 0x80ffffff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overrideControllerButtons(ScreenProcessor<?> screen, Controller<?, ?> controller) {
|
||||
if (controller == RadialMenuScreen.this.controller) {
|
||||
if (controller.bindings().GUI_BACK.justPressed()) {
|
||||
finishEditing();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActionEntry> children() {
|
||||
return children;
|
||||
@ -353,9 +379,6 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
else if (focusY + itemHeight > height)
|
||||
scrollOffset = Mth.clamp(index * itemHeight + itemHeight - height, 0, children().size() * itemHeight - height);
|
||||
}
|
||||
|
||||
controller.config().radialActions[radialIndex] = new RadialAction(focus.binding, controller.config().radialActions[radialIndex].icon());
|
||||
Controlify.instance().config().setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,7 +402,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
}
|
||||
|
||||
public class ActionEntry implements GuiEventListener {
|
||||
public class ActionEntry implements GuiEventListener, ComponentProcessor {
|
||||
private int x, y;
|
||||
private boolean focused;
|
||||
private final ResourceLocation binding;
|
||||
@ -396,7 +419,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
if (focused)
|
||||
graphics.fill(x, y, x + width, y + itemHeight, 0xff000000);
|
||||
graphics.drawString(RadialMenuScreen.this.font, name, x + 2, y + 1, -1);
|
||||
graphics.drawString(RadialMenuScreen.this.font, name, x + 2, y + 1, focused ? -1 : 0xffa6a6a6);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -419,6 +442,23 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
public ScreenRectangle getRectangle() {
|
||||
return new ScreenRectangle(x, y, width, itemHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean overrideControllerButtons(ScreenProcessor<?> screen, Controller<?, ?> controller) {
|
||||
if (controller == RadialMenuScreen.this.controller) {
|
||||
if (controller.bindings().GUI_PRESS.justPressed()) {
|
||||
var icon = RadialIcons.getIcons().keySet().toArray(new ResourceLocation[0])[minecraft.level.random.nextInt(RadialIcons.getIcons().size())];
|
||||
controller.config().radialActions[radialIndex] = new RadialAction(binding, icon);
|
||||
Controlify.instance().config().setDirty();
|
||||
|
||||
playClickSound();
|
||||
finishEditing();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
package dev.isxander.controlify.mixins.feature.screenop;
|
||||
|
||||
import dev.isxander.controlify.screenop.CustomFocus;
|
||||
import net.minecraft.client.gui.components.events.ContainerEventHandler;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(ContainerEventHandler.class)
|
||||
public interface ContainerEventHandlerMixin extends CustomFocus {
|
||||
@Shadow
|
||||
@Nullable GuiEventListener getFocused();
|
||||
|
||||
@Override
|
||||
default GuiEventListener getCustomFocus() {
|
||||
return this.getFocused();
|
||||
}
|
||||
}
|
@ -53,6 +53,7 @@
|
||||
"feature.rumble.levelevents.LevelRendererMixin",
|
||||
"feature.rumble.useitem.LivingEntityMixin",
|
||||
"feature.rumble.useitem.LocalPlayerMixin",
|
||||
"feature.screenop.ContainerEventHandlerMixin",
|
||||
"feature.screenop.GameRendererMixin",
|
||||
"feature.screenop.MinecraftMixin",
|
||||
"feature.screenop.ScreenAccessor",
|
||||
|
Reference in New Issue
Block a user