Browse Source

optimized ignoreAll()

Darren Ranalli 23 years ago
parent
commit
410a8f423a
2 changed files with 69 additions and 28 deletions
  1. 39 6
      direct/src/showbase/DirectObject.py
  2. 30 22
      direct/src/showbase/Messenger.py

+ 39 - 6
direct/src/showbase/DirectObject.py

@@ -1,6 +1,7 @@
 
 
 from MessengerGlobal import *
 from MessengerGlobal import *
 from DirectNotifyGlobal import *
 from DirectNotifyGlobal import *
+from PythonUtil import *
 
 
 class DirectObject:
 class DirectObject:
     """
     """
@@ -8,24 +9,56 @@ class DirectObject:
     """
     """
     #def __del__(self):
     #def __del__(self):
     #    print "Destructing: ", self.__class__.__name__
     #    print "Destructing: ", self.__class__.__name__
-        
+
     # Event Handling
     # Event Handling
+    def __initEvents(self):
+        # this function exists because:
+        # - DirectObject does not have a constructor, and adding one
+        #   would involve touching many, many files
+        # - a constructor that creates self.events would cause every
+        #   DirectObject to incur the cost of an additional function
+        #   call and dictionary creation
+        # - DirectObjects that do not use the messenger should not have
+        #   an unused dictionary taking up space
+        # - the speed hit of calling this function on calls to accept,
+        #   ignore, etc. is negligible, since they are not called often
+        try:
+            self.events
+        except:
+            # list of events that this object is accepting
+            # we use a dictionary to avoid linear searches
+            self.events = {}
+
     def accept(self, event, method, extraArgs=[]):
     def accept(self, event, method, extraArgs=[]):
+        self.__initEvents()
+        ifAbsentPut(self.events, event, None)
         messenger.accept(event, self, method, extraArgs, 1)
         messenger.accept(event, self, method, extraArgs, 1)
 
 
     def acceptOnce(self, event, method, extraArgs=[]):
     def acceptOnce(self, event, method, extraArgs=[]):
+        self.__initEvents()
+        ifAbsentPut(self.events, event, None)
         messenger.accept(event, self, method, extraArgs, 0)
         messenger.accept(event, self, method, extraArgs, 0)
 
 
+    def _INTERNAL_acceptOnceExpired(self, event):
+        """ this should only be called by the messenger """
+        if self.events.has_key(event):
+            del self.events[event]
+
     def ignore(self, event):
     def ignore(self, event):
+        self.__initEvents()
+        if self.events.has_key(event):
+            del self.events[event]
         messenger.ignore(event, self)
         messenger.ignore(event, self)
 
 
     def ignoreAll(self):
     def ignoreAll(self):
-        messenger.ignoreAll(self)
+        self.__initEvents()
+        for event in self.events.keys():
+            messenger.ignore(event, self)
+        self.events.clear()
 
 
     def isAccepting(self, event):
     def isAccepting(self, event):
-        return messenger.isAccepting(event, self)
+        self.__initEvents()
+        return self.events.has_key(event)
 
 
     def isIgnoring(self, event):
     def isIgnoring(self, event):
-        return messenger.isIgnoring(event, self)
-    
-
+        return not self.isAccepting(event)

+ 30 - 22
direct/src/showbase/Messenger.py

@@ -65,22 +65,23 @@ class Messenger:
             if (len(acceptorDict) == 0):
             if (len(acceptorDict) == 0):
                 del self.dict[event]
                 del self.dict[event]
     
     
-    def ignoreAll(self, object):
-        """ ignoreAll(self, DirectObject)
-        Make this object no longer respond to any events it was accepting
-        Useful for cleanup
-        """
-        if Messenger.notify.getDebug():
-            Messenger.notify.debug(`object` + '\n now ignoring all events')
-        for event, acceptorDict in self.dict.items():
-            # If this object is there, delete it from the dictionary
-            if acceptorDict.has_key(object):
-                del acceptorDict[object]
-                # If this dictionary is now empty, remove the event
-                # entry from the Messenger alltogether
-                if (len(acceptorDict) == 0):
-                    del self.dict[event]
-
+##     ### moved into DirectObject for speed
+##     ###
+##     def ignoreAll(self, object):
+##         """ ignoreAll(self, DirectObject)
+##         Make this object no longer respond to any events it was accepting
+##         Useful for cleanup
+##         """
+##         if Messenger.notify.getDebug():
+##             Messenger.notify.debug(`object` + '\n now ignoring all events')
+##         for event, acceptorDict in self.dict.items():
+##             # If this object is there, delete it from the dictionary
+##             if acceptorDict.has_key(object):
+##                 del acceptorDict[object]
+##                 # If this dictionary is now empty, remove the event
+##                 # entry from the Messenger alltogether
+##                 if (len(acceptorDict) == 0):
+##                     del self.dict[event]
 
 
     def isAccepting(self, event, object):
     def isAccepting(self, event, object):
         """ isAccepting(self, string, DirectOject)        
         """ isAccepting(self, string, DirectOject)        
@@ -120,19 +121,26 @@ class Messenger:
             # We have to make this apparently redundant check, because
             # We have to make this apparently redundant check, because
             # it is possible that one object removes its own hooks
             # it is possible that one object removes its own hooks
             # in response to a handler called by a previous object.
             # in response to a handler called by a previous object.
-            callList = acceptorDict.get(object)
-            if callList:
-                method, extraArgs, persistent = callList
+            #
+            # NOTE: there is no danger of skipping over objects due to
+            # modifications to acceptorDict, since the for..in above
+            # iterates over a list of objects that is created once at
+            # the start
+            callInfo = acceptorDict.get(object)
+            if callInfo:
+                method, extraArgs, persistent = callInfo
                 apply(method, (extraArgs + sentArgs))
                 apply(method, (extraArgs + sentArgs))
                 # If this object was only accepting this event once,
                 # If this object was only accepting this event once,
                 # remove it from the dictionary
                 # remove it from the dictionary
                 if not persistent:
                 if not persistent:
+                    # notify the object that the event has been triggered
+                    object._INTERNAL_acceptOnceExpired(event)
                     # We need to check this because the apply above might
                     # We need to check this because the apply above might
                     # have done an ignore.
                     # have done an ignore.
                     if acceptorDict.has_key(object):
                     if acceptorDict.has_key(object):
                         del acceptorDict[object]
                         del acceptorDict[object]
-                    # If the dictionary at this event is now empty, remove the event
-                    # entry from the Messenger alltogether
+                    # If the dictionary at this event is now empty, remove
+                    # the event entry from the Messenger altogether
                     if (self.dict.has_key(event) and (len(self.dict[event]) == 0)):
                     if (self.dict.has_key(event) and (len(self.dict[event]) == 0)):
                         del self.dict[event]
                         del self.dict[event]
 
 
@@ -170,7 +178,7 @@ class Messenger:
                     params[0] = newMethod
                     params[0] = newMethod
                     # Found it retrun true
                     # Found it retrun true
                     retFlag += 1
                     retFlag += 1
-        # didnt find that method, return false
+        # didn't find that method, return false
         return retFlag
         return retFlag
     
     
     def toggleVerbose(self):
     def toggleVerbose(self):