mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 19:08:55 -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
|
from direct.showbase.DirectObject import DirectObject
|
||||||
import types
|
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):
|
class State(DirectObject):
|
||||||
notify = directNotify.newCategory("State")
|
notify = directNotify.newCategory("State")
|
||||||
@ -75,6 +13,40 @@ class State(DirectObject):
|
|||||||
# can transition to any other state
|
# can transition to any other state
|
||||||
Any = 'ANY'
|
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,
|
def __init__(self, name, enterFunc=None, exitFunc=None,
|
||||||
transitions=Any, inspectorPos = []):
|
transitions=Any, inspectorPos = []):
|
||||||
"""__init__(self, string, func, func, string[], inspectorPos = [])
|
"""__init__(self, string, func, func, string[], inspectorPos = [])
|
||||||
@ -87,6 +59,8 @@ class State(DirectObject):
|
|||||||
self.__FSMList = []
|
self.__FSMList = []
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self.setInspectorPos(inspectorPos)
|
self.setInspectorPos(inspectorPos)
|
||||||
|
# For redefining
|
||||||
|
self.States[self] = 1
|
||||||
|
|
||||||
# setters and getters
|
# setters and getters
|
||||||
|
|
||||||
@ -99,38 +73,13 @@ class State(DirectObject):
|
|||||||
def getEnterFunc(self):
|
def getEnterFunc(self):
|
||||||
return(self.__enterFunc)
|
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):
|
def setEnterFunc(self, stateEnterFunc):
|
||||||
if __debug__:
|
|
||||||
self.redefineFunc(self.__enterFunc, stateEnterFunc, EnterFuncRedefineMap)
|
|
||||||
self.__enterFunc = stateEnterFunc
|
self.__enterFunc = stateEnterFunc
|
||||||
|
|
||||||
def getExitFunc(self):
|
def getExitFunc(self):
|
||||||
return(self.__exitFunc)
|
return(self.__exitFunc)
|
||||||
|
|
||||||
def setExitFunc(self, stateExitFunc):
|
def setExitFunc(self, stateExitFunc):
|
||||||
if __debug__:
|
|
||||||
self.redefineFunc(self.__exitFunc, stateExitFunc, ExitFuncRedefineMap)
|
|
||||||
self.__exitFunc = stateExitFunc
|
self.__exitFunc = stateExitFunc
|
||||||
|
|
||||||
def transitionsToAny(self):
|
def transitionsToAny(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user