@the-inclusionist/engine 7.0.1 → 8.0.0-rc.2
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 +5 -3
- package/app/css/style.css +22 -5
- 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/opendyslexic-400.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-ar.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-br.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-ca.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-cl.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-co.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-mx.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-us-modern.woff2 +0 -0
- package/app/public/vendor/fonts/playwrite-us-trad.woff2 +0 -0
- package/app/public/vendor/fonts/pressstart-400.woff2 +0 -0
- package/app/public/vendor/fonts.css +64 -2
- package/dist-pkg/boot/create-game.d.ts +107 -4
- package/dist-pkg/boot/create-game.js +337 -18
- package/dist-pkg/core/constants.d.ts +0 -28
- package/dist-pkg/core/constants.js +34 -17
- package/dist-pkg/core/contract.d.ts +99 -0
- package/dist-pkg/core/contract.js +78 -0
- package/dist-pkg/core/entity.d.ts +47 -4
- package/dist-pkg/core/layers.d.ts +18 -0
- package/dist-pkg/core/layers.js +18 -0
- package/dist-pkg/core/rng.js +14 -4
- package/dist-pkg/core/route.d.ts +42 -0
- package/dist-pkg/core/route.js +158 -0
- package/dist-pkg/core/state.d.ts +10 -1
- package/dist-pkg/core/state.js +13 -0
- package/dist-pkg/educational/adaptive-engine.d.ts +65 -0
- package/dist-pkg/educational/adaptive-engine.js +117 -0
- package/dist-pkg/educational/segment-bar.d.ts +96 -0
- package/dist-pkg/educational/segment-bar.js +89 -0
- package/dist-pkg/i18n/en.js +44 -0
- package/dist-pkg/i18n/es.js +44 -0
- package/dist-pkg/i18n/pt.js +60 -0
- package/dist-pkg/input/default-bindings.d.ts +40 -0
- package/dist-pkg/input/default-bindings.js +151 -9
- package/dist-pkg/input/gamepad.d.ts +33 -12
- package/dist-pkg/input/gamepad.js +103 -16
- package/dist-pkg/input/keyboard-runtime.d.ts +6 -8
- package/dist-pkg/input/keyboard-runtime.js +24 -5
- package/dist-pkg/input/keyboard.d.ts +42 -0
- package/dist-pkg/input/keyboard.js +87 -17
- package/dist-pkg/input/keydown.d.ts +40 -2
- package/dist-pkg/input/keydown.js +29 -6
- package/dist-pkg/input/latch-edge.d.ts +28 -0
- package/dist-pkg/input/latch-edge.js +45 -0
- package/dist-pkg/input/latch-scope.d.ts +70 -0
- package/dist-pkg/input/latch-scope.js +110 -0
- package/dist-pkg/input/latch-store.d.ts +45 -0
- package/dist-pkg/input/latch-store.js +74 -0
- package/dist-pkg/input/latch-sync.d.ts +47 -0
- package/dist-pkg/input/latch-sync.js +43 -0
- package/dist-pkg/input/origem-sintetica.d.ts +44 -0
- package/dist-pkg/input/origem-sintetica.js +60 -0
- package/dist-pkg/input/pad-defaults.d.ts +22 -0
- package/dist-pkg/input/pad-defaults.js +34 -0
- package/dist-pkg/input/pointer.d.ts +61 -0
- package/dist-pkg/input/pointer.js +71 -0
- package/dist-pkg/input/state.d.ts +86 -1
- package/dist-pkg/input/state.js +128 -1
- package/dist-pkg/input/touch-bindings.d.ts +21 -2
- package/dist-pkg/input/touch-bindings.js +15 -3
- package/dist-pkg/input/touch.js +9 -1
- package/dist-pkg/input/transporte-em-uso.d.ts +101 -0
- package/dist-pkg/input/transporte-em-uso.js +130 -0
- package/dist-pkg/input/transports.d.ts +88 -2
- package/dist-pkg/input/transports.js +60 -5
- package/dist-pkg/input/vocabulary-migration.d.ts +18 -7
- package/dist-pkg/platform/audio-earcons.d.ts +29 -2
- package/dist-pkg/platform/audio-earcons.js +10 -0
- package/dist-pkg/platform/audio-nav.d.ts +1 -1
- package/dist-pkg/platform/audio-sonar.d.ts +149 -9
- package/dist-pkg/platform/audio-sonar.js +232 -21
- package/dist-pkg/platform/guide-intensity.d.ts +40 -0
- package/dist-pkg/platform/guide-intensity.js +73 -0
- package/dist-pkg/platform/pesados-catalogo.d.ts +14 -0
- package/dist-pkg/platform/pesados-catalogo.js +177 -0
- package/dist-pkg/platform/pesados.d.ts +31 -0
- package/dist-pkg/platform/pesados.js +75 -0
- package/dist-pkg/platform/storage.d.ts +30 -0
- package/dist-pkg/platform/storage.js +35 -0
- package/dist-pkg/platform/tts.js +16 -1
- package/dist-pkg/platform/voice-plan.d.ts +109 -0
- package/dist-pkg/platform/voice-plan.js +156 -0
- package/dist-pkg/platform/vozes-prontas.d.ts +28 -0
- package/dist-pkg/platform/vozes-prontas.js +61 -0
- package/dist-pkg/render/draw.d.ts +1 -1
- package/dist-pkg/render/draw.js +15 -5
- package/dist-pkg/render/viz-axes.d.ts +17 -0
- package/dist-pkg/render/viz-axes.js +19 -0
- package/dist-pkg/render/viz-setters.d.ts +34 -2
- package/dist-pkg/render/viz-setters.js +189 -33
- package/dist-pkg/render/wheelchair-sprites.d.ts +11 -3
- package/dist-pkg/render/wheelchair-sprites.js +10 -4
- package/dist-pkg/ui/dom.js +20 -2
- package/dist-pkg/ui/fonts.d.ts +71 -1
- package/dist-pkg/ui/fonts.js +111 -8
- package/dist-pkg/ui/latch-refusal.d.ts +32 -0
- package/dist-pkg/ui/latch-refusal.js +60 -0
- package/dist-pkg/ui/layout.d.ts +32 -0
- package/dist-pkg/ui/layout.js +64 -1
- package/dist-pkg/ui/motion-scene.d.ts +41 -0
- package/dist-pkg/ui/motion-scene.js +76 -0
- package/dist-pkg/ui/panel-shell.d.ts +53 -0
- package/dist-pkg/ui/panel-shell.js +103 -0
- package/dist-pkg/ui/pause-icons.d.ts +168 -20
- package/dist-pkg/ui/pause-icons.js +315 -45
- package/dist-pkg/ui/reach-notice.js +8 -0
- package/dist-pkg/ui/settings-audio.d.ts +14 -1
- package/dist-pkg/ui/settings-audio.js +43 -3
- package/dist-pkg/ui/settings-controls.d.ts +66 -6
- package/dist-pkg/ui/settings-controls.js +179 -17
- package/dist-pkg/ui/settings-empathy.d.ts +15 -0
- package/dist-pkg/ui/settings-empathy.js +2 -0
- package/dist-pkg/ui/settings-motion.d.ts +25 -19
- package/dist-pkg/ui/settings-motion.js +32 -19
- package/dist-pkg/ui/settings-motor.d.ts +101 -3
- package/dist-pkg/ui/settings-motor.js +136 -9
- package/dist-pkg/ui/settings-typo.d.ts +49 -5
- package/dist-pkg/ui/settings-typo.js +74 -23
- package/dist-pkg/ui/settings-visual.d.ts +21 -1
- package/dist-pkg/ui/settings-visual.js +48 -4
- package/dist-pkg/ui/shell.d.ts +13 -3
- package/dist-pkg/ui/shell.js +3 -4
- package/dist-pkg/ui/simulation-refusal.d.ts +32 -0
- package/dist-pkg/ui/simulation-refusal.js +57 -0
- package/dist-pkg/ui/visual-axes-panel.d.ts +48 -0
- package/dist-pkg/ui/visual-axes-panel.js +95 -0
- package/dist-pkg/ui/webcam.js +6 -1
- package/docs/CREDITS.md +22 -1
- package/docs/LICENSES.md +170 -132
- package/package.json +25 -4
- package/app/public/vendor/fonts/greatvibes-400.woff2 +0 -0
- package/app/public/vendor/fonts/ufcook-700.woff2 +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Transporte } from './transporte-em-uso.js';
|
|
3
|
+
import type { EmFracao } from './pointer-space.js';
|
|
4
|
+
/**
|
|
5
|
+
* Onde o ponteiro está e o que ele está a fazer.
|
|
6
|
+
*
|
|
7
|
+
* `fx`/`fy` são fracção do elemento do jogo, na convenção do `pointer-space`: `0,0` é o canto superior
|
|
8
|
+
* esquerdo e `1,1` o inferior direito. ⚠️ Podem sair de `0..1` — ver `dentro`.
|
|
9
|
+
*/
|
|
10
|
+
export interface AmostraDoPonteiro {
|
|
11
|
+
readonly fx: number;
|
|
12
|
+
readonly fy: number;
|
|
13
|
+
/** Quem produziu esta amostra (ADR-0111). */
|
|
14
|
+
readonly origem: Transporte;
|
|
15
|
+
/** A «caneta» está em baixo? Rato: botão premido. Toque: dedo em contacto. Olhar: permanência. */
|
|
16
|
+
readonly apertado: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** O repouso: centro da região, sem aperto, teclado — o mesmo padrão que o `transporte-em-uso` assume. */
|
|
19
|
+
export declare const PADRAO: AmostraDoPonteiro;
|
|
20
|
+
/**
|
|
21
|
+
* A amostra está DENTRO da região do jogo?
|
|
22
|
+
*
|
|
23
|
+
* ⚠️ ESTA PERGUNTA EXISTE SEPARADA DA POSIÇÃO, e é a decisão inteira deste ficheiro. O `emFracao` não satura
|
|
24
|
+
* de propósito («quem saturasse aqui não teria como voltar atrás»), e há duas coisas a jusante que precisam
|
|
25
|
+
* de metades opostas dela:
|
|
26
|
+
*
|
|
27
|
+
* · DESENHAR precisa da posição PRESA a `0..1`, senão o traço salta para fora da tela quando a mão
|
|
28
|
+
* ultrapassa a borda durante um arrasto capturado;
|
|
29
|
+
* · o MODO OLHOS 3 do ADR-0104 usa «olhar para fora da tela» como comando de navegação — para uma criança
|
|
30
|
+
* com ELA severa, olhar para cima FORA do écran é o gesto que abre a lista de acções.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ SATURAR SEM GUARDAR ESTA RESPOSTA MATARIA O SEGUNDO. É a mesma família de defeito que este repositório
|
|
33
|
+
* já pagou várias vezes: uma informação deitada fora à porta, e o consumidor que dela dependia a descobrir
|
|
34
|
+
* tarde que a pergunta já não tem resposta.
|
|
35
|
+
*/
|
|
36
|
+
export declare function dentro(f: EmFracao): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* A posição PRESA a `0..1`, para quem desenha.
|
|
39
|
+
*
|
|
40
|
+
* 📌 Devolve o MESMO objecto quando já está dentro, e não uma cópia. O ponteiro é amostrado a cada quadro, e
|
|
41
|
+
* uma alocação por quadro num aparelho de escola é exactamente o tipo de custo que o pilar 1 recusa.
|
|
42
|
+
*/
|
|
43
|
+
export declare function prender(f: EmFracao): EmFracao;
|
|
44
|
+
/** A borda do aperto entre duas amostras: a caneta desceu, subiu, ou nada mudou. */
|
|
45
|
+
export type BordaDoAperto = 'desceu' | 'subiu' | null;
|
|
46
|
+
/**
|
|
47
|
+
* Comparar duas amostras dá a BORDA, que é o que um jogo lê.
|
|
48
|
+
*
|
|
49
|
+
* ⚠️ A BORDA E NÃO O ESTADO, pela razão que o `padPrevAct` deste repositório já escreve para o gamepad: um
|
|
50
|
+
* jogo que perguntasse «está apertado?» a cada quadro desenharia o mesmo ponto sessenta vezes, e um que
|
|
51
|
+
* quisesse reagir ao clique teria de guardar o quadro anterior por sua conta — trezentas vezes.
|
|
52
|
+
*/
|
|
53
|
+
export declare function bordaDoAperto(anterior: AmostraDoPonteiro, atual: AmostraDoPonteiro): BordaDoAperto;
|
|
54
|
+
/**
|
|
55
|
+
* O TRANSPORTE MUDOU entre estas duas amostras?
|
|
56
|
+
*
|
|
57
|
+
* ⚠️ Existe porque o ADR-0109 faz da troca de aparelho um evento com consequência — a alternância segue o
|
|
58
|
+
* aparelho em uso —, e um ponteiro é um dos sítios onde a troca acontece sem que nenhuma tecla seja premida:
|
|
59
|
+
* a criança larga o rato e olha para a tela. Sem esta pergunta, a troca seria invisível até à próxima tecla.
|
|
60
|
+
*/
|
|
61
|
+
export declare function trocouDeTransporte(anterior: AmostraDoPonteiro, atual: AmostraDoPonteiro): boolean;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// input/pointer.ts — O QUE O JOGO RECEBE QUANDO PEDE UM PONTEIRO (ADR-0112), na metade PURA.
|
|
3
|
+
//
|
|
4
|
+
// ========================= O QUE ESTE MÓDULO É =========================
|
|
5
|
+
// Uma AMOSTRA de ponteiro e as perguntas que se fazem sobre ela. Sem DOM, sem tempo, sem eventos. Quem captura
|
|
6
|
+
// é `input/touch-bindings.wirePointerPad`, que a issue #105 mediu como já existindo inteiro; quem converte um
|
|
7
|
+
// ponto de tela é `input/pointer-space`, que também já existe. Falta o que fica ENTRE os dois: a forma que
|
|
8
|
+
// atravessa a fronteira até ao cartucho.
|
|
9
|
+
//
|
|
10
|
+
// ⚠️ E A AMOSTRA CARREGA A ORIGEM, porque o ADR-0111 diz que todo comando a carrega. Um traço feito com o
|
|
11
|
+
// olhar e um traço feito com o rato têm de ser distinguíveis pela engine — as regras de transporte assistido
|
|
12
|
+
// do ADR-0109 dependem de saber qual aparelho está em uso, e um desenho não é excepção.
|
|
13
|
+
//
|
|
14
|
+
// 📌 A ORIGEM É OBRIGATÓRIA AQUI, ao contrário do `origemDe` das teclas, que devolve `undefined`. A diferença
|
|
15
|
+
// não é de rigor, é de estrutura: uma tecla entra num conjunto PARTILHADO onde qualquer código pode despachar
|
|
16
|
+
// um evento sintético, então «não sei» é uma resposta honesta. Uma amostra de ponteiro é construída PELO
|
|
17
|
+
// transporte que a produziu — ele sabe sempre o que é, porque é ele próprio.
|
|
18
|
+
/** O repouso: centro da região, sem aperto, teclado — o mesmo padrão que o `transporte-em-uso` assume. */
|
|
19
|
+
export const PADRAO = Object.freeze({ fx: 0.5, fy: 0.5, origem: 'teclado', apertado: false });
|
|
20
|
+
/**
|
|
21
|
+
* A amostra está DENTRO da região do jogo?
|
|
22
|
+
*
|
|
23
|
+
* ⚠️ ESTA PERGUNTA EXISTE SEPARADA DA POSIÇÃO, e é a decisão inteira deste ficheiro. O `emFracao` não satura
|
|
24
|
+
* de propósito («quem saturasse aqui não teria como voltar atrás»), e há duas coisas a jusante que precisam
|
|
25
|
+
* de metades opostas dela:
|
|
26
|
+
*
|
|
27
|
+
* · DESENHAR precisa da posição PRESA a `0..1`, senão o traço salta para fora da tela quando a mão
|
|
28
|
+
* ultrapassa a borda durante um arrasto capturado;
|
|
29
|
+
* · o MODO OLHOS 3 do ADR-0104 usa «olhar para fora da tela» como comando de navegação — para uma criança
|
|
30
|
+
* com ELA severa, olhar para cima FORA do écran é o gesto que abre a lista de acções.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ SATURAR SEM GUARDAR ESTA RESPOSTA MATARIA O SEGUNDO. É a mesma família de defeito que este repositório
|
|
33
|
+
* já pagou várias vezes: uma informação deitada fora à porta, e o consumidor que dela dependia a descobrir
|
|
34
|
+
* tarde que a pergunta já não tem resposta.
|
|
35
|
+
*/
|
|
36
|
+
export function dentro(f) {
|
|
37
|
+
return f.fx >= 0 && f.fx <= 1 && f.fy >= 0 && f.fy <= 1;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A posição PRESA a `0..1`, para quem desenha.
|
|
41
|
+
*
|
|
42
|
+
* 📌 Devolve o MESMO objecto quando já está dentro, e não uma cópia. O ponteiro é amostrado a cada quadro, e
|
|
43
|
+
* uma alocação por quadro num aparelho de escola é exactamente o tipo de custo que o pilar 1 recusa.
|
|
44
|
+
*/
|
|
45
|
+
export function prender(f) {
|
|
46
|
+
if (dentro(f))
|
|
47
|
+
return f;
|
|
48
|
+
return { fx: Math.min(1, Math.max(0, f.fx)), fy: Math.min(1, Math.max(0, f.fy)) };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Comparar duas amostras dá a BORDA, que é o que um jogo lê.
|
|
52
|
+
*
|
|
53
|
+
* ⚠️ A BORDA E NÃO O ESTADO, pela razão que o `padPrevAct` deste repositório já escreve para o gamepad: um
|
|
54
|
+
* jogo que perguntasse «está apertado?» a cada quadro desenharia o mesmo ponto sessenta vezes, e um que
|
|
55
|
+
* quisesse reagir ao clique teria de guardar o quadro anterior por sua conta — trezentas vezes.
|
|
56
|
+
*/
|
|
57
|
+
export function bordaDoAperto(anterior, atual) {
|
|
58
|
+
if (anterior.apertado === atual.apertado)
|
|
59
|
+
return null;
|
|
60
|
+
return atual.apertado ? 'desceu' : 'subiu';
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* O TRANSPORTE MUDOU entre estas duas amostras?
|
|
64
|
+
*
|
|
65
|
+
* ⚠️ Existe porque o ADR-0109 faz da troca de aparelho um evento com consequência — a alternância segue o
|
|
66
|
+
* aparelho em uso —, e um ponteiro é um dos sítios onde a troca acontece sem que nenhuma tecla seja premida:
|
|
67
|
+
* a criança larga o rato e olha para a tela. Sem esta pergunta, a troca seria invisível até à próxima tecla.
|
|
68
|
+
*/
|
|
69
|
+
export function trocouDeTransporte(anterior, atual) {
|
|
70
|
+
return anterior.origem !== atual.origem;
|
|
71
|
+
}
|
|
@@ -1,11 +1,96 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
2
|
import type { ControlledPlayer } from '../core/entity.js';
|
|
3
|
+
import type { Action } from '../core/actions.js';
|
|
4
|
+
import { type Transporte, type EstadoDaEntrada } from './transporte-em-uso.js';
|
|
3
5
|
export declare const keys: Set<string>;
|
|
6
|
+
/**
|
|
7
|
+
* A ORIGEM DE CADA TECLA SEGURADA — código → aparelho que a produziu (ADR-0109).
|
|
8
|
+
*
|
|
9
|
+
* ⚠️ ESTE MAPA EXISTE PORQUE `keys` APAGA A ORIGEM À PORTA, e foi essa erasão que deixou o §C da issue #114
|
|
10
|
+
* por construir durante dois meses: o toque escreve códigos aqui dentro (`press()` faz
|
|
11
|
+
* `heldKeys.add(codeFor(act))`) e a webcam despacha `KeyboardEvent` sintético, então quando o `held()`
|
|
12
|
+
* responde já não há como saber QUEM carregou. O único transporte que sobrevivia identificável era o
|
|
13
|
+
* gamepad, e só porque passa por `padCur` em vez do conjunto.
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ CAMPO NOVO AO LADO DO VELHO, sincronizado num ponto só (`marcarTecla`/`soltarTecla`), com os leitores a
|
|
16
|
+
* migrar um a um — é a forma que este repositório já usou no `p.visual` ao lado do `p.viz` (#104), e a razão
|
|
17
|
+
* é a mesma: uma troca de uma vez não tem estado verde onde parar, e isto é a espinha da entrada.
|
|
18
|
+
*
|
|
19
|
+
* 📌 Um código SEM entrada aqui não é um erro de dados — é uma tecla que entrou por um escritor que ainda não
|
|
20
|
+
* migrou. `origemDe` devolve `undefined` e quem pergunta decide; ver a nota lá.
|
|
21
|
+
*/
|
|
22
|
+
export declare const origemDaTecla: Map<string, Transporte>;
|
|
23
|
+
/**
|
|
24
|
+
* Uma tecla FOI SEGURADA, e sabe-se por quem. É o único sítio que escreve nos dois.
|
|
25
|
+
*
|
|
26
|
+
* ⚠️ OS DOIS JUNTOS OU NENHUM: enquanto forem duas estruturas, elas podem divergir, e uma divergência aqui é
|
|
27
|
+
* silenciosa — o jogo continua a andar e só a alternância fica errada. Por isso não há `keys.add` público
|
|
28
|
+
* neste módulo: quem escreve, escreve por aqui.
|
|
29
|
+
*/
|
|
30
|
+
export declare function marcarTecla(code: string, origem: Transporte): void;
|
|
31
|
+
/**
|
|
32
|
+
* A tecla foi segurada e NÃO SE SABE por quem. A porta estreita, e ela é estreita de propósito.
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ POR QUE UMA FUNÇÃO COM OUTRO NOME E NÃO UM SEGUNDO PARÂMETRO OPCIONAL. `marcarTecla(code)` com a origem
|
|
35
|
+
* omitida é o que se escreve quando não se pensou; `marcarTeclaSemOrigem(code)` é o que se escreve quando se
|
|
36
|
+
* pensou e a resposta é «não sei». O tipo não distingue as duas, mas o nome distingue — e é o nome que
|
|
37
|
+
* aparece na revisão. Um parâmetro esquecido não se lê; uma função assim chamada lê-se de longe.
|
|
38
|
+
*
|
|
39
|
+
* ⚠️ E O `delete` É A METADE QUE IMPORTA, não o `add`. Sem ele, uma tecla premida de novo por uma fonte
|
|
40
|
+
* desconhecida HERDAVA a origem da vez anterior: a criança joga por olhar, larga a tecla, um script de fora
|
|
41
|
+
* despacha o mesmo código, e a alternância continua a responder «olhos» a uma aresta que já não é dela. Um
|
|
42
|
+
* mapa que guarda a resposta certa de ontem é pior do que um que não guarda nada.
|
|
43
|
+
*
|
|
44
|
+
* 📌 Hoje há UM chamador — o `input/keydown`, para o evento sintético que ninguém assinou. Depois desta
|
|
45
|
+
* migração nada nesta engine produz um; quem produz é código de consumidor, e é para ele que esta porta fica
|
|
46
|
+
* aberta. Fechá-la faria a tecla dele simplesmente não funcionar, o que é uma quebra pior do que não saber.
|
|
47
|
+
*/
|
|
48
|
+
export declare function marcarTeclaSemOrigem(code: string): void;
|
|
49
|
+
/** A outra metade. Solta nos dois, pela mesma razão. */
|
|
50
|
+
export declare function soltarTecla(code: string): void;
|
|
51
|
+
/** Solta TUDO — o `blur` da janela. Os dois, ou o mapa fica a descrever teclas que já ninguém segura. */
|
|
52
|
+
export declare function soltarTodas(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Quem produziu esta tecla? `undefined` quando não se sabe.
|
|
55
|
+
*
|
|
56
|
+
* ⚠️ `undefined` E NÃO UM PADRÃO. Um padrão `'teclado'` faria a erasão voltar por outra porta: uma tecla do
|
|
57
|
+
* toque que entrasse por um escritor não migrado seria lida como teclado, a alternância desligava-se, e nada
|
|
58
|
+
* o diria. Não saber é uma resposta; fingir que se sabe não é.
|
|
59
|
+
*/
|
|
60
|
+
export declare function origemDe(code: string): Transporte | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* O ESTADO DA ENTRADA DESTE JOGADOR. Nunca `undefined`: quem nunca produziu uma aresta está no PADRÃO.
|
|
63
|
+
*
|
|
64
|
+
* ⚠️ `PADRAO` E NÃO `undefined`, pela mesma razão que o `origemDe` faz o contrário: ali «não sei» é uma
|
|
65
|
+
* resposta honesta sobre uma tecla que já existe; aqui a pergunta é sobre um JOGADOR, e um jogador que
|
|
66
|
+
* ainda não tocou em nada está mesmo no teclado sem assistida — que é o que `PADRAO` diz.
|
|
67
|
+
*/
|
|
68
|
+
export declare function entradaDe(jogador: number): EstadoDaEntrada;
|
|
69
|
+
/**
|
|
70
|
+
* UMA ARESTA DESTE JOGADOR CHEGOU, com a sua origem.
|
|
71
|
+
*
|
|
72
|
+
* 📌 O `aposAresta` devolve o MESMO objecto quando nada muda, então guardar de volta não aloca por quadro.
|
|
73
|
+
* ⚠️ E uma aresta de um transporte assistido NÃO o habilita — essa regra vive no `aposAresta` e a razão
|
|
74
|
+
* está lá: um falso positivo da webcam trancaria a alternância de toda a gente sem ninguém ter pedido.
|
|
75
|
+
*/
|
|
76
|
+
export declare function arestaDoJogador(jogador: number, origem: Transporte): void;
|
|
77
|
+
/** Habilitar a assistida é um ACTO EXPLÍCITO (ADR-0109 regra 4), e por isso tem porta própria. */
|
|
78
|
+
export declare function habilitarAssistidaDe(jogador: number): void;
|
|
79
|
+
export declare function desabilitarAssistidaDe(jogador: number): void;
|
|
80
|
+
/**
|
|
81
|
+
* ⚠️ ESQUECER É UMA PORTA SEPARADA, E O `soltarTodas` NÃO A CHAMA — de propósito.
|
|
82
|
+
*
|
|
83
|
+
* O `blur` da janela solta as teclas porque elas deixaram mesmo de estar premidas. Mas a criança não trocou
|
|
84
|
+
* de aparelho por mudar de separador: zerar o transporte em uso ali devolveria toda a gente ao teclado, e
|
|
85
|
+
* quem joga por olhar perderia a alternância no meio da partida sem nada o dizer. Existe para o fim de uma
|
|
86
|
+
* PARTIDA, onde a pergunta se põe de novo.
|
|
87
|
+
*/
|
|
88
|
+
export declare function esquecerEntradas(): void;
|
|
4
89
|
type PadState = Record<string, boolean>;
|
|
5
90
|
export declare const padCur: Record<number, PadState>;
|
|
6
91
|
export declare const padPrevAct: Record<number, PadState>;
|
|
7
92
|
export declare const padPrevStart: Record<number, boolean>;
|
|
8
93
|
export declare const PAD_DEAD = 0.5;
|
|
9
94
|
type HeldPlayer = Pick<ControlledPlayer, 'ctrl' | 'pad'>;
|
|
10
|
-
export declare const held: (pl: HeldPlayer, act:
|
|
95
|
+
export declare const held: (pl: HeldPlayer, act: Action) => boolean;
|
|
11
96
|
export {};
|
package/dist-pkg/input/state.js
CHANGED
|
@@ -3,10 +3,137 @@
|
|
|
3
3
|
// game.js e mutam estes objetos IN-PLACE): teclas seguradas (keys), estado de gamepad por controle
|
|
4
4
|
// (padCur/padPrevAct/padPrevStart) e a zona morta do analógico (PAD_DEAD). held(pl,act) = o jogador está
|
|
5
5
|
// segurando a ação, por teclado (pl.ctrl) OU pelo gamepad associado (pl.pad). Módulo-folha, ZERO deps. (Fase 2.22)
|
|
6
|
+
// ⚠️ O cabeçalho deste módulo dizia «ZERO deps», e ele já tinha DUAS de tipo (`ControlledPlayer`, `Action`) —
|
|
7
|
+
// a frase queria dizer «nada em tempo de execução», que continua verdade: os três imports são `type` e
|
|
8
|
+
// desaparecem no build. A terceira entra pela mesma razão que as outras duas: o vocabulário mora com quem
|
|
9
|
+
// tem as REGRAS sobre ele (`input/transporte-em-uso`), e repeti-lo aqui seria a segunda cópia de uma união.
|
|
10
|
+
import { PADRAO, aposAresta, habilitarAssistida, desabilitarAssistida, } from './transporte-em-uso.js';
|
|
6
11
|
export const keys = new Set();
|
|
12
|
+
/**
|
|
13
|
+
* A ORIGEM DE CADA TECLA SEGURADA — código → aparelho que a produziu (ADR-0109).
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ ESTE MAPA EXISTE PORQUE `keys` APAGA A ORIGEM À PORTA, e foi essa erasão que deixou o §C da issue #114
|
|
16
|
+
* por construir durante dois meses: o toque escreve códigos aqui dentro (`press()` faz
|
|
17
|
+
* `heldKeys.add(codeFor(act))`) e a webcam despacha `KeyboardEvent` sintético, então quando o `held()`
|
|
18
|
+
* responde já não há como saber QUEM carregou. O único transporte que sobrevivia identificável era o
|
|
19
|
+
* gamepad, e só porque passa por `padCur` em vez do conjunto.
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ CAMPO NOVO AO LADO DO VELHO, sincronizado num ponto só (`marcarTecla`/`soltarTecla`), com os leitores a
|
|
22
|
+
* migrar um a um — é a forma que este repositório já usou no `p.visual` ao lado do `p.viz` (#104), e a razão
|
|
23
|
+
* é a mesma: uma troca de uma vez não tem estado verde onde parar, e isto é a espinha da entrada.
|
|
24
|
+
*
|
|
25
|
+
* 📌 Um código SEM entrada aqui não é um erro de dados — é uma tecla que entrou por um escritor que ainda não
|
|
26
|
+
* migrou. `origemDe` devolve `undefined` e quem pergunta decide; ver a nota lá.
|
|
27
|
+
*/
|
|
28
|
+
export const origemDaTecla = new Map();
|
|
29
|
+
/**
|
|
30
|
+
* Uma tecla FOI SEGURADA, e sabe-se por quem. É o único sítio que escreve nos dois.
|
|
31
|
+
*
|
|
32
|
+
* ⚠️ OS DOIS JUNTOS OU NENHUM: enquanto forem duas estruturas, elas podem divergir, e uma divergência aqui é
|
|
33
|
+
* silenciosa — o jogo continua a andar e só a alternância fica errada. Por isso não há `keys.add` público
|
|
34
|
+
* neste módulo: quem escreve, escreve por aqui.
|
|
35
|
+
*/
|
|
36
|
+
export function marcarTecla(code, origem) {
|
|
37
|
+
keys.add(code);
|
|
38
|
+
origemDaTecla.set(code, origem);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* A tecla foi segurada e NÃO SE SABE por quem. A porta estreita, e ela é estreita de propósito.
|
|
42
|
+
*
|
|
43
|
+
* ⚠️ POR QUE UMA FUNÇÃO COM OUTRO NOME E NÃO UM SEGUNDO PARÂMETRO OPCIONAL. `marcarTecla(code)` com a origem
|
|
44
|
+
* omitida é o que se escreve quando não se pensou; `marcarTeclaSemOrigem(code)` é o que se escreve quando se
|
|
45
|
+
* pensou e a resposta é «não sei». O tipo não distingue as duas, mas o nome distingue — e é o nome que
|
|
46
|
+
* aparece na revisão. Um parâmetro esquecido não se lê; uma função assim chamada lê-se de longe.
|
|
47
|
+
*
|
|
48
|
+
* ⚠️ E O `delete` É A METADE QUE IMPORTA, não o `add`. Sem ele, uma tecla premida de novo por uma fonte
|
|
49
|
+
* desconhecida HERDAVA a origem da vez anterior: a criança joga por olhar, larga a tecla, um script de fora
|
|
50
|
+
* despacha o mesmo código, e a alternância continua a responder «olhos» a uma aresta que já não é dela. Um
|
|
51
|
+
* mapa que guarda a resposta certa de ontem é pior do que um que não guarda nada.
|
|
52
|
+
*
|
|
53
|
+
* 📌 Hoje há UM chamador — o `input/keydown`, para o evento sintético que ninguém assinou. Depois desta
|
|
54
|
+
* migração nada nesta engine produz um; quem produz é código de consumidor, e é para ele que esta porta fica
|
|
55
|
+
* aberta. Fechá-la faria a tecla dele simplesmente não funcionar, o que é uma quebra pior do que não saber.
|
|
56
|
+
*/
|
|
57
|
+
export function marcarTeclaSemOrigem(code) {
|
|
58
|
+
keys.add(code);
|
|
59
|
+
origemDaTecla.delete(code);
|
|
60
|
+
}
|
|
61
|
+
/** A outra metade. Solta nos dois, pela mesma razão. */
|
|
62
|
+
export function soltarTecla(code) {
|
|
63
|
+
keys.delete(code);
|
|
64
|
+
origemDaTecla.delete(code);
|
|
65
|
+
}
|
|
66
|
+
/** Solta TUDO — o `blur` da janela. Os dois, ou o mapa fica a descrever teclas que já ninguém segura. */
|
|
67
|
+
export function soltarTodas() {
|
|
68
|
+
keys.clear();
|
|
69
|
+
origemDaTecla.clear();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Quem produziu esta tecla? `undefined` quando não se sabe.
|
|
73
|
+
*
|
|
74
|
+
* ⚠️ `undefined` E NÃO UM PADRÃO. Um padrão `'teclado'` faria a erasão voltar por outra porta: uma tecla do
|
|
75
|
+
* toque que entrasse por um escritor não migrado seria lida como teclado, a alternância desligava-se, e nada
|
|
76
|
+
* o diria. Não saber é uma resposta; fingir que se sabe não é.
|
|
77
|
+
*/
|
|
78
|
+
export function origemDe(code) {
|
|
79
|
+
return origemDaTecla.get(code);
|
|
80
|
+
}
|
|
81
|
+
// ===================== O TRANSPORTE EM USO, POR JOGADOR (ADR-0109 · ADR-0113) =====================
|
|
82
|
+
//
|
|
83
|
+
// ⚠️ AQUI E NÃO NO `PlayerBase`, e a escolha é medida. O autómato responde «que aparelho está a produzir as
|
|
84
|
+
// arestas deste jogador» — isso é estado de ENTRADA, e a entrada já guarda estado por jogador neste módulo
|
|
85
|
+
// exactamente com esta forma: o `padCur` logo abaixo é um `Record<number, …>`. Pô-lo no `PlayerBase` faria
|
|
86
|
+
// dele parte do CONTRATO, e trezentos cartuchos passariam a declarar um campo sobre o qual não decidem nada.
|
|
87
|
+
//
|
|
88
|
+
// 📌 O que o jogador CARREGA é a alternância resolvida (`toggleMove`), que é o que a física lê. Este mapa é
|
|
89
|
+
// o que está a montante dela: com ele e com o `input/latch-store`, a resposta do ADR-0113 fica completa.
|
|
90
|
+
const entradaPorJogador = {};
|
|
91
|
+
/**
|
|
92
|
+
* O ESTADO DA ENTRADA DESTE JOGADOR. Nunca `undefined`: quem nunca produziu uma aresta está no PADRÃO.
|
|
93
|
+
*
|
|
94
|
+
* ⚠️ `PADRAO` E NÃO `undefined`, pela mesma razão que o `origemDe` faz o contrário: ali «não sei» é uma
|
|
95
|
+
* resposta honesta sobre uma tecla que já existe; aqui a pergunta é sobre um JOGADOR, e um jogador que
|
|
96
|
+
* ainda não tocou em nada está mesmo no teclado sem assistida — que é o que `PADRAO` diz.
|
|
97
|
+
*/
|
|
98
|
+
export function entradaDe(jogador) {
|
|
99
|
+
return entradaPorJogador[jogador] ?? PADRAO;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* UMA ARESTA DESTE JOGADOR CHEGOU, com a sua origem.
|
|
103
|
+
*
|
|
104
|
+
* 📌 O `aposAresta` devolve o MESMO objecto quando nada muda, então guardar de volta não aloca por quadro.
|
|
105
|
+
* ⚠️ E uma aresta de um transporte assistido NÃO o habilita — essa regra vive no `aposAresta` e a razão
|
|
106
|
+
* está lá: um falso positivo da webcam trancaria a alternância de toda a gente sem ninguém ter pedido.
|
|
107
|
+
*/
|
|
108
|
+
export function arestaDoJogador(jogador, origem) {
|
|
109
|
+
entradaPorJogador[jogador] = aposAresta(entradaDe(jogador), origem);
|
|
110
|
+
}
|
|
111
|
+
/** Habilitar a assistida é um ACTO EXPLÍCITO (ADR-0109 regra 4), e por isso tem porta própria. */
|
|
112
|
+
export function habilitarAssistidaDe(jogador) {
|
|
113
|
+
entradaPorJogador[jogador] = habilitarAssistida(entradaDe(jogador));
|
|
114
|
+
}
|
|
115
|
+
export function desabilitarAssistidaDe(jogador) {
|
|
116
|
+
entradaPorJogador[jogador] = desabilitarAssistida(entradaDe(jogador));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* ⚠️ ESQUECER É UMA PORTA SEPARADA, E O `soltarTodas` NÃO A CHAMA — de propósito.
|
|
120
|
+
*
|
|
121
|
+
* O `blur` da janela solta as teclas porque elas deixaram mesmo de estar premidas. Mas a criança não trocou
|
|
122
|
+
* de aparelho por mudar de separador: zerar o transporte em uso ali devolveria toda a gente ao teclado, e
|
|
123
|
+
* quem joga por olhar perderia a alternância no meio da partida sem nada o dizer. Existe para o fim de uma
|
|
124
|
+
* PARTIDA, onde a pergunta se põe de novo.
|
|
125
|
+
*/
|
|
126
|
+
export function esquecerEntradas() {
|
|
127
|
+
for (const k of Object.keys(entradaPorJogador))
|
|
128
|
+
delete entradaPorJogador[Number(k)];
|
|
129
|
+
}
|
|
7
130
|
export const padCur = {};
|
|
8
131
|
export const padPrevAct = {};
|
|
9
132
|
export const padPrevStart = {};
|
|
10
133
|
export const PAD_DEAD = 0.5; // zona morta = primeira METADE do curso do analógico (ergonomia — José 2026-07-02)
|
|
11
134
|
// Jogador está segurando a ação? teclado (algum code do esquema pl.ctrl) OU o gamepad associado (pl.pad).
|
|
12
|
-
|
|
135
|
+
// ⚠️ `?? []` e não `pl.ctrl[act]` cru: desde a issue #118 uma posição que o teclado NÃO ALCANÇA é um `null`
|
|
136
|
+
// declarado — num teclado partido por quatro não há lugar físico para ombros e gatilhos. Segurar uma ação
|
|
137
|
+
// que o teclado não alcança é `false`, e o gamepad continua a ser perguntado logo a seguir: quem tem pad
|
|
138
|
+
// alcança o que o teclado dele não alcança, que é o ponto de haver dois transportes.
|
|
139
|
+
export const held = (pl, act) => (pl.ctrl[act] ?? []).some((k) => keys.has(k)) || (pl.pad >= 0 && !!padCur[pl.pad]?.[act]);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
import type { Transporte } from './transporte-em-uso.js';
|
|
2
3
|
import { type RectLike } from './pointer-space.js';
|
|
3
4
|
import type { PlayerView } from '../core/entity.js';
|
|
4
5
|
import type { DomQuery } from '../core/dom-query.js';
|
|
@@ -172,8 +173,26 @@ export interface TouchBindingsCtx {
|
|
|
172
173
|
getControls: () => KeyScheme;
|
|
173
174
|
/** o array vivo de jogadores. Getter: o main.js o repovoa a cada `restartGame`. */
|
|
174
175
|
getPlayers: () => readonly TouchBindPlayer[];
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
marcarTecla: (code: string, origem: Transporte) => void;
|
|
177
|
+
/**
|
|
178
|
+
* ESTA ARESTA É DESTE JOGADOR, E VEIO DO TOQUE (ADR-0113 cláusula 4, issue #127) —
|
|
179
|
+
* `input/state.arestaDoJogador`.
|
|
180
|
+
*
|
|
181
|
+
* 🔴 OBRIGATÓRIO, e é aqui que a troca de aparelho fica VISÍVEL: o toque é o transporte que a criança usa
|
|
182
|
+
* ao lado do teclado, e sem esta linha o autómato responde `teclado` mesmo com o dedo no ecrã — logo a
|
|
183
|
+
* alternância lida seria a do teclado, no aparelho errado. 📌 O `onTouchControlsShown` do cartucho
|
|
184
|
+
* (`main.ts:1695`) é o remendo que existe hoje exactamente para compensar esta falta.
|
|
185
|
+
*/
|
|
186
|
+
arestaDoJogador: (jogador: number, origem: Transporte) => void;
|
|
187
|
+
soltarTecla: (code: string) => void;
|
|
188
|
+
/**
|
|
189
|
+
* O conjunto para LER — a decisão pura pergunta que teclas já estão seguradas.
|
|
190
|
+
*
|
|
191
|
+
* ⚠️ `ReadonlySet` e não `Set`, e a diferença é a razão de este par existir: LER o conjunto nunca foi o
|
|
192
|
+
* problema; ESCREVER nele é que apagava a origem. O tipo passa a dizer isso, e uma escrita crua que
|
|
193
|
+
* voltasse aqui deixa de compilar em vez de passar despercebida.
|
|
194
|
+
*/
|
|
195
|
+
readonly heldKeys: ReadonlySet<string>;
|
|
177
196
|
/** `game/attract.ts`: zera a ociosidade e encerra a demo; `true` = o toque foi só para acordar.
|
|
178
197
|
* LAZY obrigatoriamente — `attractCtl` é `const` declarado ABAIXO do ponto de init no main.js. */
|
|
179
198
|
attractOnInput: () => boolean;
|
|
@@ -85,6 +85,10 @@
|
|
|
85
85
|
/** `ui/dom.ts` `$` — injetado; o módulo nunca alcança `document`. */
|
|
86
86
|
import { EDGE_BY_ACTION, edgeAllowed } from './edges.js';
|
|
87
87
|
import { doCentro } from './pointer-space.js';
|
|
88
|
+
// `isAction` guarda a porta: o `act` chega como string de um `data-` do markup de toque, e desde a #118 o
|
|
89
|
+
// esquema só aceita as quatorze posições. Uma string que não é posição devolve `null` — o toque não faz nada,
|
|
90
|
+
// que é exactamente o que o cabeçalho desta função já prometia.
|
|
91
|
+
import { isAction } from '../core/actions.js';
|
|
88
92
|
/* ===================== PURO (sem DOM — project node) ===================== */
|
|
89
93
|
/**
|
|
90
94
|
* Ação → borda, na MESMA ordem das outras duas cópias do projeto.
|
|
@@ -106,7 +110,7 @@ export function wantsForcedTouch(search) {
|
|
|
106
110
|
* `null` = a ação não existe no esquema (ou o slot do mapa de toque está vazio) → o toque não faz nada.
|
|
107
111
|
*/
|
|
108
112
|
export function codeForAction(act, controls) {
|
|
109
|
-
if (!act)
|
|
113
|
+
if (!act || !isAction(act))
|
|
110
114
|
return null;
|
|
111
115
|
const list = controls[act];
|
|
112
116
|
return (list && list[0]) || null;
|
|
@@ -220,16 +224,24 @@ export function initTouchBindings(ctx) {
|
|
|
220
224
|
return;
|
|
221
225
|
}
|
|
222
226
|
if (d.kind === 'release') {
|
|
223
|
-
ctx.
|
|
227
|
+
ctx.soltarTecla(d.code);
|
|
224
228
|
return;
|
|
225
229
|
}
|
|
226
230
|
if (d.addKey) {
|
|
227
|
-
|
|
231
|
+
// ⚠️ `'toque'` é o carimbo, e é a regra 2 do ADR-0109 a tornar-se executável: é ESTE transporte cuja
|
|
232
|
+
// alternância liga. Enquanto o código entrava cru no conjunto, a regra não tinha como se aplicar.
|
|
233
|
+
ctx.marcarTecla(d.code, 'toque');
|
|
228
234
|
const players = ctx.getPlayers();
|
|
229
235
|
for (const { playerIndex, edge } of d.edges) {
|
|
230
236
|
const p = players[playerIndex];
|
|
231
237
|
if (p)
|
|
232
238
|
p[edge] = true;
|
|
239
|
+
// 📌 A ARESTA POR JOGADOR, ao lado da borda que ela levanta — e não uma vez por toque: o mesmo código
|
|
240
|
+
// pode pertencer a mais de um assento (`d.edges` é construído com `includes` sobre o esquema de cada
|
|
241
|
+
// um), e o transporte em uso é uma pergunta POR CRIANÇA. Marcar só o jogador 0 daria a alternância do
|
|
242
|
+
// primeiro assento a quem joga no segundo.
|
|
243
|
+
if (p)
|
|
244
|
+
ctx.arestaDoJogador(playerIndex, 'toque');
|
|
233
245
|
}
|
|
234
246
|
}
|
|
235
247
|
if (d.hideTips)
|
package/dist-pkg/input/touch.js
CHANGED
|
@@ -135,7 +135,15 @@ export function initTouch(ctx) {
|
|
|
135
135
|
// ⚠️ A palavra falada é a MESMA que a lida: sai da mesma lista que acabou de montar o `<option>`.
|
|
136
136
|
// Antes vinham de tabelas diferentes e nada obrigava as duas a concordar.
|
|
137
137
|
const escolhida = ctx.acoesDoJogo().find((x) => x.acao === sel.value);
|
|
138
|
-
|
|
138
|
+
const nomeDoSlot = label || t('touch.slot.fallback');
|
|
139
|
+
// ⚠️ SEM PALAVRA DO JOGO, O ANÚNCIO PERDE A POSIÇÃO — NÃO RECUA PARA O ID. `sel.value` é o nome
|
|
140
|
+
// ABSTRATO (`action3`), e o ADR-0074 diz que ele nunca chega a uma pessoa; o `7742ac0` já pagou este
|
|
141
|
+
// defeito no ecrã de remapeamento e a saída é a mesma: uma chave própria que diz o que importa.
|
|
142
|
+
// 📌 O recuo é alcançável porque `acoesDoJogo()` é FUNÇÃO do cartucho, relida a cada `change`: num hub
|
|
143
|
+
// de atividades a lista muda por baixo e a `<option>` desenhada antes fica órfã.
|
|
144
|
+
ctx.srSay(escolhida
|
|
145
|
+
? t('sr.touch.slotSet', { slot: nomeDoSlot, acao: escolhida.rotulo })
|
|
146
|
+
: t('sr.touch.slotSetUnnamed', { slot: nomeDoSlot }));
|
|
139
147
|
});
|
|
140
148
|
});
|
|
141
149
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/** Os aparelhos por onde uma criança joga. Fechado: um transporte novo tem de decidir a sua regra aqui. */
|
|
3
|
+
export type Transporte = 'teclado' | 'gamepad' | 'toque' | 'olhos' | 'rosto' | 'gestos' | 'fala';
|
|
4
|
+
/**
|
|
5
|
+
* A UNIÃO COMO VALOR, porque há um sítio onde ela tem de ser verificada em runtime.
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ EXISTE POR CAUSA DE UMA FRONTEIRA, e é a única razão que a justifica: o `input/origem-sintetica` lê o
|
|
8
|
+
* transporte de um EXPANDO pendurado num `KeyboardEvent` — um objecto que este código não construiu e que
|
|
9
|
+
* qualquer script da página pode construir. Um valor que atravessa essa fronteira não é um `Transporte` por
|
|
10
|
+
* o TypeScript o dizer; é uma `string` até alguém a conferir. Sem lista, `'olho'` entrava no mapa de origens
|
|
11
|
+
* como transporte fantasma, e nada o diria.
|
|
12
|
+
*
|
|
13
|
+
* 📌 Não é o defeito da lista-ao-lado-da-união que este repositório já desfez três vezes (o `RM_KEYS`, os
|
|
14
|
+
* rótulos de movimento reduzido, as chaves de armazenamento), porque a guarda abaixo é do COMPILADOR: as duas
|
|
15
|
+
* não podem divergir. Uma cópia que não pode divergir é uma projecção, não uma segunda fonte.
|
|
16
|
+
*/
|
|
17
|
+
export declare const TRANSPORTES: readonly ["teclado", "gamepad", "toque", "olhos", "rosto", "gestos", "fala"];
|
|
18
|
+
/**
|
|
19
|
+
* Isto que veio de fora é mesmo um transporte?
|
|
20
|
+
*
|
|
21
|
+
* ⚠️ A pergunta não é de segurança — os scripts desta página são todos da casa, e quem quisesse mentir usaria
|
|
22
|
+
* um valor VÁLIDO. É de correcção: impede que um carimbo errado ou ausente vire uma entrada silenciosa no
|
|
23
|
+
* `origemDaTecla`, que é a estrutura de que a alternância inteira depende.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ehTransporte(v: unknown): v is Transporte;
|
|
26
|
+
/**
|
|
27
|
+
* OS QUATRO QUE EXIGEM HABILITAÇÃO EXPLÍCITA e, uma vez habilitados, mandam em todos (regra 4).
|
|
28
|
+
*
|
|
29
|
+
* ⚠️ É a mesma lista do `UM_COMANDO_DE_CADA_VEZ` do `input/latch-scope`, e a coincidência não é acaso: são
|
|
30
|
+
* os transportes de quem NÃO CONSEGUE SEGURAR NADA. O que o ADR-0109 acrescenta é que eles não ligam a
|
|
31
|
+
* alternância só para si — ligam-na para o resto, porque quem usa a webcam pode também tocar na tela, e uma
|
|
32
|
+
* alternância que se desliga ao mudar de aparelho é uma armadilha para exactamente essa pessoa.
|
|
33
|
+
*/
|
|
34
|
+
export declare const EXIGEM_HABILITACAO: ReadonlySet<Transporte>;
|
|
35
|
+
/** O transporte que liga a alternância por si só, sem prioridade nenhuma envolvida (regra 2). */
|
|
36
|
+
export declare const COM_ALTERNANCIA_PROPRIA: ReadonlySet<Transporte>;
|
|
37
|
+
export interface EstadoDaEntrada {
|
|
38
|
+
/** Qual aparelho está a ser usado AGORA por este jogador. */
|
|
39
|
+
readonly emUso: Transporte;
|
|
40
|
+
/**
|
|
41
|
+
* A câmera/microfone foi habilitada? ⚠️ Uma vez `true`, NUNCA volta a `false` por uma aresta — só uma
|
|
42
|
+
* decisão explícita a desliga, e o ADR-0109 §4 diz que a criança não tem essa decisão. Ver `desabilitar`.
|
|
43
|
+
*/
|
|
44
|
+
readonly assistidaLigada: boolean;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* O ESTADO INICIAL: teclado, sem alternância.
|
|
48
|
+
*
|
|
49
|
+
* ⚠️ A regra 1 diz «controle E teclado, ambos sem alternância», e é por isso que o padrão pode nomear um só
|
|
50
|
+
* sem mentir: entre os dois a resposta à única pergunta que este módulo faz — há alternância? — é a MESMA.
|
|
51
|
+
* O `emUso` só passa a distingui-los quando alguém quiser MOSTRAR o aparelho corrente, que é outra questão
|
|
52
|
+
* e o ADR-0109 deixa-a explicitamente por decidir.
|
|
53
|
+
*/
|
|
54
|
+
export declare const PADRAO: EstadoDaEntrada;
|
|
55
|
+
/**
|
|
56
|
+
* HÁ ALTERNÂNCIA AGORA? — ⚠️ **NÃO PERGUNTE ISTO A ESTA FUNÇÃO.** Ver o parágrafo abaixo.
|
|
57
|
+
*
|
|
58
|
+
* ⚠️ A prioridade da assistida vem PRIMEIRO, e a ordem é a regra 4 inteira: enquanto ela estiver ligada,
|
|
59
|
+
* nenhum outro aparelho a desliga — nem o teclado, que noutro caso a desligaria. Inverter estas duas linhas
|
|
60
|
+
* é o defeito que trancaria uma criança fora do próprio jogo, e é silencioso.
|
|
61
|
+
*
|
|
62
|
+
* @deprecated 🔴 **ESTA FUNÇÃO IMPLEMENTA O MODELO QUE O ADR-0113 SUPERSEDEU**, e fica exportada por ser
|
|
63
|
+
* superfície publicada (`./input/*.js`) e por o registo ter valor histórico — não por ser a resposta.
|
|
64
|
+
*
|
|
65
|
+
* O ADR-0109 decidia a alternância **só pelo aparelho**: assistida ligada → sim; toque → sim; todo o resto
|
|
66
|
+
* → não. O ADR-0113 retirou essa cláusula, com a razão do Dev: a alternância é um **caps-lock guardado com
|
|
67
|
+
* o mapeamento do controle**, e o valor que a criança gravou vale.
|
|
68
|
+
*
|
|
69
|
+
* 🔴 A DIVERGÊNCIA TEM UMA CRIANÇA CONCRETA, e é a que motivou o registo: quem tem dificuldade motora, joga
|
|
70
|
+
* no TECLADO e gravou a alternância ligada. Esta função devolve `false` para ela — `teclado` não está em
|
|
71
|
+
* `COM_ALTERNANCIA_PROPRIA` — e é exactamente o controle que lhe seria retirado. O `latch-scope.alternanciaDe`
|
|
72
|
+
* devolve `true`, porque lê o que ela gravou.
|
|
73
|
+
*
|
|
74
|
+
* ⚠️ E A CLÁUSULA DO TOQUE TAMBÉM CAIU: sob o ADR-0113 o toque é um transporte como os outros — o valor dele
|
|
75
|
+
* é escolha e fica guardado. Só olhos, rosto, gestos e fala podem recusar-se a DESLIGAR, e essa metade vive
|
|
76
|
+
* em `latch-scope.alternanciaSempreLigada`, com um conjunto diferente deste e a responder a outra pergunta.
|
|
77
|
+
*
|
|
78
|
+
* **A resposta certa é `latch-scope.alternanciaDe(estado.emUso, leitura)`.** O papel que sobra a este
|
|
79
|
+
* módulo é o que o nome dele diz: QUAL transporte está em uso — que é o que alimenta aquele primeiro
|
|
80
|
+
* argumento. `tests/alternancia-por-transporte.node.test.js` afirma que esta função continua sem consumidor.
|
|
81
|
+
*/
|
|
82
|
+
export declare function alternanciaAgora(estado: EstadoDaEntrada): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* UMA ARESTA CHEGOU, com a sua origem. Devolve o estado NOVO.
|
|
85
|
+
*
|
|
86
|
+
* ⚠️ Uma aresta de um transporte assistido NÃO o habilita. Habilitar é um acto explícito (regra 4: «precisam
|
|
87
|
+
* ser habilitados»), e deixar uma aresta fazê-lo significaria que um falso positivo da webcam — uma sombra,
|
|
88
|
+
* um segundo rosto a passar — trancava a alternância de toda a gente sem ninguém ter pedido.
|
|
89
|
+
*/
|
|
90
|
+
export declare function aposAresta(estado: EstadoDaEntrada, origem: Transporte): EstadoDaEntrada;
|
|
91
|
+
/** A criança (ou quem a acompanha) habilitou câmera/microfone. Daqui em diante a alternância é lei. */
|
|
92
|
+
export declare function habilitarAssistida(estado: EstadoDaEntrada): EstadoDaEntrada;
|
|
93
|
+
/**
|
|
94
|
+
* DESABILITAR a assistida. Existe, e o ADR-0109 diz de quem é: NÃO é da criança durante a partida.
|
|
95
|
+
*
|
|
96
|
+
* ⚠️ Fica exportada porque desligar a câmera tem de ser possível em algum lugar — trocar de utilizador,
|
|
97
|
+
* fechar o jogo, um adulto a reconfigurar. O que o §4 proíbe é oferecê-la como um botão ao lado do jogo.
|
|
98
|
+
* Uma função que existe e não é oferecida é diferente de uma função que não existe: a primeira diz onde a
|
|
99
|
+
* decisão mora.
|
|
100
|
+
*/
|
|
101
|
+
export declare function desabilitarAssistida(estado: EstadoDaEntrada): EstadoDaEntrada;
|