Browse Source

added optional 'from' collider node parameter to optimize triggered phase changes

Josh Wilson 18 years ago
parent
commit
8e9d2b85ab
1 changed files with 44 additions and 17 deletions
  1. 44 17
      direct/src/showbase/DistancePhasedNode.py

+ 44 - 17
direct/src/showbase/DistancePhasedNode.py

@@ -18,7 +18,8 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
        exitting the largest distance sphere
        exitting the largest distance sphere
      - What the load/unload functions are
      - What the load/unload functions are
      - What sort of events to listen for when a collision occurs
      - What sort of events to listen for when a collision occurs
-     - (Optional) - a collision bitmask for the phase collision spheres
+     - (Optional) A collision bitmask for the phase collision spheres
+     - (Optional) A 'from' collision node to collide into our 'into' spheres
 
 
     You specify the distances and function names by the phaseParamMap
     You specify the distances and function names by the phaseParamMap
     parameter to __init__().  For example:
     parameter to __init__().  For example:
@@ -30,6 +31,15 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
     def unloadPhaseAlias(self):
     def unloadPhaseAlias(self):
         pass
         pass
 
 
+    If the 'fromCollideNode' is supplied, we will set up our own
+    traverser and only traverse below this node.  It will send out
+    events of the form '<enterPrefix>%in' and '<exitPrefix>%in' in
+    order to match the main collision traverser's patterns.  Note
+    that this will only be used after a reset or phase change in
+    order to fully transition to the correct phase in a single pass.
+    Most of the time, it will be reacting to events from the main
+    collision traverser.    
+    
     IMPORTANT!: The following only applies when autoCleanup == True:
     IMPORTANT!: The following only applies when autoCleanup == True:
                 If you unload the last phase, by either calling
                 If you unload the last phase, by either calling
                 cleanup() or by exitting the last phase's distance,
                 cleanup() or by exitting the last phase's distance,
@@ -70,7 +80,8 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
     def __init__(self, name, phaseParamMap = {},
     def __init__(self, name, phaseParamMap = {},
                  autoCleanup = True,
                  autoCleanup = True,
                  enterPrefix = 'enter', exitPrefix = 'exit',
                  enterPrefix = 'enter', exitPrefix = 'exit',
-                 phaseCollideMask = BitMask32.allOn()):
+                 phaseCollideMask = BitMask32.allOn(),
+                 fromCollideNode = None):
         NodePath.__init__(self, name)
         NodePath.__init__(self, name)
         self.phaseParamMap = phaseParamMap
         self.phaseParamMap = phaseParamMap
         self.phaseParamList = sorted(phaseParamMap.items(),
         self.phaseParamList = sorted(phaseParamMap.items(),
@@ -81,9 +92,11 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
         self.__id = self.__allocateId()
         self.__id = self.__allocateId()
 
 
         self.autoCleanup = autoCleanup
         self.autoCleanup = autoCleanup
-        self.phaseCollideMask = phaseCollideMask
         self.enterPrefix = enterPrefix
         self.enterPrefix = enterPrefix
         self.exitPrefix = exitPrefix
         self.exitPrefix = exitPrefix
+        self.phaseCollideMask = phaseCollideMask
+        self.cTrav = base.cTrav
+        self.fromCollideNode = fromCollideNode
         self._colSpheres = []
         self._colSpheres = []
         
         
         self.reset()
         self.reset()
@@ -94,8 +107,8 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
     def __repr__(self):
     def __repr__(self):
         outStr = 'DistancePhasedObject('
         outStr = 'DistancePhasedObject('
         outStr += '%s' % `self.getName()`
         outStr += '%s' % `self.getName()`
-        for param, value in zip(('phaseParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask'),
-                                ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()')):
+        for param, value in zip(('phaseParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'),
+                                ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()','None')):
             outStr += eval('(\', ' + param + ' = %s\' % `self.' + param + '`,\'\')[self.' + param + ' == ' + value + ']')
             outStr += eval('(\', ' + param + ' = %s\' % `self.' + param + '`,\'\')[self.' + param + ' == ' + value + ']')
         outStr += ')'
         outStr += ')'
         return outStr
         return outStr
@@ -143,6 +156,12 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
             cSphereNodePath.stash()
             cSphereNodePath.stash()
             # cSphereNodePath.show() # For debugging
             # cSphereNodePath.show() # For debugging
             self._colSpheres.append(cSphereNodePath)
             self._colSpheres.append(cSphereNodePath)
+        if self.fromCollideNode:
+            self.cTrav = CollisionTraverser()
+            cHandler = CollisionHandlerEvent()
+            cHandler.addInPattern(self.enterPrefix + '%in')
+            cHandler.addOutPattern(self.exitPrefix + '%in')
+            self.cTrav.addCollider(self.fromCollideNode,cHandler)
 
 
         self.__enableCollisions(-1)
         self.__enableCollisions(-1)
         
         
@@ -218,11 +237,16 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath):
         phasing process in one frame in the cases where
         phasing process in one frame in the cases where
         we cross more than one phase border.
         we cross more than one phase border.
         """
         """
-        # we use 'render'here since if we only try to
-        # traverse ourself, we end up calling exit
-        # events for the rest of the eventHandlers. >:(
-        if base.cTrav:
-            base.cTrav.traverse(render)
+        if self.cTrav:
+            if self.cTrav is base.cTrav:
+                # we use 'render'here since if we only try to
+                # traverse ourself, we end up calling exit
+                # events for the rest of the eventHandlers.
+                # Consider supplying the fromCollideNode parameter.
+                self.cTrav.traverse(render)
+            else:
+                # Only traverse ourself
+                self.cTrav.traverse(self)
             base.eventMgr.doEvents()
             base.eventMgr.doEvents()
         
         
 class BufferedDistancePhasedNode(DistancePhasedNode):
 class BufferedDistancePhasedNode(DistancePhasedNode):
@@ -243,7 +267,7 @@ class BufferedDistancePhasedNode(DistancePhasedNode):
     notify = directNotify.newCategory("BufferedDistancePhasedObject")
     notify = directNotify.newCategory("BufferedDistancePhasedObject")
 
 
     def __init__(self, name, bufferParamMap = {}, autoCleanup = True,
     def __init__(self, name, bufferParamMap = {}, autoCleanup = True,
-                 enterPrefix = 'enter', exitPrefix = 'exit', phaseCollideMask = BitMask32.allOn()):
+                 enterPrefix = 'enter', exitPrefix = 'exit', phaseCollideMask = BitMask32.allOn(), fromCollideNode = None):
         sParams = dict(bufferParamMap)
         sParams = dict(bufferParamMap)
         for key in sParams:
         for key in sParams:
             sParams[key] = sParams[key][0]
             sParams[key] = sParams[key][0]
@@ -252,7 +276,8 @@ class BufferedDistancePhasedNode(DistancePhasedNode):
                                     autoCleanup = autoCleanup,
                                     autoCleanup = autoCleanup,
                                     enterPrefix = enterPrefix,
                                     enterPrefix = enterPrefix,
                                     exitPrefix = exitPrefix,
                                     exitPrefix = exitPrefix,
-                                    phaseCollideMask = phaseCollideMask)
+                                    phaseCollideMask = phaseCollideMask,
+                                    fromCollideNode = fromCollideNode)
         self.bufferParamMap = bufferParamMap
         self.bufferParamMap = bufferParamMap
         self.bufferParamList = sorted(bufferParamMap.items(),
         self.bufferParamList = sorted(bufferParamMap.items(),
                                       key = lambda x: x[1],
                                       key = lambda x: x[1],
@@ -261,8 +286,8 @@ class BufferedDistancePhasedNode(DistancePhasedNode):
     def __repr__(self):
     def __repr__(self):
         outStr = 'BufferedDistancePhasedNode('
         outStr = 'BufferedDistancePhasedNode('
         outStr += '%s' % `self.getName()`
         outStr += '%s' % `self.getName()`
-        for param, value in zip(('bufferParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask'),
-                                ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()')):
+        for param, value in zip(('bufferParamMap', 'autoCleanup', 'enterPrefix', 'exitPrefix', 'phaseCollideMask', 'fromCollideNode'),
+                                ('{}', 'True','\'enter\'','\'exit\'','BitMask32.allOn()', 'None')):
             outStr += eval('(\', ' + param + ' = %s\' % `self.' + param + '`,\'\')[self.' + param + ' == ' + value + ']')
             outStr += eval('(\', ' + param + ' = %s\' % `self.' + param + '`,\'\')[self.' + param + ' == ' + value + ']')
         outStr += ')'
         outStr += ')'
         return outStr
         return outStr
@@ -294,8 +319,8 @@ if __debug__ and 0:
     cNode.addSolid(cSphere)
     cNode.addSolid(cSphere)
     cNodePath = NodePath(cNode)
     cNodePath = NodePath(cNode)
     cNodePath.reparentTo(base.cam)
     cNodePath.reparentTo(base.cam)
-    #cNodePath.show()
-    #cNodePath.setPos(25,0,0)
+    # cNodePath.show()
+    # cNodePath.setPos(25,0,0)
     
     
     base.cTrav = CollisionTraverser()
     base.cTrav = CollisionTraverser()
     
     
@@ -307,7 +332,9 @@ if __debug__ and 0:
     base.cTrav.addCollider(cNodePath,eventHandler)
     base.cTrav.addCollider(cNodePath,eventHandler)
 
 
     p = BufferedDistancePhasedNode('p',{'At':(10,20),'Near':(100,200),'Far':(1000, 1020)},
     p = BufferedDistancePhasedNode('p',{'At':(10,20),'Near':(100,200),'Far':(1000, 1020)},
-                                   autoCleanup = True)
+                                   autoCleanup = False,
+                                   fromCollideNode = cNodePath,
+                                   )
 
 
     p.reparentTo(render)
     p.reparentTo(render)
     p._DistancePhasedNode__oneTimeCollide()
     p._DistancePhasedNode__oneTimeCollide()