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
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')
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')
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()