forked from Clones/Controlify
joystick axis rendering (no textures), improve config error handling and fix joystick deadzones being unordered
This commit is contained in:
1 parent
fa1a3331e6
commit
8e31472c07
89 files changed
+169
-104
No files matched your search
@@ -125,7 +125,10 @@ public class ControllerBindings<T extends ControllerState> {
|
||||
public void fromJson(JsonObject json) {
|
||||
for (var binding : registry().values()) {
|
||||
var bind = json.get(binding.id().toString()).getAsJsonObject();
|
||||
if (bind == null) continue;
|
||||
if (bind == null) {
|
||||
Controlify.LOGGER.warn("Unknown control: " + binding.id() + " in config file. Skipping!");
|
||||
continue;
|
||||
}
|
||||
binding.setCurrentBind(IBind.fromJson(bind, controller));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public enum GamepadBind implements IBind<GamepadState> {
|
||||
public void draw(PoseStack matrices, int x, int centerY, Controller<GamepadState, ?> controller) {
|
||||
ResourceLocation texture;
|
||||
if (((GamepadConfig)controller.config()).theme == BuiltinGamepadTheme.DEFAULT) {
|
||||
texture = new ResourceLocation("controlify", "textures/gui/gamepad_buttons/" + controller.type().identifier() + "/" + identifier + ".png");
|
||||
texture = new ResourceLocation("controlify", "textures/gui/gamepad/" + controller.type().identifier() + "/" + identifier + ".png");
|
||||
} else {
|
||||
texture = textureLocations.get(((GamepadConfig)controller.config()).theme);
|
||||
}
|
||||
|
||||
@@ -32,14 +32,10 @@ public interface IBind<S extends ControllerState> {
|
||||
case JoystickButtonBind.BIND_ID -> JoystickButtonBind.fromJson(json, joystick);
|
||||
case JoystickHatBind.BIND_ID -> JoystickHatBind.fromJson(json, joystick);
|
||||
case JoystickAxisBind.BIND_ID -> JoystickAxisBind.fromJson(json, joystick);
|
||||
default -> {
|
||||
Controlify.LOGGER.error("Unknown bind type: " + type);
|
||||
yield new EmptyBind<>();
|
||||
}
|
||||
default -> throw new IllegalStateException("Unknown bind type for joystick: " + type);
|
||||
};
|
||||
}
|
||||
|
||||
Controlify.LOGGER.error("Could not parse bind for controller: " + controller.name());
|
||||
return new EmptyBind<>();
|
||||
throw new IllegalStateException("Unknown controller type: " + controller.getClass().getName());
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
package dev.isxander.controlify.bindings;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.joystick.JoystickController;
|
||||
import dev.isxander.controlify.controller.joystick.JoystickState;
|
||||
import dev.isxander.controlify.controller.joystick.mapping.JoystickMapping;
|
||||
import dev.isxander.controlify.controller.joystick.mapping.UnmappedJoystickMapping;
|
||||
import dev.isxander.controlify.gui.DrawSize;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -35,22 +40,32 @@ public class JoystickAxisBind implements IBind<JoystickState> {
|
||||
|
||||
@Override
|
||||
public void draw(PoseStack matrices, int x, int centerY, Controller<JoystickState, ?> controller) {
|
||||
var font = Minecraft.getInstance().font;
|
||||
font.drawShadow(matrices, getTempButtonName(), x + 1.5f, centerY - font.lineHeight / 2f, 0xFFFFFF);
|
||||
if (controller != joystick) return;
|
||||
JoystickMapping mapping = joystick.mapping();
|
||||
|
||||
String type = joystick.type().identifier();
|
||||
String axis = mapping.axis(axisIndex).identifier();
|
||||
String direction = mapping.axis(axisIndex).getDirectionIdentifier(axisIndex, this.direction);
|
||||
var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/axis_" + axis + "_" + direction + ".png");
|
||||
|
||||
RenderSystem.setShaderTexture(0, texture);
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
GuiComponent.blit(matrices, x, centerY - 11, 0, 0, 22, 22, 22, 22);
|
||||
|
||||
if (mapping instanceof UnmappedJoystickMapping) {
|
||||
var text = Integer.toString(axisIndex + 1);
|
||||
var font = Minecraft.getInstance().font;
|
||||
GuiComponent.drawCenteredString(matrices, font, text, x + 11, centerY - font.lineHeight / 2, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DrawSize drawSize() {
|
||||
var font = Minecraft.getInstance().font;
|
||||
return new DrawSize(font.width(getTempButtonName()) + 3, font.lineHeight);
|
||||
}
|
||||
int width = 22;
|
||||
if (joystick.mapping() instanceof UnmappedJoystickMapping)
|
||||
width = Math.max(width, Minecraft.getInstance().font.width(Integer.toString(axisIndex + 1)));
|
||||
|
||||
private Component getTempButtonName() {
|
||||
var axis = joystick.mapping().axis(axisIndex);
|
||||
return Component.empty()
|
||||
.append(axis.name())
|
||||
.append(" ")
|
||||
.append(axis.getDirectionName(axisIndex, direction));
|
||||
return new DrawSize(width, 22);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package dev.isxander.controlify.bindings;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.joystick.JoystickController;
|
||||
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.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -29,19 +32,20 @@ public class JoystickButtonBind implements IBind<JoystickState> {
|
||||
|
||||
@Override
|
||||
public void draw(PoseStack matrices, int x, int centerY, Controller<JoystickState, ?> controller) {
|
||||
var font = Minecraft.getInstance().font;
|
||||
if (controller != joystick) return;
|
||||
|
||||
font.drawShadow(matrices, getTempButtonName(), x + 1.5f, centerY - font.lineHeight / 2f, 0xFFFFFF);
|
||||
String type = joystick.type().identifier();
|
||||
String button = joystick.mapping().button(buttonIndex).identifier();
|
||||
var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/button_" + button + ".png");
|
||||
|
||||
RenderSystem.setShaderTexture(0, texture);
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
GuiComponent.blit(matrices, x, centerY - 11, 0, 0, 22, 22, 22, 22);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DrawSize drawSize() {
|
||||
var font = Minecraft.getInstance().font;
|
||||
return new DrawSize(font.width(getTempButtonName()) + 3, font.lineHeight);
|
||||
}
|
||||
|
||||
private Component getTempButtonName() {
|
||||
return joystick.mapping().button(buttonIndex).name();
|
||||
return new DrawSize(22, 22);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package dev.isxander.controlify.bindings;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.controller.joystick.JoystickController;
|
||||
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.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -31,21 +34,30 @@ public class JoystickHatBind implements IBind<JoystickState> {
|
||||
|
||||
@Override
|
||||
public void draw(PoseStack matrices, int x, int centerY, Controller<JoystickState, ?> controller) {
|
||||
var font = Minecraft.getInstance().font;
|
||||
font.drawShadow(matrices, getTempButtonName(), x + 1.5f, centerY - font.lineHeight / 2f, 0xFFFFFF);
|
||||
if (controller != joystick) return;
|
||||
|
||||
String type = joystick.type().identifier();
|
||||
String button = joystick.mapping().button(hatIndex).identifier();
|
||||
String direction = "centered";
|
||||
if (hatState.isUp())
|
||||
direction = "up";
|
||||
else if (hatState.isDown())
|
||||
direction = "down";
|
||||
else if (hatState.isLeft())
|
||||
direction = "left";
|
||||
else if (hatState.isRight())
|
||||
direction = "right";
|
||||
|
||||
var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/hat" + button + "_" + direction + ".png");
|
||||
|
||||
RenderSystem.setShaderTexture(0, texture);
|
||||
RenderSystem.setShaderColor(1, 1, 1, 1);
|
||||
GuiComponent.blit(matrices, x, centerY - 11, 0, 0, 22, 22, 22, 22);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DrawSize drawSize() {
|
||||
var font = Minecraft.getInstance().font;
|
||||
return new DrawSize(font.width(getTempButtonName()) + 3, font.lineHeight);
|
||||
}
|
||||
|
||||
private Component getTempButtonName() {
|
||||
return Component.empty()
|
||||
.append(joystick.mapping().hat(hatIndex).name())
|
||||
.append(" ")
|
||||
.append(hatState.getDisplayName());
|
||||
return new DrawSize(22, 22);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -105,8 +105,14 @@ public class ControlifyConfig {
|
||||
}
|
||||
|
||||
private void applyControllerConfig(Controller<?, ?> controller, JsonObject object) {
|
||||
controller.setConfig(GSON, object.getAsJsonObject("config"));
|
||||
controller.bindings().fromJson(object.getAsJsonObject("bindings"));
|
||||
try {
|
||||
controller.setConfig(GSON, object.getAsJsonObject("config"));
|
||||
controller.bindings().fromJson(object.getAsJsonObject("bindings"));
|
||||
} catch (Exception e) {
|
||||
Controlify.LOGGER.error("Failed to load controller data for " + controller.uid() + ". Resetting to default!", e);
|
||||
controller.resetConfig();
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
public GlobalSettings globalSettings() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -190,7 +191,8 @@ public class YACLHelper {
|
||||
.collect(Collectors.toMap(
|
||||
i -> joystick.mapping().axis(i).identifier(),
|
||||
i -> i,
|
||||
(x, y) -> x
|
||||
(x, y) -> x,
|
||||
LinkedHashMap::new
|
||||
))
|
||||
.values();
|
||||
var jsCfg = joystick.config();
|
||||
|
||||
@@ -97,6 +97,11 @@ public abstract class AbstractController<S extends ControllerState, C extends Co
|
||||
return this.defaultConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConfig() {
|
||||
this.config = defaultConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(Gson gson, JsonElement json) {
|
||||
C newConfig = gson.fromJson(json, new TypeToken<C>(getClass()){}.getType());
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.google.gson.JsonElement;
|
||||
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||
import dev.isxander.controlify.controller.gamepad.GamepadController;
|
||||
import dev.isxander.controlify.controller.joystick.JoystickController;
|
||||
import dev.isxander.controlify.debug.DebugProperties;
|
||||
import org.hid4java.HidDevice;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
@@ -24,6 +25,7 @@ public interface Controller<S extends ControllerState, C extends ControllerConfi
|
||||
|
||||
C config();
|
||||
C defaultConfig();
|
||||
void resetConfig();
|
||||
void setConfig(Gson gson, JsonElement json);
|
||||
|
||||
ControllerType type();
|
||||
@@ -39,7 +41,7 @@ public interface Controller<S extends ControllerState, C extends ControllerConfi
|
||||
return CONTROLLERS.get(joystickId);
|
||||
}
|
||||
|
||||
if (GLFW.glfwJoystickIsGamepad(joystickId)) {
|
||||
if (GLFW.glfwJoystickIsGamepad(joystickId) && !DebugProperties.FORCE_JOYSTICK) {
|
||||
GamepadController controller = new GamepadController(joystickId, device);
|
||||
CONTROLLERS.put(joystickId, controller);
|
||||
return controller;
|
||||
@@ -94,6 +96,11 @@ public interface Controller<S extends ControllerState, C extends ControllerConfi
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetConfig() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(Gson gson, JsonElement json) {
|
||||
|
||||
|
||||
@@ -6,17 +6,12 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JoystickConfig extends ControllerConfig {
|
||||
private final Map<String, Float> deadzones;
|
||||
private Map<String, Float> deadzones;
|
||||
|
||||
private transient JoystickController controller;
|
||||
|
||||
public JoystickConfig(JoystickController controller) {
|
||||
this.controller = controller;
|
||||
deadzones = new HashMap<>();
|
||||
for (int i = 0; i < controller.axisCount(); i++) {
|
||||
if (controller.mapping().axis(i).requiresDeadzone())
|
||||
deadzones.put(controller.mapping().axis(i).identifier(), 0.2f);
|
||||
}
|
||||
setup(controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,7 +30,14 @@ public class JoystickConfig extends ControllerConfig {
|
||||
return deadzones.getOrDefault(controller.mapping().axis(axis).identifier(), 0.2f);
|
||||
}
|
||||
|
||||
void setController(JoystickController controller) {
|
||||
void setup(JoystickController controller) {
|
||||
this.controller = controller;
|
||||
if (this.deadzones == null) {
|
||||
deadzones = new HashMap<>();
|
||||
for (int i = 0; i < controller.axisCount(); i++) {
|
||||
if (controller.mapping().axis(i).requiresDeadzone())
|
||||
deadzones.put(controller.mapping().axis(i).identifier(), 0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,6 @@ public class JoystickController extends AbstractController<JoystickState, Joysti
|
||||
@Override
|
||||
public void setConfig(Gson gson, JsonElement json) {
|
||||
super.setConfig(gson, json);
|
||||
this.config.setController(this);
|
||||
this.config.setup(this);
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -133,9 +133,8 @@ public class DataJoystickMapping implements JoystickMapping {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDirectionName(int axis, JoystickAxisBind.AxisDirection direction) {
|
||||
var directionId = axisNames().get(ids.indexOf(axis)).get(direction.ordinal());
|
||||
return Component.translatable("controlify.joystick_mapping." + typeId() + ".axis." + identifier() + "." + directionId);
|
||||
public String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction) {
|
||||
return this.axisNames().get(ids.indexOf(axis)).get(direction.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +143,8 @@ public class DataJoystickMapping implements JoystickMapping {
|
||||
public Component name() {
|
||||
return Component.translatable("controlify.joystick_mapping." + typeId() + ".button." + identifier());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private record HatMapping(String identifier, String typeId) implements Hat {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public interface JoystickMapping {
|
||||
|
||||
boolean isAxisResting(float value);
|
||||
|
||||
Component getDirectionName(int axis, JoystickAxisBind.AxisDirection direction);
|
||||
String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction);
|
||||
}
|
||||
|
||||
interface Button {
|
||||
|
||||
+27
-27
@@ -24,36 +24,36 @@ public class UnmappedJoystickMapping implements JoystickMapping {
|
||||
private record UnmappedAxis(int axis) implements Axis {
|
||||
|
||||
@Override
|
||||
public String identifier() {
|
||||
public String identifier() {
|
||||
return "axis-" + axis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component name() {
|
||||
return Component.translatable("controlify.joystick_mapping.unmapped.axis", axis + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresDeadzone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float modifyAxis(float value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAxisResting(float value) {
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDirectionName(int axis, JoystickAxisBind.AxisDirection direction) {
|
||||
return Component.translatable("controlify.joystick_mapping.unmapped.axis_direction." + direction.name().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component name() {
|
||||
return Component.translatable("controlify.joystick_mapping.unmapped.axis", axis + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requiresDeadzone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float modifyAxis(float value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAxisResting(float value) {
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction) {
|
||||
return direction.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
private record UnmappedButton(int button) implements Button {
|
||||
@Override
|
||||
public String identifier() {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.isxander.controlify.debug;
|
||||
|
||||
public class DebugProperties {
|
||||
// Renders debug overlay for vmouse snapping
|
||||
public static final boolean DEBUG_SNAPPING = boolProp("controlify.debug.snapping", false);
|
||||
// Forces all gamepads to be treated as a regular joystick
|
||||
public static final boolean FORCE_JOYSTICK = boolProp("controlify.debug.force_joystick", false);
|
||||
|
||||
private static boolean boolProp(String name, boolean def) {
|
||||
return Boolean.parseBoolean(System.getProperty(name, Boolean.toString(def)));
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.mojang.datafixers.util.Pair;
|
||||
import dev.isxander.controlify.Controlify;
|
||||
import dev.isxander.controlify.InputMode;
|
||||
import dev.isxander.controlify.controller.Controller;
|
||||
import dev.isxander.controlify.debug.DebugProperties;
|
||||
import dev.isxander.controlify.screenop.ScreenProcessorProvider;
|
||||
import dev.isxander.controlify.event.ControlifyEvents;
|
||||
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;
|
||||
@@ -26,7 +27,6 @@ import java.util.Comparator;
|
||||
import java.util.Set;
|
||||
|
||||
public class VirtualMouseHandler {
|
||||
private static final boolean DEBUG_SNAPPING = FabricLoader.getInstance().isDevelopmentEnvironment();
|
||||
private static final ResourceLocation CURSOR_TEXTURE = new ResourceLocation("controlify", "textures/gui/virtual_mouse.png");
|
||||
|
||||
private double targetX, targetY;
|
||||
@@ -201,7 +201,7 @@ public class VirtualMouseHandler {
|
||||
public void renderVirtualMouse(PoseStack matrices) {
|
||||
if (!virtualMouseEnabled) return;
|
||||
|
||||
if (DEBUG_SNAPPING) {
|
||||
if (DebugProperties.DEBUG_SNAPPING) {
|
||||
for (var snapPoint : snapPoints) {
|
||||
GuiComponent.fill(matrices, snapPoint.position().x() - snapPoint.range(), snapPoint.position().y() - snapPoint.range(), snapPoint.position().x() + snapPoint.range(), snapPoint.position().y() + snapPoint.range(), 0x33FFFFFF);
|
||||
GuiComponent.fill(matrices, snapPoint.position().x() - 1, snapPoint.position().y() - 1, snapPoint.position().x() + 1, snapPoint.position().y() + 1, snapPoint.equals(lastSnappedPoint) ? 0xFFFFFF00 : 0xFFFF0000);
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
// THIS FILE IS PARSED BY LENIENT GSON PARSER AND IS NOT JSON5 COMPLIANT!
|
||||
[
|
||||
{
|
||||
"name": "Xbox One Controller",
|
||||
"identifier": "xbox_one",
|
||||
|
||||
"vendor": 1118, // 0x45e
|
||||
"product": [
|
||||
767, // 0x2ff
|
||||
746, // 0x2ea
|
||||
2834, // 0xb12
|
||||
733, // 0x2dd
|
||||
739, // 0x2e3
|
||||
742, // 0x2e6
|
||||
765, // 0x2fd
|
||||
721, // 0x2d1
|
||||
649, // 0x289
|
||||
514, // 0x202
|
||||
645, // 0x285
|
||||
648 // 0x288
|
||||
]
|
||||
},
|
||||
// {
|
||||
// "name": "Xbox One Controller",
|
||||
// "identifier": "xbox_one",
|
||||
//
|
||||
// "vendor": 1118, // 0x45e
|
||||
// "product": [
|
||||
// 767, // 0x2ff
|
||||
// 746, // 0x2ea
|
||||
// 2834, // 0xb12
|
||||
// 733, // 0x2dd
|
||||
// 739, // 0x2e3
|
||||
// 742, // 0x2e6
|
||||
// 765, // 0x2fd
|
||||
// 721, // 0x2d1
|
||||
// 649, // 0x289
|
||||
// 514, // 0x202
|
||||
// 645, // 0x285
|
||||
// 648 // 0x288
|
||||
// ]
|
||||
// },
|
||||
{
|
||||
"name": "Dualshock 4 Controller",
|
||||
"identifier": "dualshock4",
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user