2
0
Dave Schuyler 22 жил өмнө
parent
commit
5a713cbba9

+ 47 - 2
direct/src/showbase/ControlManager.py

@@ -6,6 +6,7 @@ from ShowBaseGlobal import *
 
 
 import Avatar
 import Avatar
 import DirectNotifyGlobal
 import DirectNotifyGlobal
+import GhostWalker
 import GravityWalker
 import GravityWalker
 import NonPhysicsWalker
 import NonPhysicsWalker
 import PhysicsWalker
 import PhysicsWalker
@@ -21,7 +22,10 @@ class ControlManager:
     def __init__(self, avatar):
     def __init__(self, avatar):
         self.avatar = avatar
         self.avatar = avatar
         assert(self.debugPrint("ControlManager()"))
         assert(self.debugPrint("ControlManager()"))
-        self.swimControls=NonPhysicsWalker.NonPhysicsWalker()
+        self.swimControls=GravityWalker.GravityWalker(
+                    gravity = -32.1740 * 2.0)
+        #self.swimControls=NonPhysicsWalker.NonPhysicsWalker()
+        self.ghostControls=GhostWalker.GhostWalker()
         if self.wantAvatarPhysics:
         if self.wantAvatarPhysics:
             self.walkControls=GravityWalker.GravityWalker(
             self.walkControls=GravityWalker.GravityWalker(
                     gravity = -32.1740 * 2.0) # * 2.0 is a hack;
                     gravity = -32.1740 * 2.0) # * 2.0 is a hack;
@@ -57,6 +61,7 @@ class ControlManager:
         inputState.watch("jump", "alt-control", "alt-control-up")
         inputState.watch("jump", "alt-control", "alt-control-up")
         inputState.watch("jump", "shift-control", "shift-control-up")
         inputState.watch("jump", "shift-control", "shift-control-up")
         
         
+        # FYI, ghost mode uses jump for slide.
         inputState.watch("slide", "slide-is-disabled", "slide-is-disabled")
         inputState.watch("slide", "slide-is-disabled", "slide-is-disabled")
         
         
         #inputState.watch("slideLeft", "shift-arrow_left", "shift-arrow_left-up")
         #inputState.watch("slideLeft", "shift-arrow_left", "shift-arrow_left-up")
@@ -71,6 +76,24 @@ class ControlManager:
         #inputState.watch("slideRight", "shift-arrow_right", "shift-arrow_right-up")
         #inputState.watch("slideRight", "shift-arrow_right", "shift-arrow_right-up")
         inputState.watch("slideRight", "slide-is-disabled", "slide-is-disabled")
         inputState.watch("slideRight", "slide-is-disabled", "slide-is-disabled")
 
 
+    def add(self, controls, name="basic"):
+        controls = self.controls.get(name)
+        if controls is not None:
+            print "Replacing controls:", name
+            controls.delete()
+        self.controls[name] = controls
+
+    def use(self, name="basic"):
+        controls = self.controls.get(name)
+        if controls is not None:
+            if controls is not self.currentControls:
+                self.currentControls.disableAvatarControls()
+                self.currentControls.setCollisionsActive(0)
+                self.currentControls = controls
+                self.currentControls.setCollisionsActive(1)
+        else:
+            print "Unkown controls:", name
+
     def useSwimControls(self):
     def useSwimControls(self):
         assert(self.debugPrint("useSwimControls()"))
         assert(self.debugPrint("useSwimControls()"))
         if self.currentControls is not self.swimControls:
         if self.currentControls is not self.swimControls:
@@ -81,6 +104,16 @@ class ControlManager:
             if self.isEnabled:
             if self.isEnabled:
                 self.currentControls.enableAvatarControls()
                 self.currentControls.enableAvatarControls()
 
 
+    def useGhostControls(self):
+        assert(self.debugPrint("useGhostControls()"))
+        if self.currentControls is not self.ghostControls:
+            self.currentControls.disableAvatarControls()
+            self.currentControls.setCollisionsActive(0)
+            self.ghostControls.setCollisionsActive(1)
+            self.currentControls = self.ghostControls
+            if self.isEnabled:
+                self.currentControls.enableAvatarControls()
+
     def useWalkControls(self):
     def useWalkControls(self):
         assert(self.debugPrint("useWalkControls()"))
         assert(self.debugPrint("useWalkControls()"))
         if self.currentControls is not self.walkControls:
         if self.currentControls is not self.walkControls:
@@ -106,6 +139,11 @@ class ControlManager:
             toonJumpForce,
             toonJumpForce,
             toonReverseSpeed,
             toonReverseSpeed,
             toonRotateSpeed)
             toonRotateSpeed)
+        self.ghostControls.setWalkSpeed(
+            toonForwardSpeed,
+            toonJumpForce,
+            toonReverseSpeed,
+            toonRotateSpeed)
         self.walkControls.setWalkSpeed(
         self.walkControls.setWalkSpeed(
             toonForwardSpeed,
             toonForwardSpeed,
             toonJumpForce,
             toonJumpForce,
@@ -116,7 +154,7 @@ class ControlManager:
         return self.currentControls.getSpeeds()
         return self.currentControls.getSpeeds()
     
     
     def initializeCollisions(self, cTrav,
     def initializeCollisions(self, cTrav,
-            wallBitmask, floorBitmask, avatarRadius, floorOffset):
+            wallBitmask, floorBitmask, ghostBitMask, avatarRadius, floorOffset):
         assert(self.debugPrint("initializeCollisions()"))
         assert(self.debugPrint("initializeCollisions()"))
         
         
         self.walkControls.initializeCollisions(cTrav, self.avatar,
         self.walkControls.initializeCollisions(cTrav, self.avatar,
@@ -130,6 +168,12 @@ class ControlManager:
         self.swimControls.setAirborneHeightFunc(self.avatar.getAirborneHeight)
         self.swimControls.setAirborneHeightFunc(self.avatar.getAirborneHeight)
         self.swimControls.disableAvatarControls()
         self.swimControls.disableAvatarControls()
         self.swimControls.setCollisionsActive(0)
         self.swimControls.setCollisionsActive(0)
+        
+        self.ghostControls.initializeCollisions(cTrav, self.avatar,
+                ghostBitMask, floorBitmask, avatarRadius, floorOffset)
+        self.ghostControls.setAirborneHeightFunc(self.avatar.getAirborneHeight)
+        self.ghostControls.disableAvatarControls()
+        self.ghostControls.setCollisionsActive(0)
 
 
         self.walkControls.setCollisionsActive(1)
         self.walkControls.setCollisionsActive(1)
         self.walkControls.enableAvatarControls()
         self.walkControls.enableAvatarControls()
@@ -138,6 +182,7 @@ class ControlManager:
         assert(self.debugPrint("deleteCollisions()"))
         assert(self.debugPrint("deleteCollisions()"))
         self.walkControls.deleteCollisions()
         self.walkControls.deleteCollisions()
         self.swimControls.deleteCollisions()
         self.swimControls.deleteCollisions()
+        self.ghostControls.deleteCollisions()
 
 
     def collisionsOn(self):
     def collisionsOn(self):
         assert(self.debugPrint("collisionsOn()"))
         assert(self.debugPrint("collisionsOn()"))

+ 2 - 50
direct/src/showbase/GhostWalker.py

@@ -23,53 +23,5 @@ class GhostWalker(NonPhysicsWalker.NonPhysicsWalker):
 
 
     notify = DirectNotifyGlobal.directNotify.newCategory("GhostWalker")
     notify = DirectNotifyGlobal.directNotify.newCategory("GhostWalker")
 
 
-    def handleAvatarControls(self, task):
-        """
-        Check on the arrow keys and update the avatar.
-        """
-        # get the button states:
-        forward = inputState.isSet("forward")
-        reverse = inputState.isSet("reverse")
-        turnLeft = inputState.isSet("turnLeft")
-        turnRight = inputState.isSet("turnRight")
-        # Ghosts slide instead of jump:
-        slide = inputState.isSet("jump")
-        # Determine what the speeds are based on the buttons:
-        self.speed=(forward and self.avatarControlForwardSpeed or 
-                    reverse and -self.avatarControlReverseSpeed)
-        # Should fSlide be renamed slideButton?
-        self.slideSpeed=slide and (
-                (turnLeft and -self.avatarControlForwardSpeed) or 
-                (turnRight and self.avatarControlForwardSpeed))
-        self.rotationSpeed=not slide and (
-                (turnLeft and self.avatarControlRotateSpeed) or
-                (turnRight and -self.avatarControlRotateSpeed))
-            
-        # How far did we move based on the amount of time elapsed?
-        dt=min(ClockObject.getGlobalClock().getDt(), 0.1)
-        # Check to see if we're moving at all:
-        if self.speed or self.slideSpeed or self.rotationSpeed:
-            if self.stopThisFrame:
-                distance = 0.0
-                slideDistance = 0.0
-                rotation = 0.0
-                self.stopThisFrame = 0
-            else:
-                distance = dt * self.speed
-                slideDistance = dt * self.slideSpeed
-                rotation = dt * self.rotationSpeed
-
-            # Take a step in the direction of our previous heading.
-            self.vel=Vec3(Vec3.forward() * distance + 
-                          Vec3.right() * slideDistance)
-            if self.vel != Vec3.zero():
-                # rotMat is the rotation matrix corresponding to
-                # our previous heading.
-                rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
-                step=rotMat.xform(self.vel)
-                self.avatarNodePath.setFluidPos(Point3(self.avatarNodePath.getPos()+step))
-            self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
-            messenger.send("avatarMoving")
-        else:
-            self.vel.set(0.0, 0.0, 0.0)
-        return Task.cont
+    # Ghosts slide instead of jump:
+    slideName = "jump"

+ 54 - 17
direct/src/showbase/GravityWalker.py

@@ -39,6 +39,11 @@ class GravityWalker(DirectObject.DirectObject):
         
         
         self.mayJump = 1
         self.mayJump = 1
         self.jumpDelayTask = None
         self.jumpDelayTask = None
+
+        self.controlsTask = None
+        self.fixCliffTask = None
+        self.indicatorTask = None
+
         self.falling = 0
         self.falling = 0
         self.needToDeltaPos = 0
         self.needToDeltaPos = 0
         self.physVelocityIndicator=None
         self.physVelocityIndicator=None
@@ -149,7 +154,7 @@ class GravityWalker(DirectObject.DirectObject):
         """
         """
         # This is a sphere on the ground to detect barrier collisions
         # This is a sphere on the ground to detect barrier collisions
         self.avatarRadius = avatarRadius
         self.avatarRadius = avatarRadius
-        self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius, avatarRadius)
+        self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius+0.5, avatarRadius)
         cSphereNode = CollisionNode('GW.cWallSphereNode')
         cSphereNode = CollisionNode('GW.cWallSphereNode')
         cSphereNode.addSolid(self.cSphere)
         cSphereNode.addSolid(self.cSphere)
         cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
         cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
@@ -159,8 +164,8 @@ class GravityWalker(DirectObject.DirectObject):
 
 
         # set up collision mechanism
         # set up collision mechanism
         handler = CollisionHandlerPusher()
         handler = CollisionHandlerPusher()
-        handler.setInPattern("enter%in")
-        handler.setOutPattern("exit%in")
+        handler.setInPattern("pusher_enter%in")
+        handler.setOutPattern("pusher_exit%in")
 
 
         handler.addCollider(cSphereNodePath, self.avatarNodePath)
         handler.addCollider(cSphereNodePath, self.avatarNodePath)
         self.pusher = handler
         self.pusher = handler
@@ -172,7 +177,7 @@ class GravityWalker(DirectObject.DirectObject):
         """
         """
         # This is a sphere on the ground to detect barrier collisions
         # This is a sphere on the ground to detect barrier collisions
         self.avatarRadius = avatarRadius
         self.avatarRadius = avatarRadius
-        self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius-0.1, avatarRadius)
+        self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius-0.1, avatarRadius*1.04)
         cSphereNode = CollisionNode('GW.cFloorSphereNode')
         cSphereNode = CollisionNode('GW.cFloorSphereNode')
         cSphereNode.addSolid(self.cSphere)
         cSphereNode.addSolid(self.cSphere)
         cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
         cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
@@ -204,7 +209,7 @@ class GravityWalker(DirectObject.DirectObject):
 
 
         self.setupRay(floorBitmask, self.floorOffset)
         self.setupRay(floorBitmask, self.floorOffset)
         self.setupWallSphere(wallBitmask, avatarRadius)
         self.setupWallSphere(wallBitmask, avatarRadius)
-        self.setupFloorSphere(floorBitmask, avatarRadius)
+        self.setupFloorSphere(wallBitmask|floorBitmask, avatarRadius)
 
 
         self.setCollisionsActive(1)
         self.setCollisionsActive(1)
 
 
@@ -236,6 +241,9 @@ class GravityWalker(DirectObject.DirectObject):
         assert(self.debugPrint("collisionsActive(active=%s)"%(active,)))
         assert(self.debugPrint("collisionsActive(active=%s)"%(active,)))
         if self.collisionsActive != active:
         if self.collisionsActive != active:
             self.collisionsActive = active
             self.collisionsActive = active
+            # Each time we change the collision geometry, make one 
+            # more pass to ensure we aren't standing in a wall.
+            self.oneTimeCollide()
             if active:
             if active:
                 self.cTrav.addCollider(self.cWallSphereNodePath, self.pusher)
                 self.cTrav.addCollider(self.cWallSphereNodePath, self.pusher)
                 self.cTrav.addCollider(self.cFloorSphereNodePath, self.event)
                 self.cTrav.addCollider(self.cFloorSphereNodePath, self.event)
@@ -244,15 +252,25 @@ class GravityWalker(DirectObject.DirectObject):
                 self.cTrav.removeCollider(self.cWallSphereNodePath)
                 self.cTrav.removeCollider(self.cWallSphereNodePath)
                 self.cTrav.removeCollider(self.cFloorSphereNodePath)
                 self.cTrav.removeCollider(self.cFloorSphereNodePath)
                 self.cTrav.removeCollider(self.cRayNodePath)
                 self.cTrav.removeCollider(self.cRayNodePath)
-                # Now that we have disabled collisions, make one more pass
-                # right now to ensure we aren't standing in a wall.
-                self.oneTimeCollide()
 
 
     def getCollisionsActive(self):
     def getCollisionsActive(self):
         assert(self.debugPrint("getCollisionsActive() returning=%s"%(
         assert(self.debugPrint("getCollisionsActive() returning=%s"%(
             self.collisionsActive,)))
             self.collisionsActive,)))
         return self.collisionsActive
         return self.collisionsActive
 
 
+    def FixCliff(self, task):
+        """
+        People are still making polygons that are marked
+        as floor, but are nearly vertical.  This ray is
+        a hack to help deal with the cliff.
+        """
+        if self.lifter.isInOuterSpace():
+            temp = self.cRayNodePath.getZ()
+            self.cRayNodePath.setZ(14.0)
+            self.oneTimeCollide()
+            self.cRayNodePath.setZ(temp)
+        return Task.cont
+
     def oneTimeCollide(self):
     def oneTimeCollide(self):
         """
         """
         Makes one quick collision pass for the avatar, for instance as
         Makes one quick collision pass for the avatar, for instance as
@@ -294,7 +312,7 @@ class GravityWalker(DirectObject.DirectObject):
         reverse = inputState.isSet("reverse")
         reverse = inputState.isSet("reverse")
         turnLeft = inputState.isSet("turnLeft")
         turnLeft = inputState.isSet("turnLeft")
         turnRight = inputState.isSet("turnRight")
         turnRight = inputState.isSet("turnRight")
-        slide = inputState.isSet("slide")
+        slide = 0 #hack -- was: inputState.isSet("slide")
         jump = inputState.isSet("jump")
         jump = inputState.isSet("jump")
         pie = inputState.isSet("pie")
         pie = inputState.isSet("pie")
         # Determine what the speeds are based on the buttons:
         # Determine what the speeds are based on the buttons:
@@ -328,6 +346,8 @@ class GravityWalker(DirectObject.DirectObject):
             onScreenDebug.add("velocity", self.lifter.getVelocity()) #*#
             onScreenDebug.add("velocity", self.lifter.getVelocity()) #*#
             onScreenDebug.add("isAirborne", self.isAirborne) #*#
             onScreenDebug.add("isAirborne", self.isAirborne) #*#
             onScreenDebug.add("jump", jump) #*#
             onScreenDebug.add("jump", jump) #*#
+
+            onScreenDebug.add("inOuterSpace", self.lifter.isInOuterSpace()) #*#
         if self.lifter.isOnGround():
         if self.lifter.isOnGround():
             if self.isAirborne:
             if self.isAirborne:
                 self.isAirborne = 0
                 self.isAirborne = 0
@@ -408,13 +428,26 @@ class GravityWalker(DirectObject.DirectObject):
         if __debug__:
         if __debug__:
             self.accept("control-f3", self.spawnTest) #*#
             self.accept("control-f3", self.spawnTest) #*#
 
 
+        # remove any old
+        if self.controlsTask:
+            self.controlsTask.remove()
+        # spawn the new task
         taskName = "AvatarControls%s"%(id(self),)
         taskName = "AvatarControls%s"%(id(self),)
+        self.controlsTask = taskMgr.add(self.handleAvatarControls, taskName, 25)
+
         # remove any old
         # remove any old
-        taskMgr.remove(taskName)
+        if self.fixCliffTask:
+            self.fixCliffTask.remove()
         # spawn the new task
         # spawn the new task
-        taskMgr.add(self.handleAvatarControls, taskName, 25)
+        taskName = "AvatarControls-FixCliff%s"%(id(self),)
+        self.fixCliffTask = taskMgr.add(self.FixCliff, taskName, 31)
+
         if self.physVelocityIndicator:
         if self.physVelocityIndicator:
-            taskMgr.add(self.avatarPhysicsIndicator, "AvatarControlsIndicator%s"%(id(self),), 35)
+            if self.indicatorTask:
+                self.indicatorTask.remove()
+            self.indicatorTask = taskMgr.add(
+                self.avatarPhysicsIndicator,
+                "AvatarControlsIndicator%s"%(id(self),), 35)
 
 
     def disableAvatarControls(self):
     def disableAvatarControls(self):
         """
         """
@@ -422,11 +455,15 @@ class GravityWalker(DirectObject.DirectObject):
         """
         """
         assert(self.debugPrint("disableAvatarControls()"))
         assert(self.debugPrint("disableAvatarControls()"))
         print id(self), "GW.disableAvatarControls()"
         print id(self), "GW.disableAvatarControls()"
-        taskName = "AvatarControls%s"%(id(self),)
-        taskMgr.remove(taskName)
-
-        taskName = "AvatarControlsIndicator%s"%(id(self),)
-        taskMgr.remove(taskName)
+        if self.controlsTask:
+            self.controlsTask.remove()
+            self.controlsTask = None
+        if self.fixCliffTask:
+            self.fixCliffTask.remove()
+            self.fixCliffTask = None
+        if self.indicatorTask:
+            self.indicatorTask.remove()
+            self.indicatorTask = None
 
 
         if __debug__:
         if __debug__:
             self.ignore("control-f3") #*#
             self.ignore("control-f3") #*#

+ 4 - 1
direct/src/showbase/NonPhysicsWalker.py

@@ -23,6 +23,9 @@ class NonPhysicsWalker(DirectObject.DirectObject):
 
 
     notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")
     notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")
 
 
+    # Ghost mode overrides this:
+    slideName = "slide-is-disabled"
+
     # special methods
     # special methods
     def __init__(self):
     def __init__(self):
         DirectObject.DirectObject.__init__(self)
         DirectObject.DirectObject.__init__(self)
@@ -151,7 +154,7 @@ class NonPhysicsWalker(DirectObject.DirectObject):
         reverse = inputState.isSet("reverse")
         reverse = inputState.isSet("reverse")
         turnLeft = inputState.isSet("turnLeft")
         turnLeft = inputState.isSet("turnLeft")
         turnRight = inputState.isSet("turnRight")
         turnRight = inputState.isSet("turnRight")
-        slide = inputState.isSet("slide")
+        slide = inputState.isSet(self.slideName)
         #jump = inputState.isSet("jump")
         #jump = inputState.isSet("jump")
         # Determine what the speeds are based on the buttons:
         # Determine what the speeds are based on the buttons:
         self.speed=(forward and self.avatarControlForwardSpeed or 
         self.speed=(forward and self.avatarControlForwardSpeed or