Browse Source

merged ai-telemetry branch to trunk

Darren Ranalli 21 years ago
parent
commit
330918c8f9

+ 34 - 17
direct/src/distributed/DistributedNodeAI.py

@@ -1,24 +1,42 @@
 from AIBaseGlobal import *
+from PandaModules import NodePath
 import DistributedObjectAI
-import Task
 
-class DistributedNodeAI(DistributedObjectAI.DistributedObjectAI):
-    def __init__(self, air):
+class DistributedNodeAI(DistributedObjectAI.DistributedObjectAI, NodePath):
+    def __init__(self, air, name=None):
         DistributedObjectAI.DistributedObjectAI.__init__(self, air)
+        if name is None:
+            name = self.__class__.__name__
+        NodePath.__init__(self, hidden.attachNewNode(name))
 
     def delete(self):
         DistributedObjectAI.DistributedObjectAI.delete(self)
 
     ### setParent ###
 
-    def d_setParent(self, parentString):
-        if type(parentString) == type(''):
-            self.sendUpdate("setParentStr", [parentString])
+    def b_setParent(self, parentToken):
+        if type(parentToken) == types.StringType:
+            self.setParentStr(parentToken)
         else:
-            self.sendUpdate("setParent", [parentString])
+            self.setParent(parentToken)
+        self.d_setParent(parentToken)
 
-    def setParent(self, parentString):
-        pass
+    def d_setParent(self, parentToken):
+        if type(parentToken) == type(''):
+            self.sendUpdate("setParentStr", [parentToken])
+        else:
+            self.sendUpdate("setParent", [parentToken])
+
+    def setParentStr(self, parentToken):
+        print 'setParentStr(%s): %s' % (self.doId, parentToken)
+        self.do_setParent(parentToken)
+
+    def setParent(self, parentToken):
+        print 'setParent(%s): %s' % (self.doId, parentToken)
+        self.do_setParent(parentToken)
+
+    def do_setParent(self, parentToken):
+        self.air.parentMgr.requestReparent(self, parentToken)
 
     ###### set pos and hpr functions #######
 
@@ -47,8 +65,8 @@ class DistributedNodeAI(DistributedObjectAI.DistributedObjectAI):
         self.sendUpdate("setR", [r])
 
     def setXY(self, x, y):
-        pass
-
+        self.setX(x)
+        self.setY(y)
     def d_setXY(self, x, y):
         self.sendUpdate("setXY", [x, y])
 
@@ -61,19 +79,18 @@ class DistributedNodeAI(DistributedObjectAI.DistributedObjectAI):
         self.sendUpdate("setHpr", [h, p, r])
 
     def setXYH(self, x, y, h):
-        pass
-        
+        self.setX(x)
+        self.setY(y)
+        self.setH(h)
     def d_setXYH(self, x, y, h):
         self.sendUpdate("setXYH", [x, y, h])
 
     def setXYZH(self, x, y, z, h):
-        pass
-
+        self.setPos(x, y, z)
+        self.setH(h)
     def d_setXYZH(self, x, y, z, h):
         self.sendUpdate("setXYZH", [x, y, z, h])
 
     # setPosHpr provided by NodePath
     def d_setPosHpr(self, x, y, z, h, p, r):
         self.sendUpdate("setPosHpr", [x, y, z, h, p, r])
-
-

+ 11 - 42
direct/src/distributed/DistributedSmoothNode.py

@@ -3,6 +3,7 @@
 from PandaModules import *
 from ClockDelta import *
 import DistributedNode
+import DistributedSmoothNodeBase
 import Task
 
 # This number defines our tolerance for out-of-sync telemetry packets.
@@ -67,7 +68,9 @@ def activateSmoothing(smoothing, prediction):
         
 
 
-class DistributedSmoothNode(DistributedNode.DistributedNode):
+class DistributedSmoothNode(DistributedNode.DistributedNode,
+                            DistributedSmoothNodeBase.\
+                            DistributedSmoothNodeBase):
     """DistributedSmoothNode class:
 
     This specializes DistributedNode to add functionality to smooth
@@ -81,11 +84,16 @@ class DistributedSmoothNode(DistributedNode.DistributedNode):
         except:
             self.DistributedSmoothNode_initialized = 1
             DistributedNode.DistributedNode.__init__(self, cr)
+            DistributedSmoothNodeBase.DistributedSmoothNodeBase.__init__(self)
 
             self.smoother = SmoothMover()
             self.smoothStarted = 0
             self.lastSuggestResync = 0
 
+    def delete(self):
+        DistributedSmoothNodeBase.DistributedSmoothNodeBase.delete(self)
+        DistributedNode.DistributedNode.delete(self)
+
     ### Methods to handle computing and updating of the smoothed
     ### position.
 
@@ -162,76 +170,42 @@ class DistributedSmoothNode(DistributedNode.DistributedNode):
         self.smoother.setPhonyTimestamp()
         self.smoother.markPosition()
         
-
-    
-    ### distributed set pos and hpr functions ###
-
-    ### These functions send the distributed update to set the
-    ### appropriate values on the remote side.  These are
-    ### composite fields, with all the likely combinations
-    ### defined; each function maps (via the dc file) to one or
-    ### more component operations on the remote client.
-
-    def d_setSmStop(self):
-        self.sendUpdate("setSmStop", [globalClockDelta.getFrameNetworkTime()])
+    # distributed set pos and hpr functions
+    # 'send' versions are inherited from DistributedSmoothNodeBase
     def setSmStop(self, timestamp):
         self.setComponentTLive(timestamp)
-
-    def d_setSmH(self, h):
-        self.sendUpdate("setSmH", [h, globalClockDelta.getFrameNetworkTime()])
     def setSmH(self, h, timestamp):
         self.setComponentH(h)
         self.setComponentTLive(timestamp)
-
-    def d_setSmXY(self, x, y):
-        self.sendUpdate("setSmXY", [x, y, globalClockDelta.getFrameNetworkTime()])
     def setSmXY(self, x, y, timestamp):
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentTLive(timestamp)
-
-    def d_setSmXZ(self, x, z):
-        self.sendUpdate("setSmXZ", [x, z, globalClockDelta.getFrameNetworkTime()])
     def setSmXZ(self, x, z, timestamp):
         self.setComponentX(x)
         self.setComponentZ(z)
         self.setComponentTLive(timestamp)
-
-    def d_setSmPos(self, x, y, z):
-        self.sendUpdate("setSmPos", [x, y, z, globalClockDelta.getFrameNetworkTime()])
     def setSmPos(self, x, y, z, timestamp):
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentZ(z)
         self.setComponentTLive(timestamp)
-
-    def d_setSmHpr(self, h, p, r):
-        self.sendUpdate("setSmHpr", [h, p, r, globalClockDelta.getFrameNetworkTime()])
     def setSmHpr(self, h, p, r, timestamp):
         self.setComponentH(h)
         self.setComponentP(p)
         self.setComponentR(r)
         self.setComponentTLive(timestamp)
-
-    def d_setSmXYH(self, x, y, h):
-        self.sendUpdate("setSmXYH", [x, y, h, globalClockDelta.getFrameNetworkTime()])
     def setSmXYH(self, x, y, h, timestamp):
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentH(h)
         self.setComponentTLive(timestamp)
-
-    def d_setSmXYZH(self, x, y, z, h):
-        self.sendUpdate("setSmXYZH", [x, y, z, h, globalClockDelta.getFrameNetworkTime()])
     def setSmXYZH(self, x, y, z, h, timestamp):
         self.setComponentX(x)
         self.setComponentY(y)
         self.setComponentZ(z)
         self.setComponentH(h)
         self.setComponentTLive(timestamp)
-
-    def d_setSmPosHpr(self, x, y, z, h, p, r):
-        self.sendUpdate("setSmPosHpr", [x, y, z, h, p, r, globalClockDelta.getFrameNetworkTime()])
     def setSmPosHpr(self, x, y, z, h, p, r, timestamp):
         self.setComponentX(x)
         self.setComponentY(y)
@@ -311,11 +285,6 @@ class DistributedSmoothNode(DistributedNode.DistributedNode):
         self.smoother.setTimestamp(local)
         self.smoother.markPosition()
 
-    def b_clearSmoothing(self):
-        self.d_clearSmoothing()
-        self.clearSmoothing()
-    def d_clearSmoothing(self):
-        self.sendUpdate("clearSmoothing", [0])
     def clearSmoothing(self, bogus = None):
         # Call this to invalidate all the old position reports
         # (e.g. just before popping to a new position).

+ 84 - 0
direct/src/distributed/DistributedSmoothNodeAI.py

@@ -0,0 +1,84 @@
+from AIBaseGlobal import *
+import DistributedNodeAI
+import DistributedSmoothNodeBase
+
+class DistributedSmoothNodeAI(DistributedNodeAI.DistributedNodeAI,
+                              DistributedSmoothNodeBase.\
+                              DistributedSmoothNodeBase):
+    def __init__(self, air, name=None):
+        DistributedNodeAI.DistributedNodeAI.__init__(self, air, name)
+        DistributedSmoothNodeBase.DistributedSmoothNodeBase.__init__(self)
+
+    def delete(self):
+        DistributedSmoothNodeBase.DistributedSmoothNodeBase.delete(self)
+        DistributedNodeAI.DistributedNodeAI.delete(self)
+
+    # distributed set pos and hpr functions
+    # these are invoked by the DC system
+    # 'send' (d_set*) versions are inherited from DistributedSmoothNodeBase
+    def setSmStop(self, t):
+        self.setComponentT(t)
+    def setSmH(self, h, t):
+        self.setComponentH(h)
+        self.setComponentT(t)
+    def setSmXY(self, x, y, t):
+        self.setComponentX(x)
+        self.setComponentY(y)
+        self.setComponentT(t)
+    def setSmXZ(self, x, z, t):
+        self.setComponentX(x)
+        self.setComponentZ(z)
+        self.setComponentT(t)
+    def setSmPos(self, x, y, z, t):
+        self.setComponentX(x)
+        self.setComponentY(y)
+        self.setComponentZ(z)
+        self.setComponentT(t)
+    def setSmHpr(self, h, p, r, t):
+        self.setComponentH(h)
+        self.setComponentP(p)
+        self.setComponentR(r)
+        self.setComponentT(t)
+    def setSmXYH(self, x, y, h, t):
+        self.setComponentX(x)
+        self.setComponentY(y)
+        self.setComponentH(h)
+        self.setComponentT(t)
+    def setSmXYZH(self, x, y, z, h, t):
+        self.setComponentX(x)
+        self.setComponentY(y)
+        self.setComponentZ(z)
+        self.setComponentH(h)
+        self.setComponentT(t)
+    def setSmPosHpr(self, x, y, z, h, p, r, t):
+        self.setComponentX(x)
+        self.setComponentY(y)
+        self.setComponentZ(z)
+        self.setComponentH(h)
+        self.setComponentP(p)
+        self.setComponentR(r)
+        self.setComponentT(t)
+        
+    def clearSmoothing(self, bogus = None):
+        pass
+    
+    ### component set pos and hpr functions ###
+
+    ### These are the component functions that are invoked
+    ### remotely by the above composite functions.
+
+    # on the AI, the components are assigned immediately
+    def setComponentX(self, x):
+        self.setX(x)
+    def setComponentY(self, y):
+        self.setY(y)
+    def setComponentZ(self, z):
+        self.setZ(z)
+    def setComponentH(self, h):
+        self.setH(h)
+    def setComponentP(self, p):
+        self.setP(p)
+    def setComponentR(self, r):
+        self.setR(r)
+    def setComponentT(self, t):
+        pass

+ 175 - 0
direct/src/distributed/DistributedSmoothNodeBase.py

@@ -0,0 +1,175 @@
+"""DistributedSmoothNodeBase module: contains the DistributedSmoothNodeBase class"""
+
+from ClockDelta import *
+import Task
+
+class DistributedSmoothNodeBase:
+    """common base class for DistributedSmoothNode and DistributedSmoothNodeAI
+    """
+    def __init__(self):
+        pass
+
+    def delete(self):
+        pass
+
+    ### distributed set pos and hpr functions ###
+
+    ### These functions send the distributed update to set the
+    ### appropriate values on the remote side.  These are
+    ### composite fields, with all the likely combinations
+    ### defined; each function maps (via the dc file) to one or
+    ### more component operations on the remote client.
+
+    def d_setSmStop(self):
+        self.sendUpdate("setSmStop", [globalClockDelta.getFrameNetworkTime()])
+    def d_setSmH(self, h):
+        self.sendUpdate("setSmH", [h, globalClockDelta.getFrameNetworkTime()])
+    def d_setSmXY(self, x, y):
+        self.sendUpdate("setSmXY", [x, y,
+                                    globalClockDelta.getFrameNetworkTime()])
+    def d_setSmXZ(self, x, z):
+        self.sendUpdate("setSmXZ", [x, z,
+                                    globalClockDelta.getFrameNetworkTime()])
+    def d_setSmPos(self, x, y, z):
+        self.sendUpdate("setSmPos", [x, y, z,
+                                     globalClockDelta.getFrameNetworkTime()])
+    def d_setSmHpr(self, h, p, r):
+        self.sendUpdate("setSmHpr", [h, p, r,
+                                     globalClockDelta.getFrameNetworkTime()])
+    def d_setSmXYH(self, x, y, h):
+        self.sendUpdate("setSmXYH", [x, y, h,
+                                     globalClockDelta.getFrameNetworkTime()])
+    def d_setSmXYZH(self, x, y, z, h):
+        self.sendUpdate("setSmXYZH", [x, y, z, h,
+                                      globalClockDelta.getFrameNetworkTime()])
+    def d_setSmPosHpr(self, x, y, z, h, p, r):
+        self.sendUpdate("setSmPosHpr", [x, y, z, h, p, r,
+                                        globalClockDelta.getFrameNetworkTime()])
+
+    def b_clearSmoothing(self):
+        self.d_clearSmoothing()
+        self.clearSmoothing()
+    def d_clearSmoothing(self):
+        self.sendUpdate("clearSmoothing", [0])
+
+    ### posHprBroadcast ###
+
+    def getPosHprBroadcastTaskName(self):
+        # presumably, we have a doId at this point
+        return "sendPosHpr-%s" % self.doId
+
+    def stopPosHprBroadcast(self):
+        taskMgr.remove(self.getPosHprBroadcastTaskName())
+
+    def startPosHprBroadcast(self, period=.2):
+        taskName = self.getPosHprBroadcastTaskName()
+        # Set up telemetry optimization variables
+        xyz = self.getPos()
+        hpr = self.getHpr()
+
+        self.__storeX = xyz[0]
+        self.__storeY = xyz[1]
+        self.__storeZ = xyz[2]
+        self.__storeH = hpr[0]
+        self.__storeP = hpr[1]
+        self.__storeR = hpr[2]
+        self.__storeStop = 0
+        self.__epsilon = 0.01
+        self.__broadcastPeriod = period
+        # Broadcast our initial position
+        self.b_clearSmoothing()
+        self.d_setSmPosHpr(self.__storeX, self.__storeY, self.__storeZ,
+                           self.__storeH, self.__storeP, self.__storeR)
+        # remove any old tasks
+        taskMgr.remove(taskName)
+        # spawn the new task
+        taskMgr.doMethodLater(self.__broadcastPeriod,
+                              self.posHprBroadcast, taskName)
+
+    def posHprBroadcast(self, task):
+        self.d_broadcastPosHpr()
+        taskName = self.taskName("sendPosHpr")
+        taskMgr.doMethodLater(self.__broadcastPeriod,
+                              self.posHprBroadcast, taskName)
+        return Task.done
+
+    def d_broadcastPosHpr(self):
+        # send out the minimal bits to describe our new position
+        xyz = self.getPos()
+        hpr = self.getHpr()
+
+        if abs(self.__storeX - xyz[0]) > self.__epsilon:
+            self.__storeX = xyz[0]
+            newX = 1
+        else:
+            newX = 0
+
+        if abs(self.__storeY - xyz[1]) > self.__epsilon:
+            self.__storeY = xyz[1]
+            newY = 1
+        else:
+            newY = 0
+
+        if abs(self.__storeZ - xyz[2]) > self.__epsilon:
+            self.__storeZ = xyz[2]
+            newZ = 1
+        else:
+            newZ = 0
+
+        if abs(self.__storeH - hpr[0]) > self.__epsilon:
+            self.__storeH = hpr[0]
+            newH = 1
+        else:
+            newH = 0
+
+        if abs(self.__storeP - hpr[1]) > self.__epsilon:
+            self.__storeP = hpr[1]
+            newP = 1
+        else:
+            newP = 0
+
+        if abs(self.__storeR - hpr[2]) > self.__epsilon:
+            self.__storeR = hpr[2]
+            newR = 1
+        else:
+            newR = 0
+
+        # Check for changes:
+        if not(newX or newY or newZ or newH or newP or newR):
+            # No change
+            # Send one and only one "stop" message.
+            if not self.__storeStop:
+                self.__storeStop = 1
+                self.d_setSmStop()
+            # print 'no change'
+        elif (newH) and not(newX or newY or newZ or newP or newR):
+            # Only change in H
+            self.__storeStop = 0
+            self.d_setSmH(self.__storeH)
+            # print ("H change")
+        elif (newX or newY) and not(newZ or newH or newP or newR):
+            # Only change in X, Y
+            self.__storeStop = 0
+            self.d_setSmXY(self.__storeX, self.__storeY)
+            # print ("XY change")
+        elif (newX or newY or newZ) and not(newH or newP or newR):
+            # Only change in X, Y, Z
+            self.__storeStop = 0
+            self.d_setSmPos(self.__storeX, self.__storeY, self.__storeZ)
+            # print ("XYZ change")
+        elif (newX or newY or newH) and not(newZ or newP or newR):
+            # Only change in X, Y, H
+            self.__storeStop = 0
+            self.d_setSmXYH(self.__storeX, self.__storeY, self.__storeH)
+            # print ("XYH change")
+        elif (newX or newY or newZ or newH) and not(newP or newR):
+            # Only change in X, Y, Z, H
+            self.__storeStop = 0
+            self.d_setSmXYZH(self.__storeX, self.__storeY, self.__storeZ, self.__storeH)
+            # print ("XYZH change")
+        else:
+            # Other changes
+            self.__storeStop = 0
+            self.d_setSmPosHpr(self.__storeX, self.__storeY, self.__storeZ,
+                               self.__storeH, self.__storeP, self.__storeR)
+            # print ("XYZHPR change")

+ 1 - 1
direct/src/distributed/ParentMgr.py

@@ -1,9 +1,9 @@
 """ParentMgr module: contains the ParentMgr class"""
 
-from ShowBaseGlobal import *
 import DirectNotifyGlobal
 
 class ParentMgr:
+    # This is now used on the AI as well.
     """ParentMgr holds a table of nodes that avatars may be parented to
     in a distributed manner. All clients within a particular zone maintain
     identical tables of these nodes, and the nodes are referenced by 'tokens'

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

@@ -71,6 +71,10 @@ class ShowBase(DirectObject.DirectObject):
 
         self.wantStats = self.config.GetBool('want-pstats', 0)
 
+        self.clientSleep = self.config.GetFloat('client-sleep', 0.)
+        # magic-word override
+        self.mwClientSleep = 0.
+
         # Fill this in with a function to invoke when the user "exits"
         # the program by closing the main window.
         self.exitFunc = None
@@ -1106,6 +1110,12 @@ class ShowBase(DirectObject.DirectObject):
             # minimized, not just the main window.  But it will do for
             # now until someone complains.
             time.sleep(0.1)
+        else:
+            # magic word overrides config
+            if self.mwClientSleep:
+                time.sleep(self.mwClientSleep)
+            elif self.clientSleep:
+                time.sleep(self.clientSleep)
 
         # Lerp stuff needs this event, and it must be generated in
         # C++, not in Python.