{ config, lib, ... }:
with lib;
let
mappingType = (types.addCheck types.str (val: let
pattern = "[ab][0-9]+|h[0-9]+\.[0-9]+";
in builtins.match pattern val == [])) // {
name = "aI (axis), bI (button) or hI.M (hat) where I=index, M=mask";
};
mkAssignmentOption = example: name: description: mkOption {
type = types.nullOr mappingType;
default = null;
inherit example;
description = "Assignment for ${description}.";
};
mkAxisOption = mkAssignmentOption "a0";
mkButtonOption = mkAssignmentOption "b0";
axes = {
leftx = "left stick X axis";
lefty = "left stick Y axis";
rightx = "right stick X axis";
righty = "right stick Y axis";
lefttrigger = "left trigger";
righttrigger = "right trigger";
};
buttons = {
a = "A button (down)";
b = "B button (right)";
x = "X button (left)";
y = "Y button (up)";
back = "XBox back button";
guide = "XBox guide button";
start = "start button";
leftstick = "pressing the left stick";
rightstick = "pressing the right stick";
leftshoulder = "left shoulder/bumper button";
rightshoulder = "right shoulder/bumper button";
dpup = "directional pad up";
dpdown = "directional pad down";
dpleft = "directional pad left";
dpright = "directional pad right";
};
gcSubModule = { name, ... }: {
options = {
name = mkOption {
type = types.str;
default = name;
description = ''
The name of this controller, doesn't have special meaning and is only
there to make it easier to dinguish various mappings.
'';
};
guid = mkOption {
type = types.uniq types.str;
default = name;
description = ''
The SDL2 GUID to uniquely identify this controller.
Use vuizvui.list-gamecontrollers to list them.
'';
};
mapping = mapAttrs mkAxisOption axes // mapAttrs mkButtonOption buttons;
};
};
mkGCLine = const (cfg: let
validMappings = attrNames axes ++ attrNames buttons;
mkMappingVal = name: let
val = cfg.mapping.${name} or null;
in if val == null then null else "${name}:${val}";
attrs = [ cfg.guid cfg.name "platform:Linux" ]
++ remove null (map mkMappingVal validMappings);
in concatStringsSep "," attrs);
controllers = mapAttrsToList mkGCLine config.vuizvui.hardware.gameController;
controllerConfig = concatStringsSep "\n" controllers;
in {
options.vuizvui.hardware.gameController = mkOption {
type = types.attrsOf (types.submodule gcSubModule);
default = {};
description = let
url =
"https://upload.wikimedia.org/wikipedia/commons/2/2c/360_controller.svg";
in ''
A mapping of the game controllers to use with SDL2 games.
The mapping is always based on the XBox reference controller, so even if
you don't use an XBox controller, you still have to map your keys
according to this layout:
'';
};
config = mkIf (config.vuizvui.hardware.gameController != {}) {
environment.sessionVariables.SDL_GAMECONTROLLERCONFIG = controllerConfig;
};
}