1
0
forked from Clones/Controlify

(unused) abstract joystick renderer system + debug logging + tm joystick mapping

This commit is contained in:
isXander
2023-04-14 15:29:52 +01:00
parent 6092c896fe
commit bf874fef4f
25 changed files with 598 additions and 267 deletions

View File

@ -9,7 +9,7 @@ import java.util.Optional;
public record CompoundJoystickInfo(Collection<String> joystickUids, String friendlyName) {
public ControllerType type() {
return new ControllerType(friendlyName, createUID(joystickUids), true, false);
return new ControllerType(friendlyName, createUID(joystickUids), "generic", true, false);
}
public boolean canBeUsed() {
@ -37,7 +37,7 @@ public record CompoundJoystickInfo(Collection<String> joystickUids, String frien
.toList();
ControllerType type = type();
return Optional.of(new CompoundJoystickController(joystickIDs, type.identifier(), type));
return Optional.of(new CompoundJoystickController(joystickIDs, type.mappingId(), type));
}
public static String createUID(Collection<String> joystickUIDs) {

View File

@ -2,6 +2,7 @@ package dev.isxander.controlify.controller.joystick.mapping;
import dev.isxander.controlify.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.render.JoystickRenderer;
import net.minecraft.network.chat.Component;
public interface JoystickMapping {
@ -23,6 +24,8 @@ public interface JoystickMapping {
float restingValue();
String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction);
JoystickRenderer renderer();
}
interface Button {
@ -31,6 +34,8 @@ public interface JoystickMapping {
Component name();
boolean isPressed(JoystickData data);
JoystickRenderer renderer();
}
interface Hat {
@ -39,6 +44,8 @@ public interface JoystickMapping {
String identifier();
Component name();
JoystickRenderer renderer(JoystickState.HatState state);
}
record JoystickData(float[] axes, boolean[] buttons, JoystickState.HatState[] hats) {

View File

@ -5,6 +5,7 @@ import dev.isxander.controlify.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.ControllerType;
import dev.isxander.controlify.controller.joystick.JoystickController;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.render.JoystickRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
@ -141,7 +142,7 @@ public class RPJoystickMapping implements JoystickMapping {
reader.endObject();
for (var id : ids) {
axes.add(new AxisMapping(id, identifier, inpRange, outRange, restState, deadzone, type.identifier(), axisNames.get(ids.indexOf(id))));
axes.add(new AxisMapping(id, identifier, inpRange, outRange, restState, deadzone, type.mappingId(), axisNames.get(ids.indexOf(id))));
}
}
reader.endArray();
@ -171,7 +172,7 @@ public class RPJoystickMapping implements JoystickMapping {
}
reader.endObject();
buttons.add(new ButtonMapping(id, btnName, type.identifier()));
buttons.add(new ButtonMapping(id, btnName, type.mappingId()));
}
reader.endArray();
@ -231,7 +232,7 @@ public class RPJoystickMapping implements JoystickMapping {
}
reader.endObject();
hats.add(new HatMapping(id, hatName, type.identifier(), axis));
hats.add(new HatMapping(id, hatName, type.mappingId(), axis));
}
reader.endArray();
@ -254,21 +255,21 @@ public class RPJoystickMapping implements JoystickMapping {
}
public static JoystickMapping fromType(JoystickController<?> joystick) {
var resource = Minecraft.getInstance().getResourceManager().getResource(new ResourceLocation("controlify", "mappings/" + joystick.type().identifier() + ".json"));
var resource = Minecraft.getInstance().getResourceManager().getResource(new ResourceLocation("controlify", "mappings/" + joystick.type().mappingId() + ".json"));
if (resource.isEmpty()) {
Controlify.LOGGER.warn("No joystick mapping found for controller: '" + joystick.type().identifier() + "'");
Controlify.LOGGER.warn("No joystick mapping found for controller: '" + joystick.type().mappingId() + "'");
return new UnmappedJoystickMapping(joystick.joystickId());
}
try (var reader = JsonReader.json5(resource.get().openAsReader())) {
return new RPJoystickMapping(reader, joystick.type());
} catch (Exception e) {
Controlify.LOGGER.error("Failed to load joystick mapping for controller: '" + joystick.type().identifier() + "'", e);
Controlify.LOGGER.error("Failed to load joystick mapping for controller: '" + joystick.type().mappingId() + "'", e);
return new UnmappedJoystickMapping(joystick.joystickId());
}
}
private record AxisMapping(int id, String identifier, Vec2 inpRange, Vec2 outRange, float restingValue, boolean requiresDeadzone, String typeId, String[] axisNames) implements Axis {
private record AxisMapping(int id, String identifier, Vec2 inpRange, Vec2 outRange, float restingValue, boolean requiresDeadzone, String theme, String[] axisNames) implements Axis {
@Override
public float getAxis(JoystickData data) {
float rawAxis = data.axes()[id];
@ -286,13 +287,18 @@ public class RPJoystickMapping implements JoystickMapping {
@Override
public Component name() {
return Component.translatable("controlify.joystick_mapping." + typeId() + ".axis." + identifier());
return Component.translatable("controlify.joystick_mapping." + theme() + ".axis." + identifier());
}
@Override
public String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction) {
return this.axisNames()[direction.ordinal()];
}
@Override
public JoystickRenderer renderer() {
return null;
}
}
private record ButtonMapping(int id, String identifier, String typeId) implements Button {
@ -305,6 +311,11 @@ public class RPJoystickMapping implements JoystickMapping {
public Component name() {
return Component.translatable("controlify.joystick_mapping." + typeId() + ".button." + identifier());
}
@Override
public JoystickRenderer renderer() {
return null;
}
}
private record HatMapping(int hatId, String identifier, String typeId, @Nullable EmulatedAxis emulatedAxis) implements Hat {
@ -324,6 +335,11 @@ public class RPJoystickMapping implements JoystickMapping {
return Component.translatable("controlify.joystick_mapping." + typeId() + ".hat." + identifier());
}
@Override
public JoystickRenderer renderer(JoystickState.HatState state) {
return null;
}
private record EmulatedAxis(int axisId, Map<Float, JoystickState.HatState> states) {
}
}

View File

@ -1,13 +1,12 @@
package dev.isxander.controlify.controller.joystick.mapping;
import dev.isxander.controlify.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.joystick.JoystickController;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.render.GenericRenderer;
import dev.isxander.controlify.controller.joystick.render.JoystickRenderer;
import net.minecraft.network.chat.Component;
import org.lwjgl.glfw.GLFW;
import java.util.Arrays;
public class UnmappedJoystickMapping implements JoystickMapping {
public static final UnmappedJoystickMapping EMPTY = new UnmappedJoystickMapping(0, 0, 0);
@ -18,12 +17,12 @@ public class UnmappedJoystickMapping implements JoystickMapping {
private UnmappedJoystickMapping(int axisCount, int buttonCount, int hatCount) {
this.axes = new UnmappedAxis[axisCount];
for (int i = 0; i < axisCount; i++) {
this.axes[i] = new UnmappedAxis(i);
this.axes[i] = new UnmappedAxis(i, new GenericRenderer.Axis(Integer.toString(i + 1)));
}
this.buttons = new UnmappedButton[axisCount];
for (int i = 0; i < buttonCount; i++) {
this.buttons[i] = new UnmappedButton(i);
this.buttons[i] = new UnmappedButton(i, new GenericRenderer.Button(Integer.toString(i + 1)));
}
this.hats = new UnmappedHat[hatCount];
@ -55,7 +54,7 @@ public class UnmappedJoystickMapping implements JoystickMapping {
return hats;
}
private record UnmappedAxis(int axis) implements Axis {
private record UnmappedAxis(int axis, GenericRenderer.Axis renderer) implements Axis {
@Override
public float getAxis(JoystickData data) {
return data.axes()[axis];
@ -92,7 +91,7 @@ public class UnmappedJoystickMapping implements JoystickMapping {
}
}
private record UnmappedButton(int button) implements Button {
private record UnmappedButton(int button, GenericRenderer.Button renderer) implements Button {
@Override
public boolean isPressed(JoystickData data) {
return data.buttons()[button];
@ -124,5 +123,10 @@ public class UnmappedJoystickMapping implements JoystickMapping {
public Component name() {
return Component.translatable("controlify.joystick_mapping.unmapped.hat", hat + 1);
}
@Override
public JoystickRenderer renderer(JoystickState.HatState state) {
return new GenericRenderer.Hat(Integer.toString(hat + 1));
}
}
}

View File

@ -0,0 +1,144 @@
package dev.isxander.controlify.controller.joystick.render;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.gui.DrawSize;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
public abstract class GenericRenderer implements JoystickRenderer {
protected final @Nullable String annotation;
protected final Minecraft minecraft = Minecraft.getInstance();
public GenericRenderer(@Nullable String annotation) {
this.annotation = annotation;
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size) {
if (annotation != null) {
minecraft.font.draw(
poseStack,
annotation,
x + size + 2 - minecraft.font.width(annotation),
centerY + size/2f - minecraft.font.lineHeight * 0.75f,
-1
);
}
return null;
}
public static class Button extends GenericRenderer implements JoystickRenderer.Button {
private static final ResourceLocation BUTTON_TEXTURE = new ResourceLocation("controlify", "textures/gui/joystick/generic/button.png");
public Button(@Nullable String annotation) {
super(annotation);
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size) {
RenderSystem.setShaderTexture(0, BUTTON_TEXTURE);
RenderSystem.setShaderColor(1, 1, 1, 1);
poseStack.pushPose();
poseStack.translate(x, centerY, 0);
float scale = (float) size / 22f;
poseStack.scale(scale, scale, 1);
poseStack.translate(0f, -DEFAULT_SIZE / scale / 2f, 0);
GuiComponent.blit(poseStack, 0, 0, 0, 0, DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE);
poseStack.popPose();
super.render(poseStack, x, centerY, size);
return new DrawSize(size, size);
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size, boolean down) {
return this.render(poseStack, x, centerY, size);
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, boolean down) {
return this.render(poseStack, x, centerY, DEFAULT_SIZE);
}
}
public static class Axis extends GenericRenderer implements JoystickRenderer.Axis {
private static final ResourceLocation AXIS_TEXTURE = new ResourceLocation("controlify", "textures/gui/joystick/generic/axis.png");
public Axis(@Nullable String annotation) {
super(annotation);
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size, JoystickAxisBind.AxisDirection direction) {
RenderSystem.setShaderTexture(0, AXIS_TEXTURE);
RenderSystem.setShaderColor(1, 1, 1, 1);
poseStack.pushPose();
poseStack.translate(x, centerY, 0);
float scale = (float) size / 22f;
poseStack.scale(scale, scale, 1);
poseStack.translate(0f, -DEFAULT_SIZE / scale / 2f, 0);
GuiComponent.blit(
poseStack,
0, 0,
direction.ordinal() * DEFAULT_SIZE, 0,
DEFAULT_SIZE, DEFAULT_SIZE,
DEFAULT_SIZE * JoystickAxisBind.AxisDirection.values().length, DEFAULT_SIZE
);
poseStack.popPose();
super.render(poseStack, x, centerY, size);
return new DrawSize(size, size);
}
}
public static class Hat extends GenericRenderer implements JoystickRenderer.Hat {
private static final ResourceLocation HAT_TEXTURE = new ResourceLocation("controlify", "textures/gui/joystick/generic/hat.png");
public Hat(@Nullable String annotation) {
super(annotation);
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size, JoystickState.HatState hatState) {
RenderSystem.setShaderTexture(0, HAT_TEXTURE);
RenderSystem.setShaderColor(1, 1, 1, 1);
poseStack.pushPose();
poseStack.translate(x, centerY, 0);
float scale = (float) size / 22f;
poseStack.scale(scale, scale, 1);
poseStack.translate(0f, -DEFAULT_SIZE / scale / 2f, 0);
GuiComponent.blit(
poseStack,
0, 0,
hatState.ordinal() * DEFAULT_SIZE, 0,
DEFAULT_SIZE, DEFAULT_SIZE,
DEFAULT_SIZE * JoystickState.HatState.values().length, DEFAULT_SIZE
);
poseStack.popPose();
super.render(poseStack, x, centerY, size);
return new DrawSize(size, size);
}
}
}

View File

@ -0,0 +1,48 @@
package dev.isxander.controlify.controller.joystick.render;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.gui.DrawSize;
public interface JoystickRenderer {
int DEFAULT_SIZE = 22;
DrawSize render(PoseStack poseStack, int x, int centerY, int size);
interface Button extends JoystickRenderer {
DrawSize render(PoseStack poseStack, int x, int centerY, int size, boolean down);
default DrawSize render(PoseStack poseStack, int x, int centerY, boolean down) {
return render(poseStack, x, centerY, DEFAULT_SIZE, down);
}
default DrawSize render(PoseStack poseStack, int x, int centerY, int size) {
return render(poseStack, x, centerY, size, false);
}
}
interface Axis extends JoystickRenderer {
DrawSize render(PoseStack poseStack, int x, int centerY, int size, JoystickAxisBind.AxisDirection direction);
default DrawSize render(PoseStack poseStack, int x, int centerY, JoystickAxisBind.AxisDirection direction) {
return render(poseStack, x, centerY, DEFAULT_SIZE, direction);
}
default DrawSize render(PoseStack poseStack, int x, int centerY, int size) {
return render(poseStack, x, centerY, size, JoystickAxisBind.AxisDirection.POSITIVE);
}
}
interface Hat extends JoystickRenderer {
DrawSize render(PoseStack poseStack, int x, int centerY, int size, JoystickState.HatState state);
default DrawSize render(PoseStack poseStack, int x, int centerY, JoystickState.HatState state) {
return render(poseStack, x, centerY, DEFAULT_SIZE, state);
}
default DrawSize render(PoseStack poseStack, int x, int centerY, int size) {
return render(poseStack, x, centerY, size, JoystickState.HatState.CENTERED);
}
}
}

View File

@ -0,0 +1,116 @@
package dev.isxander.controlify.controller.joystick.render;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.gui.DrawSize;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.resources.ResourceLocation;
public abstract class ThemedRenderer {
protected final Minecraft minecraft = Minecraft.getInstance();
protected final String themeId;
public ThemedRenderer(String themeId) {
this.themeId = themeId;
}
public static class Button extends ThemedRenderer implements JoystickRenderer.Button {
private final ResourceLocation texture;
public Button(String themeId, String identifier) {
super(themeId);
this.texture = new ResourceLocation("controlify", "textures/gui/joystick/" + themeId + "/" + identifier + ".png");
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size, boolean down) {
RenderSystem.setShaderTexture(0, texture);
RenderSystem.setShaderColor(1, 1, 1, 1);
poseStack.pushPose();
poseStack.translate(x, centerY, 0);
float scale = (float) size / 22f;
poseStack.scale(scale, scale, 1);
poseStack.translate(0f, -DEFAULT_SIZE / scale / 2f, 0);
GuiComponent.blit(poseStack, 0, 0, 0, 0, DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE, DEFAULT_SIZE);
poseStack.popPose();
return new DrawSize(size, size);
}
}
public static class Axis extends ThemedRenderer implements JoystickRenderer.Axis {
private final ResourceLocation texture;
public Axis(String themeId, String identifier) {
super(themeId);
this.texture = new ResourceLocation("controlify", "textures/gui/joystick/" + themeId + "/" + identifier + ".png");
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size, JoystickAxisBind.AxisDirection direction) {
RenderSystem.setShaderTexture(0, texture);
RenderSystem.setShaderColor(1, 1, 1, 1);
poseStack.pushPose();
poseStack.translate(x, centerY, 0);
float scale = (float) size / 22f;
poseStack.scale(scale, scale, 1);
poseStack.translate(0f, -DEFAULT_SIZE / scale / 2f, 0);
GuiComponent.blit(
poseStack,
0, 0,
direction.ordinal() * DEFAULT_SIZE, 0,
DEFAULT_SIZE, DEFAULT_SIZE,
DEFAULT_SIZE * JoystickAxisBind.AxisDirection.values().length, DEFAULT_SIZE
);
poseStack.popPose();
return new DrawSize(size, size);
}
}
public static class Hat extends ThemedRenderer implements JoystickRenderer.Hat {
private final ResourceLocation texture;
public Hat(String themeId, String identifier) {
super(themeId);
this.texture = new ResourceLocation("controlify", "textures/gui/joystick/" + themeId + "/" + identifier + ".png");
}
@Override
public DrawSize render(PoseStack poseStack, int x, int centerY, int size, JoystickState.HatState hatState) {
RenderSystem.setShaderTexture(0, texture);
RenderSystem.setShaderColor(1, 1, 1, 1);
poseStack.pushPose();
poseStack.translate(x, centerY, 0);
float scale = (float) size / 22f;
poseStack.scale(scale, scale, 1);
poseStack.translate(0f, -DEFAULT_SIZE / scale / 2f, 0);
GuiComponent.blit(
poseStack,
0, 0,
hatState.ordinal() * DEFAULT_SIZE, 0,
DEFAULT_SIZE, DEFAULT_SIZE,
DEFAULT_SIZE * JoystickState.HatState.values().length, DEFAULT_SIZE
);
poseStack.popPose();
return new DrawSize(size, size);
}
}
}