Refactoring: one file per node, consistent comments, shared helpers, split large modules
- Graph: nodes.ts split into nodes/<category>/<Type>.ts (62 files) with shared.ts factories and index.ts registry; NodeContext/values/NodeRegistry separated, writeTyped() replaces duplicated typed writes - Comments: one style (JSDoc on non-obvious exports, // for decisions and traps), wrong/stale comments fixed or removed, ids.ts now real 10 base-36 chars - Core: chainOf, shared worldPosition/editorPosition core, commands/require.ts, commands/naming.ts, util/list.ts, setBagValue/toPosition/propDef; dead code removed (isBehaviorAsset, SCENE_OBJECT_SCHEMA, CommandStack.subscribe, Input.axis, setMode, titleText, World.worldPosition, unused ctor params) - Editor: Inspector split into inspector/ sections, App.ts into Editor.ts + debugHook.ts + shortcuts.ts, Viewport into items.ts + symbols.ts, shared "Add collider" action, unified type labels/swatches - UI toolkit: Widget.trackHover/onPointerRelease, drawControlBox, math helpers, Popup.openBelow, Menu/Dialog/ColorPicker/ListRow in own files, named Theme sizes - Tools: seed-demo/smoke-demo and demo-check project removed, tools/lib (harness, projects, builders), e2e.mjs as runner over tools/e2e/*.mjs sections - Tests: tests/helpers.ts replaces copied fixtures and NodeContext doubles Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
3234eb480f
commit
1eb28314cf
189 files changed
+6231
-5543
No files matched your search
@@ -42,6 +42,11 @@ export class BehaviorSystem implements System {
|
||||
this.syncInstances(world);
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
this.instances = [];
|
||||
this.world = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* One instance per behavior entity: entities that appeared (placed while playing) get an
|
||||
* interpreter and their `On start`; instances whose entity is gone are dropped. A behavior
|
||||
@@ -56,7 +61,10 @@ export class BehaviorSystem implements System {
|
||||
if (!asset || asset.type !== 'behavior') continue;
|
||||
const trace: Trace = { edges: new Map(), nodes: new Map() };
|
||||
const interpreter = new GraphInterpreter(asset.graph);
|
||||
interpreter.trace = this.traceListener(trace, world);
|
||||
interpreter.trace = {
|
||||
onEdge: (id) => trace.edges.set(id, world.time),
|
||||
onNode: (id) => trace.nodes.set(id, world.time),
|
||||
} satisfies TraceListener;
|
||||
const instance = { entity, interpreter, trace };
|
||||
this.instances.push(instance);
|
||||
this.run(instance, (i, ctx) => i.fire('OnStart', ctx), 0);
|
||||
@@ -117,22 +125,21 @@ export class BehaviorSystem implements System {
|
||||
fire('OnCollisionExit', this.collisions.exits);
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
this.instances = [];
|
||||
this.world = null;
|
||||
}
|
||||
|
||||
/** Live highlight data for the graph editor: merged over all instances of the asset. */
|
||||
traceFor(assetId: string): Trace {
|
||||
const merged: Trace = { edges: new Map(), nodes: new Map() };
|
||||
const latest = (into: Map<string, number>, from: Map<string, number>) => {
|
||||
for (const [id, t] of from) into.set(id, Math.max(t, into.get(id) ?? -Infinity));
|
||||
};
|
||||
for (const instance of this.instances) {
|
||||
if (instance.entity.assetId !== assetId) continue;
|
||||
for (const [id, t] of instance.trace.edges) merged.edges.set(id, Math.max(t, merged.edges.get(id) ?? -Infinity));
|
||||
for (const [id, t] of instance.trace.nodes) merged.nodes.set(id, Math.max(t, merged.nodes.get(id) ?? -Infinity));
|
||||
latest(merged.edges, instance.trace.edges);
|
||||
latest(merged.nodes, instance.trace.nodes);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
/** Runs graph code for one instance; an exception stops play and is logged, never thrown. */
|
||||
private run(instance: Instance, body: (interpreter: GraphInterpreter, ctx: NodeContext) => void, dt: number): void {
|
||||
const world = this.world;
|
||||
if (!world) return;
|
||||
@@ -146,6 +153,9 @@ export class BehaviorSystem implements System {
|
||||
}
|
||||
|
||||
private context(entity: Entity, world: World, dt: number): NodeContext {
|
||||
// Handles arriving from the graph are the entities themselves, or test doubles with the same id.
|
||||
const resolve = (handle: EntityHandle | null): Entity | undefined =>
|
||||
handle ? world.entities.find((e) => e === handle || e.id === handle.id) : undefined;
|
||||
return {
|
||||
self: entity,
|
||||
owner: entity.parent,
|
||||
@@ -156,16 +166,16 @@ export class BehaviorSystem implements System {
|
||||
isKeyDown: (key) => this.input.isDown(key),
|
||||
pointer: world.pointer,
|
||||
hitTest: (target, x, y) => {
|
||||
const found = world.entities.find((e) => e === target || e.id === target.id);
|
||||
const found = resolve(target);
|
||||
return Boolean(found && world.hitTest(found, x, y));
|
||||
},
|
||||
isTouching: (a, b) => {
|
||||
const ea = world.entities.find((e) => e === a || e.id === a.id);
|
||||
const eb = world.entities.find((e) => e === b || e.id === b.id);
|
||||
const ea = resolve(a);
|
||||
const eb = resolve(b);
|
||||
return Boolean(this.collisions && ea && eb && this.collisions.touching(world, ea, eb));
|
||||
},
|
||||
moveAndSlide: (target, dx, dy) => {
|
||||
const found = world.entities.find((e) => e === target || e.id === target.id);
|
||||
const found = resolve(target);
|
||||
if (!found) return { blockedX: false, blockedY: false };
|
||||
if (this.collisions) return this.collisions.moveAndSlide(world, found, dx, dy);
|
||||
found.x += dx;
|
||||
@@ -176,12 +186,9 @@ export class BehaviorSystem implements System {
|
||||
world.log.push(message);
|
||||
console.log(`[behavior ${entity.name}]`, message);
|
||||
},
|
||||
spawn: (assetId, position, parent) => {
|
||||
const parentEntity = parent ? world.entities.find((e) => e === parent || e.id === parent.id) ?? null : null;
|
||||
return world.spawn(assetId, position, parentEntity);
|
||||
},
|
||||
destroy: (target: EntityHandle) => {
|
||||
const found = world.entities.find((e) => e === target || e.id === target.id);
|
||||
spawn: (assetId, position, parent) => world.spawn(assetId, position, resolve(parent) ?? null),
|
||||
destroy: (target) => {
|
||||
const found = resolve(target);
|
||||
if (found) world.remove(found);
|
||||
},
|
||||
stop: () => {
|
||||
@@ -192,11 +199,4 @@ export class BehaviorSystem implements System {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private traceListener(trace: Trace, world: World): TraceListener {
|
||||
return {
|
||||
onEdge: (id) => trace.edges.set(id, world.time),
|
||||
onNode: (id) => trace.nodes.set(id, world.time),
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user