Browse Source

*** empty log message ***

Joe Shochet 25 years ago
parent
commit
e0bd9966df
4 changed files with 101 additions and 2 deletions
  1. 0 1
      direct/src/fsm/FSM.py
  2. 85 1
      direct/src/fsm/State.py
  3. 11 0
      direct/src/showbase/Finder.py
  4. 5 0
      direct/src/showbase/ShowBase.py

+ 0 - 1
direct/src/fsm/FSM.py

@@ -7,7 +7,6 @@ class FSM(DirectObject):
 
     # create FSM DirectNotify category
     notify = directNotify.newCategory("FSM")
-    #notify.setDebug(1)
 
     # special methods
     

+ 85 - 1
direct/src/fsm/State.py

@@ -2,6 +2,69 @@
 """State module: contains State class"""
 
 from DirectObject import *
+import types
+
+# This gets set by a dconfig variable in ShowBase.py
+# We cannot put a dconfig in here because FSM 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):
@@ -13,6 +76,9 @@ class State(DirectObject):
         """__init__(self, string, func, func, string[], inspectorPos = [])
         State constructor: takes name, enter func, exit func, and
         a list of states it can transition to."""
+        self.__enterFunc = None
+        self.__exitFunc = None
+        
         self.setName(name)
         self.setEnterFunc(enterFunc)
         self.setExitFunc(exitFunc)
@@ -35,8 +101,25 @@ class State(DirectObject):
         """getEnterFunc(self)"""
         return(self.__enterFunc)
 
+    def redefineFunc(self, oldMethod, newMethod, map):
+        if not FsmRedefine:
+            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):
-        """setEnterFunc(self, func)"""
+        self.redefineFunc(self.__enterFunc, stateEnterFunc, EnterFuncRedefineMap)
         self.__enterFunc = stateEnterFunc
 
     def getExitFunc(self):
@@ -45,6 +128,7 @@ class State(DirectObject):
 
     def setExitFunc(self, stateExitFunc):
         """setExitFunc(self, func)"""
+        self.redefineFunc(self.__exitFunc, stateExitFunc, ExitFuncRedefineMap)
         self.__exitFunc = stateExitFunc
 
     def getTransitions(self):

+ 11 - 0
direct/src/showbase/Finder.py

@@ -132,6 +132,7 @@ def copyFuncs(fromClass, toClass):
                 oldFunc = toClass.__dict__[key]
                 replaceMessengerFunc(oldFunc, newFunc)
                 replaceTaskMgrFunc(oldFunc, newFunc)
+                replaceStateFunc(oldFunc, newFunc)
             toClass.__dict__[key] = newFunc
 
 def replaceMessengerFunc(oldFunc, newFunc):
@@ -143,3 +144,13 @@ def replaceTaskMgrFunc(oldFunc, newFunc):
     res = taskMgr.replaceMethod(oldFunc, newFunc)
     if res:
         print ('replaced taskMgr function: ' + newFunc.__name__)
+
+def replaceStateFunc(oldFunc, newFunc):
+    import State
+    res = State.redefineEnterFunc(oldFunc, newFunc)
+    if res:
+        print ('replaced state enter function: ' + newFunc.__name__)
+    res = State.redefineExitFunc(oldFunc, newFunc)
+    if res:
+        print ('replaced state exit function: ' + newFunc.__name__)
+

+ 5 - 0
direct/src/showbase/ShowBase.py

@@ -19,6 +19,7 @@ import Transitions
 import Loader
 import time
 import FSM
+import State
 
 globalClock = ClockObject.ClockObject.getGlobalClock()
 
@@ -38,9 +39,13 @@ class ShowBase:
         self.wantStats = self.config.GetBool('want-stats', 0)
 
         taskMgr.taskTimerVerbose = self.config.GetBool('task-timer-verbose', 0)
+
         fsmDebug = self.config.GetBool('fsm-debug', 0)
         FSM.FSM.notify.setDebug(fsmDebug)
 
+        fsmRedefine = self.config.GetBool('fsm-redefine', 0)
+        State.FsmRedefine = fsmRedefine
+
         self.initialState = NodeAttributes()
         # Set a default "off color" (i.e. use poly color) for color transitions
         self.initialState.setAttribute(ColorTransition.getClassType(),