mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
weakrefs to State objects replace the old fsm-redefine system
This commit is contained in:
parent
71b568d258
commit
76872ad998
@ -5,68 +5,6 @@ from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
import types
|
||||
|
||||
# This gets set by a dconfig variable in ShowBase.py
|
||||
# We cannot put a dconfig in here because ClassicFSM is not
|
||||
# dependent on Panda
|
||||
FsmRedefine = 0
|
||||
|
||||
# Map function pointers back into states so the Finder
|
||||
# can find a function and swap a newly redefined function
|
||||
# back into the original state
|
||||
# The map is keyed off function pointers which map to
|
||||
# a list of states that have that function pointer defined
|
||||
# as their enter function (or exit function as the case may be)
|
||||
EnterFuncRedefineMap = {}
|
||||
ExitFuncRedefineMap = {}
|
||||
|
||||
|
||||
def redefineEnterFunc(oldMethod, newFunction):
|
||||
import new
|
||||
if not FsmRedefine:
|
||||
return
|
||||
for method in EnterFuncRedefineMap.keys():
|
||||
if (type(method) == types.MethodType):
|
||||
function = method.im_func
|
||||
else:
|
||||
function = method
|
||||
#print ('function: ' + `function` + '\n' +
|
||||
# 'method: ' + `method` + '\n' +
|
||||
# 'oldMethod: ' + `oldMethod` + '\n' +
|
||||
# 'newFunction: ' + `newFunction` + '\n')
|
||||
if (function == oldMethod):
|
||||
newMethod = new.instancemethod(newFunction,
|
||||
method.im_self,
|
||||
method.im_class)
|
||||
stateList = EnterFuncRedefineMap[method]
|
||||
for state in stateList:
|
||||
state.setEnterFunc(newMethod)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def redefineExitFunc(oldMethod, newFunction):
|
||||
import new
|
||||
if not FsmRedefine:
|
||||
return
|
||||
for method in ExitFuncRedefineMap.keys():
|
||||
if (type(method) == types.MethodType):
|
||||
function = method.im_func
|
||||
else:
|
||||
function = method
|
||||
#print ('function: ' + `function` + '\n' +
|
||||
# 'method: ' + `method` + '\n' +
|
||||
# 'oldMethod: ' + `oldMethod` + '\n' +
|
||||
# 'newFunction: ' + `newFunction` + '\n')
|
||||
if (function == oldMethod):
|
||||
newMethod = new.instancemethod(newFunction,
|
||||
method.im_self,
|
||||
method.im_class)
|
||||
stateList = ExitFuncRedefineMap[method]
|
||||
for state in stateList:
|
||||
state.setExitFunc(newMethod)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
class State(DirectObject):
|
||||
notify = directNotify.newCategory("State")
|
||||
@ -75,6 +13,40 @@ class State(DirectObject):
|
||||
# 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 new
|
||||
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(new.instancemethod(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(new.instancemethod(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 = [])
|
||||
@ -87,6 +59,8 @@ class State(DirectObject):
|
||||
self.__FSMList = []
|
||||
if __debug__:
|
||||
self.setInspectorPos(inspectorPos)
|
||||
# For redefining
|
||||
self.States[self] = 1
|
||||
|
||||
# setters and getters
|
||||
|
||||
@ -99,38 +73,13 @@ class State(DirectObject):
|
||||
def getEnterFunc(self):
|
||||
return(self.__enterFunc)
|
||||
|
||||
if __debug__:
|
||||
def redefineFunc(self, oldMethod, newMethod, map):
|
||||
if not FsmRedefine:
|
||||
return
|
||||
# Methods are allowed to be None
|
||||
if oldMethod is None:
|
||||
return
|
||||
if map.has_key(oldMethod):
|
||||
# Get the list of states for the old function
|
||||
stateList = map[oldMethod]
|
||||
# Remove this state from that list of states
|
||||
stateList.remove(self)
|
||||
# If the stateList is now empty, remove this entry altogether
|
||||
if not stateList:
|
||||
del(map[oldMethod])
|
||||
# Now add the new function, creating a starter state list
|
||||
# if there is not one already
|
||||
stateList = map.get(newMethod, [])
|
||||
stateList.append(self)
|
||||
map[newMethod] = stateList
|
||||
|
||||
def setEnterFunc(self, stateEnterFunc):
|
||||
if __debug__:
|
||||
self.redefineFunc(self.__enterFunc, stateEnterFunc, EnterFuncRedefineMap)
|
||||
self.__enterFunc = stateEnterFunc
|
||||
|
||||
def getExitFunc(self):
|
||||
return(self.__exitFunc)
|
||||
|
||||
def setExitFunc(self, stateExitFunc):
|
||||
if __debug__:
|
||||
self.redefineFunc(self.__exitFunc, stateExitFunc, ExitFuncRedefineMap)
|
||||
self.__exitFunc = stateExitFunc
|
||||
|
||||
def transitionsToAny(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user