forked from panda3d/panda3d
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventGroup.py
More file actions
executable file
·110 lines (91 loc) · 4.17 KB
/
EventGroup.py
File metadata and controls
executable file
·110 lines (91 loc) · 4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""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))