@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,131 +1,76 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
-
// platform/audio-sonar —
|
|
2
|
+
// platform/audio-sonar — NAVIGATION BY SOUND, the part of audio navigation that serves ANY genre (item 19).
|
|
3
3
|
//
|
|
4
|
-
// =========================
|
|
5
|
-
//
|
|
4
|
+
// ========================= A FINDING, TURNED INTO A CUT =========================
|
|
5
|
+
// A second consumer recorded it and did not work around it: the sonar could not be used by anything but a platformer.
|
|
6
|
+
// Its context asked for tiles, a solid test, a hitbox, the tile size, a coin array and a scenery — a quiz would have had
|
|
7
|
+
// to invent fake tiles, a fake hitbox and a fake scenery to ask "point at the nearest option". The module was TWO
|
|
8
|
+
// modules under one name.
|
|
6
9
|
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
10
|
+
// This is one of them: what navigates by SOUND — pointing at the nearest target, the looping beacon, the pan by relative
|
|
11
|
+
// position and the question "does this child need audio cues?". The CANE and BLIND SWIMMING, which read tiles, floor and
|
|
12
|
+
// hitbox, are the platformer's and live in its repository (ADR-0228, note CC). So is the continuous audio GUIDE, which
|
|
13
|
+
// is that game's decision: it left this module for the platformer's `platform/audio-guide` (ADR-0257, note DZ).
|
|
11
14
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
+
// ========================= WHAT REPLACED THE PLATFORMER THINGS =========================
|
|
16
|
+
// None of them crossed over. The sonar used to ask the game for an array of coins and filter by taken/owner; now it
|
|
17
|
+
// receives the CONTRACT (ADR-0030):
|
|
15
18
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
+
// · the coins + the filter → `targetsOf(i)`, the "target" half of field 5. The game hands over the spots that still
|
|
20
|
+
// count for that player, and never says what they are.
|
|
21
|
+
// · the tile size (the ruler of "near") → `topology()` + `distance()`, the metric declared in field 1. In a
|
|
22
|
+
// platformer it is pixels over `unit`; on a grid, king's steps; in a quiz, a difference of index.
|
|
23
|
+
// · the target's name → `nameAt(spot)`, field 3. It is what lets the announcement say "coin", "question" or "box"
|
|
24
|
+
// without the engine knowing any of the three.
|
|
19
25
|
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
+
// ⚠️ AND ONE WAS LEFT, THE LAST AND THE WORST: the pan measured the stereo width as `LOGICAL_W * 0.55` — the SCREEN's
|
|
27
|
+
// width. The `wx` it divides comes from the TOPOLOGY, and dividing a world measure by a screen's width only works when
|
|
28
|
+
// both use the same ruler. Measured building a football game (#121): on a 90-METRE pitch, a team-mate ten metres to the
|
|
29
|
+
// right gives `10 / 176 = 0.057` — mono, in practice. The sonar would be **right and inaudible**. For the platformer it
|
|
30
|
+
// was true by chance (its world is measured in pixels) and for `grid`/`hotspots` it was vacuous, which is why it was
|
|
31
|
+
// never seen.
|
|
26
32
|
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
// estava certa sobre a origem e errada sobre a consequência: o `wx` que ela divide vem da TOPOLOGIA, e
|
|
30
|
-
// dividir uma medida de mundo pela largura de um ecrã só funciona quando as duas usam a mesma régua.
|
|
33
|
+
// The stereo width comes from the declared metric: `PAN_PACES * step`, where the step is the continuous space's `unit`,
|
|
34
|
+
// one cell on a grid, and nothing in a list — which has no space.
|
|
31
35
|
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
// medido em pixels) e para `grid`/`hotspots` era vácuo, e é por isso que nunca se viu.
|
|
36
|
-
//
|
|
37
|
-
// A largura do estéreo passa a vir da métrica declarada: `PAN_PACES * passo`, onde o passo é o `unit` do
|
|
38
|
-
// contínuo, uma célula na grade, e nada na lista — que não tem espaço.
|
|
39
|
-
//
|
|
40
|
-
// ========================= SEM I/O NO IMPORT =========================
|
|
41
|
-
// Nada aqui toca `window` fora de `playerCtx`, que é chamada e não importada. Roda no project `node`.
|
|
36
|
+
// ========================= NO I/O AT IMPORT =========================
|
|
37
|
+
// Nothing here touches `window`: a player's own context comes from the injected `newContext` (ADR-0232 D4). It runs in the
|
|
38
|
+
// `node` project.
|
|
42
39
|
import { distance, bearing } from '../core/contract.js';
|
|
43
|
-
import { t } from '../core/i18n.js';
|
|
44
|
-
// O GUIA (#84 item 2) é feito destes dois, e de mais nada: a ROTA diz quantos passos faltam contornando
|
|
45
|
-
// parede, e a INTENSIDADE traduz esse número em brilho e volume. Nenhum dos dois toca no Web Audio; a fiação
|
|
46
|
-
// — a única parte que toca — é o `updateGuide` lá em baixo, e é por isso que o desenho é conferível em `node`.
|
|
47
|
-
import { rotaAte } from '../core/route.js';
|
|
48
|
-
import { intensidadeDoGuia, CORTE_LONGE, PASSOS_ATE_O_FUNDO } from './guide-intensity.js';
|
|
49
40
|
/**
|
|
50
|
-
*
|
|
41
|
+
* How many STEPS of the declared metric saturate the stereo. Beyond this, "to the right" is just to the right.
|
|
51
42
|
*
|
|
52
|
-
* ⚠️
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
43
|
+
* ⚠️ ELEVEN IS NOT A NEW NUMBER — it is what the platformer always had, reread on the right ruler. The old denominator was
|
|
44
|
+
* `LOGICAL_W * 0.55 = 320 × 0.55 = 176` pixels, and the platformer declares `unit: TILE` = 16: **exactly 11 tiles**.
|
|
45
|
+
* Rewriting it in steps keeps what that child already hears, and says the same in any genre — 11 squares on a board,
|
|
46
|
+
* 11 metres on a pitch.
|
|
56
47
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* precisar de mais precisão.
|
|
48
|
+
* And it fits the ruler the rest of the module uses: `distanceKey` cuts "very near" at 4 steps and "near" at 9. The
|
|
49
|
+
* stereo saturates just after the thing becomes "far", which is where direction stops needing more precision.
|
|
60
50
|
*/
|
|
61
51
|
export const PAN_PACES = 11;
|
|
62
52
|
/**
|
|
63
|
-
*
|
|
53
|
+
* What ONE step is worth, in world units. Zero = this space has no sides.
|
|
64
54
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
55
|
+
* Continuous: the declared `unit`. Grid: one cell, by definition. List: nothing — `hotspots` is an order, not a geometry,
|
|
56
|
+
* and inventing a stereo width for it would point at a side that does not exist.
|
|
67
57
|
*/
|
|
68
|
-
export function
|
|
69
|
-
return
|
|
58
|
+
export function worldStep(shape) {
|
|
59
|
+
return shape.kind === 'continuous' ? shape.unit : shape.kind === 'grid' ? 1 : 0;
|
|
70
60
|
}
|
|
71
|
-
/**
|
|
72
|
-
* ⚠️ O TIMBRE TEM DE TER HARMÓNICOS, e isto é requisito técnico, não gosto.
|
|
73
|
-
*
|
|
74
|
-
* O eixo do #84 item 2 é o BRILHO, e brilho é um passa-baixo a abrir e a fechar. **Um passa-baixo sobre uma
|
|
75
|
-
* onda `sine` não faz absolutamente nada**: a senoide não tem nada acima da fundamental para o filtro cortar,
|
|
76
|
-
* e o guia ficaria com um eixo morto e só o volume a trabalhar. A dente-de-serra é a mais rica das quatro
|
|
77
|
-
* ondas do Web Audio — tem TODOS os harmónicos —, e é por isso que ela é a escolha.
|
|
78
|
-
*
|
|
79
|
-
* E ela resolve, de graça, a outra restrição do plano: o sonar e a bengala usam `sine`. Um timbre diferente
|
|
80
|
-
* era exigência de não colidirem no mesmo canal; aqui o timbre diferente É o mecanismo.
|
|
81
|
-
*/
|
|
82
|
-
export const GUIA_TIPO = 'sawtooth';
|
|
83
|
-
/**
|
|
84
|
-
* A fundamental do guia, fixa.
|
|
85
|
-
*
|
|
86
|
-
* ⚠️ FIXA DE PROPÓSITO: a ALTURA já é a linguagem do sonar (`380 + 740 * near`, mais perto = mais agudo). Se o
|
|
87
|
-
* guia também subisse de tom, os dois estariam a dizer a mesma coisa pelo mesmo meio, e quem ouve os dois ao
|
|
88
|
-
* mesmo tempo não teria como separá-los. O guia diz distância por brilho; o sonar, por altura.
|
|
89
|
-
*/
|
|
90
|
-
export const GUIA_HZ = 220;
|
|
91
|
-
/**
|
|
92
|
-
* Quantos quadros entre dois cálculos de rota.
|
|
93
|
-
*
|
|
94
|
-
* ⚠️ A ROTA É UMA BUSCA EM LARGURA, e o `__incl.update(dt)` conta QUADROS: correr uma BFS a cada quadro num
|
|
95
|
-
* mapa de plataforma gasta o orçamento do quadro inteiro no aparelho-alvo (Positivo/Chromebook, pilar 1). Doze
|
|
96
|
-
* quadros são ~0,2 s a 60 fps — mais depressa do que a criança anda um passo, e o som não espera por eles: a
|
|
97
|
-
* intensidade é reescrita TODO quadro, com o `passos` que a última rota deixou.
|
|
98
|
-
*/
|
|
99
|
-
export const QUADROS_ENTRE_ROTAS = 12;
|
|
100
|
-
/**
|
|
101
|
-
* O tecto de pontos da rota do guia. Bem abaixo dos 4096 do `core/route`, e o próprio módulo diz porquê:
|
|
102
|
-
* «uma pista por quadro tolera muito menos do que um cálculo ao carregar a fase». Estourar devolve `null`, que
|
|
103
|
-
* é «não sei» — e o guia cai na reta, que ainda soa.
|
|
104
|
-
*/
|
|
105
|
-
export const ORCAMENTO_DA_ROTA = 1024;
|
|
106
|
-
/**
|
|
107
|
-
* O ganho de base do guia, antes de a intensidade e o volume mestre o multiplicarem.
|
|
108
|
-
*
|
|
109
|
-
* ⚠️ MAIS BAIXO DO QUE O BIPE QUE ELE SUBSTITUI (0,11), e não por engano: um som que **nunca para** é
|
|
110
|
-
* percebido como mais alto do que um transiente do mesmo pico, e cansa por permanência em vez de por
|
|
111
|
-
* intensidade — exactamente o que o modo TEA existe para não fazer.
|
|
112
|
-
*/
|
|
113
|
-
export const GUIA_VOL = 0.06;
|
|
114
|
-
/** Constante de tempo do `setTargetAtTime`. Curta o bastante para acompanhar o passo, longa o bastante para
|
|
115
|
-
* que a mudança seja um deslize e não um degrau — um degrau a cada rota seria um bipe outra vez. */
|
|
116
|
-
export const TAU_DO_GUIA = 0.08;
|
|
117
61
|
export function createAudioSonar(ctx) {
|
|
118
|
-
|
|
119
|
-
|
|
62
|
+
const { t } = ctx;
|
|
63
|
+
let _sonarCount = 0;
|
|
64
|
+
/** The player's AudioContext (for `setSinkId` on their device), or null → the global context. */
|
|
120
65
|
function playerCtx(pl) {
|
|
121
66
|
if (!pl || !pl.audioSink)
|
|
122
67
|
return null;
|
|
123
68
|
try {
|
|
124
69
|
if (!pl._ac) {
|
|
125
|
-
const
|
|
126
|
-
if (!
|
|
70
|
+
const ac = ctx.newContext();
|
|
71
|
+
if (!ac)
|
|
127
72
|
return null;
|
|
128
|
-
pl._ac =
|
|
73
|
+
pl._ac = ac;
|
|
129
74
|
pl._acOut = pl._ac.createGain();
|
|
130
75
|
pl._acOut.connect(pl._ac.destination);
|
|
131
76
|
if (pl._ac.setSinkId)
|
|
@@ -140,245 +85,122 @@ export function createAudioSonar(ctx) {
|
|
|
140
85
|
}
|
|
141
86
|
}
|
|
142
87
|
function panFor(wx, pl) {
|
|
143
|
-
const
|
|
144
|
-
// `hotspots`
|
|
145
|
-
//
|
|
146
|
-
if (!(
|
|
88
|
+
const pace = worldStep(ctx.topology());
|
|
89
|
+
// `hotspots` has no space, so no side. `bearing` already answers `none` for the same reason, and centring is the only
|
|
90
|
+
// honest answer — a pan computed over list indices points at nothing.
|
|
91
|
+
if (!(pace > 0))
|
|
147
92
|
return 0;
|
|
148
|
-
return Math.max(-1, Math.min(1, (wx - pl.x) / (PAN_PACES *
|
|
93
|
+
return Math.max(-1, Math.min(1, (wx - pl.x) / (PAN_PACES * pace)));
|
|
149
94
|
}
|
|
150
95
|
/**
|
|
151
|
-
*
|
|
96
|
+
* Impaired sight? A game's audio cues — its edge guard, its guide — ask this, and exist only when the answer is yes (or in
|
|
97
|
+
* blind mode).
|
|
152
98
|
*
|
|
153
|
-
* ⚠️
|
|
154
|
-
*
|
|
155
|
-
* render
|
|
156
|
-
* `render/viz-axes` (uma aresta ao contrário: medido, `render/` importa de `platform/` em cinco pontos e o
|
|
157
|
-
* inverso em nenhum), ou deixava de saber o que é um modo visual.
|
|
99
|
+
* ⚠️ THE VISUAL HALF IS INJECTED (#104), and the module got SMALLER instead of migrating. It used to consult a table of
|
|
100
|
+
* RENDER modes, walked with a render key, from inside `platform/`. The choice was: import `render/` (an edge the wrong
|
|
101
|
+
* way — `render/` imports `platform/`, never the reverse), or stop knowing what a visual mode is.
|
|
158
102
|
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* de composição responde, porque é ela que conhece os dois eixos.
|
|
103
|
+
* The second is right, and it is the move of `isNavigable`: inject the BOOLEAN, not the state. What this module needs to
|
|
104
|
+
* know is "does this child need audio cues", and that is not a question about filter tables — the composition root
|
|
105
|
+
* answers it, because it knows the two axes.
|
|
163
106
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
107
|
+
* What STAYS here is the rule that really is this module's: **blind mode turns the cues on for everyone**, whatever
|
|
108
|
+
* sight says.
|
|
166
109
|
*/
|
|
167
110
|
function needsAudioCues(pl) {
|
|
168
|
-
return ctx.
|
|
111
|
+
return ctx.getBlindMode() || ctx.visionImpaired(pl);
|
|
169
112
|
}
|
|
170
113
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* Era um laço sobre `getCoins()` com `if (cn.taken || cn.owner !== pl.i) continue` e `Math.hypot`. As três
|
|
174
|
-
* coisas que ele sabia sobre o jogo (que alvos são moedas, que moedas têm dono, que distância é euclidiana
|
|
175
|
-
* em pixels) viraram uma pergunta ao contrato e uma chamada a `distance`.
|
|
176
|
-
*/
|
|
177
|
-
/**
|
|
178
|
-
* O RUMO EM PALAVRAS, na língua de quem joga e no referencial que o JOGO declarou.
|
|
114
|
+
* THE BEARING IN WORDS, in the player's language and in the frame the GAME declared.
|
|
179
115
|
*
|
|
180
|
-
* ⚠️
|
|
181
|
-
*
|
|
116
|
+
* ⚠️ WHAT THIS REPLACED WAS AN ACCESSIBILITY DEFECT, not a style detail. The sonar computed the side by hand, from a raw
|
|
117
|
+
* `x`, with a ±4 dead zone:
|
|
182
118
|
*
|
|
183
|
-
*
|
|
119
|
+
* target.at.x < pl.x - 4 ? 'left' : target.at.x > pl.x + 4 ? 'right' : 'ahead'
|
|
184
120
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* a quem não vê a tela — apagada por uma zona morta.
|
|
121
|
+
* Three words where the contract has eight — and MIXING FRAMES: left/right is relative to the SCREEN, ahead is relative
|
|
122
|
+
* to the BODY, and a listener cannot know which origin each one speaks from. Worse: everything above or below the child
|
|
123
|
+
* became "ahead", exactly the information most missing for someone who cannot see the screen — erased by a dead zone.
|
|
189
124
|
*
|
|
190
|
-
* ⚠️
|
|
191
|
-
*
|
|
125
|
+
* ⚠️ AND THE FRAME IS THE GAME'S. On a board one says "to the north-east"; in a 2D platformer seen from the side, north
|
|
126
|
+
* means nothing, and what one says is "at 2 o'clock".
|
|
192
127
|
*/
|
|
193
|
-
function
|
|
128
|
+
function inWords(r) {
|
|
194
129
|
if (r.kind === 'none')
|
|
195
130
|
return t('sr.nav.here');
|
|
196
|
-
//
|
|
197
|
-
//
|
|
131
|
+
// One key with `{h}` and not twelve — but the singular has its own, because "at 1 hours" is not a sentence in any of
|
|
132
|
+
// the three languages the way the plural key would write it. Where two forms coincide, having both costs nothing.
|
|
198
133
|
if (r.kind === 'clock')
|
|
199
134
|
return r.hour === 1 ? t('sr.nav.clockOne') : t('sr.nav.clock', { h: r.hour });
|
|
200
135
|
return t('sr.nav.dir.' + r.heading);
|
|
201
136
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
137
|
+
/**
|
|
138
|
+
* This player's nearest target, in the DECLARED METRIC — and `null` if there is none.
|
|
139
|
+
*
|
|
140
|
+
* It was a loop over coins that skipped the taken and the unowned and measured with `Math.hypot`. The three things it
|
|
141
|
+
* knew about the game (that targets are coins, that coins have owners, that distance is Euclidean in pixels) became a
|
|
142
|
+
* question to the contract and a call to `distance`.
|
|
143
|
+
*/
|
|
144
|
+
function nearestSpot(pl) {
|
|
145
|
+
const shape = ctx.topology();
|
|
146
|
+
const here = { x: pl.x, y: pl.y };
|
|
147
|
+
let nearest = null, bd = Infinity;
|
|
148
|
+
for (const target of ctx.targetsOf(pl.i)) {
|
|
149
|
+
const d = distance(shape, here, target);
|
|
208
150
|
if (d < bd) {
|
|
209
151
|
bd = d;
|
|
210
|
-
|
|
152
|
+
nearest = target;
|
|
211
153
|
}
|
|
212
154
|
}
|
|
213
|
-
return
|
|
155
|
+
return nearest ? { at: nearest, d: bd } : null;
|
|
214
156
|
}
|
|
215
157
|
/**
|
|
216
|
-
* "
|
|
158
|
+
* "Near" in STEPS of the declared metric, not in pixels.
|
|
217
159
|
*
|
|
218
|
-
*
|
|
219
|
-
* a
|
|
220
|
-
*
|
|
160
|
+
* The original thresholds of 4 and 9 tiles become 4 and 9 UNITS: in a platformer with `unit = TILE` the sum is the same
|
|
161
|
+
* as before; on a grid it is four and nine squares; in a quiz, four and nine items away in the list. The same sentence
|
|
162
|
+
* for the child in any genre, which is the contract's point.
|
|
163
|
+
*/
|
|
164
|
+
const distanceKey = (d) => d < 4 ? 'sr.nav.veryClose' : d < 9 ? 'sr.nav.close' : 'sr.nav.far';
|
|
165
|
+
/**
|
|
166
|
+
* THE SONAR: a tone that points, and words (ADR-0234). The tone is the same with or without text on screen — pitch says how
|
|
167
|
+
* near the nearest target is, the pan which side, and a low tone that there is none. The WORDS are what is on the screen
|
|
168
|
+
* when there is text there, read now; only a screen with no text the engine can read gets the navigation sentence.
|
|
221
169
|
*/
|
|
222
|
-
const chaveDeDistancia = (d) => d < 4 ? 'sr.nav.veryClose' : d < 9 ? 'sr.nav.close' : 'sr.nav.far';
|
|
223
170
|
function sonar(pl) {
|
|
224
171
|
_sonarCount++;
|
|
225
172
|
const pc = playerCtx(pl);
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (!alvo) {
|
|
173
|
+
const target = nearestSpot(pl);
|
|
174
|
+
if (target)
|
|
175
|
+
ctx.tonePan(380 + 740 * Math.max(0, 1 - target.d / 12), 0.16, 'sonar', panFor(target.at.x, pl), 0.26, 'sine', pc); // nearer = higher
|
|
176
|
+
else
|
|
231
177
|
ctx.tonePan(300, 0.2, 'sonar', 0, 0.2, 'sine', pc);
|
|
178
|
+
const onScreen = ctx.screenText?.() ?? '';
|
|
179
|
+
if (onScreen) {
|
|
180
|
+
ctx.srSay(onScreen);
|
|
181
|
+
ctx.narrate(onScreen, pl.i);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// A sonar that no longer knows what the target is cannot name it when there is NO target at all: it says "nothing
|
|
185
|
+
// nearby", which is true in any genre.
|
|
186
|
+
if (!target) {
|
|
232
187
|
ctx.srSay(t('sr.nav.noTargetNear'));
|
|
233
188
|
return;
|
|
234
189
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
lado: emPalavras(bearing(ctx.topology(), { x: pl.x, y: pl.y }, alvo.at)),
|
|
243
|
-
dist: t(chaveDeDistancia(alvo.d)),
|
|
190
|
+
// The NAME comes from the game (field 3); the engine used to say "coin" because it only knew coins. The fallback is
|
|
191
|
+
// for a game that declares a target without a name: "target" is better than a raw key.
|
|
192
|
+
const name = ctx.nameAt(target.at);
|
|
193
|
+
const foundSentence = t('sr.nav.sonarFound', {
|
|
194
|
+
alvo: name ? name.text : t('sr.nav.target'),
|
|
195
|
+
lado: inWords(bearing(ctx.topology(), { x: pl.x, y: pl.y }, target.at)),
|
|
196
|
+
dist: t(distanceKey(target.d)),
|
|
244
197
|
});
|
|
245
|
-
const msg = (ctx.getNumPlayers() > 1 ? t('sr.player.prefix', { n: pl.i + 1 }) : '') +
|
|
198
|
+
const msg = (ctx.getNumPlayers() > 1 ? t('sr.player.prefix', { n: pl.i + 1 }) : '') + foundSentence;
|
|
246
199
|
ctx.srSay(msg);
|
|
247
|
-
ctx.narrate(msg);
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* QUANTOS PASSOS FALTAM, e a resposta preferida é a que contorna parede.
|
|
251
|
-
*
|
|
252
|
-
* ⚠️ AS DUAS RESPOSTAS JÁ ESTÃO NA MESMA UNIDADE, e é a única razão pela qual esta função é uma linha em vez
|
|
253
|
-
* de uma conversão: `rotaAte().passos` conta passos por definição, e `distance()` também devolve passos em
|
|
254
|
-
* TODA topologia — ela própria divide pela `unit` no ramo contínuo. Dividir aqui outra vez pelo passo do
|
|
255
|
-
* mundo era o erro à espera de ser cometido, e num jogo com `unit = 16` ele poria o guia no brilho máximo
|
|
256
|
-
* para sempre. É o mesmo defeito que a #121 tirou do `panFor`: misturar régua de mundo com régua de ecrã.
|
|
257
|
-
*
|
|
258
|
-
* A rota perde-se de duas maneiras — jogo que não injectou `roleAt`, e orçamento estourado — e as duas caem
|
|
259
|
-
* no mesmo recuo: a RETA. ⚠️ Ela mente atrás de parede (diz «perto» de um alvo que exige dar a volta), e é
|
|
260
|
-
* por isso que é recuo e não escolha. Mas é o que o guia já dizia antes desta mudança, e continuar a dizê-lo
|
|
261
|
-
* é estritamente melhor do que calar — calar afirmaria que não há alvo.
|
|
262
|
-
*/
|
|
263
|
-
function passosAteOAlvo(pl, alvo) {
|
|
264
|
-
const roleAt = ctx.roleAt;
|
|
265
|
-
if (roleAt) {
|
|
266
|
-
const rota = rotaAte({ topology: ctx.topology(), roleAt, orcamento: ORCAMENTO_DA_ROTA }, { x: pl.x, y: pl.y }, [alvo.at]);
|
|
267
|
-
if (rota)
|
|
268
|
-
return rota.passos;
|
|
269
|
-
}
|
|
270
|
-
return alvo.d;
|
|
271
|
-
}
|
|
272
|
-
/** Acende o grafo contínuo deste jogador. `null` = não deu (sem contexto, ou motor sem Web Audio). */
|
|
273
|
-
function ligarGuia(pl) {
|
|
274
|
-
const pc = playerCtx(pl);
|
|
275
|
-
const ac = pc ? pc.ac : ctx.getAudioCtx();
|
|
276
|
-
if (!ac)
|
|
277
|
-
return null;
|
|
278
|
-
try {
|
|
279
|
-
const osc = ac.createOscillator(), filtro = ac.createBiquadFilter(), ganho = ac.createGain();
|
|
280
|
-
osc.type = GUIA_TIPO;
|
|
281
|
-
osc.frequency.value = GUIA_HZ;
|
|
282
|
-
filtro.type = 'lowpass';
|
|
283
|
-
filtro.frequency.value = CORTE_LONGE; // nasce no fundo da escala e sobe; nascer aberto seria um susto
|
|
284
|
-
ganho.gain.value = 0; // e nasce calado, para não estalar ao ligar
|
|
285
|
-
let saida = ganho;
|
|
286
|
-
let panner = null;
|
|
287
|
-
if (ac.createStereoPanner) {
|
|
288
|
-
panner = ac.createStereoPanner();
|
|
289
|
-
ganho.connect(panner);
|
|
290
|
-
saida = panner;
|
|
291
|
-
}
|
|
292
|
-
osc.connect(filtro).connect(ganho);
|
|
293
|
-
saida.connect(pc ? pc.out : (ctx.catNode?.('guide') || ctx.audioOut?.() || ac.destination));
|
|
294
|
-
osc.start();
|
|
295
|
-
// `desdeARota` nasce no tecto para que a PRIMEIRA volta já meça a rota, em vez de soar doze quadros
|
|
296
|
-
// com um `passos` inventado.
|
|
297
|
-
return { ac, osc, filtro, ganho, panner, desdeARota: QUADROS_ENTRE_ROTAS, passos: PASSOS_ATE_O_FUNDO, pan: 0 };
|
|
298
|
-
}
|
|
299
|
-
catch (e) {
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
/**
|
|
304
|
-
* Apaga o grafo — e ele TEM de ser apagado, porque um oscilador que fica é a diferença entre esta forma e a
|
|
305
|
-
* anterior. O bipe morria sozinho ao fim de 0,12 s; este toca até alguém o parar. Sem esta função, desligar
|
|
306
|
-
* a categoria `guide` no mixer deixaria o som a tocar, e trocar de modo visual deixaria um segundo grafo a
|
|
307
|
-
* somar-se ao primeiro.
|
|
308
|
-
*
|
|
309
|
-
* Desce em rampa (não corta) porque um corte seco num oscilador vivo é um clique — um transiente, que é
|
|
310
|
-
* precisamente o que este item existe para tirar do ouvido da criança.
|
|
311
|
-
*/
|
|
312
|
-
function desligarGuia(pl) {
|
|
313
|
-
const g = pl._guia;
|
|
314
|
-
if (!g)
|
|
315
|
-
return;
|
|
316
|
-
pl._guia = null;
|
|
317
|
-
try {
|
|
318
|
-
const agora = g.ac.currentTime;
|
|
319
|
-
g.ganho.gain.setTargetAtTime(0, agora, 0.05);
|
|
320
|
-
g.osc.stop(agora + 0.3);
|
|
321
|
-
}
|
|
322
|
-
catch (e) { /* noop */ }
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* A PRESENÇA CONTÍNUA, um quadro de cada vez (#84 item 2).
|
|
326
|
-
*
|
|
327
|
-
* ⚠️ O QUE SAIU DAQUI FOI UM BIPE: um `triangle` de 0,12 s a cada 48 quadros, para sempre, independente de a
|
|
328
|
-
* criança se mexer ou de algo ter mudado. O veredicto do Dev: «um ping é a pior escolha possível, tenebroso
|
|
329
|
-
* para quem tem TEA». O que entra não dispara nada — o som já está lá, e muda de brilho.
|
|
330
|
-
*
|
|
331
|
-
* ⚠️ E CALAR CONTINUA A SER UMA AFIRMAÇÃO, com um significado só: NÃO HÁ ALVO. É por isso que «sem alvo»
|
|
332
|
-
* apaga o grafo e «longe» não: o piso do `guide-intensity` (`VOL_LONGE`) existe exactamente para que a
|
|
333
|
-
* criança não confunda «está longe» com «não há nada para achar».
|
|
334
|
-
*/
|
|
335
|
-
function updateGuide() {
|
|
336
|
-
const cat = ctx.getAudioCat();
|
|
337
|
-
const ligado = !!ctx.getAudioCtx() && ctx.getSoundOn() && !!cat && !!cat.guide && cat.guide.on;
|
|
338
|
-
const vol = ctx.getVolume ? ctx.getVolume() : 1;
|
|
339
|
-
for (const pl of ctx.getPlayers()) {
|
|
340
|
-
if (!ligado || !needsAudioCues(pl)) {
|
|
341
|
-
desligarGuia(pl);
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
let g = pl._guia;
|
|
345
|
-
if (!g) {
|
|
346
|
-
// ⚠️ A PERGUNTA «HÁ ALVO?» VEM ANTES DE ACENDER, e o gate cobrou-a: com o grafo a nascer primeiro, um
|
|
347
|
-
// jogador sem alvo criava um oscilador, media a rota, não achava nada e apagava-o — SESSENTA VEZES
|
|
348
|
-
// POR SEGUNDO. O bipe não tinha este problema porque não tinha nada que durasse; foi a permanência
|
|
349
|
-
// que o trouxe. `alvoMaisProximo` é um laço sobre `targetsOf`, não a BFS: perguntar por quadro custa
|
|
350
|
-
// zero quando a lista está vazia, que é exactamente o caso em questão.
|
|
351
|
-
if (!alvoMaisProximo(pl))
|
|
352
|
-
continue;
|
|
353
|
-
g = pl._guia = ligarGuia(pl);
|
|
354
|
-
if (!g)
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
if (++g.desdeARota >= QUADROS_ENTRE_ROTAS) {
|
|
358
|
-
g.desdeARota = 0;
|
|
359
|
-
const alvo = alvoMaisProximo(pl);
|
|
360
|
-
if (!alvo) {
|
|
361
|
-
desligarGuia(pl);
|
|
362
|
-
continue;
|
|
363
|
-
}
|
|
364
|
-
g.passos = passosAteOAlvo(pl, alvo);
|
|
365
|
-
g.pan = panFor(alvo.at.x, pl);
|
|
366
|
-
}
|
|
367
|
-
// TODO quadro, e não só quando a rota é nova: é isto que faz a mudança ser um deslize.
|
|
368
|
-
const i = intensidadeDoGuia(g.passos);
|
|
369
|
-
try {
|
|
370
|
-
const agora = g.ac.currentTime;
|
|
371
|
-
g.filtro.frequency.setTargetAtTime(i.corte, agora, TAU_DO_GUIA);
|
|
372
|
-
g.ganho.gain.setTargetAtTime(GUIA_VOL * i.volume * vol, agora, TAU_DO_GUIA);
|
|
373
|
-
g.panner?.pan.setTargetAtTime(g.pan, agora, TAU_DO_GUIA);
|
|
374
|
-
}
|
|
375
|
-
catch (e) { /* noop */ }
|
|
376
|
-
_guideCount++;
|
|
377
|
-
}
|
|
200
|
+
ctx.narrate(msg, pl.i);
|
|
378
201
|
}
|
|
379
202
|
return {
|
|
380
|
-
playerCtx, panFor, needsAudioCues, sonar,
|
|
203
|
+
playerCtx, panFor, needsAudioCues, sonar,
|
|
381
204
|
get sonarCount() { return _sonarCount; },
|
|
382
|
-
get guideCount() { return _guideCount; },
|
|
383
205
|
};
|
|
384
206
|
}
|