@the-inclusionist/engine 6.36.1
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/LICENSE +661 -0
- package/README.md +107 -0
- package/app/css/style.css +622 -0
- package/app/public/vendor/fonts/andika-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/andika-400.woff2 +0 -0
- package/app/public/vendor/fonts/andika-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/andika-700.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-400.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-700.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-mono-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/atkinson-mono-400.woff2 +0 -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/greatvibes-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/lexend-400-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-400.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-700-ext.woff2 +0 -0
- package/app/public/vendor/fonts/lexend-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/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/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/ufcook-700.woff2 +0 -0
- package/app/public/vendor/fonts/ufmag-400.woff2 +0 -0
- package/app/public/vendor/fonts.css +88 -0
- package/dist-pkg/boot/create-game.d.ts +159 -0
- package/dist-pkg/boot/create-game.js +266 -0
- package/dist-pkg/core/a11y-sr.d.ts +4 -0
- package/dist-pkg/core/a11y-sr.js +20 -0
- package/dist-pkg/core/actions.d.ts +100 -0
- package/dist-pkg/core/actions.js +149 -0
- package/dist-pkg/core/anel.d.ts +17 -0
- package/dist-pkg/core/anel.js +31 -0
- package/dist-pkg/core/collision.d.ts +21 -0
- package/dist-pkg/core/collision.js +62 -0
- package/dist-pkg/core/constants.d.ts +84 -0
- package/dist-pkg/core/constants.js +64 -0
- package/dist-pkg/core/contract.d.ts +227 -0
- package/dist-pkg/core/contract.js +184 -0
- package/dist-pkg/core/dom-query.d.ts +9 -0
- package/dist-pkg/core/dom-query.js +25 -0
- package/dist-pkg/core/entity.d.ts +150 -0
- package/dist-pkg/core/entity.js +38 -0
- package/dist-pkg/core/escape-html.d.ts +16 -0
- package/dist-pkg/core/escape-html.js +32 -0
- package/dist-pkg/core/i18n.d.ts +71 -0
- package/dist-pkg/core/i18n.js +236 -0
- package/dist-pkg/core/layers.d.ts +39 -0
- package/dist-pkg/core/layers.js +71 -0
- package/dist-pkg/core/letter-grid.d.ts +55 -0
- package/dist-pkg/core/letter-grid.js +116 -0
- package/dist-pkg/core/loop.d.ts +17 -0
- package/dist-pkg/core/loop.js +36 -0
- package/dist-pkg/core/password.d.ts +34 -0
- package/dist-pkg/core/password.js +205 -0
- package/dist-pkg/core/rng.d.ts +20 -0
- package/dist-pkg/core/rng.js +61 -0
- package/dist-pkg/core/rotulo-acessivel.d.ts +17 -0
- package/dist-pkg/core/rotulo-acessivel.js +41 -0
- package/dist-pkg/core/run-state.d.ts +115 -0
- package/dist-pkg/core/run-state.js +40 -0
- package/dist-pkg/core/scenes.d.ts +68 -0
- package/dist-pkg/core/scenes.js +64 -0
- package/dist-pkg/core/screens.d.ts +16 -0
- package/dist-pkg/core/screens.js +28 -0
- package/dist-pkg/core/state.d.ts +138 -0
- package/dist-pkg/core/state.js +290 -0
- package/dist-pkg/core/tiles.d.ts +12 -0
- package/dist-pkg/core/tiles.js +61 -0
- package/dist-pkg/core/world.d.ts +4 -0
- package/dist-pkg/core/world.js +58 -0
- package/dist-pkg/educational/activities-registry.d.ts +47 -0
- package/dist-pkg/educational/activities-registry.js +95 -0
- package/dist-pkg/i18n/en.d.ts +3 -0
- package/dist-pkg/i18n/en.js +560 -0
- package/dist-pkg/i18n/es.d.ts +3 -0
- package/dist-pkg/i18n/es.js +558 -0
- package/dist-pkg/i18n/pt.d.ts +3 -0
- package/dist-pkg/i18n/pt.js +618 -0
- package/dist-pkg/input/default-bindings.d.ts +24 -0
- package/dist-pkg/input/default-bindings.js +122 -0
- package/dist-pkg/input/devices.d.ts +15 -0
- package/dist-pkg/input/devices.js +31 -0
- package/dist-pkg/input/edges.d.ts +58 -0
- package/dist-pkg/input/edges.js +49 -0
- package/dist-pkg/input/gamepad.d.ts +203 -0
- package/dist-pkg/input/gamepad.js +531 -0
- package/dist-pkg/input/keyboard-runtime.d.ts +61 -0
- package/dist-pkg/input/keyboard-runtime.js +83 -0
- package/dist-pkg/input/keyboard.d.ts +45 -0
- package/dist-pkg/input/keyboard.js +80 -0
- package/dist-pkg/input/keydown.d.ts +270 -0
- package/dist-pkg/input/keydown.js +381 -0
- package/dist-pkg/input/latch.d.ts +30 -0
- package/dist-pkg/input/latch.js +63 -0
- package/dist-pkg/input/pointer-space.d.ts +40 -0
- package/dist-pkg/input/pointer-space.js +51 -0
- package/dist-pkg/input/state.d.ts +11 -0
- package/dist-pkg/input/state.js +12 -0
- package/dist-pkg/input/touch-bindings.d.ts +210 -0
- package/dist-pkg/input/touch-bindings.js +365 -0
- package/dist-pkg/input/touch.d.ts +173 -0
- package/dist-pkg/input/touch.js +314 -0
- package/dist-pkg/input/transports.d.ts +90 -0
- package/dist-pkg/input/transports.js +96 -0
- package/dist-pkg/input/vocabulary-migration.d.ts +58 -0
- package/dist-pkg/input/vocabulary-migration.js +125 -0
- package/dist-pkg/platform/audio-ambient.d.ts +27 -0
- package/dist-pkg/platform/audio-ambient.js +89 -0
- package/dist-pkg/platform/audio-earcons.d.ts +24 -0
- package/dist-pkg/platform/audio-earcons.js +62 -0
- package/dist-pkg/platform/audio-jingles.d.ts +17 -0
- package/dist-pkg/platform/audio-jingles.js +54 -0
- package/dist-pkg/platform/audio-mixer.d.ts +14 -0
- package/dist-pkg/platform/audio-mixer.js +62 -0
- package/dist-pkg/platform/audio-nav.d.ts +51 -0
- package/dist-pkg/platform/audio-nav.js +99 -0
- package/dist-pkg/platform/audio-sonar.d.ts +71 -0
- package/dist-pkg/platform/audio-sonar.js +173 -0
- package/dist-pkg/platform/audio.d.ts +32 -0
- package/dist-pkg/platform/audio.js +191 -0
- package/dist-pkg/platform/interruptible-speech.d.ts +19 -0
- package/dist-pkg/platform/interruptible-speech.js +79 -0
- package/dist-pkg/platform/speech.d.ts +2 -0
- package/dist-pkg/platform/speech.js +35 -0
- package/dist-pkg/platform/storage.d.ts +87 -0
- package/dist-pkg/platform/storage.js +148 -0
- package/dist-pkg/platform/tts.d.ts +33 -0
- package/dist-pkg/platform/tts.js +142 -0
- package/dist-pkg/render/camera.d.ts +58 -0
- package/dist-pkg/render/camera.js +105 -0
- package/dist-pkg/render/canvas.d.ts +13 -0
- package/dist-pkg/render/canvas.js +26 -0
- package/dist-pkg/render/cenario-data.d.ts +127 -0
- package/dist-pkg/render/cenario-data.js +145 -0
- package/dist-pkg/render/city-tex.d.ts +63 -0
- package/dist-pkg/render/city-tex.js +228 -0
- package/dist-pkg/render/city-tiles.d.ts +11 -0
- package/dist-pkg/render/city-tiles.js +140 -0
- package/dist-pkg/render/crt.d.ts +19 -0
- package/dist-pkg/render/crt.js +92 -0
- package/dist-pkg/render/cvd-matrices.d.ts +35 -0
- package/dist-pkg/render/cvd-matrices.js +91 -0
- package/dist-pkg/render/draw.d.ts +149 -0
- package/dist-pkg/render/draw.js +221 -0
- package/dist-pkg/render/fx.d.ts +63 -0
- package/dist-pkg/render/fx.js +123 -0
- package/dist-pkg/render/hc-role-data.d.ts +14 -0
- package/dist-pkg/render/hc-role-data.js +24 -0
- package/dist-pkg/render/high-contrast.d.ts +109 -0
- package/dist-pkg/render/high-contrast.js +254 -0
- package/dist-pkg/render/lq-filter.d.ts +37 -0
- package/dist-pkg/render/lq-filter.js +94 -0
- package/dist-pkg/render/minimap.d.ts +11 -0
- package/dist-pkg/render/minimap.js +94 -0
- package/dist-pkg/render/parallax.d.ts +85 -0
- package/dist-pkg/render/parallax.js +158 -0
- package/dist-pkg/render/player-anim.d.ts +71 -0
- package/dist-pkg/render/player-anim.js +152 -0
- package/dist-pkg/render/port.d.ts +143 -0
- package/dist-pkg/render/port.js +29 -0
- package/dist-pkg/render/recycling-tex.d.ts +48 -0
- package/dist-pkg/render/recycling-tex.js +164 -0
- package/dist-pkg/render/scene-city.d.ts +77 -0
- package/dist-pkg/render/scene-city.js +181 -0
- package/dist-pkg/render/scene-parallax.d.ts +72 -0
- package/dist-pkg/render/scene-parallax.js +426 -0
- package/dist-pkg/render/scene-sky.d.ts +126 -0
- package/dist-pkg/render/scene-sky.js +295 -0
- package/dist-pkg/render/screen-pipeline.d.ts +134 -0
- package/dist-pkg/render/screen-pipeline.js +177 -0
- package/dist-pkg/render/set-cenario.d.ts +54 -0
- package/dist-pkg/render/set-cenario.js +103 -0
- package/dist-pkg/render/sprite-fx.d.ts +3 -0
- package/dist-pkg/render/sprite-fx.js +40 -0
- package/dist-pkg/render/textures.d.ts +75 -0
- package/dist-pkg/render/textures.js +240 -0
- package/dist-pkg/render/title-scene.d.ts +46 -0
- package/dist-pkg/render/title-scene.js +75 -0
- package/dist-pkg/render/viewports.d.ts +52 -0
- package/dist-pkg/render/viewports.js +185 -0
- package/dist-pkg/render/viz-axes.d.ts +98 -0
- package/dist-pkg/render/viz-axes.js +184 -0
- package/dist-pkg/render/viz-modes.d.ts +61 -0
- package/dist-pkg/render/viz-modes.js +74 -0
- package/dist-pkg/render/viz-setters.d.ts +130 -0
- package/dist-pkg/render/viz-setters.js +244 -0
- package/dist-pkg/render/weather.d.ts +96 -0
- package/dist-pkg/render/weather.js +171 -0
- package/dist-pkg/render/wheelchair-sprites.d.ts +24 -0
- package/dist-pkg/render/wheelchair-sprites.js +63 -0
- package/dist-pkg/render/world-tex.d.ts +18 -0
- package/dist-pkg/render/world-tex.js +87 -0
- package/dist-pkg/ui/activities-menu.d.ts +258 -0
- package/dist-pkg/ui/activities-menu.js +648 -0
- package/dist-pkg/ui/caa-sets.d.ts +39 -0
- package/dist-pkg/ui/caa-sets.js +65 -0
- package/dist-pkg/ui/changed-mark.d.ts +15 -0
- package/dist-pkg/ui/changed-mark.js +96 -0
- package/dist-pkg/ui/debug-panel.d.ts +67 -0
- package/dist-pkg/ui/debug-panel.js +173 -0
- package/dist-pkg/ui/dom.d.ts +24 -0
- package/dist-pkg/ui/dom.js +47 -0
- package/dist-pkg/ui/focus-trap.d.ts +71 -0
- package/dist-pkg/ui/focus-trap.js +99 -0
- package/dist-pkg/ui/fonts.d.ts +41 -0
- package/dist-pkg/ui/fonts.js +59 -0
- package/dist-pkg/ui/hud.d.ts +137 -0
- package/dist-pkg/ui/hud.js +229 -0
- package/dist-pkg/ui/item-announcement.d.ts +19 -0
- package/dist-pkg/ui/item-announcement.js +36 -0
- package/dist-pkg/ui/layout.d.ts +6 -0
- package/dist-pkg/ui/layout.js +54 -0
- package/dist-pkg/ui/loop-crash.d.ts +19 -0
- package/dist-pkg/ui/loop-crash.js +60 -0
- package/dist-pkg/ui/map-hub.d.ts +56 -0
- package/dist-pkg/ui/map-hub.js +138 -0
- package/dist-pkg/ui/menu-nav.d.ts +141 -0
- package/dist-pkg/ui/menu-nav.js +390 -0
- package/dist-pkg/ui/pause-icons.d.ts +327 -0
- package/dist-pkg/ui/pause-icons.js +620 -0
- package/dist-pkg/ui/reach-notice.d.ts +34 -0
- package/dist-pkg/ui/reach-notice.js +71 -0
- package/dist-pkg/ui/settings-audio.d.ts +139 -0
- package/dist-pkg/ui/settings-audio.js +544 -0
- package/dist-pkg/ui/settings-caa.d.ts +45 -0
- package/dist-pkg/ui/settings-caa.js +137 -0
- package/dist-pkg/ui/settings-controls.d.ts +100 -0
- package/dist-pkg/ui/settings-controls.js +152 -0
- package/dist-pkg/ui/settings-empathy.d.ts +62 -0
- package/dist-pkg/ui/settings-empathy.js +137 -0
- package/dist-pkg/ui/settings-motion.d.ts +95 -0
- package/dist-pkg/ui/settings-motion.js +282 -0
- package/dist-pkg/ui/settings-motor.d.ts +77 -0
- package/dist-pkg/ui/settings-motor.js +215 -0
- package/dist-pkg/ui/settings-panel.d.ts +76 -0
- package/dist-pkg/ui/settings-panel.js +187 -0
- package/dist-pkg/ui/settings-typo.d.ts +74 -0
- package/dist-pkg/ui/settings-typo.js +150 -0
- package/dist-pkg/ui/settings-visual.d.ts +111 -0
- package/dist-pkg/ui/settings-visual.js +252 -0
- package/dist-pkg/ui/shell.d.ts +239 -0
- package/dist-pkg/ui/shell.js +430 -0
- package/dist-pkg/ui/title.d.ts +36 -0
- package/dist-pkg/ui/title.js +60 -0
- package/dist-pkg/ui/vlibras.d.ts +11 -0
- package/dist-pkg/ui/vlibras.js +87 -0
- package/dist-pkg/ui/webcam.d.ts +7 -0
- package/dist-pkg/ui/webcam.js +88 -0
- package/docs/CREDITS.md +64 -0
- package/docs/LICENSES.md +132 -0
- package/package.json +115 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
export const VIZ_MODES = [
|
|
3
|
+
{ key: 'normal', kind: 'normal', nome: 'viz.normal', desc: 'viz.desc.normal' },
|
|
4
|
+
{ key: 'hc-direto', kind: 'hcnew', nome: 'viz.hc-direto', desc: 'viz.desc.hc-direto' },
|
|
5
|
+
{ key: 'hc-direto-45', kind: 'hcnew', nome: 'viz.hc-direto-45', desc: 'viz.desc.hc-direto-45' },
|
|
6
|
+
{ key: 'hc-direto-7', kind: 'hcnew', nome: 'viz.hc-direto-7', desc: 'viz.desc.hc-direto-7' },
|
|
7
|
+
{ key: 'sim-deuter', sim: true, kind: 'filter', nome: 'viz.sim-deuter', desc: 'viz.desc.sim-deuter' },
|
|
8
|
+
{ key: 'sim-protan', sim: true, kind: 'filter', nome: 'viz.sim-protan', desc: 'viz.desc.sim-protan' },
|
|
9
|
+
{ key: 'sim-tritan', sim: true, kind: 'filter', nome: 'viz.sim-tritan', desc: 'viz.desc.sim-tritan' },
|
|
10
|
+
{ key: 'fix-protan', kind: 'filter', nome: 'viz.fix-protan', desc: 'viz.desc.fix-protan' },
|
|
11
|
+
{ key: 'fix-deuter', kind: 'filter', nome: 'viz.fix-deuter', desc: 'viz.desc.fix-deuter' },
|
|
12
|
+
{ key: 'fix-tritan', kind: 'filter', nome: 'viz.fix-tritan', desc: 'viz.desc.fix-tritan' },
|
|
13
|
+
{ key: 'lv-blur', sim: true, kind: 'lowvision', lv: 'blur', nome: 'viz.lv-blur', desc: 'viz.desc.lv-blur' },
|
|
14
|
+
{ key: 'lv-haze', sim: true, kind: 'lowvision', lv: 'haze', nome: 'viz.lv-haze', desc: 'viz.desc.lv-haze' },
|
|
15
|
+
{ key: 'lv-tunnel', sim: true, kind: 'lowvision', lv: 'tunnel', nome: 'viz.lv-tunnel', desc: 'viz.desc.lv-tunnel' },
|
|
16
|
+
{ key: 'lv-macular', sim: true, kind: 'lowvision', lv: 'macular', nome: 'viz.lv-macular', desc: 'viz.desc.lv-macular' },
|
|
17
|
+
{ key: 'lv-diabetic', sim: true, kind: 'lowvision', lv: 'diabetic', nome: 'viz.lv-diabetic', desc: 'viz.desc.lv-diabetic' },
|
|
18
|
+
{ key: 'blind', sim: true, kind: 'blind', nome: 'viz.blind', desc: 'viz.desc.blind' },
|
|
19
|
+
];
|
|
20
|
+
export const VIZ_BY_KEY = Object.fromEntries(VIZ_MODES.map((m) => [m.key, m]));
|
|
21
|
+
export const VIZ_FILTER = { 'sim-deuter': 'url(#cvd-deuter)', 'sim-protan': 'url(#cvd-protan)', 'sim-tritan': 'url(#cvd-tritan)',
|
|
22
|
+
'fix-protan': 'url(#cvd-fix-protan)', 'fix-deuter': 'url(#cvd-fix-deuter)', 'fix-tritan': 'url(#cvd-fix-tritan)',
|
|
23
|
+
'lv-blur': 'blur(2.4px)', 'lv-haze': 'contrast(.58) brightness(1.14) blur(.6px)', 'lv-tunnel': 'blur(.5px)', 'lv-macular': '', 'lv-diabetic': 'blur(.8px)', 'blind': 'brightness(0)' };
|
|
24
|
+
export const VIZ_CYCLE = VIZ_MODES.map((m) => m.key);
|
|
25
|
+
/**
|
|
26
|
+
* Este modo simula uma deficiência? Chave desconhecida (ou vazia) → false, porque a pergunta que o chamador
|
|
27
|
+
* está fazendo é "posso desligar isto sem tirar nada de ninguém?", e a resposta honesta diante do
|
|
28
|
+
* desconhecido é não.
|
|
29
|
+
*/
|
|
30
|
+
export function simulatesDisability(key) {
|
|
31
|
+
return VIZ_BY_KEY[key]?.sim === true;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* As CORREÇÕES de daltonismo: daltonizam a tela para quem TEM a condição. Derivadas do catálogo, nunca
|
|
35
|
+
* listadas à mão — são exatamente os filtros que não simulam.
|
|
36
|
+
*
|
|
37
|
+
* Existem como lista própria porque moram no menu de ACESSIBILIDADE VISUAL, e não no de empatia (decisão do
|
|
38
|
+
* Dev, issue #60). Ficaram anos no menu errado por um motivo que este arquivo agora conserta: `kind` não
|
|
39
|
+
* distinguia simular de corrigir, então o painel de empatia, que se recorta por `kind:'filter'`, arrastava as
|
|
40
|
+
* três junto. Dois públicos opostos na mesma lista — quem quer sentir como é ser daltônico e quem é.
|
|
41
|
+
*/
|
|
42
|
+
export const VIZ_CORRECTIONS = VIZ_MODES.filter((m) => m.kind === 'filter' && !m.sim);
|
|
43
|
+
/* ===================== AS DUAS PILHAS COM UM NOME SÓ (achado 8, item 19) ===================== */
|
|
44
|
+
//
|
|
45
|
+
// O segundo consumidor mediu, e a medição é o motivo desta seção existir:
|
|
46
|
+
//
|
|
47
|
+
// "O ALTO CONTRASTE NÃO VIAJA, e a razão é estrutural, não um defeito. Os modos `hcnew` REPINTAM
|
|
48
|
+
// TEXTURAS de tile na PIXI; um quiz não tem tiles, e não há o que repintar. Ou seja: o que o menu chama
|
|
49
|
+
// de 'acessibilidade visual' são DUAS pilhas com um nome só — uma de DOM/CSS (filtros de daltonismo,
|
|
50
|
+
// tipografia, caixa alta) que serve a qualquer jogo; uma de CANVAS (renderização direta, contornos,
|
|
51
|
+
// cores de papel) que só existe onde há mundo. O painel as apresenta numa lista única de 7 modos… A
|
|
52
|
+
// divisão do passo 5 precisa cortar AQUI."
|
|
53
|
+
//
|
|
54
|
+
// Este é o corte, e ele é de DADO e não de arquivo — os arquivos já estavam separados (`render/cvd-matrices`
|
|
55
|
+
// é DOM puro; `render/high-contrast` importa `core/collision.tileAt`). O que faltava era a tabela DIZER a
|
|
56
|
+
// qual pilha cada modo pertence, para que ninguém mais reconstruísse a resposta de cabeça.
|
|
57
|
+
//
|
|
58
|
+
// E era reconstruída: o segundo consumidor escrevia
|
|
59
|
+
// `VIZ_MODES.filter((m) => m.kind === 'normal' || (m.kind === 'filter' && !simulatesDisability(m.key)))`
|
|
60
|
+
// — uma expressão que mistura DUAS perguntas diferentes ("precisa de canvas?" e "isto simula deficiência?")
|
|
61
|
+
// e que todo consumidor futuro teria de reinventar, com a chance de acertar uma e errar a outra.
|
|
62
|
+
/** Este modo precisa de um CANVAS de mundo para existir? Só os `hcnew` precisam: eles repintam texturas. */
|
|
63
|
+
export function needsCanvas(key) {
|
|
64
|
+
return VIZ_BY_KEY[key]?.kind === 'hcnew';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Os modos que funcionam em QUALQUER jogo — os que se aplicam como filtro de CSS sobre um elemento.
|
|
68
|
+
*
|
|
69
|
+
* Derivada, nunca listada à mão: um modo novo entra na pilha certa por causa do `kind` que ele declara, e não
|
|
70
|
+
* porque alguém lembrou de acrescentá-lo aqui. É a mesma regra de `VIZ_CORRECTIONS`.
|
|
71
|
+
*/
|
|
72
|
+
export const VIZ_DOM_ONLY = VIZ_MODES.filter((m) => !needsCanvas(m.key));
|
|
73
|
+
/** Os modos que EXIGEM mundo. Complemento exato de `VIZ_DOM_ONLY` — juntos, os 16, sem sobra nem repetição. */
|
|
74
|
+
export const VIZ_CANVAS_ONLY = VIZ_MODES.filter((m) => needsCanvas(m.key));
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import { type VizMode } from './viz-modes.js';
|
|
3
|
+
import type { DomQuery } from '../core/dom-query.js';
|
|
4
|
+
import type { ComFiltro, ComTextura, Visivel, DesenhoComCirculo, AplicarFiltroCss, AlcanceDoFiltro, AplicarAltoContrasteNoDom } from './port.js';
|
|
5
|
+
/**
|
|
6
|
+
* Até onde o filtro deste modo vai. MELHORIA alcança os menus; EMPATIA fica no mundo (ver `AlcanceDoFiltro`).
|
|
7
|
+
* Derivado de `sim`, do catálogo — a mesma flag que já distingue os dois, e não uma segunda lista para
|
|
8
|
+
* alguém esquecer de atualizar.
|
|
9
|
+
*/
|
|
10
|
+
export declare function alcanceDoModo(mode: string): AlcanceDoFiltro;
|
|
11
|
+
/** Modo por chave, com o fallback do original: chave desconhecida (ou nula) CAI em `normal`. */
|
|
12
|
+
export declare function resolveViz(key: string | null | undefined): VizMode;
|
|
13
|
+
/** É um dos três níveis de Renderização Direta (alto contraste)? Mesmo teste do original: `!!DIRECT_CFG[mode]`. */
|
|
14
|
+
export declare function isDirectMode(mode: string): boolean;
|
|
15
|
+
/** Filtro CSS da canvas no SOLO: simulação/correção de visão + realce L→Q, compostos e sem vazios. */
|
|
16
|
+
export declare function cssFilterFor(mode: string, lq: string): string;
|
|
17
|
+
/** Bolinha indicadora de um viewport: só cegueira (branca) e baixa visão (verde) acendem. */
|
|
18
|
+
export declare function vizDotFor(m: VizMode | undefined): {
|
|
19
|
+
visible: boolean;
|
|
20
|
+
fill: number | null;
|
|
21
|
+
};
|
|
22
|
+
/** Bolinha GLOBAL (#viz-indicator) para um `kind`: visível, classes e rótulo de leitor de tela. */
|
|
23
|
+
export declare function vizIndicatorFor(kind: string): {
|
|
24
|
+
on: boolean;
|
|
25
|
+
blind: boolean;
|
|
26
|
+
low: boolean;
|
|
27
|
+
label: string;
|
|
28
|
+
};
|
|
29
|
+
/** Classe do overlay DOM de baixa visão (`lv-haze`/`lv-tunnel`/…); '' para qualquer outro kind. */
|
|
30
|
+
export declare function lvOverlayClassFor(m: VizMode): string;
|
|
31
|
+
/** HTML do grupo de rádios de modos visuais (uma linha por modo; o atual marcado). Verbatim do game.js. */
|
|
32
|
+
export declare function vizGroupHtml(modes: readonly VizMode[], cur: string): string;
|
|
33
|
+
/** Fala do leitor de tela ao escolher um modo: prefixa "Jogador N:" só em multi-tela. */
|
|
34
|
+
export declare function vizGroupSay(numPlayers: number, sel: number, nome: string): string;
|
|
35
|
+
type Filtered = ComFiltro;
|
|
36
|
+
type Textured = ComTextura;
|
|
37
|
+
/** PIXI.Graphics da bolinha por viewport — só o que updateVpDots realmente usa. */
|
|
38
|
+
type DotGfx = Visivel & DesenhoComCirculo;
|
|
39
|
+
interface ClassListHost {
|
|
40
|
+
classList: {
|
|
41
|
+
toggle(token: string, force?: boolean): unknown;
|
|
42
|
+
remove(...tokens: string[]): unknown;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
interface Pl {
|
|
46
|
+
viz: string;
|
|
47
|
+
sprite?: Textured | null;
|
|
48
|
+
_tx?: unknown;
|
|
49
|
+
}
|
|
50
|
+
interface Pu {
|
|
51
|
+
kind: string;
|
|
52
|
+
sprite?: Textured | null;
|
|
53
|
+
}
|
|
54
|
+
export interface VizSettersCtx {
|
|
55
|
+
/** O seletor do jogo (#viz-overlay, #viz-indicator, listas do painel). `DomQuery` de `core/dom-query`
|
|
56
|
+
* desde 2026-08-26: a versão local era NÃO-GENÉRICA, e uma função genérica atribuída a uma
|
|
57
|
+
* assinatura não-genérica é instanciada pela RESTRIÇÃO. O `El` estrutural continua abaixo — ele é a
|
|
58
|
+
* fatia que este módulo LÊ, e `HTMLElement` a satisfaz. */
|
|
59
|
+
$: DomQuery;
|
|
60
|
+
body: ClassListHost;
|
|
61
|
+
srSay: (s: string) => void;
|
|
62
|
+
aplicarFiltroCss: AplicarFiltroCss;
|
|
63
|
+
/** Alto contraste no DOM — o filtro não o alcança porque ele não É filtro. Issue #83. */
|
|
64
|
+
aplicarAltoContrasteNoDom: AplicarAltoContrasteNoDom;
|
|
65
|
+
camera: Filtered;
|
|
66
|
+
worldSprite: Textured;
|
|
67
|
+
parallaxLayers: Textured[];
|
|
68
|
+
decoSprites: Textured[];
|
|
69
|
+
getVpSpr: () => Filtered[];
|
|
70
|
+
getVpDots: () => DotGfx[];
|
|
71
|
+
/**
|
|
72
|
+
* Os sprites dos ITENS declarados (o array vive no jogo e pode ser recriado — por isso getter).
|
|
73
|
+
*
|
|
74
|
+
* Era `getCoinSprites`, e o nome dizia o que eles são. Mesma fatia que `render/draw` recebe desde o corte
|
|
75
|
+
* das entidades declaradas: uma lista de sprites, sem o desenho saber o que cada um representa.
|
|
76
|
+
*/
|
|
77
|
+
getItemSprites: () => (Textured | null | undefined)[];
|
|
78
|
+
/**
|
|
79
|
+
* Como o JOGO chama os itens dele no cache de recoloração de `render/high-contrast`.
|
|
80
|
+
*
|
|
81
|
+
* Era `spriteTexFor('coin', mode)` — a string cravada aqui dentro. O cache já não tinha forma de moeda
|
|
82
|
+
* (ele chaveia por `(id, modo)`); quem ainda nomeava uma era este módulo. Repare no vizinho de baixo: os
|
|
83
|
+
* power-ups sempre carregaram o próprio `kind`, e a engine só o repassa. Os itens não carregavam nada, e
|
|
84
|
+
* por isso o nome tinha de estar em algum lugar — agora está do lado de quem o escolheu.
|
|
85
|
+
*/
|
|
86
|
+
itemTexId: string;
|
|
87
|
+
getPowerups: () => readonly Pu[];
|
|
88
|
+
getPlayers: () => Pl[];
|
|
89
|
+
getNumPlayers: () => number;
|
|
90
|
+
getSelVizPlayer: () => number;
|
|
91
|
+
setSelVizPlayer: (i: number) => void;
|
|
92
|
+
getSharedViz: () => string | null;
|
|
93
|
+
setSharedViz: (mode: string) => void;
|
|
94
|
+
invalidateSharedViz: () => void;
|
|
95
|
+
parallaxTexFor: (i: number, mode: string) => unknown;
|
|
96
|
+
treeTexFor: (mode: string) => unknown;
|
|
97
|
+
playerVizTex: (base: unknown, mode: string) => unknown;
|
|
98
|
+
pixiFilterFor: (mode: string) => unknown;
|
|
99
|
+
clearPlayerDirectCache: () => void;
|
|
100
|
+
setFrontDim: (on: boolean) => void;
|
|
101
|
+
rebuildExtras: () => void;
|
|
102
|
+
rebuildCoins: () => void;
|
|
103
|
+
setModoCego: (on: boolean) => void;
|
|
104
|
+
hideTouchControls: (reason?: string) => void;
|
|
105
|
+
reflectVizButtons: () => void;
|
|
106
|
+
renderVisualPanel: () => void;
|
|
107
|
+
renderEmpathyPanel: () => void;
|
|
108
|
+
}
|
|
109
|
+
export interface VizSettersApi {
|
|
110
|
+
/** Multi-tela: aplica as texturas ESTÁTICAS do modo (memoizado) + a do quadro atual de cada jogador. */
|
|
111
|
+
applySharedTextures(mode: string): void;
|
|
112
|
+
/** Bolinhas indicadoras por viewport (fora do filtro do viewport — visíveis mesmo em cegueira). */
|
|
113
|
+
updateVpDots(): void;
|
|
114
|
+
/** Filtro PIXI de cada viewport = modo do jogador daquela tela. */
|
|
115
|
+
applyVpFilters(): void;
|
|
116
|
+
/** Troca o modo de UM jogador: persiste, invalida o render estático e reaplica pelo caminho certo. */
|
|
117
|
+
setPlayerViz(i: number, mode: string): void;
|
|
118
|
+
/** Caminho SOLO: filtro CSS na canvas + texturas globais + overlay DOM + bolinha. */
|
|
119
|
+
applyVizGlobal(mode: string): void;
|
|
120
|
+
/** Reaplica tudo depois de uma mudança estrutural (cenário, nº de telas). */
|
|
121
|
+
reapplyVizAll(): void;
|
|
122
|
+
/** Bolinha global (#viz-indicator) para um `kind`. */
|
|
123
|
+
updateVizIndicator(kind: string): void;
|
|
124
|
+
/** Invalida os caches de textura direta (mundo/moeda/power-up/jogador) e re-renderiza. */
|
|
125
|
+
rebakeDirect(): void;
|
|
126
|
+
/** Grupo de rádios de modos visuais nos painéis (visual/empatia). */
|
|
127
|
+
renderVizGroup(listSel: string, tabsSel: string, modes: readonly VizMode[]): void;
|
|
128
|
+
}
|
|
129
|
+
export declare function initVizSetters(ctx: VizSettersCtx): VizSettersApi;
|
|
130
|
+
export {};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// render/viz-setters — APLICAÇÃO dos modos de visão acessível (daltonismo, baixa visão, cegueira, alto
|
|
3
|
+
// contraste), por jogador e globalmente. Extraído verbatim do game.js. É a camada de POLÍTICA — "qual modo
|
|
4
|
+
// vale onde" — e não a de FÁBRICA: quem constrói pixel (pixiFilterFor / parallaxTexFor / playerVizTex /
|
|
5
|
+
// lvOverlayTex / renderVpOverlay) fica no game.js e sai depois em `render/viewports` (grupo B); esses quatro
|
|
6
|
+
// entram AQUI por injeção. Ver docs/5-Refactoring/plano-modularizacao-mapa.md (A16/B2).
|
|
7
|
+
//
|
|
8
|
+
// Fronteiras que este módulo NÃO reabre:
|
|
9
|
+
// · `_lastSharedViz` FICA no game.js — não é cache de visão, é o registro de qual modo o pipeline de render
|
|
10
|
+
// ESTÁTICO aplicou por último, escrito de cinco lugares (rebuildCoins/rebuildExtras/applySharedTextures/
|
|
11
|
+
// setPlayerViz/reapplyVizAll). Entra por `getSharedViz`/`setSharedViz`/`invalidateSharedViz`.
|
|
12
|
+
// · `selVizPlayer` idem: quatro escritores (renderVizGroup, aba de jogador, ui/settings-visual, menu de
|
|
13
|
+
// pausa) → get/set por ctx, o `let` continua no game.js até o D1.
|
|
14
|
+
// · `_playerDirect` é `let` do game.js reatribuído por estas funções → clear por ctx
|
|
15
|
+
// (binding importado não pode ser reatribuído).
|
|
16
|
+
//
|
|
17
|
+
// As camadas e sprites PIXI (camera/worldSprite/parallaxLayers/decoSprites/vpSpr/vpDots) são CRIADOS no
|
|
18
|
+
// game.js — a ordem de addChild é a ordem de desenho — e entram injetados por interface ESTRUTURAL, para o
|
|
19
|
+
// módulo rodar no project `node` sem importar PIXI. Mesmo precedente de render/scene-sky e game/traffic.
|
|
20
|
+
// SEM I/O no import: initVizSetters(ctx) só fecha closures, não chama nada.
|
|
21
|
+
import { VIZ_MODES, VIZ_BY_KEY, VIZ_FILTER, simulatesDisability } from './viz-modes.js';
|
|
22
|
+
import { t } from '../core/i18n.js'; // VIZ_MODES guarda CHAVE i18n desde o item 14; quem exibe resolve
|
|
23
|
+
import { DIRECT_CFG, worldTexFor, spriteTexFor, clearWorldTexCache, clearSpriteTexCache } from './high-contrast.js';
|
|
24
|
+
import { pupTexFor, resetPupTexCache } from './textures.js';
|
|
25
|
+
import { lqFilter } from './lq-filter.js';
|
|
26
|
+
import { setVizModeValue } from '../core/state.js';
|
|
27
|
+
import * as store from '../platform/storage.js';
|
|
28
|
+
/* ===================== PURO (sem PIXI, sem DOM) — o que rende teste de verdade ===================== */
|
|
29
|
+
/**
|
|
30
|
+
* Até onde o filtro deste modo vai. MELHORIA alcança os menus; EMPATIA fica no mundo (ver `AlcanceDoFiltro`).
|
|
31
|
+
* Derivado de `sim`, do catálogo — a mesma flag que já distingue os dois, e não uma segunda lista para
|
|
32
|
+
* alguém esquecer de atualizar.
|
|
33
|
+
*/
|
|
34
|
+
export function alcanceDoModo(mode) {
|
|
35
|
+
return simulatesDisability(mode) ? 'mundo' : 'mundo-e-menus';
|
|
36
|
+
}
|
|
37
|
+
/** Modo por chave, com o fallback do original: chave desconhecida (ou nula) CAI em `normal`. */
|
|
38
|
+
export function resolveViz(key) {
|
|
39
|
+
return VIZ_BY_KEY[key] || VIZ_BY_KEY.normal;
|
|
40
|
+
}
|
|
41
|
+
/** É um dos três níveis de Renderização Direta (alto contraste)? Mesmo teste do original: `!!DIRECT_CFG[mode]`. */
|
|
42
|
+
export function isDirectMode(mode) { return !!DIRECT_CFG[mode]; }
|
|
43
|
+
/** Filtro CSS da canvas no SOLO: simulação/correção de visão + realce L→Q, compostos e sem vazios. */
|
|
44
|
+
export function cssFilterFor(mode, lq) {
|
|
45
|
+
return [VIZ_FILTER[mode] || '', lq].filter(Boolean).join(' ');
|
|
46
|
+
}
|
|
47
|
+
/** Bolinha indicadora de um viewport: só cegueira (branca) e baixa visão (verde) acendem. */
|
|
48
|
+
export function vizDotFor(m) {
|
|
49
|
+
const on = !!m && (m.kind === 'blind' || m.kind === 'lowvision');
|
|
50
|
+
return { visible: on, fill: on ? (m.kind === 'blind' ? 0xffffff : 0x36d36a) : null };
|
|
51
|
+
}
|
|
52
|
+
/** Bolinha GLOBAL (#viz-indicator) para um `kind`: visível, classes e rótulo de leitor de tela. */
|
|
53
|
+
export function vizIndicatorFor(kind) {
|
|
54
|
+
return {
|
|
55
|
+
on: kind === 'blind' || kind === 'lowvision',
|
|
56
|
+
blind: kind === 'blind', low: kind === 'lowvision',
|
|
57
|
+
label: (kind === 'blind' ? 'Modo cegueira total' : 'Modo baixa visão') + '. Toque duas vezes para voltar às cores normais.',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Classe do overlay DOM de baixa visão (`lv-haze`/`lv-tunnel`/…); '' para qualquer outro kind. */
|
|
61
|
+
export function lvOverlayClassFor(m) {
|
|
62
|
+
return m.kind === 'lowvision' ? 'lv-' + m.lv : '';
|
|
63
|
+
}
|
|
64
|
+
/** HTML do grupo de rádios de modos visuais (uma linha por modo; o atual marcado). Verbatim do game.js. */
|
|
65
|
+
export function vizGroupHtml(modes, cur) {
|
|
66
|
+
return modes.map((m) => {
|
|
67
|
+
const sel = m.key === cur;
|
|
68
|
+
return `<div class="ctrl-row"><span><strong>${t(m.nome)}</strong><br><span class="opt-hint" style="margin:0">${t(m.desc)}</span></span>`
|
|
69
|
+
+ `<button class="mode-btn${sel ? ' is-on' : ''}" role="radio" aria-checked="${sel}" data-viz="${m.key}" type="button">${sel ? '✓ Selecionado' : 'Selecionar'}</button></div>`;
|
|
70
|
+
}).join('');
|
|
71
|
+
}
|
|
72
|
+
/** Fala do leitor de tela ao escolher um modo: prefixa "Jogador N:" só em multi-tela. */
|
|
73
|
+
export function vizGroupSay(numPlayers, sel, nome) {
|
|
74
|
+
return (numPlayers > 1 ? 'Jogador ' + (sel + 1) + ': ' : '') + nome + '.';
|
|
75
|
+
}
|
|
76
|
+
export function initVizSetters(ctx) {
|
|
77
|
+
// estáticos (mundo/parallax/moedas/itens) só re-aplicam quando o modo muda (_lastSharedViz mora no game.js)
|
|
78
|
+
function applySharedTextures(mode) {
|
|
79
|
+
if (mode !== ctx.getSharedViz()) {
|
|
80
|
+
ctx.setSharedViz(mode);
|
|
81
|
+
ctx.setFrontDim(!!DIRECT_CFG[mode]); // HC: carros/placas/semáforo (frente) escurecem como fundo
|
|
82
|
+
ctx.worldSprite.texture = worldTexFor(mode);
|
|
83
|
+
ctx.parallaxLayers.forEach((ts, j) => { ts.texture = ctx.parallaxTexFor(j, mode); });
|
|
84
|
+
ctx.decoSprites.forEach((s) => { s.texture = ctx.treeTexFor(mode); });
|
|
85
|
+
for (const s of ctx.getItemSprites()) {
|
|
86
|
+
if (s)
|
|
87
|
+
s.texture = spriteTexFor(ctx.itemTexId, mode);
|
|
88
|
+
}
|
|
89
|
+
for (const pu of ctx.getPowerups()) {
|
|
90
|
+
if (pu.sprite)
|
|
91
|
+
pu.sprite.texture = pupTexFor(pu.kind, mode);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (const pl of ctx.getPlayers()) {
|
|
95
|
+
if (pl.sprite && pl._tx)
|
|
96
|
+
pl.sprite.texture = ctx.playerVizTex(pl._tx, mode);
|
|
97
|
+
} // player muda de quadro toda frame
|
|
98
|
+
}
|
|
99
|
+
// bolinhas indicadoras por viewport (sobre os sprites de saída → NÃO sofrem o filtro do viewport, ex. cegueira)
|
|
100
|
+
function updateVpDots() {
|
|
101
|
+
const dots = ctx.getVpDots(), players = ctx.getPlayers();
|
|
102
|
+
for (let i = 0; i < dots.length; i++) {
|
|
103
|
+
const g = dots[i], m = VIZ_BY_KEY[(players[i] && players[i].viz)];
|
|
104
|
+
if (!g)
|
|
105
|
+
continue;
|
|
106
|
+
const d = vizDotFor(m);
|
|
107
|
+
g.visible = d.visible;
|
|
108
|
+
if (d.visible) {
|
|
109
|
+
g.clear();
|
|
110
|
+
g.lineStyle(1, 0x000000, .6);
|
|
111
|
+
g.beginFill(d.fill);
|
|
112
|
+
g.drawCircle(0, 0, 5);
|
|
113
|
+
g.endFill();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function applyVpFilters() {
|
|
118
|
+
const spr = ctx.getVpSpr(), players = ctx.getPlayers();
|
|
119
|
+
for (let i = 0; i < ctx.getNumPlayers(); i++) {
|
|
120
|
+
if (spr[i])
|
|
121
|
+
spr[i].filters = ctx.pixiFilterFor(players[i].viz);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function setPlayerViz(i, mode) {
|
|
125
|
+
const m = resolveViz(mode);
|
|
126
|
+
ctx.getPlayers()[i].viz = m.key;
|
|
127
|
+
store.set(store.KEYS.vizP(i), m.key);
|
|
128
|
+
ctx.invalidateSharedViz();
|
|
129
|
+
if (m.kind === 'blind')
|
|
130
|
+
ctx.setModoCego(true); // empatia cegueira total liga o modo cego (áudio) por padrão
|
|
131
|
+
if (ctx.getNumPlayers() <= 1 && i === 0) {
|
|
132
|
+
applyVizGlobal(m.key);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
applyVpFilters();
|
|
136
|
+
updateVpDots();
|
|
137
|
+
}
|
|
138
|
+
ctx.reflectVizButtons();
|
|
139
|
+
ctx.renderVisualPanel();
|
|
140
|
+
ctx.renderEmpathyPanel();
|
|
141
|
+
}
|
|
142
|
+
function applyVizGlobal(mode) {
|
|
143
|
+
const m = resolveViz(mode);
|
|
144
|
+
mode = m.key;
|
|
145
|
+
setVizModeValue(mode); // core/state: valor + persistência (incl_viz) + evento
|
|
146
|
+
// ANTES daqui saía também `ctx.setHcMode(m.kind === 'hcnew')`, alimentando um `let hcMode` no game.js cujo
|
|
147
|
+
// único leitor era o gancho window.__incl. Era `vizMode` reescrito com outro nome: derivar de VIZ_BY_KEY
|
|
148
|
+
// custa uma comparação e não pode divergir. (O inicializador daquele `let` usava OUTRA fórmula,
|
|
149
|
+
// `vizMode!=='normal'`, e discordava do setter — sem efeito, porque applyVizGlobal roda no boot antes de
|
|
150
|
+
// o gancho existir, mas é o sintoma clássico de cópia de estado.)
|
|
151
|
+
ctx.aplicarFiltroCss(cssFilterFor(mode, lqFilter()), alcanceDoModo(mode));
|
|
152
|
+
ctx.aplicarAltoContrasteNoDom(m.kind === 'hcnew'); // não é filtro: ver `AplicarAltoContrasteNoDom` // sim. daltonismo/baixa-visão/cegueira + realce L/Q compostos
|
|
153
|
+
ctx.camera.filters = (m.kind === 'hcnew') ? ctx.pixiFilterFor(mode) : null; // solo: alto contraste experimental = filtro GPU na câmera
|
|
154
|
+
ctx.setFrontDim(!!DIRECT_CFG[mode]); // HC: frente (carros/placas/semáforo) escurece como fundo
|
|
155
|
+
ctx.worldSprite.texture = worldTexFor(mode); // alto contraste direto = Renderização Direta · resto=normal
|
|
156
|
+
ctx.parallaxLayers.forEach((ts, i) => { ts.texture = ctx.parallaxTexFor(i, mode); });
|
|
157
|
+
ctx.decoSprites.forEach((s) => { s.texture = ctx.treeTexFor(mode); });
|
|
158
|
+
ctx.rebuildExtras();
|
|
159
|
+
ctx.rebuildCoins();
|
|
160
|
+
// baixa visão = névoa+manchas (overlay) + bolinha verde; cegueira = tela preta (filtro) + esconde controles + bolinha branca
|
|
161
|
+
ctx.body.classList.toggle('lowvision-mode', m.kind === 'lowvision');
|
|
162
|
+
ctx.body.classList.toggle('blind-mode', m.kind === 'blind');
|
|
163
|
+
const ov = ctx.$('#viz-overlay');
|
|
164
|
+
if (ov) {
|
|
165
|
+
ov.hidden = (m.kind !== 'lowvision');
|
|
166
|
+
ov.className = lvOverlayClassFor(m);
|
|
167
|
+
}
|
|
168
|
+
if (m.kind === 'blind') {
|
|
169
|
+
ctx.hideTouchControls('cegueira');
|
|
170
|
+
}
|
|
171
|
+
updateVizIndicator(m.kind);
|
|
172
|
+
ctx.reflectVizButtons(); // (a guarda `typeof ...==='function'` do original morreu: era declaração de função, sempre verdadeira)
|
|
173
|
+
ctx.renderVisualPanel();
|
|
174
|
+
ctx.renderEmpathyPanel();
|
|
175
|
+
}
|
|
176
|
+
// bolinha indicadora (canto sup. dir.): branca=cegueira, verde=baixa visão; toque/clique 2× volta ao normal
|
|
177
|
+
function updateVizIndicator(kind) {
|
|
178
|
+
const el = ctx.$('#viz-indicator');
|
|
179
|
+
if (!el)
|
|
180
|
+
return;
|
|
181
|
+
const s = vizIndicatorFor(kind);
|
|
182
|
+
el.hidden = !s.on;
|
|
183
|
+
el.classList.toggle('blind', s.blind);
|
|
184
|
+
el.classList.toggle('low', s.low);
|
|
185
|
+
el.setAttribute('aria-label', s.label);
|
|
186
|
+
}
|
|
187
|
+
// MP: filtro CSS/overlay/bolinha globais OFF (por viewport agora)
|
|
188
|
+
function reapplyVizAll() {
|
|
189
|
+
ctx.invalidateSharedViz();
|
|
190
|
+
if (ctx.getNumPlayers() <= 1) {
|
|
191
|
+
applyVizGlobal(ctx.getPlayers()[0].viz);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
ctx.aplicarFiltroCss(lqFilter(), 'mundo-e-menus'); // realce L/Q é melhoria: alcança o menu
|
|
195
|
+
ctx.camera.filters = null;
|
|
196
|
+
ctx.body.classList.remove('lowvision-mode', 'blind-mode');
|
|
197
|
+
const ov = ctx.$('#viz-overlay');
|
|
198
|
+
if (ov)
|
|
199
|
+
ov.hidden = true;
|
|
200
|
+
updateVizIndicator('normal');
|
|
201
|
+
applyVpFilters();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// invalida os caches de textura direta (mundo depende de bg; sprites de fg) e re-renderiza
|
|
205
|
+
function rebakeDirect() {
|
|
206
|
+
clearWorldTexCache();
|
|
207
|
+
clearSpriteTexCache();
|
|
208
|
+
resetPupTexCache();
|
|
209
|
+
ctx.clearPlayerDirectCache();
|
|
210
|
+
ctx.invalidateSharedViz();
|
|
211
|
+
if (ctx.getNumPlayers() <= 1)
|
|
212
|
+
applyVizGlobal(ctx.getPlayers()[0].viz);
|
|
213
|
+
else
|
|
214
|
+
applyVpFilters();
|
|
215
|
+
}
|
|
216
|
+
function renderVizGroup(listSel, tabsSel, modes) {
|
|
217
|
+
const el = ctx.$(listSel);
|
|
218
|
+
if (!el)
|
|
219
|
+
return;
|
|
220
|
+
if (ctx.getSelVizPlayer() >= ctx.getNumPlayers())
|
|
221
|
+
ctx.setSelVizPlayer(0);
|
|
222
|
+
const tabs = ctx.$(tabsSel);
|
|
223
|
+
if (tabs) {
|
|
224
|
+
tabs.hidden = true; // E3: sem abas — cada jogador edita só o seu
|
|
225
|
+
tabs.innerHTML = '';
|
|
226
|
+
// NOTA (verbatim do original): o innerHTML acima já esvaziou `tabs`, então este querySelectorAll não
|
|
227
|
+
// acha nada e o listener nunca é ligado. Preservado como estava — ver relatório da extração.
|
|
228
|
+
tabs.querySelectorAll('button[data-vp]').forEach((b) => b.addEventListener('click', () => {
|
|
229
|
+
ctx.setSelVizPlayer(+b.dataset.vp);
|
|
230
|
+
ctx.renderVisualPanel();
|
|
231
|
+
ctx.renderEmpathyPanel();
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
const players = ctx.getPlayers(), sel = ctx.getSelVizPlayer();
|
|
235
|
+
const cur = players[sel] ? players[sel].viz : 'normal';
|
|
236
|
+
el.innerHTML = vizGroupHtml(modes, cur);
|
|
237
|
+
el.querySelectorAll('button[data-viz]').forEach((btn) => btn.addEventListener('click', () => {
|
|
238
|
+
const key = btn.dataset.viz;
|
|
239
|
+
setPlayerViz(ctx.getSelVizPlayer(), key);
|
|
240
|
+
ctx.srSay(vizGroupSay(ctx.getNumPlayers(), ctx.getSelVizPlayer(), t(VIZ_MODES.find((m) => m.key === key).nome)));
|
|
241
|
+
}));
|
|
242
|
+
}
|
|
243
|
+
return { applySharedTextures, updateVpDots, applyVpFilters, setPlayerViz, applyVizGlobal, reapplyVizAll, updateVizIndicator, rebakeDirect, renderVizGroup };
|
|
244
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { DesenhoComLinha } from './port.js';
|
|
3
|
+
/** A single rain drop's screen-space position + falling speed. */
|
|
4
|
+
export interface RainDrop {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
len: number;
|
|
8
|
+
spd: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* L5 (rotina do José): tempo bom nos primeiros 30s; depois LOOP de 60s = garoa 5s → chuva 5s → garoa 5s → bom 45s.
|
|
12
|
+
* Skipped when scene decor is reduced-motion.
|
|
13
|
+
*
|
|
14
|
+
* QUEM TEM CHUVA É DADO DO TEMA (`CENARIOS[...].chuva`), e não uma condição escrita aqui. Era
|
|
15
|
+
* `cenario === 'cidade'` — verdade enquanto a Cidade era o único tema com chuva, e mentira no dia em que o Dev
|
|
16
|
+
* pediu chuva na Floresta. O defeito de uma condição dessas não é estar errada, é ser INVISÍVEL de onde a
|
|
17
|
+
* pessoa procura: quem abre a tabela de cenários para dar chuva a um tema novo não encontra nada para mudar.
|
|
18
|
+
*
|
|
19
|
+
* @param sec elapsed weather-clock time, in seconds
|
|
20
|
+
* @param temChuva true when the active theme declares `chuva`
|
|
21
|
+
* @param reduceDecor true when reduced-motion scene decor (rm.decor) is on
|
|
22
|
+
* @returns target rain level: 0 (dry), 0.35 (garoa) or 1 (chuva)
|
|
23
|
+
*/
|
|
24
|
+
export declare function rainLevelTarget(sec: number, temChuva: boolean, reduceDecor: boolean): number;
|
|
25
|
+
/** Onde estamos DENTRO do ciclo de 60s, em segundos. 0 = a primeira gota; 59 = um segundo antes dela. */
|
|
26
|
+
export declare function faseDoClima(sec: number): number;
|
|
27
|
+
/**
|
|
28
|
+
* AGLOMERAÇÃO DAS NUVENS: 0 = espalhadas e altas, com o céu aparecendo entre elas; 1 = fechadas numa manta.
|
|
29
|
+
*
|
|
30
|
+
* O pedido do Dev foi de um MOVIMENTO, não de um estado: as nuvens se juntam, chove, elas se separam e o pôr
|
|
31
|
+
* do sol aparece nas frestas. Quem faz isso ler como causa e não como coincidência é a ANTECEDÊNCIA — a manta
|
|
32
|
+
* fecha OITO SEGUNDOS ANTES da primeira gota. Se fechasse junto, a chuva pareceria vir do nada e as nuvens
|
|
33
|
+
* pareceriam reagir a ela; fechando antes, é a nuvem que traz a chuva, que é o que uma criança já sabe.
|
|
34
|
+
*
|
|
35
|
+
* Anda no MESMO ciclo da chuva (`faseDoClima`), e não num relógio próprio, porque dois relógios independentes
|
|
36
|
+
* desandam um do outro — não de imediato, mas depois de alguns minutos, e aí ninguém liga o defeito à causa.
|
|
37
|
+
* Devolve uma rampa contínua: não precisa de suavização depois.
|
|
38
|
+
*/
|
|
39
|
+
export declare function aglomeracaoAlvo(sec: number, temChuva: boolean, reduceDecor: boolean): number;
|
|
40
|
+
/** Ramps `current` toward `target` by at most `step`, snapping to `target` once within 0.02 (no "quase seco" flicker). */
|
|
41
|
+
export declare function rampRainLevel(current: number, target: number, step: number): number;
|
|
42
|
+
/** Thunder cooldown/flash step (só na chuva forte, > 0.45). Calls `onThunder(inten)` — e.g. platform/audio-ambient's `thunder`. */
|
|
43
|
+
export interface ThunderStep {
|
|
44
|
+
thunderCD: number;
|
|
45
|
+
flash: number;
|
|
46
|
+
}
|
|
47
|
+
export declare function stepThunder(rainLevel: number, thunderCD: number, flash: number, rndFn: () => number, onThunder: (inten: number) => void): ThunderStep;
|
|
48
|
+
/** Seeds `n` rain drops at random positions across the WxH screen (lazy — built once on first rain). */
|
|
49
|
+
export declare function makeRainDrops(n: number, W: number, H: number, rndFn: () => number): RainDrop[];
|
|
50
|
+
/** Advances one drop by its own speed; wraps to the top (new random x) past H. GAG: drops freeze when `moving` is false (pause). */
|
|
51
|
+
export declare function stepRainDrop(d: RainDrop, W: number, H: number, moving: boolean, rndFn: () => number): void;
|
|
52
|
+
type Gfx = DesenhoComLinha & {
|
|
53
|
+
parent: unknown;
|
|
54
|
+
};
|
|
55
|
+
interface StageLike {
|
|
56
|
+
children: {
|
|
57
|
+
length: number;
|
|
58
|
+
};
|
|
59
|
+
setChildIndex(child: unknown, index: number): void;
|
|
60
|
+
}
|
|
61
|
+
export interface WeatherCtx {
|
|
62
|
+
/** The PIXI.Graphics layer this module draws into (created + z-ordered in game.js, kept on top of the stage). */
|
|
63
|
+
weatherLayer: Gfx;
|
|
64
|
+
/** The PIXI.Container `weatherLayer` lives on — used only to re-pin it as the topmost child every draw. */
|
|
65
|
+
stage: StageLike;
|
|
66
|
+
/** Live screen size (pass `app.screen`; width/height read fresh on every draw()). */
|
|
67
|
+
screen: {
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
};
|
|
71
|
+
/** Reduced-motion flags; only `.decor` (scene decor/animation) matters here. */
|
|
72
|
+
getRm: () => {
|
|
73
|
+
decor?: boolean;
|
|
74
|
+
};
|
|
75
|
+
/** Called when thunder should rumble (platform/audio-ambient's `ambient.thunder`). */
|
|
76
|
+
thunder: (inten: number) => void;
|
|
77
|
+
/** Chove no cenário atual? Uma PERGUNTA e não o id do cenário: quem tem o catálogo responde. */
|
|
78
|
+
temChuva: () => boolean;
|
|
79
|
+
/** O mundo está rodando? Um BOOLEANO e não a fase — a engine não conhece o vocabulário de cenas deste
|
|
80
|
+
* jogo (ADR-0030 C3). Era `phase === 'playing'`, importado de `core/state`. É o que congela as gotas na
|
|
81
|
+
* pausa: elas param no ar em vez de continuarem caindo por trás do menu. */
|
|
82
|
+
mundoRodando: () => boolean;
|
|
83
|
+
}
|
|
84
|
+
export declare function initWeather(ctx: WeatherCtx): void;
|
|
85
|
+
/** Per-frame clima update (game.js calls this only while `phase==='playing'`, same as before). */
|
|
86
|
+
export declare function updateWeather(): void;
|
|
87
|
+
/** Redraws the rain/flash overlay (chuva/clarão em tela-espaço, sobre tudo). */
|
|
88
|
+
export declare function drawWeather(): void;
|
|
89
|
+
/** The clima→áudio bridge: platform/audio-ambient.ts reads this (never the raw value) so its rain track follows the visual. */
|
|
90
|
+
export declare function getRainLevel(): number;
|
|
91
|
+
/** A ponte clima→céu: render/scene-sky lê isto para juntar e separar as nuvens no compasso da chuva. */
|
|
92
|
+
export declare function getAglomeracao(): number;
|
|
93
|
+
/** Weather-clock read/write — the game.js `window.__incl.weatherT` debug hook fast-forwards the cycle via this. */
|
|
94
|
+
export declare function getWeatherT(): number;
|
|
95
|
+
export declare function setWeatherT(v: number): void;
|
|
96
|
+
export {};
|