def makeNew(self, pos, nor, parent = None): """Makes a new bullet hole.""" if parent == None: parent = self.container else: # Add a subnode to the parent, if it's not already there child = parent.find('bullet-holes') if child.isEmpty(): parent = parent.attachNewNode('bullet-holes') else: parent = child newhole = NodePath(self.card.generate()) newhole.reparentTo(parent) newhole.lookAt(render, Point3(newhole.getPos(render) - nor)) newhole.setR(newhole, random() * 360.0) newhole.setPos(render, pos) # Offset it a little to avoid z-fighting # Increase this value if you still see it. newhole.setY(newhole, -.001 - random() * 0.01) del newhole # We don't want one batch per bullet hole, so flatten it. # This could be made smarter to preserve culling, but # I have yet to see a performance loss. # The clearTexture() is a necessary hack. parent.clearTexture() parent.flattenStrong() parent.setTexture(self.texture) parent.setTransparency(TransparencyAttrib.MDual) parent.setShaderOff(1) parent.hide(BitMask32.bit(2)) # Invisible to volumetric lighting camera (speedup) parent.hide(BitMask32.bit(3)) # Invisible to shadow cameras (speedup)
def makeNew(self, pos, nor, parent=None): """Makes a new bullet hole.""" if parent == None: parent = self.container else: # Add a subnode to the parent, if it's not already there child = parent.find('bullet-holes') if child.isEmpty(): parent = parent.attachNewNode('bullet-holes') else: parent = child newhole = NodePath(self.card.generate()) newhole.reparentTo(parent) newhole.lookAt(render, Point3(newhole.getPos(render) - nor)) newhole.setR(newhole, random() * 360.0) newhole.setPos(render, pos) # Offset it a little to avoid z-fighting # Increase this value if you still see it. newhole.setY(newhole, -.001 - random() * 0.01) del newhole # We don't want one batch per bullet hole, so flatten it. # This could be made smarter to preserve culling, but # I have yet to see a performance loss. # The clearTexture() is a necessary hack. parent.clearTexture() parent.flattenStrong() parent.setTexture(self.texture) parent.setTransparency(TransparencyAttrib.MDual) parent.setShaderOff(1) parent.hide(BitMask32.bit( 2)) # Invisible to volumetric lighting camera (speedup) parent.hide(BitMask32.bit(3)) # Invisible to shadow cameras (speedup)
class Asteroid(object): def __init__(self, name="Asteroid"): self.name = name self.nodepath = NodePath(PandaNode("Asteroid" + name)) self.contents = {} self.levels = {} @classmethod def make_spheroid(cls, tile_type, radius=30, name="Asteroid"): self = cls(name) z_scale = 4 z_len = int(radius / z_scale) for z in range(-z_len, z_len): for x in range(-radius, radius): for y in range(-radius, radius): dist = ((z * z_scale) ** 2 + x ** 2 + y ** 2) ** 0.5 if dist < radius: self.update(x, y, z, tile_type()) elif dist < radius + 3: self.update(x, y, z, Empty()) self.redraw() return self def update(self, x, y, level, tile_type): pos = (x, y, level) self.contents[pos] = tile_type if level not in self.levels: self.levels[level] = Level(self, level) self.levels[level].nodepath.setPos(0, level * LEVEL_SPACING, 0) self.levels[level].update(x, y, tile_type.texture) def redraw(self): for level in self.levels.values(): level.redraw() def get_pos(self, x, y, level): "convert asteroid coordinates to position" pos_x, pos_y, pos_z = self.nodepath.getPos() return (pos_x + TILE_SIZE * (x + 0.5), pos_y + level * LEVEL_SPACING, pos_z + TILE_SIZE * (y + 0.5)) def get(self, x, y, level): return self.contents.get((x, y, level)) def get_collision_pos(self, collision): point3 = collision.getSurfacePoint(self.nodepath) x = int(math.floor(point3.getX() / TILE_SIZE)) y = int(math.floor(point3.getZ() / TILE_SIZE)) z = int(round(point3.getY() / LEVEL_SPACING)) return x, y, z
class PartyCog(FSM): notify = directNotify.newCategory("PartyCog") HpTextGenerator = TextNode("HpTextGenerator") hpText = None height = 7 def __init__(self, parentNode, id, bounceSpeed=3, bounceHeight=1, rotateSpeed=1, heightShift=1, xMoveSpeed=0, xMoveDistance=0, bounceOffset=0): self.id = id FSM.__init__(self, "PartyCogFSM-%d" % self.id) self.showFacingStatus = False self.xMoveSpeed = xMoveSpeed self.xMoveDistance = xMoveDistance self.heightShift = heightShift self.bounceSpeed = bounceSpeed self.bounceHeight = bounceHeight self.rotateSpeed = rotateSpeed self.parentNode = parentNode self.bounceOffset = bounceOffset self.hitInterval = None self.kaboomTrack = None self.resetRollIval = None self.netTimeSentToStartByHit = 0 self.load() self.request("Down") def load(self): self.root = NodePath("PartyCog-%d" % self.id) self.root.reparentTo(self.parentNode) path = "phase_13/models/parties/cogPinata_" self.actor = Actor( path + "actor", { "idle": path + "idle_anim", "down": path + "down_anim", "up": path + "up_anim", "bodyHitBack": path + "bodyHitBack_anim", "bodyHitFront": path + "bodyHitFront_anim", "headHitBack": path + "headHitBack_anim", "headHitFront": path + "headHitFront_anim", }) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode("temphead") self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode("PartyCog-%d-Body-Collision" % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode("PartyCog-%d-Head-Collision" % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) # Cog's Left Arm self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode("PartyCog-%d-Arm1-Collision" % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) # Cog's Right Arm self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode("PartyCog-%d-Arm2-Collision" % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound( 'AA_wholepie_only.mp3') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.mp3') self.hole = loader.loadModel("phase_13/models/parties/cogPinataHole") self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin("ground", 3) self.hole.reparentTo(self.parentNode) def unload(self): self.request("Off") self.clearHitInterval() if self.hole is not None: self.hole.removeNode() self.hole = None if self.actor is not None: self.actor.cleanup() self.actor.removeNode() self.actor = None if self.root is not None: self.root.removeNode() self.root = None if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboomTrack = None if self.resetRollIval is not None and self.resetRollIval.isPlaying(): self.resetRollIval.finish() self.resetRollIval = None if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.finish() self.hitInterval = None del self.upSound del self.pieHitSound #=============================================================================== # FSM States #=============================================================================== def enterStatic(self): pass def exitStatic(self): pass def enterActive(self, startTime): self.root.setR(0.0) updateTask = Task.Task(self.updateTask) updateTask.startTime = startTime taskMgr.add(updateTask, "PartyCog.update-%d" % self.id) def exitActive(self): taskMgr.remove("PartyCog.update-%d" % self.id) taskMgr.remove("PartyCog.bounceTask-%d" % self.id) self.clearHitInterval() self.resetRollIval = self.root.hprInterval(0.5, Point3( self.root.getH(), 0.0, 0.0), blendType="easeInOut") self.resetRollIval.start() self.actor.stop() def enterDown(self): if self.oldState == "Off": downAnimControl = self.actor.getAnimControl("down") self.actor.pose("down", downAnimControl.getNumFrames() - 1) return self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType="easeIn"), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, "down", loop=0), ), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType="easeOut"), ) self.hitInterval.start() def exitDown(self): self.root.setR(0.0) self.root.setH(0.0) self.targetDistance = 0.0 self.targetFacing = 0.0 self.currentT = 0.0 self.setAlongSpline(0.0) self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType="easeIn"), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, "up", loop=0), ), Func(self.actor.loop, "idle"), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType="easeOut"), ) self.hitInterval.start() def filterDown(self, request, args): if request == "Down": return None else: return self.defaultFilter(request, args) #------------------------------------------------------------------------------ def setEndPoints(self, start, end, amplitude=1.7): self.sinAmplitude = amplitude self.sinPeriod = (end.getX() - start.getX()) / 2 self.sinDisplacement = start.getY() self.startPoint = start self.endPoint = end self.currentT = 0.0 self.targetDistance = 0.0 self.currentFacing = 0.0 self.targetFacing = 0.0 self.setAlongSpline(self.currentT) self.hole.setPos(self.root.getPos()) self.hole.setZ(0.02) def rockBackAndForth(self, task): t = task.startTime + task.time angle = math.sin(t) * 20.0 self.root.setR(angle) # if self.id == 0: # print angle return task.cont def updateDistance(self, distance): self.targetDistance = clamp(distance, -1.0, 1.0) def updateTask(self, task): self.rockBackAndForth(task) if self.targetDistance > self.currentT: self.currentT += min(0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) elif self.targetDistance < self.currentT: self.currentT += max(-0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) if self.currentT < 0.0: self.targetFacing = -90.0 elif self.currentT > 0.0: self.targetFacing = 90.0 else: self.targetFacing = 0.0 if self.targetFacing > self.currentFacing: self.currentFacing += min(10, self.targetFacing - self.currentFacing) elif self.targetFacing < self.currentFacing: self.currentFacing += max(-10, self.targetFacing - self.currentFacing) self.root.setH(self.currentFacing) return task.cont def setAlongSpline(self, t): t = t + 1.0 dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0 x = self.startPoint.getX() + t * dist y = self.startPoint.getY() - math.sin( t * 2 * math.pi) * self.sinAmplitude self.root.setPos(x, y, 0) def startBounce(self): taskMgr.add(self.bounce, "PartyCog.bounceTask-%d" % self.id) def bounce(self, task): #self.root.setH(self.root.getH() - self.rotateSpeed) self.root.setZ((math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight) + self.heightShift) return task.cont def setPos(self, position): self.root.setPos(position) def respondToPieHit(self, timestamp, position, hot=False, direction=1.0): """The toon hit us, react appropriately.""" assert (self.notify.debugStateCall(self)) if self.netTimeSentToStartByHit < timestamp: self.__showSplat(position, direction, hot) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: #self.notify.debug('localStamp = %s, lastLocalTimeStampFromAI=%s, ignoring respondToPieHit' % (localStamp, self.lastLocalTimeStampFromAI)) self.notify.debug( 'respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearHitInterval(self): if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.clearToInitial() def __showSplat(self, position, direction, hot=False): """Show the splat graphic and sound.""" if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.clearHitInterval() splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splat.reparentTo(render) self.splat.setPos(self.root, position) self.splat.setAlphaScale(1.0) if not direction == 1.0: #self.splat.setColorScale(Vec4(0.0, 0.0, 50.0, 1.0)) self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0]) if self.currentFacing > 0.0: facing = "HitFront" else: facing = "HitBack" else: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1]) #self.splat.setColorScale(Vec4(1.0, 0.6, 0.08, 1.0)) if self.currentFacing > 0.0: facing = "HitBack" else: facing = "HitFront" if hot: targetscale = 0.75 part = "head" else: targetscale = 0.5 part = "body" def setSplatAlpha(amount): self.splat.setAlphaScale(amount) self.hitInterval = Sequence( ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, "idle"), ) self.hitInterval.start() self.kaboomTrack = Parallel( SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence( Func(self.splat.showThrough), Parallel( Sequence( LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType="easeOut"), Wait(0.175), ), Sequence( Wait(0.1), LerpFunc( setSplatAlpha, duration=1.0, #0.4, fromData=1.0, toData=0.0, blendType="easeOut"))), Func(self.splat.cleanup), Func(self.splat.removeNode), )) self.kaboomTrack.start() def showHitScore(self, number, scale=1): """ Shows the hit score. Borrowed from otp.avatar.DistributedAvatar.showHpText """ if number <= 0: return # Get rid of the number if it is already there. if self.hpText: self.hideHitScore() # Set the font self.HpTextGenerator.setFont(ToontownGlobals.getSignFont()) # Show both negative and positive signs if number < 0: self.HpTextGenerator.setText(str(number)) else: self.HpTextGenerator.setText("+" + str(number)) # No shadow self.HpTextGenerator.clearShadow() # Center the number self.HpTextGenerator.setAlign(TextNode.ACenter) # Red, always #if number < 0: r = 1 #0.9 g = 1 #0 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() # Put the hpText over the head of the avatar self.hpText = render.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) # Make sure it is a billboard self.hpText.setBillboardPointEye() # Render it after other things in the scene. self.hpText.setBin('fixed', 100) # Initial position ... Center of the body... the "tan tien" self.hpText.setPos(self.root, 0, 0, self.height / 2) # Black magic from the early days of Panda3D, later replaced by a Sequence seq = Task.sequence( # Fly the number out of the character self.hpText.lerpPos(Point3( self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), 0.25, blendType='easeOut'), Task.pause(0.25), # Fade the number self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1), # Get rid of the number Task.Task(self.__hideHitScoreTask)) taskMgr.add(seq, "PartyCogHpText" + str(self.id)) def __hideHitScoreTask(self, task): self.hideHitScore() return Task.done def hideHitScore(self): if self.hpText: taskMgr.remove("PartyCogHpText" + str(self.id)) self.hpText.removeNode() self.hpText = None def getHeadLocation(self): (self.actor.getJoints(jointName="head")[0]).getNetTransform( self.temp_transform) self.head_locator.setMat(self.temp_transform) #print self.head_locator.getZ() return self.head_locator.getZ(self.root)
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ((levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2])) self._lookAtZ = self._toon.getHeight( ) + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath('CamParent') self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath('CameraLookAt') self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode('CameraToonRay') camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask(OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath('trans') self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin('fixed', 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / ( maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[ 1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E**(dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr( smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find('col_') >= 0: np = entry.getIntoNodePath().getParent() if not np in nodesInBetween: nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if np in self._betweenCamAndToon: del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').hide() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find('lightFixture') >= 0: if not np.find('**/*floor_mesh').isEmpty(): np.find('**/*floor_mesh').show() elif np.getName().find('platform') >= 0: if not np.find('**/*Floor').isEmpty(): np.find('**/*Floor').show() self._betweenCamAndToon = nodesInBetween
class CogdoFlyingCameraManager: def __init__(self, cam, parent, player, level): self._toon = player.toon self._camera = cam self._parent = parent self._player = player self._level = level self._enabled = False def enable(self): if self._enabled: return self._toon.detachCamera() self._prevToonY = 0.0 levelBounds = self._level.getBounds() l = Globals.Camera.LevelBoundsFactor self._bounds = ( (levelBounds[0][0] * l[0], levelBounds[0][1] * l[0]), (levelBounds[1][0] * l[1], levelBounds[1][1] * l[1]), (levelBounds[2][0] * l[2], levelBounds[2][1] * l[2]), ) self._lookAtZ = self._toon.getHeight() + Globals.Camera.LookAtToonHeightOffset self._camParent = NodePath("CamParent") self._camParent.reparentTo(self._parent) self._camParent.setPos(self._toon, 0, 0, 0) self._camParent.setHpr(180, Globals.Camera.Angle, 0) self._camera.reparentTo(self._camParent) self._camera.setPos(0, Globals.Camera.Distance, 0) self._camera.lookAt(self._toon, 0, 0, self._lookAtZ) self._cameraLookAtNP = NodePath("CameraLookAt") self._cameraLookAtNP.reparentTo(self._camera.getParent()) self._cameraLookAtNP.setPosHpr(self._camera.getPos(), self._camera.getHpr()) self._levelBounds = self._level.getBounds() self._enabled = True self._frozen = False self._initCollisions() def _initCollisions(self): self._camCollRay = CollisionRay() camCollNode = CollisionNode("CameraToonRay") camCollNode.addSolid(self._camCollRay) camCollNode.setFromCollideMask( OTPGlobals.WallBitmask | OTPGlobals.CameraBitmask | ToontownGlobals.FloorEventBitmask | ToontownGlobals.CeilingBitmask ) camCollNode.setIntoCollideMask(0) self._camCollNP = self._camera.attachNewNode(camCollNode) self._camCollNP.show() self._collOffset = Vec3(0, 0, 0.5) self._collHandler = CollisionHandlerQueue() self._collTrav = CollisionTraverser() self._collTrav.addCollider(self._camCollNP, self._collHandler) self._betweenCamAndToon = {} self._transNP = NodePath("trans") self._transNP.reparentTo(render) self._transNP.setTransparency(True) self._transNP.setAlphaScale(Globals.Camera.AlphaBetweenToon) self._transNP.setBin("fixed", 10000) def _destroyCollisions(self): self._collTrav.removeCollider(self._camCollNP) self._camCollNP.removeNode() del self._camCollNP del self._camCollRay del self._collHandler del self._collOffset del self._betweenCamAndToon self._transNP.removeNode() del self._transNP def freeze(self): self._frozen = True def unfreeze(self): self._frozen = False def disable(self): if not self._enabled: return self._destroyCollisions() self._camera.wrtReparentTo(render) self._cameraLookAtNP.removeNode() del self._cameraLookAtNP self._camParent.removeNode() del self._camParent del self._prevToonY del self._lookAtZ del self._bounds del self._frozen self._enabled = False def update(self, dt=0.0): self._updateCam(dt) self._updateCollisions() def _updateCam(self, dt): toonPos = self._toon.getPos() camPos = self._camParent.getPos() x = camPos[0] z = camPos[2] toonWorldX = self._toon.getX(render) maxX = Globals.Camera.MaxSpinX toonWorldX = clamp(toonWorldX, -1.0 * maxX, maxX) spinAngle = Globals.Camera.MaxSpinAngle * toonWorldX * toonWorldX / (maxX * maxX) newH = 180.0 + spinAngle self._camParent.setH(newH) spinAngle = spinAngle * (pi / 180.0) distBehindToon = Globals.Camera.SpinRadius * cos(spinAngle) distToRightOfToon = Globals.Camera.SpinRadius * sin(spinAngle) d = self._camParent.getX() - clamp(toonPos[0], *self._bounds[0]) if abs(d) > Globals.Camera.LeewayX: if d > Globals.Camera.LeewayX: x = toonPos[0] + Globals.Camera.LeewayX else: x = toonPos[0] - Globals.Camera.LeewayX x = self._toon.getX(render) + distToRightOfToon boundToonZ = min(toonPos[2], self._bounds[2][1]) d = z - boundToonZ if d > Globals.Camera.MinLeewayZ: if self._player.velocity[2] >= 0 and toonPos[1] != self._prevToonY or self._player.velocity[2] > 0: z = boundToonZ + d * INVERSE_E ** (dt * Globals.Camera.CatchUpRateZ) elif d > Globals.Camera.MaxLeewayZ: z = boundToonZ + Globals.Camera.MaxLeewayZ elif d < -Globals.Camera.MinLeewayZ: z = boundToonZ - Globals.Camera.MinLeewayZ if self._frozen: y = camPos[1] else: y = self._toon.getY(render) - distBehindToon self._camParent.setPos(x, smooth(camPos[1], y), smooth(camPos[2], z)) if toonPos[2] < self._bounds[2][1]: h = self._cameraLookAtNP.getH() if d >= Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._toon, 0, 0, self._lookAtZ) elif d <= -Globals.Camera.MinLeewayZ: self._cameraLookAtNP.lookAt(self._camParent, 0, 0, self._lookAtZ) self._cameraLookAtNP.setHpr(h, self._cameraLookAtNP.getP(), 0) self._camera.setHpr(smooth(self._camera.getHpr(), self._cameraLookAtNP.getHpr())) self._prevToonY = toonPos[1] def _updateCollisions(self): pos = self._toon.getPos(self._camera) + self._collOffset self._camCollRay.setOrigin(pos) direction = -Vec3(pos) direction.normalize() self._camCollRay.setDirection(direction) self._collTrav.traverse(render) nodesInBetween = {} if self._collHandler.getNumEntries() > 0: self._collHandler.sortEntries() for entry in self._collHandler.getEntries(): name = entry.getIntoNode().getName() if name.find("col_") >= 0: np = entry.getIntoNodePath().getParent() if not nodesInBetween.has_key(np): nodesInBetween[np] = np.getParent() for np in nodesInBetween.keys(): if self._betweenCamAndToon.has_key(np): del self._betweenCamAndToon[np] else: np.setTransparency(True) np.wrtReparentTo(self._transNP) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").hide() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").hide() for np, parent in self._betweenCamAndToon.items(): np.wrtReparentTo(parent) np.setTransparency(False) if np.getName().find("lightFixture") >= 0: if not np.find("**/*floor_mesh").isEmpty(): np.find("**/*floor_mesh").show() elif np.getName().find("platform") >= 0: if not np.find("**/*Floor").isEmpty(): np.find("**/*Floor").show() self._betweenCamAndToon = nodesInBetween
class PartyCog(FSM): notify = directNotify.newCategory('PartyCog') HpTextGenerator = TextNode('HpTextGenerator') hpText = None height = 7 def __init__(self, parentNode, id, bounceSpeed = 3, bounceHeight = 1, rotateSpeed = 1, heightShift = 1, xMoveSpeed = 0, xMoveDistance = 0, bounceOffset = 0): self.id = id FSM.__init__(self, 'PartyCogFSM-%d' % self.id) self.showFacingStatus = False self.xMoveSpeed = xMoveSpeed self.xMoveDistance = xMoveDistance self.heightShift = heightShift self.bounceSpeed = bounceSpeed self.bounceHeight = bounceHeight self.rotateSpeed = rotateSpeed self.parentNode = parentNode self.bounceOffset = bounceOffset self.hitInterval = None self.kaboomTrack = None self.resetRollIval = None self.netTimeSentToStartByHit = 0 self.load() self.request('Down') return def load(self): self.root = NodePath('PartyCog-%d' % self.id) self.root.reparentTo(self.parentNode) path = 'phase_13/models/parties/cogPinata_' self.actor = Actor(path + 'actor', {'idle': path + 'idle_anim', 'down': path + 'down_anim', 'up': path + 'up_anim', 'bodyHitBack': path + 'bodyHitBack_anim', 'bodyHitFront': path + 'bodyHitFront_anim', 'headHitBack': path + 'headHitBack_anim', 'headHitFront': path + 'headHitFront_anim'}) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode('temphead') self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound('AA_wholepie_only.ogg') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg') self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole') self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin('ground', 3) self.hole.reparentTo(self.parentNode) def unload(self): self.request('Off') self.clearHitInterval() if self.hole is not None: self.hole.removeNode() self.hole = None if self.actor is not None: self.actor.cleanup() self.actor.removeNode() self.actor = None if self.root is not None: self.root.removeNode() self.root = None if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboomTrack = None if self.resetRollIval is not None and self.resetRollIval.isPlaying(): self.resetRollIval.finish() self.resetRollIval = None if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.finish() self.hitInterval = None del self.upSound del self.pieHitSound return def enterStatic(self): pass def exitStatic(self): pass def enterActive(self, startTime): self.root.setR(0.0) updateTask = Task.Task(self.updateTask) updateTask.startTime = startTime taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id) def exitActive(self): taskMgr.remove('PartyCog.update-%d' % self.id) taskMgr.remove('PartyCog.bounceTask-%d' % self.id) self.clearHitInterval() self.resetRollIval = self.root.hprInterval(0.5, Point3(self.root.getH(), 0.0, 0.0), blendType='easeInOut') self.resetRollIval.start() self.actor.stop() def enterDown(self): if self.oldState == 'Off': downAnimControl = self.actor.getAnimControl('down') self.actor.pose('down', downAnimControl.getNumFrames() - 1) return self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence(LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel(SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'down', loop=0)), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def exitDown(self): self.root.setR(0.0) self.root.setH(0.0) self.targetDistance = 0.0 self.targetFacing = 0.0 self.currentT = 0.0 self.setAlongSpline(0.0) self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence(LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel(SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'up', loop=0)), Func(self.actor.loop, 'idle'), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def filterDown(self, request, args): if request == 'Down': return None else: return self.defaultFilter(request, args) return None def setEndPoints(self, start, end, amplitude = 1.7): self.sinAmplitude = amplitude self.sinPeriod = (end.getX() - start.getX()) / 2 self.sinDisplacement = start.getY() self.startPoint = start self.endPoint = end self.currentT = 0.0 self.targetDistance = 0.0 self.currentFacing = 0.0 self.targetFacing = 0.0 self.setAlongSpline(self.currentT) self.hole.setPos(self.root.getPos()) self.hole.setZ(0.02) def rockBackAndForth(self, task): t = task.startTime + task.time angle = math.sin(t) * 20.0 self.root.setR(angle) return task.cont def updateDistance(self, distance): self.targetDistance = clamp(distance, -1.0, 1.0) def updateTask(self, task): self.rockBackAndForth(task) if self.targetDistance > self.currentT: self.currentT += min(0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) elif self.targetDistance < self.currentT: self.currentT += max(-0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) if self.currentT < 0.0: self.targetFacing = -90.0 elif self.currentT > 0.0: self.targetFacing = 90.0 else: self.targetFacing = 0.0 if self.targetFacing > self.currentFacing: self.currentFacing += min(10, self.targetFacing - self.currentFacing) elif self.targetFacing < self.currentFacing: self.currentFacing += max(-10, self.targetFacing - self.currentFacing) self.root.setH(self.currentFacing) return task.cont def setAlongSpline(self, t): t = t + 1.0 dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0 x = self.startPoint.getX() + t * dist y = self.startPoint.getY() - math.sin(t * 2 * math.pi) * self.sinAmplitude self.root.setPos(x, y, 0) def startBounce(self): taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id) def bounce(self, task): self.root.setZ(math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight + self.heightShift) return task.cont def setPos(self, position): self.root.setPos(position) def respondToPieHit(self, timestamp, position, hot = False, direction = 1.0): if self.netTimeSentToStartByHit < timestamp: self.__showSplat(position, direction, hot) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: self.notify.debug('respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearHitInterval(self): if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.clearToInitial() return def __showSplat(self, position, direction, hot = False): if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.clearHitInterval() splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splat.reparentTo(render) self.splat.setPos(self.root, position) self.splat.setAlphaScale(1.0) if not direction == 1.0: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0]) if self.currentFacing > 0.0: facing = 'HitFront' else: facing = 'HitBack' else: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1]) if self.currentFacing > 0.0: facing = 'HitBack' else: facing = 'HitFront' if hot: targetscale = 0.75 part = 'head' else: targetscale = 0.5 part = 'body' def setSplatAlpha(amount): self.splat.setAlphaScale(amount) self.hitInterval = Sequence(ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, 'idle')) self.hitInterval.start() self.kaboomTrack = Parallel(SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence(Func(self.splat.showThrough), Parallel(Sequence(LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType='easeOut'), Wait(0.175)), Sequence(Wait(0.1), LerpFunc(setSplatAlpha, duration=1.0, fromData=1.0, toData=0.0, blendType='easeOut'))), Func(self.splat.cleanup), Func(self.splat.removeNode))) self.kaboomTrack.start() return def showHitScore(self, number, scale = 1): if number <= 0: return if self.hpText: self.hideHitScore() self.HpTextGenerator.setFont(ToontownGlobals.getSignFont()) if number < 0: self.HpTextGenerator.setText(str(number)) else: self.HpTextGenerator.setText('+' + str(number)) self.HpTextGenerator.clearShadow() self.HpTextGenerator.setAlign(TextNode.ACenter) r = 1 g = 1 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() self.hpText = render.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) self.hpText.setBillboardPointEye() self.hpText.setBin('fixed', 100) self.hpText.setPos(self.root, 0, 0, self.height / 2) seq = Sequence(self.hpText.posInterval(0.25, Point3(self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), blendType='easeOut'), Wait(0.25), self.hpText.colorInterval(0.1, Vec4(r, g, b, 0)), Func(self.__hideHitScore)) seq.start() def hideHitScore(self): if self.hpText: taskMgr.remove('PartyCogHpText' + str(self.id)) self.hpText.removeNode() self.hpText = None return def getHeadLocation(self): self.actor.getJoints(jointName='head')[0].getNetTransform(self.temp_transform) self.head_locator.setMat(self.temp_transform) return self.head_locator.getZ(self.root)
class itemClass(objectIdClass): def __init__( self, ground ): objectIdClass.__init__( self ) self.ground = ground # create collision object pass # create position node self.positionNp = NodePath( 'positionNp%s' % self.objectId ) #self.positionNp.reparentTo( render ) # load model self.modelNp = loader.loadModelCopy( 'data/models/box.egg' ) self.modelNp.reparentTo( self.positionNp ) self.setPos( Vec3(0,0,0) ) self.create3dObject() def destroy( self ): objectIdClass.destroy( self ) def create3dObject( self ): self.reparentTo( render ) #self.positionNp.show() self.makePickable( self.modelNp ) def setPos( self, position ): xPos, yPos, zPos = position.getX(), position.getY(), position.getZ() zGround = self.ground.get_elevation( [xPos, yPos] ) zPos = zGround #if zPos < zGround: # zPos = zGround return self.positionNp.setPos( Vec3(xPos, yPos, zPos) ) def getPos( self, relativeTo=None ): return self.positionNp.getPos( relativeTo ) def setHpr( self, hpr ): return self.positionNp.setHpr( hpr ) def reparentTo( self, object ): return self.positionNp.reparentTo( object ) def wrtReparentTo( self, object ): return self.positionNp.wrtReparentTo( object ) def putOnGround( self, xyPos ): return self.ground.get_elevation( xyPos ) def destroy3dObject( self ): self.positionNp.detachNode() #self.positionNp.hide() # destroy collision object # destroy shape #pass def create2dObject( self ): pass def destroy2dObject( self ): pass
class Game(ShowBase): ''' ''' def __init__(self): ''' ''' # loadPrcFileData("", "want-pstats 1\n pstats-host 127.0.0.1\n pstats-tasks 1\n task-timer-verbose 1") # loadPrcFileData("", "pstatshost 192.168.220.121") ShowBase.__init__(self) # PStatClient.connect() #activate to start performance measuring with pstats base.setFrameRateMeter(True) # Show the Framerate # base.toggleWireframe() self.accept("space", self.onSpace) self.accept("tab", self.onTab) self.startGame() self.cam_on = True # ----------------------------------------------------------------- # ----------------------------------------------------------------- def onSpace(self, evt=None): ''' ''' if self.trackmesh2.getParent() == render: self.trackmesh.reparentTo(render) self.trackmesh2.detachNode() else: self.trackmesh.detachNode() self.trackmesh2.reparentTo(render) # base.toggleWireframe() # ----------------------------------------------------------------- def startGame(self): ''' Start the game ''' # Create the Track self.track = trackgen3d.Track3d(1000, 800, 600, 200, 5) self.trackmesh = NodePath(self.track.createRoadMesh()) tex = loader.loadTexture('data/textures/street.png') self.trackmesh.setTexture(tex) self.trackmesh2 = NodePath(self.track.createUninterpolatedRoadMesh()) self.trackmesh2.setTexture(tex) # nodePath.setTwoSided(True) self.trackmesh.reparentTo(render) # LICHT self.plight = PointLight('kkkplight') self.plight.setColor(VBase4(21, 0, 0, 1)) self.plnp = NodePath(self.plight) self.plnp.reparentTo(render) self.plnp.setPos(0, 0, 2000) self.plnp.node().setAttenuation(Point3(0, 0, 1)) self.plnp.setScale(.5, .5, .5) # self.plnp.setHpr(0,-90,0) # print plight.getAttenuation() # plnp.setPos(-10, -800, 20) render.setLight(self.plnp) self.accept("w", self.setA, [100]) self.accept("s", self.setA, [-10]) self.accept("e", self.setB, [10]) self.accept("d", self.setB, [-10]) self.accept("r", self.setC, [100]) self.accept("f", self.setC, [-100]) self.accept("z", self.setRotation, [0, 10]) self.accept("h", self.setRotation, [0, -10]) self.accept("u", self.setRotation, [1, 10]) self.accept("j", self.setRotation, [1, -10]) self.accept("i", self.setRotation, [2, 10]) self.accept("k", self.setRotation, [2, -10]) self.accept("n", self.setExponent, [-50]) self.accept("m", self.setExponent, [50]) # load our model tron = loader.loadModel("data/models/vehicles/vehicle02") self.tron = tron # self.tron.loadAnims({"running":"models/tron_anim"}) tron.reparentTo(render) tron.setPos(0, 0, 15) tron.setHpr(0, -90, 0) # nodePath2 = self.render.attachNewNode(self.track.createBorderLeftMesh()) # tex2 = loader.loadTexture('data/textures/border.png') # nodePath2.setTexture(tex2) # # nodePath3 = self.render.attachNewNode(self.track.createBorderRightMesh()) # tex2 = loader.loadTexture('data/textures/border.png') # nodePath3.setTexture(tex2) ring = loader.loadModel("data/models/ring.egg") ring.setScale(24) ring.setZ(-25) ring.setY(100) ring.setTransparency(TransparencyAttrib.MAlpha) ring.reparentTo(render) # Load the Lights ambilight = AmbientLight('ambilight') ambilight.setColor(VBase4(0.8, 0.8, 0.8, 1)) render.setLight(render.attachNewNode(ambilight)) # ----------------------------------------------------------------- def setA(self, val): ''' ''' tpos = self.tron.getPos() tpos[0] += val self.tron.setPos(tpos) pos = self.plnp.getPos() pos[0] += val print(pos) self.plnp.setPos(pos) def setB(self, val): ''' ''' tpos = self.tron.getPos() tpos[1] += val self.tron.setPos(tpos) pos = self.plnp.getPos() pos[1] += val print(pos) self.plnp.setPos(pos) def setC(self, val): ''' ''' tpos = self.tron.getPos() tpos[2] += val self.tron.setPos(tpos) pos = self.plnp.getPos() pos[2] += val print(pos) self.plnp.setPos(pos) def setRotation(self, var, val): ''' ''' hpr = self.plnp.getHpr() hpr[var] += val print(("hpr", hpr)) self.plnp.setHpr(hpr) def setExponent(self, val): ''' ''' val = self.plight.getExponent() + val print(val) self.plight.setExponent(val) def onTab(self): ''' ''' if self.cam_on: base.disableMouse() base.camera.setPos(-293.807, 91.2993, 3984.4) base.camera.setHpr(-76.0078, -85.4581, -71.7315) # base.camera.setPos(39.3053, -376.205, -3939.89) # base.camera.setHpr(5.33686, -82.7432, 8.26239) # print base.camera.getPos(), base.camera.getHpr() self.cam_on = False else: base.enableMouse() self.cam_on = True
class HtmlView(DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory('HtmlView') useHalfTexture = base.config.GetBool('news-half-texture', 0) def __init__(self, parent=aspect2d): global GlobalWebcore self.parent = parent self.mx = 0 self.my = 0 self.htmlFile = 'index.html' self.transparency = False if GlobalWebcore: pass else: GlobalWebcore = AwWebCore(AwWebCore.LOGVERBOSE, True, AwWebCore.PFBGRA) GlobalWebcore.setBaseDirectory('.') for errResponse in xrange(400, 600): GlobalWebcore.setCustomResponsePage(errResponse, 'error.html') self.webView = GlobalWebcore.createWebView(WEB_WIDTH, WEB_HEIGHT, self.transparency, False, 70) frameName = '' inGameNewsUrl = self.getInGameNewsUrl() self.imgBuffer = array.array('B') for i in xrange(WEB_WIDTH * WEB_HEIGHT): self.imgBuffer.append(0) self.imgBuffer.append(0) self.imgBuffer.append(0) self.imgBuffer.append(255) if self.useHalfTexture: self.leftBuffer = array.array('B') for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT): self.leftBuffer.append(0) self.leftBuffer.append(0) self.leftBuffer.append(0) self.leftBuffer.append(255) self.rightBuffer = array.array('B') for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT): self.rightBuffer.append(0) self.rightBuffer.append(0) self.rightBuffer.append(0) self.rightBuffer.append(255) self.setupTexture() if self.useHalfTexture: self.setupHalfTextures() self.accept('mouse1', self.mouseDown, [AwWebView.LEFTMOUSEBTN]) self.accept('mouse3', self.mouseDown, [AwWebView.RIGHTMOUSEBTN]) self.accept('mouse1-up', self.mouseUp, [AwWebView.LEFTMOUSEBTN]) self.accept('mouse3-up', self.mouseUp, [AwWebView.RIGHTMOUSEBTN]) def getInGameNewsUrl(self): result = base.config.GetString( 'fallback-news-url', 'http://cdn.toontown.disney.go.com/toontown/en/gamenews/') override = base.config.GetString('in-game-news-url', '') if override: self.notify.info( 'got an override url, using %s for in a game news' % override) result = override else: try: launcherUrl = base.launcher.getValue('GAME_IN_GAME_NEWS_URL', '') if launcherUrl: result = launcherUrl self.notify.info( 'got GAME_IN_GAME_NEWS_URL from launcher using %s' % result) else: self.notify.info( 'blank GAME_IN_GAME_NEWS_URL from launcher, using %s' % result) except: self.notify.warning( 'got exception getting GAME_IN_GAME_NEWS_URL from launcher, using %s' % result) return result def setupTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT) cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1) bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1) cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1)) card = cm.generate() self.quad = NodePath(card) self.quad.reparentTo(self.parent) self.guiTex = Texture('guiTex') self.guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.guiTex.setMinfilter(Texture.FTLinear) self.guiTex.setKeepRamImage(True) self.guiTex.makeRamImage() self.guiTex.setWrapU(Texture.WMRepeat) self.guiTex.setWrapV(Texture.WMRepeat) ts = TextureStage('webTS') self.quad.setTexture(ts, self.guiTex) self.quad.setTexScale(ts, 1.0, -1.0) self.quad.setTransparency(0) self.quad.setTwoSided(True) self.quad.setColor(1.0, 1.0, 1.0, 1.0) self.calcMouseLimits() def setupHalfTextures(self): self.setupLeftTexture() self.setupRightTexture() self.fullPnmImage = PNMImage(WEB_WIDTH, WEB_HEIGHT, 4) self.leftPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4) self.rightPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4) def setupLeftTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT) cm.setFrame(-htmlWidth / 2.0, 0, -htmlHeight / 2.0, htmlHeight / 2.0) card = cm.generate() self.leftQuad = NodePath(card) self.leftQuad.reparentTo(self.parent) self.leftGuiTex = Texture('guiTex') self.leftGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.leftGuiTex.setKeepRamImage(True) self.leftGuiTex.makeRamImage() self.leftGuiTex.setWrapU(Texture.WMClamp) self.leftGuiTex.setWrapV(Texture.WMClamp) ts = TextureStage('leftWebTS') self.leftQuad.setTexture(ts, self.leftGuiTex) self.leftQuad.setTexScale(ts, 1.0, -1.0) self.leftQuad.setTransparency(0) self.leftQuad.setTwoSided(True) self.leftQuad.setColor(1.0, 1.0, 1.0, 1.0) def setupRightTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT) cm.setFrame(0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) card = cm.generate() self.rightQuad = NodePath(card) self.rightQuad.reparentTo(self.parent) self.rightGuiTex = Texture('guiTex') self.rightGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.rightGuiTex.setKeepRamImage(True) self.rightGuiTex.makeRamImage() self.rightGuiTex.setWrapU(Texture.WMClamp) self.rightGuiTex.setWrapV(Texture.WMClamp) ts = TextureStage('rightWebTS') self.rightQuad.setTexture(ts, self.rightGuiTex) self.rightQuad.setTexScale(ts, 1.0, -1.0) self.rightQuad.setTransparency(0) self.rightQuad.setTwoSided(True) self.rightQuad.setColor(1.0, 1.0, 1.0, 1.0) def calcMouseLimits(self): ll = Point3() ur = Point3() self.quad.calcTightBounds(ll, ur) self.notify.debug('ll=%s ur=%s' % (ll, ur)) offset = self.quad.getPos(aspect2d) self.notify.debug('offset = %s ' % offset) ll.setZ(ll.getZ() + offset.getZ()) ur.setZ(ur.getZ() + offset.getZ()) self.notify.debug('new LL=%s, UR=%s' % (ll, ur)) relPointll = self.quad.getRelativePoint(aspect2d, ll) self.notify.debug('relPoint = %s' % relPointll) self.mouseLL = (aspect2d.getScale()[0] * ll[0], aspect2d.getScale()[2] * ll[2]) self.mouseUR = (aspect2d.getScale()[0] * ur[0], aspect2d.getScale()[2] * ur[2]) self.notify.debug('original mouseLL=%s, mouseUR=%s' % (self.mouseLL, self.mouseUR)) def writeTex(self, filename='guiText.png'): self.notify.debug('writing texture') self.guiTex.generateRamMipmapImages() self.guiTex.write(filename) def toggleRotation(self): if self.interval.isPlaying(): self.interval.finish() else: self.interval.loop() def mouseDown(self, button): messenger.send('wakeup') self.webView.injectMouseDown(button) def mouseUp(self, button): self.webView.injectMouseUp(button) def reload(self): pass def zoomIn(self): self.webView.zoomIn() def zoomOut(self): self.webView.zoomOut() def toggleTransparency(self): self.transparency = not self.transparency self.webView.setTransparent(self.transparency) def update(self, task): if base.mouseWatcherNode.hasMouse(): x, y = self._translateRelativeCoordinates( base.mouseWatcherNode.getMouseX(), base.mouseWatcherNode.getMouseY()) if self.mx - x != 0 or self.my - y != 0: self.webView.injectMouseMove(x, y) self.mx, self.my = x, y if self.webView.isDirty(): self.webView.render(self.imgBuffer.buffer_info()[0], WEB_WIDTH * 4, 4) Texture.setTexturesPower2(2) textureBuffer = self.guiTex.modifyRamImage() textureBuffer.setData(self.imgBuffer.tostring()) if self.useHalfTexture: self.guiTex.store(self.fullPnmImage) self.leftPnmImage.copySubImage(self.fullPnmImage, 0, 0, 0, 0, WEB_HALF_WIDTH, WEB_HEIGHT) self.rightPnmImage.copySubImage(self.fullPnmImage, 0, 0, WEB_HALF_WIDTH, 0, WEB_HALF_WIDTH, WEB_HEIGHT) self.leftGuiTex.load(self.leftPnmImage) self.rightGuiTex.load(self.rightPnmImage) self.quad.hide() Texture.setTexturesPower2(1) GlobalWebcore.update() return Task.cont def _translateRelativeCoordinates(self, x, y): sx = int((x - self.mouseLL[0]) / (self.mouseUR[0] - self.mouseLL[0]) * WEB_WIDTH_PIXELS) sy = WEB_HEIGHT_PIXELS - int( (y - self.mouseLL[1]) / (self.mouseUR[1] - self.mouseLL[1]) * WEB_HEIGHT_PIXELS) return (sx, sy) def unload(self): self.ignoreAll() self.webView.destroy() self.webView = None return def onCallback(self, name, args): if name == 'requestFPS': pass def onBeginNavigation(self, url, frameName): pass def onBeginLoading(self, url, frameName, statusCode, mimeType): pass def onFinishLoading(self): self.notify.debug('finished loading') def onReceiveTitle(self, title, frameName): pass def onChangeTooltip(self, tooltip): pass def onChangeCursor(self, cursor): pass def onChangeKeyboardFocus(self, isFocused): pass def onChangeTargetURL(self, url): pass
class PartyCog(FSM): notify = directNotify.newCategory('PartyCog') HpTextGenerator = TextNode('HpTextGenerator') hpText = None height = 7 def __init__(self, parentNode, id, bounceSpeed=3, bounceHeight=1, rotateSpeed=1, heightShift=1, xMoveSpeed=0, xMoveDistance=0, bounceOffset=0): self.id = id FSM.__init__(self, 'PartyCogFSM-%d' % self.id) self.showFacingStatus = False self.xMoveSpeed = xMoveSpeed self.xMoveDistance = xMoveDistance self.heightShift = heightShift self.bounceSpeed = bounceSpeed self.bounceHeight = bounceHeight self.rotateSpeed = rotateSpeed self.parentNode = parentNode self.bounceOffset = bounceOffset self.hitInterval = None self.kaboomTrack = None self.resetRollIval = None self.netTimeSentToStartByHit = 0 self.load() self.request('Down') return def load(self): self.root = NodePath('PartyCog-%d' % self.id) self.root.reparentTo(self.parentNode) path = 'phase_13/models/parties/cogPinata_' self.actor = Actor( path + 'actor', { 'idle': path + 'idle_anim', 'down': path + 'down_anim', 'up': path + 'up_anim', 'bodyHitBack': path + 'bodyHitBack_anim', 'bodyHitFront': path + 'bodyHitFront_anim', 'headHitBack': path + 'headHitBack_anim', 'headHitFront': path + 'headHitFront_anim' }) self.actor.reparentTo(self.root) self.temp_transform = Mat4() self.head_locator = self.actor.attachNewNode('temphead') self.bodyColl = CollisionTube(0, 0, 1, 0, 0, 5.75, 0.75) self.bodyColl.setTangible(1) self.bodyCollNode = CollisionNode('PartyCog-%d-Body-Collision' % self.id) self.bodyCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.bodyCollNode.addSolid(self.bodyColl) self.bodyCollNodePath = self.root.attachNewNode(self.bodyCollNode) self.headColl = CollisionTube(0, 0, 3, 0, 0, 3.0, 1.5) self.headColl.setTangible(1) self.headCollNode = CollisionNode('PartyCog-%d-Head-Collision' % self.id) self.headCollNode.setCollideMask(ToontownGlobals.PieBitmask) self.headCollNode.addSolid(self.headColl) self.headCollNodePath = self.root.attachNewNode(self.headCollNode) self.arm1Coll = CollisionSphere(1.65, 0, 3.95, 1.0) self.arm1Coll.setTangible(1) self.arm1CollNode = CollisionNode('PartyCog-%d-Arm1-Collision' % self.id) self.arm1CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm1CollNode.addSolid(self.arm1Coll) self.arm1CollNodePath = self.root.attachNewNode(self.arm1CollNode) self.arm2Coll = CollisionSphere(-1.65, 0, 3.45, 1.0) self.arm2Coll.setTangible(1) self.arm2CollNode = CollisionNode('PartyCog-%d-Arm2-Collision' % self.id) self.arm2CollNode.setCollideMask(ToontownGlobals.PieBitmask) self.arm2CollNode.addSolid(self.arm2Coll) self.arm2CollNodePath = self.root.attachNewNode(self.arm2CollNode) splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splatType = globalPropPool.getPropType(splatName) self.pieHitSound = globalBattleSoundCache.getSound( 'AA_wholepie_only.ogg') self.upSound = globalBattleSoundCache.getSound('AV_jump_to_side.ogg') self.hole = loader.loadModel('phase_13/models/parties/cogPinataHole') self.hole.setTransparency(True) self.hole.setP(-90.0) self.hole.setScale(3) self.hole.setBin('ground', 3) self.hole.reparentTo(self.parentNode) def unload(self): self.request('Off') self.clearHitInterval() if self.hole is not None: self.hole.removeNode() self.hole = None if self.actor is not None: self.actor.cleanup() self.actor.removeNode() self.actor = None if self.root is not None: self.root.removeNode() self.root = None if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.kaboomTrack = None if self.resetRollIval is not None and self.resetRollIval.isPlaying(): self.resetRollIval.finish() self.resetRollIval = None if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.finish() self.hitInterval = None del self.upSound del self.pieHitSound return def enterStatic(self): pass def exitStatic(self): pass def enterActive(self, startTime): self.root.setR(0.0) updateTask = Task.Task(self.updateTask) updateTask.startTime = startTime taskMgr.add(updateTask, 'PartyCog.update-%d' % self.id) def exitActive(self): taskMgr.remove('PartyCog.update-%d' % self.id) taskMgr.remove('PartyCog.bounceTask-%d' % self.id) self.clearHitInterval() self.resetRollIval = self.root.hprInterval(0.5, Point3( self.root.getH(), 0.0, 0.0), blendType='easeInOut') self.resetRollIval.start() self.actor.stop() def enterDown(self): if self.oldState == 'Off': downAnimControl = self.actor.getAnimControl('down') self.actor.pose('down', downAnimControl.getNumFrames() - 1) return self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpFunc(self.setAlongSpline, duration=1.0, fromData=self.currentT, toData=0.0), LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'down', loop=0)), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def exitDown(self): self.root.setR(0.0) self.root.setH(0.0) self.targetDistance = 0.0 self.targetFacing = 0.0 self.currentT = 0.0 self.setAlongSpline(0.0) self.clearHitInterval() startScale = self.hole.getScale() endScale = Point3(5, 5, 5) self.hitInterval = Sequence( LerpScaleInterval(self.hole, duration=0.175, scale=endScale, startScale=startScale, blendType='easeIn'), Parallel( SoundInterval(self.upSound, volume=0.6, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), ActorInterval(self.actor, 'up', loop=0)), Func(self.actor.loop, 'idle'), LerpScaleInterval(self.hole, duration=0.175, scale=Point3(3, 3, 3), startScale=endScale, blendType='easeOut')) self.hitInterval.start() def filterDown(self, request, args): if request == 'Down': return None else: return self.defaultFilter(request, args) return None def setEndPoints(self, start, end, amplitude=1.7): self.sinAmplitude = amplitude self.sinPeriod = (end.getX() - start.getX()) / 2 self.sinDisplacement = start.getY() self.startPoint = start self.endPoint = end self.currentT = 0.0 self.targetDistance = 0.0 self.currentFacing = 0.0 self.targetFacing = 0.0 self.setAlongSpline(self.currentT) self.hole.setPos(self.root.getPos()) self.hole.setZ(0.02) def rockBackAndForth(self, task): t = task.startTime + task.time angle = math.sin(t) * 20.0 self.root.setR(angle) return task.cont def updateDistance(self, distance): self.targetDistance = clamp(distance, -1.0, 1.0) def updateTask(self, task): self.rockBackAndForth(task) if self.targetDistance > self.currentT: self.currentT += min(0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) elif self.targetDistance < self.currentT: self.currentT += max(-0.01, self.targetDistance - self.currentT) self.setAlongSpline(self.currentT) if self.currentT < 0.0: self.targetFacing = -90.0 elif self.currentT > 0.0: self.targetFacing = 90.0 else: self.targetFacing = 0.0 if self.targetFacing > self.currentFacing: self.currentFacing += min(10, self.targetFacing - self.currentFacing) elif self.targetFacing < self.currentFacing: self.currentFacing += max(-10, self.targetFacing - self.currentFacing) self.root.setH(self.currentFacing) return task.cont def setAlongSpline(self, t): t = t + 1.0 dist = (self.endPoint.getX() - self.startPoint.getX()) / 2.0 x = self.startPoint.getX() + t * dist y = self.startPoint.getY() - math.sin( t * 2 * math.pi) * self.sinAmplitude self.root.setPos(x, y, 0) def startBounce(self): taskMgr.add(self.bounce, 'PartyCog.bounceTask-%d' % self.id) def bounce(self, task): self.root.setZ( math.sin((self.bounceOffset + task.time) * self.bounceSpeed) * self.bounceHeight + self.heightShift) return task.cont def setPos(self, position): self.root.setPos(position) def respondToPieHit(self, timestamp, position, hot=False, direction=1.0): if self.netTimeSentToStartByHit < timestamp: self.__showSplat(position, direction, hot) if self.netTimeSentToStartByHit < timestamp: self.netTimeSentToStartByHit = timestamp else: self.notify.debug( 'respondToPieHit self.netTimeSentToStartByHit = %s' % self.netTimeSentToStartByHit) def clearHitInterval(self): if self.hitInterval is not None and self.hitInterval.isPlaying(): self.hitInterval.clearToInitial() return def __showSplat(self, position, direction, hot=False): if self.kaboomTrack is not None and self.kaboomTrack.isPlaying(): self.kaboomTrack.finish() self.clearHitInterval() splatName = 'splat-creampie' self.splat = globalPropPool.getProp(splatName) self.splat.setBillboardPointEye() self.splat.reparentTo(render) self.splat.setPos(self.root, position) self.splat.setAlphaScale(1.0) if not direction == 1.0: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[0]) if self.currentFacing > 0.0: facing = 'HitFront' else: facing = 'HitBack' else: self.splat.setColorScale(PartyGlobals.CogActivitySplatColors[1]) if self.currentFacing > 0.0: facing = 'HitBack' else: facing = 'HitFront' if hot: targetscale = 0.75 part = 'head' else: targetscale = 0.5 part = 'body' def setSplatAlpha(amount): self.splat.setAlphaScale(amount) self.hitInterval = Sequence( ActorInterval(self.actor, part + facing, loop=0), Func(self.actor.loop, 'idle')) self.hitInterval.start() self.kaboomTrack = Parallel( SoundInterval(self.pieHitSound, volume=1.0, node=self.actor, cutOff=PartyGlobals.PARTY_COG_CUTOFF), Sequence( Func(self.splat.showThrough), Parallel( Sequence( LerpScaleInterval(self.splat, duration=0.175, scale=targetscale, startScale=Point3(0.1, 0.1, 0.1), blendType='easeOut'), Wait(0.175)), Sequence( Wait(0.1), LerpFunc(setSplatAlpha, duration=1.0, fromData=1.0, toData=0.0, blendType='easeOut'))), Func(self.splat.cleanup), Func(self.splat.removeNode))) self.kaboomTrack.start() return def showHitScore(self, number, scale=1): if number <= 0: return if self.hpText: self.hideHitScore() self.HpTextGenerator.setFont(ToontownGlobals.getSignFont()) if number < 0: self.HpTextGenerator.setText(str(number)) else: self.HpTextGenerator.setText('+' + str(number)) self.HpTextGenerator.clearShadow() self.HpTextGenerator.setAlign(TextNode.ACenter) r = 1 g = 1 b = 0 a = 1 self.HpTextGenerator.setTextColor(r, g, b, a) self.hpTextNode = self.HpTextGenerator.generate() self.hpText = render.attachNewNode(self.hpTextNode) self.hpText.setScale(scale) self.hpText.setBillboardPointEye() self.hpText.setBin('fixed', 100) self.hpText.setPos(self.root, 0, 0, self.height / 2) seq = Task.sequence( self.hpText.lerpPos(Point3( self.root.getX(render), self.root.getY(render), self.root.getZ(render) + self.height + 1.0), 0.25, blendType='easeOut'), Task.pause(0.25), self.hpText.lerpColor(Vec4(r, g, b, a), Vec4(r, g, b, 0), 0.1), Task.Task(self.__hideHitScoreTask)) taskMgr.add(seq, 'PartyCogHpText' + str(self.id)) def __hideHitScoreTask(self, task): self.hideHitScore() return Task.done def hideHitScore(self): if self.hpText: taskMgr.remove('PartyCogHpText' + str(self.id)) self.hpText.removeNode() self.hpText = None return def getHeadLocation(self): self.actor.getJoints(jointName='head')[0].getNetTransform( self.temp_transform) self.head_locator.setMat(self.temp_transform) return self.head_locator.getZ(self.root)
class Entity(DirectObject, object): def __init__(self, model = None): self.prime = None if model != None: self.set_model(model) def get_model(self): return self.prime def set_model(self, model): if model != None: if isinstance(model, PandaNode): self.prime = NodePath(model) elif isinstance(model, NodePath): self.prime = model else: if Filename(model).exists(): self.model = Filename(model).getBasenameWoExtension() path = model else: if isinstance(model, Filename): self.model = model.getBasenameWoExtension() path = model.getFullpath() else: path = APP_PATH + model print "path: ", path if Filename(path).exists(): pass elif Filename(path + ".bam").exists(): path += ".bam" elif Filename(path + ".bam.pz").exists(): path += ".bam.pz" elif Filename(path + ".egg").exists(): path += ".egg" elif Filename(path + ".egg.pz").exists(): path += ".egg.pz" elif Filename(path + ".x").exists(): path += ".x" else: print ":object(error): can't find model", model, "!" # Probably shouldn't exit because of this sys.exit(1) self.model = model self.prime = base.loader.loadModel(path) if self.prime == None: print ":object(error): can't load model", model, "!" # Probably shouldn't exit because of this sys.exit(1) def getX(self): return self.prime.getX(base.render) def getY(self): return self.prime.getY(base.render) def getZ(self): return self.prime.getZ(base.render) def getH(self): return self.prime.getH(base.render) def getP(self): return self.prime.getP(base.render) def getR(self): return self.prime.getR(base.render) def getSx(self): return self.prime.getSx(base.render) def getSy(self): return self.prime.getSy(base.render) def getSz(self): return self.prime.getSz(base.render) def getPos(self): return self.prime.getPos(base.render) def getHpr(self): return self.prime.getHpr(base.render) def getScale(self): return self.prime.getScale(base.render) def getCollideMask(self): return self.prime.getCollideMask() def getTransparency(self): return self.prime.getTransparency() def getTwoSided(self): return self.prime.getTwoSided() def getParent(self): return self.prime.getParent() def setX(self, *v): self.prime.setX(*v) def setY(self, *v): self.prime.setY(*v) def setZ(self, *v): self.prime.setZ(*v) def setH(self, *v): self.prime.setH(*v) def setP(self, *v): self.prime.setP(*v) def setR(self, *v): self.prime.setR(*v) def setSx(self, *v): self.prime.setSx(*v) def setSy(self, *v): self.prime.setSy(*v) def setSz(self, *v): self.prime.setSz(*v) def setPos(self, *v): self.prime.setPos(*v) def setHpr(self, *v): self.prime.setHpr(*v) def setScale(self, *v): self.prime.setScale(*v) def setCollideMask(self, *v): self.prime.setCollideMask(*v) def setTransparency(self, *v): self.prime.setTransparency(*v) def setTwoSided(self, *v): self.prime.setTwoSided(*v) def removeNode(self): self.prime.removeNode() def reparentTo(self, parent): if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if parent.startswith("render/"): parent = parent[7:] tv = parent parent = base.render.find(tv) if parent == NodePath(): parent = base.render.find("**/" + tv) if parent != NodePath() and parent != None: self.prime.reparentTo(parent) def wrtReparentTo(self, parent): if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if parent.startswith("render/"): parent = parent[7:] tv = parent parent = base.render.find(tv) if parent == NodePath(): parent = base.render.find("**/" + tv) if parent != NodePath(): self.prime.reparentTo(parent) def attachTo(self, parent): """This attaches the object to another object/nodepath. The caller object stays at the same place, with the same scale and rotation, but they become relative to the other object/nodepath. This is useful with for example a character that steps onto a moving ship or so.""" if isinstance(parent, Entity): parent = parent.prime if isinstance(parent, str): if(parent.startswith("render/")): parent = parent[7:] tv = parent parent = base.render.find(tv) if(parent == NodePath()): parent = base.render.find("**/" + tv) if(parent != NodePath()): self.prime.setPos(self.prime.getPos(parent)) self.prime.setHpr(self.prime.getHpr(parent)) self.prime.setScale(self.prime.getScale(parent)) self.prime.reparentTo(parent) def hide(self): self.prime.hide() def show(self): self.prime.show() def __del__(self): try: if isinstance(self.prime, NodePath): self.prime.removeNode() except AttributeError: pass def __getstate__(self): return [self.model, self.getX(), self.getY(), self.getZ(), self.getH(), self.getP(), self.getR(), self.getSx(), self.getSy(), self.getSz(), self.getCollideMask().getWord(), self.getTransparency(), self.getTwoSided(), str(self.getParent())] def __setstate__(self, p): if len(p) < 14: print ":object(error): This state is not compatible with this version!" sys.exit(1) self.setModel(p[0]) self.setX(p[1]) self.setY(p[2]) self.setZ(p[3]) self.setH(p[4]) self.setP(p[5]) self.setR(p[6]) self.setSx(p[7]) self.setSy(p[8]) self.setSz(p[9]) self.setCollideMask(BitMask32(p[10])) self.setTransparency(p[11]) self.setTwoSided(p[12]) self.reparentTo(p[13])
class Camera: """A floating 3rd person camera that follows an actor around, and can be turned left or right around the actor. Public fields: self.controlMap -- The camera's movement controls. actor -- The Actor object that the camera will follow. Public functions: init(actor) -- Initialise the camera. move(task) -- Move the camera each frame, following the assigned actor. This task is called every frame to update the camera. setControl -- Set the camera's turn left or turn right control on or off. """ def __init__(self,actor): """Initialise the camera, setting it to follow 'actor'. Arguments: actor -- The Actor that the camera will initially follow. """ self.actor = actor self.prevtime = 0 # The camera's controls: # "left" = move the camera left, 0 = off, 1 = on # "right" = move the camera right, 0 = off, 1 = on self.controlMap = {"left":0, "right":0} taskMgr.add(self.move,"cameraMoveTask") # Create a "floater" object. It is used to orient the camera above the # target actor's head. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Set up the camera. base.disableMouse() base.camera.setPos(self.actor.getX(),self.actor.getY()+2, 2) # uncomment for topdown #base.camera.setPos(self.actor.getX(),self.actor.getY()+10,2) #base.camera.setHpr(180, -50, 0) # A CollisionRay beginning above the camera and going down toward the # ground is used to detect camera collisions and the height of the # camera above the ground. A ray may hit the terrain, or it may hit a # rock or a tree. If it hits the terrain, we detect the camera's # height. If it hits anything else, the camera is in an illegal # position. self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode('camRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = base.camera.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler) # Uncomment this line to see the collision rays #self.groundColNp.show() def move(self,task): """Update the camera's position before rendering the next frame. This is a task function and is called each frame by Panda3D. The camera follows self.actor, and tries to remain above the actor and above the ground (whichever is highest) while looking at a point slightly above the actor's head. Arguments: task -- A direct.task.Task object passed to this function by Panda3D. Return: Task.cont -- To tell Panda3D to call this task function again next frame. """ # FIXME: There is a bug with the camera -- if the actor runs up a # hill and then down again, the camera's Z position follows the actor # up the hill but does not come down again when the actor goes down # the hill. elapsed = task.time - self.prevtime # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. # comment out for topdown base.camera.lookAt(self.actor) camright = base.camera.getNetTransform().getMat().getRow3(0) camright.normalize() if (self.controlMap["left"]!=0): base.camera.setPos(base.camera.getPos() - camright*(elapsed*20)) if (self.controlMap["right"]!=0): base.camera.setPos(base.camera.getPos() + camright*(elapsed*20)) # If the camera is too far from the actor, move it closer. # If the camera is too close to the actor, move it farther. camvec = self.actor.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec*(camdist-10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec*(5-camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Keep the camera at one foot above the terrain, # or two feet above the actor, whichever is greater. # comment out for topdown entries = [] for i in range(self.groundHandler.getNumEntries()): entry = self.groundHandler.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"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) if (base.camera.getZ() < self.actor.getZ() + 2.0): base.camera.setZ(self.actor.getZ() + 2.0) # The camera should look in the player's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above the player's head. self.floater.setPos(self.actor.getPos()) self.floater.setZ(self.actor.getZ() + 2.0) #self.floater.setZ(self.actor.getZ() + 10.0) #self.floater.setY(self.actor.getY() + 7.0) # comment out for topdown base.camera.lookAt(self.floater) base.camera.setPos(self.floater.getPos()) # Store the task time and continue. self.prevtime = task.time return Task.cont def setControl(self, control, value): """Set the state of one of the camera's movement controls. Arguments: See self.controlMap in __init__. control -- The control to be set, must be a string matching one of the strings in self.controlMap. value -- The value to set the control to. """ # FIXME: this function is duplicated in Camera and Character, and # keyboard control settings are spread throughout the code. Maybe # add a Controllable class? self.controlMap[control] = value
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor("media/models/boxman", { "walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle" }) self.actor.setScale(1.0) self.actor.setH(0) #self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath('agent-%s' % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ #self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) #self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint( None, 'modelRoot', 'Hand.R') self.player_left_hand = self.actor.exposeJoint(None, 'modelRoot', 'Hand.L') self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, 'modelRoot', 'Head') self.neck = self.actor.controlJoint(None, 'modelRoot', 'Head') self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0 } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") #bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(.3, .3), pos=(0, 0, 3.6), frameColor=(.6, .2, .1, .5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1)) #self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component('text0').textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, .5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(.18, .18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component('text0').textNode.setFrameColor( 1, 1, 1, 0) self.thought_bubble.component('text0').textNode.setFrameAsMargin( 0.1, 0.1, 0.1, 0.1) self.thought_bubble.component('text0').textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera('RaphViz')) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) #self.fov.node().showFrustum() # displays a box around his head #self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=['isisobject']): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if 'x_pos' not in exclude: object_dict['x_pos'] = p3[0] if 'y_pos' not in exclude: object_dict['y_pos'] = p3[2] if 'distance' not in exclude: object_dict['distance'] = o.activeModel.getDistance( self.fov) if 'orientation' not in exclude: object_dict['orientation'] = o.activeModel.getH(self.fov) if 'actions' not in exclude: object_dict['actions'] = o.list_actions() if 'isisobject' not in exclude: object_dict['isisobject'] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = {'x_pos': p3[0],\ 'y_pos': p3[2],\ 'distance':a.actorNodePath.getDistance(self.fov),\ 'orientation': a.actorNodePath.getH(self.fov)} agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x['isisobject'] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values())) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say( "If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies #percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts['objects'] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts['position'] = self.sense__get_position() # language: get last utterances that were typed percepts['language'] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts['agents'] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble['text'] = message #self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) #self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble['text'] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [ ] #[base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print 'already holding ' + hand_slot.getName() + '.' return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() #turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag('heldBy', self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print 'right hand is not holding an object.' return False if self.right_hand_holding_object.getNetTag('heldBy') == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag('heldBy', '') self.right_hand_holding_object.setRotation( self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return 'left hand is not holding an object.' if self.left_hand_holding_object.getNetTag('heldBy') == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag('heldBy', '') self.left_hand_holding_object.setRotation( self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') print "Trying to use object", target if self.can_grasp(target): if (target.call(self, action, self.right_hand_holding_object) or (self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') if self.can_grasp(target): if (target.call(self, action, self.left_hand_holding_object) or (self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ((self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag('isisobj').name == object_name)) \ or (self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag('isisobj').name == object_name))) def empty_hand(self): if (self.left_hand_holding_object is None): return self.player_left_hand elif (self.right_hand_holding_object is None): return self.player_right_hand return False def has_empty_hand(self): return (self.empty_hand() is not False) def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() #FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return {'body_x': x, 'body_y': y, 'body_z': z,'body_h':h,\ 'body_p': p, 'body_r': r, 'in_left_hand': left_hand_obj, 'in_right_hand':right_hand_obj} def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v['actions'] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if (self.controlMap["turn_left"] != 0): self.addToH(stepSize * self.speeds[0]) if (self.controlMap["turn_right"] != 0): self.addToH(-stepSize * self.speeds[1]) if self.verticalState == 'ground': # these actions require contact with the ground if (self.controlMap["move_forward"] != 0): self.speed[1] = self.speeds[2] if (self.controlMap["move_backward"] != 0): self.speed[1] = -self.speeds[3] if (self.controlMap["move_left"] != 0): self.speed[0] = -self.speeds[4] if (self.controlMap["move_right"] != 0): self.speed[0] = self.speeds[5] if (self.controlMap["jump"] != 0): kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if (self.controlMap["look_left"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if (self.controlMap["look_right"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if (self.controlMap["look_up"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if (self.controlMap["look_down"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition( self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition( self.player_left_hand.getPos(render)) #Update the dialog box and thought windows #This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble['text_bg'] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble['frameColor'] = (.6, .2, .1, .5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble['text'] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames('walk') if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose('walk', self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose('idle', 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
def test_door_setup(self): parent_np = NodePath('parent_np') parent_np.setPosHpr(0, 10, .5, 180, 0, 0) door_origin = parent_np.attachNewNode('door_origin') door_origin.setPos(10, -25, .5) block = 4 color = Vec4(.842, .167, .361, 1) # Set up door_np nodes door_np = NodePath('door_np') left_hole = door_np.attachNewNode('door_0_hole_left') right_hole = door_np.attachNewNode('door_0_hole_right') left_door = door_np.attachNewNode('door_0_left') right_door = door_np.attachNewNode('door_0_right') door_flat = door_np.attachNewNode('door_0_flat') door_trigger = door_np.attachNewNode('door_0_trigger') DNADoor.setupDoor(door_np, parent_np, door_origin, self.store, block, color) # Check if the nodes attributes and parents are correct self.assertEqual(door_np.getPos(door_origin), Point3(0, 0, 0)) self.assertEqual(door_np.getHpr(door_origin), Point3(0, 0, 0)) self.assertEqual(door_np.getScale(door_origin), Point3(1, 1, 1)) def verify_color(color1, color2): self.assertAlmostEqual(color1.getX(), color2.getX(), places=4) self.assertAlmostEqual(color1.getY(), color2.getY(), places=4) self.assertAlmostEqual(color1.getZ(), color2.getZ(), places=4) self.assertAlmostEqual(color1.getW(), color2.getW(), places=4) verify_color(color, door_np.getColor()) self.assertEqual(left_hole.getParent(), door_flat) self.assertEqual(left_hole.getName(), 'doorFrameHoleLeft') self.assertEqual(right_hole.getParent(), door_flat) self.assertEqual(right_hole.getName(), 'doorFrameHoleRight') self.assertEqual(left_door.getParent(), parent_np) self.assertEqual(left_door.getName(), 'leftDoor') verify_color(color, right_door.getColor()) self.assertEqual(right_door.getParent(), parent_np) self.assertEqual(right_door.getName(), 'rightDoor') verify_color(color, right_door.getColor()) self.assertEqual(door_trigger.getParent(), parent_np) self.assertEqual(door_trigger.getName(), 'door_trigger_%d' % block) store_np = self.store.getDoorPosHprFromBlockNumber(block) self.assertFalse(store_np.isEmpty()) # Testing the pos is a pain because of decimal precision pos = store_np.getPos() self.assertAlmostEqual(pos.getX(), -10, places=2) self.assertAlmostEqual(pos.getY(), 35, places=2) self.assertAlmostEqual(pos.getZ(), 1, places=2) # Sometimes getH() returns -180 and others 180 # Test the modulus (better than abs I guess) self.assertEqual(store_np.getH() % 180, 0)
class HtmlView(DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory("HtmlView") useHalfTexture = base.config.GetBool("news-half-texture", 0) def __init__(self, parent=aspect2d): """Properly initialize ourself.""" #AwWebViewListener.AwWebViewListener.__init__(self) self.parent = parent self.mx = 0 self.my = 0 self.htmlFile = "index.html" self.transparency = False # this is important looks weird if it's true global GlobalWebcore if GlobalWebcore: # we get a C++ crash if we construct webcore a second time pass else: GlobalWebcore = AwWebCore(AwWebCore.LOGVERBOSE, True, AwWebCore.PFBGRA) GlobalWebcore.setBaseDirectory('.') for errResponse in xrange(400, 600): GlobalWebcore.setCustomResponsePage(errResponse, "error.html") self.webView = GlobalWebcore.createWebView(WEB_WIDTH, WEB_HEIGHT, self.transparency, False, 70) #self.webView.setListener(self) #self.webView.setCallback("requestFPS"); frameName = '' inGameNewsUrl = self.getInGameNewsUrl() #self.webView.loadURL2(inGameNewsUrl) self.imgBuffer = array.array('B') for i in xrange(WEB_WIDTH * WEB_HEIGHT): self.imgBuffer.append(0) self.imgBuffer.append(0) self.imgBuffer.append(0) self.imgBuffer.append(255) if self.useHalfTexture: self.leftBuffer = array.array('B') for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT): self.leftBuffer.append(0) self.leftBuffer.append(0) self.leftBuffer.append(0) self.leftBuffer.append(255) self.rightBuffer = array.array('B') for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT): self.rightBuffer.append(0) self.rightBuffer.append(0) self.rightBuffer.append(0) self.rightBuffer.append(255) self.setupTexture() if self.useHalfTexture: self.setupHalfTextures() #self.interval = LerpHprInterval(self.quad, 2, Vec3(360, 0, 0), Vec3(0, 0, 0)) #self.accept("escape", sys.exit, [0]) #self.accept("w", self.writeTex) self.accept("mouse1", self.mouseDown, [AwWebView.LEFTMOUSEBTN]) self.accept("mouse3", self.mouseDown, [AwWebView.RIGHTMOUSEBTN]) self.accept("mouse1-up", self.mouseUp, [AwWebView.LEFTMOUSEBTN]) self.accept("mouse3-up", self.mouseUp, [AwWebView.RIGHTMOUSEBTN]) #self.accept("f1", self.toggleRotation) #self.accept("f2", self.toggleTransparency) #self.accept("f3", self.reload) #self.accept("f4", self.zoomIn) #self.accept("f5", self.zoomOut) #taskMgr.doMethodLater(1.0, self.update, 'HtmlViewUpdateTask') # we get a problem if a mid-frame hearbeat fires of this task in conjunction with igLoop #taskMgr.add(self.update, 'HtmlViewUpdateTask', priority = 51) #taskMgr.add(self.update, 'HtmlViewUpdateTask') #base.newsFrame = self def getInGameNewsUrl(self): """Get the appropriate URL to use if we are in test, qa, or live.""" # First if all else fails, we hard code the live news url result = base.config.GetString( "fallback-news-url", "http://cdn.toontown.disney.go.com/toontown/en/gamenews/") # next check if we have an override, say they want to url to point to a file in their harddisk override = base.config.GetString("in-game-news-url", "") if override: self.notify.info( "got an override url, using %s for in a game news" % override) result = override else: try: launcherUrl = base.launcher.getValue("GAME_IN_GAME_NEWS_URL", "") if launcherUrl: result = launcherUrl self.notify.info( "got GAME_IN_GAME_NEWS_URL from launcher using %s" % result) else: self.notify.info( "blank GAME_IN_GAME_NEWS_URL from launcher, using %s" % result) except: self.notify.warning( "got exception getting GAME_IN_GAME_NEWS_URL from launcher, using %s" % result) return result def setupTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT) # the html area will be center aligned and vertically top aligned #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0) cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) bottomRightX = (WEB_WIDTH_PIXELS) / float(WEB_WIDTH + 1) bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1) #cm.setUvRange(Point2(0,0), Point2(bottomRightX, bottomRightY)) cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1)) card = cm.generate() self.quad = NodePath(card) self.quad.reparentTo(self.parent) self.guiTex = Texture("guiTex") self.guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.guiTex.setMinfilter(Texture.FTLinear) self.guiTex.setKeepRamImage(True) self.guiTex.makeRamImage() self.guiTex.setWrapU(Texture.WMRepeat) self.guiTex.setWrapV(Texture.WMRepeat) ts = TextureStage('webTS') self.quad.setTexture(ts, self.guiTex) self.quad.setTexScale(ts, 1.0, -1.0) self.quad.setTransparency(0) self.quad.setTwoSided(True) self.quad.setColor(1.0, 1.0, 1.0, 1.0) #self.quad.setZ(0.1) # shtickerbook is moved up by 0.1 self.calcMouseLimits() def setupHalfTextures(self): self.setupLeftTexture() self.setupRightTexture() self.fullPnmImage = PNMImage(WEB_WIDTH, WEB_HEIGHT, 4) self.leftPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4) self.rightPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4) def setupLeftTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT) # the html area will be center aligned and vertically top aligned #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0) cm.setFrame(-htmlWidth / 2.0, 0, -htmlHeight / 2.0, htmlHeight / 2.0) card = cm.generate() self.leftQuad = NodePath(card) self.leftQuad.reparentTo(self.parent) self.leftGuiTex = Texture("guiTex") self.leftGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.leftGuiTex.setKeepRamImage(True) self.leftGuiTex.makeRamImage() self.leftGuiTex.setWrapU(Texture.WMClamp) self.leftGuiTex.setWrapV(Texture.WMClamp) ts = TextureStage('leftWebTS') self.leftQuad.setTexture(ts, self.leftGuiTex) self.leftQuad.setTexScale(ts, 1.0, -1.0) self.leftQuad.setTransparency(0) self.leftQuad.setTwoSided(True) self.leftQuad.setColor(1.0, 1.0, 1.0, 1.0) #self.quad.setZ(0.1) # shtickerbook is moved up by 0.1 def setupRightTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT) # the html area will be center aligned and vertically top aligned #cm.setFrame(-htmlWidth/2.0, htmlWidth/2.0, 1.0 - htmlHeight, 1.0) cm.setFrame(0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) card = cm.generate() self.rightQuad = NodePath(card) self.rightQuad.reparentTo(self.parent) self.rightGuiTex = Texture("guiTex") self.rightGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.rightGuiTex.setKeepRamImage(True) self.rightGuiTex.makeRamImage() self.rightGuiTex.setWrapU(Texture.WMClamp) self.rightGuiTex.setWrapV(Texture.WMClamp) ts = TextureStage('rightWebTS') self.rightQuad.setTexture(ts, self.rightGuiTex) self.rightQuad.setTexScale(ts, 1.0, -1.0) self.rightQuad.setTransparency(0) self.rightQuad.setTwoSided(True) self.rightQuad.setColor(1.0, 1.0, 1.0, 1.0) #self.quad.setZ(0.1) # shtickerbook is moved up by 0.1 def calcMouseLimits(self): ll = Point3() ur = Point3() self.quad.calcTightBounds(ll, ur) self.notify.debug("ll=%s ur=%s" % (ll, ur)) # we need to get our relative position to aspect2d, since shtiker books is shifted offset = self.quad.getPos(aspect2d) self.notify.debug("offset = %s " % offset) ll.setZ(ll.getZ() + offset.getZ()) ur.setZ(ur.getZ() + offset.getZ()) self.notify.debug("new LL=%s, UR=%s" % (ll, ur)) relPointll = self.quad.getRelativePoint(aspect2d, ll) self.notify.debug("relPoint = %s" % relPointll) self.mouseLL = (aspect2d.getScale()[0] * ll[0], aspect2d.getScale()[2] * ll[2]) self.mouseUR = (aspect2d.getScale()[0] * ur[0], aspect2d.getScale()[2] * ur[2]) self.notify.debug("original mouseLL=%s, mouseUR=%s" % (self.mouseLL, self.mouseUR)) def writeTex(self, filename="guiText.png"): self.notify.debug("writing texture") self.guiTex.generateRamMipmapImages() self.guiTex.write(filename) def toggleRotation(self): if self.interval.isPlaying(): self.interval.finish() else: self.interval.loop() def mouseDown(self, button): messenger.send('wakeup') self.webView.injectMouseDown(button) def mouseUp(self, button): self.webView.injectMouseUp(button) def reload(self): pass #self.webView.loadFile(self.htmlFile, '') def zoomIn(self): self.webView.zoomIn() def zoomOut(self): self.webView.zoomOut() def toggleTransparency(self): self.transparency = not self.transparency self.webView.setTransparent(self.transparency) def update(self, task): global GlobalWebcore if base.mouseWatcherNode.hasMouse(): x, y = self._translateRelativeCoordinates( base.mouseWatcherNode.getMouseX(), base.mouseWatcherNode.getMouseY()) #self.notify.debug('got mouse move %d %d' % (x,y)) #self.webView.injectMouseMove(x, y) if (self.mx - x) != 0 or (self.my - y) != 0: self.webView.injectMouseMove(x, y) #self.notify.debug('injecting mouse move %d %d' % (x,y)) self.mx, self.my = x, y if self.webView.isDirty(): #self.notify.debug("webview is dirty") self.webView.render(self.imgBuffer.buffer_info()[0], WEB_WIDTH * 4, 4) #Texture.setTexturesPower2(AutoTextureScale.ATSUp) Texture.setTexturesPower2(2) #self.notify.debug("about to modify ram image") textureBuffer = self.guiTex.modifyRamImage() #import pdb; pdb.set_trace() #self.notify.debug("about to call textureBuffer.setData") textureBuffer.setData(self.imgBuffer.tostring()) #self.notify.debug("done calling setData") if self.useHalfTexture: # TODO check with DRose, this feels inefficient self.guiTex.store(self.fullPnmImage) self.leftPnmImage.copySubImage(self.fullPnmImage, 0, 0, 0, 0, WEB_HALF_WIDTH, WEB_HEIGHT) self.rightPnmImage.copySubImage(self.fullPnmImage, 0, 0, WEB_HALF_WIDTH, 0, WEB_HALF_WIDTH, WEB_HEIGHT) self.leftGuiTex.load(self.leftPnmImage) self.rightGuiTex.load(self.rightPnmImage) self.quad.hide() #Texture.setTexturesPower2(AutoTextureScale.ATSDown) Texture.setTexturesPower2(1) GlobalWebcore.update() return Task.cont def _translateRelativeCoordinates(self, x, y): sx = int((x - self.mouseLL[0]) / (self.mouseUR[0] - self.mouseLL[0]) * WEB_WIDTH_PIXELS) sy = WEB_HEIGHT_PIXELS - int( (y - self.mouseLL[1]) / (self.mouseUR[1] - self.mouseLL[1]) * WEB_HEIGHT_PIXELS) return sx, sy def unload(self): """Clean up everything, especially the awesomium bits.""" self.ignoreAll() self.webView.destroy() self.webView = None #global GlobalWebcore #GlobalWebcore = None pass # --------------------[ WebViewListener implementation ]-------------------------- def onCallback(self, name, args): assert self.notify.debugStateCall(self) if name == "requestFPS": #self.webView.setProperty( "fps", JSValue("%.1f" % (1.0 / globalClock.getDt())) ) #self.webView.executeJavascript("updateFPS()", "") pass def onBeginNavigation(self, url, frameName): assert self.notify.debugStateCall(self) pass def onBeginLoading(self, url, frameName, statusCode, mimeType): assert self.notify.debugStateCall(self) pass def onFinishLoading(self): assert self.notify.debugStateCall(self) self.notify.debug("finished loading") pass def onReceiveTitle(self, title, frameName): assert self.notify.debugStateCall(self) pass def onChangeTooltip(self, tooltip): assert self.notify.debugStateCall(self) pass def onChangeCursor(self, cursor): assert self.notify.debugStateCall(self) pass def onChangeKeyboardFocus(self, isFocused): assert self.notify.debugStateCall(self) pass def onChangeTargetURL(self, url): assert self.notify.debugStateCall(self) pass
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor( "media/models/boxman", {"walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle"} ) self.actor.setScale(1.0) self.actor.setH(0) # self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath("agent-%s" % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ # self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) # self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.R") self.player_left_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.L") self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, "modelRoot", "Head") self.neck = self.actor.controlJoint(None, "modelRoot", "Head") self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0, } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") # bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(0.3, 0.3), pos=(0, 0, 3.6), frameColor=(0.6, 0.2, 0.1, 0.5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1), ) # self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component("text0").textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, 0.5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(0.18, 0.18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5, ) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component("text0").textNode.setFrameColor(1, 1, 1, 0) self.thought_bubble.component("text0").textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1) self.thought_bubble.component("text0").textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera("RaphViz")) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) # self.fov.node().showFrustum() # displays a box around his head # self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=["isisobject"]): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if "x_pos" not in exclude: object_dict["x_pos"] = p3[0] if "y_pos" not in exclude: object_dict["y_pos"] = p3[2] if "distance" not in exclude: object_dict["distance"] = o.activeModel.getDistance(self.fov) if "orientation" not in exclude: object_dict["orientation"] = o.activeModel.getH(self.fov) if "actions" not in exclude: object_dict["actions"] = o.list_actions() if "isisobject" not in exclude: object_dict["isisobject"] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = { "x_pos": p3[0], "y_pos": p3[2], "distance": a.actorNodePath.getDistance(self.fov), "orientation": a.actorNodePath.getH(self.fov), } agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x["isisobject"] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values()) ) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say("If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies # percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts["objects"] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts["position"] = self.sense__get_position() # language: get last utterances that were typed percepts["language"] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts["agents"] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble["text"] = message # self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) # self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble["text"] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( "aimRay", 5, [pos, direction], [isisobj.geom] ) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [] # [base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print "already holding " + hand_slot.getName() + "." return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() # turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag("heldBy", self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print "right hand is not holding an object." return False if self.right_hand_holding_object.getNetTag("heldBy") == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag("heldBy", "") self.right_hand_holding_object.setRotation(self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return "left hand is not holding an object." if self.left_hand_holding_object.getNetTag("heldBy") == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag("heldBy", "") self.left_hand_holding_object.setRotation(self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "Trying to use object", target if self.can_grasp(target): if target.call(self, action, self.right_hand_holding_object) or ( self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") if self.can_grasp(target): if target.call(self, action, self.left_hand_holding_object) or ( self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ( self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag("isisobj").name == object_name) ) or ( self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag("isisobj").name == object_name) ) def empty_hand(self): if self.left_hand_holding_object is None: return self.player_left_hand elif self.right_hand_holding_object is None: return self.player_right_hand return False def has_empty_hand(self): return self.empty_hand() is not False def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() # FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return { "body_x": x, "body_y": y, "body_z": z, "body_h": h, "body_p": p, "body_r": r, "in_left_hand": left_hand_obj, "in_right_hand": right_hand_obj, } def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v["actions"] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if self.controlMap["turn_left"] != 0: self.addToH(stepSize * self.speeds[0]) if self.controlMap["turn_right"] != 0: self.addToH(-stepSize * self.speeds[1]) if self.verticalState == "ground": # these actions require contact with the ground if self.controlMap["move_forward"] != 0: self.speed[1] = self.speeds[2] if self.controlMap["move_backward"] != 0: self.speed[1] = -self.speeds[3] if self.controlMap["move_left"] != 0: self.speed[0] = -self.speeds[4] if self.controlMap["move_right"] != 0: self.speed[0] = self.speeds[5] if self.controlMap["jump"] != 0: kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if self.controlMap["look_left"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if self.controlMap["look_right"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if self.controlMap["look_up"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if self.controlMap["look_down"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition(self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition(self.player_left_hand.getPos(render)) # Update the dialog box and thought windows # This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble["text_bg"] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble["frameColor"] = (0.6, 0.2, 0.1, 0.5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble["text"] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if ( (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0) ): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames("walk") if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose("walk", self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose("idle", 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
class Camera: """A floating 3rd person camera that follows an actor around, and can be turned left or right around the actor. Public fields: self.controlMap -- The camera's movement controls. actor -- The Actor object that the camera will follow. Public functions: init(actor) -- Initialise the camera. move(task) -- Move the camera each frame, following the assigned actor. This task is called every frame to update the camera. setControl -- Set the camera's turn left or turn right control on or off. """ def __init__(self, actor): """Initialise the camera, setting it to follow 'actor'. Arguments: actor -- The Actor that the camera will initially follow. """ self.actor = actor self.prevtime = 0 # The camera's controls: # "left" = move the camera left, 0 = off, 1 = on # "right" = move the camera right, 0 = off, 1 = on self.controlMap = {"left": 0, "right": 0} taskMgr.add(self.move, "cameraMoveTask") # Create a "floater" object. It is used to orient the camera above the # target actor's head. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(render) # Set up the camera. base.disableMouse() base.camera.setPos(self.actor.getX(), self.actor.getY() + 2, 2) # uncomment for topdown #base.camera.setPos(self.actor.getX(),self.actor.getY()+10,2) #base.camera.setHpr(180, -50, 0) # A CollisionRay beginning above the camera and going down toward the # ground is used to detect camera collisions and the height of the # camera above the ground. A ray may hit the terrain, or it may hit a # rock or a tree. If it hits the terrain, we detect the camera's # height. If it hits anything else, the camera is in an illegal # position. self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0, 0, 1000) self.groundRay.setDirection(0, 0, -1) self.groundCol = CollisionNode('camRay') self.groundCol.addSolid(self.groundRay) self.groundCol.setFromCollideMask(BitMask32.bit(1)) self.groundCol.setIntoCollideMask(BitMask32.allOff()) self.groundColNp = base.camera.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler) # Uncomment this line to see the collision rays #self.groundColNp.show() def move(self, task): """Update the camera's position before rendering the next frame. This is a task function and is called each frame by Panda3D. The camera follows self.actor, and tries to remain above the actor and above the ground (whichever is highest) while looking at a point slightly above the actor's head. Arguments: task -- A direct.task.Task object passed to this function by Panda3D. Return: Task.cont -- To tell Panda3D to call this task function again next frame. """ # FIXME: There is a bug with the camera -- if the actor runs up a # hill and then down again, the camera's Z position follows the actor # up the hill but does not come down again when the actor goes down # the hill. elapsed = task.time - self.prevtime # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. # comment out for topdown base.camera.lookAt(self.actor) camright = base.camera.getNetTransform().getMat().getRow3(0) camright.normalize() if (self.controlMap["left"] != 0): base.camera.setPos(base.camera.getPos() - camright * (elapsed * 20)) if (self.controlMap["right"] != 0): base.camera.setPos(base.camera.getPos() + camright * (elapsed * 20)) # If the camera is too far from the actor, move it closer. # If the camera is too close to the actor, move it farther. camvec = self.actor.getPos() - base.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if (camdist > 10.0): base.camera.setPos(base.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if (camdist < 5.0): base.camera.setPos(base.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Now check for collisions. self.cTrav.traverse(render) # Keep the camera at one foot above the terrain, # or two feet above the actor, whichever is greater. # comment out for topdown entries = [] for i in range(self.groundHandler.getNumEntries()): entry = self.groundHandler.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"): base.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if (base.camera.getZ() < self.actor.getZ() + 2.0): base.camera.setZ(self.actor.getZ() + 2.0) # The camera should look in the player's direction, # but it should also try to stay horizontal, so look at # a floater which hovers above the player's head. self.floater.setPos(self.actor.getPos()) self.floater.setZ(self.actor.getZ() + 2.0) #self.floater.setZ(self.actor.getZ() + 10.0) #self.floater.setY(self.actor.getY() + 7.0) # comment out for topdown base.camera.lookAt(self.floater) base.camera.setPos(self.floater.getPos()) # Store the task time and continue. self.prevtime = task.time return Task.cont def setControl(self, control, value): """Set the state of one of the camera's movement controls. Arguments: See self.controlMap in __init__. control -- The control to be set, must be a string matching one of the strings in self.controlMap. value -- The value to set the control to. """ # FIXME: this function is duplicated in Camera and Character, and # keyboard control settings are spread throughout the code. Maybe # add a Controllable class? self.controlMap[control] = value
class CameraManager: nextID = 0 def __init__(self, cameraNP): self.cameraNP = cameraNP self.id = CameraManager.nextID CameraManager.nextID += 1 self.otherNP = render self.lookAtNP = NodePath('CameraManager%d.lookAtNP' % self.id) self.lookAtEnabled = False self.targetPos = Point3(0.0, 0.0, 0.0) self.targetLookAtPos = Point3(0.0, 1.0, 0.0) self.enabled = False self.rate = 10.0 def destroy(self): if self.enabled: self.setEnabled(False) self.lookAtNP.removeNode() del self.lookAtNP del self.targetPos del self.targetLookAtPos del self.otherNP def setEnabled(self, enabled): if enabled != self.enabled: if enabled: taskMgr.add(self.updateTask, 'CameraManager%d.update' % self.id) else: taskMgr.remove('CameraManager%d.update' % self.id) self.enabled = enabled def setTargetPos(self, p): self.targetPos = p def setPos(self, p): self.targetPos = p self.cameraNP.setPos(self.otherNP, p) def setTargetLookAtPos(self, p): self.lookAtEnabled = True self.targetLookAtPos = p def setLookAtPos(self, p): self.lookAtEnabled = True self.targetLookAtPos = p self.lookAtNP.setPos(p) def setHpr(self, hpr): self.lookAtEnabled = False self.cameraNP.setHpr(self.otherNP, hpr) def updateTask(self, task): newCameraPos = self.rateInterpolate(self.cameraNP.getPos(self.otherNP), self.targetPos) self.cameraNP.setPos(self.otherNP, newCameraPos) if self.lookAtEnabled: newLookAtPos = self.rateInterpolate(self.lookAtNP.getPos(self.otherNP), self.targetLookAtPos) self.lookAtNP.setPos(self.otherNP, newLookAtPos) self.cameraNP.lookAt(self.lookAtNP) return task.cont def rateInterpolate(self, currentPos, targetPos): dt = globalClock.getDt() vec = currentPos - targetPos return targetPos + vec * inverse_e ** (dt * self.rate)
class Entity(ActorNode): def __init__(self, name, world, pos): ActorNode.__init__(self, name) self.nodePath = NodePath(self) self.world = world # init the model or the Actor self.model = self.getModel() self.model.reparentTo(self.nodePath) self.nodePath.setPos(*pos) self.prevPos = self.nodePath.getPos() # collision detection fromObject = self.nodePath.attachNewNode(CollisionNode(name)) self.addSolids(fromObject) fromObject.show() # setup the ground ray, needed for detecting the ground groundRay = CollisionRay() groundRay.setOrigin(0, 0, 1000) groundRay.setDirection(0, 0, -1) groundCol = CollisionNode('groundRay') groundCol.addSolid(groundRay) groundCol.setFromCollideMask(BitMask32.bit(0)) groundCol.setIntoCollideMask(BitMask32.allOff()) groundColNp = base.camera.attachNewNode(groundCol) self.groundHandler = CollisionHandlerQueue() self.world.cTrav.addCollider(groundColNp, self.groundHandler) # self.world.cTrav.addCollider(fromObject, self.world.pusher) # self.world.pusher.addCollider(fromObject, self.nodePath) self.postInit() def postInit(self): '''Subclasses can override this method to add stuff after the init''' pass def addSolids(self, fromObject): '''Subclasses can override this method to add sollids for collision detection to match their model and size. Below is a default''' fromObject.node().addSolid(CollisionSphere(0, 0, 0, 0.5)) def validateMove(self): # Make sure the entity is above the ground. groundEntry = self.world.getGroundEntry(self.groundHandler) if groundEntry is not None and groundEntry.getIntoNode().getName( ) == 'terrain': self.nodePath.setZ(groundEntry.getSurfacePoint(render).getZ()) else: self.nodePath.setPos(self.prevPos) def getGroundEntry(self, collisionHandler): '''Deprecated. Not used anymore''' # Put all the collision entries into a Python list so we can sort it, # properly. entries = [] for i in range(collisionHandler.getNumEntries()): entries.append(collisionHandler.getEntry(i)) # Sort the list by the collision points' Z values, making sure the # highest value ends up at the front of the list. entries.sort(lambda x, y: cmp( y.getSurfacePoint(render).getZ(), x.getSurfacePoint(render).getZ())) if len(entries) > 0: return entries[0] else: return None
class HtmlView(DirectObject): notify = DirectNotifyGlobal.directNotify.newCategory('HtmlView') useHalfTexture = config.GetBool('news-half-texture', 0) def __init__(self, parent = aspect2d): global GlobalWebcore self.parent = parent self.mx = 0 self.my = 0 self.htmlFile = 'index.html' self.transparency = False if GlobalWebcore: pass else: GlobalWebcore = AwWebCore(AwWebCore.LOGVERBOSE, True, AwWebCore.PFBGRA) GlobalWebcore.setBaseDirectory('.') for errResponse in xrange(400, 600): GlobalWebcore.setCustomResponsePage(errResponse, 'error.html') self.webView = GlobalWebcore.createWebView(WEB_WIDTH, WEB_HEIGHT, self.transparency, False, 70) frameName = '' inGameNewsUrl = self.getInGameNewsUrl() self.imgBuffer = array.array('B') for i in xrange(WEB_WIDTH * WEB_HEIGHT): self.imgBuffer.append(0) self.imgBuffer.append(0) self.imgBuffer.append(0) self.imgBuffer.append(255) if self.useHalfTexture: self.leftBuffer = array.array('B') for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT): self.leftBuffer.append(0) self.leftBuffer.append(0) self.leftBuffer.append(0) self.leftBuffer.append(255) self.rightBuffer = array.array('B') for i in xrange(WEB_HALF_WIDTH * WEB_HEIGHT): self.rightBuffer.append(0) self.rightBuffer.append(0) self.rightBuffer.append(0) self.rightBuffer.append(255) self.setupTexture() if self.useHalfTexture: self.setupHalfTextures() self.accept('mouse1', self.mouseDown, [AwWebView.LEFTMOUSEBTN]) self.accept('mouse3', self.mouseDown, [AwWebView.RIGHTMOUSEBTN]) self.accept('mouse1-up', self.mouseUp, [AwWebView.LEFTMOUSEBTN]) self.accept('mouse3-up', self.mouseUp, [AwWebView.RIGHTMOUSEBTN]) def getInGameNewsUrl(self): result = config.GetString('fallback-news-url', 'http://cdn.toontown.disney.go.com/toontown/en/gamenews/') override = config.GetString('in-game-news-url', '') if override: self.notify.info('got an override url, using %s for in a game news' % override) result = override else: try: launcherUrl = base.launcher.getValue('GAME_IN_GAME_NEWS_URL', '') if launcherUrl: result = launcherUrl self.notify.info('got GAME_IN_GAME_NEWS_URL from launcher using %s' % result) else: self.notify.info('blank GAME_IN_GAME_NEWS_URL from launcher, using %s' % result) except: self.notify.warning('got exception getting GAME_IN_GAME_NEWS_URL from launcher, using %s' % result) return result def setupTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH_PIXELS / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT_PIXELS) / float(WIN_HEIGHT) cm.setFrame(-htmlWidth / 2.0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) bottomRightX = WEB_WIDTH_PIXELS / float(WEB_WIDTH + 1) bottomRightY = WEB_HEIGHT_PIXELS / float(WEB_HEIGHT + 1) cm.setUvRange(Point2(0, 1 - bottomRightY), Point2(bottomRightX, 1)) card = cm.generate() self.quad = NodePath(card) self.quad.reparentTo(self.parent) self.guiTex = Texture('guiTex') self.guiTex.setupTexture(Texture.TT2dTexture, WEB_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.guiTex.setMinfilter(Texture.FTLinear) self.guiTex.setKeepRamImage(True) self.guiTex.makeRamImage() self.guiTex.setWrapU(Texture.WMRepeat) self.guiTex.setWrapV(Texture.WMRepeat) ts = TextureStage('webTS') self.quad.setTexture(ts, self.guiTex) self.quad.setTexScale(ts, 1.0, -1.0) self.quad.setTransparency(0) self.quad.setTwoSided(True) self.quad.setColor(1.0, 1.0, 1.0, 1.0) self.calcMouseLimits() def setupHalfTextures(self): self.setupLeftTexture() self.setupRightTexture() self.fullPnmImage = PNMImage(WEB_WIDTH, WEB_HEIGHT, 4) self.leftPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4) self.rightPnmImage = PNMImage(WEB_HALF_WIDTH, WEB_HEIGHT, 4) def setupLeftTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT) cm.setFrame(-htmlWidth / 2.0, 0, -htmlHeight / 2.0, htmlHeight / 2.0) card = cm.generate() self.leftQuad = NodePath(card) self.leftQuad.reparentTo(self.parent) self.leftGuiTex = Texture('guiTex') self.leftGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.leftGuiTex.setKeepRamImage(True) self.leftGuiTex.makeRamImage() self.leftGuiTex.setWrapU(Texture.WMClamp) self.leftGuiTex.setWrapV(Texture.WMClamp) ts = TextureStage('leftWebTS') self.leftQuad.setTexture(ts, self.leftGuiTex) self.leftQuad.setTexScale(ts, 1.0, -1.0) self.leftQuad.setTransparency(0) self.leftQuad.setTwoSided(True) self.leftQuad.setColor(1.0, 1.0, 1.0, 1.0) def setupRightTexture(self): cm = CardMaker('quadMaker') cm.setColor(1.0, 1.0, 1.0, 1.0) aspect = base.camLens.getAspectRatio() htmlWidth = 2.0 * aspect * WEB_WIDTH / float(WIN_WIDTH) htmlHeight = 2.0 * float(WEB_HEIGHT) / float(WIN_HEIGHT) cm.setFrame(0, htmlWidth / 2.0, -htmlHeight / 2.0, htmlHeight / 2.0) card = cm.generate() self.rightQuad = NodePath(card) self.rightQuad.reparentTo(self.parent) self.rightGuiTex = Texture('guiTex') self.rightGuiTex.setupTexture(Texture.TT2dTexture, WEB_HALF_WIDTH, WEB_HEIGHT, 1, Texture.TUnsignedByte, Texture.FRgba) self.rightGuiTex.setKeepRamImage(True) self.rightGuiTex.makeRamImage() self.rightGuiTex.setWrapU(Texture.WMClamp) self.rightGuiTex.setWrapV(Texture.WMClamp) ts = TextureStage('rightWebTS') self.rightQuad.setTexture(ts, self.rightGuiTex) self.rightQuad.setTexScale(ts, 1.0, -1.0) self.rightQuad.setTransparency(0) self.rightQuad.setTwoSided(True) self.rightQuad.setColor(1.0, 1.0, 1.0, 1.0) def calcMouseLimits(self): ll = Point3() ur = Point3() self.quad.calcTightBounds(ll, ur) self.notify.debug('ll=%s ur=%s' % (ll, ur)) offset = self.quad.getPos(aspect2d) self.notify.debug('offset = %s ' % offset) ll.setZ(ll.getZ() + offset.getZ()) ur.setZ(ur.getZ() + offset.getZ()) self.notify.debug('new LL=%s, UR=%s' % (ll, ur)) relPointll = self.quad.getRelativePoint(aspect2d, ll) self.notify.debug('relPoint = %s' % relPointll) self.mouseLL = (aspect2d.getScale()[0] * ll[0], aspect2d.getScale()[2] * ll[2]) self.mouseUR = (aspect2d.getScale()[0] * ur[0], aspect2d.getScale()[2] * ur[2]) self.notify.debug('original mouseLL=%s, mouseUR=%s' % (self.mouseLL, self.mouseUR)) def writeTex(self, filename = 'guiText.png'): self.notify.debug('writing texture') self.guiTex.generateRamMipmapImages() self.guiTex.write(filename) def toggleRotation(self): if self.interval.isPlaying(): self.interval.finish() else: self.interval.loop() def mouseDown(self, button): messenger.send('wakeup') self.webView.injectMouseDown(button) def mouseUp(self, button): self.webView.injectMouseUp(button) def reload(self): pass def zoomIn(self): self.webView.zoomIn() def zoomOut(self): self.webView.zoomOut() def toggleTransparency(self): self.transparency = not self.transparency self.webView.setTransparent(self.transparency) def update(self, task): if base.mouseWatcherNode.hasMouse(): x, y = self._translateRelativeCoordinates(base.mouseWatcherNode.getMouseX(), base.mouseWatcherNode.getMouseY()) if self.mx - x != 0 or self.my - y != 0: self.webView.injectMouseMove(x, y) self.mx, self.my = x, y if self.webView.isDirty(): self.webView.render(self.imgBuffer.buffer_info()[0], WEB_WIDTH * 4, 4) Texture.setTexturesPower2(2) textureBuffer = self.guiTex.modifyRamImage() textureBuffer.setData(self.imgBuffer.tostring()) if self.useHalfTexture: self.guiTex.store(self.fullPnmImage) self.leftPnmImage.copySubImage(self.fullPnmImage, 0, 0, 0, 0, WEB_HALF_WIDTH, WEB_HEIGHT) self.rightPnmImage.copySubImage(self.fullPnmImage, 0, 0, WEB_HALF_WIDTH, 0, WEB_HALF_WIDTH, WEB_HEIGHT) self.leftGuiTex.load(self.leftPnmImage) self.rightGuiTex.load(self.rightPnmImage) self.quad.hide() Texture.setTexturesPower2(1) GlobalWebcore.update() return Task.cont def _translateRelativeCoordinates(self, x, y): sx = int((x - self.mouseLL[0]) / (self.mouseUR[0] - self.mouseLL[0]) * WEB_WIDTH_PIXELS) sy = WEB_HEIGHT_PIXELS - int((y - self.mouseLL[1]) / (self.mouseUR[1] - self.mouseLL[1]) * WEB_HEIGHT_PIXELS) return (sx, sy) def unload(self): self.ignoreAll() self.webView.destroy() self.webView = None return def onCallback(self, name, args): if name == 'requestFPS': pass def onBeginNavigation(self, url, frameName): pass def onBeginLoading(self, url, frameName, statusCode, mimeType): pass def onFinishLoading(self): self.notify.debug('finished loading') def onReceiveTitle(self, title, frameName): pass def onChangeTooltip(self, tooltip): pass def onChangeCursor(self, cursor): pass def onChangeKeyboardFocus(self, isFocused): pass def onChangeTargetURL(self, url): pass
class PartyCogActivityLocalPlayer(PartyCogActivityPlayer): def __init__(self, activity, position, team, exitActivityCallback=None): PartyCogActivityPlayer.__init__(self, activity, base.localAvatar, position, team) self.input = PartyCogActivityInput(exitActivityCallback) self.gui = PartyCogActivityGui() self.throwPiePrevTime = 0 self.lastMoved = 0 if base.localAvatar: self.prevPos = base.localAvatar.getPos() self.cameraManager = None self.control = None self.consecutiveShortThrows = 0 return def destroy(self): if self.enabled: self.disable() if self.cameraManager is not None: self.cameraManager.setEnabled(False) self.cameraManager.destroy() del self.cameraManager del self.gui del self.input if self.control is not None: self.control.destroy() del self.control PartyCogActivityPlayer.destroy(self) return def _initOrthoWalk(self): orthoDrive = OrthoDrive(9.778, customCollisionCallback=self.activity.view. checkOrthoDriveCollision) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True) def _destroyOrthoWalk(self): self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk def getPieThrowingPower(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) w = 1.0 / PartyGlobals.CogActivityPowerMeterTime * 2.0 * math.pi power = int(round(-math.cos(w * elapsed) * 50.0 + 50.0)) return power def isShortThrow(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) return elapsed <= PartyGlobals.CogActivityShortThrowTime def checkForThrowSpam(self, time): if self.isShortThrow(time): self.consecutiveShortThrows += 1 else: self.consecutiveShortThrows = 0 return self.consecutiveShortThrows >= PartyGlobals.CogActivityShortThrowSpam def _startUpdateTask(self): task = Task(self._updateTask) task.lastPositionBroadcastTime = 0.0 self.throwPiePrevTime = 0 taskMgr.add(task, UPDATE_TASK_NAME) def _stopUpdateTask(self): taskMgr.remove(UPDATE_TASK_NAME) def _updateTask(self, task): self._update() if base.localAvatar.getPos() != self.prevPos: self.prevPos = base.localAvatar.getPos() self.lastMoved = self.activity.getCurrentActivityTime() if max(self.activity.getCurrentActivityTime() - self.lastMoved, 0) > PartyGlobals.ToonMoveIdleThreshold: self.gui.showMoveControls() if max(self.activity.getCurrentActivityTime() - self.throwPiePrevTime, 0) > PartyGlobals.ToonAttackIdleThreshold: self.gui.showAttackControls() if self.input.throwPieWasReleased: if self.checkForThrowSpam(globalClock.getFrameTime()): self.gui.showSpamWarning() self.input.throwPieWasReleased = False self.throwPie(self.getPieThrowingPower(globalClock.getFrameTime())) return Task.cont def throwPie(self, piePower): if not self.activity.isState('Active'): return if self.activity.getCurrentActivityTime( ) - self.throwPiePrevTime > THROW_PIE_LIMIT_TIME: self.throwPiePrevTime = self.activity.getCurrentActivityTime() self.activity.b_pieThrow(self.toon, piePower) def _update(self): self.control.update() def getLookat(self, whosLooking, refNode=None): if refNode is None: refNode = render dist = 5.0 oldParent = self.tempNP.getParent() self.tempNP.reparentTo(whosLooking) self.tempNP.setPos(0.0, dist, 0.0) pos = self.tempNP.getPos(refNode) self.tempNP.reparentTo(oldParent) return pos def entersActivity(self): base.cr.playGame.getPlace().setState('activity') PartyCogActivityPlayer.entersActivity(self) self.gui.disableToontownHUD() self.cameraManager = CameraManager(camera) self.tempNP = NodePath('temp') self.lookAtMyTeam() self.control = StrafingControl(self) def exitsActivity(self): PartyCogActivityPlayer.exitsActivity(self) self.gui.enableToontownHUD() self.cameraManager.setEnabled(False) self.tempNP.removeNode() self.tempNP = None if not aspect2d.find('**/JellybeanRewardGui*'): base.cr.playGame.getPlace().setState('walk') else: self.toon.startPosHprBroadcast() return def getRunToStartPositionIval(self): targetH = self.locator.getH() travelVec = self.position - self.toon.getPos(self.activity.root) duration = travelVec.length() / 9.778 startH = 0.0 if travelVec.getY() < 0.0: startH = 180.0 return Sequence( Func(self.toon.startPosHprBroadcast, 0.1), Func(self.toon.b_setAnimState, 'run'), Parallel( self.toon.hprInterval(0.5, VBase3(startH, 0.0, 0.0), other=self.activity.root), self.toon.posInterval(duration, self.position, other=self.activity.root)), Func(self.toon.b_setAnimState, 'neutral'), self.toon.hprInterval(0.25, VBase3(targetH, 0.0, 0.0), other=self.activity.root), Func(self.toon.stopPosHprBroadcast)) def enable(self): if self.enabled: return PartyCogActivityPlayer.enable(self) self.toon.b_setAnimState('Happy') self._initOrthoWalk() self.orthoWalk.start() self.orthoWalking = True self.input.enable() self.gui.disableToontownHUD() self.gui.load() self.gui.setScore(0) self.gui.showScore() self.gui.setTeam(self.team) self.gui.startTrackingCogs(self.activity.view.cogManager.cogs) self.control.enable() self._startUpdateTask() def disable(self): if not self.enabled: return self._stopUpdateTask() self.toon.b_setAnimState('neutral') PartyCogActivityPlayer.disable(self) self.orthoWalking = False self.orthoWalk.stop() self._destroyOrthoWalk() self.input.disable() self._aimMode = False self.cameraManager.setEnabled(False) self.gui.hide() self.gui.stopTrackingCogs() self.gui.unload() def updateScore(self): self.gui.setScore(self.score) def b_updateToonPosition(self): self.updateToonPosition() self.d_updateToonPosition() def d_updateToonPosition(self): self.toon.d_setPos(self.toon.getX(), self.toon.getY(), self.toon.getZ()) self.toon.d_setH(self.toon.getH()) def lookAtArena(self): self.cameraManager.setEnabled(True) self.cameraManager.setTargetPos( self.activity.view.arena.find( '**/conclusionCamPos_locator').getPos(render)) self.cameraManager.setTargetLookAtPos( self.activity.view.arena.find( '**/conclusionCamAim_locator').getPos(render)) def lookAtMyTeam(self): activityView = self.activity.view arena = activityView.arena pos = activityView.teamCamPosLocators[self.team].getPos() aim = activityView.teamCamAimLocators[self.team].getPos() camera.wrtReparentTo(arena) self.cameraManager.setPos(camera.getPos(render)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, pos) self.cameraManager.setTargetPos(self.tempNP.getPos(render)) self.cameraManager.setLookAtPos(self.getLookat(camera)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, aim) self.cameraManager.setTargetLookAtPos(self.tempNP.getPos(render)) self.cameraManager.setEnabled(True) camera.setP(0.0) camera.setR(0.0)
class PartyCogActivityLocalPlayer(PartyCogActivityPlayer): def __init__(self, activity, position, team, exitActivityCallback = None): PartyCogActivityPlayer.__init__(self, activity, base.localAvatar, position, team) self.input = PartyCogActivityInput(exitActivityCallback) self.gui = PartyCogActivityGui() self.throwPiePrevTime = 0 self.lastMoved = 0 if base.localAvatar: self.prevPos = base.localAvatar.getPos() self.cameraManager = None self.control = None self.consecutiveShortThrows = 0 return def destroy(self): if self.enabled: self.disable() if self.cameraManager is not None: self.cameraManager.setEnabled(False) self.cameraManager.destroy() del self.cameraManager del self.gui del self.input if self.control is not None: self.control.destroy() del self.control PartyCogActivityPlayer.destroy(self) return def _initOrthoWalk(self): orthoDrive = OrthoDrive(9.778, customCollisionCallback=self.activity.view.checkOrthoDriveCollision) self.orthoWalk = OrthoWalk(orthoDrive, broadcast=True) def _destroyOrthoWalk(self): self.orthoWalk.stop() self.orthoWalk.destroy() del self.orthoWalk def getPieThrowingPower(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) w = 1.0 / PartyGlobals.CogActivityPowerMeterTime * 2.0 * math.pi power = int(round(-math.cos(w * elapsed) * 50.0 + 50.0)) return power def isShortThrow(self, time): elapsed = max(time - self.input.throwPiePressedStartTime, 0.0) return elapsed <= PartyGlobals.CogActivityShortThrowTime def checkForThrowSpam(self, time): if self.isShortThrow(time): self.consecutiveShortThrows += 1 else: self.consecutiveShortThrows = 0 return self.consecutiveShortThrows >= PartyGlobals.CogActivityShortThrowSpam def _startUpdateTask(self): task = Task(self._updateTask) task.lastPositionBroadcastTime = 0.0 self.throwPiePrevTime = 0 taskMgr.add(task, UPDATE_TASK_NAME) def _stopUpdateTask(self): taskMgr.remove(UPDATE_TASK_NAME) def _updateTask(self, task): self._update() if base.localAvatar.getPos() != self.prevPos: self.prevPos = base.localAvatar.getPos() self.lastMoved = self.activity.getCurrentActivityTime() if max(self.activity.getCurrentActivityTime() - self.lastMoved, 0) > PartyGlobals.ToonMoveIdleThreshold: self.gui.showMoveControls() if max(self.activity.getCurrentActivityTime() - self.throwPiePrevTime, 0) > PartyGlobals.ToonAttackIdleThreshold: self.gui.showAttackControls() if self.input.throwPieWasReleased: if self.checkForThrowSpam(globalClock.getFrameTime()): self.gui.showSpamWarning() self.input.throwPieWasReleased = False self.throwPie(self.getPieThrowingPower(globalClock.getFrameTime())) return Task.cont def throwPie(self, piePower): if not self.activity.isState('Active'): return if self.activity.getCurrentActivityTime() - self.throwPiePrevTime > THROW_PIE_LIMIT_TIME: self.throwPiePrevTime = self.activity.getCurrentActivityTime() self.activity.b_pieThrow(self.toon, piePower) def _update(self): self.control.update() def getLookat(self, whosLooking, refNode = None): if refNode is None: refNode = render dist = 5.0 oldParent = self.tempNP.getParent() self.tempNP.reparentTo(whosLooking) self.tempNP.setPos(0.0, dist, 0.0) pos = self.tempNP.getPos(refNode) self.tempNP.reparentTo(oldParent) return pos def entersActivity(self): base.cr.playGame.getPlace().setState('activity') PartyCogActivityPlayer.entersActivity(self) self.gui.disableToontownHUD() self.cameraManager = CameraManager(camera) self.tempNP = NodePath('temp') self.lookAtMyTeam() self.control = StrafingControl(self) def exitsActivity(self): PartyCogActivityPlayer.exitsActivity(self) self.gui.enableToontownHUD() self.cameraManager.setEnabled(False) self.tempNP.removeNode() self.tempNP = None if not aspect2d.find('**/JellybeanRewardGui*'): base.cr.playGame.getPlace().setState('walk') else: self.toon.startPosHprBroadcast() return def getRunToStartPositionIval(self): targetH = self.locator.getH() travelVec = self.position - self.toon.getPos(self.activity.root) duration = travelVec.length() / 9.778 startH = 0.0 if travelVec.getY() < 0.0: startH = 180.0 return Sequence(Func(self.toon.startPosHprBroadcast, 0.1), Func(self.toon.b_setAnimState, 'run'), Parallel(self.toon.hprInterval(0.5, VBase3(startH, 0.0, 0.0), other=self.activity.root), self.toon.posInterval(duration, self.position, other=self.activity.root)), Func(self.toon.b_setAnimState, 'neutral'), self.toon.hprInterval(0.25, VBase3(targetH, 0.0, 0.0), other=self.activity.root), Func(self.toon.stopPosHprBroadcast)) def enable(self): if self.enabled: return PartyCogActivityPlayer.enable(self) self.toon.b_setAnimState('Happy') self._initOrthoWalk() self.orthoWalk.start() self.orthoWalking = True self.input.enable() self.gui.disableToontownHUD() self.gui.load() self.gui.setScore(0) self.gui.showScore() self.gui.setTeam(self.team) self.gui.startTrackingCogs(self.activity.view.cogManager.cogs) self.control.enable() self._startUpdateTask() def disable(self): if not self.enabled: return self._stopUpdateTask() self.toon.b_setAnimState('neutral') PartyCogActivityPlayer.disable(self) self.orthoWalking = False self.orthoWalk.stop() self._destroyOrthoWalk() self.input.disable() self._aimMode = False self.cameraManager.setEnabled(False) self.gui.hide() self.gui.stopTrackingCogs() self.gui.unload() def updateScore(self): self.gui.setScore(self.score) def b_updateToonPosition(self): self.updateToonPosition() self.d_updateToonPosition() def d_updateToonPosition(self): self.toon.d_setPos(self.toon.getX(), self.toon.getY(), self.toon.getZ()) self.toon.d_setH(self.toon.getH()) def lookAtArena(self): self.cameraManager.setEnabled(True) self.cameraManager.setTargetPos(self.activity.view.arena.find('**/conclusionCamPos_locator').getPos(render)) self.cameraManager.setTargetLookAtPos(self.activity.view.arena.find('**/conclusionCamAim_locator').getPos(render)) def lookAtMyTeam(self): activityView = self.activity.view arena = activityView.arena pos = activityView.teamCamPosLocators[self.team].getPos() aim = activityView.teamCamAimLocators[self.team].getPos() camera.wrtReparentTo(arena) self.cameraManager.setPos(camera.getPos(render)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, pos) self.cameraManager.setTargetPos(self.tempNP.getPos(render)) self.cameraManager.setLookAtPos(self.getLookat(camera)) self.tempNP.reparentTo(arena) self.tempNP.setPos(arena, aim) self.cameraManager.setTargetLookAtPos(self.tempNP.getPos(render)) self.cameraManager.setEnabled(True) camera.setP(0.0) camera.setR(0.0)