diff --git a/src/core/commands/require.ts b/src/core/commands/require.ts index f1742da4..051a37d3 100644 --- a/src/core/commands/require.ts +++ b/src/core/commands/require.ts @@ -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}"`); diff --git a/src/core/commands/sceneObjectCommands.ts b/src/core/commands/sceneObjectCommands.ts index 025f86fc..ab1f3b55 100644 --- a/src/core/commands/sceneObjectCommands.ts +++ b/src/core/commands/sceneObjectCommands.ts @@ -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. diff --git a/src/core/graph/NodeRegistry.ts b/src/core/graph/NodeRegistry.ts index 744c3181..532ae6fd 100644 --- a/src/core/graph/NodeRegistry.ts +++ b/src/core/graph/NodeRegistry.ts @@ -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()]; } diff --git a/src/core/model/Asset.ts b/src/core/model/Asset.ts index 3ea1cf02..c3a5d7dc 100644 --- a/src/core/model/Asset.ts +++ b/src/core/model/Asset.ts @@ -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'; -} diff --git a/src/core/model/Project.ts b/src/core/model/Project.ts index debac45a..d24be6a8 100644 --- a/src/core/model/Project.ts +++ b/src/core/model/Project.ts @@ -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'); -} diff --git a/src/editor/AssetTabEditor.ts b/src/editor/AssetTabEditor.ts index 98607b75..29f316b6 100644 --- a/src/editor/AssetTabEditor.ts +++ b/src/editor/AssetTabEditor.ts @@ -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; diff --git a/src/ui/FocusManager.ts b/src/ui/FocusManager.ts index 6a1f3b21..0de4e619 100644 --- a/src/ui/FocusManager.ts +++ b/src/ui/FocusManager.ts @@ -91,10 +91,6 @@ export class FocusManager { } } } - - destroy(): void { - window.removeEventListener('keydown', this.onKeyDown); - } } function isAttached(node: Container, root: Container): boolean { diff --git a/src/ui/KeyboardBridge.ts b/src/ui/KeyboardBridge.ts index f26a6933..60e4e7a4 100644 --- a/src/ui/KeyboardBridge.ts +++ b/src/ui/KeyboardBridge.ts @@ -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; diff --git a/src/ui/Theme.ts b/src/ui/Theme.ts index 1b9843b9..798f326c 100644 --- a/src/ui/Theme.ts +++ b/src/ui/Theme.ts @@ -26,7 +26,7 @@ export const Theme = { border: 0x383c46, control: 0x16181d, controlHover: 0x1e2127, - controlActive: 0x2a2e37, + controlActive: 0x16181d, accent: 0x4c8dff, accentText: 0xffffff, text: 0xe6e8ee, diff --git a/src/ui/widgets/ColorField.ts b/src/ui/widgets/ColorField.ts index dc0de163..1843c8ce 100644 --- a/src/ui/widgets/ColorField.ts +++ b/src/ui/widgets/ColorField.ts @@ -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; diff --git a/src/ui/widgets/ListView.ts b/src/ui/widgets/ListView.ts index 8b4ea0ec..52baa9b1 100644 --- a/src/ui/widgets/ListView.ts +++ b/src/ui/widgets/ListView.ts @@ -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). diff --git a/src/ui/widgets/NumberField.ts b/src/ui/widgets/NumberField.ts index 6a41d0c4..f7e0a4cf 100644 --- a/src/ui/widgets/NumberField.ts +++ b/src/ui/widgets/NumberField.ts @@ -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); diff --git a/src/viewport/items.ts b/src/viewport/items.ts index 63754dba..7824de1a 100644 --- a/src/viewport/items.ts +++ b/src/viewport/items.ts @@ -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 }; diff --git a/tests/core/commands.test.ts b/tests/core/commands.test.ts index 3070e0b1..2b499b9e 100644 --- a/tests/core/commands.test.ts +++ b/tests/core/commands.test.ts @@ -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 }); diff --git a/tests/core/container.test.ts b/tests/core/container.test.ts index c5524ac2..f5fa73db 100644 --- a/tests/core/container.test.ts +++ b/tests/core/container.test.ts @@ -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(); diff --git a/tests/core/dynamic-ports.test.ts b/tests/core/dynamic-ports.test.ts index 84463acc..9c8658b0 100644 --- a/tests/core/dynamic-ports.test.ts +++ b/tests/core/dynamic-ports.test.ts @@ -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'; diff --git a/tests/core/graph.test.ts b/tests/core/graph.test.ts index 55654102..9fafbd29 100644 --- a/tests/core/graph.test.ts +++ b/tests/core/graph.test.ts @@ -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'; diff --git a/tests/core/hierarchy.test.ts b/tests/core/hierarchy.test.ts index f4b0a8ad..df0bfcf4 100644 --- a/tests/core/hierarchy.test.ts +++ b/tests/core/hierarchy.test.ts @@ -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]); diff --git a/tests/core/holders.test.ts b/tests/core/holders.test.ts index d0bb0e78..7da67588 100644 --- a/tests/core/holders.test.ts +++ b/tests/core/holders.test.ts @@ -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. diff --git a/tests/core/node-catalog.test.ts b/tests/core/node-catalog.test.ts index 52525880..c1ed2a8f 100644 --- a/tests/core/node-catalog.test.ts +++ b/tests/core/node-catalog.test.ts @@ -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, diff --git a/tests/core/texture-commands.test.ts b/tests/core/texture-commands.test.ts index 108d2814..e0c8268a 100644 --- a/tests/core/texture-commands.test.ts +++ b/tests/core/texture-commands.test.ts @@ -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' }); diff --git a/tests/core/world-sync.test.ts b/tests/core/world-sync.test.ts index 24cad15a..445f1645 100644 --- a/tests/core/world-sync.test.ts +++ b/tests/core/world-sync.test.ts @@ -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. diff --git a/tests/helpers.ts b/tests/helpers.ts index 53b5497a..6fe416ba 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -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, diff --git a/todo-notes/graph-during-play-mode.md b/todo-notes/graph-during-play-mode.md new file mode 100644 index 00000000..8b621971 --- /dev/null +++ b/todo-notes/graph-during-play-mode.md @@ -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)