瀏覽代碼

*** empty log message ***

Mark Mine 25 年之前
父節點
當前提交
f240602bf6

+ 40 - 1
direct/src/directutil/DirectCameraControl.py

@@ -1,6 +1,7 @@
 from PandaObject import *
 from PandaObject import *
 
 
 CAM_MOVE_DURATION = 1.0
 CAM_MOVE_DURATION = 1.0
+Y_AXIS = Vec3(0,1,0)
 
 
 class DirectCameraControl(PandaObject):
 class DirectCameraControl(PandaObject):
     def __init__(self, direct):
     def __init__(self, direct):
@@ -34,7 +35,8 @@ class DirectCameraControl(PandaObject):
                 # If shift key is pressed, just perform horiz and vert pan:
                 # If shift key is pressed, just perform horiz and vert pan:
                 self.spawnHPPan()
                 self.spawnHPPan()
             else:
             else:
-                # Otherwise, check for a hit point based on current mouse position
+                # Otherwise, check for a hit point based on
+                # current mouse position
                 # And then spawn task to determine mouse mode
                 # And then spawn task to determine mouse mode
                 numEntries = self.direct.iRay.pickGeom(
                 numEntries = self.direct.iRay.pickGeom(
                     render,chan.mouseX,chan.mouseY)
                     render,chan.mouseX,chan.mouseY)
@@ -348,6 +350,43 @@ class DirectCameraControl(PandaObject):
                            0.0)
                            0.0)
         return Task.cont
         return Task.cont
 
 
+    def fitOnWidget(self):
+        # Fit the node on the screen
+        
+        # stop any ongoing tasks
+        taskMgr.removeTasksNamed('manipulateCamera')
+
+        # How big is the node?
+        nodeScale = self.direct.widget.getScale(render)
+        maxScale = max(nodeScale[0],nodeScale[1],nodeScale[2])
+        maxDim = min(self.chan.nearWidth, self.chan.nearHeight)
+
+        # At what distance does the object fill 30% of the screen?
+        # Assuming radius of 1 on widget
+        camY = self.chan.near * (2.0 * maxScale)/(0.3 * maxDim)
+    
+        # What is the vector through the center of the screen?
+        centerVec = Y_AXIS * camY
+    
+        # Where is the node relative to the viewpoint
+        vWidget2Camera = self.direct.widget.getPos(self.camera)
+    
+        # How far do you move the camera to be this distance from the node?
+        deltaMove = vWidget2Camera - centerVec
+    
+        # Move a target there
+        self.relNodePath.setPos(self.camera, deltaMove)
+
+	parent = self.camera.getParent()
+	self.camera.wrtReparentTo(self.relNodePath)
+	fitTask = self.camera.lerpPos(Point3(0,0,0),
+                                      CAM_MOVE_DURATION,
+                                      blendType = 'easeInOut',
+                                      task = 'manipulateCamera')
+        # Upon death, reparent Cam to parent
+        fitTask.parent = parent
+        fitTask.uponDeath = self.reparentCam
+
     def enableMouseFly(self):
     def enableMouseFly(self):
 	self.enableMouseInteraction()
 	self.enableMouseInteraction()
 	self.enableHotKeys()
 	self.enableHotKeys()

+ 4 - 1
direct/src/directutil/DirectSession.py

@@ -73,7 +73,10 @@ class DirectSession(PandaObject):
 
 
             # Adjust widgets size
             # Adjust widgets size
             self.widget.setScale(dnp.getRadius())
             self.widget.setScale(dnp.getRadius())
-            
+            # This is the additional scaling factor used to grow and
+            # shrink the widget
+            self.widget.setScalingFactor(1.0)
+
             # Spawn task to have object handles follow the selected object
             # Spawn task to have object handles follow the selected object
             taskMgr.removeTasksNamed('followSelectedNodePath')
             taskMgr.removeTasksNamed('followSelectedNodePath')
             t = Task.Task(self.followSelectedNodePathTask)
             t = Task.Task(self.followSelectedNodePathTask)

+ 4 - 0
direct/src/showbase/FSM.py

@@ -97,6 +97,8 @@ class FSM(DirectObject):
         """__exitCurrent(self)
         """__exitCurrent(self)
         Exit the current state"""
         Exit the current state"""
         FSM.notify.info("exiting %s" % self.__currentState.getName())
         FSM.notify.info("exiting %s" % self.__currentState.getName())
+        messenger.send(self.getName() + '_' +
+                       self.__currentState.getName() + '_exited')
         self.__currentState.exit()
         self.__currentState.exit()
         self.__currentState = None
         self.__currentState = None
                     
                     
@@ -106,6 +108,8 @@ class FSM(DirectObject):
         if (aState in self.__states):
         if (aState in self.__states):
             self.__currentState = aState
             self.__currentState = aState
             aState.enter()
             aState.enter()
+            messenger.send(self.getName() + '_' +
+                           aState.getName() + '_entered')
             FSM.notify.info("entering %s" % aState.getName())
             FSM.notify.info("entering %s" % aState.getName())
         else:
         else:
             FSM.notify.error("enter: no such state")
             FSM.notify.error("enter: no such state")

+ 9 - 0
direct/src/showbase/State.py

@@ -16,6 +16,7 @@ class State(DirectObject):
         self.setEnterFunc(enterFunc)
         self.setEnterFunc(enterFunc)
         self.setExitFunc(exitFunc)
         self.setExitFunc(exitFunc)
         self.setTransitions(transitions)
         self.setTransitions(transitions)
+        self.setDefaultPosition([])
         self.__FSMList = None
         self.__FSMList = None
 
 
 
 
@@ -53,6 +54,14 @@ class State(DirectObject):
         """setTransitions(self, string[])"""
         """setTransitions(self, string[])"""
         self.__transitions = stateTransitions
         self.__transitions = stateTransitions
 
 
+    def getDefaultPosition(self):
+        """getDefaultPosition(self)"""
+        return(self.__defaultPosition)
+
+    def setDefaultPosition(self, defaultPosition):
+        """setDefaultPosition(self, x, y)"""
+        self.__defaultPosition = defaultPosition
+
 
 
     # support for HFSMs
     # support for HFSMs
     
     

+ 59 - 26
direct/src/tkpanels/FSMInspector.py

@@ -1,3 +1,4 @@
+from PandaObject import *
 from Tkinter import *
 from Tkinter import *
 from tkSimpleDialog import askstring
 from tkSimpleDialog import askstring
 import Pmw
 import Pmw
@@ -6,23 +7,27 @@ import operator
 
 
 DELTA = (5.0 / 360.) * 2.0 * math.pi
 DELTA = (5.0 / 360.) * 2.0 * math.pi
 
 
-class FSMInspector(Pmw.MegaToplevel):
+class FSMInspector(Pmw.MegaToplevel, PandaObject):
     def __init__(self, parent = None, **kw):
     def __init__(self, parent = None, **kw):
+        
         # Initialize instance variables
         # Initialize instance variables
+        self.states = []
         self.stateInspectorDict = {}
         self.stateInspectorDict = {}
         
         
         #define the megawidget options
         #define the megawidget options
         INITOPT = Pmw.INITOPT
         INITOPT = Pmw.INITOPT
         optiondefs = (
         optiondefs = (
             ('title', 'FSM Viewer', None),
             ('title', 'FSM Viewer', None),
-            ('currentFSM', (), None),
+            ('FSM', (), None),
             ('gridSize', '0.25i', self._setGridSize),
             ('gridSize', '0.25i', self._setGridSize),
             )
             )
         self.defineoptions(kw, optiondefs)
         self.defineoptions(kw, optiondefs)
 
 
         # Initialize the toplevel widget
         # Initialize the toplevel widget
         Pmw.MegaToplevel.__init__(self, parent)
         Pmw.MegaToplevel.__init__(self, parent)
-        
+
+        self.fsm = self['FSM']
+
         # Create the components
         # Create the components
         oldInterior = Pmw.MegaToplevel.interior(self)
         oldInterior = Pmw.MegaToplevel.interior(self)
         # The Menu Bar
         # The Menu Bar
@@ -138,8 +143,8 @@ class FSMInspector(Pmw.MegaToplevel):
         for key in self.stateInspectorDict.keys():
         for key in self.stateInspectorDict.keys():
             si = self.stateInspectorDict[key]
             si = self.stateInspectorDict[key]
             state = si.state
             state = si.state
-            if state.transitionArray:
-                for name in state.transitionArray:
+            if state.getTransitions():
+                for name in state.getTransitions():
                     self.connectStates(si, self.getStateInspector(name))
                     self.connectStates(si, self.getStateInspector(name))
 
 
     def connectStates(self, fromState, toState):
     def connectStates(self, fromState, toState):
@@ -199,29 +204,39 @@ class FSMInspector(Pmw.MegaToplevel):
         self._top = self._canvas.yview()[0]
         self._top = self._canvas.yview()[0]
 
 
     def createStateInspectors(self):
     def createStateInspectors(self):
-        fsm = self['currentFSM']
-        # Number of rows/cols needed to fit inspectors in a grid 
-        dim = int(math.ceil(math.sqrt(len(fsm))))
+        fsm = self.fsm
+        self.states = fsm.getStates()
+        # Number of rows/cols needed to fit inspectors in a grid
+        dim = int(math.ceil(math.sqrt(len(self.states))))
         # Separation between nodes
         # Separation between nodes
         spacing = 2.5 * self._canvas.canvasx('0.375i')
         spacing = 2.5 * self._canvas.canvasx('0.375i')
         count = 0
         count = 0
-        for state in self['currentFSM']:
+        for state in self.states:
             si = self.addState(state)
             si = self.addState(state)
-            if state.defaultPosition:
-                si.setPos(state.defaultPosition[0], state.defaultPosition[1])
+            if state.getDefaultPosition():
+                si.setPos(state.getDefaultPosition()[0],
+                          state.getDefaultPosition()[1])
             else:
             else:
                 row = int(math.floor(count / dim))
                 row = int(math.floor(count / dim))
                 col = count % dim
                 col = count % dim
                 si.setPos(col * spacing, row * spacing +
                 si.setPos(col * spacing, row * spacing +
                           0.5 * (0, spacing)[col % 2])
                           0.5 * (0, spacing)[col % 2])
+            # Add hooks
+            self.accept(fsm.getName() + '_' + si.getName() + '_entered',
+                        si.enteredState)
+            self.accept(fsm.getName() + '_' + si.getName() + '_exited',
+                        si.exitedState)
             count = count + 1
             count = count + 1
         self.drawConnections()
         self.drawConnections()
+        if fsm.getCurrentState():
+            self.enteredState(fsm.getCurrentState().getName())
 
 
     def getStateInspector(self, name):
     def getStateInspector(self, name):
         return self.stateInspectorDict.get(name, None)
         return self.stateInspectorDict.get(name, None)
 
 
     def addState(self, state):
     def addState(self, state):
-        si = self.stateInspectorDict[state.name] = StateInspector(self, state)
+        si = self.stateInspectorDict[state.getName()] = (
+            StateInspector(self, state))
         return si
         return si
 
 
     def enteredState(self, stateName):
     def enteredState(self, stateName):
@@ -263,12 +278,12 @@ class FSMInspector(Pmw.MegaToplevel):
             si = dict[key]
             si = dict[key]
             center = si.center()
             center = si.center()
             print "'%s' : (%.3f, %.3f)," % \
             print "'%s' : (%.3f, %.3f)," % \
-                  (si.state.name, center[0], center[1])
+                  (si.state.getName(), center[0], center[1])
         for key in keys[-1:]:
         for key in keys[-1:]:
             si = dict[key]
             si = dict[key]
             center = si.center()
             center = si.center()
             print "'%s' : (%.3f, %.3f)," % \
             print "'%s' : (%.3f, %.3f)," % \
-                  (si.state.name, center[0], center[1])
+                  (si.state.getName(), center[0], center[1])
         print '}'
         print '}'
 
 
     def toggleBalloon(self):
     def toggleBalloon(self):
@@ -287,8 +302,9 @@ class StateInspector(Pmw.MegaArchetype):
         self.state = state
         self.state = state
         # Create a unique tag which you can use to move a marker and
         # Create a unique tag which you can use to move a marker and
         # and its corresponding text around together
         # and its corresponding text around together
-        self.tag = state.name
-
+        self.tag = state.getName()
+        self.fsm = inspector.fsm
+        
         # Pointers to the inspector's components
         # Pointers to the inspector's components
         self.scrolledCanvas = inspector.component('scrolledCanvas')
         self.scrolledCanvas = inspector.component('scrolledCanvas')
         self._canvas = self.scrolledCanvas.component('canvas')
         self._canvas = self.scrolledCanvas.component('canvas')
@@ -313,11 +329,11 @@ class StateInspector(Pmw.MegaArchetype):
                                                (self.y + half),
                                                (self.y + half),
                                               fill = 'CornflowerBlue',
                                               fill = 'CornflowerBlue',
                                               tags = (self.tag,'markers'))
                                               tags = (self.tag,'markers'))
-        self.text = self._canvas.create_text(0, 0, text = state.name, 
+        self.text = self._canvas.create_text(0, 0, text = state.getName(),
                                            justify = CENTER,
                                            justify = CENTER,
                                            tags = (self.tag,'labels'))
                                            tags = (self.tag,'labels'))
         # Is this state contain a sub machine?
         # Is this state contain a sub machine?
-        if state.fsmArray:
+        if state.hasChildren():
             # reduce half by sqrt of 2.0
             # reduce half by sqrt of 2.0
             half = half * 0.707106
             half = half * 0.707106
             self.rect = self._canvas.create_rectangle((- half), (- half),
             self.rect = self._canvas.create_rectangle((- half), (- half),
@@ -327,11 +343,11 @@ class StateInspector(Pmw.MegaArchetype):
 
 
         # The Popup State Menu
         # The Popup State Menu
         self._popupMenu = Menu(self._canvas, tearoff = 0)
         self._popupMenu = Menu(self._canvas, tearoff = 0)
-        self._popupMenu.add_command(label = 'Request transistion to ' +
-                                    state.name,
+        self._popupMenu.add_command(label = 'Request transition to ' +
+                                    state.getName(),
                                     command = self.transitionTo)
                                     command = self.transitionTo)
-        if state.fsmArray:
-            self._popupMenu.add_command(label = 'Inspect ' + state.name +
+        if state.hasChildren():
+            self._popupMenu.add_command(label = 'Inspect ' + state.getName() +
                                         ' submachine',
                                         ' submachine',
                                         command = self.inspectSubMachine)
                                         command = self.inspectSubMachine)
                     
                     
@@ -356,7 +372,7 @@ class StateInspector(Pmw.MegaArchetype):
         c = self.center()
         c = self.center()
         self._canvas.coords(self.marker,
         self._canvas.coords(self.marker,
                             c[0] - half, c[1] - half, c[0] + half, c[1] + half)
                             c[0] - half, c[1] - half, c[0] + half, c[1] + half)
-        if self.state.fsmArray:
+        if self.state.hasChildren():
             half = self.radius * 0.707106
             half = self.radius * 0.707106
             self._canvas.coords(self.rect,
             self._canvas.coords(self.rect,
                             c[0] - half, c[1] - half, c[0] + half, c[1] + half)
                             c[0] - half, c[1] - half, c[0] + half, c[1] + half)
@@ -389,6 +405,9 @@ class StateInspector(Pmw.MegaArchetype):
         c = self._canvas.coords(self.marker)
         c = self._canvas.coords(self.marker)
         return (c[0] + c[2])/2.0, (c[1] + c[3])/2.0
         return (c[0] + c[2])/2.0, (c[1] + c[3])/2.0
 
 
+    def getName(self):
+        return self.tag
+
     # Event Handlers
     # Event Handlers
     def mouseEnter(self, event):
     def mouseEnter(self, event):
         self._canvas.itemconfig(self.marker, width = 2)
         self._canvas.itemconfig(self.marker, width = 2)
@@ -416,7 +435,7 @@ class StateInspector(Pmw.MegaArchetype):
                              event.widget.winfo_pointery())
                              event.widget.winfo_pointery())
 
 
     def transitionTo(self):
     def transitionTo(self):
-        print 'transition to ' + self.tag
+        self.fsm.request(self.getName())
 
 
     def inspectSubMachine(self):
     def inspectSubMachine(self):
         print 'inspect ' + self.tag + ' subMachine'
         print 'inspect ' + self.tag + ' subMachine'
@@ -441,7 +460,7 @@ class dummyFSM:
         self.stateCollection = stateCollection
         self.stateCollection = stateCollection
         if layout:
         if layout:
             for state in self.stateCollection:
             for state in self.stateCollection:
-                pos = layout.get(state.name, None)
+                pos = layout.get(state.getName(), None)
                 if pos:
                 if pos:
                     state.defaultPosition= pos
                     state.defaultPosition= pos
     def __getitem__(self, item):
     def __getitem__(self, item):
@@ -465,5 +484,19 @@ if __name__ == '__main__':
                              'state-4' : (335.67, 143.86),
                              'state-4' : (335.67, 143.86),
                              'state-5' : (239.76, 143.86),
                              'state-5' : (239.76, 143.86),
                              'state-6' : (23.98, 71.93)})
                              'state-6' : (23.98, 71.93)})
-    fsmi = FSMInspector(title = 'My Little Viewer', currentFSM = fsm)
+    fsmi = FSMInspector(title = 'My Little Viewer', FSM = fsm)
     mainloop()
     mainloop()
+"""
+def enterState():
+    print 'enterState'
+def exitState():
+    print 'exitState'
+fsm = FSM.FSM('stopLight',
+          [ State.State('red', enterState, exitState, ['green']),
+            State.State('yellow', enterState, exitState, ['red']),
+            State.State('green', enterState, exitState, ['yellow']) ],
+          'red',
+          'red')
+inspector = FSMInspector(FSM = fsm)
+"""
+