EventGroup.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. """This module defines the EventGroup class."""
  2. __all__ = ['EventGroup']
  3. from direct.showbase import DirectObject
  4. from direct.showbase.PythonUtil import SerialNumGen, Functor
  5. class EventGroup(DirectObject.DirectObject):
  6. """This class allows you to group together multiple events and treat
  7. them as a single event. The EventGroup will not send out its event until
  8. all of its sub-events have occured."""
  9. _SerialNumGen = SerialNumGen()
  10. def __init__(self, name, subEvents=None, doneEvent=None):
  11. """
  12. Provide a meaningful name to aid debugging.
  13. doneEvent is optional. If not provided, a unique done event will be
  14. generated and is available as EventGroup.getDoneEvent().
  15. Examples:
  16. # waits for gotRed and gotBlue, then sends out 'gotColors'
  17. EventGroup('getRedAndBlue', ('gotRed', 'gotBlue'), doneEvent='gotColors')
  18. # waits for two interests to close, then calls self._handleBothInterestsClosed()
  19. # uses EventGroup.getDoneEvent() and EventGroup.newEvent() to generate unique,
  20. # disposable event names
  21. eGroup = EventGroup('closeInterests')
  22. self.acceptOnce(eGroup.getDoneEvent(), self._handleBothInterestsClosed)
  23. base.cr.closeInterest(interest1, event=eGroup.newEvent('closeInterest1'))
  24. base.cr.closeInterest(interest2, event=eGroup.newEvent('closeInterest2'))
  25. """
  26. self._name = name
  27. self._subEvents = set()
  28. self._completedEvents = set()
  29. if doneEvent is None:
  30. # no doneEvent provided, allocate a unique event name
  31. doneEvent = 'EventGroup-%s-%s-Done' % (
  32. EventGroup._SerialNumGen.next(), self._name)
  33. self._doneEvent = doneEvent
  34. self._completed = False
  35. if subEvents is not None:
  36. # add the events that were passed in to start with, more may be added
  37. # later via newEvent()
  38. for event in subEvents:
  39. self.addEvent(event)
  40. def destroy(self):
  41. if hasattr(self, '_name'):
  42. # keep this around
  43. #del self._doneEvent
  44. del self._name
  45. del self._subEvents
  46. del self._completedEvents
  47. self.ignoreAll()
  48. def getName(self):
  49. return self._name
  50. def getDoneEvent(self):
  51. return self._doneEvent
  52. def isCompleted(self):
  53. return self._completed
  54. def addEvent(self, eventName):
  55. """ Adds a new event to the list of sub-events that we're waiting on.
  56. Returns the name of the event. """
  57. if self._completed:
  58. self.notify.error('addEvent(\'%s\') called on completed EventGroup \'%s\'' % (
  59. eventName, self.getName()))
  60. if eventName in self._subEvents:
  61. self.notify.error('addEvent(\'%s\'): event already in EventGroup \'%s\'' % (
  62. eventName, self.getName()))
  63. self._subEvents.add(eventName)
  64. self.acceptOnce(eventName, Functor(self._subEventComplete, eventName))
  65. return eventName
  66. def newEvent(self, name):
  67. """ Pass in an event name and it will be unique-ified for you and added
  68. to this EventGroup. TIP: there's no need to repeat information in this event
  69. name that is already in the name of the EventGroup object.
  70. Returns the new event name. """
  71. return self.addEvent('%s-SubEvent-%s-%s' % (
  72. self._name, EventGroup._SerialNumGen.next(), name))
  73. def _subEventComplete(self, subEventName, *args, **kwArgs):
  74. if subEventName in self._completedEvents:
  75. self.notify.warning('_subEventComplete: \'%s\' already received' %
  76. subEventName)
  77. else:
  78. self._completedEvents.add(subEventName)
  79. if self._completedEvents == self._subEvents:
  80. self._signalComplete()
  81. def _signalComplete(self):
  82. self._completed = True
  83. messenger.send(self._doneEvent)
  84. self.destroy()
  85. def __repr__(self):
  86. return '%s(\'%s\', %s, doneEvent=\'%s\') # completed=%s' % (
  87. self.__class__.__name__,
  88. self._name,
  89. tuple(self._subEvents),
  90. self._doneEvent,
  91. tuple(self._completedEvents))