New in version 0.7.
obengine.scenegraph provides a simple, SQLite [1]-based scene graph implementation. Before OpenBlox 0.7, the only “scene graph” available was obengine.datatypes.AttrDict, and that class had several shortcomings:
To address these issues, this module, obengine.scenegraph, was born.
Each node on the scene graph has its own unique ID number (node ID/NID) - no two nodes (no matter when or where they were created) have identical ID numbers. So, each node’s primary means of identification is through its NID. The benefits of using node IDs to access your nodes are:
There are 2 main weaknesses with NIDs:
Because of these shortcomings, each scene node also has a user-defined name, which can also be used to access a scene node. The advantages of using scene node names are:
However, node names also have some problems:
It is up to you to decide which identification method better suits your purposes. The best strategy right now looks like this:
Basic usage:
>>> from obengine.scenegraph import *
>>> sg = SceneGraph()
>>> n1 = SceneNode('Node 1')
>>> sg.add_node(n1)
>>> print sg.get_node_by_name('Node 1').name
Node 1
Nodes can have names, but they must be unique within their scope, i.e, their parent can have no other children with the same name, if you want to be able to use obengine.scenegraph.SceneNode.get_child_by_name:
>>> n2 = SceneNode('Node 2')
>>> n3 = SceneNode('Node 2')
>>> sg.add_node(n2)
>>> n3.parent = n1
>>> print n1.get_child_by_name('Node 2').name
Node 2
But, if we try to use obengine.scenegraph.SceneGraph.get_node_by_name, what happens?
>>> print sg.get_node_by_name('Node 2').name
Traceback (most recent call last):
...
AmbiguousNameException: Node 2
This occurred because the scene graph wasn’t able to figure out which node with the name Node 2 you wanted: n1 or n2.
A SQLite-based scene graph.
Example:
>>> sg = SceneGraph()
>>> n1 = SceneNode('Node 1')
>>> n2 = SceneNode('Node 2')
>>> sg.add_node(n1)
>>> n2.parent = n1
>>> print sg.find_node_by_name('Node 2').name
Node 2
Retrieves the node named name from the scene graph. NoSuchNameException is raised if the requested name couldn’t be found; AmbiguousNameException is raised if more than one node with the given name was found.
NOTE: AmbiguousNameException is raised if there are more than one nodes with the given name on the entire scene graph; i.e, the entire scene graph is queried at once. So, if you have a node named “Name”, and a child node also named “Name”, then if you call SceneGraph.get_node_by_name(‘Name’), then AmbiguousNameException is raised.
Removes a node (with NID nid) from the scene graph. It also recursively removes all its children.
If the requested NID isn’t found, NoSuchIdException is raised.
Removes a node (with name name) from the scene graph. It also recursively removes all its children.
If the requested name couldn’t be found, NoSuchNameException is raised. Also, if more than one scene graph node is named name, then AmbiguousNameException is raised.
Generic scene node. You’ll probably want to subclass this class, instead of using it directly.
Recursively searches this node’s children for the first node named name. If multiple nodes named name are found at the same depth, if fail_on_ambiguous is False, then the first match is returned (be very careful with this). Otherwise (if fail_on_ambiguous is True, the default), AmbiguousNameException is raised. This method also raises NoSuchNameException if no node named name was found, and exc_on_non_existent is True.
Example:
>>> sg = SceneGraph()
>>> n1 = SceneNode('Node 1')
>>> n2 = SceneNode('Node 2')
>>> n3 = SceneNode('Node 3')
>>> n3.parent = n2
>>> n2.parent = n1
>>> sg.add_node(n1)
>>> print n1.find_child_by_name('Node 3').name
Node 3
Returns the child named name from this node’s list of children, If this node doesn’t have a child named name, then NoSuchNameException is raised.
Otherwise, if this node has more than one child named name, then AmbiguousNameException is raised.
WARNING: This method can be slow if this node has a lot of children (> 10,000).
Example:
>>> sg = SceneGraph()
>>> n1 = SceneNode('Node 1')
>>> n2 = SceneNode('Node 2')
>>> sg.add_node(n1)
>>> n2.parent = n1
>>> print n1.get_child_by_name('Node 2').name
Node 2
The name of this scene node. Example:
>>> sg = SceneGraph()
>>> n1 = SceneNode('Node 1')
>>> sg.add_node(n1)
>>> print sg.get_node_by_name('Node 1').name
Node 1
>>> n1.name = 'Node 1 - changed name'
>>> print sg.get_node_by_name('Node 1 - changed name').name
Node 1 - changed name
>>> print sg.get_node_by_name('Node 1')
Traceback (most recent call last):
...
NoSuchNameException: Node 1
Removes child with NID nid from this node’s list of children. It also recursively removes all that child’s children, as well.
If this node doesn’t have a child with the given NID, then NoSuchIdException is raised.
Footnotes
[1] | http://sqlite.org - the SQLite website |