Ejemplo n.º 1
0
class WeaponGfxNetwork(WeaponGfx):
    def __init__(self, mediator, car, cars):
        WeaponGfx.__init__(self, mediator, car, cars)
        self.ipos = None
        self.ifwd = None

    def update_props(self, pos, fwd):
        if pos == (0, 0, 0) and fwd == (0, 0, 0): return
        wpn_np = self.gfx_np.node
        old_pos = wpn_np.get_pos(render)
        self.gfx_np.node.reparent_to(render)
        wpn_np.set_pos(old_pos)
        self.ipos = LerpPosInterval(wpn_np, self.eng.client.rate, pos)
        self.ipos.start()
        fwd_start = render.get_relative_vector(wpn_np, Vec3(0, 1, 0))
        if self.ifwd: self.ifwd.finish()
        self.ifwd = LerpFunc(self._rotate_wpn,
                             fromData=0,
                             toData=1,
                             duration=self.eng.client.rate,
                             extraArgs=[wpn_np, fwd_start, fwd])
        self.ifwd.start()

    def update_fired_props(self, pos, fwd):
        if pos == (0, 0, 0) and fwd == (0, 0, 0): return
        wpn_np = self.gfx_np.node
        old_pos = wpn_np.get_pos(render)
        self.gfx_np.node.reparent_to(render)
        wpn_np.set_pos(old_pos)
        self.ipos = LerpPosInterval(wpn_np, self.eng.client.rate, pos)
        self.ipos.start()
        fwd_start = render.get_relative_vector(wpn_np, Vec3(0, 1, 0))
        if self.ifwd: self.ifwd.finish()
        self.ifwd = LerpFunc(self._rotate_wpn,
                             fromData=0,
                             toData=1,
                             duration=self.eng.client.rate,
                             extraArgs=[wpn_np, fwd_start, fwd])
        self.ifwd.start()

    @staticmethod
    def _rotate_wpn(t, node, start_vec, end_vec):
        interp_vec = Vec3(
            float(start_vec[0]) * (1 - t) + float(end_vec[0]) * t,
            float(start_vec[1]) * (1 - t) + float(end_vec[1]) * t,
            float(start_vec[2]) * (1 - t) + float(end_vec[2]) * t)
        node.look_at(node.get_pos() + interp_vec)

    def destroy(self):
        if self.ipos: self.ipos.finish()
        if self.ifwd: self.ifwd.finish()
        self.ipos = self.ifwd = None
        WeaponGfx.destroy(self)
class FPS(object, DirectObject):
    def __init__(self):
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        winprops = WindowProperties()
        winprops.setCursorHidden(True)
        base.win.requestProperties(winprops)
        self.model = loader.loadModel('models/Guns/45.x')
        self.model.reparentTo(base.camera)
        self.model.setPos(USP45_POS)
        self.model.setHpr(USP45_HPR)
        self.model.setScale(PISTOL_SCALE)
        self.gun = 1

        self.initSound()
        self.initCollision()
        self.loadLevel()
        self.initPlayer()
        self.setupMouseCollision()
        self.loadCrosshairs()
        self.loadRalph()

    def initSound(self):
        self.deathSnd = base.loader.loadSfx("models/sounds/and.ogg")
        self.spawnSnd = base.loader.loadSfx("models/sounds/faster.ogg")
        self.fireSnd = base.loader.loadSfx("models/sounds/rifle.ogg")

    def loadCrosshairs(self):
        self.crosshairs = OnscreenImage(image='models/crosshair.png',
                                        pos=base.win.getPointer(0))
        self.crosshairs.setTransparency(TransparencyAttrib.MAlpha)
        self.crosshairs.setScale(.04, .04, .04)

    def initCollision(self):
        #initialize traverser
        base.cTrav = CollisionTraverser()
        base.cTrav.setRespectPrevTransform(True)
        base.cTrav.showCollisions(render)
        self.mPicker = CollisionTraverser()
        self.mPicker.showCollisions(render)
        self.mCQue = CollisionHandlerQueue()
        #         base.cTrav.showCollisions(render)
        #initialize pusher
        self.pusher = CollisionHandlerPusher()
        # collision bits
        self.groundCollBit = BitMask32.bit(0)
        self.collBitOff = BitMask32.allOff()
        self.zombieColBitFrom = BitMask32.bit(2)
        self.zombieColBitInto = BitMask32.bit(2)
        self.zombieColBitOff = BitMask32.allOff()

    def loadLevel(self):

        self.level = loader.loadModel('models/world')
        self.level.reparentTo(render)
        self.level.setPos(0, 0, 0)
        self.level.setColor(1, 1, 1, .5)
        self.level.setCollideMask(self.groundCollBit)

        self.box = loader.loadModel("models/box")
        self.box.reparentTo(render)
        self.box.setPos(-29.83, 0, 0)
        self.box.setScale(1)
        self.box.setCollideMask(self.groundCollBit)
        self.box1 = loader.loadModel("models/box")
        self.box1.reparentTo(render)
        self.box1.setPos(-51.14, -17.90, 0)
        self.box1.setScale(1)
        self.box1.setCollideMask(self.groundCollBit)

    def loadRalph(self):
        ralphStartPos = Vec3(-98.64, -20.60, 0)
        self.ralph = Actor("models/ralph", {
            "run": "models/ralph-run",
            "walk": "models/ralph-walk"
        })
        self.ralph.reparentTo(render)
        self.ralph.setPos(ralphStartPos)
        self.ralph.setScale(.3)
        self.ralphLife = 10
        ralphaiStartPos = Vec3(-50, 20, 0)
        self.ralphai = Actor("models/ralph", {
            "run": "models/ralph-run",
            "walk": "models/ralph-walk"
        })
        self.cTrav = CollisionTraverser()

        self.ralphGroundRay = CollisionRay()
        self.ralphGroundRay.setOrigin(0, 0, 1000)
        self.ralphGroundRay.setDirection(0, 0, -1)
        self.ralphGroundCol = CollisionNode('ralphRay')
        self.ralphGroundCol.addSolid(self.ralphGroundRay)
        self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0))
        self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff())
        self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol)
        self.ralphGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler)

        self.ralphHeadSphere = CollisionSphere(0, -.2, 4.5, .7)
        self.ralphHeadCol = CollisionNode('ralphHeadColSphere')
        self.ralphHeadCol.addSolid(self.ralphHeadSphere)
        self.ralphHeadCol.setFromCollideMask(self.zombieColBitFrom)
        self.ralphHeadCol.setIntoCollideMask(self.zombieColBitInto)
        self.ralphHeadColNp = self.ralph.attachNewNode(self.ralphHeadCol)
        self.mPicker.addCollider(self.ralphHeadColNp, self.mCQue)

        self.ralphBodySphere = CollisionSphere(0, -.2, 2, 1)
        self.ralphBodyCol = CollisionNode('ralphBodyColSphere')
        self.ralphBodyCol.addSolid(self.ralphBodySphere)
        self.ralphBodyCol.setFromCollideMask(self.zombieColBitFrom)
        self.ralphBodyCol.setIntoCollideMask(self.zombieColBitInto)
        self.ralphBodyColNp = self.ralph.attachNewNode(self.ralphBodyCol)
        self.mPicker.addCollider(self.ralphBodyColNp, self.mCQue)
        self.ralphHeadColNp.show()
        self.ralphBodyColNp.show()

        base.taskMgr.doMethodLater(.7, self.spawnSound, "spawnSound")
        self.isMoving = False
        self.setAI()

    def spawnSound(self, task):
        self.spawnSnd.play()
        return task.done

    def Scar(self):
        self.model.removeNode()
        self.model = loader.loadModel('models/Guns/SCAR.x')
        self.model.reparentTo(base.camera)
        self.model.setPos(SCAR_POS)
        self.model.setHpr(SCAR_HPR)
        self.model.setScale(RIFLE_SCALE)
        self.gun = 4

    def M4(self):
        self.model.removeNode()
        self.model = loader.loadModel('models/Guns/M4.x')
        self.model.reparentTo(base.camera)
        self.model.setPos(M4_POS)
        self.model.setHpr(M4_HPR)
        self.model.setScale(RIFLE_SCALE)
        self.gun = 3

    def Shotgun(self):
        self.model.removeNode()
        self.model = loader.loadModel('models/Guns/Shotgun.x')
        self.model.reparentTo(base.camera)
        self.model.setPos(SHOTGUN_POS)
        self.model.setHpr(SHOTGUN_HPR)
        self.model.setScale(RIFLE_SCALE)
        self.gun = 2

    def Pistol(self):
        self.model.removeNode()
        self.model = loader.loadModel('models/Guns/45.x')
        self.model.reparentTo(base.camera)
        self.model.setPos(USP45_POS)
        self.model.setHpr(USP45_HPR)
        self.model.setScale(PISTOL_SCALE)
        self.gun = 1

    def setupMouseCollision(self):

        self.mRay = CollisionRay()
        self.mRayNode = CollisionNode('pickRay')
        self.mRayNode.addSolid(self.mRay)
        self.mRayNode.setFromCollideMask(self.zombieColBitFrom)
        self.mRayNode.setIntoCollideMask(self.zombieColBitOff)
        self.mPickNp = base.camera.attachNewNode(self.mRayNode)
        self.mPicker.addCollider(self.mPickNp, self.mCQue)

        self.mPickNp.show()

    def initPlayer(self):
        #load man
        self.man = render.attachNewNode(
            'man')  # keep this node scaled to identity
        self.man.setPos(0, 0, 10)

        # camera
        base.camera.reparentTo(self.man)
        base.camera.setPos(0, 0, 1.7)
        base.camLens.setNearFar(.1, 1000)
        base.disableMouse()
        #create a collsion solid around the man
        manC = self.man.attachCollisionSphere('manSphere', 0, 0, 1, .4,
                                              self.groundCollBit,
                                              self.collBitOff)
        self.pusher.addCollider(manC, self.man)
        base.cTrav.addCollider(manC, self.pusher)

        speed = 4
        Forward = Vec3(0, speed * 2, 0)
        Back = Vec3(0, -speed, 0)
        Left = Vec3(-speed, 0, 0)
        Right = Vec3(speed, 0, 0)
        Stop = Vec3(0)
        self.walk = Stop
        self.strife = Stop
        self.jump = 0
        taskMgr.add(self.move, 'move-task')
        self.jumping = LerpFunc(Functor(self.__setattr__, "jump"),
                                duration=.5,
                                fromData=.4,
                                toData=0)

        self.accept("escape", sys.exit)
        self.accept("space", self.startJump)
        self.accept("s", self.__setattr__, ["walk", Back])
        self.accept("w", self.__setattr__, ["walk", Forward])
        self.accept("s-up", self.__setattr__, ["walk", Stop])
        self.accept("w-up", self.__setattr__, ["walk", Stop])
        self.accept("a", self.__setattr__, ["strife", Left])
        self.accept("d", self.__setattr__, ["strife", Right])
        self.accept("a-up", self.__setattr__, ["strife", Stop])
        self.accept("d-up", self.__setattr__, ["strife", Stop])
        self.accept("wheel_up", self.nextWeapon)
        self.accept("wheel_down", self.prevWeapon)
        self.accept("1", self.Pistol)
        self.accept("2", self.Shotgun)
        self.accept("3", self.M4)
        self.accept("4", self.Scar)
        self.accept('mouse1', self.onMouseTask)
        #add mouse collision to our world
        self.setupMouseCollision()
        self.manGroundColNp = self.man.attachCollisionRay(
            'manRay', 0, 0, .6, 0, 0, -1, self.groundCollBit, self.collBitOff)
        self.manGroundHandler = CollisionHandlerGravity()
        self.manGroundHandler.addCollider(self.manGroundColNp, self.man)
        base.cTrav.addCollider(self.manGroundColNp, self.manGroundHandler)

    def nextWeapon(self):
        if self.gun == 1:
            self.Shotgun()
        elif self.gun == 2:
            self.M4()
        elif self.gun == 3:
            self.Scar()
        elif self.gun == 4:
            self.Pistol()

    def prevWeapon(self):
        if self.gun == 1:
            self.Scar()
        elif self.gun == 2:
            self.Pistol()
        elif self.gun == 3:
            self.Shotgun()
        elif self.gun == 4:
            self.M4()

    def startJump(self):
        if self.manGroundHandler.isOnGround():
            self.jumping.start()

    def move(self, task):
        dt = globalClock.getDt()
        # mouse
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if base.win.movePointer(0, self.winXhalf, self.winYhalf):
            self.man.setH(self.man, (x - self.winXhalf) * -0.1)
            base.camera.setP(
                clampScalar(-90, 90,
                            base.camera.getP() - (y - self.winYhalf) * 0.1))
        # move where the keys set it
        moveVec = (self.walk + self.strife) * dt  # horisontal
        moveVec.setZ(self.jump)  # vertical
        self.man.setFluidPos(self.man, moveVec)
        # jump damping
        if self.jump > 0:
            self.jump = clampScalar(0, 1, self.jump * .9)

        return task.cont

    def onMouseTask(self):

        mpos = base.mouseWatcherNode.getMouse()
        self.mRay.setDirection(render.getRelativeVector(camera, Vec3(0, 1, 0)))
        self.mRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
        self.mPicker.traverse(render)
        self.fireSnd.play()
        entries = []
        for i in range(self.mCQue.getNumEntries()):
            entry = self.mCQue.getEntry(i)
            print entry
            entries.append(entry)
        if (len(entries) > 0) and (entries[0].getIntoNode().getName()
                                   == 'terrain'):
            print 'terrain'

        entries = []
        for i in range(self.mCQue.getNumEntries()):
            entry = self.mCQue.getEntry(i)
            print entry
            entries.append(entry)
        if (len(entries) > 0) and (entries[0].getIntoNode().getName()
                                   == 'ralphHeadColSphere'):
            self.ralphLife -= 10
            base.taskMgr.doMethodLater(.3, self.deathSound, "deathSound")

        entries = []
        for i in range(self.mCQue.getNumEntries()):
            entry = self.mCQue.getEntry(i)
            print entry
            entries.append(entry)
        if (len(entries) > 0) and (entries[0].getIntoNode().getName()
                                   == 'ralphBodyColSphere'):
            self.ralphLife -= 5
            if self.ralphLife < 5:
                base.taskMgr.doMethodLater(.3, self.deathSound, "deathSound")

        if self.ralphLife <= 0:
            self.ralph.cleanup()
            self.ralphai.cleanup()
            self.loadRalph()

    def deathSound(self, task):
        self.deathSnd.play()
        return task.done

    def setAI(self):
        #Creating AI World
        self.AIworld = AIWorld(render)
        self.AIchar = AICharacter("ralph", self.ralph, 130, 0.05, 25)
        self.AIworld.addAiChar(self.AIchar)
        self.AIbehaviors = self.AIchar.getAiBehaviors()

        self.AIbehaviors.initPathFind("models/navmesh.csv")
        self.setMove()
        #AI World update
        taskMgr.add(self.AIUpdate, "AIUpdate")

    def setMove(self):
        self.AIbehaviors.addStaticObstacle(self.box)
        self.AIbehaviors.addStaticObstacle(self.box1)
        self.AIbehaviors.pathFindTo(self.man)
        self.ralph.loop("run")

    #to update the AIWorld
    def AIUpdate(self, task):
        self.AIworld.update()
        self.ralphMove()

        return Task.cont

    def ralphMove(self):

        startpos = self.ralph.getPos()

        # Now check for collisions.

        self.cTrav.traverse(render)

        entries = []
        for i in range(self.ralphGroundHandler.getNumEntries()):
            entry = self.ralphGroundHandler.getEntry(i)
            entries.append(entry)
        entries.sort(lambda x, y: cmp(
            y.getSurfacePoint(render).getZ(),
            x.getSurfacePoint(render).getZ()))
        if (len(entries) > 0) and (entries[0].getIntoNode().getName()
                                   == "terrain"):
            self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.ralph.setPos(startpos)

        self.ralph.setP(0)
        return Task.cont
Ejemplo n.º 3
0
class ArcBall(NodePath, DirectObject):
    def __init__(self,
                 name,
                 radius=1,
                 scrollFactor=1,
                 camera=base.cam,
                 frame=Vec4(-1, 1, -1, 1),
                 keepUpright=0,
                 mouseDownEvent='mouse1',
                 mouseUpEvent='mouse1-up',
                 *args,
                 **kwargs):
        NodePath.__init__(self, name, *args, **kwargs)
        DirectObject.__init__(self)
        self._rNode = self.attachNewNode('rotateNode')
        self._setRadius(radius, False)
        self._setScrollFactor(scrollFactor, False)
        self._setCamera(camera, False)
        self._setFrame(frame, False)
        self._setKeepUpright(keepUpright)
        self._setMouseEvents(mouseDownEvent, mouseUpEvent)
        self.setRotateMode(0)
        self._setControlButtonState(0)
        self._setTiltLimit(25 * math.pi / 180, False)
        self.saveNorth()
        self._colBitMask = BitMask32(1 << 16)
        self._colNode = self.attachNewNode(CollisionNode(name + '-cNode'))
        self._colNode.node().addSolid(CollisionSphere(0, 0, 0, 1))
        self._colNode.node().setIntoCollideMask(self._colBitMask)
        self._mouseEnabled = True
        self._initCollisions()
        self.geom_node_path = self.attachNewNode('arrow')
        self.geom_node_path.setBin('fixed', 100)
        self.geom_node_path.setDepthTest(0)
        self.geom_node_path.setTransparency(1)
        self.head_geom_node = GeomNode('head')
        self.head_geom_node_path = self.geom_node_path.attachNewNode(
            self.head_geom_node)
        self.tail_geom_node = GeomNode('tail')
        self.tail_geom_node_path = self.geom_node_path.attachNewNode(
            self.tail_geom_node)
        self._ballIval = None

    def removeNode(self):
        self.ignoreAll()
        NodePath.removeNode(self)

    def _setRadius(self, radius, reset=True):
        self._radius = radius

    def _setScrollFactor(self, scrollFactor, reset=True):
        self._scrollFactor = float(scrollFactor)

    def _setCamera(self, cam, reset=True):
        self.cam = cam
        self.camNode = cam.node()
        self.camLens = self.camNode.getLens()

    def _setFrame(self, frame, reset=True):
        self._frame = frame
        self.saveTransforms()

    def _setKeepUpright(self, keepUpright):
        self._keepUpright = keepUpright

    def _setControlButtonState(self, state):
        self._ctrlBtnState = state

    def _setTiltLimit(self, limit=math.pi / 6, reset=True):
        self._tiltLimit = limit
        if reset:
            self._applyConstraints()

    def _setMouseEvents(self, down, up):
        if hasattr(self, '_mouseDownEventStr'):
            self.ignore(self._mouseDownEventStr)

        if hasattr(self, '_mouseUpEventStr'):
            self.ignore(self._mouseUpEventStr)

        self._mouseDownEventStr = down
        self._mouseUpEventStr = up
        self.accept(self._mouseDownEventStr, self._mouseDown)
        self.accept(self._mouseUpEventStr, self._mouseUp)

    def setRadius(self, radius):
        self._setRadius(radius)

    def setScrollFactor(self, scrollFactor):
        self._setScrollFactor(scrollFactor)

    def setCamera(self, camera):
        self._setCamera(camera)

    def setFrame(self, frame):
        self._setFrame(frame)

    def setKeepUpright(self, keepUpright):
        self._setKeepUpright(keepUpright)

    def setMouseEvents(self, downEvent, upEvent):
        self._setMouseEvents(downEvent, upEvent)

    def setMouseEnabled(self, enabled):
        self._mouseEnabled = enabled
        if not self._mouseEnabled:
            self._mouseUp()

    def setRotateMode(self, mode):
        self.rMode = mode

    def enable(self):
        self.setMouseEnabled(True)

    def disable(self):
        if self._ballIval:
            self._ballIval.pause()
            self._ballIval = None

        self.setMouseEnabled(False)

    def getRotateRoot(self):
        return self._rNode

    def attachForRotation(self, nodepath):
        nodepath.reparentTo(self._rNode)

    def getInternalHpr(self, *args, **kwargs):
        return self._rNode.getHpr(*args, **kwargs)

    def setInternalHpr(self, *args, **kwargs):
        self._rNode.setHpr(*args, **kwargs)

    def getInternalQuat(self, *args, **kwargs):
        return self._rNode.getQuat(*args, **kwargs)

    def setInternalQuat(self, *args, **kwargs):
        self._rNode.setQuat(*args, **kwargs)

    def _mouseDown(self, *args):
        if self._mouseEnabled:
            self._startRotateTask()

    def _mouseUp(self, *args):
        self._stopRotateTask()

    def _initCollisions(self):
        self.traverser = CollisionTraverser()
        self.colHandlerQueue = CollisionHandlerQueue()
        self.camRayNode = self.cam.attachNewNode(CollisionNode('camRayNode'))
        self.camRay = CollisionRay()
        self.camRayNode.node().addSolid(self.camRay)
        self.traverser.addCollider(self.camRayNode, self.colHandlerQueue)

    def _mouseRayCollide(self, rayBitMask=BitMask32.allOn()):
        if base.mouseWatcherNode.hasMouse():
            mousePt = base.mouseWatcherNode.getMouse()
            mousePt = self._transMouseToHomogenousFramePt(mousePt)
            self.camRay.setFromLens(self.camNode, mousePt[0], mousePt[1])
            self.camRayNode.node().setFromCollideMask(rayBitMask)
            self.traverser.traverse(self)
            self.traverser.traverse(self.getTop())
        else:
            self.colHandlerQueue.clearEntries()

    def _camRayCollide(self, rayBitMask=BitMask32.allOn()):
        self.camRay.setOrigin(Point3(0))
        self.camRay.setDirection(Vec3(0, 1, 0))
        self.camRayNode.node().setFromCollideMask(rayBitMask)
        self.traverser.traverse(self)
        self.traverser.traverse(self.getTop())

    def getHorizonCollisionPt(self, raySpace=None, rayDirection=None):
        raySpaceToSelf = raySpace.getTransform(self)
        rayOrig = raySpaceToSelf.getMat().xformPoint(Point3(0))
        rayDist = rayOrig.length()
        ray = raySpaceToSelf.getMat().xformPoint(rayDirection)
        a = rayOrig * self._radius * self._radius / rayDist * rayDist
        b = -rayOrig.cross(ray).cross(-rayOrig)
        b.normalize()
        b *= math.sqrt(1 - 1 / rayDist / rayDist)
        return a + b

    def _getCollisionPt(self):
        entryCount = self.colHandlerQueue.getNumEntries()
        for x in range(entryCount):
            entry = self.colHandlerQueue.getEntry(x)
            if entry.getIntoNode().getName() == self.getName() + '-cNode':
                return entry.getSurfacePoint(entry.getIntoNodePath())
                continue

        camRay = self.camRayNode.node().getSolid(0).getDirection()
        pt = self.getHorizonCollisionPt(self.cam, camRay)
        return pt

    def getMouseRayCollisionPt(self, rayBitMask=None):
        if not rayBitMask:
            rayBitMask = self._colBitMask

        self._mouseRayCollide(rayBitMask)
        return self._getCollisionPt()

    def getCamRayCollisionPt(self, rayBitMask=None):
        if not rayBitMask:
            rayBitMask = self._colBitMask

        self._camRayCollide(rayBitMask)
        return self._getCollisionPt()

    def _getCollisionEntry(self):
        entryCount = self.colHandlerQueue.getNumEntries()
        if entryCount:
            self.colHandlerQueue.sort()
            return self.colHandlerQueue.getEntry(0)
        else:
            return None

    def getMouseRayCollisionEntry(self, rayBitMask=None):
        if not rayBitMask:
            rayBitMask = self._colBitMask

        self._mouseRayCollide(rayBitMask)
        return self._getCollisionEntry()

    def saveTransforms(self):
        frame = self._frame
        ll = Point3(frame[0], frame[2], 0)
        ur = Point3(frame[1], frame[3], 0)
        aspectTs = TransformState.makeScale2d(
            Point2(1 / base.camLens.getAspectRatio(), 1))
        ll = aspectTs.getMat().xformPoint(ll)
        ur = aspectTs.getMat().xformPoint(ur)
        posTs = TransformState.makePos2d(
            Point2(ll[0] + ur[0], ll[1] + ur[1]) / -2.0)
        scaleTs = TransformState.makeScale2d(
            Point2(2.0 / (ur[0] - ll[0]), 2.0 / (ur[1] - ll[1])))
        frameTs = scaleTs.compose(posTs)
        self._mouseToHomogenousFrameMat = Mat4(frameTs.getMat())
        self._mouseToHomogenousFrameMatInv = Mat4(
            frameTs.getInverse().getMat())
        self._camLensProjMat = Mat4(self.camLens.getProjectionMat())
        self._camLensProjMatInv = Mat4(self._camLensProjMat)
        self._camLensProjMatInv.invertInPlace()

    def _transMouseToHomogenousFramePt(self, pt):
        pt = Point3(pt[0], pt[1], 0)
        return self._mouseToHomogenousFrameMat.xformPoint(pt)

    def _transHomogenousFrameToMousePt(self, pt):
        return self._mouseToHomogenousFrameMatInv.xformPoint(pt)

    def _transCamSpaceToHomogenousFramePt(self, pt):
        pt = self._camLensProjMat.xform(Vec4(pt[0], pt[1], pt[2], 1))
        pt /= pt[3]
        return pt

    def _transHomogenousFrameToCamSpacePt(self, pt):
        pt = self._camLensProjMatInv.xform(Vec4(pt[0], pt[1], pt[2], 1))
        pt /= pt[3]
        return pt

    def setNorth(self, northVec):
        self._north = northVec

    def saveNorth(self):
        upSpaceNodePath = self
        Z = Vec3.unitZ()
        upSpaceToRNode = TransformState.makeHpr(
            upSpaceNodePath.getHpr(self._rNode))
        self._north = upSpaceToRNode.getMat().xformPoint(Z)

    def _applyConstraints(self):
        self._rotate(self.getOrthTiltLimitQuat(self._tiltLimit), 1.0)
        if self._keepUpright:
            self.clampOrientationAboutSpherePt(self.getCamRayCollisionPt())

    def getTiltLimitQuat(self, thetaLimit):
        Y = Vec3.unitY()
        Z = Vec3.unitZ()
        upSpaceNodePath = self
        rNodeNorth = Z
        arcballNorth = -Y
        rNodeToUpSpace = TransformState.makeHpr(
            self._rNode.getHpr(upSpaceNodePath))
        northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)
        dot = northPole.dot(arcballNorth)
        theta = math.acos(clampScalar(-1, 1, dot))
        if theta < thetaLimit:
            return Quat.identQuat()
        else:
            axis = northPole.cross(arcballNorth)
            axis.normalize()
            theta -= thetaLimit
            return Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0))

    def getOrthTiltLimitQuat(self, thetaLimit=10):
        X = Vec3.unitX()
        Y = Vec3.unitY()
        Z = Vec3.unitZ()
        upSpaceNodePath = self
        rNodeNorth = Z
        arcballNorth = -Y
        baseQuat = self._rNode.getQuat(upSpaceNodePath)
        quatX = Quat.identQuat()
        quatY = Quat.identQuat()
        rNodeToUpSpace = TransformState.makeQuat(baseQuat)
        northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)
        dot = northPole.dot(X)
        proj = northPole - X * dot
        theta = math.acos(
            clampScalar(-1.0, 1.0,
                        proj.dot(arcballNorth) / proj.length()))
        if theta > thetaLimit:
            theta -= thetaLimit
            if northPole.dot(Z) < 0.0:
                theta *= -1

            quatX = Quat(math.cos(theta / 2.0), X * math.sin(theta / 2.0))
            baseQuat *= quatX
            rNodeToUpSpace = TransformState.makeQuat(baseQuat)
            northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)

        dot = northPole.dot(Z)
        proj = northPole - Z * dot
        theta = math.acos(
            clampScalar(-1.0, 1.0,
                        proj.dot(arcballNorth) / proj.length()))
        if theta > thetaLimit:
            theta -= thetaLimit
            if northPole.dot(X) >= 0.0:
                theta *= -1

            quatY = Quat(math.cos(theta / 2.0), Z * math.sin(theta / 2.0))
            baseQuat *= quatY

        return quatX * quatY

    def getUprightCorrectionQuat(self, pt):
        Y = Vec3.unitY()
        Z = Vec3.unitZ()
        rNodeNorth = self._north
        upSpaceNodePath = self
        axis = pt / pt.length()
        up = Z
        rNodeToUpSpace = TransformState.makeHpr(
            self._rNode.getHpr(upSpaceNodePath))
        northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)
        right = up.cross(axis)
        final = axis.cross(right)
        dot = northPole.dot(axis)
        proj = northPole - axis * dot
        theta = math.acos(
            clampScalar(-1.0, 1.0,
                        proj.dot(final) / proj.length() * final.length()))
        if northPole.dot(right) < 0.0:
            theta *= -1

        return Quat(math.cos(theta / 2.0), Vec3(axis) * math.sin(theta / 2.0))

    def _rotate(self, q, factor=1.0):
        q = nLerp(Quat(1, Vec3(0)), q, factor)
        self._rNode.setQuat(self._rNode.getQuat() * q)

    def _rotatePtToPt(self, p0, p1, factor=1.0):
        self._rotate(self._getPtToPtQuat(p0, p1), factor)

    def _getPtToPtQuat(self, p0, p1, factor=1.0):
        p0.normalize()
        p1.normalize()
        theta = math.acos(clampScalar(-1, 1, p0.dot(p1)))
        axis = p0.cross(p1)
        axis.normalize()
        if factor == 1.0:
            return Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0))
        elif 0.0 < factor:
            pass
        elif factor == 1.0:
            q = nLerp(
                Quat.identQuat(),
                Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0)),
                factor)
            return q

    def _getRotateAboutAxisQuat(self, axis, p0, p1, factor=1.0):
        axis = axis / axis.length()
        dot0 = axis.dot(p0)
        proj0 = p0 - axis * dot0
        dot1 = axis.dot(p1)
        proj1 = p1 - axis * dot1
        axis = proj0.cross(proj1)
        area = axis.length()
        axis.normalize()
        theta = math.acos(
            clampScalar(-1, 1,
                        proj0.dot(proj1) / proj0.length() * proj1.length()))
        return (Quat(math.cos(theta / 2.0),
                     axis * math.sin(theta / 2.0)), area)

    def _rotateQuatByQuat(self, q0, q1, factor=1.0):
        self._rNode.setQuat(nLerp(q0, q0 * q1, factor))

    def clampOrientationAboutSpherePt(self, pt):
        q = self.getUprightCorrectionQuat(pt)
        self._rotate(q, 1.0)

    def rotatePtToCenter(self, pt):
        centerPt = self.getCamRayCollisionPt()
        self._rotatePtToPt(pt, centerPt)
        self._applyConstraints()

    def rotateSpherePtToCenter(self, spherePt):
        pt = self._colNode.getRelativePoint(self._rNode, spherePt)
        self.rotatePtToCenter(pt)

    def clampSpherePtToHorizon(self, pt):
        camRaySpherePt = self.findCamRaySpherePt(pt)
        if camRaySpherePt and not pt.almostEqual(camRaySpherePt, 0.0001):
            camToSphere = self.cam.getTransform(self._rNode)
            OC = camToSphere.getMat().xformPoint(Vec3(0, 0, 0))
            theta = math.acos(
                clampScalar(-1.0, 1.0, self._radius / OC.length()))
            axis = OC.cross(pt)
            axis.normalize()
            q = Quat(math.cos(theta / 2), axis * math.sin(theta / 2))
            ts = TransformState.makeQuat(q)
            OC.normalize()
            OC *= self._radius
            newPt = ts.getMat().xformPoint(OC)
            dTheta = math.acos(clampScalar(-1.0, 1.0, pt.dot(newPt)))
            return (newPt, dTheta)
        else:
            return (pt, 0)

    def reorientNorth(self, time=0.0):
        self.setNorth(Vec3(0, 1, 0))
        curQ = self.getInternalQuat()
        pt = self.getCamRayCollision()
        upQ = self.getUprightCorrectionQuat(pt)

        def rotateFunc(t):
            self._rotateQuatByQuat(curQ, upQ, t)

        if self._ballIval:
            self._ballIval.pause()

        self._ballIval = LerpFunc(rotateFunc, duration=time)
        self._ballIval.start()

    def showRotationSphere(self):
        if not hasattr(self, '_ArcBall_rotGuide'):
            self._rotGuide = loader.loadModel('models/misc/sphere')
            self._rotGuide.setName('RotationGuide')
            self._rotGuide.setRenderModeWireframe()
            self._rotGuide.setTwoSided(1)
            self._rotGuide.setTextureOff(1)
            self._rotGuide.setColor(Vec4(1, 0, 0, 1))
            self._rotGuide.reparentTo(self.getRotateRoot())

        self._rotGuide.setScale(self._radius)
        self._rotGuide.show()

    def hideRotationSphere(self):
        if hasattr(self, '_ArcBall_rotGuide'):
            self._rotGuide.hide()

    def _startRotateTask(self, *args):
        self.saveTransforms()
        modePairs = ((0, 2), (1, 3))
        if not self._ctrlBtnState:
            rMode = modePairs[self.rMode][0]
        else:
            rMode = modePairs[self.rMode][1]
        if self.rMode in [1]:
            props = WindowProperties()
            props.setCursorHidden(1)
            base.win.requestProperties(props)

        task = taskMgr.add(self._rotateTask, self.getName() + '-rotateTask')
        task.rMode = rMode

    def _rotateTask(self, task):
        if not hasattr(task, 'startPt'):
            task.startPt = self.getMouseRayCollisionPt()
            task.camPt = self.getCamRayCollisionPt()
            task.quat = self._rNode.getQuat()

        if task.rMode == 0:
            pt = self.getMouseRayCollisionPt()
            q = self._getPtToPtQuat(task.startPt, pt)
            self._rotateQuatByQuat(task.quat, q, 1.0)
            self._applyConstraints()
        elif task.rMode == 1:
            dt = globalClock.getDt()
            pt = self.getMouseRayCollisionPt()
            self._rotatePtToPt(pt, task.startPt, dt * self._scrollFactor * 5)
            self._applyConstraints()
            self.createStraightArrow(task.startPt, pt, 0.02)
        elif task.rMode == 2:
            pt = self.getMouseRayCollisionPt()
            (q, area) = self._getRotateAboutAxisQuat(task.camPt, task.startPt,
                                                     pt)
            self._rotateQuatByQuat(task.quat, q, 1.0)
            self.saveNorth()
        elif task.rMode == 3:
            dt = globalClock.getDt()
            pt = self.getMouseRayCollisionPt()
            (q, area) = self._getRotateAboutAxisQuat(task.camPt, pt,
                                                     task.startPt)
            self._rotate(q, dt * self._scrollFactor * area * 300)
            self.createCurvedArrow(task.camPt, pt, task.startPt, 0.02)
            self.saveNorth()

        return task.cont

    def _stopRotateTask(self, *args):
        taskMgr.remove(self.getName() + '-rotateTask')
        self.tail_geom_node.removeAllGeoms()
        self.head_geom_node.removeAllGeoms()
        if self.rMode in [1]:
            props = WindowProperties()
            props.setCursorHidden(0)
            base.win.requestProperties(props)

    def createStraightArrow(self, p0, p1, width):
        p0.normalize()
        p1.normalize()
        dot = p0.dot(p1)
        cross = p0.cross(p1)
        arcLen = math.acos(clampScalar(-1, 1, dot))
        self.tail_geom_node.removeAllGeoms()
        self.head_geom_node.removeAllGeoms()
        if arcLen > 0.0:
            cross.normalize()
            cross *= width / 2.0
            theta = 2 * math.asin(width / 2.0)
            div = arcLen / theta
            steps = int(div)
            remainder = div - steps
            pts = []
            for n in range(steps + 1):
                pts.append(sLerp(p1, p0, n / div, arcLen) * self._radius)

            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            if len(pts) == 1:
                vertex_writer.addData3f(p1[0] - cross[0], p1[1] - cross[1],
                                        p1[2] - cross[2])
                vertex_writer.addData3f(p1[0] + cross[0], p1[1] + cross[1],
                                        p1[2] + cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)
                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)
                vertex_writer.addData3f(p0[0] - cross[0], p0[1] - cross[1],
                                        p0[2] - cross[2])
                vertex_writer.addData3f(p0[0] + cross[0], p0[1] + cross[1],
                                        p0[2] + cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)
                texture_writer.addData2f(1, 1 - remainder)
                texture_writer.addData2f(0, 1 - remainder)
                triStrip.addNextVertices(4)
            else:
                for pt in pts[:2]:
                    vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1],
                                            pt[2] - cross[2])
                    vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1],
                                            pt[2] + cross[2])
                    color_writer.addData4f(0, 1, 0, 1)
                    color_writer.addData4f(0, 1, 0, 1)

                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)
                texture_writer.addData2f(1, 0)
                texture_writer.addData2f(0, 0)
                triStrip.addNextVertices(4)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.head_geom_node.addGeom(geometry)
            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            for pt in pts[1:]:
                vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1],
                                        pt[2] - cross[2])
                vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1],
                                        pt[2] + cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)

            numPts = len(pts[1:])
            for x in range(numPts / 2):
                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)
                texture_writer.addData2f(1, 0)
                texture_writer.addData2f(0, 0)

            if numPts % 2:
                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)

            vertex_writer.addData3f(p0[0] - cross[0], p0[1] - cross[1],
                                    p0[2] - cross[2])
            vertex_writer.addData3f(p0[0] + cross[0], p0[1] + cross[1],
                                    p0[2] + cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            if numPts % 2:
                texture_writer.addData2f(1, 1 - remainder)
                texture_writer.addData2f(0, 1 - remainder)
            else:
                texture_writer.addData2f(1, remainder)
                texture_writer.addData2f(0, remainder)
            triStrip.addNextVertices(numPts * 2 + 2)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.tail_geom_node.addGeom(geometry)

    def createCurvedArrow(self, axis, p0, p1, width, numPanels=10):
        N = numPanels
        self.tail_geom_node.removeAllGeoms()
        self.head_geom_node.removeAllGeoms()
        axis = axis / axis.length()
        dot0 = axis.dot(p0)
        proj0 = p0 - axis * dot0
        dot1 = axis.dot(p1)
        proj1 = p1 - axis * dot1
        theta = math.acos(
            clampScalar(-1, 1,
                        proj0.dot(proj1) / proj0.length() * proj1.length()))
        if not proj0.almostEqual(proj1, 0.0001) and theta != 0:
            if proj0.lengthSquared() >= proj1.lengthSquared():
                A = proj0
                C = proj1
            else:
                A = proj1
                C = proj0
            a = A.length()
            aUnit = A / a
            x = A.dot(C) / a
            yy = C.lengthSquared() - x * x
            bUnit = A.cross(C).cross(A)
            bUnit.normalize()
            b = math.sqrt(max(0.0, yy / (1 - x * x / a * a)))
            t = math.atan2(a, b / math.tan(theta))
            aUnit *= a
            bUnit *= b
            pts = [
                aUnit * math.cos(x * t / N) + bUnit * math.sin(x * t / N)
                for x in range(N + 1)
            ]
            pts = [
                pt + axis *
                math.sqrt(self._radius * self._radius - pt.lengthSquared())
                for pt in pts
            ]
            if A != proj0:
                pts.reverse()

            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            cross = pts[0].cross(pts[1] - pts[0])
            cross.normalize()
            cross *= width / 2.0
            pt = pts[0]
            vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1],
                                    pt[2] + cross[2])
            vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1],
                                    pt[2] - cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            texture_writer.addData2f(0, 1)
            texture_writer.addData2f(1, 1)
            diffA = pts[1] - pts[0]
            diffB = pts[2] - pts[1]
            cross = pts[1].cross((diffB + diffA) / 2.0)
            cross.normalize()
            cross *= width / 2.0
            pt = pts[1]
            vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1],
                                    pt[2] + cross[2])
            vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1],
                                    pt[2] - cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            texture_writer.addData2f(0, 0)
            texture_writer.addData2f(1, 0)
            triStrip.addNextVertices(4)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.head_geom_node.addGeom(geometry)
            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            for x in range(len(pts[1:-1])):
                cross = pts[x + 1].cross(pts[x + 2] - pts[x])
                cross.normalize()
                cross *= width / 2.0
                pt = pts[x + 1]
                vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1],
                                        pt[2] + cross[2])
                vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1],
                                        pt[2] - cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)
                if x % 2:
                    texture_writer.addData2f(0, 1)
                    texture_writer.addData2f(1, 1)
                else:
                    texture_writer.addData2f(0, 0)
                    texture_writer.addData2f(1, 0)
                triStrip.addNextVertices(2)

            cross = pts[-1].cross(pts[-1] - pts[-2])
            cross.normalize()
            cross *= width / 2.0
            pt = pts[-1]
            vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1],
                                    pt[2] + cross[2])
            vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1],
                                    pt[2] - cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            if N % 2:
                texture_writer.addData2f(0, 0)
                texture_writer.addData2f(1, 0)
            else:
                texture_writer.addData2f(0, 1)
                texture_writer.addData2f(1, 1)
            triStrip.addNextVertices(2)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.tail_geom_node.addGeom(geometry)

    def _startArrowTask(self):
        taskMgr.add(self._arrowTask, self.getName() + '-arrowTask')

    def _arrowTask(self, task):
        if not hasattr(task, 'p0'):
            task.p0 = self.getMouseRayCollisionPt()
            task.p0.normalize()

        p1 = self.getMouseRayCollisionPt()
        p1.normalize()
        self.createStraightArrow(task.p0, p1, 0.02)
        return task.cont

    def _stopArrowTask(self):
        taskMgr.remove(self.getName() + '-arrowTask')
Ejemplo n.º 4
0
class FPS(object,DirectObject): 
    def __init__(self): 
        self.winXhalf = base.win.getXSize()/2 
        self.winYhalf = base.win.getYSize()/2 
        self.initCollision() 
        self.loadLevel() 
        self.initPlayer() 

    def initCollision(self): 
        #initialize traverser 
        base.cTrav = CollisionTraverser() 
        base.cTrav.setRespectPrevTransform(True) 
#         base.cTrav.showCollisions(render) 
        #initialize pusher 
        self.pusher = CollisionHandlerPusher() 
        # collision bits 
        self.groundCollBit = BitMask32.bit(0) 
        self.collBitOff = BitMask32.allOff() 

    def loadLevel(self): 

        #load level 
        # must have 
        #<Group> *something* { 
        #  <Collide> { Polyset keep descend } in the egg file 
        level = loader.loadModel("models/environment") 
        level.reparentTo(render) 
        level.setPos(0,0,0) 
        level.setColor(1,1,1,.5) 

    def initPlayer(self): 
        #load man 
        self.man = render.attachNewNode('man') # keep this node scaled to identity 
        self.man.setPos(0,0,0) 
        # should be avatar model 
#         model = loader.loadModel('teapot') 
#         model.reparentTo(self.man) 
#         model.setScale(.05) 
        # camera 
        base.camera.reparentTo(self.man) 
        base.camera.setPos(0,0,1.7) 
        base.camLens.setNearFar(.1,1000) 
        base.disableMouse() 
        #create a collsion solid around the man 
        manC = self.man.attachCollisionSphere('manSphere', 0,0,1, .4, self.groundCollBit,self.collBitOff) 
        self.pusher.addCollider(manC,self.man) 
        base.cTrav.addCollider(manC,self.pusher) 

        speed = 4 
        Forward = Vec3(0,speed*2,0) 
        Back = Vec3(0,-speed,0) 
        Left = Vec3(-speed,0,0) 
        Right = Vec3(speed,0,0) 
        Stop = Vec3(0) 
        self.walk = Stop 
        self.strife = Stop 
        self.jump = 0 
        taskMgr.add(self.move, 'move-task') 
        self.jumping = LerpFunc( Functor(self.__setattr__,"jump"), 
                                 duration=.25, fromData=.25, toData=0) 
        self.accept( "escape",sys.exit ) 
        self.accept( "space" , self.startJump) 
        self.accept( "s" , self.__setattr__,["walk",Back] ) 
        self.accept( "w" , self.__setattr__,["walk",Forward]) 
        self.accept( "s-up" , self.__setattr__,["walk",Stop] ) 
        self.accept( "w-up" , self.__setattr__,["walk",Stop] ) 
        self.accept( "a" , self.__setattr__,["strife",Left]) 
        self.accept( "d" , self.__setattr__,["strife",Right] ) 
        self.accept( "a-up" , self.__setattr__,["strife",Stop] ) 
        self.accept( "d-up" , self.__setattr__,["strife",Stop] ) 

        self.manGroundColNp = self.man.attachCollisionRay( 'manRay', 
                                                           0,0,.6, 0,0,-1, 
                                                           self.groundCollBit,self.collBitOff) 
        self.manGroundHandler = CollisionHandlerGravity() 
        self.manGroundHandler.addCollider(self.manGroundColNp,self.man) 
        base.cTrav.addCollider(self.manGroundColNp, self.manGroundHandler) 

    def startJump(self): 
        if self.manGroundHandler.isOnGround(): 
           self.jumping.start() 

    def move(self,task): 
        dt=globalClock.getDt() 
        # mouse 
        md = base.win.getPointer(0) 
        x = md.getX() 
        y = md.getY() 
        if base.win.movePointer(0, self.winXhalf, self.winYhalf): 
            self.man.setH(self.man, (x - self.winXhalf)*-0.1) 
            base.camera.setP( clampScalar(-90,90, base.camera.getP() - (y - self.winYhalf)*0.1) ) 
        # move where the keys set it 
        moveVec=(self.walk+self.strife)*dt # horisontal 
        moveVec.setZ( self.jump )          # vertical 
        self.man.setFluidPos(self.man,moveVec) 
        # jump damping 
        if self.jump>0: 
           self.jump = clampScalar( 0,1, self.jump*.9 ) 

        return task.cont 
class ArcBall(NodePath, DirectObject):

    def __init__(self, name, radius = 1, scrollFactor = 1, camera = base.cam, frame = Vec4(-1, 1, -1, 1), keepUpright = 0, mouseDownEvent = 'mouse1', mouseUpEvent = 'mouse1-up', *args, **kwargs):
        NodePath.__init__(self, name, *args, **kwargs)
        DirectObject.__init__(self)
        self._rNode = self.attachNewNode('rotateNode')
        self._setRadius(radius, False)
        self._setScrollFactor(scrollFactor, False)
        self._setCamera(camera, False)
        self._setFrame(frame, False)
        self._setKeepUpright(keepUpright)
        self._setMouseEvents(mouseDownEvent, mouseUpEvent)
        self.setRotateMode(0)
        self._setControlButtonState(0)
        self._setTiltLimit(25 * math.pi / 180, False)
        self.saveNorth()
        self._colBitMask = BitMask32(1 << 16)
        self._colNode = self.attachNewNode(CollisionNode(name + '-cNode'))
        self._colNode.node().addSolid(CollisionSphere(0, 0, 0, 1))
        self._colNode.node().setIntoCollideMask(self._colBitMask)
        self._mouseEnabled = True
        self._initCollisions()
        self.geom_node_path = self.attachNewNode('arrow')
        self.geom_node_path.setBin('fixed', 100)
        self.geom_node_path.setDepthTest(0)
        self.geom_node_path.setTransparency(1)
        self.head_geom_node = GeomNode('head')
        self.head_geom_node_path = self.geom_node_path.attachNewNode(self.head_geom_node)
        self.tail_geom_node = GeomNode('tail')
        self.tail_geom_node_path = self.geom_node_path.attachNewNode(self.tail_geom_node)
        self._ballIval = None


    def removeNode(self):
        self.ignoreAll()
        NodePath.removeNode(self)


    def _setRadius(self, radius, reset = True):
        self._radius = radius


    def _setScrollFactor(self, scrollFactor, reset = True):
        self._scrollFactor = float(scrollFactor)


    def _setCamera(self, cam, reset = True):
        self.cam = cam
        self.camNode = cam.node()
        self.camLens = self.camNode.getLens()


    def _setFrame(self, frame, reset = True):
        self._frame = frame
        self.saveTransforms()


    def _setKeepUpright(self, keepUpright):
        self._keepUpright = keepUpright


    def _setControlButtonState(self, state):
        self._ctrlBtnState = state


    def _setTiltLimit(self, limit = math.pi / 6, reset = True):
        self._tiltLimit = limit
        if reset:
            self._applyConstraints()



    def _setMouseEvents(self, down, up):
        if hasattr(self, '_mouseDownEventStr'):
            self.ignore(self._mouseDownEventStr)

        if hasattr(self, '_mouseUpEventStr'):
            self.ignore(self._mouseUpEventStr)

        self._mouseDownEventStr = down
        self._mouseUpEventStr = up
        self.accept(self._mouseDownEventStr, self._mouseDown)
        self.accept(self._mouseUpEventStr, self._mouseUp)


    def setRadius(self, radius):
        self._setRadius(radius)


    def setScrollFactor(self, scrollFactor):
        self._setScrollFactor(scrollFactor)


    def setCamera(self, camera):
        self._setCamera(camera)


    def setFrame(self, frame):
        self._setFrame(frame)


    def setKeepUpright(self, keepUpright):
        self._setKeepUpright(keepUpright)


    def setMouseEvents(self, downEvent, upEvent):
        self._setMouseEvents(downEvent, upEvent)


    def setMouseEnabled(self, enabled):
        self._mouseEnabled = enabled
        if not self._mouseEnabled:
            self._mouseUp()



    def setRotateMode(self, mode):
        self.rMode = mode


    def enable(self):
        self.setMouseEnabled(True)


    def disable(self):
        if self._ballIval:
            self._ballIval.pause()
            self._ballIval = None

        self.setMouseEnabled(False)


    def getRotateRoot(self):
        return self._rNode


    def attachForRotation(self, nodepath):
        nodepath.reparentTo(self._rNode)


    def getInternalHpr(self, *args, **kwargs):
        return self._rNode.getHpr(*args, **kwargs)


    def setInternalHpr(self, *args, **kwargs):
        self._rNode.setHpr(*args, **kwargs)


    def getInternalQuat(self, *args, **kwargs):
        return self._rNode.getQuat(*args, **kwargs)


    def setInternalQuat(self, *args, **kwargs):
        self._rNode.setQuat(*args, **kwargs)


    def _mouseDown(self, *args):
        if self._mouseEnabled:
            self._startRotateTask()



    def _mouseUp(self, *args):
        self._stopRotateTask()


    def _initCollisions(self):
        self.traverser = CollisionTraverser()
        self.colHandlerQueue = CollisionHandlerQueue()
        self.camRayNode = self.cam.attachNewNode(CollisionNode('camRayNode'))
        self.camRay = CollisionRay()
        self.camRayNode.node().addSolid(self.camRay)
        self.traverser.addCollider(self.camRayNode, self.colHandlerQueue)


    def _mouseRayCollide(self, rayBitMask = BitMask32.allOn()):
        if base.mouseWatcherNode.hasMouse():
            mousePt = base.mouseWatcherNode.getMouse()
            mousePt = self._transMouseToHomogenousFramePt(mousePt)
            self.camRay.setFromLens(self.camNode, mousePt[0], mousePt[1])
            self.camRayNode.node().setFromCollideMask(rayBitMask)
            self.traverser.traverse(self)
            self.traverser.traverse(self.getTop())
        else:
            self.colHandlerQueue.clearEntries()


    def _camRayCollide(self, rayBitMask = BitMask32.allOn()):
        self.camRay.setOrigin(Point3(0))
        self.camRay.setDirection(Vec3(0, 1, 0))
        self.camRayNode.node().setFromCollideMask(rayBitMask)
        self.traverser.traverse(self)
        self.traverser.traverse(self.getTop())


    def getHorizonCollisionPt(self, raySpace = None, rayDirection = None):
        raySpaceToSelf = raySpace.getTransform(self)
        rayOrig = raySpaceToSelf.getMat().xformPoint(Point3(0))
        rayDist = rayOrig.length()
        ray = raySpaceToSelf.getMat().xformPoint(rayDirection)
        a = rayOrig * self._radius * self._radius / rayDist * rayDist
        b = -rayOrig.cross(ray).cross(-rayOrig)
        b.normalize()
        b *= math.sqrt(1 - 1 / rayDist / rayDist)
        return a + b


    def _getCollisionPt(self):
        entryCount = self.colHandlerQueue.getNumEntries()
        for x in range(entryCount):
            entry = self.colHandlerQueue.getEntry(x)
            if entry.getIntoNode().getName() == self.getName() + '-cNode':
                return entry.getSurfacePoint(entry.getIntoNodePath())
                continue

        camRay = self.camRayNode.node().getSolid(0).getDirection()
        pt = self.getHorizonCollisionPt(self.cam, camRay)
        return pt


    def getMouseRayCollisionPt(self, rayBitMask = None):
        if not rayBitMask:
            rayBitMask = self._colBitMask

        self._mouseRayCollide(rayBitMask)
        return self._getCollisionPt()


    def getCamRayCollisionPt(self, rayBitMask = None):
        if not rayBitMask:
            rayBitMask = self._colBitMask

        self._camRayCollide(rayBitMask)
        return self._getCollisionPt()


    def _getCollisionEntry(self):
        entryCount = self.colHandlerQueue.getNumEntries()
        if entryCount:
            self.colHandlerQueue.sort()
            return self.colHandlerQueue.getEntry(0)
        else:
            return None


    def getMouseRayCollisionEntry(self, rayBitMask = None):
        if not rayBitMask:
            rayBitMask = self._colBitMask

        self._mouseRayCollide(rayBitMask)
        return self._getCollisionEntry()


    def saveTransforms(self):
        frame = self._frame
        ll = Point3(frame[0], frame[2], 0)
        ur = Point3(frame[1], frame[3], 0)
        aspectTs = TransformState.makeScale2d(Point2(1 / base.camLens.getAspectRatio(), 1))
        ll = aspectTs.getMat().xformPoint(ll)
        ur = aspectTs.getMat().xformPoint(ur)
        posTs = TransformState.makePos2d(Point2(ll[0] + ur[0], ll[1] + ur[1]) / -2.0)
        scaleTs = TransformState.makeScale2d(Point2(2.0 / (ur[0] - ll[0]), 2.0 / (ur[1] - ll[1])))
        frameTs = scaleTs.compose(posTs)
        self._mouseToHomogenousFrameMat = Mat4(frameTs.getMat())
        self._mouseToHomogenousFrameMatInv = Mat4(frameTs.getInverse().getMat())
        self._camLensProjMat = Mat4(self.camLens.getProjectionMat())
        self._camLensProjMatInv = Mat4(self._camLensProjMat)
        self._camLensProjMatInv.invertInPlace()


    def _transMouseToHomogenousFramePt(self, pt):
        pt = Point3(pt[0], pt[1], 0)
        return self._mouseToHomogenousFrameMat.xformPoint(pt)


    def _transHomogenousFrameToMousePt(self, pt):
        return self._mouseToHomogenousFrameMatInv.xformPoint(pt)


    def _transCamSpaceToHomogenousFramePt(self, pt):
        pt = self._camLensProjMat.xform(Vec4(pt[0], pt[1], pt[2], 1))
        pt /= pt[3]
        return pt


    def _transHomogenousFrameToCamSpacePt(self, pt):
        pt = self._camLensProjMatInv.xform(Vec4(pt[0], pt[1], pt[2], 1))
        pt /= pt[3]
        return pt


    def setNorth(self, northVec):
        self._north = northVec


    def saveNorth(self):
        upSpaceNodePath = self
        Z = Vec3.unitZ()
        upSpaceToRNode = TransformState.makeHpr(upSpaceNodePath.getHpr(self._rNode))
        self._north = upSpaceToRNode.getMat().xformPoint(Z)


    def _applyConstraints(self):
        self._rotate(self.getOrthTiltLimitQuat(self._tiltLimit), 1.0)
        if self._keepUpright:
            self.clampOrientationAboutSpherePt(self.getCamRayCollisionPt())



    def getTiltLimitQuat(self, thetaLimit):
        Y = Vec3.unitY()
        Z = Vec3.unitZ()
        upSpaceNodePath = self
        rNodeNorth = Z
        arcballNorth = -Y
        rNodeToUpSpace = TransformState.makeHpr(self._rNode.getHpr(upSpaceNodePath))
        northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)
        dot = northPole.dot(arcballNorth)
        theta = math.acos(clampScalar(-1, 1, dot))
        if theta < thetaLimit:
            return Quat.identQuat()
        else:
            axis = northPole.cross(arcballNorth)
            axis.normalize()
            theta -= thetaLimit
            return Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0))


    def getOrthTiltLimitQuat(self, thetaLimit = 10):
        X = Vec3.unitX()
        Y = Vec3.unitY()
        Z = Vec3.unitZ()
        upSpaceNodePath = self
        rNodeNorth = Z
        arcballNorth = -Y
        baseQuat = self._rNode.getQuat(upSpaceNodePath)
        quatX = Quat.identQuat()
        quatY = Quat.identQuat()
        rNodeToUpSpace = TransformState.makeQuat(baseQuat)
        northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)
        dot = northPole.dot(X)
        proj = northPole - X * dot
        theta = math.acos(clampScalar(-1.0, 1.0, proj.dot(arcballNorth) / proj.length()))
        if theta > thetaLimit:
            theta -= thetaLimit
            if northPole.dot(Z) < 0.0:
                theta *= -1

            quatX = Quat(math.cos(theta / 2.0), X * math.sin(theta / 2.0))
            baseQuat *= quatX
            rNodeToUpSpace = TransformState.makeQuat(baseQuat)
            northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)

        dot = northPole.dot(Z)
        proj = northPole - Z * dot
        theta = math.acos(clampScalar(-1.0, 1.0, proj.dot(arcballNorth) / proj.length()))
        if theta > thetaLimit:
            theta -= thetaLimit
            if northPole.dot(X) >= 0.0:
                theta *= -1

            quatY = Quat(math.cos(theta / 2.0), Z * math.sin(theta / 2.0))
            baseQuat *= quatY

        return quatX * quatY


    def getUprightCorrectionQuat(self, pt):
        Y = Vec3.unitY()
        Z = Vec3.unitZ()
        rNodeNorth = self._north
        upSpaceNodePath = self
        axis = pt / pt.length()
        up = Z
        rNodeToUpSpace = TransformState.makeHpr(self._rNode.getHpr(upSpaceNodePath))
        northPole = rNodeToUpSpace.getMat().xformPoint(rNodeNorth)
        right = up.cross(axis)
        final = axis.cross(right)
        dot = northPole.dot(axis)
        proj = northPole - axis * dot
        theta = math.acos(clampScalar(-1.0, 1.0, proj.dot(final) / proj.length() * final.length()))
        if northPole.dot(right) < 0.0:
            theta *= -1

        return Quat(math.cos(theta / 2.0), Vec3(axis) * math.sin(theta / 2.0))


    def _rotate(self, q, factor = 1.0):
        q = nLerp(Quat(1, Vec3(0)), q, factor)
        self._rNode.setQuat(self._rNode.getQuat() * q)


    def _rotatePtToPt(self, p0, p1, factor = 1.0):
        self._rotate(self._getPtToPtQuat(p0, p1), factor)


    def _getPtToPtQuat(self, p0, p1, factor = 1.0):
        p0.normalize()
        p1.normalize()
        theta = math.acos(clampScalar(-1, 1, p0.dot(p1)))
        axis = p0.cross(p1)
        axis.normalize()
        if factor == 1.0:
            return Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0))
        elif 0.0 < factor:
            pass
        elif factor == 1.0:
            q = nLerp(Quat.identQuat(), Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0)), factor)
            return q



    def _getRotateAboutAxisQuat(self, axis, p0, p1, factor = 1.0):
        axis = axis / axis.length()
        dot0 = axis.dot(p0)
        proj0 = p0 - axis * dot0
        dot1 = axis.dot(p1)
        proj1 = p1 - axis * dot1
        axis = proj0.cross(proj1)
        area = axis.length()
        axis.normalize()
        theta = math.acos(clampScalar(-1, 1, proj0.dot(proj1) / proj0.length() * proj1.length()))
        return (Quat(math.cos(theta / 2.0), axis * math.sin(theta / 2.0)), area)


    def _rotateQuatByQuat(self, q0, q1, factor = 1.0):
        self._rNode.setQuat(nLerp(q0, q0 * q1, factor))


    def clampOrientationAboutSpherePt(self, pt):
        q = self.getUprightCorrectionQuat(pt)
        self._rotate(q, 1.0)


    def rotatePtToCenter(self, pt):
        centerPt = self.getCamRayCollisionPt()
        self._rotatePtToPt(pt, centerPt)
        self._applyConstraints()


    def rotateSpherePtToCenter(self, spherePt):
        pt = self._colNode.getRelativePoint(self._rNode, spherePt)
        self.rotatePtToCenter(pt)


    def clampSpherePtToHorizon(self, pt):
        camRaySpherePt = self.findCamRaySpherePt(pt)
        if camRaySpherePt and not pt.almostEqual(camRaySpherePt, 0.0001):
            camToSphere = self.cam.getTransform(self._rNode)
            OC = camToSphere.getMat().xformPoint(Vec3(0, 0, 0))
            theta = math.acos(clampScalar(-1.0, 1.0, self._radius / OC.length()))
            axis = OC.cross(pt)
            axis.normalize()
            q = Quat(math.cos(theta / 2), axis * math.sin(theta / 2))
            ts = TransformState.makeQuat(q)
            OC.normalize()
            OC *= self._radius
            newPt = ts.getMat().xformPoint(OC)
            dTheta = math.acos(clampScalar(-1.0, 1.0, pt.dot(newPt)))
            return (newPt, dTheta)
        else:
            return (pt, 0)


    def reorientNorth(self, time = 0.0):
        self.setNorth(Vec3(0, 1, 0))
        curQ = self.getInternalQuat()
        pt = self.getCamRayCollision()
        upQ = self.getUprightCorrectionQuat(pt)

        def rotateFunc(t):
            self._rotateQuatByQuat(curQ, upQ, t)

        if self._ballIval:
            self._ballIval.pause()

        self._ballIval = LerpFunc(rotateFunc, duration = time)
        self._ballIval.start()


    def showRotationSphere(self):
        if not hasattr(self, '_ArcBall_rotGuide'):
            self._rotGuide = loader.loadModel('models/misc/sphere')
            self._rotGuide.setName('RotationGuide')
            self._rotGuide.setRenderModeWireframe()
            self._rotGuide.setTwoSided(1)
            self._rotGuide.setTextureOff(1)
            self._rotGuide.setColor(Vec4(1, 0, 0, 1))
            self._rotGuide.reparentTo(self.getRotateRoot())

        self._rotGuide.setScale(self._radius)
        self._rotGuide.show()


    def hideRotationSphere(self):
        if hasattr(self, '_ArcBall_rotGuide'):
            self._rotGuide.hide()



    def _startRotateTask(self, *args):
        self.saveTransforms()
        modePairs = ((0, 2), (1, 3))
        if not self._ctrlBtnState:
            rMode = modePairs[self.rMode][0]
        else:
            rMode = modePairs[self.rMode][1]
        if self.rMode in [
            1]:
            props = WindowProperties()
            props.setCursorHidden(1)
            base.win.requestProperties(props)

        task = taskMgr.add(self._rotateTask, self.getName() + '-rotateTask')
        task.rMode = rMode


    def _rotateTask(self, task):
        if not hasattr(task, 'startPt'):
            task.startPt = self.getMouseRayCollisionPt()
            task.camPt = self.getCamRayCollisionPt()
            task.quat = self._rNode.getQuat()

        if task.rMode == 0:
            pt = self.getMouseRayCollisionPt()
            q = self._getPtToPtQuat(task.startPt, pt)
            self._rotateQuatByQuat(task.quat, q, 1.0)
            self._applyConstraints()
        elif task.rMode == 1:
            dt = globalClock.getDt()
            pt = self.getMouseRayCollisionPt()
            self._rotatePtToPt(pt, task.startPt, dt * self._scrollFactor * 5)
            self._applyConstraints()
            self.createStraightArrow(task.startPt, pt, 0.02)
        elif task.rMode == 2:
            pt = self.getMouseRayCollisionPt()
            (q, area) = self._getRotateAboutAxisQuat(task.camPt, task.startPt, pt)
            self._rotateQuatByQuat(task.quat, q, 1.0)
            self.saveNorth()
        elif task.rMode == 3:
            dt = globalClock.getDt()
            pt = self.getMouseRayCollisionPt()
            (q, area) = self._getRotateAboutAxisQuat(task.camPt, pt, task.startPt)
            self._rotate(q, dt * self._scrollFactor * area * 300)
            self.createCurvedArrow(task.camPt, pt, task.startPt, 0.02)
            self.saveNorth()

        return task.cont


    def _stopRotateTask(self, *args):
        taskMgr.remove(self.getName() + '-rotateTask')
        self.tail_geom_node.removeAllGeoms()
        self.head_geom_node.removeAllGeoms()
        if self.rMode in [
            1]:
            props = WindowProperties()
            props.setCursorHidden(0)
            base.win.requestProperties(props)



    def createStraightArrow(self, p0, p1, width):
        p0.normalize()
        p1.normalize()
        dot = p0.dot(p1)
        cross = p0.cross(p1)
        arcLen = math.acos(clampScalar(-1, 1, dot))
        self.tail_geom_node.removeAllGeoms()
        self.head_geom_node.removeAllGeoms()
        if arcLen > 0.0:
            cross.normalize()
            cross *= width / 2.0
            theta = 2 * math.asin(width / 2.0)
            div = arcLen / theta
            steps = int(div)
            remainder = div - steps
            pts = []
            for n in range(steps + 1):
                pts.append(sLerp(p1, p0, n / div, arcLen) * self._radius)

            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            if len(pts) == 1:
                vertex_writer.addData3f(p1[0] - cross[0], p1[1] - cross[1], p1[2] - cross[2])
                vertex_writer.addData3f(p1[0] + cross[0], p1[1] + cross[1], p1[2] + cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)
                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)
                vertex_writer.addData3f(p0[0] - cross[0], p0[1] - cross[1], p0[2] - cross[2])
                vertex_writer.addData3f(p0[0] + cross[0], p0[1] + cross[1], p0[2] + cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)
                texture_writer.addData2f(1, 1 - remainder)
                texture_writer.addData2f(0, 1 - remainder)
                triStrip.addNextVertices(4)
            else:
                for pt in pts[:2]:
                    vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2])
                    vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2])
                    color_writer.addData4f(0, 1, 0, 1)
                    color_writer.addData4f(0, 1, 0, 1)

                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)
                texture_writer.addData2f(1, 0)
                texture_writer.addData2f(0, 0)
                triStrip.addNextVertices(4)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.head_geom_node.addGeom(geometry)
            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            for pt in pts[1:]:
                vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2])
                vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)

            numPts = len(pts[1:])
            for x in range(numPts / 2):
                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)
                texture_writer.addData2f(1, 0)
                texture_writer.addData2f(0, 0)

            if numPts % 2:
                texture_writer.addData2f(1, 1)
                texture_writer.addData2f(0, 1)

            vertex_writer.addData3f(p0[0] - cross[0], p0[1] - cross[1], p0[2] - cross[2])
            vertex_writer.addData3f(p0[0] + cross[0], p0[1] + cross[1], p0[2] + cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            if numPts % 2:
                texture_writer.addData2f(1, 1 - remainder)
                texture_writer.addData2f(0, 1 - remainder)
            else:
                texture_writer.addData2f(1, remainder)
                texture_writer.addData2f(0, remainder)
            triStrip.addNextVertices(numPts * 2 + 2)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.tail_geom_node.addGeom(geometry)



    def createCurvedArrow(self, axis, p0, p1, width, numPanels = 10):
        N = numPanels
        self.tail_geom_node.removeAllGeoms()
        self.head_geom_node.removeAllGeoms()
        axis = axis / axis.length()
        dot0 = axis.dot(p0)
        proj0 = p0 - axis * dot0
        dot1 = axis.dot(p1)
        proj1 = p1 - axis * dot1
        theta = math.acos(clampScalar(-1, 1, proj0.dot(proj1) / proj0.length() * proj1.length()))
        if not proj0.almostEqual(proj1, 0.0001) and theta != 0:
            if proj0.lengthSquared() >= proj1.lengthSquared():
                A = proj0
                C = proj1
            else:
                A = proj1
                C = proj0
            a = A.length()
            aUnit = A / a
            x = A.dot(C) / a
            yy = C.lengthSquared() - x * x
            bUnit = A.cross(C).cross(A)
            bUnit.normalize()
            b = math.sqrt(max(0.0, yy / (1 - x * x / a * a)))
            t = math.atan2(a, b / math.tan(theta))
            aUnit *= a
            bUnit *= b
            pts = [ aUnit * math.cos(x * t / N) + bUnit * math.sin(x * t / N) for x in range(N + 1) ]
            pts = [ pt + axis * math.sqrt(self._radius * self._radius - pt.lengthSquared()) for pt in pts ]
            if A != proj0:
                pts.reverse()

            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            cross = pts[0].cross(pts[1] - pts[0])
            cross.normalize()
            cross *= width / 2.0
            pt = pts[0]
            vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2])
            vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            texture_writer.addData2f(0, 1)
            texture_writer.addData2f(1, 1)
            diffA = pts[1] - pts[0]
            diffB = pts[2] - pts[1]
            cross = pts[1].cross((diffB + diffA) / 2.0)
            cross.normalize()
            cross *= width / 2.0
            pt = pts[1]
            vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2])
            vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            texture_writer.addData2f(0, 0)
            texture_writer.addData2f(1, 0)
            triStrip.addNextVertices(4)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.head_geom_node.addGeom(geometry)
            format = GeomVertexFormat.getV3c4t2()
            vertex_data = GeomVertexData('arc_ball', format, Geom.UHStatic)
            vertex_writer = GeomVertexWriter(vertex_data, 'vertex')
            color_writer = GeomVertexWriter(vertex_data, 'color')
            texture_writer = GeomVertexWriter(vertex_data, 'texcoord')
            triStrip = GeomTristrips(Geom.UHStatic)
            for x in range(len(pts[1:-1])):
                cross = pts[x + 1].cross(pts[x + 2] - pts[x])
                cross.normalize()
                cross *= width / 2.0
                pt = pts[x + 1]
                vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2])
                vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2])
                color_writer.addData4f(0, 1, 0, 1)
                color_writer.addData4f(0, 1, 0, 1)
                if x % 2:
                    texture_writer.addData2f(0, 1)
                    texture_writer.addData2f(1, 1)
                else:
                    texture_writer.addData2f(0, 0)
                    texture_writer.addData2f(1, 0)
                triStrip.addNextVertices(2)

            cross = pts[-1].cross(pts[-1] - pts[-2])
            cross.normalize()
            cross *= width / 2.0
            pt = pts[-1]
            vertex_writer.addData3f(pt[0] + cross[0], pt[1] + cross[1], pt[2] + cross[2])
            vertex_writer.addData3f(pt[0] - cross[0], pt[1] - cross[1], pt[2] - cross[2])
            color_writer.addData4f(0, 1, 0, 1)
            color_writer.addData4f(0, 1, 0, 1)
            if N % 2:
                texture_writer.addData2f(0, 0)
                texture_writer.addData2f(1, 0)
            else:
                texture_writer.addData2f(0, 1)
                texture_writer.addData2f(1, 1)
            triStrip.addNextVertices(2)
            geometry = Geom(vertex_data)
            geometry.addPrimitive(triStrip)
            self.tail_geom_node.addGeom(geometry)



    def _startArrowTask(self):
        taskMgr.add(self._arrowTask, self.getName() + '-arrowTask')


    def _arrowTask(self, task):
        if not hasattr(task, 'p0'):
            task.p0 = self.getMouseRayCollisionPt()
            task.p0.normalize()

        p1 = self.getMouseRayCollisionPt()
        p1.normalize()
        self.createStraightArrow(task.p0, p1, 0.02)
        return task.cont


    def _stopArrowTask(self):
        taskMgr.remove(self.getName() + '-arrowTask')
Ejemplo n.º 6
0
class TTCHood:
    
    def __init__(self, cr):
        self.cr = cr
        self.dnaStore = DNAStorage()
        self.isLoaded = 0
        self.suitEffectEnabled = False
        self.amblight = None
        self.ambNode = None
        self.sky = None
        self.skyTrack = None
        self.skySeq = None
        self.lightTrack = None
        self.skyUtil = SkyUtil()
        
    def createHood(self, loadStorage = 1, AI = 0):
        if loadStorage:
            loadDNAFile(self.dnaStore, "phase_4/dna/storage.dna")
            loadDNAFile(self.dnaStore, "phase_4/dna/storage_TT.dna")
            loadDNAFile(self.dnaStore, "phase_4/dna/storage_TT_sz.dna")
            loadDNAFile(self.dnaStore, "phase_5/dna/storage_town.dna")
            loadDNAFile(self.dnaStore, "phase_5/dna/storage_TT_town.dna")
        self.node = loadDNAFile(self.dnaStore, "phase_4/dna/toontown_central_sz.dna")
        if self.node.getNumParents() == 1:
            self.geom = NodePath(self.node.getParent(0))
            self.geom.reparentTo(hidden)
        else:
            self.geom = hidden.attachNewNode(self.node)
        gsg = base.win.getGsg()
        if gsg:
            self.geom.prepareScene(gsg)
        self.geom.setName('toontown_central')
        
        self.geom.find('**/hill').setTransparency(TransparencyAttrib.MBinary, 1)
        self.createSky("tt")
        base.hoodBGM = base.loadMusic("phase_4/audio/bgm/TC_nbrhood.ogg")
        base.hoodBGM.setVolume(0.25)
        base.hoodBGM.setLoop(True)
        base.hoodBGM.play()
        
        self.clerk_node = render.attach_new_node('clerk_node')
        self.clerk_node.set_pos(-80, -85.57, 0.5)
        self.clerk_node.set_h(165.07)
        
        self.geom.find('**/toontown_central').setCollideMask(BitMask32.allOff())
        self.geom.find('**/coll_sidewalk').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/collision_1').node().setIntoCollideMask(CIGlobals.WallBitmask)
        self.geom.find('**/coll_mainFoolr').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/left_ear').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/right_ear').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_bridge_floor').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_bridge').node().setIntoCollideMask(CIGlobals.WallBitmask)
        self.geom.find('**/coll_r_stair').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_l_stair_2').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_l_stairend_1').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_r_satirend_1').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_plaza').node().setIntoCollideMask(CIGlobals.FloorBitmask)
        self.geom.find('**/coll_hedges').node().setIntoCollideMask(CIGlobals.WallBitmask)
        
        self.coll_list = ['coll_sidewalk', 'collision_1', 'coll_mainFoolr', 'left_ear', 'right_ear', 'coll_bridge_floor', 'coll_bridge', 'coll_r_stair',
                        'coll_l_stair_2', 'coll_l_stairend_1', 'coll_r_stairend_1', 'coll_plaza', 'coll_hedges']
        self.geom.reparentTo(render)
        
        self.telescope = Actor(self.geom.find('**/*animated_prop_HQTelescopeAnimatedProp*'),
                            {"chan": "phase_3.5/models/props/HQ_telescope-chan.bam"}, copy=0)
        self.telescope.reparentTo(self.geom.find('**/*toon_landmark_hqTT*'))
        self.createLights(1, 1, 1)
        
        #if AI:
        #    self.createTrolley()
        
        taskMgr.add(self.telescopeTask, "telescopeTask")
        self.isLoaded = 1
        messenger.send("loadedHood")
        
    def createLights(self, r, g, b, startColor=1, fade=0):
        self.deleteLights()
        self.amblight = AmbientLight("amblight")
        self.amblight.setColor(VBase4(r, g, b, 1))
        self.ambNode = render.attachNewNode(self.amblight)
        render.setLight(self.ambNode)
        if fade:
            self.lightTrack = LerpFunc(self.setLightColor,
                                fromData=startColor,
                                toData=r,
                                duration=2.5,
                                blendType="easeInOut")
            self.lightTrack.start()
            self.skyTrack = LerpColorInterval(self.sky,
                                        color=VBase4(r + 0.4, g + 0.4, b + 0.4, 1.0),
                                        startColor=VBase4(startColor, startColor, startColor, 1.0),
                                        duration=1.5)
            self.skyTrack.start()
            sky = "tt"
            if r < 0.6:
                sky = "br"
            self.skySeq = Sequence(Wait(1.5), Func(self.createSky, sky))
            self.skySeq.start()
            
    def createSky(self, sky):
        self.deleteSky()
        skyPath = "phase_3.5/models/props/" + sky.upper() + "_sky.bam"
        self.sky = loader.loadModel(skyPath)
        self.sky.reparentTo(self.geom)
        self.sky.setPos(9.15527e-005, -1.90735e-006, 2.6226e-006)
        self.sky.setH(-90)
        if sky == "tt":
            self.skyUtil.startSky(self.sky)
            
    def deleteSky(self):
        self.skyUtil.stopSky()
        if self.sky:
            self.sky.removeNode()
            self.sky = None
        if self.lightTrack:
            self.lightTrack.pause()
            self.lightTrack = None
        if self.skyTrack:
            self.skyTrack.pause()
            self.skyTrack = None
        if self.skySeq:
            self.skySeq.pause()
            self.skySeq = None
            
    def setLightColor(self, color):
        self.amblight.setColor(VBase4(color, color, color, 1))
        
    def deleteLights(self):
        if self.ambNode:
            render.clearLight(self.ambNode)
            self.ambNode.removeNode()
            self.ambNode = None
        
    def telescopeTask(self, task):
        if not self.isLoaded:
            return task.done
        self.telescope.play("chan")
        task.delayTime = 12
        return task.again
        
    def enableSuitEffect(self, size):
        self.createLights(0.4, 0.4, 0.4, startColor=1, fade=1)
        
        self.fogNode = Fog("fog")
        self.fogNode.setColor(0.3, 0.3, 0.3)
        self.fogNode.setExpDensity(0.0025)
        render.setFog(self.fogNode)
        
        base.hoodBGM.stop()
        song = random.randint(1, 4)
        base.hoodBGM = base.loadMusic("phase_3.5/audio/bgm/encntr_general_bg.ogg")
        base.hoodBGM.setVolume(0.7)
        base.hoodBGM.setLoop(True)
        base.hoodBGM.play()
        
        self.suitEffectEnabled = True
        
    def bossSpawned(self):
        base.hoodBGM.stop()
        base.hoodBGM = base.loadMusic("phase_7/audio/bgm/encntr_suit_winning_indoor.ogg")
        base.hoodBGM.setVolume(0.7)
        base.hoodBGM.setLoop(True)
        Sequence(Wait(0.5), Func(base.hoodBGM.play)).start()
        
    def disableSuitEffect(self):
        self.createLights(1, 1, 1)
        self.createSky("tt")
        #render.clearFog()
        
        base.hoodBGM.stop()
        base.hoodBGM = base.loadMusic("phase_4/audio/bgm/TC_nbrhood.ogg")
        base.hoodBGM.setVolume(0.25)
        base.hoodBGM.setLoop(True)
        base.hoodBGM.play()
        
        self.suitEffectEnabled = False
        
    def unloadHood(self):
        self.isLoaded = 0
        if self.suitEffectEnabled:
            self.disableSuitEffect()
        self.deleteSky()
        self.deleteLights()
        self.geom.remove()
        self.clerk_node.remove_node()
        base.hoodBGM.stop()