panda3d/direct/src/showbase/Messenger.py
2001-08-30 20:40:57 +00:00

232 lines
9.1 KiB
Python

from PythonUtil import *
from DirectNotifyGlobal import *
class Messenger:
notify = None
def __init__(self):
""" __init__(self)
One dictionary does it all. It has the following structure:
{event1 : {object1: [method, extraArgs, persistent],
object2: [method, extraArgs, persistent]},
event2 : {object1: [method, extraArgs, persistent],
object2: [method, extraArgs, persistent]}}
Or, for an example with more real data:
{'mouseDown' : {avatar : [avatar.jump, [2.0], 1]}}
"""
self.dict = {}
if (Messenger.notify == None):
Messenger.notify = directNotify.newCategory("Messenger")
# Messenger.notify.setDebug(1)
def accept(self, event, object, method, extraArgs=[], persistent=1):
""" accept(self, string, DirectObject, Function, List, Boolean)
Make this object accept this event. When the event is
sent (using Messenger.send or from C++), method will be executed,
optionally passing in extraArgs.
If the persistent flag is set, it will continue to respond
to this event, otherwise it will respond only once.
"""
if Messenger.notify.getDebug():
Messenger.notify.debug('object: ' + `object`
+ '\n now accepting: ' + `event`
+ '\n method: ' + `method`
+ '\n extraArgs: ' + `extraArgs`
+ '\n persistent: ' + `persistent`)
acceptorDict = ifAbsentPut(self.dict, event, {})
acceptorDict[object] = [method, extraArgs, persistent]
def ignore(self, event, object):
""" ignore(self, string, DirectObject)
Make this object no longer respond to this event.
It is safe to call even if it was not already accepting
"""
if Messenger.notify.getDebug():
Messenger.notify.debug(`object` + '\n now ignoring: ' + `event`)
# Find the dictionary of all the objects accepting this event
acceptorDict = self.dict.get(event)
# If this object is there, delete it from the dictionary
if acceptorDict and 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 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):
""" isAccepting(self, string, DirectOject)
Is this object accepting this event?
"""
if self.dict.has_key(event):
if self.dict[event].has_key(object):
# Found it, return true
return 1
# If we looked in both dictionaries and made it here
# that object must not be accepting that event.
return 0
def whoAccepts(self, event):
""" whoAccepts(self, event):
Return objects accepting the given event
"""
return self.dict.get(event, None)
def isIgnoring(self, event, object):
""" isIgnorning(self, string, DirectObject)
Is this object ignoring this event?
"""
return (not self.isAccepting(event, object))
def send(self, event, sentArgs=[]):
""" send(self, string, [arg1, arg2,...])
Send this event, optionally passing in arguments
"""
# Do not print the new frame debug, it is too noisy!
if (Messenger.notify.getDebug() and (event != 'NewFrame')):
Messenger.notify.debug('sent event: ' + event + ' sentArgs: ' + `sentArgs`)
acceptorDict = self.dict.get(event)
if not acceptorDict:
return
for object in acceptorDict.keys():
# We have to make this apparently redundant check, because
# it is possible that one object removes its own hooks
# in response to a handler called by a previous object.
callList = acceptorDict.get(object)
if callList:
method, extraArgs, persistent = callList
apply(method, (extraArgs + sentArgs))
# If this object was only accepting this event once,
# remove it from the dictionary
if not persistent:
# We need to check this because the apply above might
# have done an ignore.
if acceptorDict.has_key(object):
del acceptorDict[object]
# If the dictionary at this event is now empty, remove the event
# entry from the Messenger alltogether
if (self.dict.has_key(event) and (len(self.dict[event]) == 0)):
del self.dict[event]
def clear(self):
"""clear(self)
Start fresh with a clear dict
"""
self.dict.clear()
def replaceMethod(self, oldMethod, newFunction):
"""
This is only used by Finder.py - the module that lets
you redefine functions with Control-c-Control-v
"""
import new
retFlag = 0
for entry in self.dict.items():
event, objectDict = entry
for objectEntry in objectDict.items():
object, params = objectEntry
method = params[0]
if (type(method) == types.MethodType):
function = method.im_func
else:
function = method
#print ('function: ' + `function` + '\n' +
# 'method: ' + `method` + '\n' +
# 'oldMethod: ' + `oldMethod` + '\n' +
# 'newFunction: ' + `newFunction` + '\n')
if (function == oldMethod):
newMethod = new.instancemethod(newFunction,
method.im_self,
method.im_class)
params[0] = newMethod
# Found it retrun true
retFlag += 1
# didnt find that method, return false
return retFlag
def toggleVerbose(self):
Messenger.notify.setDebug(1 - Messenger.notify.getDebug())
def __repr__(self):
"""
Compact version of event, acceptor pairs
"""
str = "="*64 + "\n"
keys = self.dict.keys()
keys.sort()
for event in keys:
str = str + event.ljust(32) + '\t'
acceptorDict = self.dict[event]
for object in acceptorDict.keys():
method, extraArgs, persistent = acceptorDict[object]
className = object.__class__.__name__
methodName = method.__name__
str = str + className + '.' + methodName + ' '
str = str + '\n'
return str
def detailedRepr(self):
"""
Print out the table in a detailed readable format
"""
import types
str = 'Messenger\n'
str = str + '='*50 + '\n'
keys = self.dict.keys()
keys.sort()
for event in keys:
acceptorDict = self.dict[event]
str = str + 'Event: ' + event + '\n'
for object in acceptorDict.keys():
function, extraArgs, persistent = acceptorDict[object]
if (type(object) == types.InstanceType):
className = object.__class__.__name__
else:
className = "Not a class"
functionName = function.__name__
str = (str + '\t' +
'Acceptor: ' + className + ' instance' + '\n\t' +
'Function name:' + functionName + '\n\t' +
'Extra Args: ' + `extraArgs` + '\n\t' +
'Persistent: ' + `persistent` + '\n')
# If this is a class method, get its actual function
if (type(function) == types.MethodType):
str = (str + '\t' +
'Method: ' + `function` + '\n\t' +
'Function: ' + `function.im_func` + '\n')
else:
str = (str + '\t' +
'Function: ' + `function` + '\n')
str = str + '='*50 + '\n'
return str