Stop a key getting stuck when Shift changes it while held (#227)
Input remembered keys under KeyboardEvent.key. Pressing a, adding Shift and letting go sent "A" on release, which matched nothing, so "a" stayed down until the next release without Shift. - New rule keyName in src/core/keys.ts lowercases a single character. So a and A are the same key, also under Caps Lock. - Input remembers per physical key (e.code) under which name it went down and releases exactly that name. So 1 released as ! is freed too, which lowercasing alone does not cover. - On key down, up and held, Key is down and Axis input compare with the same rule. A node that already stores A reacts to a. - Recording a key in the inspector stores Shift+A as a. - Limit: holding Shift before pressing 1 still sends !, and a node on 1 does not react. Nothing gets stuck by it. Tests: - 3 new unit tests in tests/core/behavior-events.test.ts: the flow from the issue, 1 released as !, and a node on A hearing a. - Without lowercasing exactly the issue test and the A test fail. - Without the code memory exactly the 1/! test fails. - ./check.sh: 159 files, 2340 tests, CHECK EXIT 0 (before 2337). - No e2e change, the check sum stays at 1377. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c1a6d63edb
commit
ffb5bbe039
5 files changed
+79
-11
No files matched your search
@@ -22,6 +22,7 @@ import {
|
||||
type Value,
|
||||
} from '../../core/graph';
|
||||
import { stepKeyRepeat } from '../../core/graph/keyRepeat';
|
||||
import { keyName } from '../../core/keys';
|
||||
import { graphLookup } from '../../core/model/graphLookup';
|
||||
import { type PropertyBag, textOf, type Vec2 } from '../../core/model/Properties';
|
||||
import { findAssetOf, findScene, type Project } from '../../core/model/Project';
|
||||
@@ -436,7 +437,7 @@ export class BehaviorSystem implements System {
|
||||
|
||||
update(world: World, dt: number): void {
|
||||
this.syncInstances(world);
|
||||
const keyOf = (node: { params: PropertyBag }) => textOf(node.params.key ?? '');
|
||||
const keyOf = (node: { params: PropertyBag }) => keyName(textOf(node.params.key ?? ''));
|
||||
const frozen = world.frozen;
|
||||
for (const instance of this.instances) {
|
||||
if (!world.entities.includes(instance.entity)) continue; // destroyed this frame, reaped below
|
||||
@@ -490,7 +491,7 @@ export class BehaviorSystem implements System {
|
||||
* in `nodeState`, so two nodes on the same key repeat on their own schedules.
|
||||
*/
|
||||
private fireKeyDown(i: GraphInterpreter, ctx: NodeContext, node: GraphNode, dt: number): void {
|
||||
const key = textOf(node.params.key ?? '');
|
||||
const key = keyName(textOf(node.params.key ?? ''));
|
||||
const stored = i.nodeState.get(node.id);
|
||||
const { state, fires } = stepKeyRepeat(
|
||||
stored ? { held: stored.held ?? 0, repeats: stored.repeats ?? 0 } : null,
|
||||
|
||||
Reference in new issue
Block a user