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)
|
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):
|
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
|
:type renderNode: mcedit2.rendering.rendernode.RenderNode
|
||||||
"""
|
"""
|
||||||
@ -162,47 +188,45 @@ def updateRenderNode(renderNode):
|
|||||||
if sceneNode.dirty:
|
if sceneNode.dirty:
|
||||||
renderNode.invalidate()
|
renderNode.invalidate()
|
||||||
sceneNode.dirty = False
|
sceneNode.dirty = False
|
||||||
if sceneNode.descendentChildrenChanged or sceneNode.childrenChanged:
|
|
||||||
|
if sceneNode.childrenChanged:
|
||||||
updateChildren(renderNode)
|
updateChildren(renderNode)
|
||||||
sceneNode.descendentChildrenChanged = False
|
|
||||||
sceneNode.childrenChanged = False
|
sceneNode.childrenChanged = False
|
||||||
|
|
||||||
|
if sceneNode.descendentNeedsUpdate:
|
||||||
def createRenderNode(sceneNode):
|
for renderChild in renderNode.children:
|
||||||
"""
|
updateRenderNode(renderChild)
|
||||||
|
sceneNode.descendentNeedsUpdate = False
|
||||||
:type sceneNode: Node
|
|
||||||
:rtype: mcedit2.rendering.rendernode.RenderNode
|
|
||||||
"""
|
|
||||||
renderNode = sceneNode.RenderNodeClass(sceneNode)
|
|
||||||
updateChildren(renderNode)
|
|
||||||
return renderNode
|
|
||||||
|
|
||||||
|
|
||||||
def updateChildren(renderNode):
|
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
|
:type renderNode: mcedit2.rendering.rendernode.RenderNode
|
||||||
:return:
|
:return:
|
||||||
:rtype:
|
:rtype:
|
||||||
"""
|
"""
|
||||||
sceneNode = renderNode.sceneNode
|
sceneNode = renderNode.sceneNode
|
||||||
deadChildren = []
|
orphans = []
|
||||||
|
|
||||||
|
# Find renderNode children whose sceneNode no longer has a parent
|
||||||
for renderChild in renderNode.children:
|
for renderChild in renderNode.children:
|
||||||
if renderChild.sceneNode.parent is None:
|
if renderChild.sceneNode.parent is None:
|
||||||
deadChildren.append(renderChild)
|
orphans.append(renderChild)
|
||||||
|
|
||||||
for dc in deadChildren:
|
for node in orphans:
|
||||||
renderNode.removeChild(dc)
|
renderNode.removeChild(node)
|
||||||
dc.destroy()
|
node.destroy()
|
||||||
|
|
||||||
|
# Find sceneNode children who do not have a renderNode as a child of this renderNode
|
||||||
for index, sceneChild in enumerate(sceneNode.children):
|
for index, sceneChild in enumerate(sceneNode.children):
|
||||||
renderChild = renderNode.childrenBySceneNode.get(sceneChild)
|
renderChild = renderNode.childrenBySceneNode.get(sceneChild)
|
||||||
if renderChild is None:
|
if renderChild is None:
|
||||||
renderNode.insertNode(index, createRenderNode(sceneChild))
|
renderNode.insertNode(index, createRenderNode(sceneChild))
|
||||||
sceneChild.dirty = False
|
sceneChild.dirty = False
|
||||||
else:
|
|
||||||
updateRenderNode(renderChild)
|
|
||||||
|
|
||||||
|
|
||||||
def renderScene(renderNode):
|
def renderScene(renderNode):
|
||||||
|
@ -18,7 +18,7 @@ class Node(object):
|
|||||||
self._children = []
|
self._children = []
|
||||||
self._dirty = True
|
self._dirty = True
|
||||||
self.childrenChanged = False
|
self.childrenChanged = False
|
||||||
self.descendentChildrenChanged = False
|
self.descendentNeedsUpdate = False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s(visible=%s, children=%d)" % (self.__class__.__name__, self.visible, len(self._children))
|
return "%s(visible=%s, children=%d)" % (self.__class__.__name__, self.visible, len(self._children))
|
||||||
@ -36,32 +36,32 @@ class Node(object):
|
|||||||
else:
|
else:
|
||||||
self._parent = None
|
self._parent = None
|
||||||
|
|
||||||
def touchChildren(self):
|
def childrenDidChange(self):
|
||||||
node = self
|
node = self
|
||||||
node.childrenChanged = True
|
node.childrenChanged = True
|
||||||
while node.parent:
|
while node.parent:
|
||||||
node = node.parent
|
node = node.parent
|
||||||
node.descendentChildrenChanged = True
|
node.descendentNeedsUpdate = True
|
||||||
|
|
||||||
def addChild(self, node):
|
def addChild(self, node):
|
||||||
self._children.append(node)
|
self._children.append(node)
|
||||||
node.parent = self
|
node.parent = self
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
|
|
||||||
def insertChild(self, index, node):
|
def insertChild(self, index, node):
|
||||||
self._children.insert(index, node)
|
self._children.insert(index, node)
|
||||||
node.parent = self
|
node.parent = self
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
|
|
||||||
def removeChild(self, node):
|
def removeChild(self, node):
|
||||||
self._children.remove(node)
|
self._children.remove(node)
|
||||||
node.parent = None
|
node.parent = None
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
for c in self._children:
|
for c in self._children:
|
||||||
c.parent = None
|
c.parent = None
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
self._children[:] = []
|
self._children[:] = []
|
||||||
|
|
||||||
def childCount(self):
|
def childCount(self):
|
||||||
@ -82,7 +82,7 @@ class Node(object):
|
|||||||
node = self
|
node = self
|
||||||
while node.parent:
|
while node.parent:
|
||||||
node = node.parent
|
node = node.parent
|
||||||
node.descendentChildrenChanged = True
|
node.descendentNeedsUpdate = True
|
||||||
|
|
||||||
_visible = True
|
_visible = True
|
||||||
@property
|
@property
|
||||||
@ -111,7 +111,7 @@ class NamedChildrenNode(Node):
|
|||||||
oldNode.parent = None
|
oldNode.parent = None
|
||||||
self._children[name] = node
|
self._children[name] = node
|
||||||
node.parent = self
|
node.parent = self
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
|
|
||||||
insertChild = NotImplemented
|
insertChild = NotImplemented
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ class NamedChildrenNode(Node):
|
|||||||
node = self._children.pop(name, None)
|
node = self._children.pop(name, None)
|
||||||
if node:
|
if node:
|
||||||
node.parent = None
|
node.parent = None
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
|
|
||||||
def getChild(self, name):
|
def getChild(self, name):
|
||||||
return self._children.get(name)
|
return self._children.get(name)
|
||||||
@ -128,7 +128,7 @@ class NamedChildrenNode(Node):
|
|||||||
for node in self.children:
|
for node in self.children:
|
||||||
node.parent = None
|
node.parent = None
|
||||||
self._children.clear()
|
self._children.clear()
|
||||||
self.touchChildren()
|
self.childrenDidChange()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def children(self):
|
def children(self):
|
||||||
|
Reference in New Issue
Block a user