-
-
Notifications
You must be signed in to change notification settings - Fork 75
Expand file tree
/
Copy pathgenerate_gamepad_mappings.py
More file actions
83 lines (68 loc) · 3.12 KB
/
Copy pathgenerate_gamepad_mappings.py
File metadata and controls
83 lines (68 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/env python3
"""Generate engine/platform/glfw/GamepadMappings.h from SDL_GameControllerDB.
GLFW's built-in gamepad database is frozen at release time, so controllers
released (or added to the community database) after that report as plain
joysticks and glfwGetGamepadState() fails for them. The generated header
embeds the community database so Doriax can apply it with
glfwUpdateGamepadMappings() right after glfwInit().
Usage:
curl -O https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/master/gamecontrollerdb.txt
python3 generate_gamepad_mappings.py gamecontrollerdb.txt engine/platform/glfw/GamepadMappings.h
Only Windows, Mac OS X and Linux entries are kept: the GLFW backend is only
used on desktop (Android/iOS/web have their own input paths). The header
stores one C string per mapping line because MSVC caps a single string
literal at 64 KB.
"""
import sys
from datetime import date
DESKTOP_PLATFORMS = ("platform:Windows", "platform:Mac OS X", "platform:Linux")
def escape_c(line: str) -> str:
out = []
for ch in line:
if ch == "\\":
out.append("\\\\")
elif ch == '"':
out.append('\\"')
elif 0x20 <= ord(ch) <= 0x7E:
out.append(ch)
else:
# Octal escapes stop at 3 digits, unlike \x which greedily eats
# any following hex characters.
out.append("".join("\\%03o" % b for b in ch.encode("utf-8")))
return "".join(out)
def main() -> int:
if len(sys.argv) != 3:
print(__doc__, file=sys.stderr)
return 1
db_path, header_path = sys.argv[1], sys.argv[2]
mappings = []
with open(db_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
if any(p in line for p in DESKTOP_PLATFORMS):
mappings.append(line)
with open(header_path, "w", encoding="utf-8", newline="\n") as f:
f.write("// This file is auto-generated by generate_gamepad_mappings.py. Do not edit manually.\n")
f.write("//\n")
f.write("// Community gamepad mappings from SDL_GameControllerDB\n")
f.write("// (https://github.com/mdqinc/SDL_GameControllerDB), desktop platforms only.\n")
f.write("// Generated on %s. Apply after glfwInit() with:\n" % date.today().isoformat())
f.write("// for (size_t i = 0; i < DORIAX_GAMEPAD_MAPPINGS_COUNT; i++)\n")
f.write("// glfwUpdateGamepadMappings(DORIAX_GAMEPAD_MAPPINGS[i]);\n")
f.write("\n")
f.write("#pragma once\n")
f.write("\n")
f.write("#include <stddef.h>\n")
f.write("\n")
f.write("static const char* const DORIAX_GAMEPAD_MAPPINGS[] = {\n")
for m in mappings:
f.write(' "%s",\n' % escape_c(m))
f.write("};\n")
f.write("\n")
f.write("static const size_t DORIAX_GAMEPAD_MAPPINGS_COUNT = sizeof(DORIAX_GAMEPAD_MAPPINGS) / sizeof(DORIAX_GAMEPAD_MAPPINGS[0]);\n")
print("Wrote %d mappings to %s" % (len(mappings), header_path))
return 0
if __name__ == "__main__":
sys.exit(main())