forked from panda3d/panda3d
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathState.py
More file actions
233 lines (177 loc) · 7.15 KB
/
State.py
File metadata and controls
233 lines (177 loc) · 7.15 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
"""State module: contains State class"""
__all__ = ['State']
from direct.directnotify.DirectNotifyGlobal import directNotify
from direct.showbase.DirectObject import DirectObject
import types
class State(DirectObject):
notify = directNotify.newCategory("State")
# this 'constant' can be used to specify that the state
# can transition to any other state
Any = 'ANY'
# Keep a list of State objects currently in memory for
# Control-C-Control-V redefining. These are just weakrefs so they
# should not cause any leaks.
if __debug__:
import weakref
States = weakref.WeakKeyDictionary()
@classmethod
def replaceMethod(self, oldFunction, newFunction):
import types
count = 0
for state in self.States:
# Note: you can only replace methods currently
enterFunc = state.getEnterFunc()
exitFunc = state.getExitFunc()
# print 'testing: ', state, enterFunc, exitFunc, oldFunction
if type(enterFunc) == types.MethodType:
if (enterFunc.im_func == oldFunction):
# print 'found: ', enterFunc, oldFunction
state.setEnterFunc(types.MethodType(newFunction,
enterFunc.im_self,
enterFunc.im_class))
count += 1
if type(exitFunc) == types.MethodType:
if (exitFunc.im_func == oldFunction):
# print 'found: ', exitFunc, oldFunction
state.setExitFunc(types.MethodType(newFunction,
exitFunc.im_self,
exitFunc.im_class))
count += 1
return count
def __init__(self, name, enterFunc=None, exitFunc=None,
transitions=Any, inspectorPos = []):
"""__init__(self, string, func, func, string[], inspectorPos = [])
State constructor: takes name, enter func, exit func, and
a list of states it can transition to (or State.Any)."""
self.__name = name
self.__enterFunc = enterFunc
self.__exitFunc = exitFunc
self.__transitions = transitions
self.__FSMList = []
if __debug__:
self.setInspectorPos(inspectorPos)
# For redefining
self.States[self] = 1
# setters and getters
def getName(self):
return(self.__name)
def setName(self, stateName):
self.__name = stateName
def getEnterFunc(self):
return(self.__enterFunc)
def setEnterFunc(self, stateEnterFunc):
self.__enterFunc = stateEnterFunc
def getExitFunc(self):
return(self.__exitFunc)
def setExitFunc(self, stateExitFunc):
self.__exitFunc = stateExitFunc
def transitionsToAny(self):
""" returns true if State defines transitions to any other state """
return self.__transitions is State.Any
def getTransitions(self):
"""
warning -- if the state transitions to any other state,
returns an empty list (falsely implying that the state
has no transitions)
see State.transitionsToAny()
"""
if self.transitionsToAny():
return []
return self.__transitions
def isTransitionDefined(self, otherState):
if self.transitionsToAny():
return 1
# if we're given a state object, get its name instead
if type(otherState) != type(''):
otherState = otherState.getName()
return (otherState in self.__transitions)
def setTransitions(self, stateTransitions):
"""setTransitions(self, string[])"""
self.__transitions = stateTransitions
def addTransition(self, transition):
"""addTransitions(self, string)"""
if not self.transitionsToAny():
self.__transitions.append(transition)
else:
State.notify.warning(
'attempted to add transition %s to state that '
'transitions to any state')
if __debug__:
def getInspectorPos(self):
"""getInspectorPos(self)"""
return(self.__inspectorPos)
def setInspectorPos(self, inspectorPos):
"""setInspectorPos(self, [x, y])"""
self.__inspectorPos = inspectorPos
# support for HFSMs
def getChildren(self):
"""
Return the list of child FSMs
"""
return(self.__FSMList)
def setChildren(self, FSMList):
"""setChildren(self, ClassicFSM[])
Set the children to given list of FSMs
"""
self.__FSMList = FSMList
def addChild(self, ClassicFSM):
"""
Add the given ClassicFSM to list of child FSMs
"""
self.__FSMList.append(ClassicFSM)
def removeChild(self, ClassicFSM):
"""
Remove the given ClassicFSM from list of child FSMs
"""
if ClassicFSM in self.__FSMList:
self.__FSMList.remove(ClassicFSM)
def hasChildren(self):
"""
Return true if state has child FSMs
"""
return len(self.__FSMList) > 0
def __enterChildren(self, argList):
"""
Enter all child FSMs
"""
for fsm in self.__FSMList:
# Check to see if the child fsm is already in a state
# if it is, politely request the initial state
if fsm.getCurrentState():
# made this 'conditional_request()' instead of 'request()' to avoid warning when
# loading minigames where rules->frameworkInit transition doesnt exist and you
# don't want to add it since it results in hanging the game
fsm.conditional_request((fsm.getInitialState()).getName())
# If it has no current state, I assume this means it
# has never entered the initial state, so enter it
# explicitly
else:
fsm.enterInitialState()
def __exitChildren(self, argList):
"""
Exit all child FSMs
"""
for fsm in self.__FSMList:
fsm.request((fsm.getFinalState()).getName())
# basic State functionality
def enter(self, argList=[]):
"""
Call the enter function for this state
"""
# enter child FSMs first. It is assumed these have a start
# state that is safe to enter
self.__enterChildren(argList)
if (self.__enterFunc != None):
apply(self.__enterFunc, argList)
def exit(self, argList=[]):
"""
Call the exit function for this state
"""
# first exit child FSMs
self.__exitChildren(argList)
# call exit function if it exists
if (self.__exitFunc != None):
apply(self.__exitFunc, argList)
def __str__(self):
return "State: name = %s, enter = %s, exit = %s, trans = %s, children = %s" %\
(self.__name, self.__enterFunc, self.__exitFunc, self.__transitions, self.__FSMList)