about summary refs log tree commit diff
path: root/modules/hardware/gamecontroller.nix
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2016-01-26 04:09:46 +0100
committeraszlig <aszlig@redmoonstudios.org>2016-01-26 04:09:46 +0100
commit1515bae55bfd6c21d6277883826a88cc12cce7d7 (patch)
tree99a5bc0ad94a58c57a0afa2043f3813ed54bd4c7 /modules/hardware/gamecontroller.nix
parent0353b8b3ffcbaa102d36fa7e8f2bb218a1374820 (diff)
modules: Add a new gamecontroller module
This module is for declaratively specifying SDL_GAMECONTROLLERCONFIG, an
environment variable used by SDL 2 to map arbitrary controllers to that
of an XBox reference controller.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Diffstat (limited to 'modules/hardware/gamecontroller.nix')
-rw-r--r--modules/hardware/gamecontroller.nix109
1 files changed, 109 insertions, 0 deletions
diff --git a/modules/hardware/gamecontroller.nix b/modules/hardware/gamecontroller.nix
new file mode 100644
index 00000000..5cfe9d16
--- /dev/null
+++ b/modules/hardware/gamecontroller.nix
@@ -0,0 +1,109 @@
+{ 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 <literal>back</literal> button";
+    guide = "XBox <literal>guide</literal> button";
+    start = "<literal>start</literal> 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 <literal>vuizvui.list-gamecontrollers</literal> 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:
+
+      <link xlink:href="${
+        "https://upload.wikimedia.org/wikipedia/commons/2/2c/360_controller.svg"
+      }"/>
+    '';
+  };
+
+  config = mkIf (config.vuizvui.hardware.gameController != {}) {
+    environment.sessionVariables.SDL_GAMECONTROLLERCONFIG = controllerConfig;
+  };
+}