From 4f77115b948f8d5825ac0a5e67e374f11ea62fd0 Mon Sep 17 00:00:00 2001 From: Darren Ranalli Date: Tue, 25 Apr 2006 21:49:23 +0000 Subject: [PATCH] added EventGroup --- direct/src/showbase/EventGroup.py | 104 ++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 direct/src/showbase/EventGroup.py diff --git a/direct/src/showbase/EventGroup.py b/direct/src/showbase/EventGroup.py new file mode 100755 index 0000000000..d1090a84fd --- /dev/null +++ b/direct/src/showbase/EventGroup.py @@ -0,0 +1,104 @@ +from direct.showbase import DirectObject +from direct.showbase.PythonUtil import SerialNum, Functor + +class EventGroup(DirectObject.DirectObject): + """This class allows you to group together multiple events and treat + them as a single event. The EventGroup will not send out its event until + all of its sub-events have occured.""" + + _SerialNum = SerialNum() + + def __init__(self, name, subEvents=None, doneEvent=None): + """ + Provide a meaningful name to aid debugging. + + doneEvent is optional. If not provided, a unique done event will be + generated and is available as EventGroup.getDoneEvent(). + + Examples: + + # waits for gotRed and gotBlue, then sends out 'gotColors' + EventGroup('getRedAndBlue', ('gotRed', 'gotBlue'), doneEvent='gotColors') + + # waits for two interests to close, then calls self._handleBothInterestsClosed() + # uses EventGroup.getDoneEvent() and EventGroup.newEvent() to generate unique, + # disposable event names + eGroup = EventGroup('closeInterests') + self.acceptOnce(eGroup.getDoneEvent(), self._handleBothInterestsClosed) + base.cr.closeInterest(interest1, event=eGroup.newEvent('closeInterest1')) + base.cr.closeInterest(interest2, event=eGroup.newEvent('closeInterest2')) + """ + self._name = name + self._subEvents = set() + self._completedEvents = set() + if doneEvent is None: + # no doneEvent provided, allocate a unique event name + doneEvent = 'EventGroup-%s-%s-Done' % ( + EventGroup._SerialNum.next(), self._name) + self._doneEvent = doneEvent + self._completed = False + + if subEvents is not None: + # add the events that were passed in to start with, more may be added + # later via newEvent() + for event in subEvents: + self.addEvent(event) + + def destroy(self): + del self._name + del self._subEvents + del self._completedEvents + del self._doneEvent + self.ignoreAll() + + def getName(self): + return self._name + + def getDoneEvent(self): + return self._doneEvent + + def isCompleted(self): + return self._completed + + def addEvent(self, eventName): + """ Adds a new event to the list of sub-events that we're waiting on. + Returns the name of the event. """ + if self._completed: + self.notify.error('addEvent(\'%s\') called on completed EventGroup \'%s\'' % ( + eventName, self.getName())) + if eventName in self._subEvents: + self.notify.error('addEvent(\'%s\'): event already in EventGroup \'%s\'' % ( + eventName, self.getName())) + self._subEvents.add(eventName) + self.acceptOnce(eventName, Functor(self._subEventComplete, eventName)) + return eventName + + def newEvent(self, name): + """ Pass in an event name and it will be unique-ified for you and added + to this EventGroup. TIP: there's no need to repeat information in this event + name that is already in the name of the EventGroup object. + Returns the new event name. """ + return self.addEvent('%s-SubEvent-%s-%s' % ( + self._name, EventGroup._SerialNum.next(), name)) + + def _subEventComplete(self, subEventName, *args, **kwArgs): + if subEventName in self._completedEvents: + self.notify.warning('_subEventComplete: \'%s\' already received' % + subEventName) + else: + self._completedEvents.add(subEventName) + if self._completedEvents == self._subEvents: + self._signalComplete() + + def _signalComplete(self): + self._completed = True + messenger.send(self._doneEvent) + self.destroy() + + def __repr__(self): + return '%s(\'%s\', %s, doneEvent=\'%s\') # completed=%s' % ( + self.__class__.__name__, + self._name, + tuple(self._subEvents), + self._doneEvent, + tuple(self._completedEvents))