Document createRenderNode, updateRenderNode, and updateChildren to make intentions more clear.
Change updateChildren to be non-recursive. updateRenderNode now descends into children and calls updateChildren as needed. The rendergraph is now slightly less creepy.
This commit is contained in:
parent
f66e2a8dbf
commit
5125fdf86e
@ -152,8 +152,34 @@ class BoxFaceRenderNode(RenderNode):
|
||||
GL.glDisable(GL.GL_BLEND)
|
||||
"""
|
||||
|
||||
def createRenderNode(sceneNode):
|
||||
"""
|
||||
Create and return a renderNode that renders the given sceneNode and all of its
|
||||
children.
|
||||
|
||||
Calls updateRenderNode to recursively create child renderNodes for each descendent of
|
||||
sceneNode.
|
||||
|
||||
:type sceneNode: Node
|
||||
:rtype: mcedit2.rendering.rendernode.RenderNode
|
||||
"""
|
||||
renderNode = sceneNode.RenderNodeClass(sceneNode)
|
||||
updateRenderNode(renderNode)
|
||||
return renderNode
|
||||
|
||||
|
||||
def updateRenderNode(renderNode):
|
||||
"""
|
||||
Synchronize the state of a renderNode and its childre with its scene node.
|
||||
|
||||
If the sceneNode that owns this renderNode is dirty, invalidates the renderNode.
|
||||
Then, updateChildren is called to add or remove renderNodes if the sceneNode had
|
||||
children added or removed.
|
||||
|
||||
As an optimization, each sceneNode keeps track of whether one of its descendents
|
||||
was dirtied or had children added or removed. This allows us to skip the recursive
|
||||
updateRenderNode call if it is not needed.
|
||||
|
||||
|
||||
:type renderNode: mcedit2.rendering.rendernode.RenderNode
|
||||
"""
|
||||
@ -162,47 +188,45 @@ def updateRenderNode(renderNode):
|
||||
if sceneNode.dirty:
|
||||
renderNode.invalidate()
|
||||
sceneNode.dirty = False
|
||||
if sceneNode.descendentChildrenChanged or sceneNode.childrenChanged:
|
||||
|
||||
if sceneNode.childrenChanged:
|
||||
updateChildren(renderNode)
|
||||
sceneNode.descendentChildrenChanged = False
|
||||
sceneNode.childrenChanged = False
|
||||
|
||||
|
||||
def createRenderNode(sceneNode):
|
||||
"""
|
||||
|
||||
:type sceneNode: Node
|
||||
:rtype: mcedit2.rendering.rendernode.RenderNode
|
||||
"""
|
||||
renderNode = sceneNode.RenderNodeClass(sceneNode)
|
||||
updateChildren(renderNode)
|
||||
return renderNode
|
||||
|
||||
if sceneNode.descendentNeedsUpdate:
|
||||
for renderChild in renderNode.children:
|
||||
updateRenderNode(renderChild)
|
||||
sceneNode.descendentNeedsUpdate = False
|
||||
|
||||
def updateChildren(renderNode):
|
||||
"""
|
||||
Compare the children of this renderNode to the children of its sceneNode. Create
|
||||
renderNodes for any new sceneNodes, and remove any renderNodes whose
|
||||
sceneNode is no longer a child of this node's sceneNode.
|
||||
|
||||
:type renderNode: mcedit2.rendering.rendernode.RenderNode
|
||||
:return:
|
||||
:rtype:
|
||||
"""
|
||||
sceneNode = renderNode.sceneNode
|
||||
deadChildren = []
|
||||
orphans = []
|
||||
|
||||
# Find renderNode children whose sceneNode no longer has a parent
|
||||
for renderChild in renderNode.children:
|
||||
if renderChild.sceneNode.parent is None:
|
||||
deadChildren.append(renderChild)
|
||||
orphans.append(renderChild)
|
||||
|
||||
for dc in deadChildren:
|
||||
renderNode.removeChild(dc)
|
||||
dc.destroy()
|
||||
for node in orphans:
|
||||
renderNode.removeChild(node)
|
||||
node.destroy()
|
||||
|
||||
# Find sceneNode children who do not have a renderNode as a child of this renderNode
|
||||
for index, sceneChild in enumerate(sceneNode.children):
|
||||
renderChild = renderNode.childrenBySceneNode.get(sceneChild)
|
||||
if renderChild is None:
|
||||
renderNode.insertNode(index, createRenderNode(sceneChild))
|
||||
sceneChild.dirty = False
|
||||
else:
|
||||
updateRenderNode(renderChild)
|
||||
|
||||
|
||||
|
||||
def renderScene(renderNode):
|
||||
|
@ -18,7 +18,7 @@ class Node(object):
|
||||
self._children = []
|
||||
self._dirty = True
|
||||
self.childrenChanged = False
|
||||
self.descendentChildrenChanged = False
|
||||
self.descendentNeedsUpdate = False
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(visible=%s, children=%d)" % (self.__class__.__name__, self.visible, len(self._children))
|
||||
@ -36,32 +36,32 @@ class Node(object):
|
||||
else:
|
||||
self._parent = None
|
||||
|
||||
def touchChildren(self):
|
||||
def childrenDidChange(self):
|
||||
node = self
|
||||
node.childrenChanged = True
|
||||
while node.parent:
|
||||
node = node.parent
|
||||
node.descendentChildrenChanged = True
|
||||
node.descendentNeedsUpdate = True
|
||||
|
||||
def addChild(self, node):
|
||||
self._children.append(node)
|
||||
node.parent = self
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
|
||||
def insertChild(self, index, node):
|
||||
self._children.insert(index, node)
|
||||
node.parent = self
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
|
||||
def removeChild(self, node):
|
||||
self._children.remove(node)
|
||||
node.parent = None
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
|
||||
def clear(self):
|
||||
for c in self._children:
|
||||
c.parent = None
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
self._children[:] = []
|
||||
|
||||
def childCount(self):
|
||||
@ -82,7 +82,7 @@ class Node(object):
|
||||
node = self
|
||||
while node.parent:
|
||||
node = node.parent
|
||||
node.descendentChildrenChanged = True
|
||||
node.descendentNeedsUpdate = True
|
||||
|
||||
_visible = True
|
||||
@property
|
||||
@ -111,7 +111,7 @@ class NamedChildrenNode(Node):
|
||||
oldNode.parent = None
|
||||
self._children[name] = node
|
||||
node.parent = self
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
|
||||
insertChild = NotImplemented
|
||||
|
||||
@ -119,7 +119,7 @@ class NamedChildrenNode(Node):
|
||||
node = self._children.pop(name, None)
|
||||
if node:
|
||||
node.parent = None
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
|
||||
def getChild(self, name):
|
||||
return self._children.get(name)
|
||||
@ -128,7 +128,7 @@ class NamedChildrenNode(Node):
|
||||
for node in self.children:
|
||||
node.parent = None
|
||||
self._children.clear()
|
||||
self.touchChildren()
|
||||
self.childrenDidChange()
|
||||
|
||||
@property
|
||||
def children(self):
|
||||
|
Reference in New Issue
Block a user