Remove exports and methods nothing uses any more

A reference search over every export and method in src/ found code that
only tests still called, or that was never called at all:

- RemoveSceneObjectCommand: the product only removes through the
  multi-object command; the tests now use that one too.
- NodeRegistry.requireNodeDef: a second function of the same name in
  commands/require.ts raises a CommandError instead of throwing, and is
  the one the product uses. The twin invited the wrong import.
- isTextureAsset, listContainers, AssetTabEditor.show,
  FocusManager.destroy, KeyboardBridge.selectAll and the getters
  ColorField.value, ListView.selected, NumberField.number.

Also: Theme.controlActive now matches the resting control colour, and a
new note asks what editing the graph during play would take.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5 committed 2026-09-11 20:15:49 +02:00
1 parent 0376ae175d
commit 495756b500
24 files changed
+22 -77

No files matched your search

+1 -4
View File
@@ -62,10 +62,7 @@ export function requireNode(project: Project, assetId: string, nodeId: string):
return node;
}
/**
* `NodeRegistry.requireNodeDef` throws a plain `Error`, which the editor does not catch; a command
* needs a `CommandError` so an unknown type becomes a notice instead of a crash.
*/
/** A `CommandError`, so an unknown type becomes a notice instead of a crash. */
export function requireNodeDef(type: string): NodeDef {
const def = nodeDef(type);
if (!def) throw new CommandError(`Unknown node type "${type}"`);
-6
View File
@@ -111,12 +111,6 @@ export class RemoveSceneObjectsCommand implements Command {
}
}
export class RemoveSceneObjectCommand extends RemoveSceneObjectsCommand {
constructor(holderId: string, objectId: string) {
super(holderId, [objectId]);
}
}
/**
* The previous position is read at execution time, so a caller that previewed the move must
* restore the model before executing.
-6
View File
@@ -111,12 +111,6 @@ export function nodeDef(type: string): NodeDef | undefined {
return defs.get(type);
}
export function requireNodeDef(type: string): NodeDef {
const def = defs.get(type);
if (!def) throw new Error(`Unknown node type "${type}"`);
return def;
}
export function allNodeDefs(): NodeDef[] {
return [...defs.values()];
}
-4
View File
@@ -86,7 +86,3 @@ export type Asset =
export function isSceneAsset(asset: Asset): asset is SceneAsset {
return asset.type === 'scene';
}
export function isTextureAsset(asset: Asset): asset is TextureAsset {
return asset.type === 'texture';
}
-4
View File
@@ -64,7 +64,3 @@ export function findObjectHolder(project: Project, holderId: string): ObjectHold
const asset = findAsset(project, holderId);
return asset && isObjectHolder(asset) ? asset : undefined;
}
export function listContainers(project: Project): ContainerAsset[] {
return project.assets.filter((a): a is ContainerAsset => a.type === 'container');
}
-5
View File
@@ -85,11 +85,6 @@ export abstract class AssetTabEditor<
return this.canvas.currentAssetId;
}
show(assetId: string): void {
this.canvas.show(assetId);
this.refresh();
}
/** The selection's id for this kind of asset, `''` when the selection is about something else. */
protected abstract selectedId(): string;
-4
View File
@@ -91,10 +91,6 @@ export class FocusManager {
}
}
}
destroy(): void {
window.removeEventListener('keydown', this.onKeyDown);
}
}
function isAttached(node: Container, root: Container): boolean {
-5
View File
@@ -88,11 +88,6 @@ export class KeyboardBridge {
if (document.activeElement === this.input) this.input.setSelectionRange(selectionStart, selectionEnd);
}
/** The field learns about it through the usual `onBridgeInput` sync. */
selectAll(): void {
this.input.select();
}
/** Ignored when another field attached meanwhile, so a late blur cannot steal it. */
detach(target: TextEditTarget): void {
if (this.target !== target) return;
+1 -1
View File
@@ -26,7 +26,7 @@ export const Theme = {
border: 0x383c46,
control: 0x16181d,
controlHover: 0x1e2127,
controlActive: 0x2a2e37,
controlActive: 0x16181d,
accent: 0x4c8dff,
accentText: 0xffffff,
text: 0xe6e8ee,
-5
View File
@@ -57,11 +57,6 @@ export class ColorField extends Widget {
this.addChild(this.row);
}
/** The last valid color: an invalid hex being typed does not change it. */
get value(): number {
return this.color;
}
/** Model → view update: refreshes the hex text and an open picker without firing callbacks. */
setValue(color: number): void {
if (color === this.color) return;
-4
View File
@@ -92,10 +92,6 @@ export class ListView extends Widget {
this.onPointerRelease(() => this.onDragEnd());
}
get selected(): string | null {
return this.selectedId;
}
/**
* Rebuilds all rows. The selection survives when its id is still present and is dropped
* silently otherwise; highlights are kept as they are (the owner refreshes them).
-5
View File
@@ -85,11 +85,6 @@ export class NumberField extends TextField {
});
}
/** The clamped numeric value; while typing, the last valid parse of the text. */
get number(): number {
return this.numeric;
}
/** The one place the value becomes text, so every path honours `decimals`. */
private get display(): string {
return formatNumber(this.numeric, this.decimals);
+1 -1
View File
@@ -82,7 +82,7 @@ export function collectWorldItems(world: World): DrawList {
props: e.props,
parentId: e.parent?.objectId ?? '',
enabled: true,
// Resolved per frame on purpose: a behavior may swap `texture` with `Set property`.
// Resolved per frame on purpose: a `Properties` node may swap `texture`.
texture: e.type === 'sprite' ? resolveTexture(world.project, e.props) : null,
}));
return { items, background: world.backgroundColor };
+2 -2
View File
@@ -11,7 +11,7 @@ import {
ClearOverrideCommand,
MoveSceneObjectCommand,
PlaceAssetCommand,
RemoveSceneObjectCommand,
RemoveSceneObjectsCommand,
SetOverrideCommand,
} from '../../src/core/commands/sceneObjectCommands';
import { findAsset } from '../../src/core/model/Project';
@@ -132,7 +132,7 @@ describe('scene object commands', () => {
stack.undo();
expect(object(box).overrides).toEqual({ color: 0x123456 });
stack.execute(new RemoveSceneObjectCommand(sceneId, box));
stack.execute(new RemoveSceneObjectsCommand(sceneId, [box]));
expect(sceneOf().objects).toHaveLength(0);
stack.undo();
expect(object(box).position).toEqual({ x: 40, y: 50, z: 3 });
+3 -4
View File
@@ -6,7 +6,6 @@ import { CreateContainerCommand, UnpackContainerCommand } from '../../src/core/c
import {
MoveSceneObjectCommand,
PlaceAssetCommand,
RemoveSceneObjectCommand,
RemoveSceneObjectsCommand,
ReorderObjectCommand,
ClearOverrideCommand,
@@ -240,7 +239,7 @@ describe('editing a container template', () => {
expect(object(child(tA, instance)).overrides.width).toBe(55);
}
stack.execute(new RemoveSceneObjectCommand(containerId, tA));
stack.execute(new RemoveSceneObjectsCommand(containerId, [tA]));
expect(template(tA)).toBeUndefined();
expect(f.viewOf().objects.some((o) => o.id === child(tA, second))).toBe(false);
@@ -340,7 +339,7 @@ describe('a value changed on one instance', () => {
describe('the structure of a placed container', () => {
it('cannot be changed from the scene', () => {
const { stack, sceneId, tA, tB, child } = templateSetup();
expect(() => stack.execute(new RemoveSceneObjectCommand(sceneId, child(tA)))).toThrow(
expect(() => stack.execute(new RemoveSceneObjectsCommand(sceneId, [child(tA)]))).toThrow(
/comes from a container template/,
);
expect(() => stack.execute(new SetParentCommand(sceneId, child(tA), child(tB)))).toThrow(
@@ -373,7 +372,7 @@ describe('the structure of a placed container', () => {
stack.execute(new SetOverrideCommand(containerId, tA, 'width', 55));
expect(object(child(tA)).overrides.width).toBe(12);
stack.execute(new RemoveSceneObjectCommand(sceneId, child(tA)));
stack.execute(new RemoveSceneObjectsCommand(sceneId, [child(tA)]));
expect(sceneOf().objects.map((o) => o.id)).not.toContain(child(tA));
stack.undo();
+1 -1
View File
@@ -1,5 +1,6 @@
/** Ports a node works out for itself (`NodeDef.derivePorts`): from its settings, or from its own edges. */
import { describe, expect, it } from 'vitest';
import { requireNodeDef } from '../../src/core/commands/require';
import { AddPortCommand } from '../../src/core/commands/portCommands';
import { DisconnectCommand, SetNodeParamCommand } from '../../src/core/commands/graphCommands';
import {
@@ -8,7 +9,6 @@ import {
type GraphNode,
GraphInterpreter,
inlineInputs,
requireNodeDef,
resolveDef,
} from '../../src/core/graph';
import { behaviorLookup } from '../../src/core/model/behaviorPrograms';
+1 -1
View File
@@ -1,4 +1,5 @@
import { describe, expect, it } from 'vitest';
import { requireNodeDef } from '../../src/core/commands/require';
import { CommandError } from '../../src/core/commands/Command';
import {
AddNodeCommand,
@@ -21,7 +22,6 @@ import {
NO_BEHAVIORS,
type PortType,
portsCompatible,
requireNodeDef,
} from '../../src/core/graph';
import type { BehaviorAsset } from '../../src/core/model/Asset';
import { findAsset } from '../../src/core/model/Project';
+2 -2
View File
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
import { DeleteAssetCommand } from '../../src/core/commands/assetCommands';
import {
MoveSceneObjectCommand,
RemoveSceneObjectCommand,
RemoveSceneObjectsCommand,
ReorderObjectCommand,
SetParentCommand,
} from '../../src/core/commands/sceneObjectCommands';
@@ -126,7 +126,7 @@ describe('scene hierarchy', () => {
expect(object(logic).position).toEqual({ x: -100, y: -100, z: -1 });
stack.execute(new SetParentCommand(sceneId, b, a));
stack.execute(new RemoveSceneObjectCommand(sceneId, a));
stack.execute(new RemoveSceneObjectsCommand(sceneId, [a]));
expect(sceneOf().objects.map((o) => o.id)).toEqual([c]);
stack.undo();
expect(sceneOf().objects.map((o) => o.id)).toEqual([a, b, c, logic]);
+1 -6
View File
@@ -9,7 +9,7 @@ import { CreateContainerCommand } from '../../src/core/commands/containerCommand
import { SetOverrideCommand } from '../../src/core/commands/sceneObjectCommands';
import { RemoveVariableCommand, RenameVariableCommand } from '../../src/core/commands/variableCommands';
import type { ContainerAsset } from '../../src/core/model/Asset';
import { findAsset, findObjectHolder, listContainers, objectHolders } from '../../src/core/model/Project';
import { findAsset, findObjectHolder, objectHolders } from '../../src/core/model/Project';
import { instanceChildId } from '../../src/core/model/instance';
import { findUsages } from '../../src/core/model/usages';
import { makeBehavior, makeSpriteScene, place } from '../helpers';
@@ -47,11 +47,6 @@ describe('object holders', () => {
expect(findObjectHolder(project, 'nope')).toBeUndefined();
});
it('lists the container assets on their own', () => {
const { project, containerId } = containerWithOverride();
expect(listContainers(project).map((c) => c.id)).toEqual([containerId]);
});
it('finds usages inside container templates, not just in scenes', () => {
const { project, behaviorId, containerId, template } = containerWithOverride();
// Only the template: what the scene shows is resolved from it, never stored.
+1 -1
View File
@@ -3,13 +3,13 @@
* fails `covers every built-in node`. The run-less event nodes are listed in `EVENT_NODES`.
*/
import { describe, expect, it } from 'vitest';
import { requireNodeDef } from '../../src/core/commands/require';
import { BUILT_IN_NODES } from '../../src/core/graph/nodes';
import {
createEmptyGraph,
type DeclaredPort,
NO_BEHAVIORS,
type NodeContext,
requireNodeDef,
resolveDef,
type RunResult,
type Value,
-2
View File
@@ -1,7 +1,6 @@
import { describe, expect, it } from 'vitest';
import { CreateAssetCommand, CreateTextureCommand } from '../../src/core/commands/assetCommands';
import { CommandError } from '../../src/core/commands/Command';
import { isTextureAsset } from '../../src/core/model/Asset';
import { findAsset } from '../../src/core/model/Project';
import { spriteFromTexture } from '../../src/core/properties/aspect';
import { makeProject } from '../helpers';
@@ -15,7 +14,6 @@ describe('CreateTextureCommand', () => {
stack.execute(command);
const asset = findAsset(project, command.asset.id);
expect(asset && isTextureAsset(asset)).toBe(true);
expect(asset).toMatchObject({ type: 'texture', name: 'Hero', file: FILE, width: 64, height: 32 });
// The schema default comes along, so the new texture is a complete asset – nothing to fill in later.
expect(asset?.props).toEqual({ filter: 'linear' });
+3 -3
View File
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest';
import { SetAssetPropertyCommand } from '../../src/core/commands/assetCommands';
import {
ClearOverrideCommand,
RemoveSceneObjectCommand,
RemoveSceneObjectsCommand,
SetOverrideCommand,
SetParentCommand,
} from '../../src/core/commands/sceneObjectCommands';
@@ -45,7 +45,7 @@ describe('world ↔ model synchronisation (editing while playing)', () => {
expect(world.findByObjectId(b)!.x).toBe(object(b).position.x);
// Removed while playing → entity gone.
stack.execute(new RemoveSceneObjectCommand(sceneId, c));
stack.execute(new RemoveSceneObjectsCommand(sceneId, [c]));
world.syncFromModel();
expect(world.entities.map((e) => e.objectId)).toEqual([a, b]);
});
@@ -56,7 +56,7 @@ describe('world ↔ model synchronisation (editing while playing)', () => {
const { world } = startWorld(f);
const entityA = world.findByObjectId(a)!;
entityA.x = 123;
entityA.props.width = 999; // what a Set property node would do
entityA.props.width = 999; // what a Properties node would do
entityA.props.height = 100; // unchanged → no override
// No object appeared or vanished, but a position and an override were written – which is
// what tells the editor run that it has something to save.
+1 -1
View File
@@ -3,6 +3,7 @@ import { CommandStack } from '../src/core/commands/CommandStack';
import { AddNodeCommand, ConnectCommand } from '../src/core/commands/graphCommands';
import { AddPortsCommand } from '../src/core/commands/portCommands';
import { PlaceAssetCommand } from '../src/core/commands/sceneObjectCommands';
import { requireNodeDef } from '../src/core/commands/require';
import { AddVariableCommand } from '../src/core/commands/variableCommands';
import {
type DeclaredPort,
@@ -12,7 +13,6 @@ import {
type NodeContext,
type PointerState,
type Value,
requireNodeDef,
type RunResult,
portKindOf,
PROPERTIES,
+4
View File
@@ -0,0 +1,4 @@
graph während dem playmode lässt sich nicht editieren.
- abklären was zu machen wäre um das zu ermöglichen
- abklären ob es möglich wäre aktuelle werte anzuzeigen (nicht nur den wie der flow läuft sondern auch was)