@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.
- package/README.md +120 -78
- package/app/css/style.css +761 -377
- package/app/public/vendor/fonts/playwrite-cu.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es-deco.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-es.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-j.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-gb-s.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pe.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-pt.woff2 +0 -0
- package/app/public/vendor/fonts-licences/NOTICE.txt +166 -0
- package/app/public/vendor/fonts-licences/OFL-1.1.txt +86 -0
- package/app/public/vendor/fonts.css +36 -84
- package/dist-pkg/boot/create-game.d.ts +499 -219
- package/dist-pkg/boot/create-game.js +3944 -562
- package/dist-pkg/core/a11y-sr.d.ts +25 -3
- package/dist-pkg/core/a11y-sr.js +38 -19
- package/dist-pkg/core/accessible-label.d.ts +17 -0
- package/dist-pkg/core/accessible-label.js +37 -0
- package/dist-pkg/core/accommodation-subjects.d.ts +26 -0
- package/dist-pkg/core/accommodation-subjects.js +32 -0
- package/dist-pkg/core/accommodations.d.ts +125 -0
- package/dist-pkg/core/accommodations.js +195 -0
- package/dist-pkg/core/actions.d.ts +108 -55
- package/dist-pkg/core/actions.js +122 -71
- package/dist-pkg/core/calm-mode.d.ts +31 -0
- package/dist-pkg/core/calm-mode.js +47 -0
- package/dist-pkg/core/camera-cycle.d.ts +15 -0
- package/dist-pkg/core/camera-cycle.js +7 -0
- package/dist-pkg/core/caption-duration.d.ts +15 -0
- package/dist-pkg/core/caption-duration.js +19 -0
- package/dist-pkg/core/cartridge-problems.d.ts +34 -0
- package/dist-pkg/core/cartridge-problems.js +53 -0
- package/dist-pkg/core/constants.d.ts +0 -54
- package/dist-pkg/core/constants.js +9 -76
- package/dist-pkg/core/contract.d.ts +142 -164
- package/dist-pkg/core/contract.js +222 -208
- package/dist-pkg/core/dom-query.d.ts +4 -4
- package/dist-pkg/core/dom-query.js +12 -20
- package/dist-pkg/core/entity.d.ts +62 -77
- package/dist-pkg/core/entity.js +18 -32
- package/dist-pkg/core/escape-html.d.ts +9 -10
- package/dist-pkg/core/escape-html.js +16 -20
- package/dist-pkg/core/flash-threshold.d.ts +17 -0
- package/dist-pkg/core/flash-threshold.js +113 -0
- package/dist-pkg/core/game-speed.d.ts +11 -0
- package/dist-pkg/core/game-speed.js +16 -0
- package/dist-pkg/core/genres.d.ts +20 -0
- package/dist-pkg/core/genres.js +44 -0
- package/dist-pkg/core/i18n.d.ts +71 -60
- package/dist-pkg/core/i18n.js +186 -200
- package/dist-pkg/core/loop.d.ts +17 -6
- package/dist-pkg/core/loop.js +26 -26
- package/dist-pkg/core/pause-icon-catalogue.d.ts +15 -0
- package/dist-pkg/core/pause-icon-catalogue.js +54 -0
- package/dist-pkg/core/ring.d.ts +17 -0
- package/dist-pkg/core/ring.js +29 -0
- package/dist-pkg/core/rng.d.ts +7 -12
- package/dist-pkg/core/rng.js +23 -53
- package/dist-pkg/core/route.d.ts +26 -26
- package/dist-pkg/core/route.js +126 -121
- package/dist-pkg/core/scenes.d.ts +37 -40
- package/dist-pkg/core/scenes.js +41 -43
- package/dist-pkg/core/screens.d.ts +4 -4
- package/dist-pkg/core/screens.js +11 -16
- package/dist-pkg/core/session-clock.d.ts +23 -0
- package/dist-pkg/core/session-clock.js +37 -0
- package/dist-pkg/core/setting-defaults.d.ts +61 -0
- package/dist-pkg/core/setting-defaults.js +66 -0
- package/dist-pkg/core/speech-rate.d.ts +29 -0
- package/dist-pkg/core/speech-rate.js +47 -0
- package/dist-pkg/core/state.d.ts +118 -118
- package/dist-pkg/core/state.js +322 -297
- package/dist-pkg/core/visual-cycles.d.ts +30 -0
- package/dist-pkg/core/visual-cycles.js +52 -0
- package/dist-pkg/core/visual-state.d.ts +13 -0
- package/dist-pkg/core/visual-state.js +6 -0
- package/dist-pkg/educational/activities-registry.d.ts +1 -1
- package/dist-pkg/educational/activities-registry.js +9 -8
- package/dist-pkg/educational/adaptive-engine.d.ts +11 -11
- package/dist-pkg/educational/adaptive-engine.js +17 -17
- package/dist-pkg/educational/segment-bar.d.ts +12 -12
- package/dist-pkg/educational/segment-bar.js +9 -9
- package/dist-pkg/i18n/en.js +324 -223
- package/dist-pkg/i18n/es.js +323 -223
- package/dist-pkg/i18n/pt.js +348 -226
- package/dist-pkg/input/default-bindings.d.ts +37 -38
- package/dist-pkg/input/default-bindings.js +127 -144
- package/dist-pkg/input/devices.d.ts +7 -7
- package/dist-pkg/input/devices.js +17 -16
- package/dist-pkg/input/edges.d.ts +23 -32
- package/dist-pkg/input/edges.js +23 -28
- package/dist-pkg/input/empathy-filter.d.ts +22 -0
- package/dist-pkg/input/empathy-filter.js +34 -0
- package/dist-pkg/input/face-map.d.ts +96 -0
- package/dist-pkg/input/face-map.js +255 -0
- package/dist-pkg/input/face-signals.d.ts +40 -0
- package/dist-pkg/input/face-signals.js +48 -0
- package/dist-pkg/input/gamepad.d.ts +195 -145
- package/dist-pkg/input/gamepad.js +383 -556
- package/dist-pkg/input/gaze-cycle.d.ts +64 -0
- package/dist-pkg/input/gaze-cycle.js +133 -0
- package/dist-pkg/input/gaze-relative.d.ts +68 -0
- package/dist-pkg/input/gaze-relative.js +142 -0
- package/dist-pkg/input/hand-map.d.ts +28 -0
- package/dist-pkg/input/hand-map.js +142 -0
- package/dist-pkg/input/input-cooldown.d.ts +17 -0
- package/dist-pkg/input/input-cooldown.js +39 -0
- package/dist-pkg/input/key-default.d.ts +30 -0
- package/dist-pkg/input/key-default.js +60 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +15 -21
- package/dist-pkg/input/keyboard-runtime.js +23 -27
- package/dist-pkg/input/keyboard.d.ts +68 -63
- package/dist-pkg/input/keyboard.js +83 -105
- package/dist-pkg/input/keydown.d.ts +123 -137
- package/dist-pkg/input/keydown.js +284 -289
- package/dist-pkg/input/latch-edge.d.ts +33 -21
- package/dist-pkg/input/latch-edge.js +34 -35
- package/dist-pkg/input/latch-scope.d.ts +51 -50
- package/dist-pkg/input/latch-scope.js +61 -82
- package/dist-pkg/input/latch-store.d.ts +26 -30
- package/dist-pkg/input/latch-store.js +42 -50
- package/dist-pkg/input/latch-sync.d.ts +29 -29
- package/dist-pkg/input/latch-sync.js +25 -25
- package/dist-pkg/input/latch.d.ts +14 -17
- package/dist-pkg/input/latch.js +29 -37
- package/dist-pkg/input/pad-defaults.d.ts +13 -16
- package/dist-pkg/input/pad-defaults.js +21 -28
- package/dist-pkg/input/pad-reading.d.ts +76 -0
- package/dist-pkg/input/pad-reading.js +169 -0
- package/dist-pkg/input/pad-wizard.d.ts +99 -0
- package/dist-pkg/input/pad-wizard.js +256 -0
- package/dist-pkg/input/pointer-space.d.ts +19 -20
- package/dist-pkg/input/pointer-space.js +27 -32
- package/dist-pkg/input/pointer.d.ts +39 -40
- package/dist-pkg/input/pointer.js +42 -45
- package/dist-pkg/input/state.d.ts +101 -89
- package/dist-pkg/input/state.js +54 -134
- package/dist-pkg/input/switch-scan.d.ts +59 -0
- package/dist-pkg/input/switch-scan.js +67 -0
- package/dist-pkg/input/synthetic-source.d.ts +42 -0
- package/dist-pkg/input/synthetic-source.js +57 -0
- package/dist-pkg/input/touch-bindings.d.ts +127 -116
- package/dist-pkg/input/touch-bindings.js +158 -173
- package/dist-pkg/input/touch.d.ts +147 -72
- package/dist-pkg/input/touch.js +362 -126
- package/dist-pkg/input/transport-in-use.d.ts +107 -0
- package/dist-pkg/input/transport-in-use.js +130 -0
- package/dist-pkg/input/transports.d.ts +90 -117
- package/dist-pkg/input/transports.js +104 -106
- package/dist-pkg/input/virtual-controller.d.ts +82 -0
- package/dist-pkg/input/virtual-controller.js +69 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +50 -49
- package/dist-pkg/input/vocabulary-migration.js +80 -79
- package/dist-pkg/input/voice-map.d.ts +59 -0
- package/dist-pkg/input/voice-map.js +123 -0
- package/dist-pkg/platform/audio-ambient.d.ts +13 -2
- package/dist-pkg/platform/audio-ambient.js +14 -14
- package/dist-pkg/platform/audio-earcons.d.ts +20 -19
- package/dist-pkg/platform/audio-earcons.js +51 -42
- package/dist-pkg/platform/audio-jingles.js +9 -10
- package/dist-pkg/platform/audio-mixer.d.ts +14 -2
- package/dist-pkg/platform/audio-mixer.js +31 -39
- package/dist-pkg/platform/audio-sonar.d.ts +49 -152
- package/dist-pkg/platform/audio-sonar.js +124 -302
- package/dist-pkg/platform/audio.d.ts +62 -19
- package/dist-pkg/platform/audio.js +193 -168
- package/dist-pkg/platform/choose-by-voice.d.ts +70 -0
- package/dist-pkg/platform/choose-by-voice.js +157 -0
- package/dist-pkg/platform/flash-sampler.d.ts +19 -0
- package/dist-pkg/platform/flash-sampler.js +79 -0
- package/dist-pkg/platform/font-library.d.ts +77 -0
- package/dist-pkg/platform/font-library.js +98 -0
- package/dist-pkg/platform/font-library.json +721 -0
- package/dist-pkg/platform/heavy-catalogue.d.ts +77 -0
- package/dist-pkg/platform/heavy-catalogue.js +256 -0
- package/dist-pkg/platform/heavy-mirror.d.ts +20 -0
- package/dist-pkg/platform/heavy-mirror.js +73 -0
- package/dist-pkg/platform/heavy.d.ts +136 -0
- package/dist-pkg/platform/heavy.js +324 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +23 -16
- package/dist-pkg/platform/interruptible-speech.js +77 -54
- package/dist-pkg/platform/kokoro-port.d.ts +27 -0
- package/dist-pkg/platform/kokoro-port.js +50 -0
- package/dist-pkg/platform/kokoro-runtime.d.ts +20 -0
- package/dist-pkg/platform/kokoro-runtime.js +52 -0
- package/dist-pkg/platform/kokoro.d.ts +70 -0
- package/dist-pkg/platform/kokoro.js +133 -0
- package/dist-pkg/platform/listener-scope.d.ts +12 -0
- package/dist-pkg/platform/listener-scope.js +90 -0
- package/dist-pkg/platform/locale-host.d.ts +14 -0
- package/dist-pkg/platform/locale-host.js +45 -0
- package/dist-pkg/platform/microphone.d.ts +51 -0
- package/dist-pkg/platform/microphone.js +118 -0
- package/dist-pkg/platform/onnx-runtime.d.ts +34 -0
- package/dist-pkg/platform/onnx-runtime.js +42 -0
- package/dist-pkg/platform/reading-in-worker.d.ts +64 -0
- package/dist-pkg/platform/reading-in-worker.js +125 -0
- package/dist-pkg/platform/reading-model.d.ts +94 -0
- package/dist-pkg/platform/reading-model.js +272 -0
- package/dist-pkg/platform/reading-runtime.d.ts +24 -0
- package/dist-pkg/platform/reading-runtime.js +164 -0
- package/dist-pkg/platform/reading-worker.d.ts +41 -0
- package/dist-pkg/platform/reading-worker.js +58 -0
- package/dist-pkg/platform/reading.d.ts +80 -0
- package/dist-pkg/platform/reading.js +136 -0
- package/dist-pkg/platform/speech-recognition.d.ts +60 -0
- package/dist-pkg/platform/speech-recognition.js +104 -0
- package/dist-pkg/platform/speech.d.ts +23 -1
- package/dist-pkg/platform/speech.js +29 -18
- package/dist-pkg/platform/storage-keys.d.ts +96 -0
- package/dist-pkg/platform/storage-keys.js +106 -0
- package/dist-pkg/platform/storage.d.ts +46 -111
- package/dist-pkg/platform/storage.js +104 -169
- package/dist-pkg/platform/tts.d.ts +85 -39
- package/dist-pkg/platform/tts.js +447 -127
- package/dist-pkg/platform/vision-loop.d.ts +23 -0
- package/dist-pkg/platform/vision-loop.js +56 -0
- package/dist-pkg/platform/vision.d.ts +132 -0
- package/dist-pkg/platform/vision.js +117 -0
- package/dist-pkg/platform/voice-listener.d.ts +40 -0
- package/dist-pkg/platform/voice-listener.js +88 -0
- package/dist-pkg/platform/voice-plan.d.ts +15 -98
- package/dist-pkg/platform/voice-plan.js +56 -143
- package/dist-pkg/platform/vosk-runtime.d.ts +96 -0
- package/dist-pkg/platform/vosk-runtime.js +151 -0
- package/dist-pkg/platform/vosk-vocabulary.d.ts +6 -0
- package/dist-pkg/platform/vosk-vocabulary.js +178 -0
- package/dist-pkg/render/canvas.d.ts +13 -7
- package/dist-pkg/render/canvas.js +13 -13
- package/dist-pkg/render/crt.d.ts +48 -12
- package/dist-pkg/render/crt.js +78 -80
- package/dist-pkg/render/cvd-matrices.d.ts +22 -18
- package/dist-pkg/render/cvd-matrices.js +37 -38
- package/dist-pkg/render/hc-role-data.d.ts +7 -7
- package/dist-pkg/render/hc-role-data.js +14 -14
- package/dist-pkg/render/high-contrast.d.ts +67 -56
- package/dist-pkg/render/high-contrast.js +226 -217
- package/dist-pkg/render/low-vision-drawing.d.ts +5 -0
- package/dist-pkg/render/low-vision-drawing.js +46 -0
- package/dist-pkg/render/lq-filter.d.ts +32 -20
- package/dist-pkg/render/lq-filter.js +59 -65
- package/dist-pkg/render/port.d.ts +86 -88
- package/dist-pkg/render/port.js +17 -23
- package/dist-pkg/render/screen-pipeline.d.ts +42 -42
- package/dist-pkg/render/screen-pipeline.js +80 -87
- package/dist-pkg/render/sprite-fx.d.ts +2 -1
- package/dist-pkg/render/sprite-fx.js +16 -14
- package/dist-pkg/render/viewports.d.ts +20 -15
- package/dist-pkg/render/viewports.js +83 -114
- package/dist-pkg/render/viz-axes-labels.d.ts +47 -0
- package/dist-pkg/render/viz-axes-labels.js +88 -0
- package/dist-pkg/render/viz-axes.d.ts +89 -86
- package/dist-pkg/render/viz-axes.js +128 -116
- package/dist-pkg/render/viz-modes.d.ts +28 -29
- package/dist-pkg/render/viz-modes.js +40 -45
- package/dist-pkg/render/viz-refusal.d.ts +32 -0
- package/dist-pkg/render/viz-refusal.js +57 -0
- package/dist-pkg/render/viz-setters.d.ts +104 -66
- package/dist-pkg/render/viz-setters.js +182 -191
- package/dist-pkg/ui/aac-sets.d.ts +45 -0
- package/dist-pkg/ui/aac-sets.js +41 -0
- package/dist-pkg/ui/audio-choices.d.ts +68 -0
- package/dist-pkg/ui/audio-choices.js +98 -0
- package/dist-pkg/ui/audio-rows-that-apply.d.ts +12 -0
- package/dist-pkg/ui/audio-rows-that-apply.js +43 -0
- package/dist-pkg/ui/camera-control.d.ts +53 -0
- package/dist-pkg/ui/camera-control.js +48 -0
- package/dist-pkg/ui/changed-mark.d.ts +9 -8
- package/dist-pkg/ui/changed-mark.js +22 -53
- package/dist-pkg/ui/control-choices.d.ts +37 -0
- package/dist-pkg/ui/control-choices.js +84 -0
- package/dist-pkg/ui/debug-panel.d.ts +59 -43
- package/dist-pkg/ui/debug-panel.js +68 -69
- package/dist-pkg/ui/declared-words.d.ts +21 -0
- package/dist-pkg/ui/declared-words.js +66 -0
- package/dist-pkg/ui/dom.d.ts +10 -14
- package/dist-pkg/ui/dom.js +10 -47
- package/dist-pkg/ui/drawing-problems.d.ts +25 -0
- package/dist-pkg/ui/drawing-problems.js +94 -0
- package/dist-pkg/ui/eye-control.d.ts +36 -0
- package/dist-pkg/ui/eye-control.js +178 -0
- package/dist-pkg/ui/face-control.d.ts +25 -0
- package/dist-pkg/ui/face-control.js +183 -0
- package/dist-pkg/ui/focus-trap.d.ts +39 -49
- package/dist-pkg/ui/focus-trap.js +56 -65
- package/dist-pkg/ui/fonts.d.ts +157 -68
- package/dist-pkg/ui/fonts.js +305 -115
- package/dist-pkg/ui/footer-scroll-driver.d.ts +14 -0
- package/dist-pkg/ui/footer-scroll-driver.js +201 -0
- package/dist-pkg/ui/footer-scroll.d.ts +38 -0
- package/dist-pkg/ui/footer-scroll.js +55 -0
- package/dist-pkg/ui/game-options.d.ts +47 -0
- package/dist-pkg/ui/game-options.js +158 -0
- package/dist-pkg/ui/gaze-overlay.d.ts +64 -0
- package/dist-pkg/ui/gaze-overlay.js +165 -0
- package/dist-pkg/ui/hand-control.d.ts +25 -0
- package/dist-pkg/ui/hand-control.js +143 -0
- package/dist-pkg/ui/help-panel.d.ts +87 -0
- package/dist-pkg/ui/help-panel.js +242 -0
- package/dist-pkg/ui/hud-bands.d.ts +62 -0
- package/dist-pkg/ui/hud-bands.js +146 -0
- package/dist-pkg/ui/hud-row.d.ts +34 -0
- package/dist-pkg/ui/hud-row.js +80 -0
- package/dist-pkg/ui/hud.d.ts +73 -73
- package/dist-pkg/ui/hud.js +94 -98
- package/dist-pkg/ui/item-announcement.d.ts +13 -12
- package/dist-pkg/ui/item-announcement.js +25 -26
- package/dist-pkg/ui/layout.d.ts +103 -28
- package/dist-pkg/ui/layout.js +117 -99
- package/dist-pkg/ui/libras-avatar-clip.d.ts +30 -0
- package/dist-pkg/ui/libras-avatar-clip.js +86 -0
- package/dist-pkg/ui/libras-avatar-load.d.ts +52 -0
- package/dist-pkg/ui/libras-avatar-load.js +134 -0
- package/dist-pkg/ui/libras-avatar-plan.d.ts +102 -0
- package/dist-pkg/ui/libras-avatar-plan.js +211 -0
- package/dist-pkg/ui/libras-avatar-player.d.ts +28 -0
- package/dist-pkg/ui/libras-avatar-player.js +226 -0
- package/dist-pkg/ui/libras-avatar-stage.d.ts +37 -0
- package/dist-pkg/ui/libras-avatar-stage.js +208 -0
- package/dist-pkg/ui/libras-glosses.d.ts +28 -0
- package/dist-pkg/ui/libras-glosses.js +161 -0
- package/dist-pkg/ui/locale-flags.d.ts +16 -0
- package/dist-pkg/ui/locale-flags.js +30 -0
- package/dist-pkg/ui/loop-crash.d.ts +17 -17
- package/dist-pkg/ui/loop-crash.js +33 -62
- package/dist-pkg/ui/menu-intent.d.ts +61 -0
- package/dist-pkg/ui/menu-intent.js +88 -0
- package/dist-pkg/ui/menu-items.d.ts +20 -0
- package/dist-pkg/ui/menu-items.js +51 -0
- package/dist-pkg/ui/menu-nav.d.ts +98 -92
- package/dist-pkg/ui/menu-nav.js +398 -286
- package/dist-pkg/ui/mobility-choices.d.ts +26 -0
- package/dist-pkg/ui/mobility-choices.js +41 -0
- package/dist-pkg/ui/motion-choices.d.ts +31 -0
- package/dist-pkg/ui/motion-choices.js +68 -0
- package/dist-pkg/ui/motion-scene.d.ts +24 -19
- package/dist-pkg/ui/motion-scene.js +29 -61
- package/dist-pkg/ui/mount-panel.d.ts +81 -0
- package/dist-pkg/ui/mount-panel.js +61 -0
- package/dist-pkg/ui/panel-shell.d.ts +65 -31
- package/dist-pkg/ui/panel-shell.js +92 -66
- package/dist-pkg/ui/panel-widgets.d.ts +150 -0
- package/dist-pkg/ui/panel-widgets.js +294 -0
- package/dist-pkg/ui/pause-buttons.d.ts +35 -0
- package/dist-pkg/ui/pause-buttons.js +66 -0
- package/dist-pkg/ui/pause-icons.d.ts +261 -347
- package/dist-pkg/ui/pause-icons.js +671 -601
- package/dist-pkg/ui/pause-markup.d.ts +86 -0
- package/dist-pkg/ui/pause-markup.js +125 -0
- package/dist-pkg/ui/reach-notice.d.ts +22 -23
- package/dist-pkg/ui/reach-notice.js +55 -58
- package/dist-pkg/ui/scan-overlay.d.ts +23 -0
- package/dist-pkg/ui/scan-overlay.js +50 -0
- package/dist-pkg/ui/screen-text.d.ts +25 -0
- package/dist-pkg/ui/screen-text.js +152 -0
- package/dist-pkg/ui/session-clock.d.ts +32 -0
- package/dist-pkg/ui/session-clock.js +67 -0
- package/dist-pkg/ui/settings-aac.d.ts +70 -0
- package/dist-pkg/ui/settings-aac.js +208 -0
- package/dist-pkg/ui/settings-audio.d.ts +97 -114
- package/dist-pkg/ui/settings-audio.js +493 -425
- package/dist-pkg/ui/settings-controls.d.ts +53 -96
- package/dist-pkg/ui/settings-controls.js +143 -215
- package/dist-pkg/ui/settings-empathy.d.ts +39 -30
- package/dist-pkg/ui/settings-empathy.js +53 -60
- package/dist-pkg/ui/settings-mobility.d.ts +192 -0
- package/dist-pkg/ui/settings-mobility.js +332 -0
- package/dist-pkg/ui/settings-motion.d.ts +91 -70
- package/dist-pkg/ui/settings-motion.js +287 -198
- package/dist-pkg/ui/settings-panel.d.ts +58 -45
- package/dist-pkg/ui/settings-panel.js +189 -94
- package/dist-pkg/ui/settings-typo.d.ts +29 -78
- package/dist-pkg/ui/settings-typo.js +158 -129
- package/dist-pkg/ui/settings-visual.d.ts +29 -87
- package/dist-pkg/ui/settings-visual.js +240 -193
- package/dist-pkg/ui/shell.d.ts +112 -135
- package/dist-pkg/ui/shell.js +148 -217
- package/dist-pkg/ui/simulation-list.d.ts +27 -0
- package/dist-pkg/ui/simulation-list.js +76 -0
- package/dist-pkg/ui/simulation-over-the-world.d.ts +23 -0
- package/dist-pkg/ui/simulation-over-the-world.js +131 -0
- package/dist-pkg/ui/simulation-refusal.d.ts +5 -31
- package/dist-pkg/ui/simulation-refusal.js +8 -56
- package/dist-pkg/ui/switchable-control.d.ts +11 -0
- package/dist-pkg/ui/switchable-control.js +19 -0
- package/dist-pkg/ui/title.d.ts +3 -12
- package/dist-pkg/ui/title.js +49 -18
- package/dist-pkg/ui/top-band.d.ts +26 -0
- package/dist-pkg/ui/top-band.js +96 -0
- package/dist-pkg/ui/typo-choices.d.ts +71 -0
- package/dist-pkg/ui/typo-choices.js +85 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +11 -47
- package/dist-pkg/ui/visual-axes-panel.js +12 -94
- package/dist-pkg/ui/visual-choices.d.ts +77 -0
- package/dist-pkg/ui/visual-choices.js +107 -0
- package/dist-pkg/ui/vlibras.d.ts +77 -10
- package/dist-pkg/ui/vlibras.js +130 -81
- package/dist-pkg/ui/voice-control.d.ts +68 -0
- package/dist-pkg/ui/voice-control.js +276 -0
- package/dist-pkg/ui/voice-settings.d.ts +95 -0
- package/dist-pkg/ui/voice-settings.js +352 -0
- package/dist-pkg/ui/where-the-child-is.d.ts +31 -0
- package/dist-pkg/ui/where-the-child-is.js +70 -0
- package/docs/CREDITS.md +300 -44
- package/docs/LICENSES.md +189 -145
- package/package.json +51 -27
- package/scripts/check-cartridge.mjs +78 -0
- package/scripts/game-build.d.mts +25 -0
- package/scripts/game-build.mjs +144 -0
- package/scripts/heavy-into-the-delivery.mjs +388 -0
- package/scripts/libras-avatar.json +680 -0
- package/scripts/libras-avatar.mjs +246 -0
- package/scripts/libras-glosses/gloss.py +95 -0
- package/scripts/libras-glosses/pyproject.toml +32 -0
- package/scripts/libras-glosses/uv.lock +781 -0
- package/scripts/libras-glosses.mjs +351 -0
- package/scripts/licences/Apache-2.0.txt +176 -0
- package/scripts/licences/GPL-3.0.txt +674 -0
- package/scripts/licences/MIT.txt +17 -0
- package/scripts/licences/OFL-1.1.txt +86 -0
- package/scripts/licences/UFL-1.0.txt +96 -0
- package/scripts/licences/fonts.mjs +389 -0
- package/scripts/licences/third-party.mjs +301 -0
- package/scripts/licences/vosk-browser.NOTICE.txt +268 -0
- package/app/public/vendor/fonts/comicneue-400.woff2 +0 -0
- package/app/public/vendor/fonts/comicneue-700.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/fondamento-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-400.woff2 +0 -0
- package/app/public/vendor/fonts/inter-700.woff2 +0 -0
- package/app/public/vendor/fonts/lato-400.woff2 +0 -0
- package/app/public/vendor/fonts/lato-700.woff2 +0 -0
- package/app/public/vendor/fonts/literata-400.woff2 +0 -0
- package/app/public/vendor/fonts/literata-700.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-400.woff2 +0 -0
- package/app/public/vendor/fonts/newsreader-700.woff2 +0 -0
- package/app/public/vendor/fonts/opendyslexic-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-400.woff2 +0 -0
- package/app/public/vendor/fonts/opensans-700.woff2 +0 -0
- package/app/public/vendor/fonts/pinyon-400.woff2 +0 -0
- package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-400.woff2 +0 -0
- package/app/public/vendor/fonts/quattro-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourcesans-700.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-400.woff2 +0 -0
- package/app/public/vendor/fonts/sourceserif-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/dist-pkg/core/anel.d.ts +0 -17
- package/dist-pkg/core/anel.js +0 -31
- package/dist-pkg/core/collision.d.ts +0 -21
- package/dist-pkg/core/collision.js +0 -62
- package/dist-pkg/core/layers.d.ts +0 -63
- package/dist-pkg/core/layers.js +0 -95
- package/dist-pkg/core/letter-grid.d.ts +0 -55
- package/dist-pkg/core/letter-grid.js +0 -116
- package/dist-pkg/core/password.d.ts +0 -34
- package/dist-pkg/core/password.js +0 -205
- package/dist-pkg/core/rotulo-acessivel.d.ts +0 -17
- package/dist-pkg/core/rotulo-acessivel.js +0 -41
- package/dist-pkg/core/run-state.d.ts +0 -115
- package/dist-pkg/core/run-state.js +0 -40
- package/dist-pkg/core/tiles.d.ts +0 -12
- package/dist-pkg/core/tiles.js +0 -61
- package/dist-pkg/core/world.d.ts +0 -4
- package/dist-pkg/core/world.js +0 -58
- package/dist-pkg/input/origem-sintetica.d.ts +0 -44
- package/dist-pkg/input/origem-sintetica.js +0 -60
- package/dist-pkg/input/transporte-em-uso.d.ts +0 -101
- package/dist-pkg/input/transporte-em-uso.js +0 -130
- package/dist-pkg/platform/audio-nav.d.ts +0 -51
- package/dist-pkg/platform/audio-nav.js +0 -99
- package/dist-pkg/platform/guide-intensity.d.ts +0 -40
- package/dist-pkg/platform/guide-intensity.js +0 -73
- package/dist-pkg/platform/pesados-catalogo.d.ts +0 -14
- package/dist-pkg/platform/pesados-catalogo.js +0 -177
- package/dist-pkg/platform/pesados.d.ts +0 -31
- package/dist-pkg/platform/pesados.js +0 -75
- package/dist-pkg/platform/vozes-prontas.d.ts +0 -28
- package/dist-pkg/platform/vozes-prontas.js +0 -61
- package/dist-pkg/render/camera.d.ts +0 -58
- package/dist-pkg/render/camera.js +0 -105
- package/dist-pkg/render/cenario-data.d.ts +0 -127
- package/dist-pkg/render/cenario-data.js +0 -145
- package/dist-pkg/render/city-tex.d.ts +0 -63
- package/dist-pkg/render/city-tex.js +0 -228
- package/dist-pkg/render/city-tiles.d.ts +0 -11
- package/dist-pkg/render/city-tiles.js +0 -140
- package/dist-pkg/render/draw.d.ts +0 -149
- package/dist-pkg/render/draw.js +0 -231
- package/dist-pkg/render/fx.d.ts +0 -63
- package/dist-pkg/render/fx.js +0 -123
- package/dist-pkg/render/minimap.d.ts +0 -11
- package/dist-pkg/render/minimap.js +0 -94
- package/dist-pkg/render/parallax.d.ts +0 -85
- package/dist-pkg/render/parallax.js +0 -158
- package/dist-pkg/render/player-anim.d.ts +0 -71
- package/dist-pkg/render/player-anim.js +0 -152
- package/dist-pkg/render/recycling-tex.d.ts +0 -48
- package/dist-pkg/render/recycling-tex.js +0 -164
- package/dist-pkg/render/scene-city.d.ts +0 -77
- package/dist-pkg/render/scene-city.js +0 -181
- package/dist-pkg/render/scene-parallax.d.ts +0 -72
- package/dist-pkg/render/scene-parallax.js +0 -426
- package/dist-pkg/render/scene-sky.d.ts +0 -126
- package/dist-pkg/render/scene-sky.js +0 -295
- package/dist-pkg/render/set-cenario.d.ts +0 -54
- package/dist-pkg/render/set-cenario.js +0 -103
- package/dist-pkg/render/textures.d.ts +0 -75
- package/dist-pkg/render/textures.js +0 -240
- package/dist-pkg/render/title-scene.d.ts +0 -46
- package/dist-pkg/render/title-scene.js +0 -75
- package/dist-pkg/render/weather.d.ts +0 -96
- package/dist-pkg/render/weather.js +0 -171
- package/dist-pkg/render/wheelchair-sprites.d.ts +0 -32
- package/dist-pkg/render/wheelchair-sprites.js +0 -69
- package/dist-pkg/render/world-tex.d.ts +0 -18
- package/dist-pkg/render/world-tex.js +0 -87
- package/dist-pkg/ui/activities-menu.d.ts +0 -258
- package/dist-pkg/ui/activities-menu.js +0 -648
- package/dist-pkg/ui/caa-sets.d.ts +0 -39
- package/dist-pkg/ui/caa-sets.js +0 -65
- package/dist-pkg/ui/latch-refusal.d.ts +0 -32
- package/dist-pkg/ui/latch-refusal.js +0 -60
- package/dist-pkg/ui/map-hub.d.ts +0 -56
- package/dist-pkg/ui/map-hub.js +0 -138
- package/dist-pkg/ui/settings-caa.d.ts +0 -45
- package/dist-pkg/ui/settings-caa.js +0 -137
- package/dist-pkg/ui/settings-motor.d.ts +0 -175
- package/dist-pkg/ui/settings-motor.js +0 -342
- package/dist-pkg/ui/webcam.d.ts +0 -7
- package/dist-pkg/ui/webcam.js +0 -93
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
type
|
|
2
|
+
import { type AudioCatStore } from './audio-mixer.js';
|
|
3
|
+
export type CatState = {
|
|
3
4
|
on: boolean;
|
|
4
5
|
vol: number;
|
|
5
6
|
};
|
|
@@ -10,23 +11,65 @@ type PlayerCtx = {
|
|
|
10
11
|
type ACWithCache = AudioContext & {
|
|
11
12
|
_noiseBuf?: AudioBuffer;
|
|
12
13
|
};
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
export interface AudioDeps {
|
|
15
|
+
/**
|
|
16
|
+
* Makes the engine's AudioContext, or answers `null` where the host has none. Called at the FIRST sound and not before: a
|
|
17
|
+
* context made before the child's first gesture is born suspended, and the browser only lets it run from a gesture. The root
|
|
18
|
+
* builds it from `host.win` (ADR-0232 point 2); REQUIRED, because a default would be the page's window reached from here.
|
|
19
|
+
*/
|
|
20
|
+
readonly newContext: () => AudioContext | null;
|
|
21
|
+
/** Where the mixer's categories are read from and kept: the page's store, built by the root. */
|
|
22
|
+
readonly store: AudioCatStore;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* ONE ROOT'S SOUND. The reads are GETTERS, so `audio.soundOn` is the value of now; copying one into a local freezes it. The
|
|
26
|
+
* methods hold no `this` and can be destructured.
|
|
27
|
+
*/
|
|
28
|
+
export interface Audio {
|
|
29
|
+
/** The game's master switch. Session only (not stored). */
|
|
30
|
+
readonly soundOn: boolean;
|
|
31
|
+
setSoundOn(v: boolean): void;
|
|
32
|
+
/** The master volume, 0..1, which every synthesis multiplies by. Session only. */
|
|
33
|
+
readonly volume: number;
|
|
34
|
+
setVolume(v: number): void;
|
|
35
|
+
/** The engine's context, `null` until the first sound asks for one. */
|
|
36
|
+
readonly audioCtx: AudioContext | null;
|
|
37
|
+
/** The context, made on the first call and resumed if the browser suspended it; `null` where the host has none. */
|
|
38
|
+
ensureAC(): AudioContext | null;
|
|
39
|
+
/** The master node (master gain → optional hearing-loss filter → destination), made on the first call. */
|
|
40
|
+
audioOut(): GainNode | null;
|
|
41
|
+
/** Whether the hearing-loss empathy simulation is on the master node. */
|
|
42
|
+
readonly hearingLoss: boolean;
|
|
43
|
+
/** Switches the hearing-loss filter on the master node. Storing it and announcing it are the caller's. */
|
|
44
|
+
setHearingLossGraph(on: boolean): void;
|
|
45
|
+
/** The pause and title silence everything; playing brings it back. Acts only if the master exists — never makes one. */
|
|
46
|
+
setMasterMuted(muted: boolean): void;
|
|
47
|
+
/**
|
|
48
|
+
* The mixer's live state per category, loaded from the store when the audio is built. Written in place — `on`, `vol`, or the
|
|
49
|
+
* whole category — by the panels, the bar and any game, and EVERY write that changes a value is told to `onCatChange`.
|
|
50
|
+
*/
|
|
51
|
+
readonly audioCat: Record<string, CatState>;
|
|
52
|
+
/**
|
|
53
|
+
* Listens to every change of a category — its `on` or its `vol` — WHOEVER made it: the engine's panels and bar, and a game
|
|
54
|
+
* writing `audio.audioCat.tts.on = false` itself (ADR-0247). Called with the category's key, after the value changed; a write
|
|
55
|
+
* of the value already there is no change. Answers the function that stops listening.
|
|
56
|
+
*/
|
|
57
|
+
onCatChange(listener: (cat: string) => void): () => void;
|
|
58
|
+
/** A category's bus, hanging off the master node. */
|
|
59
|
+
catNode(cat: string): GainNode | null;
|
|
60
|
+
/** Moves a category's bus to its state now, and keeps that state in the store. */
|
|
61
|
+
setCatGain(cat: string): void;
|
|
62
|
+
tone(freq: number, dur: number, type?: OscillatorType, when?: number, vol?: number): void;
|
|
63
|
+
/** `pc` = a per-player audio context, passed to route the cue to that player's device. */
|
|
64
|
+
tonePan(freq: number, dur: number, cat: string, pan?: number | null, vol?: number, type?: OscillatorType, pc?: PlayerCtx | null): void;
|
|
65
|
+
noiseHit(mat: string, pan?: number | null, pc?: PlayerCtx | null): void;
|
|
66
|
+
/** A count of steps and taps (an accessibility statistic). */
|
|
67
|
+
readonly footCount: number;
|
|
68
|
+
}
|
|
30
69
|
export declare function noiseBuffer(ac: ACWithCache): AudioBuffer;
|
|
31
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Builds one root's sound. The mixer's state is read from `store` HERE, so a voice built after it finds its categories — the
|
|
72
|
+
* order the second consumer once found by the silence (create-game, finding 3) is now the order of construction.
|
|
73
|
+
*/
|
|
74
|
+
export declare function createAudio(deps: AudioDeps): Audio;
|
|
32
75
|
export {};
|
|
@@ -1,40 +1,21 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// platform/audio.ts —
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
import { loadAudioCat, saveAudioCat } from './audio-mixer.js'; // mixer
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export let audioCtx = null;
|
|
13
|
-
export function ensureAC() {
|
|
14
|
-
if (!audioCtx) {
|
|
15
|
-
const AC = window.AudioContext || window.webkitAudioContext;
|
|
16
|
-
if (AC)
|
|
17
|
-
audioCtx = new AC();
|
|
18
|
-
}
|
|
19
|
-
if (audioCtx && audioCtx.state === 'suspended')
|
|
20
|
-
audioCtx.resume();
|
|
21
|
-
return audioCtx;
|
|
22
|
-
}
|
|
23
|
-
// ===== Nó MESTRE: master gain → (filtro de perda auditiva opcional) → destino. =====
|
|
24
|
-
export let hearingLoss = false;
|
|
25
|
-
let _masterGain = null, _hlChain = null;
|
|
26
|
-
export function audioOut() { const ac = ensureAC(); if (!ac)
|
|
27
|
-
return null; if (!_masterGain) {
|
|
28
|
-
_masterGain = ac.createGain();
|
|
29
|
-
wireMaster();
|
|
30
|
-
} return _masterGain; }
|
|
2
|
+
// platform/audio.ts — the audio base: the AudioContext's lifecycle (ensureAC), the master and mixer graph, and the
|
|
3
|
+
// oscillator and noise syntheses every game's cues are made of. One per root (ADR-0232 D4, issue #207): `createAudio` holds
|
|
4
|
+
// the context, the master, the mixer and the counters in its closure, and receives the host's context maker and store.
|
|
5
|
+
import { loadAudioCat, saveAudioCat } from './audio-mixer.js'; // per-category mixer (data + persistence)
|
|
6
|
+
export function noiseBuffer(ac) { if (ac._noiseBuf && ac._noiseBuf.length === ((ac.sampleRate * 0.2) | 0))
|
|
7
|
+
return ac._noiseBuf; const n = (ac.sampleRate * 0.2) | 0, b = ac.createBuffer(1, n, ac.sampleRate), d = b.getChannelData(0); for (let i = 0; i < n; i++)
|
|
8
|
+
d[i] = Math.random() * 2 - 1; return ac._noiseBuf = b; }
|
|
9
|
+
const FOOT = { grama: { f: 'highpass', hz: 2000, d: 0.09, v: 0.10 }, piso: { f: 'bandpass', hz: 1200, d: 0.06, v: 0.15 }, pedra: { f: 'highpass', hz: 1600, d: 0.05, v: 0.19 },
|
|
10
|
+
areia: { f: 'lowpass', hz: 650, d: 0.13, v: 0.10 }, madeira: { f: 'bandpass', hz: 480, d: 0.08, v: 0.15 }, ferro: { f: 'bandpass', hz: 2600, d: 0.12, v: 0.16 }, parede: { f: 'highpass', hz: 3200, d: 0.10, v: 0.08 },
|
|
11
|
+
terra: { f: 'lowpass', hz: 520, d: 0.11, v: 0.12 }, agua: { f: 'lowpass', hz: 330, d: 0.15, v: 0.13 } };
|
|
31
12
|
function buildHearingChain(ac) {
|
|
32
13
|
const lp = ac.createBiquadFilter();
|
|
33
14
|
lp.type = 'lowpass';
|
|
34
15
|
lp.frequency.value = 1400;
|
|
35
|
-
lp.Q.value = 0.7; //
|
|
16
|
+
lp.Q.value = 0.7; // the highs go first
|
|
36
17
|
const sp = ac.createScriptProcessor(512, 1, 1);
|
|
37
|
-
const TH = 0.06, RED = 0.12; // frame
|
|
18
|
+
const TH = 0.06, RED = 0.12; // a frame below the threshold → ×0.12 (a hearing aid in reverse)
|
|
38
19
|
sp.onaudioprocess = (e) => { const inp = e.inputBuffer.getChannelData(0), out = e.outputBuffer.getChannelData(0); let s = 0; for (let i = 0; i < inp.length; i++)
|
|
39
20
|
s += inp[i] * inp[i]; const g = Math.sqrt(s / inp.length) < TH ? RED : 1; for (let i = 0; i < inp.length; i++)
|
|
40
21
|
out[i] = inp[i] * g; };
|
|
@@ -42,150 +23,194 @@ function buildHearingChain(ac) {
|
|
|
42
23
|
sp.connect(ac.destination);
|
|
43
24
|
return { input: lp };
|
|
44
25
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
26
|
+
/**
|
|
27
|
+
* THE CATEGORIES AS THE MIXER HOLDS THEM, each write heard (ADR-0247). A game reaches the mixer itself (`Engine.audio`), and
|
|
28
|
+
* its door to a category is a plain property write — `audioCat.tts.on = false` — with no call after it that an event could
|
|
29
|
+
* hang on. So the write IS the door: `on` and `vol` are accessors that tell `changed`, and so is the category itself, whose
|
|
30
|
+
* replacement (`audioCat.tts = {…}`) is copied INTO the mixer's object — replaced, the object every surface reads would come
|
|
31
|
+
* apart from the one the engine and the game write, and no later write would be heard.
|
|
32
|
+
*/
|
|
33
|
+
function heardCategories(stored, changed) {
|
|
34
|
+
const cats = {};
|
|
35
|
+
for (const [k, first] of Object.entries(stored)) {
|
|
36
|
+
let on = first.on, vol = first.vol;
|
|
37
|
+
const live = {};
|
|
38
|
+
Object.defineProperties(live, {
|
|
39
|
+
on: { enumerable: true, get: () => on, set: (v) => { if (v !== on) {
|
|
40
|
+
on = v;
|
|
41
|
+
changed(k);
|
|
42
|
+
} } },
|
|
43
|
+
vol: { enumerable: true, get: () => vol, set: (v) => { if (v !== vol) {
|
|
44
|
+
vol = v;
|
|
45
|
+
changed(k);
|
|
46
|
+
} } },
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(cats, k, { enumerable: true, get: () => live, set: (v) => { live.on = v.on; live.vol = v.vol; } });
|
|
51
49
|
}
|
|
52
|
-
|
|
53
|
-
if (hearingLoss) {
|
|
54
|
-
if (!_hlChain)
|
|
55
|
-
_hlChain = buildHearingChain(ac);
|
|
56
|
-
_masterGain.connect(_hlChain.input);
|
|
57
|
-
}
|
|
58
|
-
else
|
|
59
|
-
_masterGain.connect(ac.destination);
|
|
50
|
+
return cats;
|
|
60
51
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return;
|
|
69
|
-
_masterGain.gain.setTargetAtTime(muted ? 0 : 1, audioCtx.currentTime, 0.04);
|
|
52
|
+
/** The last node before the output: a panner clamped to the two ears when a pan is asked, the gain itself when not. */
|
|
53
|
+
function panned(ac, g, pan) {
|
|
54
|
+
if (pan == null || !ac.createStereoPanner)
|
|
55
|
+
return g;
|
|
56
|
+
const p = ac.createStereoPanner();
|
|
57
|
+
p.pan.value = Math.max(-1, Math.min(1, pan));
|
|
58
|
+
g.connect(p);
|
|
59
|
+
return p;
|
|
70
60
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (!
|
|
61
|
+
/**
|
|
62
|
+
* Builds one root's sound. The mixer's state is read from `store` HERE, so a voice built after it finds its categories — the
|
|
63
|
+
* order the second consumer once found by the silence (create-game, finding 3) is now the order of construction.
|
|
64
|
+
*/
|
|
65
|
+
export function createAudio(deps) {
|
|
66
|
+
let soundOn = true, volume = 0.6;
|
|
67
|
+
let audioCtx = null;
|
|
68
|
+
let hearingLoss = false;
|
|
69
|
+
let masterGain = null, hlChain = null;
|
|
70
|
+
let footCount = 0;
|
|
71
|
+
const catListeners = new Set();
|
|
72
|
+
// a copy of the listeners, so one that stops listening while it is told does not skip the next
|
|
73
|
+
const audioCat = heardCategories(loadAudioCat(deps.store), (cat) => { for (const l of [...catListeners])
|
|
74
|
+
l(cat); });
|
|
75
|
+
const catNodes = {};
|
|
76
|
+
function onCatChange(listener) {
|
|
77
|
+
catListeners.add(listener);
|
|
78
|
+
return () => { catListeners.delete(listener); };
|
|
79
|
+
}
|
|
80
|
+
function ensureAC() {
|
|
81
|
+
if (!audioCtx)
|
|
82
|
+
audioCtx = deps.newContext();
|
|
83
|
+
if (audioCtx && audioCtx.state === 'suspended')
|
|
84
|
+
audioCtx.resume();
|
|
85
|
+
return audioCtx;
|
|
86
|
+
}
|
|
87
|
+
// ===== The MASTER node: master gain → (optional hearing-loss filter) → destination. =====
|
|
88
|
+
function audioOut() { const ac = ensureAC(); if (!ac)
|
|
89
|
+
return null; if (!masterGain) {
|
|
90
|
+
masterGain = ac.createGain();
|
|
91
|
+
wireMaster();
|
|
92
|
+
} return masterGain; }
|
|
93
|
+
function wireMaster() {
|
|
94
|
+
const ac = audioCtx;
|
|
95
|
+
if (!ac || !masterGain)
|
|
100
96
|
return;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
try {
|
|
98
|
+
masterGain.disconnect();
|
|
99
|
+
}
|
|
100
|
+
catch (e) { /* noop */ }
|
|
101
|
+
if (hearingLoss) {
|
|
102
|
+
if (!hlChain)
|
|
103
|
+
hlChain = buildHearingChain(ac);
|
|
104
|
+
masterGain.connect(hlChain.input);
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
masterGain.connect(ac.destination);
|
|
110
108
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
109
|
+
function setHearingLossGraph(on) { hearingLoss = on; if (audioCtx) {
|
|
110
|
+
audioOut();
|
|
111
|
+
wireMaster();
|
|
112
|
+
} }
|
|
113
|
+
function setMasterMuted(muted) { if (!masterGain || !audioCtx)
|
|
114
|
+
return; try {
|
|
115
|
+
masterGain.gain.setTargetAtTime(muted ? 0 : 1, audioCtx.currentTime, 0.04);
|
|
116
|
+
}
|
|
117
|
+
catch (e) { /* noop */ } }
|
|
118
|
+
// ===== The per-category mixer: each category has its gain (on/off + volume), hanging off the master node. =====
|
|
119
|
+
/** A category's level: silence when it is switched off, its volume when on — asked the same way when its bus is made and when the slider moves. */
|
|
120
|
+
function catLevel(cat) { const c = audioCat[cat]; return c.on ? c.vol : 0; }
|
|
121
|
+
function catNode(cat) { const ac = ensureAC(); if (!ac)
|
|
122
|
+
return null; const out = audioOut(); if (!out)
|
|
123
|
+
return null; if (!catNodes[cat]) {
|
|
124
|
+
const g = ac.createGain();
|
|
125
|
+
g.gain.value = catLevel(cat);
|
|
126
|
+
g.connect(out);
|
|
127
|
+
catNodes[cat] = g;
|
|
128
|
+
} return catNodes[cat]; }
|
|
129
|
+
function setCatGain(cat) { const g = catNodes[cat]; if (g && audioCtx)
|
|
130
|
+
g.gain.setTargetAtTime(catLevel(cat), audioCtx.currentTime, 0.02); saveAudioCat(deps.store, cat, audioCat[cat]); }
|
|
131
|
+
// ===== The questions a cue asks before it sounds, the same for the tone and the noise. =====
|
|
132
|
+
/** Whether a sound may play at all: the game's sound on, and the master above zero. */
|
|
133
|
+
function audible() { return soundOn && volume > 0; }
|
|
134
|
+
/** The context a cue plays in: the player's own device when one is given, the engine's otherwise. */
|
|
135
|
+
function contextFor(pc) { return pc ? pc.ac : ensureAC(); }
|
|
136
|
+
/** Where a cue goes out: the player's own device; otherwise its category's bus, the master, or the device itself. */
|
|
137
|
+
function outFor(ac, cat, pc) { return pc ? pc.out : (catNode(cat) || audioOut() || ac.destination); }
|
|
138
|
+
// ===== Oscillator syntheses (earcons/melodies). They read soundOn/volume and route through mixer → master. =====
|
|
139
|
+
function tone(freq, dur, type, when, vol) {
|
|
140
|
+
if (!audible())
|
|
141
|
+
return;
|
|
142
|
+
try {
|
|
143
|
+
const ac = contextFor();
|
|
144
|
+
if (!ac)
|
|
145
|
+
return;
|
|
146
|
+
const o = ac.createOscillator(), g = ac.createGain(), t = ac.currentTime + (when || 0);
|
|
147
|
+
o.type = type || 'square';
|
|
148
|
+
o.frequency.setValueAtTime(freq, t);
|
|
149
|
+
g.gain.setValueAtTime(0.0001, t);
|
|
150
|
+
g.gain.exponentialRampToValueAtTime(Math.max(0.02, (vol || 0.22) * volume), t + 0.01);
|
|
151
|
+
g.gain.exponentialRampToValueAtTime(0.0001, t + dur);
|
|
152
|
+
o.connect(g).connect(outFor(ac, 'earcons'));
|
|
153
|
+
o.start(t);
|
|
154
|
+
o.stop(t + dur + 0.02);
|
|
132
155
|
}
|
|
133
|
-
|
|
134
|
-
node.connect(pc ? pc.out : (catNode(cat) || audioOut() || ac.destination));
|
|
135
|
-
o.start(t);
|
|
136
|
-
o.stop(t + dur + 0.02);
|
|
156
|
+
catch (e) { /* noop */ }
|
|
137
157
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
158
|
+
function tonePan(freq, dur, cat, pan, vol, type, pc) {
|
|
159
|
+
if (!audible())
|
|
160
|
+
return;
|
|
161
|
+
const ac = contextFor(pc);
|
|
162
|
+
if (!ac)
|
|
163
|
+
return;
|
|
164
|
+
try {
|
|
165
|
+
const o = ac.createOscillator(), g = ac.createGain(), t = ac.currentTime;
|
|
166
|
+
o.type = type || 'sine';
|
|
167
|
+
o.frequency.value = freq;
|
|
168
|
+
g.gain.setValueAtTime(0.0001, t);
|
|
169
|
+
g.gain.exponentialRampToValueAtTime(Math.max(0.02, (vol || 0.2) * volume), t + 0.01);
|
|
170
|
+
g.gain.exponentialRampToValueAtTime(0.0001, t + dur);
|
|
171
|
+
o.connect(g);
|
|
172
|
+
panned(ac, g, pan).connect(outFor(ac, cat, pc));
|
|
173
|
+
o.start(t);
|
|
174
|
+
o.stop(t + dur + 0.02);
|
|
175
|
+
}
|
|
176
|
+
catch (e) { /* noop */ }
|
|
177
|
+
}
|
|
178
|
+
// ===== The NOISE synth (footsteps by material, the cane). noiseBuffer caches per context (supports one per player). =====
|
|
179
|
+
function noiseHit(mat, pan, pc) {
|
|
180
|
+
if (!audible())
|
|
181
|
+
return;
|
|
182
|
+
const ac = contextFor(pc);
|
|
183
|
+
if (!ac)
|
|
184
|
+
return;
|
|
185
|
+
const f = FOOT[mat] || FOOT.piso;
|
|
186
|
+
try {
|
|
187
|
+
const src = ac.createBufferSource();
|
|
188
|
+
src.buffer = noiseBuffer(ac);
|
|
189
|
+
const bq = ac.createBiquadFilter();
|
|
190
|
+
bq.type = f.f;
|
|
191
|
+
bq.frequency.value = f.hz;
|
|
192
|
+
bq.Q.value = 1.2;
|
|
193
|
+
const g = ac.createGain(), t = ac.currentTime;
|
|
194
|
+
g.gain.setValueAtTime(0.0001, t);
|
|
195
|
+
g.gain.exponentialRampToValueAtTime(Math.max(0.02, f.v * volume), t + 0.006);
|
|
196
|
+
g.gain.exponentialRampToValueAtTime(0.0001, t + f.d);
|
|
197
|
+
src.connect(bq).connect(g);
|
|
198
|
+
panned(ac, g, pan).connect(outFor(ac, 'interact', pc));
|
|
199
|
+
src.start(t);
|
|
200
|
+
src.stop(t + f.d + 0.03);
|
|
201
|
+
footCount++;
|
|
172
202
|
}
|
|
173
|
-
|
|
174
|
-
node.connect(pc ? pc.out : (catNode('interact') || audioOut() || ac.destination));
|
|
175
|
-
src.start(t);
|
|
176
|
-
src.stop(t + f.d + 0.03);
|
|
177
|
-
_footCount++;
|
|
203
|
+
catch (e) { /* noop */ }
|
|
178
204
|
}
|
|
179
|
-
|
|
205
|
+
return {
|
|
206
|
+
get soundOn() { return soundOn; }, setSoundOn: (v) => { soundOn = v; },
|
|
207
|
+
get volume() { return volume; }, setVolume: (v) => { volume = v; },
|
|
208
|
+
get audioCtx() { return audioCtx; }, ensureAC, audioOut,
|
|
209
|
+
get hearingLoss() { return hearingLoss; }, setHearingLossGraph, setMasterMuted,
|
|
210
|
+
audioCat, onCatChange, catNode, setCatGain,
|
|
211
|
+
tone, tonePan, noiseHit,
|
|
212
|
+
get footCount() { return footCount; },
|
|
213
|
+
};
|
|
180
214
|
}
|
|
181
|
-
/*
|
|
182
|
-
*
|
|
183
|
-
* De dez earcons, sete eram deste jogo: `coin`/`key`/`gate`/`power` são objetos deste mundo e
|
|
184
|
-
* `correct`/`wrong`/`place` são eventos da atividade. O gate acusava só a linha do `coin`, porque é a única
|
|
185
|
-
* com palavra que o casador conhece — e a linha acusada era a menos interessante das dez.
|
|
186
|
-
*
|
|
187
|
-
* As legendas eram pt-BR CRU (`'🔊 Coletou'`, `'🔊 Portão abriu'`): nove frases dentro de um módulo de
|
|
188
|
-
* plataforma, que o gate de i18n do `main.js` não alcança. Viraram CHAVES, e quem exibe resolve.
|
|
189
|
-
*
|
|
190
|
-
* O que ficou aqui é a SÍNTESE — oscilador, envelope, ruído, roteamento por categoria —, que serve a
|
|
191
|
-
* qualquer jogo. O que é 880 Hz de triangular por 0,14 s ao pegar uma moeda, não. */
|
|
215
|
+
/* What lives here is the SYNTHESIS — oscillator, envelope, noise, routing by category — which serves any game. A table of
|
|
216
|
+
* earcons does not: "880 Hz of triangle for 0.14 s when a coin is taken" is one game's world, and it lives with that game. */
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { type VoskDeps, type VoskLoad } from './vosk-runtime.js';
|
|
3
|
+
import { type VoiceListenerDeps } from './voice-listener.js';
|
|
4
|
+
/** What a choice gives back: the index of the option said, or `null`; what was heard; why it ended. */
|
|
5
|
+
export interface ChoiceHeard {
|
|
6
|
+
readonly chosen: number | null;
|
|
7
|
+
readonly heard: string;
|
|
8
|
+
/** One option said · more than one said in one sentence · no option in time · asked to stop. */
|
|
9
|
+
readonly ended: 'chosen' | 'unclear' | 'timeout' | 'asked';
|
|
10
|
+
}
|
|
11
|
+
export interface ChooseSettings {
|
|
12
|
+
/** The language the options are in — the content's, when it is not the page's (ADR-0225). Default: the page's. */
|
|
13
|
+
readonly language?: string;
|
|
14
|
+
/** How long to wait for an option. Default 10 s: time to think, and a microphone that is never forgotten open. */
|
|
15
|
+
readonly maxMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Called once, when the ear is OPEN and a word said now would be heard — at once when the 👄's ear is lent, after the model
|
|
18
|
+
* has loaded when one had to be opened. Before it, a game says «loading», not «say the answer»: the first choice in a language
|
|
19
|
+
* waits a few seconds for its model, and a child told to speak into that wait is not heard (the Dev, 2026-09-27).
|
|
20
|
+
*/
|
|
21
|
+
readonly onListening?: () => void;
|
|
22
|
+
}
|
|
23
|
+
/** A recogniser listening with a grammar: it can be stopped, and it may say which words its model knows. */
|
|
24
|
+
export interface OpenedChoice {
|
|
25
|
+
stop(): Promise<void>;
|
|
26
|
+
/** The words the language's model knows, when they can be read — an option with a word outside them can never be chosen. */
|
|
27
|
+
readonly vocabulary?: () => Promise<ReadonlySet<string> | null>;
|
|
28
|
+
}
|
|
29
|
+
export interface VoiceChooserDeps {
|
|
30
|
+
/** The page's language (`core/i18n.bcp47`). */
|
|
31
|
+
readonly language: () => string;
|
|
32
|
+
/**
|
|
33
|
+
* Opens the command recogniser for `language` with this grammar and the microphone, calling `onHeard` with every text it hears
|
|
34
|
+
* — `final` when the sentence ended. REJECTS, with the reason, when the model or the microphone cannot be had.
|
|
35
|
+
*/
|
|
36
|
+
readonly open: (language: string, grammar: readonly string[], onHeard: (text: string, final: boolean) => void) => Promise<OpenedChoice>;
|
|
37
|
+
readonly after: (fn: () => void, ms: number) => unknown;
|
|
38
|
+
readonly cancel: (handle: unknown) => void;
|
|
39
|
+
/** A line for `problems`, written once per reason (ADR-0169). */
|
|
40
|
+
readonly report: (line: string) => void;
|
|
41
|
+
/**
|
|
42
|
+
* An ear ALREADY LISTENING in `language`, lent for this choice with the grammar given — the 👄's (`ui/voice-control.borrow`) — or
|
|
43
|
+
* `null`. Borrowed, nothing is opened and nothing paused: one model and one microphone, however many choices.
|
|
44
|
+
*/
|
|
45
|
+
readonly borrow?: (language: string, grammar: readonly string[], onHeard: (text: string, final: boolean) => void) => OpenedChoice | null;
|
|
46
|
+
/** Called before an ear of its own is opened and after it is let go: the root pauses the 👄 in between (one ear per word). */
|
|
47
|
+
readonly pause?: () => void;
|
|
48
|
+
readonly resume?: () => void;
|
|
49
|
+
}
|
|
50
|
+
export interface VoiceChooser {
|
|
51
|
+
choose(options: readonly string[], settings?: ChooseSettings): Promise<ChoiceHeard>;
|
|
52
|
+
/** Ends the choice in hand now: it answers `null`, `ended: 'asked'`. */
|
|
53
|
+
stop(): void;
|
|
54
|
+
}
|
|
55
|
+
/** What opening the command recogniser for a choice uses of the delivery and the browser, lent by the root (ADR-0232 D4). */
|
|
56
|
+
export type CommandRecogniserDeps = Omit<VoskDeps, 'language'> & Pick<VoiceListenerDeps, 'getUserMedia' | 'createContext'> & {
|
|
57
|
+
/** How a language's model is had — the root's `keepVoskModels(…).load`, so it is loaded once; default a fresh load. */
|
|
58
|
+
readonly load?: (d: VoskDeps) => Promise<VoskLoad>;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* THE `open` A CHOOSER IS GIVEN WHERE THE COMMAND RECOGNISER IS THE EAR: the language's model from the delivery, then the
|
|
62
|
+
* microphone with the grammar. A model that opened for a microphone that did not is let go before the refusal travels.
|
|
63
|
+
*/
|
|
64
|
+
export declare function openWithCommandRecogniser(d: CommandRecogniserDeps): VoiceChooserDeps['open'];
|
|
65
|
+
/**
|
|
66
|
+
* The options a sentence names, in the order said, each once: read word by word, the LONGEST option that starts at each word —
|
|
67
|
+
* so «cavalo marinho» is one option and not also «cavalo» — accents and case aside, whole words only.
|
|
68
|
+
*/
|
|
69
|
+
export declare function optionsNamed(options: readonly string[], sentence: string): number[];
|
|
70
|
+
export declare function createVoiceChooser(d: VoiceChooserDeps): VoiceChooser;
|