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

@ -11,10 +11,10 @@ blossom = "1.3.+"
minecraft = "1.19.4" minecraft = "1.19.4"
quilt_mappings = "10" quilt_mappings = "10"
fabric_loader = "0.14.17" fabric_loader = "0.14.17"
fabric_api = "0.76.0+1.19.4" fabric_api = "0.78.0+1.19.4"
mixin_extras = "0.2.0-beta.1" mixin_extras = "0.2.0-beta.6"
yet_another_config_lib = "2.4.0" yet_another_config_lib = "2.4.0"
mod_menu = "6.1.0-rc.1" mod_menu = "6.1.0-rc.4"
hid4java = "0.7.0" hid4java = "0.7.0"
quilt_json5 = "1.0.3" quilt_json5 = "1.0.3"
sodium = "mc1.19.4-0.4.10" sodium = "mc1.19.4-0.4.10"
@ -27,7 +27,7 @@ minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" } fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" } fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" }
mixin_extras = { module = "com.github.llamalad7:mixinextras", version.ref = "mixin_extras" } mixin_extras = { module = "com.github.llamalad7.mixinextras:mixinextras-fabric", version.ref = "mixin_extras" }
yet_another_config_lib = { module = "dev.isxander:yet-another-config-lib", version.ref = "yet_another_config_lib" } yet_another_config_lib = { module = "dev.isxander:yet-another-config-lib", version.ref = "yet_another_config_lib" }
mod_menu = { module = "com.terraformersmc:modmenu", version.ref = "mod_menu" } mod_menu = { module = "com.terraformersmc:modmenu", version.ref = "mod_menu" }
hid4java = { module = "org.hid4java:hid4java", version.ref = "hid4java" } hid4java = { module = "org.hid4java:hid4java", version.ref = "hid4java" }

View File

@ -8,6 +8,7 @@ import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState; import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.controller.joystick.CompoundJoystickController; import dev.isxander.controlify.controller.joystick.CompoundJoystickController;
import dev.isxander.controlify.controller.sdl2.SDL2NativesManager; import dev.isxander.controlify.controller.sdl2.SDL2NativesManager;
import dev.isxander.controlify.debug.DebugProperties;
import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen; import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen;
import dev.isxander.controlify.gui.screen.VibrationOnboardingScreen; import dev.isxander.controlify.gui.screen.VibrationOnboardingScreen;
import dev.isxander.controlify.screenop.ScreenProcessorProvider; import dev.isxander.controlify.screenop.ScreenProcessorProvider;
@ -17,6 +18,7 @@ import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.ingame.guide.InGameButtonGuide; import dev.isxander.controlify.ingame.guide.InGameButtonGuide;
import dev.isxander.controlify.ingame.InGameInputHandler; import dev.isxander.controlify.ingame.InGameInputHandler;
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor; import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
import dev.isxander.controlify.utils.DebugLog;
import dev.isxander.controlify.utils.ToastUtils; import dev.isxander.controlify.utils.ToastUtils;
import dev.isxander.controlify.virtualmouse.VirtualMouseHandler; import dev.isxander.controlify.virtualmouse.VirtualMouseHandler;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
@ -74,9 +76,7 @@ public class Controlify implements ControlifyApi {
} }
private void initializeControllers() { private void initializeControllers() {
LOGGER.info("Discovering and initializing controllers..."); DebugLog.log("Discovering and initializing controllers...");
config().load();
if (config().globalSettings().loadVibrationNatives) if (config().globalSettings().loadVibrationNatives)
SDL2NativesManager.initialise(); SDL2NativesManager.initialise();
@ -140,6 +140,8 @@ public class Controlify implements ControlifyApi {
} }
public void preInitialiseControlify() { public void preInitialiseControlify() {
DebugProperties.printProperties();
LOGGER.info("Pre-initializing Controlify..."); LOGGER.info("Pre-initializing Controlify...");
this.inGameInputHandler = new InGameInputHandler(Controller.DUMMY); // initialize with dummy controller before connection in case of no controller this.inGameInputHandler = new InGameInputHandler(Controller.DUMMY); // initialize with dummy controller before connection in case of no controller
@ -205,7 +207,7 @@ public class Controlify implements ControlifyApi {
if (state.hasAnyInput()) if (state.hasAnyInput())
this.setInputMode(InputMode.CONTROLLER); this.setInputMode(InputMode.CONTROLLER);
if (consecutiveInputSwitches > 500) { if (consecutiveInputSwitches > 100) {
LOGGER.warn("Controlify detected current controller to be constantly giving input and has been disabled."); LOGGER.warn("Controlify detected current controller to be constantly giving input and has been disabled.");
ToastUtils.sendToast( ToastUtils.sendToast(
Component.translatable("controlify.toast.faulty_input.title"), Component.translatable("controlify.toast.faulty_input.title"),
@ -289,13 +291,13 @@ public class Controlify implements ControlifyApi {
try { try {
if (info.isLoaded() && !info.canBeUsed()) { if (info.isLoaded() && !info.canBeUsed()) {
LOGGER.warn("Unloading compound joystick " + info.friendlyName() + " due to missing controllers."); LOGGER.warn("Unloading compound joystick " + info.friendlyName() + " due to missing controllers.");
Controller.CONTROLLERS.remove(info.type().identifier()); Controller.CONTROLLERS.remove(info.type().mappingId());
} }
if (!info.isLoaded() && info.canBeUsed()) { if (!info.isLoaded() && info.canBeUsed()) {
LOGGER.info("Loading compound joystick " + info.type().identifier() + "."); LOGGER.info("Loading compound joystick " + info.type().mappingId() + ".");
CompoundJoystickController controller = info.attemptCreate().orElseThrow(); CompoundJoystickController controller = info.attemptCreate().orElseThrow();
Controller.CONTROLLERS.put(info.type().identifier(), controller); Controller.CONTROLLERS.put(info.type().mappingId(), controller);
config().loadOrCreateControllerData(controller); config().loadOrCreateControllerData(controller);
} }
} catch (Exception e) { } catch (Exception e) {
@ -339,14 +341,14 @@ public class Controlify implements ControlifyApi {
switchableController = null; switchableController = null;
} }
LOGGER.info("Updated current controller to " + controller.name() + "(" + controller.uid() + ")"); DebugLog.log("Updated current controller to {}({})", controller.name(), controller.uid());
if (!config().currentControllerUid().equals(controller.uid())) { if (!config().currentControllerUid().equals(controller.uid())) {
config().save(); config().save();
} }
this.inGameInputHandler = new InGameInputHandler(controller); this.inGameInputHandler = new InGameInputHandler(controller);
if (Minecraft.getInstance().player != null) { if (minecraft.player != null) {
this.inGameButtonGuide = new InGameButtonGuide(controller, Minecraft.getInstance().player); this.inGameButtonGuide = new InGameButtonGuide(controller, Minecraft.getInstance().player);
} }

View File

@ -65,7 +65,7 @@ public class GamepadBind implements IBind<GamepadState> {
private ResourceLocation getTexture(BuiltinGamepadTheme theme) { private ResourceLocation getTexture(BuiltinGamepadTheme theme) {
String themeId = theme.id(); String themeId = theme.id();
if (theme == BuiltinGamepadTheme.DEFAULT) if (theme == BuiltinGamepadTheme.DEFAULT)
themeId = gamepad.type().identifier(); themeId = gamepad.type().themeId();
return new ResourceLocation("controlify", "textures/gui/gamepad/" + themeId + "/" + identifier + ".png"); return new ResourceLocation("controlify", "textures/gui/gamepad/" + themeId + "/" + identifier + ".png");
} }

View File

@ -41,7 +41,7 @@ public class JoystickAxisBind implements IBind<JoystickState> {
public void draw(PoseStack matrices, int x, int centerY) { public void draw(PoseStack matrices, int x, int centerY) {
JoystickMapping mapping = joystick.mapping(); JoystickMapping mapping = joystick.mapping();
String type = joystick.type().identifier(); String type = joystick.type().themeId();
String axis = mapping.axes()[axisIndex].identifier(); String axis = mapping.axes()[axisIndex].identifier();
String direction = mapping.axes()[axisIndex].getDirectionIdentifier(axisIndex, this.direction); String direction = mapping.axes()[axisIndex].getDirectionIdentifier(axisIndex, this.direction);
var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/axis_" + axis + "_" + direction + ".png"); var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/axis_" + axis + "_" + direction + ".png");

View File

@ -30,7 +30,7 @@ public class JoystickButtonBind implements IBind<JoystickState> {
@Override @Override
public void draw(PoseStack matrices, int x, int centerY) { public void draw(PoseStack matrices, int x, int centerY) {
String type = joystick.type().identifier(); String type = joystick.type().themeId();
String button = joystick.mapping().buttons()[buttonIndex].identifier(); String button = joystick.mapping().buttons()[buttonIndex].identifier();
var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/button_" + button + ".png"); var texture = new ResourceLocation("controlify", "textures/gui/joystick/" + type + "/button_" + button + ".png");

View File

@ -32,7 +32,7 @@ public class JoystickHatBind implements IBind<JoystickState> {
@Override @Override
public void draw(PoseStack matrices, int x, int centerY) { public void draw(PoseStack matrices, int x, int centerY) {
String type = joystick.type().identifier(); String type = joystick.type().themeId();
String hat = joystick.mapping().hats()[hatIndex].identifier(); String hat = joystick.mapping().hats()[hatIndex].identifier();
String direction = "centered"; String direction = "centered";
if (hatState.isUp()) if (hatState.isUp())

View File

@ -4,6 +4,7 @@ import com.google.gson.*;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.joystick.CompoundJoystickInfo; import dev.isxander.controlify.controller.joystick.CompoundJoystickInfo;
import dev.isxander.controlify.utils.DebugLog;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import java.io.IOException; import java.io.IOException;
@ -66,7 +67,7 @@ public class ControlifyConfig {
} }
if (dirty) { if (dirty) {
Controlify.LOGGER.info("Config was dirty after load, saving..."); DebugLog.log("Config was dirty after load, saving...");
save(); save();
} }
} }
@ -121,7 +122,7 @@ public class ControlifyConfig {
.asList() .asList()
.stream() .stream()
.map(element -> GSON.fromJson(element, CompoundJoystickInfo.class)) .map(element -> GSON.fromJson(element, CompoundJoystickInfo.class))
.collect(Collectors.toMap(info -> info.type().identifier(), Function.identity())); .collect(Collectors.toMap(info -> info.type().mappingId(), Function.identity()));
if (object.has("current_controller")) { if (object.has("current_controller")) {
currentControllerUid = object.get("current_controller").getAsString(); currentControllerUid = object.get("current_controller").getAsString();
@ -134,10 +135,10 @@ public class ControlifyConfig {
public void loadOrCreateControllerData(Controller<?, ?> controller) { public void loadOrCreateControllerData(Controller<?, ?> controller) {
var uid = controller.uid(); var uid = controller.uid();
if (controllerData.has(uid)) { if (controllerData.has(uid)) {
Controlify.LOGGER.info("Loading controller data for " + uid); DebugLog.log("Loading controller data for " + uid);
applyControllerConfig(controller, controllerData.getAsJsonObject(uid)); applyControllerConfig(controller, controllerData.getAsJsonObject(uid));
} else { } else {
Controlify.LOGGER.info("New controller found, creating controller data for " + uid); DebugLog.log("New controller found, setting config dirty ({})", uid);
setDirty(); setDirty();
} }
} }
@ -159,7 +160,7 @@ public class ControlifyConfig {
public void saveIfDirty() { public void saveIfDirty() {
if (dirty) { if (dirty) {
Controlify.LOGGER.info("Config is dirty. Saving..."); DebugLog.log("Config is dirty. Saving...");
save(); save();
} }
} }

View File

@ -237,7 +237,7 @@ public class YACLHelper {
} }
category.group(vibrationGroup.build()); category.group(vibrationGroup.build());
if (controller instanceof GamepadController gamepad && (gamepad.hasGyro() || true)) { if (controller instanceof GamepadController gamepad && gamepad.hasGyro()) {
var gpCfg = gamepad.config(); var gpCfg = gamepad.config();
var gpCfgDef = gamepad.defaultConfig(); var gpCfgDef = gamepad.defaultConfig();

View File

@ -11,6 +11,7 @@ import dev.isxander.controlify.debug.DebugProperties;
import dev.isxander.controlify.rumble.RumbleCapable; import dev.isxander.controlify.rumble.RumbleCapable;
import dev.isxander.controlify.rumble.RumbleManager; import dev.isxander.controlify.rumble.RumbleManager;
import dev.isxander.controlify.rumble.RumbleSource; import dev.isxander.controlify.rumble.RumbleSource;
import dev.isxander.controlify.utils.DebugLog;
import net.minecraft.CrashReport; import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory; import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException; import net.minecraft.ReportedException;
@ -59,7 +60,7 @@ public interface Controller<S extends ControllerState, C extends ControllerConfi
} }
if (hidInfo.type().dontLoad()) { if (hidInfo.type().dontLoad()) {
Controlify.LOGGER.warn("Preventing load of controller #" + joystickId + " because its type prevents loading."); DebugLog.log("Preventing load of controller #" + joystickId + " because its type prevents loading.");
return Optional.empty(); return Optional.empty();
} }

View File

@ -11,8 +11,8 @@ import org.quiltmc.json5.JsonReader;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
public record ControllerType(String friendlyName, String identifier, boolean forceJoystick, boolean dontLoad) { public record ControllerType(String friendlyName, String mappingId, String themeId, boolean forceJoystick, boolean dontLoad) {
public static final ControllerType UNKNOWN = new ControllerType("Unknown", "unknown", false, false); public static final ControllerType UNKNOWN = new ControllerType("Unknown", "unknown", "unknown", false, false);
private static Map<HIDIdentifier, ControllerType> typeMap = null; private static Map<HIDIdentifier, ControllerType> typeMap = null;
private static final ResourceLocation hidDbLocation = new ResourceLocation("controlify", "controllers/controller_identification.json5"); private static final ResourceLocation hidDbLocation = new ResourceLocation("controlify", "controllers/controller_identification.json5");
@ -46,7 +46,9 @@ public record ControllerType(String friendlyName, String identifier, boolean for
reader.beginArray(); reader.beginArray();
while (reader.hasNext()) { while (reader.hasNext()) {
String friendlyName = null; String friendlyName = null;
String identifier = null; String legacyIdentifier = null;
String themeId = null;
String mappingId = null;
boolean forceJoystick = false; boolean forceJoystick = false;
boolean dontLoad = false; boolean dontLoad = false;
Set<HIDIdentifier> hids = new HashSet<>(); Set<HIDIdentifier> hids = new HashSet<>();
@ -57,7 +59,9 @@ public record ControllerType(String friendlyName, String identifier, boolean for
switch (name) { switch (name) {
case "name" -> friendlyName = reader.nextString(); case "name" -> friendlyName = reader.nextString();
case "identifier" -> identifier = reader.nextString(); case "identifier" -> legacyIdentifier = reader.nextString();
case "theme" -> themeId = reader.nextString();
case "mapping" -> mappingId = reader.nextString();
case "hids" -> { case "hids" -> {
reader.beginArray(); reader.beginArray();
while (reader.hasNext()) { while (reader.hasNext()) {
@ -89,12 +93,18 @@ public record ControllerType(String friendlyName, String identifier, boolean for
} }
reader.endObject(); reader.endObject();
if (friendlyName == null || identifier == null || hids.isEmpty()) { if (legacyIdentifier != null) {
Controlify.LOGGER.warn("Legacy identifier found in HID DB. Please replace with `theme` and `mapping` (if needed).");
themeId = legacyIdentifier;
mappingId = legacyIdentifier;
}
if (friendlyName == null || themeId == null || hids.isEmpty()) {
Controlify.LOGGER.warn("Invalid entry in HID DB. Skipping..."); Controlify.LOGGER.warn("Invalid entry in HID DB. Skipping...");
continue; continue;
} }
var type = new ControllerType(friendlyName, identifier, forceJoystick, dontLoad); var type = new ControllerType(friendlyName, mappingId, themeId, forceJoystick, dontLoad);
for (var hid : hids) { for (var hid : hids) {
typeMap.put(hid, type); typeMap.put(hid, type);
} }

View File

@ -129,7 +129,6 @@ public class GamepadController extends AbstractController<GamepadState, GamepadC
public void open() { public void open() {
if (SDL2NativesManager.isLoaded()) { if (SDL2NativesManager.isLoaded()) {
this.gamepadPtr = SDL.SDL_GameControllerOpen(joystickId); this.gamepadPtr = SDL.SDL_GameControllerOpen(joystickId);
Controlify.LOGGER.info(SDL.SDL_GetError());
this.rumbleSupported = SDL.SDL_GameControllerHasRumble(gamepadPtr); this.rumbleSupported = SDL.SDL_GameControllerHasRumble(gamepadPtr);
this.triggerRumbleSupported = SDL.SDL_GameControllerHasRumble(gamepadPtr); this.triggerRumbleSupported = SDL.SDL_GameControllerHasRumble(gamepadPtr);
if (this.hasGyro = SDL.SDL_GameControllerHasSensor(gamepadPtr, SDL.SDL_SENSOR_GYRO)) { if (this.hasGyro = SDL.SDL_GameControllerHasSensor(gamepadPtr, SDL.SDL_SENSOR_GYRO)) {

View File

@ -9,7 +9,7 @@ import java.util.Optional;
public record CompoundJoystickInfo(Collection<String> joystickUids, String friendlyName) { public record CompoundJoystickInfo(Collection<String> joystickUids, String friendlyName) {
public ControllerType type() { public ControllerType type() {
return new ControllerType(friendlyName, createUID(joystickUids), true, false); return new ControllerType(friendlyName, createUID(joystickUids), "generic", true, false);
} }
public boolean canBeUsed() { public boolean canBeUsed() {
@ -37,7 +37,7 @@ public record CompoundJoystickInfo(Collection<String> joystickUids, String frien
.toList(); .toList();
ControllerType type = type(); 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) { 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.bindings.JoystickAxisBind;
import dev.isxander.controlify.controller.joystick.JoystickState; import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.render.JoystickRenderer;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
public interface JoystickMapping { public interface JoystickMapping {
@ -23,6 +24,8 @@ public interface JoystickMapping {
float restingValue(); float restingValue();
String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction); String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction);
JoystickRenderer renderer();
} }
interface Button { interface Button {
@ -31,6 +34,8 @@ public interface JoystickMapping {
Component name(); Component name();
boolean isPressed(JoystickData data); boolean isPressed(JoystickData data);
JoystickRenderer renderer();
} }
interface Hat { interface Hat {
@ -39,6 +44,8 @@ public interface JoystickMapping {
String identifier(); String identifier();
Component name(); Component name();
JoystickRenderer renderer(JoystickState.HatState state);
} }
record JoystickData(float[] axes, boolean[] buttons, JoystickState.HatState[] hats) { 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.ControllerType;
import dev.isxander.controlify.controller.joystick.JoystickController; import dev.isxander.controlify.controller.joystick.JoystickController;
import dev.isxander.controlify.controller.joystick.JoystickState; import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.render.JoystickRenderer;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@ -141,7 +142,7 @@ public class RPJoystickMapping implements JoystickMapping {
reader.endObject(); reader.endObject();
for (var id : ids) { 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(); reader.endArray();
@ -171,7 +172,7 @@ public class RPJoystickMapping implements JoystickMapping {
} }
reader.endObject(); reader.endObject();
buttons.add(new ButtonMapping(id, btnName, type.identifier())); buttons.add(new ButtonMapping(id, btnName, type.mappingId()));
} }
reader.endArray(); reader.endArray();
@ -231,7 +232,7 @@ public class RPJoystickMapping implements JoystickMapping {
} }
reader.endObject(); reader.endObject();
hats.add(new HatMapping(id, hatName, type.identifier(), axis)); hats.add(new HatMapping(id, hatName, type.mappingId(), axis));
} }
reader.endArray(); reader.endArray();
@ -254,21 +255,21 @@ public class RPJoystickMapping implements JoystickMapping {
} }
public static JoystickMapping fromType(JoystickController<?> joystick) { 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()) { 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()); return new UnmappedJoystickMapping(joystick.joystickId());
} }
try (var reader = JsonReader.json5(resource.get().openAsReader())) { try (var reader = JsonReader.json5(resource.get().openAsReader())) {
return new RPJoystickMapping(reader, joystick.type()); return new RPJoystickMapping(reader, joystick.type());
} catch (Exception e) { } 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()); 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 @Override
public float getAxis(JoystickData data) { public float getAxis(JoystickData data) {
float rawAxis = data.axes()[id]; float rawAxis = data.axes()[id];
@ -286,13 +287,18 @@ public class RPJoystickMapping implements JoystickMapping {
@Override @Override
public Component name() { public Component name() {
return Component.translatable("controlify.joystick_mapping." + typeId() + ".axis." + identifier()); return Component.translatable("controlify.joystick_mapping." + theme() + ".axis." + identifier());
} }
@Override @Override
public String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction) { public String getDirectionIdentifier(int axis, JoystickAxisBind.AxisDirection direction) {
return this.axisNames()[direction.ordinal()]; return this.axisNames()[direction.ordinal()];
} }
@Override
public JoystickRenderer renderer() {
return null;
}
} }
private record ButtonMapping(int id, String identifier, String typeId) implements Button { private record ButtonMapping(int id, String identifier, String typeId) implements Button {
@ -305,6 +311,11 @@ public class RPJoystickMapping implements JoystickMapping {
public Component name() { public Component name() {
return Component.translatable("controlify.joystick_mapping." + typeId() + ".button." + identifier()); 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 { 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()); 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) { private record EmulatedAxis(int axisId, Map<Float, JoystickState.HatState> states) {
} }
} }

View File

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

View File

@ -1,6 +1,7 @@
package dev.isxander.controlify.controller.sdl2; package dev.isxander.controlify.controller.sdl2;
import dev.isxander.controlify.Controlify; import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.utils.DebugLog;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.Util; import net.minecraft.Util;
import org.libsdl.SDL; import org.libsdl.SDL;
@ -31,7 +32,7 @@ public class SDL2NativesManager {
public static void initialise() { public static void initialise() {
if (loaded) return; if (loaded) return;
Controlify.LOGGER.info("Initialising SDL2 native library"); DebugLog.log("Initialising SDL2 native library");
if (!Target.CURRENT.hasNativeLibrary()) { if (!Target.CURRENT.hasNativeLibrary()) {
Controlify.LOGGER.warn("SDL2 native library not available for OS: " + Target.CURRENT); Controlify.LOGGER.warn("SDL2 native library not available for OS: " + Target.CURRENT);
@ -77,7 +78,7 @@ public class SDL2NativesManager {
throw new RuntimeException("Failed to initialise SDL2: " + SDL.SDL_GetError()); throw new RuntimeException("Failed to initialise SDL2: " + SDL.SDL_GetError());
} }
Controlify.LOGGER.info("Initialised SDL2"); DebugLog.log("Initialised SDL2");
} }
private static boolean downloadLibrary(Path path) { private static boolean downloadLibrary(Path path) {

View File

@ -1,19 +1,49 @@
package dev.isxander.controlify.debug; package dev.isxander.controlify.debug;
import dev.isxander.controlify.Controlify;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import java.util.ArrayList;
import java.util.List;
public class DebugProperties { public class DebugProperties {
private static final List<DebugProperty> properties = new ArrayList<>();
public static final boolean DEBUG_LOGGING = boolProp("controlify.debug.logging", false, true);
/* Renders debug overlay for vmouse snapping */ /* Renders debug overlay for vmouse snapping */
public static final boolean DEBUG_SNAPPING = boolProp("controlify.debug.snapping", false, false); public static final boolean DEBUG_SNAPPING = boolProp("controlify.debug.snapping", false, false);
/* Forces all gamepads to be treated as a regular joystick */ /* Forces all gamepads to be treated as a regular joystick */
public static final boolean FORCE_JOYSTICK = boolProp("controlify.debug.force_joystick", false, false); public static final boolean FORCE_JOYSTICK = boolProp("controlify.debug.force_joystick", false, false);
/* Prints joystick input counts for making joystick mappings */ /* Prints joystick input counts for making joystick mappings */
public static final boolean PRINT_JOY_INPUT_COUNT = boolProp("controlify.debug.print_joy_input_count", false, true); public static final boolean PRINT_JOY_INPUT_COUNT = boolProp("controlify.debug.print_joy_input_count", false, false);
/* Print gyro data if supported */ /* Print gyro data if supported */
public static final boolean PRINT_GYRO = boolProp("controlify.debug.print_gyro", false, false); public static final boolean PRINT_GYRO = boolProp("controlify.debug.print_gyro", false, false);
public static void printProperties() {
if (properties.stream().noneMatch(DebugProperty::enabled))
return;
String header = "*----------------- Controlify Debug Properties -----------------*";
Controlify.LOGGER.error(header);
int maxWidth = properties.stream().mapToInt(prop -> prop.name().length()).max().orElse(0);
for (var prop : properties) {
String line = "| %s%s = %s".formatted(prop.name(), " ".repeat(maxWidth - prop.name().length()), prop.enabled());
line += " ".repeat(header.length() - line.length() - 1) + "|";
Controlify.LOGGER.error(line);
}
Controlify.LOGGER.error("*---------------------------------------------------------------*");
}
private static boolean boolProp(String name, boolean defProd, boolean defDev) { private static boolean boolProp(String name, boolean defProd, boolean defDev) {
boolean def = FabricLoader.getInstance().isDevelopmentEnvironment() ? defDev : defProd; boolean def = FabricLoader.getInstance().isDevelopmentEnvironment() ? defDev : defProd;
return Boolean.parseBoolean(System.getProperty(name, Boolean.toString(def))); boolean enabled = Boolean.parseBoolean(System.getProperty(name, Boolean.toString(def)));
properties.add(new DebugProperty(name, enabled));
return enabled;
}
private record DebugProperty(String name, boolean enabled) {
} }
} }

View File

@ -0,0 +1,12 @@
package dev.isxander.controlify.utils;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.debug.DebugProperties;
public class DebugLog {
public static void log(String message, Object... args) {
if (DebugProperties.DEBUG_LOGGING) {
Controlify.LOGGER.info(message, args);
}
}
}

View File

@ -1,7 +1,7 @@
[ [
{ {
"name": "Xbox One Controller", "name": "Xbox One Controller",
"identifier": "xbox_one", "theme": "xbox_one",
"hids": [ "hids": [
[0x45e, 0x2ff], [0x45e, 0x2ff],
@ -21,7 +21,7 @@
}, },
{ {
"name": "Dualshock 4 Controller", "name": "Dualshock 4 Controller",
"identifier": "dualshock4", "theme": "dualshock4",
"hids": [ "hids": [
[0x54c, 0x5c4], [0x54c, 0x5c4],
@ -31,7 +31,7 @@
}, },
{ {
"name": "Steam Deck", "name": "Steam Deck",
"identifier": "steam_deck", "theme": "xbox_one",
"hids": [ "hids": [
[0x28de, 0x1205], [0x28de, 0x1205],
@ -39,10 +39,19 @@
}, },
{ {
"name": "Stadia Controller", "name": "Stadia Controller",
"identifier": "stadia", "theme": "stadia",
"hids": [ "hids": [
[0x18d1, 0x9400], [0x18d1, 0x9400],
] ]
},
{
"name": "Thrustmaster T16000M",
"theme": "thrustmaster",
"mapping": "tm_t16000m",
"hids": [
[0x044f, 0xb10a]
]
} }
] ]

View File

@ -202,40 +202,6 @@
"controlify.guide.interact": "Interact", "controlify.guide.interact": "Interact",
"controlify.guide.pick_block": "Pick Block", "controlify.guide.pick_block": "Pick Block",
"controlify.joystick_mapping.unmapped.axis": "Axis #%s",
"controlify.joystick_mapping.unmapped.button": "Button #%s",
"controlify.joystick_mapping.unmapped.hat": "Hat #%s",
"controlify.joystick_mapping.unmapped.axis_direction.negative": "(Negative)",
"controlify.joystick_mapping.unmapped.axis_direction.positive": "(Positive)",
"controlify.joystick_mapping.xbox_one.axis.left_stick": "Left Stick",
"controlify.joystick_mapping.xbox_one.axis.left_stick.left": "Left",
"controlify.joystick_mapping.xbox_one.axis.left_stick.right": "Right",
"controlify.joystick_mapping.xbox_one.axis.left_stick.up": "Up",
"controlify.joystick_mapping.xbox_one.axis.left_stick.down": "Down",
"controlify.joystick_mapping.xbox_one.axis.right_stick": "Right Stick",
"controlify.joystick_mapping.xbox_one.axis.right_stick.left": "Left",
"controlify.joystick_mapping.xbox_one.axis.right_stick.right": "Right",
"controlify.joystick_mapping.xbox_one.axis.right_stick.up": "Up",
"controlify.joystick_mapping.xbox_one.axis.right_stick.down": "Down",
"controlify.joystick_mapping.xbox_one.axis.left_trigger": "Left Trigger",
"controlify.joystick_mapping.xbox_one.axis.left_trigger.up": "Up",
"controlify.joystick_mapping.xbox_one.axis.left_trigger.down": "Down",
"controlify.joystick_mapping.xbox_one.axis.right_trigger": "Right Trigger",
"controlify.joystick_mapping.xbox_one.axis.right_trigger.up": "Up",
"controlify.joystick_mapping.xbox_one.axis.right_trigger.down": "Down",
"controlify.joystick_mapping.xbox_one.button.a": "A",
"controlify.joystick_mapping.xbox_one.button.b": "B",
"controlify.joystick_mapping.xbox_one.button.x": "X",
"controlify.joystick_mapping.xbox_one.button.y": "Y",
"controlify.joystick_mapping.xbox_one.button.left_bumper": "Left Bumper",
"controlify.joystick_mapping.xbox_one.button.right_bumper": "Right Bumper",
"controlify.joystick_mapping.xbox_one.button.left_stick": "Left Stick Press",
"controlify.joystick_mapping.xbox_one.button.right_stick": "Right Stick Press",
"controlify.joystick_mapping.xbox_one.button.back": "Back",
"controlify.joystick_mapping.xbox_one.button.start": "Start",
"controlify.joystick_mapping.xbox_one.button.guide": "Guide",
"controlify.joystick_mapping.xbox_one.hat.dpad": "D-Pad",
"controlify.calibration.title": "Controller Calibration for '%s'", "controlify.calibration.title": "Controller Calibration for '%s'",
"controlify.calibration.info": "This process will optimize settings for your controller to prevent stick drift. Stick drift happens in your controller thumbsticks and outputs slightly wrong values when you aren't touching them at all. Deadzones are used to prevent this.\n\nThis will only take a few seconds.", "controlify.calibration.info": "This process will optimize settings for your controller to prevent stick drift. Stick drift happens in your controller thumbsticks and outputs slightly wrong values when you aren't touching them at all. Deadzones are used to prevent this.\n\nThis will only take a few seconds.",
"controlify.calibration.wait": "Please do not touch your controller thumbsticks until the progress bar is complete. This process will only take a few seconds.", "controlify.calibration.wait": "Please do not touch your controller thumbsticks until the progress bar is complete. This process will only take a few seconds.",
@ -255,5 +221,33 @@
"controlify.hat_state.up": "Up", "controlify.hat_state.up": "Up",
"controlify.hat_state.down": "Down", "controlify.hat_state.down": "Down",
"controlify.hat_state.left": "Left", "controlify.hat_state.left": "Left",
"controlify.hat_state.right": "Right" "controlify.hat_state.right": "Right",
"controlify.joystick_mapping.unmapped.axis": "Axis #%s",
"controlify.joystick_mapping.unmapped.button": "Button #%s",
"controlify.joystick_mapping.unmapped.hat": "Hat #%s",
"controlify.joystick_mapping.unmapped.axis_direction.negative": "(Negative)",
"controlify.joystick_mapping.unmapped.axis_direction.positive": "(Positive)",
"controlify.joystick_mapping.tm_t16000.axis.roll": "Roll",
"controlify.joystick_mapping.tm_t16000.axis.pitch": "Pitch",
"controlify.joystick_mapping.tm_t16000.axis.yaw": "Yaw",
"controlify.joystick_mapping.tm_t16000.axis.throttle": "Throttle",
"controlify.joystick_mapping.tm_t16000.button.trigger": "Trigger",
"controlify.joystick_mapping.tm_t16000.button.a": "A",
"controlify.joystick_mapping.tm_t16000.button.x": "X",
"controlify.joystick_mapping.tm_t16000.button.b": "B",
"controlify.joystick_mapping.tm_t16000.left_1": "Left 1",
"controlify.joystick_mapping.tm_t16000.left_2": "Left 2",
"controlify.joystick_mapping.tm_t16000.left_3": "Left 3",
"controlify.joystick_mapping.tm_t16000.left_4": "Left 4",
"controlify.joystick_mapping.tm_t16000.left_5": "Left 5",
"controlify.joystick_mapping.tm_t16000.left_6": "Left 6",
"controlify.joystick_mapping.tm_t16000.right_1": "Right 1",
"controlify.joystick_mapping.tm_t16000.right_2": "Right 2",
"controlify.joystick_mapping.tm_t16000.right_3": "Right 3",
"controlify.joystick_mapping.tm_t16000.right_4": "Right 4",
"controlify.joystick_mapping.tm_t16000.right_5": "Right 5",
"controlify.joystick_mapping.tm_t16000.right_6": "Right 6",
"controlify.joystick_mapping.tm_t16000.hat": "Hat"
} }

View File

@ -1,176 +0,0 @@
{
"axes": [
{
"ids": [0, 1],
"identifier": "ps4_left_stick",
"deadzone": true,
"rest": 0.0,
"axis_names": [
["right", "left"],
["down", "up"]
]
},
{
"ids": [2, 5],
"identifier": "ps4_right_stick",
"deadzone": true,
"axis_names": [
["right", "left"],
["down", "up"]
],
"rest": 0.0
},
{
"ids": [3],
"identifier": "ps4_left_trigger",
"rest": 0.0,
"deadzone": false,
"range": [0.0, 1.0],
"axis_names": [
["down", "up"]
]
},
{
"ids": [4],
"identifier": "ps4_right_trigger",
"rest": 0.0,
"deadzone": false,
"range": [0.0, 1.0],
"axis_names": [
["down", "up"]
]
},
{
"ids": [6, 7],
"identifier": "xbox_left_stick",
"deadzone": true,
"rest": 0.0,
"axis_names": [
["right", "left"],
["down", "up"]
]
},
{
"ids": [8, 9],
"identifier": "xbox_right_stick",
"deadzone": true,
"axis_names": [
["right", "left"],
["down", "up"]
],
"rest": 0.0
},
{
"ids": [10],
"identifier": "xbox_left_trigger",
"deadzone": false,
"rest": 0.0,
"range": [0.0, 1.0],
"axis_names": [
["down", "up"]
]
},
{
"ids": [11],
"identifier": "xbox_right_trigger",
"deadzone": false,
"rest": 0.0,
"range": [0.0, 1.0],
"axis_names": [
["down", "up"]
]
}
],
"buttons": [
{
"button": 0,
"name": "a"
},
{
"button": 1,
"name": "b"
},
{
"button": 2,
"name": "x"
},
{
"button": 3,
"name": "y"
},
{
"button": 4,
"name": "left_bumper"
},
{
"button": 5,
"name": "right_bumper"
},
{
"button": 6,
"name": "back"
},
{
"button": 7,
"name": "start"
},
{
"button": 8,
"name": "left_stick"
},
{
"button": 9,
"name": "right_stick"
},
{
"button": 10,
"name": "a1"
},
{
"button": 11,
"name": "b1"
},
{
"button": 12,
"name": "x1"
},
{
"button": 13,
"name": "y1"
},
{
"button": 14,
"name": "left_bumper1"
},
{
"button": 15,
"name": "right_bumper1"
},
{
"button": 16,
"name": "back1"
},
{
"button": 17,
"name": "start1"
},
{
"button": 18,
"name": "left_stick1"
},
{
"button": 19,
"name": "right_stick1"
}
],
"hats": [
{
"hat": 0,
"name": "dpad_xbox"
},
{
"hat": 1,
"name": "dpad_ps4"
}
]
}

View File

@ -0,0 +1,113 @@
{
"axes": [
{
"ids": [0],
"identifier": "roll",
"deadzone": true,
"rest": 0.0,
"axis_names": [
["right", "left"]
]
},
{
"ids": [1],
"identifier": "pitch",
"deadzone": true,
"rest": 0.0,
"axis_names": [
["down", "up"]
]
},
{
"ids": [2],
"identifier": "yaw",
"deadzone": true,
"rest": 0.0,
"axis_names": [
["right", "left"]
]
},
{
"ids": [3],
"identifier": "throttle",
"rest": 0.0,
"deadzone": false,
"range": [0.0, 1.0],
"axis_names": [
["down", "up"]
]
}
],
"buttons": [
{
"button": 0,
"name": "trigger"
},
{
"button": 1,
"name": "a"
},
{
"button": 2,
"name": "x"
},
{
"button": 3,
"name": "b"
},
{
"button": 4,
"name": "left_1"
},
{
"button": 5,
"name": "left_2"
},
{
"button": 6,
"name": "left_3"
},
{
"button": 7,
"name": "left_4"
},
{
"button": 8,
"name": "left_5"
},
{
"button": 9,
"name": "left_6"
},
{
"button": 10,
"name": "right_1"
},
{
"button": 11,
"name": "right_2"
},
{
"button": 12,
"name": "right_3"
},
{
"button": 13,
"name": "right_4"
},
{
"button": 14,
"name": "right_5"
},
{
"button": 15,
"name": "right_6"
}
],
"hats": [
{
"name": "hat",
"hat": 0
}
]
}