Node class

The humble node.

Overview

Nodes are the buildings block of Ignis. They are organized in a directed, acyclic tree, with children ordered by priority. Nodes may be assembled into subtrees using add and remove any number of times.

Building

Nodes should initialize children, connect signals, and add tick behavior in their build method. build is called every time a node is mounted to a live scene, or as the root of its own scene with mount.

build should be written in such a way that it can be run multiple times. To facilitate this, build internally tracks every node added and every signal subscribed inside that method call. If you create resources that should be disposed, place it into the trash to prevent leaks.

Lastly, the rebuild method is provided as a way to "reboot" the internals of any node. This method will remove added nodes, unsubscribe from signals, and process the trash. Then, it will call build again.

Do not make build async. An asynchronous build breaks engine invariants in multiple, devastating ways.

Signals

Nodes communicate time-sensitive events through signals: named, type-safe message emitters. Use one to report an event to consumers, or as an input to react to external events.

Conventionally, signals are prefixed with the word on. For example, the signal a collider emits on contact is named onCollisionStart. This allows consumers to have a natural-reading constructor, e.g. onCollisionStart(/* do stuff */);.

Scenes

Nodes may be mounted to a Scene, which drives them with a game loop. When mounted, the scene will propagate through the entire subtree emitting the onMount signal on each node, from top to bottom. Unmounting does the reverse, emitting the onUnmount signal from the leaves upward.

Tree

Before being mounted, the add, remove, and priority tree operations take effect immediately, allowing a subtree to be freely assembled long before it goes live.

Once mounted, however, the same calls are instead merely enqueued. The scene applies pending changes right before the next update. As a result, operations for live node trees are always delayed a frame. Although unintuitive, this queue allows the engine to mitigate modification during iteration, and improves performance by batching the changes.

Dependency Injection

Nodes come integrated with a type-based dependency injection (DI) system. A node may provide a value to its entire subtree, keyed by its type. read resolves the nearest match, checking the node itself before its ancestors.

Reassembly

When the world changes out from under a live tree, the scene walks it calling reassemble. Unlike update and render, the walk ignores the enabled flag, so even disabled nodes are asked.

Currently, the walk runs in two, distinct situations:

  • Whenever the SceneWidget reassembles in the Flutter tree.
  • Whenever Ignis.cache changes, such as via the local asset bundle.

Each node answers for itself, and the default answer is nothing, so a save leaves a running game exactly as it was.

Implementers
Available extensions

Constructors

Node({bool? enabled, int? priority, Iterable<Node> children = const []})
Creates a new node.

Properties

ancestors Iterable<Node>
This node's ancestors in the tree.
no setter
children Iterable<Node>
This node's direct children.
no setter
descendants Iterable<Node>
This node's descendants in depth-first preorder.
no setter
enabled bool
Whether this node updates and renders. Defaults to true.
getter/setter pair
hashCode int
The hash code for this object.
no setterinherited
hasParent bool
True if this node has a non-null parent.
no setter
isMounted bool
True while this node is part of a mounted tree.
no setter
onMount Signal0
Emitted when this node is added to a scene.
final
onSceneResize Signal1<Vector2>
Emitted when the scene resizes, and once at mount.
final
onUnmount Signal0
Emitted when this node is removed from a scene.
final
parent Node?
The parent that owns this node, or null when it is parentless.
no setter
priority int
This node's order in updating and rendering in its parent. Defaults to 0.
getter/setter pair
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
scene Scene<Node>
This node's owning scene. Only valid while isMounted.
no setter

Methods

add<T extends Node>(T node) → T
Adds node to this node. The node is returned.
addAll(Iterable<Node> nodes) → void
Adds all nodes to this node.
attach(Node node) → void
Adds this node to the target node.
build() → void
Declares this node's children and behavior.
contains(Node other) bool
Checks if this node contains the other node in its tree.
containsPoint(Vector2 point) bool
Whether this node's hit area contains point.
cycles(Node node) bool
True if node is (or soon will be) an ancestor of this node.
debugDraw(DebugDraw draw) → void
Draws to the debug overlay every frame, in the same space as draw.
debugRender(Canvas canvas) → void
Renders the debug overlay for this node and its children to canvas.
debugRenderSelf(Canvas canvas) → void
Runs this node's debugDraw callbacks, in the same space as renderSelf.
detach() bool
Removes this node from its parent, or from the parent it is on its way to.
disable() → void
Disables this node, so it stops updating and rendering.
draw(Draw draw) → void
Draws to canvas every frame, in this node's own coordinate space.
enable() → void
Enables this node, so it resumes updating and rendering.
hitTest(Vector2 point) Iterable<Node>
Finds every enabled node in this subtree whose hit area contains point, per containsPoint, topmost first.
mount() Scene<T>

Available on T, provided by the Mount extension

Mounts this node as the root of a new Scene and returns it.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
owns(Node other) bool
Checks if this node owns the other node.
provide<T>(T value) → void
Provides value as this node's instance of T, overwriting any value previously provided for T.
query<T extends Node>() Iterable<T>
This node's direct children of type T, in priority order.
read<T>() → T
Reads the nearest instance of T provided by this node or an ancestor, checking this node first.
readOrNull<T>() → T?
Reads the nearest instance of T provided by this node or an ancestor, checking this node first. Returns null if none was provided.
reassemble() → void
What this node does when the tree is reassembled.
rebuild() → void
Re-derives this node by running build again over the wreckage of the last one.
remove(Node node) bool
Removes the child node.
removeAll() → void
Removes all children.
render(Canvas canvas) → void
Renders this node and its children to canvas.
renderSelf(Canvas canvas) → void
Runs this node's draw callbacks.
tick(Tick tick) → void
Calls tick with the elapsed seconds on every frame.
toString() String
A string representation of this object.
inherited
trash(Cleanup cleanup) → void
Defers cleanup until this build stops being current.
update(double dt) → void
Updates this node and its children by dt seconds.

Operators

operator ==(Object other) bool
The equality operator.
inherited