forked from Clones/Controlify
✏️ Finishing touches on radial screen
This commit is contained in:
@ -39,6 +39,7 @@ public class ControllerBindings<T extends ControllerState> {
|
||||
public static final Component VMOUSE_CATEGORY = Component.translatable("controlify.binding_category.vmouse");
|
||||
public static final Component GUI_CATEGORY = Component.translatable("controlify.binding_category.gui");
|
||||
public static final Component MISC_CATEGORY = Component.translatable("key.categories.misc");
|
||||
public static final Component RADIAL_CATEGORY = Component.translatable("controlify.gui.radial_menu");
|
||||
|
||||
public final ControllerBinding
|
||||
WALK_FORWARD, WALK_BACKWARD, WALK_LEFT, WALK_RIGHT,
|
||||
@ -61,7 +62,7 @@ public class ControllerBindings<T extends ControllerState> {
|
||||
PICK_BLOCK,
|
||||
TOGGLE_HUD_VISIBILITY,
|
||||
SHOW_PLAYER_LIST,
|
||||
RADIAL_MENU,
|
||||
RADIAL_MENU, RADIAL_AXIS_UP, RADIAL_AXIS_DOWN, RADIAL_AXIS_LEFT, RADIAL_AXIS_RIGHT,
|
||||
VMOUSE_MOVE_UP, VMOUSE_MOVE_DOWN, VMOUSE_MOVE_LEFT, VMOUSE_MOVE_RIGHT,
|
||||
VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_SHIFT_CLICK,
|
||||
VMOUSE_SCROLL_UP, VMOUSE_SCROLL_DOWN,
|
||||
@ -222,7 +223,7 @@ public class ControllerBindings<T extends ControllerState> {
|
||||
.identifier("controlify", "swap_hands")
|
||||
.defaultBind(GamepadBinds.X_BUTTON)
|
||||
.category(INVENTORY_CATEGORY)
|
||||
.context(BindContexts.INGAME, BindContexts.INVENTORY)
|
||||
.context(BindContexts.INGAME)
|
||||
.radialCandidate(RadialIcons.getItem(Items.BONE))
|
||||
.build());
|
||||
register(OPEN_CHAT = ControllerBindingBuilder.create(controller)
|
||||
@ -304,17 +305,41 @@ public class ControllerBindings<T extends ControllerState> {
|
||||
.build());
|
||||
register(SHOW_PLAYER_LIST = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "show_player_list")
|
||||
.defaultBind(GamepadBinds.DPAD_RIGHT)
|
||||
.defaultBind(new EmptyBind<>())
|
||||
.category(MISC_CATEGORY)
|
||||
.context(BindContexts.INGAME)
|
||||
.radialCandidate(RadialIcons.getItem(Items.PLAYER_HEAD))
|
||||
.build());
|
||||
register(RADIAL_MENU = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "radial_menu")
|
||||
.defaultBind(GamepadBinds.DPAD_DOWN)
|
||||
.category(MISC_CATEGORY)
|
||||
.defaultBind(GamepadBinds.DPAD_RIGHT)
|
||||
.category(RADIAL_CATEGORY)
|
||||
.context(BindContexts.INGAME)
|
||||
.build());
|
||||
register(RADIAL_AXIS_UP = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "radial_axis_up")
|
||||
.defaultBind(GamepadBinds.RIGHT_STICK_FORWARD)
|
||||
.category(RADIAL_CATEGORY)
|
||||
.context(BindContexts.GUI)
|
||||
.build());
|
||||
register(RADIAL_AXIS_DOWN = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "radial_axis_down")
|
||||
.defaultBind(GamepadBinds.RIGHT_STICK_BACKWARD)
|
||||
.category(RADIAL_CATEGORY)
|
||||
.context(BindContexts.GUI)
|
||||
.build());
|
||||
register(RADIAL_AXIS_LEFT = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "radial_axis_left")
|
||||
.defaultBind(GamepadBinds.RIGHT_STICK_LEFT)
|
||||
.category(RADIAL_CATEGORY)
|
||||
.context(BindContexts.GUI)
|
||||
.build());
|
||||
register(RADIAL_AXIS_RIGHT = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "radial_axis_right")
|
||||
.defaultBind(GamepadBinds.RIGHT_STICK_RIGHT)
|
||||
.category(RADIAL_CATEGORY)
|
||||
.context(BindContexts.GUI)
|
||||
.build());
|
||||
register(VMOUSE_MOVE_UP = ControllerBindingBuilder.create(controller)
|
||||
.identifier("controlify", "vmouse_move_up")
|
||||
.defaultBind(GamepadBinds.LEFT_STICK_FORWARD)
|
||||
|
@ -19,19 +19,19 @@ public final class RadialIcons {
|
||||
private static final Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
public static final ResourceLocation EMPTY = new ResourceLocation("controlify", "empty");
|
||||
public static final ResourceLocation FABRIC_ICON = new ResourceLocation("fabric", "icon");
|
||||
public static final ResourceLocation FABRIC_ICON = new ResourceLocation("fabric-resource-loader-v0", "icon.png");
|
||||
|
||||
private static final Map<ResourceLocation, Icon> icons = Util.make(() -> {
|
||||
Map<ResourceLocation, Icon> map = new HashMap<>();
|
||||
|
||||
map.put(EMPTY, (graphics, x, y) -> {});
|
||||
map.put(FABRIC_ICON, ((graphics, x, y) -> {
|
||||
map.put(FABRIC_ICON, (graphics, x, y) -> {
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().translate(x, y, 0);
|
||||
graphics.pose().scale(0.5f, 0.5f, 1f);
|
||||
graphics.blit(FABRIC_ICON, 0, 0, 0, 0, 32, 32);
|
||||
graphics.pose().popPose();
|
||||
}));
|
||||
});
|
||||
addItems(map);
|
||||
addPotionEffects(map);
|
||||
|
||||
|
@ -155,8 +155,8 @@ public class ControlifyConfig {
|
||||
|
||||
private void applyControllerConfig(Controller<?, ?> controller, JsonObject object) {
|
||||
try {
|
||||
controller.setConfig(GSON, object.getAsJsonObject("config"));
|
||||
dirty |= !controller.bindings().fromJson(object.getAsJsonObject("bindings"));
|
||||
controller.setConfig(GSON, object.getAsJsonObject("config"));
|
||||
} catch (Exception e) {
|
||||
Log.LOGGER.error("Failed to load controller data for " + controller.uid() + ". Resetting to default!", e);
|
||||
controller.resetConfig();
|
||||
|
@ -120,6 +120,7 @@ public abstract class AbstractController<S extends ControllerState, C extends Co
|
||||
this.config = SerializationUtils.clone(defaultConfig());
|
||||
Controlify.instance().config().setDirty();
|
||||
}
|
||||
this.config.validateRadialActions(bindings);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,8 @@ package dev.isxander.controlify.controller;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||
import dev.isxander.controlify.gui.screen.RadialMenuScreen;
|
||||
import dev.isxander.controlify.rumble.RumbleSource;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@ -39,14 +41,7 @@ public abstract class ControllerConfig implements Serializable {
|
||||
public boolean mixedInput = false;
|
||||
|
||||
public ResourceLocation[] radialActions = new ResourceLocation[]{
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
RadialMenuScreen.EMPTY_ACTION,
|
||||
null, null, null, null, null, null, null, null,
|
||||
};
|
||||
|
||||
public abstract void setDeadzone(int axis, float deadzone);
|
||||
@ -59,4 +54,33 @@ public abstract class ControllerConfig implements Serializable {
|
||||
public void setRumbleStrength(RumbleSource source, float strength) {
|
||||
vibrationStrengths.addProperty(source.id().toString(), strength);
|
||||
}
|
||||
|
||||
public boolean validateRadialActions(ControllerBindings<?> bindings) {
|
||||
boolean changed = false;
|
||||
for (int i = 0; i < radialActions.length; i++) {
|
||||
ResourceLocation action = radialActions[i];
|
||||
if (!RadialMenuScreen.EMPTY_ACTION.equals(action) && (action == null || !bindings.registry().containsKey(action) || bindings.registry().get(action).radialIcon().isEmpty())) {
|
||||
setDefaultRadialAction(bindings, i);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
Controlify.instance().config().setDirty();
|
||||
|
||||
return !changed;
|
||||
}
|
||||
|
||||
private void setDefaultRadialAction(ControllerBindings<?> bindings, int index) {
|
||||
radialActions[index] = switch (index) {
|
||||
case 0 -> bindings.TOGGLE_HUD_VISIBILITY.id();
|
||||
case 1 -> bindings.CHANGE_PERSPECTIVE.id();
|
||||
case 2 -> bindings.DROP_STACK.id();
|
||||
case 3 -> bindings.OPEN_CHAT.id();
|
||||
case 4 -> bindings.SWAP_HANDS.id();
|
||||
case 5 -> bindings.PICK_BLOCK.id();
|
||||
case 6 -> bindings.PAUSE.id();
|
||||
case 7 -> bindings.SHOW_PLAYER_LIST.id();
|
||||
default -> RadialMenuScreen.EMPTY_ACTION;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +193,11 @@ public class InGameButtonGuide implements IngameGuideRegistry {
|
||||
return Optional.of(Component.translatable("controlify.guide.ingame.inventory"));
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction(controller.bindings().RADIAL_MENU, ActionLocation.RIGHT, ctx -> {
|
||||
if (ctx.client().screen == null)
|
||||
return Optional.of(Component.translatable("controlify.gui.radial_menu"));
|
||||
return Optional.empty();
|
||||
});
|
||||
registerGuideAction(controller.bindings().ATTACK, ActionLocation.RIGHT, (ctx) -> {
|
||||
var hitResult = ctx.hitResult();
|
||||
if (hitResult.getType() == HitResult.Type.ENTITY)
|
||||
|
@ -1,10 +1,10 @@
|
||||
package dev.isxander.controlify.gui.screen;
|
||||
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.api.bind.BindRenderer;
|
||||
import dev.isxander.controlify.api.bind.ControllerBinding;
|
||||
import dev.isxander.controlify.bindings.RadialIcons;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
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;
|
||||
@ -12,9 +12,11 @@ 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.screenop.ScreenProcessorProvider;
|
||||
import dev.isxander.controlify.sound.ControlifySounds;
|
||||
import dev.isxander.controlify.utils.Animator;
|
||||
import dev.isxander.controlify.utils.Easings;
|
||||
import dev.isxander.controlify.virtualmouse.VirtualMouseBehaviour;
|
||||
import net.minecraft.client.gui.ComponentPath;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.MultiLineLabel;
|
||||
@ -22,6 +24,7 @@ import net.minecraft.client.gui.components.Renderable;
|
||||
import net.minecraft.client.gui.components.events.ContainerEventHandler;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.gui.narration.NarratedElementType;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.client.gui.navigation.FocusNavigationEvent;
|
||||
import net.minecraft.client.gui.navigation.ScreenRectangle;
|
||||
@ -39,7 +42,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class RadialMenuScreen extends Screen implements ScreenControllerEventListener {
|
||||
public class RadialMenuScreen extends Screen implements ScreenControllerEventListener, ScreenProcessorProvider {
|
||||
public static final ResourceLocation EMPTY_ACTION = new ResourceLocation("controlify", "empty_action");
|
||||
|
||||
private final Controller<?, ?> controller;
|
||||
@ -53,6 +56,8 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
private ActionSelectList actionSelectList;
|
||||
|
||||
private final Processor processor = new Processor(this);
|
||||
|
||||
public RadialMenuScreen(Controller<?, ?> controller, boolean editMode, Screen parent) {
|
||||
super(Component.empty());
|
||||
this.controller = controller;
|
||||
@ -114,9 +119,13 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
onClose();
|
||||
}
|
||||
|
||||
if (!isEditing && controller.state() instanceof GamepadState state) {
|
||||
float x = state.gamepadAxes().rightStickX();
|
||||
float y = state.gamepadAxes().rightStickY();
|
||||
if (editMode && controller.bindings().GUI_BACK.justPressed()) {
|
||||
onClose();
|
||||
}
|
||||
|
||||
if (!isEditing) {
|
||||
float x = controller.bindings().RADIAL_AXIS_RIGHT.state() - controller.bindings().RADIAL_AXIS_LEFT.state();
|
||||
float y = controller.bindings().RADIAL_AXIS_DOWN.state() - controller.bindings().RADIAL_AXIS_UP.state();
|
||||
float threshold = controller.config().buttonActivationThreshold;
|
||||
|
||||
if (Math.abs(x) >= threshold || Math.abs(y) >= threshold) {
|
||||
@ -152,13 +161,19 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
|
||||
if (minecraft.level == null)
|
||||
if (editMode)
|
||||
renderDirtBackground(graphics);
|
||||
|
||||
super.render(graphics, mouseX, mouseY, delta);
|
||||
|
||||
if (!editMode) {
|
||||
graphics.drawCenteredString(font, Component.translatable("controlify.radial_menu.configure_hint"), width / 2, height - 10 - font.lineHeight, -1);
|
||||
graphics.drawCenteredString(
|
||||
font,
|
||||
Component.translatable("controlify.radial_menu.configure_hint"),
|
||||
width / 2,
|
||||
height - 39,
|
||||
-1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,6 +193,16 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
minecraft.setScreen(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen() {
|
||||
return editMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenProcessor<?> screenProcessor() {
|
||||
return this.processor;
|
||||
}
|
||||
|
||||
public class RadialButton implements Renderable, GuiEventListener, NarratableEntry, ComponentProcessor {
|
||||
public static final ResourceLocation TEXTURE = Controlify.id("textures/gui/radial-buttons.png");
|
||||
|
||||
@ -199,15 +224,24 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) {
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().translate(x + translateX, y + translateY, 0);
|
||||
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().scale(2, 2, 1);
|
||||
graphics.blit(TEXTURE, 0, 0, focused ? 16 : 0, 0, 16, 16, 32, 16);
|
||||
graphics.pose().popPose();
|
||||
|
||||
if (!editMode || !focused) {
|
||||
graphics.pose().pushPose();
|
||||
graphics.pose().translate(x + translateX + 4, y + translateY + 4, 0);
|
||||
graphics.pose().translate(4, 4, 0);
|
||||
graphics.pose().scale(1.5f, 1.5f, 1);
|
||||
this.icon.draw(graphics, 0, 0);
|
||||
graphics.pose().popPose();
|
||||
} else {
|
||||
BindRenderer renderer = controller.bindings().GUI_PRESS.renderer();
|
||||
renderer.render(graphics, 16 - renderer.size().width() / 2, 16);
|
||||
}
|
||||
|
||||
graphics.pose().popPose();
|
||||
|
||||
if (focused)
|
||||
name.renderCentered(graphics, width / 2, height / 2 - font.lineHeight / 2 - ((name.getLineCount() - 1) * font.lineHeight / 2));
|
||||
@ -263,8 +297,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
@Override
|
||||
public boolean overrideControllerButtons(ScreenProcessor<?> screen, Controller<?, ?> controller) {
|
||||
if (controller == RadialMenuScreen.this.controller) {
|
||||
if (controller.bindings().GUI_PRESS.justPressed()) {
|
||||
if (editMode && controller == RadialMenuScreen.this.controller && 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);
|
||||
@ -273,7 +306,6 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
isEditing = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -284,7 +316,8 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
@Override
|
||||
public void updateNarration(NarrationElementOutput builder) {
|
||||
|
||||
if (binding != null)
|
||||
builder.add(NarratedElementType.TITLE, binding.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -370,7 +403,7 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GuiEventListener getFocused() {
|
||||
public ActionEntry getFocused() {
|
||||
return focusedEntry;
|
||||
}
|
||||
|
||||
@ -408,7 +441,9 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
|
||||
@Override
|
||||
public void updateNarration(NarrationElementOutput builder) {
|
||||
|
||||
if (getFocused() != null) {
|
||||
builder.add(NarratedElementType.TITLE, getFocused().name);
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionEntry implements GuiEventListener, ComponentProcessor {
|
||||
@ -471,4 +506,15 @@ public class RadialMenuScreen extends Screen implements ScreenControllerEventLis
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Processor extends ScreenProcessor<RadialMenuScreen> {
|
||||
public Processor(RadialMenuScreen screen) {
|
||||
super(screen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualMouseBehaviour virtualMouseBehaviour() {
|
||||
return VirtualMouseBehaviour.DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,9 @@ public class InGameInputHandler {
|
||||
minecraft.options.hideGui = !minecraft.options.hideGui;
|
||||
}
|
||||
|
||||
shouldShowPlayerList = controller.bindings().SHOW_PLAYER_LIST.held();
|
||||
if (controller.bindings().SHOW_PLAYER_LIST.justPressed()) {
|
||||
shouldShowPlayerList = !shouldShowPlayerList;
|
||||
}
|
||||
|
||||
if (controller.bindings().RADIAL_MENU.justPressed()) {
|
||||
minecraft.setScreen(new RadialMenuScreen(controller, false, null));
|
||||
|
Reference in New Issue
Block a user