mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-18 12:43:44 -04:00
165 lines
5.2 KiB
Python
165 lines
5.2 KiB
Python
"""Finite State Machine module: contains the FSM class"""
|
|
|
|
from DirectObject import *
|
|
|
|
class FSM(DirectObject):
|
|
"""FSM class: Finite State Machine class"""
|
|
|
|
# create FSM DirectNotify category
|
|
notify = directNotify.newCategory("FSM")
|
|
#notify.setDebug(1)
|
|
|
|
# special methods
|
|
|
|
def __init__(self, name, states=[], initialStateName=None,
|
|
finalStateName=None):
|
|
"""__init__(self, string, State[], string, string)
|
|
|
|
FSM constructor: takes name, list of states, initial state and
|
|
final state as:
|
|
|
|
fsm = FSM.FSM('stopLight',
|
|
[ State.State('red', enterRed, exitRed, ['green']),
|
|
State.State('yellow', enterYellow, exitYellow, ['red']),
|
|
State.State('green', enterGreen, exitGreen, ['yellow']) ],
|
|
'red',
|
|
'red')
|
|
|
|
"""
|
|
|
|
self.setName(name)
|
|
self.setStates(states)
|
|
self.setInitialState(initialStateName)
|
|
self.setFinalState(finalStateName)
|
|
|
|
|
|
# Enter the initial state.
|
|
# It is assumed that the initial state takes no arguments.
|
|
self.__currentState = self.__initialState
|
|
#self.__enter(self.__initialState)
|
|
|
|
def enterInitialState(self):
|
|
self.__enter(self.__initialState)
|
|
|
|
def __str__(self):
|
|
"""__str__(self)"""
|
|
return "FSM: name = %s \n states = %s \n initial = %s \n final = %s \n current = %s" % (self.__name, self.__states, self.__initialState, self.__finalState, self.__currentState)
|
|
|
|
|
|
# setters and getters
|
|
|
|
def getName(self):
|
|
"""getName(self)"""
|
|
return(self.__name)
|
|
|
|
def setName(self, name):
|
|
"""setName(self, string)"""
|
|
self.__name = name
|
|
|
|
def getStates(self):
|
|
"""getStates(self)"""
|
|
return(self.__states)
|
|
|
|
def setStates(self, states):
|
|
"""setStates(self, State[])"""
|
|
self.__states = states
|
|
|
|
def getInitialState(self):
|
|
"""getInitialState(self)"""
|
|
return(self.__initialState)
|
|
|
|
def setInitialState(self, initialStateName):
|
|
"""setInitialState(self, string)"""
|
|
self.__initialState = self.getStateNamed(initialStateName)
|
|
|
|
def getFinalState(self):
|
|
"""getFinalState(self)"""
|
|
return(self.__finalState)
|
|
|
|
def setFinalState(self, finalStateName):
|
|
"""setFinalState(self, string)"""
|
|
self.__finalState = self.getStateNamed(finalStateName)
|
|
|
|
def getCurrentState(self):
|
|
"""getCurrentState(self)"""
|
|
return(self.__currentState)
|
|
|
|
|
|
# lookup funcs
|
|
|
|
def getStateNamed(self, stateName):
|
|
"""getStateNamed(self, string)
|
|
Return the state with given name if found, issue warning otherwise"""
|
|
for state in self.__states:
|
|
if (state.getName() == stateName):
|
|
return state
|
|
FSM.notify.warning("[%s] : getStateNamed: %s no such state" %
|
|
(self.__name, str(stateName)))
|
|
|
|
|
|
# basic FSM functionality
|
|
|
|
def __exitCurrent(self, argList):
|
|
"""__exitCurrent(self)
|
|
Exit the current state"""
|
|
FSM.notify.debug("[%s]: exiting %s" % (self.__name,
|
|
self.__currentState.getName()))
|
|
self.__currentState.exit(argList)
|
|
messenger.send(self.getName() + '_' +
|
|
self.__currentState.getName() + '_exited')
|
|
self.__currentState = None
|
|
|
|
def __enter(self, aState, argList=[]):
|
|
"""__enter(self, State)
|
|
Enter a given state, if it exists"""
|
|
if (aState in self.__states):
|
|
FSM.notify.debug("[%s]: entering %s" % (self.__name,
|
|
aState.getName()))
|
|
self.__currentState = aState
|
|
messenger.send(self.getName() + '_' +
|
|
aState.getName() + '_entered')
|
|
aState.enter(argList)
|
|
else:
|
|
FSM.notify.error("[%s]: enter: no such state" % self.__name)
|
|
|
|
def __transition(self, aState, enterArgList=[], exitArgList=[]):
|
|
"""__transition(self, State, enterArgList, exitArgList)
|
|
Exit currentState and enter given one"""
|
|
self.__exitCurrent(exitArgList)
|
|
self.__enter(aState, enterArgList)
|
|
|
|
def request(self, aStateName, enterArgList=[], exitArgList=[]):
|
|
"""request(self, string)
|
|
Attempt transition from currentState to given one.
|
|
Return true is transition exists to given state,
|
|
false otherwise.
|
|
"""
|
|
if (aStateName in self.__currentState.getTransitions()):
|
|
self.__transition(self.getStateNamed(aStateName),
|
|
enterArgList,
|
|
exitArgList)
|
|
return 1
|
|
# We can implicitly always transition to our final state.
|
|
elif (aStateName == self.__finalState.getName()):
|
|
FSM.notify.debug("[%s]: implicit transition to final state: %s" %
|
|
(self.__name, aStateName))
|
|
self.__transition(self.getStateNamed(aStateName),
|
|
enterArgList,
|
|
exitArgList)
|
|
return 1
|
|
else:
|
|
FSM.notify.debug("[%s]: no transition exists to %s" %
|
|
(self.__name, aStateName))
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|