Exemple #1
0
 def shoot(self, rangeVector):
     if not self.gag:
         return
     rangeNode = NodePath('Shoot Range')
     rangeNode.reparentTo(self.turret.getCannon())
     rangeNode.setScale(render, 1)
     rangeNode.setPos(rangeVector)
     rangeNode.setHpr(90, -90, 90)
     self.gag.setScale(self.gag.getScale(render))
     self.gag.setScale(self.gag.getScale(render))
     self.gag.setPos(self.gag.getPos(render))
     self.gag.reparentTo(render)
     self.gag.setHpr(rangeNode.getHpr(render))
     base.audio3d.attachSoundToObject(self.gagClass.woosh, self.gag)
     self.gagClass.woosh.play()
     self.track = ProjectileInterval(self.gag, startPos=self.gag.getPos(render), endPos=rangeNode.getPos(render), gravityMult=self.gravityMult, duration=self.duration, name=self.trackName)
     self.track.setDoneEvent(self.track.getName())
     self.acceptOnce(self.track.getDoneEvent(), self.cleanup)
     self.track.start()
     fireSfx = base.audio3d.loadSfx('phase_4/audio/sfx/MG_cannon_fire_alt.mp3')
     base.audio3d.attachSoundToObject(fireSfx, self.turret.getCannon())
     fireSfx.play()
     if self.turret.isLocal():
         self.buildCollisions()
         self.acceptOnce(self.eventName, self.handleCollision)
Exemple #2
0
 def __doThrow(self, alreadyThrown):
     self.weapon.setScale(1)
     pathNP = NodePath('throwPath')
     if not alreadyThrown:
         pathNP.reparentTo(self.suit)
     else:
         pathNP.reparentTo(self.weapon)
     pathNP.setScale(render, 1.0)
     pathNP.setPos(0, 30, -100)
     pathNP.setHpr(90, -90, 90)
     print pathNP.getPos(base.render)
     if self.throwTrajectory:
         self.throwTrajectory.pause()
         self.throwTrajectory = None
     if alreadyThrown:
         startPos = self.weapon.getPos(base.render)
         gravity = 0.7
     else:
         gravity = 0.7
         startPos = self.suit.find('**/joint_Rhold').getPos(base.render)
     self.throwTrajectory = ProjectileInterval(self.weapon, startPos=startPos, endPos=pathNP.getPos(base.render), gravityMult=gravity, duration=3.0)
     self.throwTrajectory.start()
     self.weapon.setScale(10)
     self.weapon.reparentTo(render)
     self.weapon.setHpr(pathNP.getHpr(render))
     self.weapon_state = 'released'
     self.acceptOnce(self.wsnp.node().getName() + '-into', self.__handleHitFloor)
     return
Exemple #3
0
 def __init__(self, toon, mg):
     self.mg = mg
     self.toon = toon
     self.splat = Actor(GagGlobals.SPLAT_MDL,
                        {'chan': GagGlobals.SPLAT_CHAN})
     self.splat.setScale(0.5)
     self.splat.setColor(
         VBase4(250.0 / 255.0, 241.0 / 255.0, 24.0 / 255.0, 1.0))
     self.splat.setBillboardPointEye()
     self.gc = WholeCreamPie()
     self.gc.build()
     self.gag = self.gc.getGag()
     self.toon.play('toss', fromFrame=60, toFrame=85)
     self.gag.reparentTo(self.toon.find('**/def_joint_right_hold'))
     throwPath = NodePath('ThrowPath')
     throwPath.reparentTo(self.toon)
     throwPath.setScale(render, 1)
     throwPath.setPos(0, 150, -90)
     throwPath.setHpr(90, -90, 90)
     self.gag.wrtReparentTo(render)
     self.gag.setHpr(throwPath.getHpr(render))
     self.track = ProjectileInterval(
         self.gag,
         startPos=self.toon.find('**/def_joint_right_hold').getPos(render),
         endPos=throwPath.getPos(render),
         gravityMult=0.9,
         duration=3)
     self.track.start()
     taskMgr.doMethodLater(3, self.__handleThrowTrackDone,
                           'handleThrowTrackDoneDGP-' + str(hash(self)))
Exemple #4
0
 def gagRelease(self, task):
     gagRange = NodePath('Gag Range')
     gagRange.reparentTo(self.localAvatar.find('**/joint_nameTag'))
     gagRange.setPos(0, 75, 0)
     gagRange.setHpr(90, -90, 90)
     if self.gag == None:
         gagRange.removeNode()
         base.taskMgr.doMethodLater(0.1, self.enableThrowing, 'Enable Gag Throw')
         return
     else:
         if self.height > 1:
             grav = 0.7 + self.height / 10
         else:
             grav = 0.7
         if self.height > 5.2:
             base.taskMgr.add(self.enableThrowing, 'Enable Gag Throw')
             return
         self.gag.reparentTo(render)
         self.gag.setHpr(gagRange.getHpr(render))
         self.gagMgr.getGagByName(self.currentGag).addCollision(self.gag)
         handJoint = self.localAvatar.find('**/def_joint_right_hold')
         startPos = Vec3(handJoint.getPos(render).getX(), handJoint.getPos(render).getY(), handJoint.getPos(render).getZ() + 0.8)
         self.projectile = ProjectileInterval(self.gag, startPos=startPos, endPos=gagRange.getPos(render), duration=1, gravityMult=grav)
         self.projectile.start()
         SoundBank.getSound('pie_throw').play()
         base.taskMgr.doMethodLater(0.8, self.enableThrowing, 'Enable Gag Throw')
         base.taskMgr.doMethodLater(2, self.destroyGag, 'Destroy Gag', extraArgs = [self.gag, self.projectile], appendTask = True)
         base.accept('delete-up', self.null)
         base.accept('p-up', self.null)
         self.throwingPie = False
         return Task.done
 def throwObject(self, projectile=True):
     if not self.weapon:
         return
     self.acceptOnce('enter' + self.wsnp.node().getName(), self.handleWeaponCollision)
     self.playWeaponSound()
     if self.weapon:
         self.weapon.wrtReparentTo(render)
         self.weapon.setHpr(Vec3(0, 0, 0))
     if self.attack not in ('glowerpower', ):
         parent = self.suit.find('**/joint_Rhold')
     else:
         parent = self.suit.find('**/joint_head')
     startNP = parent.attachNewNode('startNp')
     startNP.lookAt(render, self.targetX, self.targetY, self.targetZ)
     pathNP = NodePath('throwPath')
     pathNP.reparentTo(startNP)
     pathNP.setScale(render, 1.0)
     pathNP.setPos(0, 50, 0)
     if self.attack in ('clipontie', 'powertie', 'halfwindsor'):
         self.weapon.setHpr(pathNP.getHpr(render))
     if projectile == True:
         self.throwTrajectory = ProjectileInterval(self.weapon, startPos=self.suit.find('**/joint_Rhold').getPos(render), endPos=pathNP.getPos(render), gravityMult=0.7, duration=1.0)
     else:
         self.weapon.setH(pathNP.getH(render))
         self.throwTrajectory = LerpPosInterval(self.weapon, duration=0.5, pos=pathNP.getPos(render), startPos=startNP.getPos(render) + (0,
                                                                                                                                         3,
                                                                                                                                         0))
     self.throwTrajectory.start()
     self.weapon_state = 'released'
     startNP.removeNode()
     del startNP
     pathNP.removeNode()
     del pathNP
 def __doThrow(self, alreadyThrown):
     self.weapon.setScale(1)
     pathNP = NodePath('throwPath')
     if not alreadyThrown:
         pathNP.reparentTo(self.suit)
     else:
         pathNP.reparentTo(self.weapon)
     pathNP.setScale(render, 1.0)
     pathNP.setPos(0, 30, -100)
     pathNP.setHpr(90, -90, 90)
     print pathNP.getPos(base.render)
     if self.throwTrajectory:
         self.throwTrajectory.pause()
         self.throwTrajectory = None
     if alreadyThrown:
         startPos = self.weapon.getPos(base.render)
         gravity = 0.7
     else:
         gravity = 0.7
         startPos = self.suit.find('**/joint_Rhold').getPos(base.render)
     self.throwTrajectory = ProjectileInterval(self.weapon, startPos=startPos, endPos=pathNP.getPos(base.render), gravityMult=gravity, duration=3.0)
     self.throwTrajectory.start()
     self.weapon.setScale(10)
     self.weapon.reparentTo(render)
     self.weapon.setHpr(pathNP.getHpr(render))
     self.weapon_state = 'released'
     self.acceptOnce(self.wsnp.node().getName() + '-into', self.__handleHitFloor)
     return
    def release(self):
        throwPath = NodePath('ThrowPath')
        throwPath.reparentTo(self.avatar)
        throwPath.setScale(render, 1)
        throwPath.setPos(0, 160, -120)
        throwPath.setHpr(0, 90, 0)

        if not self.gag:
            self.build()

        self.entity = self.gag
        self.gag = None
        self.entity.wrtReparentTo(render)
        self.entity.setHpr(throwPath.getHpr(render))

        self.setHandJoint()
        self.track = ProjectileInterval(self.entity,
                                        startPos=self.handJoint.getPos(render),
                                        endPos=throwPath.getPos(render),
                                        gravityMult=0.9,
                                        duration=3)
        self.track.start()

        if self.isLocal():
            self.startTimeout()
            self.buildCollisions()
            self.avatar.acceptOnce('gagSensor-into', self.onCollision)

        self.reset()
        TrapGag.release(self)
 def release(self):
     Gag.release(self)
     base.audio3d.attachSoundToObject(self.woosh, self.gag)
     base.playSfx(self.woosh, node=self.gag)
     throwPath = NodePath('ThrowPath')
     throwPath.reparentTo(self.avatar)
     throwPath.setScale(render, 1)
     throwPath.setPos(0, self.power, -90)
     throwPath.setHpr(90, -90, 90)
     entity = self.gag
     if not entity:
         entity = self.build()
     entity.wrtReparentTo(render)
     entity.setHpr(throwPath.getHpr(render))
     self.gag = None
     if not self.handJoint:
         self.handJoint = self.avatar.find('**/def_joint_right_hold')
     track = ProjectileInterval(entity, startPos=self.handJoint.getPos(render), endPos=throwPath.getPos(render), gravityMult=0.9, duration=3)
     event = self.avatar.uniqueName('throwIvalDone') + '-' + str(hash(entity))
     track.setDoneEvent(event)
     base.acceptOnce(event, self.__handlePieIvalDone, [entity])
     track.start()
     self.entities.append([entity, track])
     if self.isLocal():
         self.buildCollisions(entity)
         base.localAvatar.sendUpdate('usedGag', [self.id])
     self.reset()
     return
Exemple #9
0
    def throw(self):
        if not self.gag and not self.isLocal():
            self.setHandJoint()
            self.build()
        if self.gag and self.getLocation():
            self.startEntity()
        elif self.gag and self.trapMode == 1:
            throwPath = NodePath('ThrowPath')
            throwPath.reparentTo(self.avatar)
            throwPath.setScale(render, 1)
            throwPath.setPos(0, 160, -120)
            throwPath.setHpr(0, 90, 0)

            self.gag.setScale(self.gag.getScale(render))
            self.gag.reparentTo(render)
            self.gag.setHpr(throwPath.getHpr(render))

            self.setHandJoint()
            self.track = ProjectileInterval(
                self.gag,
                startPos=self.handJoint.getPos(render),
                endPos=throwPath.getPos(render),
                gravityMult=0.9,
                duration=3)
            self.track.start()
            self.buildProjCollisions()
            self.reset()
            self.avatar.acceptOnce('projSensor-into', self.onProjCollision)
Exemple #10
0
 def shoot(self, rangeVector):
     if not self.gag:
         return
     rangeNode = NodePath('Shoot Range')
     rangeNode.reparentTo(self.turret.getCannon())
     rangeNode.setScale(render, 1)
     rangeNode.setPos(rangeVector)
     rangeNode.setHpr(90, -90, 90)
     self.gag.setScale(self.gag.getScale(render))
     self.gag.setScale(self.gag.getScale(render))
     self.gag.setPos(self.gag.getPos(render))
     self.gag.reparentTo(render)
     self.gag.setHpr(rangeNode.getHpr(render))
     base.audio3d.attachSoundToObject(self.gagClass.woosh, self.gag)
     self.gagClass.woosh.play()
     self.track = ProjectileInterval(self.gag,
                                     startPos=self.gag.getPos(render),
                                     endPos=rangeNode.getPos(render),
                                     gravityMult=self.gravityMult,
                                     duration=self.duration,
                                     name=self.trackName)
     self.track.setDoneEvent(self.track.getName())
     self.acceptOnce(self.track.getDoneEvent(), self.cleanup)
     self.track.start()
     fireSfx = base.audio3d.loadSfx(
         'phase_4/audio/sfx/MG_cannon_fire_alt.ogg')
     base.audio3d.attachSoundToObject(fireSfx, self.turret.getCannon())
     fireSfx.play()
     if self.turret.isLocal():
         self.buildCollisions()
         self.acceptOnce(self.eventName, self.handleCollision)
Exemple #11
0
 def throwObject(self, projectile = True):
     if not self.weapon:
         return
     self.acceptOnce('enter' + self.wsnp.node().getName(), self.handleWeaponCollision)
     self.playWeaponSound()
     if self.weapon:
         self.weapon.wrtReparentTo(render)
         self.weapon.setHpr(Vec3(0, 0, 0))
     if self.attack not in ('glowerpower',):
         parent = self.suit.find('**/joint_Rhold')
     else:
         parent = self.suit.find('**/joint_head')
     startNP = parent.attachNewNode('startNp')
     startNP.lookAt(render, self.targetX, self.targetY, self.targetZ)
     pathNP = NodePath('throwPath')
     pathNP.reparentTo(startNP)
     pathNP.setScale(render, 1.0)
     pathNP.setPos(0, 50, 0)
     if self.attack in ('clipontie', 'powertie', 'halfwindsor'):
         self.weapon.setHpr(pathNP.getHpr(render))
     if projectile == True:
         self.throwTrajectory = ProjectileInterval(self.weapon, startPos=self.suit.find('**/joint_Rhold').getPos(render), endPos=pathNP.getPos(render), gravityMult=0.7, duration=1.0)
     else:
         self.weapon.setH(pathNP.getH(render))
         self.throwTrajectory = LerpPosInterval(self.weapon, duration=0.5, pos=pathNP.getPos(render), startPos=startNP.getPos(render) + (0, 3, 0))
     self.throwTrajectory.start()
     self.weapon_state = 'released'
     startNP.removeNode()
     del startNP
     pathNP.removeNode()
     del pathNP
Exemple #12
0
 def release(self):
     TrapGag.release(self)
     throwPath = NodePath('ThrowPath')
     throwPath.reparentTo(self.avatar)
     throwPath.setScale(render, 1)
     throwPath.setPos(0, 160, -120)
     throwPath.setHpr(0, 90, 0)
     if not self.gag:
         self.build()
     self.gag.wrtReparentTo(render)
     self.gag.setHpr(throwPath.getHpr(render))
     self.setHandJoint()
     self.track = ProjectileInterval(self.gag, startPos=self.handJoint.getPos(render), endPos=throwPath.getPos(render), gravityMult=0.9, duration=3)
     self.track.start()
     if base.localAvatar == self.avatar:
         self.buildCollisions()
         self.avatar.acceptOnce('gagSensor-into', self.onCollision)
     self.reset()
Exemple #13
0
 def throw(self):
     if not self.gag and not self.isLocal():
         self.setHandJoint()
         self.build()
     if self.gag and self.getLocation():
         self.startEntity()
     elif self.gag and self.trapMode == 1:
         throwPath = NodePath('ThrowPath')
         throwPath.reparentTo(self.avatar)
         throwPath.setScale(render, 1)
         throwPath.setPos(0, 160, -120)
         throwPath.setHpr(0, 90, 0)
         self.gag.setScale(self.gag.getScale(render))
         self.gag.reparentTo(render)
         self.gag.setHpr(throwPath.getHpr(render))
         self.setHandJoint()
         self.track = ProjectileInterval(self.gag, startPos=self.handJoint.getPos(render), endPos=throwPath.getPos(render), gravityMult=0.9, duration=3)
         self.track.start()
         self.buildProjCollisions()
         self.reset()
         self.avatar.acceptOnce('projSensor-into', self.onProjCollision)
         if self.isLocal():
             base.localAvatar.enablePieKeys()
    def save(self, filePath=None):
        if filePath == None:
            filePath = self.fromFile

        config = []
        for element in self.elements:
            np = NodePath(element)
            
            od = {}

            od["type"] = element.getTypeName()
            od["pos"] = tuple(np.getPos())
            od["rot"] = tuple(np.getHpr())

            if element.getSkin() is not None:
                od["skin"] = element.getSkin()

            if element.getTypeName() == "Pinger":
                od["frequency"] = element.pinger_frequency

            config.append(od)

        plistlib.writePlist(config, filePath)
Exemple #15
0
    def save(self, filePath=None):
        if filePath == None:
            filePath = self.fromFile

        config = []
        for element in self.elements:
            np = NodePath(element)

            od = {}

            od["type"] = element.getTypeName()
            od["pos"] = tuple(np.getPos())
            od["rot"] = tuple(np.getHpr())

            if element.getSkin() is not None:
                od["skin"] = element.getSkin()

            if element.getTypeName() == "Pinger":
                od["frequency"] = element.pinger_frequency

            config.append(od)

        plistlib.writePlist(config, filePath)
Exemple #16
0
 def release(self):
     Gag.release(self)
     base.audio3d.attachSoundToObject(self.woosh, self.gag)
     self.woosh.play()
     throwPath = NodePath('ThrowPath')
     throwPath.reparentTo(self.avatar)
     throwPath.setScale(render, 1)
     throwPath.setPos(0, 160, -90)
     throwPath.setHpr(90, -90, 90)
     entity = self.gag
     if not entity:
         entity = self.build()
     entity.wrtReparentTo(render)
     entity.setHpr(throwPath.getHpr(render))
     self.gag = None
     if not self.handJoint:
         self.handJoint = self.avatar.find('**/def_joint_right_hold')
     track = ProjectileInterval(entity, startPos=self.handJoint.getPos(render), endPos=throwPath.getPos(render), gravityMult=0.9, duration=3)
     track.start()
     self.entities.append([entity, track])
     if self.isLocal():
         self.buildCollisions(entity)
     self.reset()
     return
    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)
Exemple #18
0
class SpotLight(Light, DebugObject):

    """ This light type simulates a SpotLight. It has a position
    and an orientation. """

    def __init__(self):
        """ Creates a new spot light. """
        Light.__init__(self)
        DebugObject.__init__(self, "SpotLight")
        self.typeName = "SpotLight"

        self.nearPlane = 0.5
        self.radius = 30.0
        self.spotSize = Vec2(30, 30)

        # Used to compute the MVP
        self.ghostCamera = Camera("PointLight")
        self.ghostCamera.setActive(False)
        self.ghostLens = PerspectiveLens()
        self.ghostLens.setFov(130)
        self.ghostCamera.setLens(self.ghostLens)
        self.ghostCameraNode = NodePath(self.ghostCamera)
        self.ghostCameraNode.reparentTo(Globals.render)
        self.ghostCameraNode.hide()

    def getLightType(self):
        """ Internal method to fetch the type of this light, used by Light """
        return LightType.Spot

    def _updateLens(self):
        """ Internal method which gets called when the lens properties changed """
        for source in self.shadowSources:
            source.rebuildMatrixCache()

    def cleanup(self):
        """ Internal method which gets called when the light got deleted """
        self.ghostCameraNode.removeNode()
        Light.cleanup(self)

    def setFov(self, fov):
        """ Sets the field of view of the spotlight """
        assert(fov > 1 and fov < 180)
        self.ghostLens.setFov(fov)
        self._updateLens()

    def setPos(self, pos):
        """ Sets the position of the spotlight """
        self.ghostCameraNode.setPos(pos)
        Light.setPos(self, pos)

    def lookAt(self, pos):
        """ Makes the spotlight look at the given position """
        self.ghostCameraNode.lookAt(pos)

    def _computeAdditionalData(self):
        """ Internal method to recompute the spotlight MVP """
        self.ghostCameraNode.setPos(self.position)

        projMat = self.ghostLens.getProjectionMat()

        modelViewMat = Globals.render.getTransform(self.ghostCameraNode).getMat()
        self.mvp = modelViewMat * projMat

    def _computeLightBounds(self):
        """ Recomputes the bounds of this light. For a SpotLight, we for now
        use a simple BoundingSphere """
        self.bounds = BoundingSphere(Point3(self.position), self.radius * 2.0)

    def setNearFar(self, near, far):
        """ Sets the near and far plane of the spotlight """
        self.nearPlane = near
        self.radius = far
        self.ghostLens.setNearFar(near, far)
        self._updateLens()

    def _updateDebugNode(self):
        """ Internal method to generate new debug geometry. """
        debugNode = NodePath("SpotLightDebugNode")

        # Create the inner image 
        cm = CardMaker("SpotLightDebug")
        cm.setFrameFullscreenQuad()
        innerNode = NodePath(cm.generate())
        innerNode.setTexture(Globals.loader.loadTexture("Data/GUI/Visualization/SpotLight.png"))
        innerNode.setBillboardPointEye()
        innerNode.reparentTo(debugNode)
        innerNode.setPos(self.position)
        innerNode.setColorScale(1,1,0,1)

        # Create the outer lines
        lineNode = debugNode.attachNewNode("lines")

        currentNodeTransform = render.getTransform(self.ghostCameraNode).getMat()
        currentCamTransform = self.ghostLens.getProjectionMat()
        currentRelativeCamPos = self.ghostCameraNode.getPos(render)
        currentCamBounds = self.ghostLens.makeBounds()
        currentCamBounds.xform(self.ghostCameraNode.getMat(render))

        p = lambda index: currentCamBounds.getPoint(index)

        # Make a circle at the bottom
        frustumBottomCenter = (p(0) + p(1) + p(2) + p(3)) * 0.25
        upVector = (p(0) + p(1)) / 2 - frustumBottomCenter
        rightVector = (p(1) + p(2)) / 2 - frustumBottomCenter
        points = []
        for idx in xrange(64):
            rad = idx / 64.0 * math.pi * 2.0
            pos = upVector * math.sin(rad) + rightVector * math.cos(rad)
            pos += frustumBottomCenter
            points.append(pos)
        frustumLine = self._createDebugLine(points, True)
        frustumLine.setColorScale(1,1,0,1)
        frustumLine.reparentTo(lineNode)


        # Create frustum lines which connect the origin to the bottom circle
        pointArrays = [
            [self.position, frustumBottomCenter + upVector],
            [self.position, frustumBottomCenter - upVector],
            [self.position, frustumBottomCenter + rightVector],
            [self.position, frustumBottomCenter - rightVector],
        ]

        for pointArray in pointArrays:
            frustumLine = self._createDebugLine(pointArray, False)
            frustumLine.setColorScale(1,1,0,1)
            frustumLine.reparentTo(lineNode)

        # Create line which is in the direction of the spot light
        startPoint = (p(0) + p(1) + p(2) + p(3)) * 0.25
        endPoint = (p(4) + p(5) + p(6) + p(7)) * 0.25
        line = self._createDebugLine([startPoint, endPoint], False)
        line.setColorScale(1,1,1,1)
        line.reparentTo(lineNode)

        # Remove the old debug node
        self.debugNode.node().removeAllChildren()

        # Attach the new debug node
        debugNode.reparentTo(self.debugNode)
        # self.debugNode.flattenStrong()

    def _initShadowSources(self):
        """ Internal method to init the shadow sources """
        source = ShadowSource()
        source.setResolution(self.shadowResolution)
        source.setLens(self.ghostLens)
        self._addShadowSource(source)

    def _updateShadowSources(self):
        """ Recomputes the position of the shadow source """
        self.shadowSources[0].setPos(self.position)
        self.shadowSources[0].setHpr(self.ghostCameraNode.getHpr())

    def __repr__(self):
        """ Generates a string representation of this instance """
        return "SpotLight[]"
class CogdoExecutiveSuiteIntro(CogdoGameMovie):
    notify = DirectNotifyGlobal.directNotify.newCategory('CogdoExecutiveSuiteIntro')
    introDuration = 7
    cameraMoveDuration = 3

    def __init__(self, shopOwner):
        CogdoGameMovie.__init__(self)
        self._shopOwner = shopOwner
        self._lookAtCamTarget = False
        self._camTarget = None
        self._camHelperNode = None
        self._toonDialogueSfx = None
        self.toonHead = None
        self.frame = None
        return

    def displayLine(self, text):
        self.notify.debug('displayLine')
        self._dialogueLabel.node().setText(text)
        self.toonHead.reparentTo(aspect2d)
        self._toonDialogueSfx.play()
        self.toonHead.setClipPlane(self.clipPlane)

    def makeSuit(self, suitType):
        self.notify.debug('makeSuit()')
        suit = Suit.Suit()
        dna = SuitDNA.SuitDNA()
        dna.newSuit(suitType)
        suit.setStyle(dna)
        suit.isDisguised = 1
        suit.generateSuit()
        suit.setScale(1, 1, 2)
        suit.setPos(0, 0, -4.4)
        suit.reparentTo(self.toonHead)
        for part in suit.getHeadParts():
            part.hide()

        suit.loop('neutral')

    def load(self):
        self.notify.debug('load()')
        CogdoGameMovie.load(self)
        backgroundGui = loader.loadModel('phase_5/models/cogdominium/tt_m_gui_csa_flyThru')
        self.bg = backgroundGui.find('**/background')
        self.chatBubble = backgroundGui.find('**/chatBubble')
        self.chatBubble.setScale(6.5, 6.5, 7.3)
        self.chatBubble.setPos(0.32, 0, -0.78)
        self.bg.setScale(5.2)
        self.bg.setPos(0.14, 0, -0.6667)
        self.bg.reparentTo(aspect2d)
        self.chatBubble.reparentTo(aspect2d)
        self.frame = DirectFrame(geom=self.bg, relief=None, pos=(0.2, 0, -0.6667))
        self.bg.wrtReparentTo(self.frame)
        self.gameTitleText = DirectLabel(parent=self.frame, text=TTLocalizer.CogdoExecutiveSuiteTitle, scale=TTLocalizer.MRPgameTitleText * 0.8, text_align=TextNode.ACenter, text_font=getSignFont(), text_fg=(1.0, 0.33, 0.33, 1.0), pos=TTLocalizer.MRgameTitleTextPos, relief=None)
        self.chatBubble.wrtReparentTo(self.frame)
        self.frame.hide()
        backgroundGui.removeNode()
        self.toonDNA = ToonDNA.ToonDNA()
        self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2, 1, 8, 1, 8, 1, 14)
        self.toonHead = Toon.Toon()
        self.toonHead.setDNA(self.toonDNA)
        self.makeSuit('sc')
        self.toonHead.getGeomNode().setDepthWrite(1)
        self.toonHead.getGeomNode().setDepthTest(1)
        self.toonHead.loop('neutral')
        self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18, 0.18)
        self.toonHead.reparentTo(hidden)
        self.toonHead.startBlink()
        self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip'))
        self.clipPlane.node().setPlane(Plane(0, 0, 1, 0))
        self.clipPlane.setPos(0, 0, 2.45)
        self._toonDialogueSfx = loader.loadSfx('phase_3.5/audio/dial/AV_dog_long.ogg')
        self._camHelperNode = NodePath('CamHelperNode')
        self._camHelperNode.reparentTo(render)
        dialogue = TTLocalizer.CogdoExecutiveSuiteIntroMessage

        def start():
            self.frame.show()
            base.setCellsActive(base.bottomCells + base.leftCells + base.rightCells, 0)

        def showShopOwner():
            self._setCamTarget(self._shopOwner, -10, offset=Point3(0, 0, 5))

        def end():
            self._dialogueLabel.reparentTo(hidden)
            self.toonHead.reparentTo(hidden)
            self.frame.hide()
            base.setCellsActive(base.bottomCells + base.leftCells + base.rightCells, 1)
            self._stopUpdateTask()

        self._ival = Sequence(Func(start), Func(self.displayLine, dialogue), Func(showShopOwner), ParallelEndTogether(camera.posInterval(self.cameraMoveDuration, Point3(8, 0, 13), blendType='easeInOut'), camera.hprInterval(0.5, self._camHelperNode.getHpr(), blendType='easeInOut')), Wait(self.introDuration), Func(end))
        self._startUpdateTask()
        return

    def _setCamTarget(self, targetNP, distance, offset = Point3(0, 0, 0), angle = Point3(0, 0, 0)):
        camera.wrtReparentTo(render)
        self._camTarget = targetNP
        self._camOffset = offset
        self._camAngle = angle
        self._camDistance = distance
        self._camHelperNode.setPos(self._camTarget, self._camOffset)
        self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0], self._camAngle[1], self._camAngle[2])
        self._camHelperNode.setPos(self._camHelperNode, 0, self._camDistance, 0)

    def _updateTask(self, task):
        dt = globalClock.getDt()
        return task.cont

    def unload(self):
        self._shopOwner = None
        self._camTarget = None
        if hasattr(self, '_camHelperNode') and self._camHelperNode:
            self._camHelperNode.removeNode()
            del self._camHelperNode
        self.frame.destroy()
        del self.frame
        self.bg.removeNode()
        del self.bg
        self.chatBubble.removeNode()
        del self.chatBubble
        self.toonHead.stopBlink()
        self.toonHead.stop()
        self.toonHead.removeNode()
        self.toonHead.delete()
        del self.toonHead
        CogdoGameMovie.unload(self)
        return
Exemple #20
0
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 np not 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
Exemple #21
0
class FPSCamera(DirectObject):

    MaxP = 90.0
    MinP = -90.0
    PitchUpdateEpsilon = 0.1
    ViewModelFOV = 70.0

    BobCycleMin = 1.0
    BobCycleMax = 0.45
    Bob = 0.002
    BobUp = 0.5

    PunchDamping = 9.0
    PunchSpring = 65.0

    PrintAnimLengths = False

    def __init__(self):
        DirectObject.__init__(self)

        self.mouseEnabled = False

        self.lastCamRoot2Quat = Quat(Quat.identQuat())

        self.punchAngleVel = Vec3(0)
        self.punchAngle = Vec3(0)

        self.lastFacing = Vec3(0)

        self.lastMousePos = Point2(0)
        self.currMousePos = Point2(0)

        self.bobTime = 0
        self.lastBobTime = 0

        self.lastVMPos = Point3(0)

        self.camRoot = NodePath("camRoot")
        self.camRoot2 = self.camRoot.attachNewNode("camRoot2")
        self.lastPitch = 0

        self.lastEyeHeight = 0.0

        # Updates to the transform of camRoot
        self.vmRender = NodePath(
            BSPRender('vmRender', BSPLoader.getGlobalPtr()))
        self.vmRender.setShaderAuto()
        self.vmRoot = self.vmRender.attachNewNode('vmRoot')
        self.vmRoot2 = self.vmRoot.attachNewNode(ModelRoot('vmRoot2'))
        self.viewModel = Actor(
            "phase_14/models/char/v_toon_arms.bam",
            {
                "zero": "phase_14/models/char/v_toon_arms.egg",

                # Squirt gun viewmodel animations
                "sg_draw": "phase_14/models/char/v_toon_arms-draw.egg",
                "sg_idle": "phase_14/models/char/v_toon_arms-idle.egg",
                "sg_inspect": "phase_14/models/char/v_toon_arms-inspect.egg",
                "sg_shoot_begin":
                "phase_14/models/char/v_toon_arms-shoot_begin.egg",
                "sg_shoot_loop":
                "phase_14/models/char/v_toon_arms-shoot_loop.egg",
                "sg_shoot_end":
                "phase_14/models/char/v_toon_arms-shoot_end.egg",
                "pie_draw": "phase_14/models/char/v_toon_arms-pie_draw.egg",
                "pie_idle": "phase_14/models/char/v_toon_arms-pie_idle.egg",
                "button_draw":
                "phase_14/models/char/v_toon_arms-button_draw.egg",
                "button_idle":
                "phase_14/models/char/v_toon_arms-button_idle.egg",
                "button_press":
                "phase_14/models/char/v_toon_arms-button_press.egg",
                "gumball_draw":
                "phase_14/models/char/v_toon_arms-gumball_draw.egg",
                "gumball_idle":
                "phase_14/models/char/v_toon_arms-gumball_idle.egg",
                "gumball_fire":
                "phase_14/models/char/v_toon_arms-gumball_fire.egg",
                "hose_draw": "phase_14/models/char/v_toon_arms-hose_draw.egg",
                "hose_idle": "phase_14/models/char/v_toon_arms-hose_idle.egg",
                "hose_shoot_begin":
                "phase_14/models/char/v_toon_arms-hose_shoot_begin.egg",
                "hose_shoot_loop":
                "phase_14/models/char/v_toon_arms-hose_shoot_loop.egg",
                "hose_shoot_end":
                "phase_14/models/char/v_toon_arms-hose_shoot_end.egg",
                "tnt_draw": "phase_14/models/char/v_toon_arms-tnt_draw.egg",
                "tnt_idle": "phase_14/models/char/v_toon_arms-tnt_idle.egg",
                "tnt_throw": "phase_14/models/char/v_toon_arms-tnt_throw.egg",
                "slap_idle": "phase_14/models/char/v_toon_arms-slap_idle.egg",
                "slap_hit": "phase_14/models/char/v_toon_arms-slap_hit.egg",
                "sound": "phase_14/models/char/v_toon_arms-sound.egg"
            })
        self.viewModel.setBlend(
            frameBlend=base.config.GetBool("interpolate-frames", False))
        self.viewModel.reparentTo(self.vmRoot2)
        self.viewModel.find("**/hands").setTwoSided(True)
        self.viewModel.hide()

        self.defaultViewModel = self.viewModel
        self.idealFov = self.ViewModelFOV

        precacheActor(self.viewModel)
        #self.viewModel.clearMaterial()
        #self.viewModel.setMaterial(CIGlobals.getCharacterMaterial(specular = (0, 0, 0, 1)), 1)
        self.viewportLens = PerspectiveLens()
        self.viewportLens.setMinFov(self.ViewModelFOV / (4. / 3.))
        self.viewportLens.setNear(0.3)
        # Updates to the transform of base.camera
        self.viewportCam = base.makeCamera(base.win,
                                           clearDepth=True,
                                           camName='fpsViewport',
                                           mask=CIGlobals.ViewModelCamMask,
                                           lens=self.viewportLens)
        # Pretend to be the main camera so the viewmodel gets ambient probes updated
        self.viewportCam.node().setTag("__mainpass__", "1")
        self.viewportCam.reparentTo(self.vmRoot)

        self.vmGag = None
        self.vmAnimTrack = None
        self.dmgFade = OnscreenImage(image="phase_14/maps/damage_effect.png",
                                     parent=render2d)
        self.dmgFade.setBin('gui-popup', 100)
        self.dmgFade.setTransparency(1)
        self.dmgFade.setColorScale(1, 1, 1, 0)
        self.dmgFadeIval = None

        #self.accept('v', self.vmRender.ls)

        #base.bspLoader.addDynamicNode(self.vmRoot)

        if self.PrintAnimLengths:
            print "v_toon_arms animation lengths:"
            for anim in self.viewModel.getAnimNames():
                print "\t{0}\t:\t{1}".format(anim,
                                             self.viewModel.getDuration(anim))

        taskMgr.add(self.__vpDebugTask, "vpdebutask", sort=-100)

    def setViewModelFOV(self, fov):
        self.idealFov = fov

    def restoreViewModelFOV(self):
        self.idealFov = self.ViewModelFOV

    def swapViewModel(self, newViewModel, fov=70.0):
        if newViewModel.isEmpty():
            return

        isHidden = False
        if not self.viewModel.isEmpty():
            self.viewModel.reparentTo(hidden)
            isHidden = self.viewModel.isHidden()

        self.viewModel = newViewModel
        self.viewModel.reparentTo(self.vmRoot2)
        if isHidden:
            self.viewModel.hide()
        else:
            self.viewModel.show()

        self.setViewModelFOV(fov)

    def restoreViewModel(self):
        isHidden = False
        if not self.viewModel.isEmpty():
            self.viewModel.reparentTo(hidden)
            isHidden = self.viewModel.isHidden()

        self.viewModel = self.defaultViewModel
        self.viewModel.reparentTo(self.vmRoot2)
        if isHidden:
            self.viewModel.hide()
        else:
            self.viewModel.show()

        self.restoreViewModelFOV()

    def addViewPunch(self, punch):
        self.punchAngleVel += punch * 20

    def resetViewPunch(self, tolerance=0.0):
        if tolerance != 0.0:
            tolerance *= tolerance
            check = self.punchAngleVel.lengthSquared(
            ) + self.punchAngle.lengthSquared()
            if check > tolerance:
                return

        self.punchAngle = Vec3(0)
        self.punchAngleVel = Vec3(0)

    def decayPunchAngle(self):
        if self.punchAngle.lengthSquared(
        ) > 0.001 or self.punchAngleVel.lengthSquared() > 0.001:
            dt = globalClock.getDt()
            self.punchAngle += self.punchAngleVel * dt
            damping = 1 - (self.PunchDamping * dt)

            if damping < 0:
                damping = 0
            self.punchAngleVel *= damping

            # Torsional spring
            springForceMag = self.PunchSpring * dt
            springForceMag = CIGlobals.clamp(springForceMag, 0.0, 2.0)
            self.punchAngleVel -= self.punchAngle * springForceMag

            # Don't wrap around
            self.punchAngle.set(CIGlobals.clamp(self.punchAngle[0], -179, 179),
                                CIGlobals.clamp(self.punchAngle[1], -89, 89),
                                CIGlobals.clamp(self.punchAngle[2], -89, 89))
        else:
            self.punchAngle = Vec3(0)
            self.punchAngleVel = Vec3(0)

    def hideViewModel(self):
        self.viewModel.hide(BitMask32.allOn())

    def showViewModel(self):
        if not base.localAvatar.isFirstPerson():
            return

        self.viewModel.showThrough(CIGlobals.ViewModelCamMask)

    def __vpDebugTask(self, task):
        if self.vmRender.getState() != render.getState():
            # pretend like the view model is part of the main scene
            self.vmRender.setState(render.getState())

        self.viewportLens.setAspectRatio(base.getAspectRatio())
        self.viewportLens.setMinFov(self.idealFov / (4. / 3.))
        self.vmRoot.setTransform(render, self.camRoot.getTransform(render))
        self.viewportCam.setTransform(render, base.camera.getTransform(render))

        # Since the viewmodel is not underneath BSPRender, it's not going to be automatically
        # influenced by the ambient probes. We need to do this explicitly.
        #base.bspLoader.updateDynamicNode(self.vmRoot)

        #self.viewportDebug.setImage(self.viewportCam.node().getDisplayRegion(0).getScreenshot())

        return task.cont

    def handleSuitAttack(self, attack):
        print "FPSCamera handleSuitAttack:", attack

    def doDamageFade(self, r, g, b, severity=1.0):
        if self.dmgFadeIval:
            self.dmgFadeIval.finish()
            self.dmgFadeIval = None
        severity = min(1.0, severity)
        self.dmgFadeIval = Sequence(
            LerpColorScaleInterval(self.dmgFade,
                                   0.25, (r, g, b, severity), (r, g, b, 0),
                                   blendType='easeOut'), Wait(1.0),
            LerpColorScaleInterval(self.dmgFade,
                                   2.0, (r, g, b, 0), (r, g, b, severity),
                                   blendType='easeInOut'))
        self.dmgFadeIval.start()

    def setVMAnimTrack(self, track, loop=False):
        self.clearVMAnimTrack()

        self.vmAnimTrack = track
        if loop:
            self.vmAnimTrack.loop()
        else:
            self.vmAnimTrack.start()

    def clearVMAnimTrack(self):
        if self.vmAnimTrack:
            self.vmAnimTrack.pause()
            self.vmAnimTrack = None

    def setVMGag(self,
                 gag,
                 pos=(0, 0, 0),
                 hpr=(0, 0, 0),
                 scale=(1, 1, 1),
                 hand=0,
                 animate=True):
        self.clearVMGag()

        handNode = NodePath()
        if hand == ATTACK_HOLD_RIGHT:
            handNode = self.getViewModelRightHand()
        elif hand == ATTACK_HOLD_LEFT:
            handNode = self.getViewModelLeftHand()

        if isinstance(gag, Actor) and animate:
            self.vmGag = Actor(other=gag)
            self.vmGag.reparentTo(handNode)
            self.vmGag.loop('chan')
        else:
            self.vmGag = gag.copyTo(handNode)
        self.vmGag.setPos(pos)
        self.vmGag.setHpr(hpr)
        self.vmGag.setScale(scale)

    def clearVMGag(self):
        if self.vmGag:
            if isinstance(self.vmGag, Actor):
                self.vmGag.cleanup()
            self.vmGag.removeNode()
            self.vmGag = None

    def setup(self):
        try:
            # Match the arm color with the torso color of local avatar
            self.viewModel.find("**/arms").setColorScale(
                base.localAvatar.getTorsoColor(), 1)
            # Same with glove cover
            self.viewModel.find("**/hands").setColorScale(
                base.localAvatar.getGloveColor(), 1)
        except:
            pass

        self.attachCamera()

    def attachCamera(self, reset=True):
        if reset:
            self.camRoot.reparentTo(base.localAvatar)
            if base.localAvatar.isFirstPerson():
                self.camRoot.setPos(base.localAvatar.getEyePoint())
            else:
                self.camRoot.setPos(0, 0, max(base.localAvatar.getHeight(),
                                              3.0))
            self.camRoot.setHpr(0, 0, 0)
            self.camRoot2.setPosHpr(0, 0, 0, 0, 0, 0)

        base.camera.reparentTo(self.camRoot2)

        if base.localAvatar.isFirstPerson():
            base.camera.setPosHpr(0, 0, 0, 0, 0, 0)
        elif base.localAvatar.isThirdPerson():
            pos, lookAt = self.getThirdPersonBattleCam()
            base.localAvatar.smartCamera.setIdealCameraPos(pos)
            base.localAvatar.smartCamera.setLookAtPoint(lookAt)

    def getThirdPersonBattleCam(self):
        camHeight = max(base.localAvatar.getHeight(), 3.0)
        heightScaleFactor = camHeight * 0.3333333333

        return ((1, -5 * heightScaleFactor, 0), (1, 10, 0))

    def getViewModelLeftHand(self):
        return self.viewModel.find("**/def_left_hold")

    def getViewModelRightHand(self):
        return self.viewModel.find("**/def_right_hold")

    def getViewModel(self):
        return self.viewModel

    def acceptEngageKeys(self):
        self.acceptOnce("escape", self.__handleEscapeKey)

    def ignoreEngageKeys(self):
        self.ignore("escape")

    def enableMouseMovement(self):
        props = WindowProperties()
        props.setMouseMode(WindowProperties.MConfined)
        props.setCursorHidden(True)
        base.win.requestProperties(props)

        self.attachCamera(False)
        if base.localAvatar.isFirstPerson():
            base.localAvatar.getGeomNode().hide()

        base.win.movePointer(0,
                             base.win.getXSize() / 2,
                             base.win.getYSize() / 2)

        base.taskMgr.add(self.__updateTask, "mouseUpdateFPSCamera", sort=-40)
        self.acceptEngageKeys()

        self.mouseEnabled = True

        base.localAvatar.enableGagKeys()

    def disableMouseMovement(self, allowEnable=False, showAvatar=True):
        props = WindowProperties()
        props.setMouseMode(WindowProperties.MAbsolute)
        props.setCursorHidden(False)
        base.win.requestProperties(props)

        base.taskMgr.remove("mouseUpdateFPSCamera")

        base.localAvatar.disableGagKeys()

        if allowEnable:
            self.acceptEngageKeys()
        else:
            self.ignoreEngageKeys()
            if showAvatar or base.localAvatar.isThirdPerson():
                base.localAvatar.getGeomNode().show()
            else:
                base.localAvatar.getGeomNode().hide()

        self.mouseEnabled = False

    def __handleEscapeKey(self):
        if self.mouseEnabled:
            self.disableMouseMovement(True)
        else:
            self.enableMouseMovement()

    #def doCameraJolt(self, amplitude, horizRange = [-1, 1], vertRange = [1]):
    #h = random.choice(horizRange) * amplitude
    #p = random.choice(vertRange) * amplitude
    #nquat = Quat(Quat.identQuat())
    #nquat.setHpr((h, p, 0))
    #self.lastCamRoot2Quat = self.lastCamRoot2Quat + nquat

    #Effects.createPBounce(self.camRoot2, 3, self.camRoot2.getHpr(), 1, amplitude).start()
    #Effects.createHBounce(self.camRoot2, 3, self.camRoot2.getHpr(), 1, amplitude).start()

    def handleJumpHardLand(self):
        down = Parallel(
            LerpPosInterval(base.cam,
                            0.1, (-0.1, 0, -0.2), (0, 0, 0),
                            blendType='easeOut'),
            LerpHprInterval(base.cam,
                            0.1, (0, 0, -2.5), (0, 0, 0),
                            blendType='easeOut'))
        up = Parallel(
            LerpPosInterval(base.cam,
                            0.7, (0, 0, 0), (-0.1, 0, -0.2),
                            blendType='easeInOut'),
            LerpHprInterval(base.cam,
                            0.7, (0, 0, 0), (0, 0, -2.5),
                            blendType='easeInOut'))
        Sequence(down, up).start()

    def __updateTask(self, task):
        # TODO -- This function does a lot of math, I measured it to take .5 ms on my laptop
        #         That's a lot of time for something miniscule like sway and bob.

        dt = globalClock.getDt()
        time = globalClock.getFrameTime()

        if base.localAvatar.isFirstPerson():
            eyePoint = base.localAvatar.getEyePoint()
            if base.localAvatar.walkControls.crouching:
                eyePoint[2] = eyePoint[2] / 2.0
            eyePoint[2] = CIGlobals.lerpWithRatio(eyePoint[2],
                                                  self.lastEyeHeight, 0.4)
            self.lastEyeHeight = eyePoint[2]

        camRootAngles = Vec3(0)

        # Mouse look around
        mw = base.mouseWatcherNode
        if mw.hasMouse():
            md = base.win.getPointer(0)
            center = Point2(base.win.getXSize() / 2, base.win.getYSize() / 2)

            xDist = md.getX() - center.getX()
            yDist = md.getY() - center.getY()

            sens = self.__getMouseSensitivity()

            angular = -(xDist * sens) / dt
            base.localAvatar.walkControls.controller.setAngularMovement(
                angular)
            camRootAngles.setY(self.lastPitch - yDist * sens)

            if camRootAngles.getY() > FPSCamera.MaxP:
                camRootAngles.setY(FPSCamera.MaxP)
                yDist = 0
            elif camRootAngles.getY() < FPSCamera.MinP:
                yDist = 0
                camRootAngles.setY(FPSCamera.MinP)

            base.win.movePointer(0, int(center.getX()), int(center.getY()))

        if base.localAvatar.isFirstPerson():
            # Camera / viewmodel bobbing
            vmBob = Point3(0)
            vmAngles = Vec3(0)
            vmRaise = Point3(0)
            camBob = Point3(0)

            maxSpeed = base.localAvatar.walkControls.BattleRunSpeed * 16.0

            speed = base.localAvatar.walkControls.speeds.length() * 16.0
            speed = max(-maxSpeed, min(maxSpeed, speed))

            bobOffset = CIGlobals.remapVal(speed, 0, maxSpeed, 0.0, 1.0)

            self.bobTime += (time - self.lastBobTime) * bobOffset
            self.lastBobTime = time

            # Calculate the vertical bob
            cycle = self.bobTime - int(
                self.bobTime / self.BobCycleMax) * self.BobCycleMax
            cycle /= self.BobCycleMax
            if cycle < self.BobUp:
                cycle = math.pi * cycle / self.BobUp
            else:
                cycle = math.pi + math.pi * (cycle - self.BobUp) / (1.0 -
                                                                    self.BobUp)

            verticalBob = speed * 0.005
            verticalBob = verticalBob * 0.3 + verticalBob * 0.7 * math.sin(
                cycle)
            verticalBob = max(-7.0, min(4.0, verticalBob))
            verticalBob /= 16.0

            # Calculate the lateral bob
            cycle = self.bobTime - int(
                self.bobTime / self.BobCycleMax * 2) * self.BobCycleMax * 2
            cycle /= self.BobCycleMax * 2
            if cycle < self.BobUp:
                cycle = math.pi * cycle / self.BobUp
            else:
                cycle = math.pi + math.pi * (cycle - self.BobUp) / (1.0 -
                                                                    self.BobUp)

            lateralBob = speed * 0.005
            lateralBob = lateralBob * 0.3 + lateralBob * 0.7 * math.sin(cycle)
            lateralBob = max(-7.0, min(4.0, lateralBob))
            lateralBob /= 16.0

            # Apply bob, but scaled down a bit
            vmBob.set(lateralBob * 0.8, 0, verticalBob * 0.1)
            # Z bob a bit more
            vmBob[2] += verticalBob * 0.1
            # Bob the angles
            vmAngles[2] += verticalBob * 0.5
            vmAngles[1] -= verticalBob * 0.4
            vmAngles[0] -= lateralBob * 0.3

            # ================================================================
            # Viewmodel lag/sway

            angles = self.camRoot.getHpr(render)
            quat = Quat()
            quat.setHpr(angles)
            invQuat = Quat()
            invQuat.invertFrom(quat)

            maxVMLag = 1.5
            lagforward = quat.getForward()
            if dt != 0.0:
                lagdifference = lagforward - self.lastFacing
                lagspeed = 5.0
                lagdiff = lagdifference.length()
                if (lagdiff > maxVMLag) and (maxVMLag > 0.0):
                    lagscale = lagdiff / maxVMLag
                    lagspeed *= lagscale

                self.lastFacing = CIGlobals.extrude(self.lastFacing,
                                                    lagspeed * dt,
                                                    lagdifference)
                self.lastFacing.normalize()
                lfLocal = invQuat.xform(lagdifference)
                vmBob = CIGlobals.extrude(vmBob, 5.0 / 16.0, lfLocal * -1.0)

            pitch = angles[1]
            if pitch > 180:
                pitch -= 360
            elif pitch < -180:
                pitch += 360

            vmBob = CIGlobals.extrude(vmBob, pitch * (0.035 / 16),
                                      Vec3.forward())
            vmBob = CIGlobals.extrude(vmBob, pitch * (0.03 / 16), Vec3.right())
            vmBob = CIGlobals.extrude(vmBob, pitch * (0.02 / 16), Vec3.up())

            # ================================================================

            vmRaise.set(
                0, 0, 0
            )  #(0, abs(camRootAngles.getY()) * -0.002, camRootAngles.getY() * 0.002)
            camBob.set(0, 0, 0)

            # Apply bob, raise, and sway to the viewmodel.
            self.viewModel.setPos(vmBob + vmRaise + self.lastVMPos)
            self.vmRoot2.setHpr(vmAngles)
            self.camRoot.setPos(eyePoint + camBob)

        newPitch = camRootAngles.getY()

        if abs(newPitch - self.lastPitch) > self.PitchUpdateEpsilon:
            # Broadcast where our head is looking
            head = base.localAvatar.getPart("head")
            if head and not head.isEmpty():
                # Constrain the head pitch a little bit so it doesn't look like their head snapped
                headPitch = max(-47, newPitch)
                headPitch = min(75, headPitch)
                base.localAvatar.b_setLookPitch(headPitch)

        self.lastPitch = newPitch

        if base.localAvatar.isFirstPerson():
            # Apply punch angle
            self.decayPunchAngle()
            camRootAngles += self.punchAngle

        self.camRoot.setHpr(camRootAngles)

        return task.cont

    def __getMouseSensitivity(self):
        return CIGlobals.getSettingsMgr().getSetting('fpmgms').getValue()

    def cleanup(self):
        taskMgr.remove("vpdebutask")
        self.disableMouseMovement(False, False)
        self.clearVMAnimTrack()
        self.clearVMGag()
        if self.viewModel:
            self.viewModel.cleanup()
            self.viewModel.removeNode()
        self.viewModel = None
        if self.vmRender:
            self.vmRender.removeNode()
        self.vmRender = None
        self.vmRoot = None
        self.vmRoot2 = None
        self.viewportLens = None
        if self.viewportCam:
            self.viewportCam.removeNode()
        self.viewportCam = None
        if self.camRoot:
            self.camRoot.removeNode()
        self.camRoot = None
        self.camRoot2 = None
        self.lastEyeHeight = None
        self.lastPitch = None
        self.bobTime = None
        self.lastBobTime = None
        self.mouseEnabled = None
        self.lastCamRoot2Quat = None
        self.punchAngleVel = None
        self.punchAngle = None
        self.lastFacing = None
        self.lastMousePos = None
        self.currMousePos = None
        self.lastVMPos = None
        self.defaultViewModel = None
        self.idealFov = None
        self.vmGag = None
        self.vmAnimTrack = None
        self.dmgFade = None
        self.dmgFadeIval = None
        self.ignoreAll()
Exemple #22
0
class Transform(Component):
    """Each game object has exactly one of these. A transform holds data
    about position, rotation, scale and parent relationship.
    
    In Panity this is a wrapper for a NodePath.
    """
    def __init__(self, game_object, name):
        # Component class sets self.game_object = game_object
        Component.__init__(self, game_object)
        self.node = NodePath(name)
        self.node.setPythonTag("transform", self)

    @classmethod
    def getClassSerializedProperties(cls):
        """Return all special property attributes in a dict. Only attributes
        derived from SerializedProperty are respected.

        On transform component this method always returns local position,
        -rotation and scale only.
        """
        d = {}
        d["local_position"] = Transform.local_position
        d["local_euler_angles"] = Transform.local_euler_angles
        d["local_scale"] = Transform.local_scale
        return d

    def getSerializedProperties(self):
        """Return all properties for serialization. In the case of transform
        this only returns local position, -rotation and -scale, which are
        required to restore the state of the node.
        """
        d = {}
        d["local_position"] = self.local_position
        d["local_euler_angles"] = self.local_euler_angles
        d["local_scale"] = self.local_scale
        return d

    # We use the panda node to save the name on it for better debugging and
    # efficient finding of nodes with NodePath().find()
    @SerializedPropertyDecorator
    def name(self):
        return self.node.getName()

    @name.setter
    def name(self, name):
        if name == "render":
            name = "_render"
        self.node.setName(name)

    @SerializedPropertyDecorator
    def position(self):
        return self.node.getPos(self.root.node)

    @position.setter
    def position(self, position):
        self.node.setPos(self.root.node, *position)

    @SerializedPropertyDecorator
    def local_position(self):
        return self.node.getPos()

    @local_position.setter
    def local_position(self, position):
        self.node.setPos(*position)

    @SerializedPropertyDecorator
    def euler_angles(self):
        return self.node.getHpr(self.root.node)

    @euler_angles.setter
    def euler_angles(self, angles):
        self.node.setHpr(self.root.node, *angles)

    @SerializedPropertyDecorator
    def local_euler_angles(self):
        return self.node.getHpr()

    @local_euler_angles.setter
    def local_euler_angles(self, angles):
        self.node.setHpr(*angles)

    @SerializedPropertyDecorator
    def rotation(self):
        return self.node.getQuat(self.root.node)

    @rotation.setter
    def rotation(self, quaternion):
        self.node.setQuat(self.root.node, *quaternion)

    @SerializedPropertyDecorator
    def local_rotation(self):
        return self.node.getQuat()

    @local_rotation.setter
    def local_rotation(self, quaternion):
        self.node.setQuat(*quaternion)

    @SerializedPropertyDecorator
    def local_scale(self):
        return self.node.getScale()

    @local_scale.setter
    def local_scale(self, scale):
        self.node.setScale(*scale)

    @SerializedPropertyDecorator
    def parent(self):
        p = self.node.getParent()
        if p.isEmpty() or p.getName() == "render":
            return self
        elif p.hasPythonTag("transform"):
            return p.getPythonTag("transform")

    @parent.setter
    def parent(self, parent):
        self.node.wrtReparentTo(parent.node)

    @SerializedPropertyDecorator
    def root(self):
        if self.parent is not self:
            return self.parent.root()
        else:
            return self

    def destroy(self):
        """Ultimately remove this transform. Warning: this might cause errors
        for other components on this game object. Use this only when removing
        the whole GameObject.
        """
        self.node.removeNode()

    def getChildren(self):
        """Return children as Transforms."""
        # this requires the __iter__() method
        return [c for c in self]

    def __iter__(self):
        """Iterate over children nodes and yield the transform instances."""
        for child in self.node.getChildren():
            if child.hasPythonTag("transform"):
                yield child.getPythonTag("transform")

    def __str__(self):
        r = "Transform for '{}'\n".format(self.name)
        r += "local position: {}\n".format(self.local_position)
        r += "local rotation: {}\n".format(self.local_euler_angles)
        r += "local scale:    {}\n".format(self.local_scale)
        return r
Exemple #23
0
class DistributedButterfly(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedButterfly')
    id = 0
    wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6')
    yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1))
    whiteColors = (Vec4(0.8, 0, 0.8, 1),
     Vec4(0, 0.8, 0.8, 1),
     Vec4(0.9, 0.4, 0.6, 1),
     Vec4(0.9, 0.4, 0.4, 1),
     Vec4(0.8, 0.5, 0.9, 1),
     Vec4(0.4, 0.1, 0.7, 1))
    paleYellowColors = (Vec4(0.8, 0, 0.8, 1),
     Vec4(0.6, 0.6, 0.9, 1),
     Vec4(0.7, 0.6, 0.9, 1),
     Vec4(0.8, 0.6, 0.9, 1),
     Vec4(0.9, 0.6, 0.9, 1),
     Vec4(1, 0.6, 0.9, 1))
    shadowScaleBig = Point3(0.07, 0.07, 0.07)
    shadowScaleSmall = Point3(0.01, 0.01, 0.01)

    def __init__(self, cr):
        DistributedObject.DistributedObject.__init__(self, cr)
        self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying'])], 'off', 'off')
        self.butterfly = None
        self.butterflyNode = None
        self.curIndex = 0
        self.destIndex = 0
        self.time = 0.0
        self.ival = None
        self.fsm.enterInitialState()
        return

    def generate(self):
        DistributedObject.DistributedObject.generate(self)
        if self.butterfly:
            return
        self.butterfly = Actor.Actor()
        self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod.bam')
        self.butterfly.loadAnims({'flutter': 'phase_4/models/props/SZ_butterfly-flutter.bam',
         'glide': 'phase_4/models/props/SZ_butterfly-glide.bam',
         'land': 'phase_4/models/props/SZ_butterfly-land.bam'})
        index = self.doId % len(self.wingTypes)
        chosenType = self.wingTypes[index]
        node = self.butterfly.getGeomNode()
        for type in self.wingTypes:
            wing = node.find('**/' + type)
            if type != chosenType:
                wing.removeNode()
            else:
                if index == 0 or index == 1:
                    color = self.yellowColors[self.doId % len(self.yellowColors)]
                elif index == 2 or index == 3:
                    color = self.whiteColors[self.doId % len(self.whiteColors)]
                elif index == 4:
                    color = self.paleYellowColors[self.doId % len(self.paleYellowColors)]
                else:
                    color = Vec4(1, 1, 1, 1)
                wing.setColor(color)

        self.butterfly2 = Actor.Actor(other=self.butterfly)
        self.butterfly.enableBlend(blendType=PartBundle.BTLinear)
        self.butterfly.loop('flutter')
        self.butterfly.loop('land')
        self.butterfly.loop('glide')
        rng = RandomNumGen.RandomNumGen(self.doId)
        playRate = 0.6 + 0.8 * rng.random()
        self.butterfly.setPlayRate(playRate, 'flutter')
        self.butterfly.setPlayRate(playRate, 'land')
        self.butterfly.setPlayRate(playRate, 'glide')
        self.butterfly2.setPlayRate(playRate, 'flutter')
        self.butterfly2.setPlayRate(playRate, 'land')
        self.butterfly2.setPlayRate(playRate, 'glide')
        self.glideWeight = rng.random() * 2
        lodNode = LODNode('butterfly-node')
        lodNode.addSwitch(100, 40)
        lodNode.addSwitch(40, 0)
        self.butterflyNode = NodePath(lodNode)
        self.butterfly2.setH(180.0)
        self.butterfly2.reparentTo(self.butterflyNode)
        self.butterfly.setH(180.0)
        self.butterfly.reparentTo(self.butterflyNode)
        self.__initCollisions()
        self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
        self.dropShadow.setColor(0, 0, 0, 0.3)
        self.dropShadow.setPos(0, 0.1, -0.05)
        self.dropShadow.setScale(self.shadowScaleBig)
        self.dropShadow.reparentTo(self.butterfly)

    def disable(self):
        self.butterflyNode.reparentTo(hidden)
        if self.ival != None:
            self.ival.finish()
        self.__ignoreAvatars()
        DistributedObject.DistributedObject.disable(self)
        return

    def delete(self):
        self.butterfly.cleanup()
        self.butterfly = None
        self.butterfly2.cleanup()
        self.butterfly2 = None
        self.butterflyNode.removeNode()
        self.__deleteCollisions()
        self.ival = None
        del self.fsm
        DistributedObject.DistributedObject.delete(self)
        return

    def uniqueButterflyName(self, name):
        DistributedButterfly.id += 1
        return name + '-%d' % DistributedButterfly.id

    def __detectAvatars(self):
        self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter)

    def __ignoreAvatars(self):
        self.ignore('enter' + self.cSphereNode.getName())

    def __initCollisions(self):
        self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0)
        self.cSphere.setTangible(0)
        self.cSphereNode = CollisionNode(self.uniqueButterflyName('cSphereNode'))
        self.cSphereNode.addSolid(self.cSphere)
        self.cSphereNodePath = self.butterflyNode.attachNewNode(self.cSphereNode)
        self.cSphereNodePath.hide()
        self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask)

    def __deleteCollisions(self):
        del self.cSphere
        del self.cSphereNode
        self.cSphereNodePath.removeNode()
        del self.cSphereNodePath

    def __handleCollisionSphereEnter(self, collEntry):
        self.sendUpdate('avatarEnter', [])

    def setArea(self, playground, area):
        self.playground = playground
        self.area = area

    def setState(self, stateIndex, curIndex, destIndex, time, timestamp):
        self.curIndex = curIndex
        self.destIndex = destIndex
        self.time = time
        self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)])

    def enterOff(self, ts = 0.0):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(hidden)
        return

    def exitOff(self):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(render)
        return

    def enterFlying(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex]
        destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.destIndex]
        flyHeight = max(curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground]
        curPosHigh = Point3(curPos[0], curPos[1], flyHeight)
        destPosHigh = Point3(destPos[0], destPos[1], flyHeight)
        if ts <= self.time:
            flyTime = self.time - (ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground])
            self.butterflyNode.setPos(curPos)
            self.dropShadow.show()
            self.dropShadow.setScale(self.shadowScaleBig)
            oldHpr = self.butterflyNode.getHpr()
            self.butterflyNode.headsUp(destPos)
            newHpr = self.butterflyNode.getHpr()
            self.butterflyNode.setHpr(oldHpr)
            takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground]
            landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[self.playground]
            self.butterfly2.loop('flutter')
            self.ival = Sequence(Parallel(LerpPosHprInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence(LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel(LerpPosInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence(Wait(ButterflyGlobals.BUTTERFLY_LANDING[self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly'))
            self.ival.start(ts)
        else:
            self.ival = None
            self.butterflyNode.setPos(destPos)
            self.butterfly.setControlEffect('land', 1.0)
            self.butterfly.setControlEffect('flutter', 0.0)
            self.butterfly.setControlEffect('glide', 0.0)
            self.butterfly2.loop('land')
        return

    def exitFlying(self):
        self.__ignoreAvatars()
        if self.ival != None:
            self.ival.finish()
            self.ival = None
        return

    def enterLanded(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex]
        self.butterflyNode.setPos(curPos)
        self.dropShadow.show()
        self.dropShadow.setScale(self.shadowScaleBig)
        self.butterfly.setControlEffect('land', 1.0)
        self.butterfly.setControlEffect('flutter', 0.0)
        self.butterfly.setControlEffect('glide', 0.0)
        self.butterfly2.pose('land', random.randrange(self.butterfly2.getNumFrames('land')))
        return None

    def exitLanded(self):
        self.__ignoreAvatars()
        return None
Exemple #24
0
class ProjectilePie(DirectObject):
    def __init__(self, collideEventName, parent, pie, endPos, gravityMult,
                 duration, local, turretClass):
        self.turret = turretClass
        self.collideEventName = collideEventName
        self.pieNp = NodePath('pieNP')
        self.pieNp.reparentTo(parent)
        self.pieNp.setScale(render, 1)
        self.pieNp.setPos(endPos)
        self.pieNp.setHpr(90, -90, 90)

        self.pie = pie
        if local:
            self.pieCollisions()
        self.pie.setScale(self.pie.getScale(render))
        self.pie.setPos(self.pie.getPos(render))
        self.pie.reparentTo(render)
        self.pie.setHpr(self.pieNp.getHpr(render))

        self.trajectory = ProjectileInterval(self.pie,
                                             startPos=self.pie.getPos(render),
                                             endPos=self.pieNp.getPos(render),
                                             gravityMult=gravityMult,
                                             duration=duration,
                                             name='projectilePieTraj' +
                                             str(id(self)))
        self.trajectory.setDoneEvent(self.trajectory.getName())
        self.acceptOnce(self.trajectory.getDoneEvent(), self.handleTrajDone)
        self.trajectory.start()
        sfx = base.localAvatar.audio3d.loadSfx(
            "phase_4/audio/sfx/MG_cannon_fire_alt.mp3")
        base.localAvatar.audio3d.attachSoundToObject(sfx, parent)
        base.playSfx(sfx)

        if local:
            self.acceptOnce('projectilePieSensor' + str(id(self)) + '-into',
                            self.handleCollision)

    def pieCollisions(self):
        pss = CollisionSphere(0, 0, 0, 1)
        psnode = CollisionNode('projectilePieSensor' + str(id(self)))
        psnode.add_solid(pss)
        self.psnp = self.pie.attach_new_node(psnode)
        self.psnp.set_collide_mask(BitMask32(0))
        self.psnp.node().set_from_collide_mask(CIGlobals.WallBitmask
                                               | CIGlobals.FloorBitmask)

        event = CollisionHandlerEvent()
        event.set_in_pattern("%fn-into")
        event.set_out_pattern("%fn-out")
        base.cTrav.add_collider(self.psnp, event)

    def handleCollision(self, entry):
        messenger.send(self.collideEventName, [entry, self])

    def handleTrajDone(self):
        self.cleanup()

    def cleanup(self):
        self.ignore(self.trajectory.getDoneEvent())
        self.trajectory.finish()
        del self.trajectory
        if self.turret.piesInFlight:
            self.turret.piesInFlight.remove(self)
        self.ignore('projectilePieSensor' + str(id(self)) + '-into')
        del self.collideEventName
        if hasattr(self, 'psnp'):
            self.psnp.removeNode()
            del self.psnp
        self.pie.removeNode()
        del self.pie
        del self.pieNp
        del self.turret
class DistributedButterfly(DistributedObject.DistributedObject):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedButterfly')
    id = 0
    wingTypes = ('wings_1', 'wings_2', 'wings_3', 'wings_4', 'wings_5', 'wings_6')
    yellowColors = (Vec4(1, 1, 1, 1), Vec4(0.2, 0, 1, 1), Vec4(0.8, 0, 1, 1))
    whiteColors = (Vec4(0.8, 0, 0.8, 1),
     Vec4(0, 0.8, 0.8, 1),
     Vec4(0.9, 0.4, 0.6, 1),
     Vec4(0.9, 0.4, 0.4, 1),
     Vec4(0.8, 0.5, 0.9, 1),
     Vec4(0.4, 0.1, 0.7, 1))
    paleYellowColors = (Vec4(0.8, 0, 0.8, 1),
     Vec4(0.6, 0.6, 0.9, 1),
     Vec4(0.7, 0.6, 0.9, 1),
     Vec4(0.8, 0.6, 0.9, 1),
     Vec4(0.9, 0.6, 0.9, 1),
     Vec4(1, 0.6, 0.9, 1))
    shadowScaleBig = Point3(0.07, 0.07, 0.07)
    shadowScaleSmall = Point3(0.01, 0.01, 0.01)

    def __init__(self, cr):
        DistributedObject.DistributedObject.__init__(self, cr)
        self.fsm = ClassicFSM.ClassicFSM('DistributedButterfly', [State.State('off', self.enterOff, self.exitOff, ['Flying', 'Landed']), State.State('Flying', self.enterFlying, self.exitFlying, ['Landed']), State.State('Landed', self.enterLanded, self.exitLanded, ['Flying'])], 'off', 'off')
        self.butterfly = None
        self.butterflyNode = None
        self.curIndex = 0
        self.destIndex = 0
        self.time = 0.0
        self.ival = None
        self.fsm.enterInitialState()
        return

    def generate(self):
        DistributedObject.DistributedObject.generate(self)
        if self.butterfly:
            return
        self.butterfly = Actor.Actor()
        self.butterfly.loadModel('phase_4/models/props/SZ_butterfly-mod.bam')
        self.butterfly.loadAnims({'flutter': 'phase_4/models/props/SZ_butterfly-flutter.bam',
         'glide': 'phase_4/models/props/SZ_butterfly-glide.bam',
         'land': 'phase_4/models/props/SZ_butterfly-land.bam'})
        index = self.doId % len(self.wingTypes)
        chosenType = self.wingTypes[index]
        node = self.butterfly.getGeomNode()
        for type in self.wingTypes:
            wing = node.find('**/' + type)
            if type != chosenType:
                wing.removeNode()
            else:
                if index == 0 or index == 1:
                    color = self.yellowColors[self.doId % len(self.yellowColors)]
                elif index == 2 or index == 3:
                    color = self.whiteColors[self.doId % len(self.whiteColors)]
                elif index == 4:
                    color = self.paleYellowColors[self.doId % len(self.paleYellowColors)]
                else:
                    color = Vec4(1, 1, 1, 1)
                wing.setColor(color)

        self.butterfly2 = Actor.Actor(other=self.butterfly)
        self.butterfly.enableBlend(blendType=PartBundle.BTLinear)
        self.butterfly.loop('flutter')
        self.butterfly.loop('land')
        self.butterfly.loop('glide')
        rng = RandomNumGen.RandomNumGen(self.doId)
        playRate = 0.6 + 0.8 * rng.random()
        self.butterfly.setPlayRate(playRate, 'flutter')
        self.butterfly.setPlayRate(playRate, 'land')
        self.butterfly.setPlayRate(playRate, 'glide')
        self.butterfly2.setPlayRate(playRate, 'flutter')
        self.butterfly2.setPlayRate(playRate, 'land')
        self.butterfly2.setPlayRate(playRate, 'glide')
        self.glideWeight = rng.random() * 2
        lodNode = LODNode('butterfly-node')
        lodNode.addSwitch(100, 40)
        lodNode.addSwitch(40, 0)
        self.butterflyNode = NodePath(lodNode)
        self.butterfly2.setH(180.0)
        self.butterfly2.reparentTo(self.butterflyNode)
        self.butterfly.setH(180.0)
        self.butterfly.reparentTo(self.butterflyNode)
        self.__initCollisions()
        self.dropShadow = loader.loadModel('phase_3/models/props/drop_shadow')
        self.dropShadow.setColor(0, 0, 0, 0.3)
        self.dropShadow.setPos(0, 0.1, -0.05)
        self.dropShadow.setScale(self.shadowScaleBig)
        self.dropShadow.reparentTo(self.butterfly)

    def disable(self):
        self.butterflyNode.reparentTo(hidden)
        if self.ival != None:
            self.ival.finish()
        self.__ignoreAvatars()
        DistributedObject.DistributedObject.disable(self)
        return

    def delete(self):
        self.butterfly.cleanup()
        self.butterfly = None
        self.butterfly2.cleanup()
        self.butterfly2 = None
        self.butterflyNode.removeNode()
        self.__deleteCollisions()
        self.ival = None
        del self.fsm
        DistributedObject.DistributedObject.delete(self)
        return

    def uniqueButterflyName(self, name):
        DistributedButterfly.id += 1
        return name + '-%d' % DistributedButterfly.id

    def __detectAvatars(self):
        self.accept('enter' + self.cSphereNode.getName(), self.__handleCollisionSphereEnter)

    def __ignoreAvatars(self):
        self.ignore('enter' + self.cSphereNode.getName())

    def __initCollisions(self):
        self.cSphere = CollisionSphere(0.0, 1.0, 0.0, 3.0)
        self.cSphere.setTangible(0)
        self.cSphereNode = CollisionNode(self.uniqueButterflyName('cSphereNode'))
        self.cSphereNode.addSolid(self.cSphere)
        self.cSphereNodePath = self.butterflyNode.attachNewNode(self.cSphereNode)
        self.cSphereNodePath.hide()
        self.cSphereNode.setCollideMask(ToontownGlobals.WallBitmask)

    def __deleteCollisions(self):
        del self.cSphere
        del self.cSphereNode
        self.cSphereNodePath.removeNode()
        del self.cSphereNodePath

    def __handleCollisionSphereEnter(self, collEntry):
        self.sendUpdate('avatarEnter', [])

    def setArea(self, playground, area):
        self.playground = playground
        self.area = area

    def setState(self, stateIndex, curIndex, destIndex, time, timestamp):
        self.curIndex = curIndex
        self.destIndex = destIndex
        self.time = time
        self.fsm.request(ButterflyGlobals.states[stateIndex], [globalClockDelta.localElapsedTime(timestamp)])

    def enterOff(self, ts = 0.0):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(hidden)
        return

    def exitOff(self):
        if self.butterflyNode != None:
            self.butterflyNode.reparentTo(render)
        return

    def enterFlying(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex]
        destPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.destIndex]
        flyHeight = max(curPos[2], destPos[2]) + ButterflyGlobals.BUTTERFLY_HEIGHT[self.playground]
        curPosHigh = Point3(curPos[0], curPos[1], flyHeight)
        destPosHigh = Point3(destPos[0], destPos[1], flyHeight)
        if ts <= self.time:
            flyTime = self.time - (ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground] + ButterflyGlobals.BUTTERFLY_LANDING[self.playground])
            self.butterflyNode.setPos(curPos)
            self.dropShadow.show()
            self.dropShadow.setScale(self.shadowScaleBig)
            oldHpr = self.butterflyNode.getHpr()
            self.butterflyNode.headsUp(destPos)
            newHpr = self.butterflyNode.getHpr()
            self.butterflyNode.setHpr(oldHpr)
            takeoffShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground]
            landShadowT = 0.2 * ButterflyGlobals.BUTTERFLY_LANDING[self.playground]
            self.butterfly2.loop('flutter')
            self.ival = Sequence(Parallel(LerpPosHprInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], curPosHigh, newHpr), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], 'land', 'flutter'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_TAKEOFF[self.playground], None, 'glide', startWeight=0, endWeight=self.glideWeight), Sequence(LerpScaleInterval(self.dropShadow, takeoffShadowT, self.shadowScaleSmall, startScale=self.shadowScaleBig), HideInterval(self.dropShadow))), LerpPosInterval(self.butterflyNode, flyTime, destPosHigh), Parallel(LerpPosInterval(self.butterflyNode, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], destPos), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], 'flutter', 'land'), LerpAnimInterval(self.butterfly, ButterflyGlobals.BUTTERFLY_LANDING[self.playground], None, 'glide', startWeight=self.glideWeight, endWeight=0), Sequence(Wait(ButterflyGlobals.BUTTERFLY_LANDING[self.playground] - landShadowT), ShowInterval(self.dropShadow), LerpScaleInterval(self.dropShadow, landShadowT, self.shadowScaleBig, startScale=self.shadowScaleSmall))), name=self.uniqueName('Butterfly'))
            self.ival.start(ts)
        else:
            self.ival = None
            self.butterflyNode.setPos(destPos)
            self.butterfly.setControlEffect('land', 1.0)
            self.butterfly.setControlEffect('flutter', 0.0)
            self.butterfly.setControlEffect('glide', 0.0)
            self.butterfly2.loop('land')
        return

    def exitFlying(self):
        self.__ignoreAvatars()
        if self.ival != None:
            self.ival.finish()
            self.ival = None
        return

    def enterLanded(self, ts):
        self.__detectAvatars()
        curPos = ButterflyGlobals.ButterflyPoints[self.playground][self.area][self.curIndex]
        self.butterflyNode.setPos(curPos)
        self.dropShadow.show()
        self.dropShadow.setScale(self.shadowScaleBig)
        self.butterfly.setControlEffect('land', 1.0)
        self.butterfly.setControlEffect('flutter', 0.0)
        self.butterfly.setControlEffect('glide', 0.0)
        self.butterfly2.pose('land', random.randrange(self.butterfly2.getNumFrames('land')))
        return None

    def exitLanded(self):
        self.__ignoreAvatars()
        return None
Exemple #26
0
class Bot(object):

    def __init__(self, team, position, direction):
        self._orders = Actions.DoNothing
        self._hp = 5
        self._death_played = False
        self._interval = None
        self.kills = 0

        self.team = team

        self._model = NodePath('bot')
        self._model.reparentTo(render)

        self._model.setPos(position)
        self._model.setHpr(direction, 0, 0)
        self._model.setColorScale(*self.team)
        self._model.setScale(.2, .2, .2)

        # Load the animations
        self._actor = Actor("models/RockGolem", {
            'idle': 'models/RockGolem-idle',
            'walk': 'models/RockGolem-walk',
            'reverse-walk': 'models/RockGolem-walk',
            'punch': 'models/RockGolem-punch',
            'death': 'models/RockGolem-death',
            'throw': 'models/RockGolem-throw',
        })
        self._actor.setPlayRate(2.65, 'walk')
        self._actor.setPlayRate(-2.65, 'reverse-walk')
        self._actor.setPlayRate(4, 'punch')
        self._actor.setPlayRate(5.25, 'throw')
        self._actor.setBlend(frameBlend=True)
        self._actor.reparentTo(self._model)
        self._actor.loop('idle')
        self._actor.setH(180)

        # Floating Label
        text = TextNode('node name')
        text.setText(self.__class__.__name__)
        text.setAlign(TextNode.ACenter)
        self._name_label = self._model.attachNewNode(text)
        self._name_label.setBillboardPointEye()
        self._name_label.setPos(Vec3(0, 0, 6))
        self._name_label.setScale(3, 3, 3)

        # Debug Field of View Cones
        # fov = make_fov()
        # fov.reparentTo(self._model)

    def update(self, tick_number, visible_objects):
        return Actions.DoNothing

    def get_position(self):
        """Return a rounded version of the position vector."""
        p = self._model.getPos()
        return Vec3(round(p.x, 0), round(p.y, 0), round(p.z, 0))

    def get_direction(self):
        """Return a rounded version of the direction vector."""
        v = render.getRelativeVector(self._model, Vec3(0, 1, 0))
        v.normalize()
        return Vec3(round(v.x, 0), round(v.y, 0), round(v.z, 0))

    def get_name(self):
        return self.__class__.__name__

    def _get_orders(self, tick_number, visible_objects):
        # If the health is too low, die.
        if self._hp <= 0:
            self._orders = Actions.Suicide
            return

        # noinspection PyBroadException
        try:
            self._orders = self.update(tick_number, visible_objects)
        except Exception as e:
            print(type(self), e)
            self._orders = None

    def _execute_orders(self, tick_length, battle):
        # Pre-calculate some useful things
        new_pos = self.get_position()
        new_dir = self._model.getHpr()  # TODO: Getting rounding errors here
        velocity = self.get_direction()

        # If we're outside of the arena, take damage
        ARENA_SIZE = 13
        if new_pos.length() > ARENA_SIZE:
            battle.announce("{} fled the battle!".format(self.get_name()))
            self.take_damage(999)

        # Execute the order
        if self._orders == Actions.MoveForward:
            new_pos += velocity
            self.safe_loop('walk')

        elif self._orders == Actions.MoveBackward:
            new_pos -= velocity
            self.safe_loop('reverse-walk')

        elif self._orders == Actions.StrafeLeft:
            v = render.getRelativeVector(self._model, Vec3(-1, 0, 0))
            v.normalize()
            v = Vec3(round(v.x, 0), round(v.y, 0), round(v.z, 0))
            new_pos += v
            self.safe_loop('walk')

        elif self._orders == Actions.StrafeRight:
            v = render.getRelativeVector(self._model, Vec3(1, 0, 0))
            v.normalize()
            v = Vec3(round(v.x, 0), round(v.y, 0), round(v.z, 0))
            new_pos += v
            self.safe_loop('walk')

        elif self._orders == Actions.TurnLeft:
            new_dir.x += 90
            self.safe_loop('walk')

        elif self._orders == Actions.TurnAround:
            new_dir.x += 180
            self.safe_loop('walk')

        elif self._orders == Actions.TurnRight:
            new_dir.x -= 90
            self.safe_loop('walk')

        elif self._orders == Actions.Punch:
            self.punch(battle)

        elif self._orders == Actions.DoNothing:
            self.safe_loop('idle')

        elif self._orders == Actions.Suicide:
            self._hp = 0
            battle.announce("{} killed itself.".format(self.get_name()))
            self.take_damage(999)

        else:  # Bad orders detected! Kill this bot.
            self._hp = 0
            battle.announce("{} made an illegal move and died.".format(self.get_name()))
            self.take_damage(999)

        # Animate the motion
        if self._hp <= 0:
            return
        self._interval = LerpPosHprInterval(
            self._model, tick_length-0.05, new_pos, new_dir)
        self._interval.start()

    def safe_loop(self, animation):
        if self._death_played:
            return
        if self._actor.getCurrentAnim() != animation:
            self._actor.loop(animation)

    def punch(self, battle):
        if not self._death_played:
            self._actor.play('punch')
        hazard = self.get_direction() + self.get_position()
        bot = battle.get_object_at_position(hazard)
        if isinstance(bot, Bot):
            bot.take_damage(5)  # TODO: This is fun as 1
            if bot._hp > 0:
                return
            if bot.team == self.team:
                message = "{self} killed its teammate {target}!"
                self.kills -= 1
            else:
                message = "{self} just pwned {target}!"
                self.kills += 1
            battle.announce(message.format(self=self.get_name(),
                                           target=bot.get_name()),
                            color=self.team,
                            sfx="Ownage" if self.kills == 1 else None)
            if self.kills == 2:
                battle.announce("{} is ON FIRE!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="DoubleKill")
            elif self.kills == 3:
                battle.announce("{} is UNSTOPPABLE!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="TripleKill")
            elif self.kills == 4:
                battle.announce("{} is DOMINATING!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="Dominating")
            elif self.kills > 4:
                battle.announce("{} is GODLIKE!".format(self.get_name()),
                                color=(1.0, 0.5, 0.0, 1.0), sfx="Godlike")

    def take_damage(self, amount):
        self._hp -= amount
        if self._hp <= 0:
            self._name_label.hide()
            if self._interval:
                self._interval.pause()
            if not self._death_played:
                self._actor.play('death')
                self._death_played = True

    def delete(self):
        self._model.removeNode()
        self._actor.cleanup()
        self._name_label.removeNode()
Exemple #27
0
class Bot:
    _orders = Actions.DoNothing
    _hp = 5
    _death_played = False

    def __init__(self, team, position, direction):
        self.team = team

        self._model = NodePath("bot")
        self._model.reparentTo(render)

        self._model.setPos(position)
        self._model.setHpr(direction, 0, 0)
        self._model.setColorScale(*self.team)
        self._model.setScale(0.15, 0.15, 0.15)

        # Load the animations
        self._actor = Actor(
            "models/RockGolem",
            {
                "idle": "models/RockGolem-idle",
                "walk": "models/RockGolem-walk",
                "reverse-walk": "models/RockGolem-walk",
                "punch": "models/RockGolem-punch",
                "death": "models/RockGolem-death",
            },
        )
        self._actor.setPlayRate(2.65, "walk")
        self._actor.setPlayRate(-2.65, "reverse-walk")
        self._actor.setPlayRate(4, "punch")
        self._actor.setBlend(frameBlend=True)
        self._actor.reparentTo(self._model)
        self._actor.loop("idle")
        self._actor.setH(90)

        # fov = make_fov()
        # fov.reparentTo(self._model)

    def update(self, tick_number, visible_objects):
        return Actions.DoNothing

    def _get_orders(self, tick_number, visible_objects):
        if self._hp <= 0:
            return

        # noinspection PyBroadException
        try:
            self._orders = self.update(tick_number, visible_objects)
        except Exception as e:
            print(type(self), e)
            self._orders = Actions.Suicide

    def _execute_orders(self, tick_length):
        # Pre-calculate some useful things
        new_pos = self._model.getPos()
        new_dir = self._model.getHpr()
        velocity = render.getRelativeVector(self._model, Vec3(1, 0, 0))
        velocity.normalize()

        if self._orders == Actions.MoveForward:
            new_pos += velocity
            self.safe_loop("walk")

        elif self._orders == Actions.MoveBackward:
            new_pos -= velocity
            self.safe_loop("reverse-walk")

        elif self._orders == Actions.StrafeLeft:
            new_pos += velocity
            self.safe_loop("walk")

        elif self._orders == Actions.StrafeRight:
            new_pos += velocity
            self.safe_loop("walk")

        elif self._orders == Actions.TurnLeft:
            new_dir.x += 90
            self.safe_loop("walk")

        elif self._orders == Actions.TurnAround:
            new_dir.x += 180
            self.safe_loop("walk")

        elif self._orders == Actions.TurnRight:
            new_dir.x -= 90
            self.safe_loop("walk")

        elif self._orders == Actions.Punch:
            self.punch()

        elif self._orders == Actions.Shoot:
            self.shoot()

        elif self._orders == Actions.DoNothing:
            self.safe_loop("idle")

        elif self._orders == Actions.Suicide:
            self._hp = 0
            self.die()

        else:  # Bad orders detected! Kill this bot.
            self._hp = 0
            self.die()

        # Animate the motion
        tick = tick_length - 0.05  # Shave off a tiny bit to finish the interval
        LerpPosHprInterval(self._model, tick, new_pos, new_dir).start()

    def safe_loop(self, animation):
        if self._actor.getCurrentAnim() != animation:
            self._actor.loop(animation)

    def die(self):
        if not self._death_played:
            self._actor.play("death")
            self._death_played = True

    def punch(self):
        print("Punching not implemented yet!")
        self._actor.play("punch")

    def shoot(self):
        print("Shooting not implemented yet!")
        self._actor.play("shoot")
Exemple #28
0
class MapObject(MapWritable):

    ObjectName = "object"

    def __init__(self, id):
        MapObjectInit.start()

        MapWritable.__init__(self, base.document)
        self.temporary = False
        self.id = id
        self.selected = False
        self.classname = ""
        self.parent = None
        self.children = {}
        self.boundingBox = BoundingBox(Vec3(-0.5, -0.5, -0.5), Vec3(0.5, 0.5, 0.5))
        self.boundsBox = Box()
        self.boundsBox.addView(GeomView.Lines, VIEWPORT_3D_MASK, state = BoundsBox3DState)
        self.boundsBox.addView(GeomView.Lines, VIEWPORT_2D_MASK, state = BoundsBox2DState)
        self.boundsBox.generateGeometry()
        self.collNp = None

        self.group = None

        self.properties = {}

        # All MapObjects have transform
        self.addProperty(OriginProperty(self))
        self.addProperty(AnglesProperty(self))
        self.addProperty(ScaleProperty(self))
        self.addProperty(ShearProperty(self))

        self.np = NodePath(ModelNode(self.ObjectName + ".%i" % self.id))
        self.np.setPythonTag("mapobject", self)
        self.applyCollideMask()
        # Test bounding volume at this node and but nothing below it.
        self.np.node().setFinal(True)

        MapObjectInit.stop()

    def getClassName(self):
        return self.classname

    def isWorld(self):
        return False

    def r_findAllParents(self, parents, type):
        if not self.parent or self.parent.isWorld():
            return

        if type is None or isinstance(self.parent, type):
            parents.append(self.parent)

        self.parent.r_findAllParents(parents, type)

    def findAllParents(self, type = None):
        parents = []
        self.r_findAllParents(parents, type)
        return parents

    def findTopmostParent(self, type = None):
        parents = self.findAllParents(type)
        if len(parents) == 0:
            return None

        return parents[len(parents) - 1]

    def r_findAllChildren(self, children, type):
        for child in self.children.values():
            if type is None or isinstance(child, type):
                children.append(child)
            child.r_findAllChildren(children, type)

    def findAllChildren(self, type = None):
        children = []

        self.r_findAllChildren(children, type)

        return children

    def applyCollideMask(self):
        self.np.setCollideMask(LEGlobals.ObjectMask)

    def setTemporary(self, flag):
        self.temporary = flag

    # Returns the bounding volume of the object itself, not including children objects.
    def getObjBounds(self, other = None):
        if not other:
            other = self.np.getParent()
        return self.np.getTightBounds(other)

    # Returns the min and max points of the bounds of the object, not including children.
    def getBounds(self, other = None):
        if not other:
            other = self.np.getParent()
        mins = Point3()
        maxs = Point3()
        self.np.calcTightBounds(mins, maxs, other)
        return [mins, maxs]

    def findChildByID(self, id):
        if id == self.id:
            return self

        if id in self.children:
            return self.children[id]

        for child in self.children.values():
            ret = child.findChildByID(id)
            if ret is not None:
                return ret

        return None

    def hasChildWithID(self, id):
        return id in self.children

    def copy(self, generator):
        raise NotImplementedError

    def paste(self, o, generator):
        raise NotImplementedError

    def clone(self):
        raise NotImplementedError

    def unclone(self, o):
        raise NotImplementedError

    #
    # Base copy and paste functions shared by all MapObjects.
    # Each specific MapObject must implement the functions above for their
    # specific functionality.
    #

    def copyProperties(self, props):
        newProps = {}
        for key, prop in props.items():
            newProp = prop.clone(self)
            newProp.setValue(prop.getValue())
            newProps[key] = newProp
        self.updateProperties(newProps)

    def copyBase(self, other, generator, clone = False):
        if clone and other.id != self.id:
            parent = other.parent
            setPar = other.parent is not None and other.parent.hasChildWithID(other.id) and other.parent.children[other.id] == other
            if setPar:
                other.reparentTo(NodePath())
            other.id = self.id
            if setPar:
                other.reparentTo(parent)

        other.parent = self.parent

        for child in self.children.values():
            if clone:
                newChild = child.clone()
            else:
                newChild = child.copy(generator)
            newChild.reparentTo(other)

        other.setClassname(self.classname)
        other.copyProperties(self.properties)
        other.selected = self.selected

    def pasteBase(self, o, generator, performUnclone = False):
        if performUnclone and o.id != self.id:
            parent = self.parent
            setPar = self.parent is not None and self.parent.hasChildWithID(self.id) and self.parent.children[self.id] == self
            if setPar:
                self.reparentTo(NodePath())
            self.id = o.id
            if setPar:
                self.reparentTo(parent)

        for child in o.children.values():
            if performUnclone:
                newChild = child.clone()
            else:
                newChild = child.copy(generator)
            newChild.reparentTo(self)

        self.setClassname(o.classname)
        self.copyProperties(o.properties)
        self.selected = o.selected

    def getName(self):
        return "Object"

    def getDescription(self):
        return "Object in a map."

    def addProperty(self, prop):
        self.properties[prop.name] = prop

    # Returns list of property names with the specified value types.
    def getPropsWithValueType(self, types):
        if isinstance(types, str):
            types = [types]
        props = []
        for propName, prop in self.properties.items():
            if prop.valueType in types:
                props.append(propName)
        return props

    def getPropNativeType(self, key):
        prop = self.properties.get(key, None)
        if not prop:
            return str

        return prop.getNativeType()

    def getPropValueType(self, key):
        prop = self.properties.get(key, None)
        if not prop:
            return "string"

        return prop.valueType

    def getPropDefaultValue(self, prop):
        if isinstance(prop, str):
            prop = self.properties.get(prop, None)

        if not prop:
            return ""

        return prop.defaultValue

    def getPropertyValue(self, key, asString = False, default = ""):
        prop = self.properties.get(key, None)
        if not prop:
            return default

        if asString:
            return prop.getSerializedValue()
        else:
            return prop.getValue()

    def getProperty(self, name):
        return self.properties.get(name, None)

    def updateProperties(self, data):
        for key, value in data.items():
            if not isinstance(value, ObjectProperty):
                # If only a value was specified and not a property object itself,
                # this is an update to an existing property.

                prop = self.properties.get(key, None)
                if not prop:
                    continue

                oldValue = prop.getValue()

                val = prop.getUnserializedValue(value)

                # If the property has a min/max range, ensure the value we want to
                # set is within that range.
                if (not prop.testMinValue(val)) or (not prop.testMaxValue(val)):
                    # Not within range. Use the default value
                    val = prop.defaultValue

                prop.setValue(val)
            else:
                # A property object was given, simply add it to the dict of properties.
                prop = value
                oldValue = None
                val = prop.getValue()
                self.properties[prop.name] = prop

            self.propertyChanged(prop, oldValue, val)

    def propertyChanged(self, prop, oldValue, newValue):
        if oldValue != newValue:
            self.send('objectPropertyChanged', [self, prop, newValue])

    def setAbsOrigin(self, origin):
        self.np.setPos(base.render, origin)
        self.transformChanged()

    def setOrigin(self, origin):
        self.np.setPos(origin)
        self.transformChanged()

    def getAbsOrigin(self):
        return self.np.getPos(base.render)

    def getOrigin(self):
        return self.np.getPos()

    def setAngles(self, angles):
        self.np.setHpr(angles)
        self.transformChanged()

    def setAbsAngles(self, angles):
        self.np.setHpr(base.render, angles)
        self.transformChanged()

    def getAbsAngles(self):
        return self.np.getHpr(base.render)

    def getAngles(self):
        return self.np.getHpr()

    def setScale(self, scale):
        self.np.setScale(scale)
        self.transformChanged()

    def setAbsScale(self, scale):
        self.np.setScale(base.render, scale)
        self.transformChanged()

    def getAbsScale(self):
        return self.np.getScale(base.render)

    def getScale(self):
        return self.np.getScale()

    def setShear(self, shear):
        self.np.setShear(shear)
        self.transformChanged()

    def setAbsShear(self, shear):
        self.np.setShear(base.render, shear)
        self.transformChanged()

    def getAbsShear(self):
        return self.np.getShear(base.render)

    def getShear(self):
        return self.np.getShear()

    def transformChanged(self):
        self.recalcBoundingBox()
        self.send('objectTransformChanged', [self])

    def showBoundingBox(self):
        self.boundsBox.np.reparentTo(self.np)

    def hideBoundingBox(self):
        self.boundsBox.np.reparentTo(NodePath())

    def select(self):
        self.selected = True
        self.showBoundingBox()
        #self.np.setColorScale(1, 0, 0, 1)

    def deselect(self):
        self.selected = False
        self.hideBoundingBox()
        #self.np.setColorScale(1, 1, 1, 1)

    def setClassname(self, classname):
        self.classname = classname

    def fixBounds(self, mins, maxs):
        # Ensures that the bounds are not flat on any axis
        sameX = mins.x == maxs.x
        sameY = mins.y == maxs.y
        sameZ = mins.z == maxs.z

        invalid = False

        if sameX:
            # Flat horizontal
            if sameY and sameZ:
                invalid = True
            elif not sameY:
                mins.x = mins.y
                maxs.x = maxs.y
            elif not sameZ:
                mins.x = mins.z
                maxs.x = maxs.z

        if sameY:
            # Flat forward/back
            if sameX and sameZ:
                invalid = True
            elif not sameX:
                mins.y = mins.x
                maxs.y = maxs.x
            elif not sameZ:
                mins.y = mins.z
                maxs.y = maxs.z

        if sameZ:
            if sameX and sameY:
                invalid = True
            elif not sameX:
                mins.z = mins.x
                maxs.z = maxs.x
            elif not sameY:
                mins.z = mins.y
                maxs.z = maxs.y

        return [invalid, mins, maxs]

    def recalcBoundingBox(self):
        if not self.np:
            return

        # Don't have the picker box or selection visualization contribute to the
        # calculation of the bounding box.
        if self.collNp:
            self.collNp.stash()
        self.hideBoundingBox()

        # Calculate a bounding box relative to ourself
        mins, maxs = self.getBounds(self.np)

        invalid, mins, maxs = self.fixBounds(mins, maxs)
        if invalid:
            mins = Point3(-8)
            maxs = Point3(8)

        self.boundingBox = BoundingBox(mins, maxs)
        self.boundsBox.setMinMax(mins, maxs)
        if self.selected:
            self.showBoundingBox()

        if self.collNp:
            self.collNp.unstash()
            self.collNp.node().clearSolids()
            self.collNp.node().addSolid(CollisionBox(mins, maxs))
            self.collNp.hide(~VIEWPORT_3D_MASK)

        self.send('mapObjectBoundsChanged', [self])

    def removePickBox(self):
        if self.collNp:
            self.collNp.removeNode()
            self.collNp = None

    def delete(self):
        if not self.temporary:
            # Take the children with us
            for child in list(self.children.values()):
                child.delete()
            self.children = None
            # if we are selected, deselect
            base.selectionMgr.deselect(self)

        if self.boundsBox:
            self.boundsBox.cleanup()
            self.boundsBox = None

        self.removePickBox()

        if not self.temporary:
            self.reparentTo(NodePath())
        self.np.removeNode()
        self.np = None
        self.properties = None
        self.metaData = None

        self.temporary = None

    def __clearParent(self):
        if self.parent:
            self.parent.__removeChild(self)
            self.np.reparentTo(NodePath())
            self.parent = None

    def __setParent(self, other):
        if isinstance(other, NodePath):
            # We are reparenting directly to a NodePath, outside of the MapObject tree.
            self.parent = None
            self.np.reparentTo(other)
        else:
            self.parent = other
            if self.parent:
                self.parent.__addChild(self)
                self.np.reparentTo(self.parent.np)
            else:
                # If None was passed, assume base.render
                self.np.reparentTo(base.render)

    def reparentTo(self, other):
        # If a NodePath is passed to this method, the object will be placed under the specified node
        # in the Panda3D scene graph, but will be taken out of the MapObject tree. If None is passed,
        # the object will be parented to base.render and taken out of the MapObject tree.
        #
        # Use reparentTo(NodePath()) to place the object outside of both the scene graph and the
        # MapObject tree.
        self.__clearParent()
        self.__setParent(other)

    def __addChild(self, child):
        self.children[child.id] = child
        #self.recalcBoundingBox()

    def __removeChild(self, child):
        if child.id in self.children:
            del self.children[child.id]
            #self.recalcBoundingBox()

    def doWriteKeyValues(self, parent):
        kv = CKeyValues(self.ObjectName, parent)
        self.writeKeyValues(kv)
        for child in self.children.values():
            child.doWriteKeyValues(kv)

    def writeKeyValues(self, keyvalues):
        keyvalues.setKeyValue("id", str(self.id))
        # Write out our object properties
        for name, prop in self.properties.items():
            prop.writeKeyValues(keyvalues)

    def readKeyValues(self, keyvalues):
        for i in range(keyvalues.getNumKeys()):
            key = keyvalues.getKey(i)
            value = keyvalues.getValue(i)
            if MetaData.isPropertyExcluded(key):
                continue
            # Find the property with this name.
            prop = self.properties.get(key, None)
            if not prop:
                # Prop wasn't explicit or part of FGD metadata (if it's an Entity)
                continue

            nativeValue = prop.getUnserializedValue(value)

            # Set the value!
            self.updateProperties({prop.name: nativeValue})
Exemple #29
0
class CogdoExecutiveSuiteIntro(CogdoGameMovie):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        'CogdoExecutiveSuiteIntro')
    introDuration = 7
    cameraMoveDuration = 3

    def __init__(self, shopOwner):
        CogdoGameMovie.__init__(self)
        self._shopOwner = shopOwner
        self._lookAtCamTarget = False
        self._camTarget = None
        self._camHelperNode = None
        self._toonDialogueSfx = None
        self.toonHead = None
        self.frame = None
        return

    def displayLine(self, text):
        self.notify.debug('displayLine')
        self._dialogueLabel.node().setText(text)
        self.toonHead.reparentTo(aspect2d)
        self._toonDialogueSfx.play()
        self.toonHead.setClipPlane(self.clipPlane)

    def makeSuit(self, suitType):
        self.notify.debug('makeSuit()')
        suit = Suit.Suit()
        dna = SuitDNA.SuitDNA()
        dna.newSuit(suitType)
        suit.setStyle(dna)
        suit.isDisguised = 1
        suit.generateSuit()
        suit.setScale(1, 1, 2)
        suit.setPos(0, 0, -4.4)
        suit.reparentTo(self.toonHead)
        for part in suit.getHeadParts():
            part.hide()

        suit.loop('neutral')

    def load(self):
        self.notify.debug('load()')
        CogdoGameMovie.load(self)
        backgroundGui = loader.loadModel(
            'phase_5/models/cogdominium/tt_m_gui_csa_flyThru')
        self.bg = backgroundGui.find('**/background')
        self.chatBubble = backgroundGui.find('**/chatBubble')
        self.chatBubble.setScale(6.5, 6.5, 7.3)
        self.chatBubble.setPos(0.32, 0, -0.78)
        self.bg.setScale(5.2)
        self.bg.setPos(0.14, 0, -0.6667)
        self.bg.reparentTo(aspect2d)
        self.chatBubble.reparentTo(aspect2d)
        self.frame = DirectFrame(geom=self.bg,
                                 relief=None,
                                 pos=(0.2, 0, -0.6667))
        self.bg.wrtReparentTo(self.frame)
        self.gameTitleText = DirectLabel(
            parent=self.frame,
            text=TTLocalizer.CogdoExecutiveSuiteTitle,
            scale=TTLocalizer.MRPgameTitleText * 0.8,
            text_align=TextNode.ACenter,
            text_font=getSignFont(),
            text_fg=(1.0, 0.33, 0.33, 1.0),
            pos=TTLocalizer.MRgameTitleTextPos,
            relief=None)
        self.chatBubble.wrtReparentTo(self.frame)
        self.frame.hide()
        backgroundGui.removeNode()
        self.toonDNA = ToonDNA.ToonDNA()
        self.toonDNA.newToonFromProperties('dss', 'ss', 'm', 'm', 2, 0, 2, 2,
                                           1, 8, 1, 8, 1, 14)
        self.toonHead = Toon.Toon()
        self.toonHead.setDNA(self.toonDNA)
        self.makeSuit('sc')
        self.toonHead.getGeomNode().setDepthWrite(1)
        self.toonHead.getGeomNode().setDepthTest(1)
        self.toonHead.loop('neutral')
        self.toonHead.setPosHprScale(-0.73, 0, -1.27, 180, 0, 0, 0.18, 0.18,
                                     0.18)
        self.toonHead.reparentTo(hidden)
        self.toonHead.startBlink()
        self.clipPlane = self.toonHead.attachNewNode(PlaneNode('clip'))
        self.clipPlane.node().setPlane(Plane(0, 0, 1, 0))
        self.clipPlane.setPos(0, 0, 2.45)
        self._toonDialogueSfx = loader.loadSfx(
            'phase_3.5/audio/dial/AV_dog_long.ogg')
        self._camHelperNode = NodePath('CamHelperNode')
        self._camHelperNode.reparentTo(render)
        dialogue = TTLocalizer.CogdoExecutiveSuiteIntroMessage

        def start():
            self.frame.show()
            base.setCellsActive(
                base.bottomCells + base.leftCells + base.rightCells, 0)

        def showShopOwner():
            self._setCamTarget(self._shopOwner, -10, offset=Point3(0, 0, 5))

        def end():
            self._dialogueLabel.reparentTo(hidden)
            self.toonHead.reparentTo(hidden)
            self.frame.hide()
            base.setCellsActive(
                base.bottomCells + base.leftCells + base.rightCells, 1)
            self._stopUpdateTask()

        self._ival = Sequence(
            Func(start), Func(self.displayLine, dialogue), Func(showShopOwner),
            ParallelEndTogether(
                camera.posInterval(self.cameraMoveDuration,
                                   Point3(8, 0, 13),
                                   blendType='easeInOut'),
                camera.hprInterval(0.5,
                                   self._camHelperNode.getHpr(),
                                   blendType='easeInOut')),
            Wait(self.introDuration), Func(end))
        self._startUpdateTask()
        return

    def _setCamTarget(self,
                      targetNP,
                      distance,
                      offset=Point3(0, 0, 0),
                      angle=Point3(0, 0, 0)):
        camera.wrtReparentTo(render)
        self._camTarget = targetNP
        self._camOffset = offset
        self._camAngle = angle
        self._camDistance = distance
        self._camHelperNode.setPos(self._camTarget, self._camOffset)
        self._camHelperNode.setHpr(self._camTarget, 180 + self._camAngle[0],
                                   self._camAngle[1], self._camAngle[2])
        self._camHelperNode.setPos(self._camHelperNode, 0, self._camDistance,
                                   0)

    def _updateTask(self, task):
        dt = globalClock.getDt()
        return task.cont

    def unload(self):
        self._shopOwner = None
        self._camTarget = None
        if hasattr(self, '_camHelperNode') and self._camHelperNode:
            self._camHelperNode.removeNode()
            del self._camHelperNode
        self.frame.destroy()
        del self.frame
        self.bg.removeNode()
        del self.bg
        self.chatBubble.removeNode()
        del self.chatBubble
        self.toonHead.stopBlink()
        self.toonHead.stop()
        self.toonHead.removeNode()
        self.toonHead.delete()
        del self.toonHead
        CogdoGameMovie.unload(self)
        return
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 np not 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:
                    np.find('**/*floor_mesh').hide()
                elif np.getName().find('platform') >= 0:
                    np.find('**/*Floor').hide()

        for np, parent in self._betweenCamAndToon.items():
            np.wrtReparentTo(parent)
            np.setTransparency(False)
            if np.getName().find('lightFixture') >= 0:
                np.find('**/*floor_mesh').show()
            elif np.getName().find('platform') >= 0:
                np.find('**/*Floor').show()

        self._betweenCamAndToon = nodesInBetween
Exemple #31
0
class Transform(Component):
    """Each game object has exactly one of these. A transform holds data
    about position, rotation, scale and parent relationship.
    
    In Panity this is a wrapper for a NodePath.
    """

    def __init__(self, game_object, name):
        # Component class sets self.game_object = game_object
        Component.__init__(self, game_object)
        self.node = NodePath(name)
        self.node.setPythonTag("transform", self)

    @classmethod
    def getClassSerializedProperties(cls):
        """Return all special property attributes in a dict. Only attributes
        derived from SerializedProperty are respected.

        On transform component this method always returns local position,
        -rotation and scale only.
        """
        d = {}
        d["local_position"] = Transform.local_position
        d["local_euler_angles"] = Transform.local_euler_angles
        d["local_scale"] = Transform.local_scale
        return d

    def getSerializedProperties(self):
        """Return all properties for serialization. In the case of transform
        this only returns local position, -rotation and -scale, which are
        required to restore the state of the node.
        """
        d = {}
        d["local_position"] = self.local_position
        d["local_euler_angles"] = self.local_euler_angles
        d["local_scale"] = self.local_scale
        return d

    # We use the panda node to save the name on it for better debugging and
    # efficient finding of nodes with NodePath().find()
    @SerializedPropertyDecorator
    def name(self):
        return self.node.getName()
    @name.setter
    def name(self, name):
        if name == "render":
            name = "_render"
        self.node.setName(name)

    @SerializedPropertyDecorator
    def position(self):
        return self.node.getPos(self.root.node)
    @position.setter
    def position(self, position):
        self.node.setPos(self.root.node, *position)
    
    @SerializedPropertyDecorator
    def local_position(self):
        return self.node.getPos()
    @local_position.setter
    def local_position(self, position):
        self.node.setPos(*position)

    @SerializedPropertyDecorator
    def euler_angles(self):
        return self.node.getHpr(self.root.node)
    @euler_angles.setter
    def euler_angles(self, angles):
        self.node.setHpr(self.root.node, *angles)
    
    @SerializedPropertyDecorator
    def local_euler_angles(self):
        return self.node.getHpr()
    @local_euler_angles.setter
    def local_euler_angles(self, angles):
        self.node.setHpr(*angles)
    
    @SerializedPropertyDecorator
    def rotation(self):
        return self.node.getQuat(self.root.node)
    @rotation.setter
    def rotation(self, quaternion):
        self.node.setQuat(self.root.node, *quaternion)

    @SerializedPropertyDecorator
    def local_rotation(self):
        return self.node.getQuat()
    @local_rotation.setter
    def local_rotation(self, quaternion):
        self.node.setQuat(*quaternion)

    @SerializedPropertyDecorator
    def local_scale(self):
        return self.node.getScale()
    @local_scale.setter
    def local_scale(self, scale):
        self.node.setScale(*scale)

    @SerializedPropertyDecorator
    def parent(self):
        p = self.node.getParent()
        if p.isEmpty() or p.getName() == "render":
            return self
        elif p.hasPythonTag("transform"):
            return p.getPythonTag("transform")
    @parent.setter
    def parent(self, parent):
        self.node.wrtReparentTo(parent.node)

    @SerializedPropertyDecorator
    def root(self):
        if self.parent is not self:
            return self.parent.root()
        else:
            return self
    
    def destroy(self):
        """Ultimately remove this transform. Warning: this might cause errors
        for other components on this game object. Use this only when removing
        the whole GameObject.
        """
        self.node.removeNode()

    def getChildren(self):
        """Return children as Transforms."""
        # this requires the __iter__() method
        return [c for c in self]

    def __iter__(self):
        """Iterate over children nodes and yield the transform instances."""
        for child in self.node.getChildren():
            if child.hasPythonTag("transform"):
                yield child.getPythonTag("transform")
    
    def __str__(self):
        r = "Transform for '{}'\n".format(self.name)
        r += "local position: {}\n".format(self.local_position)
        r += "local rotation: {}\n".format(self.local_euler_angles)
        r += "local scale:    {}\n".format(self.local_scale)
        return r
Exemple #32
0
class TQGraphicsNodePath:
    """ Anything that fundamentally is a only a graphics object in this engine should have these properties.

    Kwargs:
        TQGraphicsNodePath_creation_parent_node : this is assigned in the constructor, and after makeObject and the return of
        the p3d Nodepath, each TQGraphicsNodePath object has to call set_p3d_node """

    def __init__(self, **kwargs):
        """ """
        self.TQGraphicsNodePath_creation_parent_node = None
        self.p3d_nodepath = NodePath("empty")
        self.p3d_nodepath_changed_post_init_p = False
        self.p3d_parent_nodepath = NodePath("empty")

        self.node_p3d = None

        self.p3d_nodepath.reparentTo(self.p3d_parent_nodepath)

        self.apply_kwargs(**kwargs)

    def apply_kwargs(self, **kwargs):
        """ """
        if 'color' in kwargs:
            TQGraphicsNodePath.setColor(self, kwargs.get('color'))
        else:
            TQGraphicsNodePath.setColor(self, Vec4(1., 1., 1., 1.))

    def attach_to_render(self):
        """ """
        # assert self.p3d_nodepath
        # self.p3d_nodepath.reparentTo(render)
        assert self.p3d_nodepath
        self.reparentTo(engine.tq_graphics_basics.tq_render)

    def attach_to_aspect2d(self):
        """ """
        # assert self.p3d_nodepath
        # self.p3d_nodepath.reparentTo(aspect2d)
        assert self.p3d_nodepath
        self.reparentTo(engine.tq_graphics_basics.tq_aspect2d)

    def _set_p3d_nodepath_plain_post_init(p3d_nodepath):
        """ """
        self.p3d_nodepath = p3d_nodepath
        self.p3d_nodepath_changed_post_init_p = True

    @staticmethod
    def from_p3d_nodepath(p3d_nodepath, **tq_graphics_nodepath_kwargs):
        """ factory """
        go = TQGraphicsNodePath(**tq_graphics_nodepath_kwargs)
        go.set_p3d_nodepath(p3d_nodepath)
        return go

    def set_parent_node_for_nodepath_creation(
            self, TQGraphicsNodePath_creation_parent_node):
        """ when calling attachNewNode_p3d, a new node pat is generated.
        E.g.: To attach a line to render (3d world) is different than attaching
        it to aspect2d (2d GUI plane), since the aspect2d children are not directly
        affected by camera movements
        Args:
        - TQGraphicsNodePath_creation_parent_node : the NodePath to attach the TQGraphicsNodePath to
                                          (e.g. render or aspect2d in p3d)
        """

        # self.set_parent_node_for_nodepath_creation(self.TQGraphicsNodePath_creation_parent_node)
        self.TQGraphicsNodePath_creation_parent_node = TQGraphicsNodePath_creation_parent_node

    def set_p3d_nodepath(self, p3d_nodepath, remove_old_nodepath=True):
        """ """
        self.p3d_nodepath = p3d_nodepath

    def get_p3d_nodepath(self):
        """ """
        return self.p3d_nodepath

    def set_render_above_all(self, p):
        """ set render order to be such that it renders normally (false), or above all (true)
        Args:
            p: True or False to enable or disable the 'above all' rendering mode """

        try:
            if p == True:
                self.p3d_nodepath.setBin("fixed", 0)
                self.p3d_nodepath.setDepthTest(False)
                self.p3d_nodepath.setDepthWrite(False)
            else:
                self.p3d_nodepath.setBin("default", 0)
                self.p3d_nodepath.setDepthTest(True)
                self.p3d_nodepath.setDepthWrite(True)
        except NameError:       # if p3d_nodepath is not yet defined
            print("NameError in set_render_above_all()")

    def remove(self):
        """ """
        self.p3d_nodepath.removeNode()

    def setPos(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setPos(*args, **kwargs)

    def getPos(self):
        """ """
        return self.p3d_nodepath.getPos()

    def setScale(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setScale(*args, **kwargs)

    def getScale(self):
        """ """
        return self.p3d_nodepath.getScale()

    def setMat(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setMat(*args, **kwargs)

    def setMat_normal(self, mat4x4_normal_np):
        """ normal convention (numpy array), i.e. convert to forrowvecs convention for p3d setMat call """
        return self.p3d_nodepath.setMat(math_utils.to_forrowvecs(mat4x4_normal_np))


    def getMat(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getMat(*args, **kwargs)

    def getMat_normal(self, *args, **kwargs):
        """ """
        return math_utils.from_forrowvecs(self.p3d_nodepath.getMat(*args, **kwargs))

    def setTexture(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setTexture(*args, **kwargs)

    def setColor(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setColor(*args, **kwargs)

    def setTwoSided(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setTwoSided(*args, **kwargs)

    def setRenderModeWireframe(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setRenderModeWireframe(*args, **kwargs)

    def reparentTo(self, *args, **kwargs):
        """ """
        new_args = list(args)
        new_args[0] = new_args[0].p3d_nodepath
        return self.p3d_nodepath.reparentTo(*new_args, **kwargs)

    def reparentTo_p3d(self, *args, **kwargs):
        """ input a p3d nodepath directly """
        # new_args = list(args)
        # new_args[0] = new_args[0].p3d_nodepath
        return self.p3d_nodepath.reparentTo(*args, **kwargs)

    def get_node_p3d(self):
        """ """
        # return self.p3d_nodepath.node()
        return self.node_p3d

    def set_node_p3d(self, node_p3d):
        """ not available in p3d NodePath class """
        self.node_p3d = node_p3d

    def setRenderModeFilled(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setRenderModeFilled(*args, **kwargs)

    def setLightOff(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setLightOff(*args, **kwargs)

    def show(self):
        """ """
        return self.p3d_nodepath.show()

    def hide(self):
        """ """
        return self.p3d_nodepath.hide()

    def setRenderModeThickness(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setRenderModeThickness(*args, **kwargs)

    def removeNode(self):
        """ """
        return self.p3d_nodepath.removeNode()

    def setHpr(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setHpr(*args, **kwargs)

    def showBounds(self):
        """ """
        return self.p3d_nodepath.showBounds()

    def setCollideMask(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setCollideMask(*args, **kwargs)

    def getParent_p3d(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getParent(*args, **kwargs)

    def wrtReparentTo(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.wrtReparentTo(*args, **kwargs)

    def setBin(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setBin(*args, **kwargs)

    def setDepthTest(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setDepthTest(*args, **kwargs)

    def setDepthWrite(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setDepthWrite(*args, **kwargs)

    def get_children_p3d(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.get_children(*args, **kwargs)

    def attachNewNode_p3d(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.attachNewNode(*args, **kwargs)

    def lookAt(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.lookAt(*args, **kwargs)

    def setLight(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setLight(*args, **kwargs)

    def setAntialias(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setAntialias(*args, **kwargs)

    def getRelativeVector(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getRelativeVector(*args, **kwargs)

    def setTransparency(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setTransparency(*args, **kwargs)

    def getHpr(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getHpr(*args, **kwargs)

    def setHpr(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.setHpr(*args, **kwargs)

    def getTightBounds(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.getTightBounds(*args, **kwargs)

    def showTightBounds(self, *args, **kwargs):
        """ """
        return self.p3d_nodepath.showTightBounds(*args, **kwargs)