@the-inclusionist/engine 9.0.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (532) hide show
  1. package/README.md +120 -78
  2. package/app/css/style.css +761 -377
  3. package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
  4. package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
  5. package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
  6. package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
  7. package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
  8. package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
  9. package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
  10. package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
  11. package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
  12. package/app/public/vendor/fonts.css +36 -84
  13. package/dist-pkg/boot/create-game.d.ts +499 -219
  14. package/dist-pkg/boot/create-game.js +3944 -562
  15. package/dist-pkg/core/a11y-sr.d.ts +25 -3
  16. package/dist-pkg/core/a11y-sr.js +38 -19
  17. package/dist-pkg/core/accessible-label.d.ts +17 -0
  18. package/dist-pkg/core/accessible-label.js +37 -0
  19. package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
  20. package/dist-pkg/core/accommodation-subjects.js +32 -0
  21. package/dist-pkg/core/accommodations.d.ts +125 -0
  22. package/dist-pkg/core/accommodations.js +195 -0
  23. package/dist-pkg/core/actions.d.ts +108 -55
  24. package/dist-pkg/core/actions.js +122 -71
  25. package/dist-pkg/core/calm-mode.d.ts +31 -0
  26. package/dist-pkg/core/calm-mode.js +47 -0
  27. package/dist-pkg/core/camera-cycle.d.ts +15 -0
  28. package/dist-pkg/core/camera-cycle.js +7 -0
  29. package/dist-pkg/core/caption-duration.d.ts +15 -0
  30. package/dist-pkg/core/caption-duration.js +19 -0
  31. package/dist-pkg/core/cartridge-problems.d.ts +34 -0
  32. package/dist-pkg/core/cartridge-problems.js +53 -0
  33. package/dist-pkg/core/constants.d.ts +0 -54
  34. package/dist-pkg/core/constants.js +9 -76
  35. package/dist-pkg/core/contract.d.ts +142 -164
  36. package/dist-pkg/core/contract.js +222 -208
  37. package/dist-pkg/core/dom-query.d.ts +4 -4
  38. package/dist-pkg/core/dom-query.js +12 -20
  39. package/dist-pkg/core/entity.d.ts +62 -77
  40. package/dist-pkg/core/entity.js +18 -32
  41. package/dist-pkg/core/escape-html.d.ts +9 -10
  42. package/dist-pkg/core/escape-html.js +16 -20
  43. package/dist-pkg/core/flash-threshold.d.ts +17 -0
  44. package/dist-pkg/core/flash-threshold.js +113 -0
  45. package/dist-pkg/core/game-speed.d.ts +11 -0
  46. package/dist-pkg/core/game-speed.js +16 -0
  47. package/dist-pkg/core/genres.d.ts +20 -0
  48. package/dist-pkg/core/genres.js +44 -0
  49. package/dist-pkg/core/i18n.d.ts +71 -60
  50. package/dist-pkg/core/i18n.js +186 -200
  51. package/dist-pkg/core/loop.d.ts +17 -6
  52. package/dist-pkg/core/loop.js +26 -26
  53. package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
  54. package/dist-pkg/core/pause-icon-catalogue.js +54 -0
  55. package/dist-pkg/core/ring.d.ts +17 -0
  56. package/dist-pkg/core/ring.js +29 -0
  57. package/dist-pkg/core/rng.d.ts +7 -12
  58. package/dist-pkg/core/rng.js +23 -53
  59. package/dist-pkg/core/route.d.ts +26 -26
  60. package/dist-pkg/core/route.js +126 -121
  61. package/dist-pkg/core/scenes.d.ts +37 -40
  62. package/dist-pkg/core/scenes.js +41 -43
  63. package/dist-pkg/core/screens.d.ts +4 -4
  64. package/dist-pkg/core/screens.js +11 -16
  65. package/dist-pkg/core/session-clock.d.ts +23 -0
  66. package/dist-pkg/core/session-clock.js +37 -0
  67. package/dist-pkg/core/setting-defaults.d.ts +61 -0
  68. package/dist-pkg/core/setting-defaults.js +66 -0
  69. package/dist-pkg/core/speech-rate.d.ts +29 -0
  70. package/dist-pkg/core/speech-rate.js +47 -0
  71. package/dist-pkg/core/state.d.ts +118 -118
  72. package/dist-pkg/core/state.js +322 -297
  73. package/dist-pkg/core/visual-cycles.d.ts +30 -0
  74. package/dist-pkg/core/visual-cycles.js +52 -0
  75. package/dist-pkg/core/visual-state.d.ts +13 -0
  76. package/dist-pkg/core/visual-state.js +6 -0
  77. package/dist-pkg/educational/activities-registry.d.ts +1 -1
  78. package/dist-pkg/educational/activities-registry.js +9 -8
  79. package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
  80. package/dist-pkg/educational/adaptive-engine.js +17 -17
  81. package/dist-pkg/educational/segment-bar.d.ts +12 -12
  82. package/dist-pkg/educational/segment-bar.js +9 -9
  83. package/dist-pkg/i18n/en.js +324 -223
  84. package/dist-pkg/i18n/es.js +323 -223
  85. package/dist-pkg/i18n/pt.js +348 -226
  86. package/dist-pkg/input/default-bindings.d.ts +37 -38
  87. package/dist-pkg/input/default-bindings.js +127 -144
  88. package/dist-pkg/input/devices.d.ts +7 -7
  89. package/dist-pkg/input/devices.js +17 -16
  90. package/dist-pkg/input/edges.d.ts +23 -32
  91. package/dist-pkg/input/edges.js +23 -28
  92. package/dist-pkg/input/empathy-filter.d.ts +22 -0
  93. package/dist-pkg/input/empathy-filter.js +34 -0
  94. package/dist-pkg/input/face-map.d.ts +96 -0
  95. package/dist-pkg/input/face-map.js +255 -0
  96. package/dist-pkg/input/face-signals.d.ts +40 -0
  97. package/dist-pkg/input/face-signals.js +48 -0
  98. package/dist-pkg/input/gamepad.d.ts +195 -145
  99. package/dist-pkg/input/gamepad.js +383 -556
  100. package/dist-pkg/input/gaze-cycle.d.ts +64 -0
  101. package/dist-pkg/input/gaze-cycle.js +133 -0
  102. package/dist-pkg/input/gaze-relative.d.ts +68 -0
  103. package/dist-pkg/input/gaze-relative.js +142 -0
  104. package/dist-pkg/input/hand-map.d.ts +28 -0
  105. package/dist-pkg/input/hand-map.js +142 -0
  106. package/dist-pkg/input/input-cooldown.d.ts +17 -0
  107. package/dist-pkg/input/input-cooldown.js +39 -0
  108. package/dist-pkg/input/key-default.d.ts +30 -0
  109. package/dist-pkg/input/key-default.js +60 -0
  110. package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
  111. package/dist-pkg/input/keyboard-runtime.js +23 -27
  112. package/dist-pkg/input/keyboard.d.ts +68 -63
  113. package/dist-pkg/input/keyboard.js +83 -105
  114. package/dist-pkg/input/keydown.d.ts +123 -137
  115. package/dist-pkg/input/keydown.js +284 -289
  116. package/dist-pkg/input/latch-edge.d.ts +33 -21
  117. package/dist-pkg/input/latch-edge.js +34 -35
  118. package/dist-pkg/input/latch-scope.d.ts +51 -50
  119. package/dist-pkg/input/latch-scope.js +61 -82
  120. package/dist-pkg/input/latch-store.d.ts +26 -30
  121. package/dist-pkg/input/latch-store.js +42 -50
  122. package/dist-pkg/input/latch-sync.d.ts +29 -29
  123. package/dist-pkg/input/latch-sync.js +25 -25
  124. package/dist-pkg/input/latch.d.ts +14 -17
  125. package/dist-pkg/input/latch.js +29 -37
  126. package/dist-pkg/input/pad-defaults.d.ts +13 -16
  127. package/dist-pkg/input/pad-defaults.js +21 -28
  128. package/dist-pkg/input/pad-reading.d.ts +76 -0
  129. package/dist-pkg/input/pad-reading.js +169 -0
  130. package/dist-pkg/input/pad-wizard.d.ts +99 -0
  131. package/dist-pkg/input/pad-wizard.js +256 -0
  132. package/dist-pkg/input/pointer-space.d.ts +19 -20
  133. package/dist-pkg/input/pointer-space.js +27 -32
  134. package/dist-pkg/input/pointer.d.ts +39 -40
  135. package/dist-pkg/input/pointer.js +42 -45
  136. package/dist-pkg/input/state.d.ts +101 -89
  137. package/dist-pkg/input/state.js +54 -134
  138. package/dist-pkg/input/switch-scan.d.ts +59 -0
  139. package/dist-pkg/input/switch-scan.js +67 -0
  140. package/dist-pkg/input/synthetic-source.d.ts +42 -0
  141. package/dist-pkg/input/synthetic-source.js +57 -0
  142. package/dist-pkg/input/touch-bindings.d.ts +127 -116
  143. package/dist-pkg/input/touch-bindings.js +158 -173
  144. package/dist-pkg/input/touch.d.ts +147 -72
  145. package/dist-pkg/input/touch.js +362 -126
  146. package/dist-pkg/input/transport-in-use.d.ts +107 -0
  147. package/dist-pkg/input/transport-in-use.js +130 -0
  148. package/dist-pkg/input/transports.d.ts +90 -117
  149. package/dist-pkg/input/transports.js +104 -106
  150. package/dist-pkg/input/virtual-controller.d.ts +82 -0
  151. package/dist-pkg/input/virtual-controller.js +69 -0
  152. package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
  153. package/dist-pkg/input/vocabulary-migration.js +80 -79
  154. package/dist-pkg/input/voice-map.d.ts +59 -0
  155. package/dist-pkg/input/voice-map.js +123 -0
  156. package/dist-pkg/platform/audio-ambient.d.ts +13 -2
  157. package/dist-pkg/platform/audio-ambient.js +14 -14
  158. package/dist-pkg/platform/audio-earcons.d.ts +20 -19
  159. package/dist-pkg/platform/audio-earcons.js +51 -42
  160. package/dist-pkg/platform/audio-jingles.js +9 -10
  161. package/dist-pkg/platform/audio-mixer.d.ts +14 -2
  162. package/dist-pkg/platform/audio-mixer.js +31 -39
  163. package/dist-pkg/platform/audio-sonar.d.ts +49 -152
  164. package/dist-pkg/platform/audio-sonar.js +124 -302
  165. package/dist-pkg/platform/audio.d.ts +62 -19
  166. package/dist-pkg/platform/audio.js +193 -168
  167. package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
  168. package/dist-pkg/platform/choose-by-voice.js +157 -0
  169. package/dist-pkg/platform/flash-sampler.d.ts +19 -0
  170. package/dist-pkg/platform/flash-sampler.js +79 -0
  171. package/dist-pkg/platform/font-library.d.ts +77 -0
  172. package/dist-pkg/platform/font-library.js +98 -0
  173. package/dist-pkg/platform/font-library.json +721 -0
  174. package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
  175. package/dist-pkg/platform/heavy-catalogue.js +256 -0
  176. package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
  177. package/dist-pkg/platform/heavy-mirror.js +73 -0
  178. package/dist-pkg/platform/heavy.d.ts +136 -0
  179. package/dist-pkg/platform/heavy.js +324 -0
  180. package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
  181. package/dist-pkg/platform/interruptible-speech.js +77 -54
  182. package/dist-pkg/platform/kokoro-port.d.ts +27 -0
  183. package/dist-pkg/platform/kokoro-port.js +50 -0
  184. package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
  185. package/dist-pkg/platform/kokoro-runtime.js +52 -0
  186. package/dist-pkg/platform/kokoro.d.ts +70 -0
  187. package/dist-pkg/platform/kokoro.js +133 -0
  188. package/dist-pkg/platform/listener-scope.d.ts +12 -0
  189. package/dist-pkg/platform/listener-scope.js +90 -0
  190. package/dist-pkg/platform/locale-host.d.ts +14 -0
  191. package/dist-pkg/platform/locale-host.js +45 -0
  192. package/dist-pkg/platform/microphone.d.ts +51 -0
  193. package/dist-pkg/platform/microphone.js +118 -0
  194. package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
  195. package/dist-pkg/platform/onnx-runtime.js +42 -0
  196. package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
  197. package/dist-pkg/platform/reading-in-worker.js +125 -0
  198. package/dist-pkg/platform/reading-model.d.ts +94 -0
  199. package/dist-pkg/platform/reading-model.js +272 -0
  200. package/dist-pkg/platform/reading-runtime.d.ts +24 -0
  201. package/dist-pkg/platform/reading-runtime.js +164 -0
  202. package/dist-pkg/platform/reading-worker.d.ts +41 -0
  203. package/dist-pkg/platform/reading-worker.js +58 -0
  204. package/dist-pkg/platform/reading.d.ts +80 -0
  205. package/dist-pkg/platform/reading.js +136 -0
  206. package/dist-pkg/platform/speech-recognition.d.ts +60 -0
  207. package/dist-pkg/platform/speech-recognition.js +104 -0
  208. package/dist-pkg/platform/speech.d.ts +23 -1
  209. package/dist-pkg/platform/speech.js +29 -18
  210. package/dist-pkg/platform/storage-keys.d.ts +96 -0
  211. package/dist-pkg/platform/storage-keys.js +106 -0
  212. package/dist-pkg/platform/storage.d.ts +46 -111
  213. package/dist-pkg/platform/storage.js +104 -169
  214. package/dist-pkg/platform/tts.d.ts +85 -39
  215. package/dist-pkg/platform/tts.js +447 -127
  216. package/dist-pkg/platform/vision-loop.d.ts +23 -0
  217. package/dist-pkg/platform/vision-loop.js +56 -0
  218. package/dist-pkg/platform/vision.d.ts +132 -0
  219. package/dist-pkg/platform/vision.js +117 -0
  220. package/dist-pkg/platform/voice-listener.d.ts +40 -0
  221. package/dist-pkg/platform/voice-listener.js +88 -0
  222. package/dist-pkg/platform/voice-plan.d.ts +15 -98
  223. package/dist-pkg/platform/voice-plan.js +56 -143
  224. package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
  225. package/dist-pkg/platform/vosk-runtime.js +151 -0
  226. package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
  227. package/dist-pkg/platform/vosk-vocabulary.js +178 -0
  228. package/dist-pkg/render/canvas.d.ts +13 -7
  229. package/dist-pkg/render/canvas.js +13 -13
  230. package/dist-pkg/render/crt.d.ts +48 -12
  231. package/dist-pkg/render/crt.js +78 -80
  232. package/dist-pkg/render/cvd-matrices.d.ts +22 -18
  233. package/dist-pkg/render/cvd-matrices.js +37 -38
  234. package/dist-pkg/render/hc-role-data.d.ts +7 -7
  235. package/dist-pkg/render/hc-role-data.js +14 -14
  236. package/dist-pkg/render/high-contrast.d.ts +67 -56
  237. package/dist-pkg/render/high-contrast.js +226 -217
  238. package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
  239. package/dist-pkg/render/low-vision-drawing.js +46 -0
  240. package/dist-pkg/render/lq-filter.d.ts +32 -20
  241. package/dist-pkg/render/lq-filter.js +59 -65
  242. package/dist-pkg/render/port.d.ts +86 -88
  243. package/dist-pkg/render/port.js +17 -23
  244. package/dist-pkg/render/screen-pipeline.d.ts +42 -42
  245. package/dist-pkg/render/screen-pipeline.js +80 -87
  246. package/dist-pkg/render/sprite-fx.d.ts +2 -1
  247. package/dist-pkg/render/sprite-fx.js +16 -14
  248. package/dist-pkg/render/viewports.d.ts +20 -15
  249. package/dist-pkg/render/viewports.js +83 -114
  250. package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
  251. package/dist-pkg/render/viz-axes-labels.js +88 -0
  252. package/dist-pkg/render/viz-axes.d.ts +89 -86
  253. package/dist-pkg/render/viz-axes.js +128 -116
  254. package/dist-pkg/render/viz-modes.d.ts +28 -29
  255. package/dist-pkg/render/viz-modes.js +40 -45
  256. package/dist-pkg/render/viz-refusal.d.ts +32 -0
  257. package/dist-pkg/render/viz-refusal.js +57 -0
  258. package/dist-pkg/render/viz-setters.d.ts +104 -66
  259. package/dist-pkg/render/viz-setters.js +182 -191
  260. package/dist-pkg/ui/aac-sets.d.ts +45 -0
  261. package/dist-pkg/ui/aac-sets.js +41 -0
  262. package/dist-pkg/ui/audio-choices.d.ts +68 -0
  263. package/dist-pkg/ui/audio-choices.js +98 -0
  264. package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
  265. package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
  266. package/dist-pkg/ui/camera-control.d.ts +53 -0
  267. package/dist-pkg/ui/camera-control.js +48 -0
  268. package/dist-pkg/ui/changed-mark.d.ts +9 -8
  269. package/dist-pkg/ui/changed-mark.js +22 -53
  270. package/dist-pkg/ui/control-choices.d.ts +37 -0
  271. package/dist-pkg/ui/control-choices.js +84 -0
  272. package/dist-pkg/ui/debug-panel.d.ts +59 -43
  273. package/dist-pkg/ui/debug-panel.js +68 -69
  274. package/dist-pkg/ui/declared-words.d.ts +21 -0
  275. package/dist-pkg/ui/declared-words.js +66 -0
  276. package/dist-pkg/ui/dom.d.ts +10 -14
  277. package/dist-pkg/ui/dom.js +10 -47
  278. package/dist-pkg/ui/drawing-problems.d.ts +25 -0
  279. package/dist-pkg/ui/drawing-problems.js +94 -0
  280. package/dist-pkg/ui/eye-control.d.ts +36 -0
  281. package/dist-pkg/ui/eye-control.js +178 -0
  282. package/dist-pkg/ui/face-control.d.ts +25 -0
  283. package/dist-pkg/ui/face-control.js +183 -0
  284. package/dist-pkg/ui/focus-trap.d.ts +39 -49
  285. package/dist-pkg/ui/focus-trap.js +56 -65
  286. package/dist-pkg/ui/fonts.d.ts +157 -68
  287. package/dist-pkg/ui/fonts.js +305 -115
  288. package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
  289. package/dist-pkg/ui/footer-scroll-driver.js +201 -0
  290. package/dist-pkg/ui/footer-scroll.d.ts +38 -0
  291. package/dist-pkg/ui/footer-scroll.js +55 -0
  292. package/dist-pkg/ui/game-options.d.ts +47 -0
  293. package/dist-pkg/ui/game-options.js +158 -0
  294. package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
  295. package/dist-pkg/ui/gaze-overlay.js +165 -0
  296. package/dist-pkg/ui/hand-control.d.ts +25 -0
  297. package/dist-pkg/ui/hand-control.js +143 -0
  298. package/dist-pkg/ui/help-panel.d.ts +87 -0
  299. package/dist-pkg/ui/help-panel.js +242 -0
  300. package/dist-pkg/ui/hud-bands.d.ts +62 -0
  301. package/dist-pkg/ui/hud-bands.js +146 -0
  302. package/dist-pkg/ui/hud-row.d.ts +34 -0
  303. package/dist-pkg/ui/hud-row.js +80 -0
  304. package/dist-pkg/ui/hud.d.ts +73 -73
  305. package/dist-pkg/ui/hud.js +94 -98
  306. package/dist-pkg/ui/item-announcement.d.ts +13 -12
  307. package/dist-pkg/ui/item-announcement.js +25 -26
  308. package/dist-pkg/ui/layout.d.ts +103 -28
  309. package/dist-pkg/ui/layout.js +117 -99
  310. package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
  311. package/dist-pkg/ui/libras-avatar-clip.js +86 -0
  312. package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
  313. package/dist-pkg/ui/libras-avatar-load.js +134 -0
  314. package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
  315. package/dist-pkg/ui/libras-avatar-plan.js +211 -0
  316. package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
  317. package/dist-pkg/ui/libras-avatar-player.js +226 -0
  318. package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
  319. package/dist-pkg/ui/libras-avatar-stage.js +208 -0
  320. package/dist-pkg/ui/libras-glosses.d.ts +28 -0
  321. package/dist-pkg/ui/libras-glosses.js +161 -0
  322. package/dist-pkg/ui/locale-flags.d.ts +16 -0
  323. package/dist-pkg/ui/locale-flags.js +30 -0
  324. package/dist-pkg/ui/loop-crash.d.ts +17 -17
  325. package/dist-pkg/ui/loop-crash.js +33 -62
  326. package/dist-pkg/ui/menu-intent.d.ts +61 -0
  327. package/dist-pkg/ui/menu-intent.js +88 -0
  328. package/dist-pkg/ui/menu-items.d.ts +20 -0
  329. package/dist-pkg/ui/menu-items.js +51 -0
  330. package/dist-pkg/ui/menu-nav.d.ts +98 -92
  331. package/dist-pkg/ui/menu-nav.js +398 -286
  332. package/dist-pkg/ui/mobility-choices.d.ts +26 -0
  333. package/dist-pkg/ui/mobility-choices.js +41 -0
  334. package/dist-pkg/ui/motion-choices.d.ts +31 -0
  335. package/dist-pkg/ui/motion-choices.js +68 -0
  336. package/dist-pkg/ui/motion-scene.d.ts +24 -19
  337. package/dist-pkg/ui/motion-scene.js +29 -61
  338. package/dist-pkg/ui/mount-panel.d.ts +81 -0
  339. package/dist-pkg/ui/mount-panel.js +61 -0
  340. package/dist-pkg/ui/panel-shell.d.ts +65 -31
  341. package/dist-pkg/ui/panel-shell.js +92 -66
  342. package/dist-pkg/ui/panel-widgets.d.ts +150 -0
  343. package/dist-pkg/ui/panel-widgets.js +294 -0
  344. package/dist-pkg/ui/pause-buttons.d.ts +35 -0
  345. package/dist-pkg/ui/pause-buttons.js +66 -0
  346. package/dist-pkg/ui/pause-icons.d.ts +261 -347
  347. package/dist-pkg/ui/pause-icons.js +671 -601
  348. package/dist-pkg/ui/pause-markup.d.ts +86 -0
  349. package/dist-pkg/ui/pause-markup.js +125 -0
  350. package/dist-pkg/ui/reach-notice.d.ts +22 -23
  351. package/dist-pkg/ui/reach-notice.js +55 -58
  352. package/dist-pkg/ui/scan-overlay.d.ts +23 -0
  353. package/dist-pkg/ui/scan-overlay.js +50 -0
  354. package/dist-pkg/ui/screen-text.d.ts +25 -0
  355. package/dist-pkg/ui/screen-text.js +152 -0
  356. package/dist-pkg/ui/session-clock.d.ts +32 -0
  357. package/dist-pkg/ui/session-clock.js +67 -0
  358. package/dist-pkg/ui/settings-aac.d.ts +70 -0
  359. package/dist-pkg/ui/settings-aac.js +208 -0
  360. package/dist-pkg/ui/settings-audio.d.ts +97 -114
  361. package/dist-pkg/ui/settings-audio.js +493 -425
  362. package/dist-pkg/ui/settings-controls.d.ts +53 -96
  363. package/dist-pkg/ui/settings-controls.js +143 -215
  364. package/dist-pkg/ui/settings-empathy.d.ts +39 -30
  365. package/dist-pkg/ui/settings-empathy.js +53 -60
  366. package/dist-pkg/ui/settings-mobility.d.ts +192 -0
  367. package/dist-pkg/ui/settings-mobility.js +332 -0
  368. package/dist-pkg/ui/settings-motion.d.ts +91 -70
  369. package/dist-pkg/ui/settings-motion.js +287 -198
  370. package/dist-pkg/ui/settings-panel.d.ts +58 -45
  371. package/dist-pkg/ui/settings-panel.js +189 -94
  372. package/dist-pkg/ui/settings-typo.d.ts +29 -78
  373. package/dist-pkg/ui/settings-typo.js +158 -129
  374. package/dist-pkg/ui/settings-visual.d.ts +29 -87
  375. package/dist-pkg/ui/settings-visual.js +240 -193
  376. package/dist-pkg/ui/shell.d.ts +112 -135
  377. package/dist-pkg/ui/shell.js +148 -217
  378. package/dist-pkg/ui/simulation-list.d.ts +27 -0
  379. package/dist-pkg/ui/simulation-list.js +76 -0
  380. package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
  381. package/dist-pkg/ui/simulation-over-the-world.js +131 -0
  382. package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
  383. package/dist-pkg/ui/simulation-refusal.js +8 -56
  384. package/dist-pkg/ui/switchable-control.d.ts +11 -0
  385. package/dist-pkg/ui/switchable-control.js +19 -0
  386. package/dist-pkg/ui/title.d.ts +3 -12
  387. package/dist-pkg/ui/title.js +49 -18
  388. package/dist-pkg/ui/top-band.d.ts +26 -0
  389. package/dist-pkg/ui/top-band.js +96 -0
  390. package/dist-pkg/ui/typo-choices.d.ts +71 -0
  391. package/dist-pkg/ui/typo-choices.js +85 -0
  392. package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
  393. package/dist-pkg/ui/visual-axes-panel.js +12 -94
  394. package/dist-pkg/ui/visual-choices.d.ts +77 -0
  395. package/dist-pkg/ui/visual-choices.js +107 -0
  396. package/dist-pkg/ui/vlibras.d.ts +77 -10
  397. package/dist-pkg/ui/vlibras.js +130 -81
  398. package/dist-pkg/ui/voice-control.d.ts +68 -0
  399. package/dist-pkg/ui/voice-control.js +276 -0
  400. package/dist-pkg/ui/voice-settings.d.ts +95 -0
  401. package/dist-pkg/ui/voice-settings.js +352 -0
  402. package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
  403. package/dist-pkg/ui/where-the-child-is.js +70 -0
  404. package/docs/CREDITS.md +300 -44
  405. package/docs/LICENSES.md +189 -145
  406. package/package.json +51 -27
  407. package/scripts/check-cartridge.mjs +78 -0
  408. package/scripts/game-build.d.mts +25 -0
  409. package/scripts/game-build.mjs +144 -0
  410. package/scripts/heavy-into-the-delivery.mjs +388 -0
  411. package/scripts/libras-avatar.json +680 -0
  412. package/scripts/libras-avatar.mjs +246 -0
  413. package/scripts/libras-glosses/gloss.py +95 -0
  414. package/scripts/libras-glosses/pyproject.toml +32 -0
  415. package/scripts/libras-glosses/uv.lock +781 -0
  416. package/scripts/libras-glosses.mjs +351 -0
  417. package/scripts/licences/Apache-2.0.txt +176 -0
  418. package/scripts/licences/GPL-3.0.txt +674 -0
  419. package/scripts/licences/MIT.txt +17 -0
  420. package/scripts/licences/OFL-1.1.txt +86 -0
  421. package/scripts/licences/UFL-1.0.txt +96 -0
  422. package/scripts/licences/fonts.mjs +389 -0
  423. package/scripts/licences/third-party.mjs +301 -0
  424. package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
  425. package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
  426. package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
  427. package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
  428. package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
  429. package/app/public/vendor/fonts/inter-400.woff2 +0 -0
  430. package/app/public/vendor/fonts/inter-700.woff2 +0 -0
  431. package/app/public/vendor/fonts/lato-400.woff2 +0 -0
  432. package/app/public/vendor/fonts/lato-700.woff2 +0 -0
  433. package/app/public/vendor/fonts/literata-400.woff2 +0 -0
  434. package/app/public/vendor/fonts/literata-700.woff2 +0 -0
  435. package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
  436. package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
  437. package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
  438. package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
  439. package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
  440. package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
  441. package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
  442. package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
  443. package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
  444. package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
  445. package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
  446. package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
  447. package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
  448. package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
  449. package/dist-pkg/core/anel.d.ts +0 -17
  450. package/dist-pkg/core/anel.js +0 -31
  451. package/dist-pkg/core/collision.d.ts +0 -21
  452. package/dist-pkg/core/collision.js +0 -62
  453. package/dist-pkg/core/layers.d.ts +0 -63
  454. package/dist-pkg/core/layers.js +0 -95
  455. package/dist-pkg/core/letter-grid.d.ts +0 -55
  456. package/dist-pkg/core/letter-grid.js +0 -116
  457. package/dist-pkg/core/password.d.ts +0 -34
  458. package/dist-pkg/core/password.js +0 -205
  459. package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
  460. package/dist-pkg/core/rotulo-acessivel.js +0 -41
  461. package/dist-pkg/core/run-state.d.ts +0 -115
  462. package/dist-pkg/core/run-state.js +0 -40
  463. package/dist-pkg/core/tiles.d.ts +0 -12
  464. package/dist-pkg/core/tiles.js +0 -61
  465. package/dist-pkg/core/world.d.ts +0 -4
  466. package/dist-pkg/core/world.js +0 -58
  467. package/dist-pkg/input/origem-sintetica.d.ts +0 -44
  468. package/dist-pkg/input/origem-sintetica.js +0 -60
  469. package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
  470. package/dist-pkg/input/transporte-em-uso.js +0 -130
  471. package/dist-pkg/platform/audio-nav.d.ts +0 -51
  472. package/dist-pkg/platform/audio-nav.js +0 -99
  473. package/dist-pkg/platform/guide-intensity.d.ts +0 -40
  474. package/dist-pkg/platform/guide-intensity.js +0 -73
  475. package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
  476. package/dist-pkg/platform/pesados-catalogo.js +0 -177
  477. package/dist-pkg/platform/pesados.d.ts +0 -31
  478. package/dist-pkg/platform/pesados.js +0 -75
  479. package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
  480. package/dist-pkg/platform/vozes-prontas.js +0 -61
  481. package/dist-pkg/render/camera.d.ts +0 -58
  482. package/dist-pkg/render/camera.js +0 -105
  483. package/dist-pkg/render/cenario-data.d.ts +0 -127
  484. package/dist-pkg/render/cenario-data.js +0 -145
  485. package/dist-pkg/render/city-tex.d.ts +0 -63
  486. package/dist-pkg/render/city-tex.js +0 -228
  487. package/dist-pkg/render/city-tiles.d.ts +0 -11
  488. package/dist-pkg/render/city-tiles.js +0 -140
  489. package/dist-pkg/render/draw.d.ts +0 -149
  490. package/dist-pkg/render/draw.js +0 -231
  491. package/dist-pkg/render/fx.d.ts +0 -63
  492. package/dist-pkg/render/fx.js +0 -123
  493. package/dist-pkg/render/minimap.d.ts +0 -11
  494. package/dist-pkg/render/minimap.js +0 -94
  495. package/dist-pkg/render/parallax.d.ts +0 -85
  496. package/dist-pkg/render/parallax.js +0 -158
  497. package/dist-pkg/render/player-anim.d.ts +0 -71
  498. package/dist-pkg/render/player-anim.js +0 -152
  499. package/dist-pkg/render/recycling-tex.d.ts +0 -48
  500. package/dist-pkg/render/recycling-tex.js +0 -164
  501. package/dist-pkg/render/scene-city.d.ts +0 -77
  502. package/dist-pkg/render/scene-city.js +0 -181
  503. package/dist-pkg/render/scene-parallax.d.ts +0 -72
  504. package/dist-pkg/render/scene-parallax.js +0 -426
  505. package/dist-pkg/render/scene-sky.d.ts +0 -126
  506. package/dist-pkg/render/scene-sky.js +0 -295
  507. package/dist-pkg/render/set-cenario.d.ts +0 -54
  508. package/dist-pkg/render/set-cenario.js +0 -103
  509. package/dist-pkg/render/textures.d.ts +0 -75
  510. package/dist-pkg/render/textures.js +0 -240
  511. package/dist-pkg/render/title-scene.d.ts +0 -46
  512. package/dist-pkg/render/title-scene.js +0 -75
  513. package/dist-pkg/render/weather.d.ts +0 -96
  514. package/dist-pkg/render/weather.js +0 -171
  515. package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
  516. package/dist-pkg/render/wheelchair-sprites.js +0 -69
  517. package/dist-pkg/render/world-tex.d.ts +0 -18
  518. package/dist-pkg/render/world-tex.js +0 -87
  519. package/dist-pkg/ui/activities-menu.d.ts +0 -258
  520. package/dist-pkg/ui/activities-menu.js +0 -648
  521. package/dist-pkg/ui/caa-sets.d.ts +0 -39
  522. package/dist-pkg/ui/caa-sets.js +0 -65
  523. package/dist-pkg/ui/latch-refusal.d.ts +0 -32
  524. package/dist-pkg/ui/latch-refusal.js +0 -60
  525. package/dist-pkg/ui/map-hub.d.ts +0 -56
  526. package/dist-pkg/ui/map-hub.js +0 -138
  527. package/dist-pkg/ui/settings-caa.d.ts +0 -45
  528. package/dist-pkg/ui/settings-caa.js +0 -137
  529. package/dist-pkg/ui/settings-motor.d.ts +0 -175
  530. package/dist-pkg/ui/settings-motor.js +0 -342
  531. package/dist-pkg/ui/webcam.d.ts +0 -7
  532. package/dist-pkg/ui/webcam.js +0 -93
@@ -1,46 +1,46 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // render/high-contrast — Renderização Direta (Estágio 4, Tier 2): o motor de alto contraste de acessibilidade
3
- // (ADR-0011) — outline + color-blocking por papel + fundo recuado (dessaturado/escurecido), 3 níveis de
4
- // contraste (3:1/4,5:1/7:1). worldToTextureDirect/directBgTexture/directSprite{Canvas,Texture} + os caches
5
- // _worldTexHC/_coinTexHC (worldTexFor/coinTexFor) + a paleta HC_ROLE (persistida) vivem aqui. INJETADO via
6
- // initHighContrast: os limites do grid (W/H), os dois níveis de contorno (outlineFg/outlineBg — mutados por
7
- // setOutlineFg/setOutlineBg no game.js) e os canvases/texturas NORMAIS do mundo/moeda (mundo é `let` e muda de
8
- // cenário → getter; moeda nunca é reatribuída → valor direto). `_lastSharedViz` FICA no game.js: não é cache de
9
- // alto contraste, é o cache de "modo já aplicado" que TODO o pipeline de render estático (mundo/parallax/moedas/
10
- // power-ups/portão) usa para decidir quando reaplicar texturas por viewport — 7 subsistemas fora daqui escrevem
11
- // nele. `_pupTexHC`/`_playerDirect` (power-ups/player) também ficam no game.js: consomem directSpriteCanvas/
12
- // directSpriteTexture DAQUI mas não estão na lista de extração desta onda.
13
- // Ver docs/2-Architecture/adr/ADR-0011-visual-accessibility.yaml + docs/5-Refactoring/plano-modularizacao-mapa.md.
2
+ // render/high-contrast — Direct Rendering: the accessibility high-contrast engine (ADR-0011) — outline + color-blocking
3
+ // by role + a pushed-back background (desaturated/darkened), 3 contrast levels (3:1/4.5:1/7:1).
4
+ // `createHighContrast(ctx)` returns worldToTextureDirect/directBgTexture/directSprite{Canvas,Texture} + the caches
5
+ // (worldTexFor/spriteTexFor) + the role palette (persisted) — ONE instance per world, built by whoever HAS a world: the
6
+ // root has none, so a game that draws one builds it (ADR-0232 D4, issue #207). INJECTED: the document the canvases are
7
+ // made in, the grid's bounds (W/H), the tile lookup, the two outline levels (outlineFg/outlineBg, which the host changes)
8
+ // and the NORMAL world canvas/texture (the scenery can swap it → getter). The "mode already applied" cache that the
9
+ // host's static render pipeline uses to decide when to reapply textures per viewport is NOT here: it is not a
10
+ // high-contrast cache, and several subsystems outside write into it.
11
+ // See the ADR-0011 record (visual accessibility).
14
12
  import { makeCanvas, tex } from './canvas.js';
15
13
  import { outlineCanvas } from './sprite-fx.js';
16
14
  import { TILE } from '../core/constants.js';
17
- import { tileAt } from '../core/collision.js';
18
15
  import { HC_ROLE_DEF } from './hc-role-data.js';
19
- import * as store from '../platform/storage.js';
20
- export { HC_ROLE_KEYS, HC_ROLE_DEF } from './hc-role-data.js';
21
- export const HC_ROLE = (() => {
22
- const d = JSON.parse(JSON.stringify(HC_ROLE_DEF));
23
- const s = store.getJSON(store.KEYS.hcrole, null);
24
- if (s && typeof s === 'object') {
25
- for (const k of Object.keys(d)) {
26
- const v = s[k];
27
- if (Array.isArray(v) && v.length === 3)
28
- d[k] = v.map((n) => Math.max(0, Math.min(255, n | 0)));
29
- }
16
+ import { KEYS } from '../platform/storage-keys.js';
17
+ /* ===================== role → colour (color-blocking) ===================== */
18
+ // The roles and their default colours live in render/hc-role-data (a leaf, no dependencies), because the visual
19
+ // accessibility panel needs the SAME list to offer a colour picker per role. `HC_ROLE_DEF` is re-exported here because the
20
+ // engine imports it from here; the rest is read from the leaf (issue #204).
21
+ export { HC_ROLE_DEF } from './hc-role-data.js';
22
+ /** The defaults with the stored colours laid over them, each clamped to 0–255; a malformed entry keeps its default. */
23
+ function storedPalette(store) {
24
+ const palette = JSON.parse(JSON.stringify(HC_ROLE_DEF));
25
+ const s = store.getJSON(KEYS.hcrole, null);
26
+ if (!s || typeof s !== 'object')
27
+ return palette;
28
+ for (const k of Object.keys(palette)) {
29
+ const v = s[k];
30
+ if (Array.isArray(v) && v.length === 3)
31
+ palette[k] = v.map((n) => Math.max(0, Math.min(255, n | 0)));
30
32
  }
31
- return d;
32
- })();
33
- /** Persiste HC_ROLE (chamado por setRoleColor/resetRoleColors no game.js). Migrado de localStorage direto → store. */
34
- export function saveHcRole() { store.setJSON(store.KEYS.hcrole, HC_ROLE); }
35
- // off/mul = mapa da plataforma (mais off = mais clara → mais contraste); bgMul = fundo (menor = mais escuro/
36
- // recuado). Contraste plataforma×fundo ≈ 3 / 4,5 / 7 (ver ADR-0011: 3:1 é o default, "7:1 fica feio").
33
+ return palette;
34
+ }
35
+ // off/mul = the platform map (more off = lighter → more contrast); bgMul = the background (lower = darker/pushed back).
36
+ // Platform×background contrast ≈ 3 / 4.5 / 7 (see ADR-0011: 3:1 is the default, and 7:1 looks ugly).
37
37
  export const DIRECT_CFG = {
38
38
  'hc-direto': { off: 55, mul: 0.5, bgMul: 0.30 },
39
39
  'hc-direto-45': { off: 66, mul: 0.5, bgMul: 0.28 },
40
40
  'hc-direto-7': { off: 100, mul: 0.48, bgMul: 0.13 },
41
41
  };
42
42
  export function dcfg(mode) { return DIRECT_CFG[mode] || DIRECT_CFG['hc-direto']; }
43
- /* ===================== dessaturação/escurecimento (fundo/estrutura) ===================== */
43
+ /* ===================== desaturation/darkening (background/structure) ===================== */
44
44
  export function dimDesat(c, w, h, mul, blue, off) {
45
45
  off = off || 0;
46
46
  const img = c.getImageData(0, 0, w, h), d = img.data;
@@ -54,201 +54,210 @@ export function dimDesat(c, w, h, mul, blue, off) {
54
54
  }
55
55
  c.putImageData(img, 0, 0);
56
56
  }
57
- let ctx = null;
58
- export function initHighContrast(c) { ctx = c; }
59
- function requireCtx() {
60
- if (!ctx)
61
- throw new Error('render/high-contrast: initHighContrast(ctx) ainda não foi chamado');
62
- return ctx;
57
+ /** LADDER: black + rails and rungs in the role's colour → it reads as a ladder, not a solid band. */
58
+ function drawLadder(c, X, Y, climb) {
59
+ c.fillStyle = '#0a0e14';
60
+ c.fillRect(X, Y, TILE, TILE);
61
+ c.fillStyle = 'rgb(' + climb.join(',') + ')';
62
+ c.fillRect(X + 1, Y, 2, TILE);
63
+ c.fillRect(X + TILE - 3, Y, 2, TILE); // side rails (the role's colour, customisable)
64
+ for (let ry = 2; ry < TILE - 1; ry += 5)
65
+ c.fillRect(X + 1, Y + ry, TILE - 2, 2); // rungs
63
66
  }
64
- /* ===================== Renderização Direta: mundo + fundo + sprites de 1º plano ===================== */
65
- /** Mundo em alto contraste: base dessaturada/clareada + repintura por papel (com escada como caso especial:
66
- * trilhos/degraus, não faixa sólida) + contorno de 2º plano no perímetro externo (navegável × não-navegável). */
67
- export function worldToTextureDirect(srcCanvas, mode) {
68
- const hc = requireCtx();
69
- const cfg = dcfg(mode);
70
- const cv = makeCanvas(srcCanvas.width, srcCanvas.height), c = cv.getContext('2d');
71
- c.drawImage(srcCanvas, 0, 0);
72
- dimDesat(c, cv.width, cv.height, cfg.mul, 1.22, cfg.off); // base: estrutura vira cinza-azulado (mais clara = mais contraste)
67
+ /** A tile repainted in its role's colour `rc`, by the brightness of each pixel (BT.601 luma); a hazard starts from brighter. */
68
+ function repaintByRole(c, X, Y, role, rc) {
69
+ const img = c.getImageData(X, Y, TILE, TILE), d = img.data, lo = role === 'hazard' ? 0.58 : 0.44;
70
+ for (let i = 0; i < d.length; i += 4) {
71
+ if (d[i + 3] < 8)
72
+ continue;
73
+ const g = (0.299 * d[i] + 0.587 * d[i + 1] + 0.114 * d[i + 2]) / 255, f = lo + (1 - lo) * g;
74
+ d[i] = Math.min(255, rc[0] * f) | 0;
75
+ d[i + 1] = Math.min(255, rc[1] * f) | 0;
76
+ d[i + 2] = Math.min(255, rc[2] * f) | 0;
77
+ }
78
+ c.putImageData(img, X, Y);
79
+ }
80
+ /** Tiles 0 and 1 are this map's air (see the note in the loop below: a platformer's numbering, declared, not generalised). */
81
+ const isAir = (t) => t === 0 || t === 1;
82
+ /** The background outline: ONLY the outer perimeter — a block's edges that face the air —, not every block. */
83
+ function outlineSecondPlane(c, hc, th) {
84
+ if (th <= 0)
85
+ return;
86
+ const air = (x, y) => isAir(hc.tileAt(x, y));
87
+ c.fillStyle = 'rgba(200,222,255,0.97)';
73
88
  for (let y = 0; y < hc.H; y++)
74
89
  for (let x = 0; x < hc.W; x++) {
75
- const t = tileAt(x, y), role = hc.roleOf(t);
76
- if (!role)
77
- continue; // repinta tiles não-estruturais pela cor do papel
78
- const X = x * TILE, Y = y * TILE;
79
- // ⚠️ O QUE SOBRA DE PLATAFORMA AQUI. A escada é desenhada com trilhos e degraus porque uma faixa sólida
80
- // não LÊ como escada — decisão de acessibilidade, que serviria a qualquer jogo com algo escalável. Mas a
81
- // forma da pergunta injetada ("este tile se desenha como escada?" · "que pintor este papel usa?") ainda
82
- // não tem evidência que a escolha, e foi um consumidor que mostrou, no menu-nav, que a forma importa mais
83
- // que a existência da injeção. Declarado em vez de adivinhado. Ver game/tile-roles.
84
- if (t === 4) { // ESCADA: preto + trilhos e degraus ciano → lê como escada (não faixa verde sólida)
85
- c.fillStyle = '#0a0e14';
86
- c.fillRect(X, Y, TILE, TILE);
87
- c.fillStyle = 'rgb(' + HC_ROLE.climb.join(',') + ')';
88
- c.fillRect(X + 1, Y, 2, TILE);
89
- c.fillRect(X + TILE - 3, Y, 2, TILE); // trilhos laterais (cor do papel, customizável)
90
- for (let ry = 2; ry < TILE - 1; ry += 5)
91
- c.fillRect(X + 1, Y + ry, TILE - 2, 2); // degraus
90
+ if (air(x, y))
92
91
  continue;
93
- }
94
- const rc = HC_ROLE[role], img = c.getImageData(X, Y, TILE, TILE), d = img.data, lo = role === 'hazard' ? 0.58 : 0.44;
95
- for (let i = 0; i < d.length; i += 4) {
96
- if (d[i + 3] < 8)
97
- continue;
98
- const g = (0.299 * d[i] + 0.587 * d[i + 1] + 0.114 * d[i + 2]) / 255, f = lo + (1 - lo) * g;
99
- d[i] = Math.min(255, rc[0] * f) | 0;
100
- d[i + 1] = Math.min(255, rc[1] * f) | 0;
101
- d[i + 2] = Math.min(255, rc[2] * f) | 0;
102
- }
103
- c.putImageData(img, X, Y);
92
+ const X = x * TILE, Y = y * TILE;
93
+ if (air(x, y - 1))
94
+ c.fillRect(X, Y, TILE, th);
95
+ if (air(x, y + 1))
96
+ c.fillRect(X, Y + TILE - th, TILE, th);
97
+ if (air(x - 1, y))
98
+ c.fillRect(X, Y, th, TILE);
99
+ if (air(x + 1, y))
100
+ c.fillRect(X + TILE - th, Y, th, TILE);
104
101
  }
105
- const th = hc.outlineBg(); // contorno de 2º plano: SÓ o perímetro externo (bordas voltadas ao ar) — não em cada bloco
106
- if (th > 0) {
107
- const air = (x, y) => { const t = tileAt(x, y); return t === 0 || t === 1; };
108
- c.fillStyle = 'rgba(200,222,255,0.97)';
109
- for (let y = 0; y < hc.H; y++)
110
- for (let x = 0; x < hc.W; x++) {
111
- const t = tileAt(x, y);
112
- if (t === 0 || t === 1)
113
- continue;
114
- const X = x * TILE, Y = y * TILE;
115
- if (air(x, y - 1))
116
- c.fillRect(X, Y, TILE, th);
117
- if (air(x, y + 1))
118
- c.fillRect(X, Y + TILE - th, TILE, th);
119
- if (air(x - 1, y))
120
- c.fillRect(X, Y, th, TILE);
121
- if (air(x + 1, y))
122
- c.fillRect(X + TILE - th, Y, th, TILE);
102
+ }
103
+ /**
104
+ * Builds one world's high contrast and READS the stored role colours into its palette — at build, never at import
105
+ * (ADR-0232). The palette and the two texture caches live in this closure, so two worlds on one page share none of them.
106
+ */
107
+ export function createHighContrast(ctx) {
108
+ const { store, doc } = ctx;
109
+ const role = storedPalette(store);
110
+ const saveRole = () => { store.setJSON(KEYS.hcrole, role); };
111
+ /* ===================== Direct Rendering: world + background + foreground sprites ===================== */
112
+ /** The world in high contrast: a desaturated/lightened base + repaint by role (with the ladder as a special case:
113
+ * rails/rungs, not a solid band) + a background outline on the outer perimeter (walkable × not walkable). */
114
+ function worldToTextureDirect(srcCanvas, mode) {
115
+ const cfg = dcfg(mode);
116
+ const cv = makeCanvas(doc, srcCanvas.width, srcCanvas.height), c = cv.getContext('2d');
117
+ c.drawImage(srcCanvas, 0, 0);
118
+ dimDesat(c, cv.width, cv.height, cfg.mul, 1.22, cfg.off); // base: structure turns blue-grey (lighter = more contrast)
119
+ for (let y = 0; y < ctx.H; y++)
120
+ for (let x = 0; x < ctx.W; x++) {
121
+ const t = ctx.tileAt(x, y), r = ctx.roleOf(t);
122
+ if (!r)
123
+ continue; // repaint non-structural tiles in the role's colour
124
+ // ⚠️ WHAT PLATFORMER IS LEFT HERE. The ladder is drawn with rails and rungs because a solid band does not READ as a
125
+ // ladder — an accessibility decision that would serve any game with something climbable. But the shape of the
126
+ // injected question ("does this tile draw as a ladder?" · "which painter does this role use?") has no evidence to
127
+ // choose it yet, and a consumer showed, in menu-nav, that the shape matters more than the existence of the
128
+ // injection. Declared instead of guessed.
129
+ if (t === 4)
130
+ drawLadder(c, x * TILE, y * TILE, role.climb);
131
+ else
132
+ repaintByRole(c, x * TILE, y * TILE, r, role[r]);
123
133
  }
134
+ outlineSecondPlane(c, ctx, ctx.outlineBg());
135
+ return tex(cv);
124
136
  }
125
- return tex(cv);
126
- }
127
- /** Fundo/decoração em alto contraste: só dessaturação/escurecimento (recua) — sem repintura por papel nem
128
- * contorno. Usada por game.js para árvores (treeTexFor) e parallax (parallaxTexFor). */
129
- export function directBgTexture(srcTex, mode) {
130
- const cfg = dcfg(mode);
131
- const cv = makeCanvas(Math.max(1, srcTex.orig.width), Math.max(1, srcTex.orig.height)), dst = tex(cv);
132
- const paint = () => {
133
- const s = srcTex.baseTexture.resource && srcTex.baseTexture.resource.source;
134
- if (!s || !s.width)
135
- return;
136
- cv.width = s.width;
137
- cv.height = s.height;
138
- const c = cv.getContext('2d');
139
- c.clearRect(0, 0, cv.width, cv.height);
140
- c.drawImage(s, 0, 0);
141
- dimDesat(c, cv.width, cv.height, cfg.bgMul, 1.2);
142
- dst.update();
143
- };
144
- if (srcTex.baseTexture.valid)
145
- paint();
146
- else
147
- srcTex.baseTexture.once('loaded', paint);
148
- return dst;
149
- }
150
- /** Sprite de 1º plano (player/moeda/power-up) em alto contraste: mantém a cor da arte + contorno ESCURO
151
- * (WCAG 2.4.7 — "salta" do fundo recuado). `mode` não é usado (mantido só p/ paridade de assinatura com as
152
- * outras 3 funções "direct*" — o dispatch por DIRECT_CFG[mode] já aconteceu no chamador). fg=0 → sem contorno. */
153
- export function directSpriteCanvas(srcCanvas, mode) {
154
- void mode;
155
- const fg = requireCtx().outlineFg();
156
- return fg > 0 ? outlineCanvas(srcCanvas, fg) : srcCanvas;
157
- }
158
- /** Variante PIXI.Texture de directSpriteCanvas (player: a textura de origem já é uma PIXI.Texture, não um
159
- * canvas cru). `mode` idem — não usado, mantido por paridade de assinatura. */
160
- export function directSpriteTexture(srcTex, mode) {
161
- void mode;
162
- const fg = requireCtx().outlineFg();
163
- if (fg <= 0)
164
- return srcTex;
165
- const th = fg;
166
- const cv = makeCanvas(Math.max(1, srcTex.orig.width), Math.max(1, srcTex.orig.height)), dst = tex(cv);
167
- const paint = () => {
168
- const s = srcTex.baseTexture.resource && srcTex.baseTexture.resource.source;
169
- if (!s || !s.width)
170
- return;
171
- // ===================== O RECORTE VEM ANTES DO CONTORNO =====================
172
- // Aqui morava o "kage bunshin". Esta função lia a BASE e ignorava o `frame`, e havia um comentário
173
- // explicando por que isso era seguro: "só é chamada p/ texturas de player (sempre canvas-sourced)". A
174
- // afirmação era verdadeira e VIROU FALSA — o item 22 empacotou os sprites num atlas de 256×207, e desde
175
- // então só os quadros que passam pelo tapa-costuras (idle/andar/correr) viram tela própria. Pulo, escada,
176
- // parede, teto, nado e voo são RECORTE dentro do atlas, e contornar a base deles desenhava o atlas
177
- // inteiro: todos os quadros do personagem de uma vez, em grade.
178
- //
179
- // O tapa-costuras é assíncrono, e por isso o idle também aparecia: com alto contraste ligado cedo, o
180
- // cache `_playerDirect` memoriza a versão baseada no atlas e a guarda para sempre.
181
- const f = srcTex.frame;
182
- const precisaRecortar = !!f && (f.x !== 0 || f.y !== 0 || f.width !== s.width || f.height !== s.height);
183
- let fonte = s;
184
- if (precisaRecortar && f) {
185
- const rec = makeCanvas(Math.max(1, f.width), Math.max(1, f.height));
186
- const rc = rec.getContext('2d');
187
- rc.imageSmoothingEnabled = false; // pixel art: reamostrar aqui borraria o contorno que o modo promete
188
- rc.drawImage(s, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height);
189
- fonte = rec;
137
+ /** Background/decoration in high contrast: only desaturation/darkening (it steps back) — no repaint by role and no
138
+ * outline. Used by render/viewports for decoration (treeTexFor) and parallax (parallaxTexFor). */
139
+ function directBgTexture(srcTex, mode) {
140
+ const cfg = dcfg(mode);
141
+ const cv = makeCanvas(doc, Math.max(1, srcTex.orig.width), Math.max(1, srcTex.orig.height)), dst = tex(cv);
142
+ const paint = () => {
143
+ const s = srcTex.baseTexture.resource && srcTex.baseTexture.resource.source;
144
+ if (!s || !s.width)
145
+ return;
146
+ cv.width = s.width;
147
+ cv.height = s.height;
148
+ const c = cv.getContext('2d');
149
+ c.clearRect(0, 0, cv.width, cv.height);
150
+ c.drawImage(s, 0, 0);
151
+ dimDesat(c, cv.width, cv.height, cfg.bgMul, 1.2);
152
+ dst.update();
153
+ };
154
+ if (srcTex.baseTexture.valid)
155
+ paint();
156
+ else
157
+ srcTex.baseTexture.once('loaded', paint);
158
+ return dst;
159
+ }
160
+ /** A foreground sprite (player/coin/power-up) in high contrast: it keeps the art's colour + a DARK outline (WCAG 2.4.7 —
161
+ * it "jumps" off the pushed-back background). `mode` is unused (kept only for signature parity with the other 3
162
+ * "direct*" functions — the dispatch by DIRECT_CFG[mode] already happened in the caller). fg=0 → no outline. */
163
+ function directSpriteCanvas(srcCanvas, mode) {
164
+ void mode;
165
+ const fg = ctx.outlineFg();
166
+ return fg > 0 ? outlineCanvas(srcCanvas, fg) : srcCanvas;
167
+ }
168
+ /** The PIXI.Texture variant of directSpriteCanvas (player: the source texture is already a PIXI.Texture, not a raw
169
+ * canvas). `mode` likewise — unused, kept for signature parity. */
170
+ function directSpriteTexture(srcTex, mode) {
171
+ void mode;
172
+ const fg = ctx.outlineFg();
173
+ if (fg <= 0)
174
+ return srcTex;
175
+ const th = fg;
176
+ const cv = makeCanvas(doc, Math.max(1, srcTex.orig.width), Math.max(1, srcTex.orig.height)), dst = tex(cv);
177
+ const paint = () => {
178
+ const s = srcTex.baseTexture.resource && srcTex.baseTexture.resource.source;
179
+ if (!s || !s.width)
180
+ return;
181
+ // ===================== THE CLIP COMES BEFORE THE OUTLINE =====================
182
+ // Reading the BASE and ignoring the `frame` draws, for a frame packed in an atlas, the whole atlas: every frame of the
183
+ // character at once, in a grid — the "kage bunshin" defect. It happened once the character's sprites were packed
184
+ // into an atlas, where only the frames that go through the seam fixer (idle/walk/run) become canvases of their own
185
+ // and jump, ladder, wall, ceiling, swim and flight are CLIPS.
186
+ //
187
+ // The seam fixer is asynchronous, so the idle frame showed it too: with high contrast on early, the outlined-frame
188
+ // cache memorises the atlas-based version and keeps it forever.
189
+ const f = srcTex.frame;
190
+ const needsClipping = !!f && (f.x !== 0 || f.y !== 0 || f.width !== s.width || f.height !== s.height);
191
+ let drawSource = s;
192
+ if (needsClipping && f) {
193
+ const rec = makeCanvas(doc, Math.max(1, f.width), Math.max(1, f.height));
194
+ const rc = rec.getContext('2d');
195
+ rc.imageSmoothingEnabled = false; // pixel art: resampling here would blur the outline the mode promises
196
+ rc.drawImage(s, f.x, f.y, f.width, f.height, 0, 0, f.width, f.height);
197
+ drawSource = rec;
198
+ }
199
+ // outlineCanvas only declares HTMLCanvasElement; the clip already returns a canvas, and an unclipped base is
200
+ // canvas-sourced on the paths that remain. The cast changes nothing at runtime.
201
+ const o = outlineCanvas(drawSource, th);
202
+ cv.width = o.width;
203
+ cv.height = o.height;
204
+ const c = cv.getContext('2d');
205
+ c.clearRect(0, 0, cv.width, cv.height);
206
+ c.drawImage(o, 0, 0);
207
+ dst.update();
208
+ };
209
+ if (srcTex.baseTexture.valid)
210
+ paint();
211
+ else
212
+ srcTex.baseTexture.once('loaded', paint);
213
+ return dst;
214
+ }
215
+ /* ===================== lazy caches (world/sprites) + per-mode selector ===================== */
216
+ const worldTexHC = {};
217
+ /** The recoloured-sprite cache, keyed by `id|mode` — one cache for every sprite of this world, not one per game's coin. */
218
+ const spriteTexHC = {};
219
+ function worldTexFor(mode) {
220
+ if (DIRECT_CFG[mode]) {
221
+ if (!worldTexHC[mode])
222
+ worldTexHC[mode] = worldToTextureDirect(ctx.getWorldCanvasNormal(), mode);
223
+ return worldTexHC[mode];
190
224
  }
191
- // outlineCanvas só declara HTMLCanvasElement; o recorte já devolve canvas, e a base sem recorte é
192
- // canvas-sourced pelos caminhos que restam. O cast preserva o runtime idêntico ao original.
193
- const o = outlineCanvas(fonte, th);
194
- cv.width = o.width;
195
- cv.height = o.height;
196
- const c = cv.getContext('2d');
197
- c.clearRect(0, 0, cv.width, cv.height);
198
- c.drawImage(o, 0, 0);
199
- dst.update();
200
- };
201
- if (srcTex.baseTexture.valid)
202
- paint();
203
- else
204
- srcTex.baseTexture.once('loaded', paint);
205
- return dst;
206
- }
207
- /* ===================== caches preguiçosos (mundo/moeda) + seletor por modo ===================== */
208
- const _worldTexHC = {};
209
- /** Cache de sprite recolorido, chaveado por `id|modo`. Era `_coinTexHC[modo]` — um cache por jogo. */
210
- const _spriteTexHC = {};
211
- /** Textura do MUNDO para `mode` (normal → a textura viva; hc-* → Renderização Direta, cacheada). */
212
- export function worldTexFor(mode) {
213
- const hc = requireCtx();
214
- if (DIRECT_CFG[mode]) {
215
- if (!_worldTexHC[mode])
216
- _worldTexHC[mode] = worldToTextureDirect(hc.getWorldCanvasNormal(), mode);
217
- return _worldTexHC[mode];
225
+ return ctx.getWorldTexNormal();
218
226
  }
219
- return hc.getWorldTexNormal();
220
- }
221
- /**
222
- * Textura do sprite `id` para `mode` (mesma lógica de `worldTexFor`, cache por `id|modo`).
223
- *
224
- * Fora dos modos de renderização direta devolve a textura normal declarada pelo jogo — e devolve `undefined`
225
- * para um id que o jogo não declarou, em vez de lançar: um sprite ausente vira "sem textura" no desenho, que
226
- * é degradação; lançar aqui derrubaria o quadro inteiro por causa de um item.
227
- */
228
- export function spriteTexFor(id, mode) {
229
- const hc = requireCtx();
230
- const src = hc.sprites()[id];
231
- if (!src)
232
- return undefined;
233
- if (DIRECT_CFG[mode]) {
234
- const chave = id + '|' + mode;
235
- if (!_spriteTexHC[chave] && src.canvas)
236
- _spriteTexHC[chave] = tex(directSpriteCanvas(src.canvas, mode));
237
- return _spriteTexHC[chave] ?? src.tex;
227
+ /**
228
+ * Sprite `id`'s texture for `mode` (the same logic as `worldTexFor`, cached by `id|mode`).
229
+ *
230
+ * Outside the direct rendering modes it returns the normal texture the game declared — and it returns `undefined` for
231
+ * an id the game did not declare, instead of throwing: a missing sprite becomes "no texture" in the drawing, which is
232
+ * degradation; throwing here would take the whole frame down because of one item.
233
+ */
234
+ function spriteTexFor(id, mode) {
235
+ const src = ctx.sprites()[id];
236
+ if (!src)
237
+ return undefined;
238
+ if (DIRECT_CFG[mode]) {
239
+ const key = id + '|' + mode;
240
+ if (!spriteTexHC[key] && src.canvas)
241
+ spriteTexHC[key] = tex(directSpriteCanvas(src.canvas, mode));
242
+ return spriteTexHC[key] ?? src.tex;
243
+ }
244
+ return src.tex;
238
245
  }
239
- return src.tex;
240
- }
241
- /** Invalida o cache de mundo (tema/cenário mudou → worldCanvasNormal é outro canvas). */
242
- export function clearWorldTexCache() { for (const k in _worldTexHC)
243
- delete _worldTexHC[k]; }
244
- /**
245
- * Invalida o cache de sprites (cor de papel mudou → `_rebakeDirect` no game.js). Sem argumento limpa TUDO;
246
- * com um `id`, só as entradas daquele sprite — o que um jogo com muitos sprites vai querer, e o que um cache
247
- * chaveado só por modo não conseguia oferecer.
248
- */
249
- export function clearSpriteTexCache(id) {
250
- for (const k in _spriteTexHC) {
251
- if (id === undefined || k.startsWith(id + '|'))
252
- delete _spriteTexHC[k];
246
+ function clearWorldTexCache() { for (const k in worldTexHC)
247
+ delete worldTexHC[k]; }
248
+ /**
249
+ * With no argument it clears EVERYTHING; with an `id`, only that sprite's entries — what a game with many sprites will
250
+ * want, and what a cache keyed only by mode could not offer.
251
+ */
252
+ function clearSpriteTexCache(id) {
253
+ for (const k in spriteTexHC) {
254
+ if (id === undefined || k.startsWith(id + '|'))
255
+ delete spriteTexHC[k];
256
+ }
253
257
  }
258
+ return {
259
+ role, saveRole,
260
+ worldToTextureDirect, directBgTexture, directSpriteCanvas, directSpriteTexture,
261
+ worldTexFor, spriteTexFor, clearWorldTexCache, clearSpriteTexCache,
262
+ };
254
263
  }
@@ -0,0 +1,5 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ /** The simulations drawn rather than filtered. `haze` is also a filter under `createGame`, which draws only the other three. */
3
+ export type LowVisionDrawing = 'haze' | 'tunnel' | 'macular' | 'diabetic';
4
+ /** Draws simulation `lv` on a `w`×`h` context, over transparency. A key that is not a drawn simulation draws nothing. */
5
+ export declare function drawLowVision(c: CanvasRenderingContext2D, lv: string, w: number, h: number): void;
@@ -0,0 +1,46 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // render/low-vision-drawing — what a colour filter cannot make: the white film of cataract, the tunnel of glaucoma, the central
3
+ // scotoma of macular degeneration and the scattered scotomas of diabetic retinopathy. They are a DRAWING over the world, not a
4
+ // transformation of its colours.
5
+ //
6
+ // One drawing, two consumers: `render/viewports` stamps it into each viewport's texture, and `boot/create-game` lays it over
7
+ // the declared world for the empathy panel (issue #182). Written once so the two cannot show different simulations under one name.
8
+ /** Where the scattered scotomas of diabetic retinopathy sit, as fractions of the view: x, y and radius (of the width). */
9
+ const SCATTERED_SPOTS = [[.22, .3, .1], [.64, .22, .075], [.8, .58, .11], [.4, .7, .085], [.16, .8, .07], [.54, .48, .06]];
10
+ /** One radial gradient: its centre and radii, and its colour stops from the inside out. */
11
+ function radial(c, [x0, y0, r0, x1, y1, r1], stops) {
12
+ const g = c.createRadialGradient(x0, y0, r0, x1, y1, r1);
13
+ for (const [at, colour] of stops)
14
+ g.addColorStop(at, colour);
15
+ return g;
16
+ }
17
+ /** Each drawn simulation, one row. A table and not a chain of `else if`: a fifth simulation is one more row. */
18
+ const DRAWN = Object.freeze({
19
+ // a film over everything, translucent — the world shows through it, washed out
20
+ haze: (c, w, h) => { c.fillStyle = 'rgba(244,246,250,0.42)'; c.fillRect(0, 0, w, h); },
21
+ // the edges close in, the centre stays clear
22
+ tunnel: (c, w, h) => {
23
+ c.fillStyle = radial(c, [w / 2, h / 2, h * 0.12, w / 2, h / 2, h * 0.6], [[0, 'rgba(0,0,0,0)'], [.5, 'rgba(0,0,0,.55)'], [1, 'rgba(0,0,0,.99)']]);
24
+ c.fillRect(0, 0, w, h);
25
+ },
26
+ // the centre is gone, the edges stay
27
+ macular: (c, w, h) => {
28
+ c.fillStyle = radial(c, [w / 2, h / 2, 2, w / 2, h / 2, h * 0.34], [[0, 'rgba(12,12,15,.95)'], [.55, 'rgba(12,12,15,.5)'], [1, 'rgba(12,12,15,0)']]);
29
+ c.fillRect(0, 0, w, h);
30
+ },
31
+ // several dark spots, scattered, each in its own square
32
+ diabetic: (c, w, h) => {
33
+ for (const [fx, fy, fr] of SCATTERED_SPOTS) {
34
+ const x = fx * w, y = fy * h, r = fr * w;
35
+ c.fillStyle = radial(c, [x, y, 1, x, y, r], [[0, 'rgba(10,10,14,.95)'], [.5, 'rgba(10,10,14,.7)'], [1, 'rgba(10,10,14,0)']]);
36
+ c.fillRect(x - r, y - r, 2 * r, 2 * r);
37
+ }
38
+ },
39
+ });
40
+ /** Draws simulation `lv` on a `w`×`h` context, over transparency. A key that is not a drawn simulation draws nothing. */
41
+ export function drawLowVision(c, lv, w, h) {
42
+ // an OWN key only: `toString` is on every object, and it is not a simulation
43
+ if (!Object.hasOwn(DRAWN, lv))
44
+ return;
45
+ DRAWN[lv](c, w, h);
46
+ }