92 lines
3.7 KiB
TypeScript
92 lines
3.7 KiB
TypeScript
import type { PropertyBag } from '../model/Properties';
|
||
import { sumAlongChain } from '../model/walk';
|
||
import { enabledAlongChain } from '../properties/enabled';
|
||
|
||
/**
|
||
* What a graph sees of a running entity. The runtime's Entity satisfies this shape; unit
|
||
* tests use plain objects. Mutating `x`/`y`/`props` is how actions take effect.
|
||
*/
|
||
export interface EntityHandle {
|
||
id: string;
|
||
/** Asset this entity was instantiated from (what `Is asset` compares against). */
|
||
assetId: string;
|
||
name: string;
|
||
/** Position local to `parent` (world position for top-level entities). */
|
||
x: number;
|
||
y: number;
|
||
z: number;
|
||
props: PropertyBag;
|
||
/** The entity this one is parented to; children move with their parent. */
|
||
parent: EntityHandle | null;
|
||
}
|
||
|
||
/** World position of a handle: its local position plus those of all ancestors. */
|
||
export function worldPositionOf(handle: EntityHandle): { x: number; y: number; z: number } {
|
||
return sumAlongChain(handle, (h) => h.parent, (h) => h);
|
||
}
|
||
|
||
/** Whether a handle and every ancestor of it are switched on (see `properties/enabled.ts`). */
|
||
export function isHandleEnabled(handle: EntityHandle): boolean {
|
||
return enabledAlongChain(handle, (h) => h.props, (h) => h.parent);
|
||
}
|
||
|
||
/** Where the mouse is (world units) and what it did this frame. */
|
||
export interface PointerState {
|
||
x: number;
|
||
y: number;
|
||
/** Whether the pointer is over the game view at all. */
|
||
inside: boolean;
|
||
down: boolean;
|
||
/** Went down / up during this frame. */
|
||
pressed: boolean;
|
||
released: boolean;
|
||
}
|
||
|
||
/**
|
||
* Services a graph may use while running. Implemented by the runtime (BehaviorSystem) and
|
||
* by test doubles. Everything the graph does to the world goes through here, so the core
|
||
* stays free of runtime imports.
|
||
*/
|
||
export interface NodeContext {
|
||
/** The behavior entity itself. */
|
||
self: EntityHandle;
|
||
/** The behavior's parent object (the one the graph acts on), if any. */
|
||
owner: EntityHandle | null;
|
||
/** Mutable variable state of this behavior instance. */
|
||
variables: PropertyBag;
|
||
/** Seconds since the world started and since the last tick. */
|
||
time: number;
|
||
dt: number;
|
||
findByName(name: string): EntityHandle | null;
|
||
isKeyDown(key: string): boolean;
|
||
/** Mouse state of this frame, in world units. */
|
||
pointer: PointerState;
|
||
/**
|
||
* Whether a world point lies on `target` – on its colliders when it has any, otherwise on
|
||
* its own footprint or that of anything parented below it (so a button made of a container
|
||
* with a sprite and a label is hit as a whole).
|
||
*/
|
||
hitTest(target: EntityHandle, x: number, y: number): boolean;
|
||
/**
|
||
* Whether any collider of `a` overlaps any collider of `b` right now. A collider entity
|
||
* stands for itself; any other entity stands for its direct collider children.
|
||
*/
|
||
isTouching(a: EntityHandle, b: EntityHandle): boolean;
|
||
/**
|
||
* Moves `target` by (dx, dy) in local units, stopping its solid colliders at other solid
|
||
* colliders axis by axis (x first, then y) so it slides along walls. Reports which axes hit.
|
||
*/
|
||
moveAndSlide(target: EntityHandle, dx: number, dy: number): { blockedX: boolean; blockedY: boolean };
|
||
log(message: string): void;
|
||
/**
|
||
* Places a new instance of an asset into the running scene and returns it. The position is
|
||
* local to `parent` (world when none). Returns null when the asset does not exist or cannot
|
||
* be placed (a scene). Spawned behaviors run their `On start` on the next tick.
|
||
*/
|
||
spawn(assetId: string, position: { x: number; y: number; z: number }, parent: EntityHandle | null): EntityHandle | null;
|
||
destroy(target: EntityHandle): void;
|
||
stop(): void;
|
||
/** Ends the run and starts it again from the saved scene (everything spawned is lost). */
|
||
restart(): void;
|
||
}
|