A composition can now sit in a scene like a container and play there. Its items become real objects while they run, so behaviors, colliders and events work on them as on any other object. - A composition is placeable with its own symbol, transform and render layer. The scene view shows its picture at frame 0. A click on that picture selects the placement, not a single item. - CompositionSystem spawns each item as an object under the placement when it begins, with the id <placement>~<item>. On start and the other events run. The object is destroyed when the item ends. - The top track lies in front no matter which item started first. World.arrange() orders the entity list and the scene objects. - Clips and driven videos follow the same rules as compositionAt(). Loop, restart, stop and the game pause work. - New nodes: Play composition (with restart), Stop composition and the event On composition finished. They were planned for step 4 but come now, because without autoplay nothing could play otherwise. - The editor run ignores Play composition and says so in the log. It writes into the saved project, and the items would stay behind. - contentId() moved to instance.ts. The animation system uses it for nested ids too. - Compositions get no "Sort with parent" for now. Tests: the gate passed with 301 files and 4643 tests, 18 more than step 1. 13 of them are in tests/core/composition-play.test.ts. The first gate run failed in event-order.test.ts, which counts the event nodes and now finds 19. Five counter-checks each turned exactly their test red. Two order tests stayed green without the fix at first and were rebuilt. e2e 68 is new and passed with 5 own checks. Its counter-check without arrange() failed as expected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
42 lines
2.0 KiB
TypeScript
42 lines
2.0 KiB
TypeScript
import type { ENTITY_HANDLE } from '../core/graph/NodeContext';
|
|
import type { AnimationPlayer } from '../core/model/animation';
|
|
import type { AssetType } from '../core/model/AssetTypes';
|
|
import type { CompositionPlayer } from '../core/model/composition';
|
|
import type { FrameOutline } from '../core/model/frameOutline';
|
|
import type { TileEdits } from '../core/model/liveTilemap';
|
|
import type { PropertyBag } from '../core/model/Properties';
|
|
|
|
/** A live instance of a scene object; its resolved props are mutable runtime state the world mirrors back. */
|
|
export interface Entity {
|
|
/** What tells a graph this object is a live entity and not a struct value. */
|
|
readonly [ENTITY_HANDLE]: true;
|
|
id: string;
|
|
/** Scene object this entity was instantiated from (for selection highlighting). */
|
|
objectId: string;
|
|
assetId: string;
|
|
type: AssetType;
|
|
name: string;
|
|
/** Position local to `parent` (world position for top-level entities). */
|
|
x: number;
|
|
y: number;
|
|
/** Draw order, relative to the parent as well; higher is drawn on top. */
|
|
z: number;
|
|
/** For behaviors: the resolved variables (mutable state). For others: resolved properties. */
|
|
props: PropertyBag;
|
|
/** Parent entity (mirrors `SceneObject.parentId`); children move and die with it. */
|
|
parent: Entity | null;
|
|
/** The animations playing on this object; kept out of `props`, which the world writes back. */
|
|
animations?: AnimationPlayer[];
|
|
/** For a placed composition: what `Play composition` started (#417), out of `props` like `animations`. */
|
|
composition?: CompositionPlayer;
|
|
/** How often an `Emit` node has restarted this particle source; out of `props` for the same reason. */
|
|
emits?: number;
|
|
/**
|
|
* The frame a collider of the shape "Frame collision" wears (#193), looked up in the world's project on every
|
|
* call, so a changed `frame` prop or a redrawn outline counts at once. Absent outside a world.
|
|
*/
|
|
wornFrame?: () => FrameOutline | null;
|
|
/** For a placed tilemap: the cells a behavior set during the run (#135), never written back. */
|
|
tileEdits?: TileEdits;
|
|
}
|