| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- """This module defines the EventGroup class."""
- __all__ = ['EventGroup']
- from direct.showbase import DirectObject
- from direct.showbase.PythonUtil import SerialNumGen, 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."""
- _SerialNumGen = SerialNumGen()
- 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._SerialNumGen.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):
- if hasattr(self, '_name'):
- # keep this around
- #del self._doneEvent
- del self._name
- del self._subEvents
- del self._completedEvents
- 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._SerialNumGen.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))
|