The GraphNode class represents a node within a hierarchical scene graph. Each GraphNode can
reference a array of child nodes. This creates a tree-like structure that is fundamental for
organizing and managing the spatial relationships between objects in a 3D scene. This class
provides a comprehensive API for manipulating the position, rotation, and scale of nodes both
locally and in world space.
GraphNode is the superclass of Entity, which is the primary class for creating objects
in a Mirror Engine application. For this reason, GraphNode is rarely used directly, but it provides
a powerful set of features that are leveraged by the Entity class.
new GraphNode(name?: string): GraphNode
Create a new GraphNode instance.
string = 'Untitled'
The non-unique name of a graph node. Defaults to 'Untitled'.
EventHandler.constructor
name: string
The non-unique name of a graph node. Defaults to 'Untitled'.
tags: Tags
Interface for tagging graph nodes. Tag based searches can be performed using the GraphNode#findByTag function.
get children(): GraphNode[]
Gets the children of this graph node.
get enabled(): boolean
Gets the enabled state of the GraphNode.
boolean
set enabled(enabled: boolean): void
Sets the enabled state of the GraphNode. If one of the GraphNode's parents is disabled there will be no other side effects. If all the parents are enabled then the new value will activate or deactivate all the enabled children of the GraphNode.
boolean
void
get forward(): Vec3
Gets the normalized local space negative Z-axis vector of the graph node in world space.
get graphDepth(): number
Gets the depth of this child within the graph. Note that for performance reasons this is only recalculated when a node is added to a new parent. In other words, it is not recalculated when a node is simply removed from the graph.
number
get parent(): null | GraphNode
Gets the parent of this graph node.
null | GraphNode
get path(): string
Gets the path of this graph node relative to the root of the hierarchy.
string
get right(): Vec3
Gets the normalized local space X-axis vector of the graph node in world space.
get root(): GraphNode
Gets the oldest ancestor graph node from this graph node.
get up(): Vec3
Gets the normalized local space Y-axis vector of the graph node in world space.
addChild(node: GraphNode): void
Add a new child to the child list and update the parent value of the child node. If the node already had a parent, it is removed from its child list.
The new child to add.
void
const e = new Entity(app)
this.entity.addChild(e)
clone(): GraphNode
Clone a graph node.
A clone of the specified graph node.
destroy(): void
Destroy the graph node and all of its descendants. First, the graph node is removed from the hierarchy. This is then repeated recursively for all descendants of the graph node.
The last thing the graph node does is fire the destroy event.
void
const firstChild = graphNode.children[0]
firstChild.destroy() // destroy child and all of its descendants
find(attr: string | FindNodeCallback, value?: any): GraphNode[]
Search the graph node and all of its descendants for the nodes that satisfy some search criteria.
This can either be a function or a string. If it's a function, it is executed for each descendant node to test if node satisfies the search logic. Returning true from the function will include the node into the results. If it's a string then it represents the name of a field or a method of the node. If this is the name of a field then the value passed as the second argument will be checked for equality. If this is the name of a function then the return value of the function will be checked for equality against the valued passed as the second argument to this function.
string | FindNodeCallback
any
If the first argument (attr) is a property name then this value will be checked against the value of the property.
The array of graph nodes that match the search criteria.
// Finds all nodes that have a model component and have 'door' in their lower-cased name
const doors = house.find(function (node) {
return node.model && node.name.toLowerCase().indexOf('door') !== -1
})
// Finds all nodes that have the name property set to 'Test'
const entities = parent.find('name', 'Test')
findByName(name: string): null | GraphNode
Get the first node found in the graph with the name. The search is depth first.
string
The name of the graph.
null | GraphNode
The first node to be found matching the supplied name. Returns null if no node is found.
findByPath(path: string | string[]): null | GraphNode
Get the first node found in the graph by its full path in the graph. The full path has this form 'parent/child/sub-child'. The search is depth first.
The full path of the GraphNode as either a string or array of GraphNode names.
string | string
null | GraphNode
The first node to be found matching the supplied path. Returns null if no node is found.
// String form
const grandchild = this.entity.findByPath('child/grandchild')
// Array form
const grandchild = this.entity.findByPath([
'child',
'grandchild'
])
findByTag(...args: any): GraphNode[]
Return all graph nodes that satisfy the search query. Query can be simply a string, or comma separated strings, to have inclusive results of assets that match at least one query. A query that consists of an array of tags can be used to match graph nodes that have each tag of array.
...any
A list of all graph nodes that match the query.
// Return all graph nodes that tagged by `animal`
const animals = node.findByTag('animal')
// Return all graph nodes that tagged by `bird` OR `mammal`
const birdsAndMammals = node.findByTag('bird', 'mammal')
// Return all assets that tagged by `carnivore` AND `mammal`
const meatEatingMammals = node.findByTag([
'carnivore',
'mammal'
])
// Return all assets that tagged by (`carnivore` AND `mammal`) OR (`carnivore` AND `reptile`)
const meatEatingMammalsAndReptiles = node.findByTag(
[
'carnivore',
'mammal'
],
[
'carnivore',
'reptile'
]
)
findOne(attr: string | FindNodeCallback, value?: any): null | GraphNode
Search the graph node and all of its descendants for the first node that satisfies some search criteria.
This can either be a function or a string. If it's a function, it is executed for each descendant node to test if node satisfies the search logic. Returning true from the function will result in that node being returned from findOne. If it's a string then it represents the name of a field or a method of the node. If this is the name of a field then the value passed as the second argument will be checked for equality. If this is the name of a function then the return value of the function will be checked for equality against the valued passed as the second argument to this function.
string | FindNodeCallback
any
If the first argument (attr) is a property name then this value will be checked against the value of the property.
null | GraphNode
A graph node that match the search criteria. Returns null if no node is found.
// Find the first node that is called 'head' and has a model component
const head = player.findOne(function (node) {
return node.model && node.name === 'head'
})
// Finds the first node that has the name property set to 'Test'
const node = parent.findOne('name', 'Test')
fire(
name: string,
arg1?: any,
arg2?: any,
arg3?: any,
arg4?: any,
arg5?: any,
arg6?: any,
arg7?: any,
arg8?: any): EventHandler
Fire an event, all additional arguments are passed on to the event listener.
string
Name of event to fire.
any
First argument that is passed to the event handler.
any
Second argument that is passed to the event handler.
any
Third argument that is passed to the event handler.
any
Fourth argument that is passed to the event handler.
any
Fifth argument that is passed to the event handler.
any
Sixth argument that is passed to the event handler.
any
Seventh argument that is passed to the event handler.
any
Eighth argument that is passed to the event handler.
Self for chaining.
obj.fire('test', 'This is the message')
forEach(callback: ForEachNodeCallback, thisArg?: any): void
Executes a provided function once on this graph node and all of its descendants.
ForEachNodeCallback
The function to execute on the graph node and each descendant.
any
Optional value to use as this when executing callback function.
void
// Log the path and name of each node in descendant tree starting with "parent"
parent.forEach(function (node) {
console.log(node.path + '/' + node.name)
})
getEulerAngles(): Vec3
Get the world space rotation for the specified GraphNode in Euler angle form. The rotation is returned as euler angles in a Vec3. The value returned by this function should be considered read-only. In order to set the world space rotation of the graph node, use GraphNode#setEulerAngles.
The world space rotation of the graph node in Euler angle form.
const angles = this.entity.getEulerAngles()
angles.y = 180 // rotate the entity around Y by 180 degrees
this.entity.setEulerAngles(angles)
getLocalEulerAngles(): Vec3
Get the rotation in local space for the specified GraphNode. The rotation is returned as euler angles in a Vec3. The returned vector should be considered read-only. To update the local rotation, use GraphNode#setLocalEulerAngles.
The local space rotation of the graph node as euler angles in XYZ order.
const angles = this.entity.getLocalEulerAngles()
angles.y = 180
this.entity.setLocalEulerAngles(angles)
getLocalPosition(): Vec3
Get the position in local space for the specified GraphNode. The position is returned as a Vec3. The returned vector should be considered read-only. To update the local position, use GraphNode#setLocalPosition.
The local space position of the graph node.
const position = this.entity.getLocalPosition()
position.x += 1 // move the entity 1 unit along x.
this.entity.setLocalPosition(position)
getLocalRotation(): Quat
Get the rotation in local space for the specified GraphNode. The rotation is returned as a Quat. The returned quaternion should be considered read-only. To update the local rotation, use GraphNode#setLocalRotation.
The local space rotation of the graph node as a quaternion.
const rotation = this.entity.getLocalRotation()
getLocalScale(): Vec3
Get the scale in local space for the specified GraphNode. The scale is returned as a Vec3. The returned vector should be considered read-only. To update the local scale, use GraphNode#setLocalScale.
The local space scale of the graph node.
const scale = this.entity.getLocalScale()
scale.x = 100
this.entity.setLocalScale(scale)
getLocalTransform(): Mat4
Get the local transform matrix for this graph node. This matrix is the transform relative to the node's parent's world transformation matrix.
The node's local transformation matrix.
const transform = this.entity.getLocalTransform()
getPosition(): Vec3
Get the world space position for the specified GraphNode. The position is returned as a Vec3. The value returned by this function should be considered read-only. In order to set the world space position of the graph node, use GraphNode#setPosition.
The world space position of the graph node.
const position = this.entity.getPosition()
position.x = 10
this.entity.setPosition(position)
getRotation(): Quat
Get the world space rotation for the specified GraphNode. The rotation is returned as a Quat. The value returned by this function should be considered read-only. In order to set the world space rotation of the graph node, use GraphNode#setRotation.
The world space rotation of the graph node as a quaternion.
const rotation = this.entity.getRotation()
getWorldTransform(): Mat4
Get the world transformation matrix for this graph node.
The node's world transformation matrix.
const transform = this.entity.getWorldTransform()
hasEvent(name: string): boolean
Test if there are any handlers bound to an event name.
string
The name of the event to test.
boolean
True if the object has handlers bound to the specified event name.
obj.on('test', () => {}) // bind an event to 'test'
obj.hasEvent('test') // returns true
obj.hasEvent('hello') // returns false
insertChild(node: GraphNode, index: number): void
Insert a new child to the child list at the specified index and update the parent value of the child node. If the node already had a parent, it is removed from its child list.
The new child to insert.
number
The index in the child list of the parent where the new node will be inserted.
void
const e = new Entity(app)
this.entity.insertChild(e, 1)
isAncestorOf(node: GraphNode): boolean
Check if node is ancestor for another node.
Potential descendant of node.
boolean
If node is ancestor for another node.
if (body.isAncestorOf(foot)) {
// foot is within body's hierarchy
}
isDescendantOf(node: GraphNode): boolean
Check if node is descendant of another node.
Potential ancestor of node.
boolean
If node is descendant of another node.
if (roof.isDescendantOf(house)) {
// roof is descendant of house entity
}
lookAt(
x: number | Vec3,
y?: number | Vec3,
z?: number,
ux?: number,
uy?: number,
uz?: number): void
Reorients the graph node so that the negative z-axis points towards the target. This function has two valid signatures. Either pass 3D vectors for the look at coordinate and up vector, or pass numbers to represent the vectors.
If passing a 3D vector, this is the world space coordinate to look at. Otherwise, it is the x-component of the world space coordinate to look at.
number | Vec3
If passing a 3D vector, this is the world space up vector for look at transform. Otherwise, it is the y-component of the world space coordinate to look at.
number | Vec3
number
Z-component of the world space coordinate to look at.
number = 0
X-component of the up vector for the look at transform. Defaults to 0.
number = 1
Y-component of the up vector for the look at transform. Defaults to 1.
number = 0
Z-component of the up vector for the look at transform. Defaults to 0.
void
// Look at another entity, using the (default) positive y-axis for up
const position = otherEntity.getPosition()
this.entity.lookAt(position)
// Look at another entity, using the negative world y-axis for up
const position = otherEntity.getPosition()
this.entity.lookAt(position, Vec3.DOWN)
// Look at the world space origin, using the (default) positive y-axis for up
this.entity.lookAt(0, 0, 0)
// Look at world space coordinate [10, 10, 10], using the negative world y-axis for up
this.entity.lookAt(10, 10, 10, 0, -1, 0)
off(
name?: string,
callback?: HandleEventCallback,
scope?: any): EventHandler
Detach an event handler from an event. If callback is not provided then all callbacks are unbound from the event, if scope is not provided then all events with the callback will be unbound.
string
Name of the event to unbind.
HandleEventCallback
Function to be unbound.
any
Scope that was used as the this when the event is fired.
Self for chaining.
const handler = () => {}
obj.on('test', handler)
obj.off() // Removes all events
obj.off('test') // Removes all events called 'test'
obj.off('test', handler) // Removes all handler functions, called 'test'
obj.off('test', handler, this) // Removes all handler functions, called 'test' with scope this
on(
name: string,
callback: HandleEventCallback,
scope?: any): EventHandle
Attach an event handler to an event.
string
Name of the event to bind the callback to.
HandleEventCallback
Function that is called when event is fired. Note the callback is limited to 8 arguments.
any = ...
Object to use as 'this' when the event is fired, defaults to current this.
Can be used for removing event in the future.
obj.on('test', (a, b) => {
console.log(a + b)
})
obj.fire('test', 1, 2) // prints 3 to the console
const evt = obj.on('test', (a, b) => {
console.log(a + b)
})
// some time later
evt.off()
once(
name: string,
callback: HandleEventCallback,
scope?: any): EventHandle
Attach an event handler to an event. This handler will be removed after being fired once.
string
Name of the event to bind the callback to.
HandleEventCallback
Function that is called when event is fired. Note the callback is limited to 8 arguments.
any = ...
Object to use as 'this' when the event is fired, defaults to current this.
obj.once('test', (a, b) => {
console.log(a + b)
})
obj.fire('test', 1, 2) // prints 3 to the console
obj.fire('test', 1, 2) // not going to get handled
remove(): void
Remove graph node from current parent.
void
removeChild(child: GraphNode): void
Remove the node from the child list and update the parent value of the child.
The node to remove.
void
const child = this.entity.children[0]
this.entity.removeChild(child)
reparent(parent: GraphNode, index?: number): void
Remove graph node from current parent and add as child to new parent.
New parent to attach graph node to.
number
The child index where the child node should be placed.
void
rotate(
x: number | Vec3,
y?: number,
z?: number): void
Rotates the graph node in world space by the specified Euler angles. Eulers are specified in degrees in XYZ order. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the world space rotation.
3-dimensional vector holding world space rotation or rotation around world space x-axis in degrees.
number | Vec3
number
Rotation around world space y-axis in degrees.
number
Rotation around world space z-axis in degrees.
void
// Rotate via 3 numbers
this.entity.rotate(0, 90, 0)
// Rotate via vector
const r = new Vec3(0, 90, 0)
this.entity.rotate(r)
rotateLocal(
x: number | Vec3,
y?: number,
z?: number): void
Rotates the graph node in local space by the specified Euler angles. Eulers are specified in degrees in XYZ order. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the local space rotation.
3-dimensional vector holding local space rotation or rotation around local space x-axis in degrees.
number | Vec3
number
Rotation around local space y-axis in degrees.
number
Rotation around local space z-axis in degrees.
void
// Rotate via 3 numbers
this.entity.rotateLocal(0, 90, 0)
// Rotate via vector
const r = new Vec3(0, 90, 0)
this.entity.rotateLocal(r)
setEulerAngles(
x: number | Vec3,
y?: number,
z?: number): void
Sets the world space rotation of the specified graph node using euler angles. Eulers are interpreted in XYZ order. Eulers must be specified in degrees. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the world space euler rotation.
3-dimensional vector holding eulers or rotation around world space x-axis in degrees.
number | Vec3
number
Rotation around world space y-axis in degrees.
number
Rotation around world space z-axis in degrees.
void
// Set rotation of 90 degrees around world space y-axis via 3 numbers
this.entity.setEulerAngles(0, 90, 0)
// Set rotation of 90 degrees around world space y-axis via a vector
const angles = new Vec3(0, 90, 0)
this.entity.setEulerAngles(angles)
setLocalEulerAngles(
x: number | Vec3,
y?: number,
z?: number): void
Sets the local space rotation of the specified graph node using euler angles. Eulers are interpreted in XYZ order. Eulers must be specified in degrees. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the local space euler rotation.
3-dimensional vector holding eulers or rotation around local space x-axis in degrees.
number | Vec3
number
Rotation around local space y-axis in degrees.
number
Rotation around local space z-axis in degrees.
void
// Set rotation of 90 degrees around y-axis via 3 numbers
this.entity.setLocalEulerAngles(0, 90, 0)
// Set rotation of 90 degrees around y-axis via a vector
const angles = new Vec3(0, 90, 0)
this.entity.setLocalEulerAngles(angles)
setLocalPosition(
x: number | Vec3,
y?: number,
z?: number): void
Sets the local space position of the specified graph node. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the local space position.
3-dimensional vector holding local space position or x-coordinate of local space position.
number | Vec3
number
Y-coordinate of local space position.
number
Z-coordinate of local space position.
void
// Set via 3 numbers
this.entity.setLocalPosition(0, 10, 0)
// Set via vector
const pos = new Vec3(0, 10, 0)
this.entity.setLocalPosition(pos)
setLocalRotation(
x: number | Quat,
y?: number,
z?: number,
w?: number): void
Sets the local space rotation of the specified graph node. This function has two valid signatures: you can either pass a quaternion or 3 numbers to specify the local space rotation.
Quaternion holding local space rotation or x-component of local space quaternion rotation.
number | Quat
number
Y-component of local space quaternion rotation.
number
Z-component of local space quaternion rotation.
number
W-component of local space quaternion rotation.
void
// Set via 4 numbers
this.entity.setLocalRotation(0, 0, 0, 1)
// Set via quaternion
const q = Quat()
this.entity.setLocalRotation(q)
setLocalScale(
x: number | Vec3,
y?: number,
z?: number): void
Sets the local space scale factor of the specified graph node. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the local space scale.
3-dimensional vector holding local space scale or x-coordinate of local space scale.
number | Vec3
number
Y-coordinate of local space scale.
number
Z-coordinate of local space scale.
void
// Set via 3 numbers
this.entity.setLocalScale(10, 10, 10)
// Set via vector
const scale = new Vec3(10, 10, 10)
this.entity.setLocalScale(scale)
setPosition(
x: number | Vec3,
y?: number,
z?: number): void
Sets the world space position of the specified graph node. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the world space position.
3-dimensional vector holding world space position or x-coordinate of world space position.
number | Vec3
number
Y-coordinate of world space position.
number
Z-coordinate of world space position.
void
// Set via 3 numbers
this.entity.setPosition(0, 10, 0)
// Set via vector
const position = new Vec3(0, 10, 0)
this.entity.setPosition(position)
setPositionAndRotation(position: Vec3, rotation: Quat): void
Sets the world space position and rotation of the specified graph node. This is faster than setting the position and rotation independently.
The world space position to set.
The world space rotation to set.
void
const position = new Vec3(0, 10, 0)
const rotation = new Quat().setFromEulerAngles(0, 90, 0)
this.entity.setPositionAndRotation(position, rotation)
setRotation(
x: number | Quat,
y?: number,
z?: number,
w?: number): void
Sets the world space rotation of the specified graph node. This function has two valid signatures: you can either pass a quaternion or 3 numbers to specify the world space rotation.
Quaternion holding world space rotation or x-component of world space quaternion rotation.
number | Quat
number
Y-component of world space quaternion rotation.
number
Z-component of world space quaternion rotation.
number
W-component of world space quaternion rotation.
void
// Set via 4 numbers
this.entity.setRotation(0, 0, 0, 1)
// Set via quaternion
const q = Quat()
this.entity.setRotation(q)
translate(
x: number | Vec3,
y?: number,
z?: number): void
Translates the graph node in world space by the specified translation vector. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the world space translation.
3-dimensional vector holding world space translation or x-coordinate of world space translation.
number | Vec3
number
Y-coordinate of world space translation.
number
Z-coordinate of world space translation.
void
// Translate via 3 numbers
this.entity.translate(10, 0, 0)
// Translate via vector
const t = new Vec3(10, 0, 0)
this.entity.translate(t)
translateLocal(
x: number | Vec3,
y?: number,
z?: number): void
Translates the graph node in local space by the specified translation vector. This function has two valid signatures: you can either pass a 3D vector or 3 numbers to specify the local space translation.
3-dimensional vector holding local space translation or x-coordinate of local space translation.
number | Vec3
number
Y-coordinate of local space translation.
number
Z-coordinate of local space translation.
void
// Translate via 3 numbers
this.entity.translateLocal(10, 0, 0)
// Translate via vector
const t = new Vec3(10, 0, 0)
this.entity.translateLocal(t)