From 76872ad998c660aa98b69f3dc5f60e07b12d7252 Mon Sep 17 00:00:00 2001 From: Joe Shochet Date: Thu, 15 Jun 2006 16:54:38 +0000 Subject: [PATCH] weakrefs to State objects replace the old fsm-redefine system --- direct/src/fsm/State.py | 123 ++++++++++++---------------------------- 1 file changed, 36 insertions(+), 87 deletions(-) diff --git a/direct/src/fsm/State.py b/direct/src/fsm/State.py index 12e5dbaa61..156b5f9eb0 100644 --- a/direct/src/fsm/State.py +++ b/direct/src/fsm/State.py @@ -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):