Beispiel #1
0
    def create_node(self):
        if self.model == "Grenade":
            m = Actor("grenade.egg")
            shell = m.find("**/shell")
            shell.setColor(1, 0.3, 0.3, 1)
            inner_top = m.find("**/inner_top")
            inner_bottom = m.find("**/inner_bottom")
            inner_top.setColor(0.4, 0.4, 0.4, 1)
            inner_bottom.setColor(0.4, 0.4, 0.4, 1)
            self.spin_bone = m.controlJoint(None, "modelRoot", "grenade_bone")
            m.set_scale(GRENADE_SCALE)

        elif self.model == "Missile":
            m = load_model("missile.egg")
            body = m.find("**/bodywings")
            body.set_color(0.3, 0.3, 1, 1)
            main_engines = m.find("**/mainengines")
            wing_engines = m.find("**/wingengines")
            main_engines.set_color(0.1, 0.1, 0.1, 1)
            wing_engines.set_color(0.1, 0.1, 0.1, 1)
            m.set_scale(MISSILE_SCALE)
        else:
            m = load_model("misc/rgbCube")
            m.set_scale(0.5)
            m.set_hpr(45, 45, 45)
        return m
Beispiel #2
0
    def create_node(self):
        if self.model == "Grenade":
            m = Actor('grenade.egg')
            shell = m.find('**/shell')
            shell.setColor(1,.3,.3,1)
            inner_top = m.find('**/inner_top')
            inner_bottom = m.find('**/inner_bottom')
            inner_top.setColor(.4,.4,.4,1)
            inner_bottom.setColor(.4,.4,.4,1)
            self.spin_bone = m.controlJoint(None, 'modelRoot', 'grenade_bone')
            m.set_scale(GRENADE_SCALE)

        elif self.model == "Missile":
            m = load_model('missile.egg')
            body = m.find('**/bodywings')
            body.set_color(.3,.3,1,1)
            main_engines = m.find('**/mainengines')
            wing_engines = m.find('**/wingengines')
            main_engines.set_color(.1,.1,.1,1)
            wing_engines.set_color(.1,.1,.1,1)
            m.set_scale(MISSILE_SCALE)
        else:
            m = load_model('misc/rgbCube')
            m.set_scale(.5)
            m.set_hpr(45,45,45)
        return m
Beispiel #3
0
    def create_node(self):
        if self.model == "Grenade":
            m = Actor('grenade.egg')
            shell = m.find('**/shell')
            shell.setColor(1, .3, .3, 1)
            inner_top = m.find('**/inner_top')
            inner_bottom = m.find('**/inner_bottom')
            inner_top.setColor(.4, .4, .4, 1)
            inner_bottom.setColor(.4, .4, .4, 1)
            self.spin_bone = m.controlJoint(None, 'modelRoot', 'grenade_bone')
            m.set_scale(GRENADE_SCALE)

        elif self.model == "Missile":
            m = load_model('missile.egg')
            body = m.find('**/bodywings')
            body.set_color(.3, .3, 1, 1)
            main_engines = m.find('**/mainengines')
            wing_engines = m.find('**/wingengines')
            main_engines.set_color(.1, .1, .1, 1)
            wing_engines.set_color(.1, .1, .1, 1)
            m.set_scale(MISSILE_SCALE)
        else:
            m = load_model('misc/rgbCube')
            m.set_scale(.5)
            m.set_hpr(45, 45, 45)
        return m
Beispiel #4
0
 def __init__(self):
     ShowBase.__init__(self)
     self.accept("escape", sys.exit)
     base.disableMouse()
     base.camera.set_pos(0, -10, 0)
     base.camera.look_at(0, 0, 0)
     a = Actor('box.egg')
     a.reparentTo(render)
     self.j_1 = a.controlJoint(None, 'modelRoot', 'Key1')
     self.j_2 = a.controlJoint(None, 'modelRoot', 'Key2')
     base.taskMgr.add(self.animate, "Shape Key Animation")
 def __init__(self):
     ShowBase.__init__(self)
     self.accept("escape", sys.exit)
     base.disableMouse()
     base.camera.set_pos(0, -10, 0)
     base.camera.look_at(0, 0, 0)
     a = Actor('box.egg')
     a.reparentTo(render)
     self.j_1 = a.controlJoint(None,'modelRoot' ,'Key1')
     self.j_2 = a.controlJoint(None,'modelRoot' ,'Key2')
     base.taskMgr.add(self.animate, "Shape Key Animation")
    def loadPlaneModel(self, modelname):
        """Loads models and animations from the planes directory."""
        animcontrols = {}
        model = loader.loadModel("planes/{0}/{0}".format(modelname))
        actor = Actor(model,
                      setFinal=True,
                      mergeLODBundles=True,
                      allowAsyncBind=False,
                      okMissing=False)
        #actor = Actor(model, lodNode="mid")

        subparts = (
            # subpart,       joints,                   animations
            ("Doors", ["Windscreen*", "Door*"], ("Open", "Close")),
            #("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", "LG In")),
            ("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", )),
            ("Ailerons", ["Aileron*"], ("Roll Left", "Roll Right")),
            ("Rudders", ["Rudder*"], ("Head Left", "Head Right")),
            ("Elevators", ["Elevator*"], ("Pitch Up", "Pitch Down")))

        for line in subparts:
            subpart, joints, anims = line
            actor.makeSubpart(subpart, joints)

            path = "planes/{0}/{0}-{{0}}".format(modelname)
            d = dict((anim, path.format(anim)) for anim in anims)

            #actor.loadAnims(d, subpart, "mid")
            actor.loadAnims(d, subpart)
            for anim in anims:
                #actor.bindAnim(anim, subpart, "mid")
                actor.bindAnim(anim, subpart)
                #animcontrols[anim] = actor.getAnimControls(anim, subpart,
                #                                           "mid", False)[0]
                animcontrols[anim] = actor.getAnimControls(
                    anim, subpart, None, False)[0]
        actor.makeSubpart("propellers", "Propeller*")
        actor.verifySubpartsComplete()
        actor.setSubpartsComplete(True)
        for p in actor.getJoints("propellers", "Propeller*", "lodRoot"):
            self.propellers.append(
                actor.controlJoint(None, "propellers", p.getName()))
        #actor.pprint()

        cams = model.findAllMatches("**/camera ?*")
        if not cams.isEmpty():
            cameras = actor.attachNewNode("cameras")
            cams.reparentTo(cameras)

        return actor, animcontrols
class CoreografiaSS(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()
        self.Ralph = Actor("models/ralph")
        self.Ralph.setScale(.5, .5, .5)
        self.Ralph.reparentTo(self.render)
        self.Ralph.setPos(0, 10, -1)
        self.Ralph.listJoints()

        #Mover Piesecillo Ralph
        self.PieRalphIzq = self.Ralph.controlJoint(None, 'modelRoot', 'LeftBall')

        self.BrazoRalphDrc = self.Ralph.controlJoint(None, 'modelRoot', 'RightShoulder')
        self.CodoRalphDrc = self.Ralph.controlJoint(None, 'modelRoot', 'RightElbow')
        

        self.PieIzqAbajo = self.PieRalphIzq.hprInterval(0.3, Point3(0, 0, 0))
        self.PieIzqArriba = self.PieRalphIzq.hprInterval(0.3, Point3(0, -20, 0))
        self.MoverPieIzq = Sequence(self.PieIzqArriba, self.PieIzqAbajo)
        self.MoverPieIzq.loop()
                            #BajarBrazo RotarMano
        self.BrazoRalphDrc.setHpr(10, 0, 10)
        self.CodoRalphDrc.setHpr(60, 170, 0)

        self.accept("q", self.moverDerecha)
        self.accept("e", self.moverIzquierda)
        self.accept("escape", sys.exit)


    def moverDerecha(self):
        x = self.Ralph.getH()
        self.Ralph.setHpr(x+10, 0, 0)

    def moverIzquierda(self):
        x = self.Ralph.getH()
        self.Ralph.setHpr(x-10, 0, 0)
    def loadPlaneModel(self, modelname):
        """Loads models and animations from the planes directory."""
        animcontrols = {}
        model = loader.loadModel("planes/{0}/{0}".format(modelname))
        actor = Actor(model, setFinal=True, mergeLODBundles=True,
                      allowAsyncBind=False, okMissing=False)
        #actor = Actor(model, lodNode="mid")

        subparts = (
        # subpart,       joints,                   animations
        ("Doors",        ["Windscreen*", "Door*"], ("Open", "Close")),
        #("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", "LG In")),
        ("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out",)),
        ("Ailerons",     ["Aileron*"],            ("Roll Left", "Roll Right")),
        ("Rudders",      ["Rudder*"],             ("Head Left", "Head Right")),
        ("Elevators",    ["Elevator*"],           ("Pitch Up", "Pitch Down"))
        )

        for line in subparts:
            subpart, joints, anims = line
            actor.makeSubpart(subpart, joints)

            path = "planes/{0}/{0}-{{0}}".format(modelname)
            d = dict((anim, path.format(anim)) for anim in anims)

            #actor.loadAnims(d, subpart, "mid")
            actor.loadAnims(d, subpart)
            for anim in anims:
                #actor.bindAnim(anim, subpart, "mid")
                actor.bindAnim(anim, subpart)
                #animcontrols[anim] = actor.getAnimControls(anim, subpart,
                #                                           "mid", False)[0]
                animcontrols[anim] = actor.getAnimControls(anim, subpart,
                                                               None, False)[0]
                
        actor.makeSubpart("propellers", "Propeller*")
        actor.verifySubpartsComplete()
        actor.setSubpartsComplete(True)
        for p in actor.getJoints("propellers", "Propeller*", "lodRoot"):
            self.propellers.append(actor.controlJoint(None, "propellers",
                                                                 p.getName()))
        #actor.pprint()

        cams = model.findAllMatches("**/camera ?*")
        if not cams.isEmpty():
            cameras = actor.attachNewNode("cameras")
            cams.reparentTo(cameras)

        return actor, animcontrols
Beispiel #9
0
class Player:
    def __init__(self, x, y, z, id):
        self.health = 100
        radius = .15
        height = 1
        shape = BulletCylinderShape(radius, height, ZUp)
        self.playerNode = BulletCharacterControllerNode(shape, 0.4, str(id))
        self.playerNode.setMaxJumpHeight(2.0)
        self.playerNode.setJumpSpeed(4.0)
        self.playerNP = base.render.attachNewNode(self.playerNode)
        self.playerNP.setPos(x, y, z)
        self.playerModel = Actor('models/soldier.egg', {"idle": "models/soldier_ani_idle.egg",
                                                        "walk": "models/soldier_ani_walk.egg",
                                                        "pistol": "models/soldier_ani_pistol.egg",
                                                        "death": "models/soldier_ani_death.egg",})

        self.playerModel.makeSubpart("legs", ["mixamorig:LeftUpLeg", "mixamorig:RightUpLeg"])
        self.playerModel.makeSubpart("hips", ["mixamorig:Hips"], ["mixamorig:LeftUpLeg", "mixamorig:RightUpLeg", "mixamorig:Spine"])
        self.playerModel.makeSubpart("upperBody", ["mixamorig:Spine"])
        self.playerModel.pose("idle", 0, partName="hips")

        self.playerModel.setH(90)
        self.playerModel.setScale(.06)
        self.playerModel.setZ(-.45)
        self.playerModel.flattenLight()
        # self.playerModel.setLightOff()self.playerSpine
        self.playerModel.reparentTo(self.playerNP)

        self.playerSpine = self.playerModel.controlJoint(None, 'modelRoot', 'mixamorig:Spine')
        self.hand = self.playerModel.exposeJoint(None, 'modelRoot', 'mixamorig:RightHand')
        self.spineExpose = self.playerModel.exposeJoint(None, 'modelRoot', 'mixamorig:Spine')
        self.playerSpine.setH(-7)

        # player weapon
        self.weapon = Ak47(self.hand)

        # player animation
        self.xSpeed = 0
        self.ySpeed = 0
        self.animation = Animation(self)

        self.model = NodePath("MySpineNode")

    def bendBody(self):
        self.model.setPos(self.spineExpose, 0, 0, 0)
        obj = RayCollider.getObjectHit()
        self.model.lookAt(obj)
        self.playerSpine.setP(self.model.getP())
Beispiel #10
0
class Effects(ShowBase):
    def __init__(self):
        #ShowBase.__init__(self)

        #################fulscreen###############
        root = Tkinter.Tk()
        w = root.winfo_screenwidth()
        h = root.winfo_screenheight()
        props = WindowProperties()
        props.setSize(w, h)
        base.win.requestProperties(props)
        #################end####################3

        #camera.setPos(-500,-80,0)
        base.enableParticles()
        self.txt = ""
        self.p = ParticleEffect()

        st_x = 5.0  ####-515,-60,0
        st_y = 8.0
        st_z = 0.0

        self.c2 = Actor(
            'Models/dancer/dancer'
        )  #Actor("Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve",{"run":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-run",	"jump":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-jump",	"offbalance":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-offbalance",	"tireroll":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-tireroll"})
        self.c2.setPos(offset_x + st_x, offset_y + st_y + 7, offset_z + st_z)
        self.c2.reparentTo(render)
        self.c2.loadAnims({'win': 'Models/dancer/dancer'})
        self.c2.loop('win')
        '''self.tex = Texture()
		self.tex.setMinfilter(Texture.FTLinear)
		base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture)
		
		self.backcam = base.makeCamera2d(base.win, sort=-10)
		self.background = NodePath("background")
		self.backcam.reparentTo(self.background)
		self.background.setDepthTest(0)
		self.background.setDepthWrite(0)
		self.backcam.node().getDisplayRegion(0).setClearDepthActive(0)
		
		#taskMgr.add(self.takeSnapShot, "takeSnapShot")
		
		self.bcard = base.win.getTextureCard()
		self.bcard.reparentTo(self.background)
		self.bcard.setTransparency(1)
		self.fcard = base.win.getTextureCard()
		self.fcard.reparentTo(render2d)
		self.fcard.setTransparency(1)
		
		base.setBackgroundColor(0,0,0,1)
		self.bcard.hide()
		self.fcard.show()
		self.fcard.setColor(1.0,1.0,1.0,0.99)
		self.fcard.setScale(1.00)
		self.fcard.setPos(0,0,0)
		self.fcard.setR(0)
		self.clickrate = 30
		self.nextclick = 0'''

        self.c4 = Actor('Models/dancer/dancer')
        #self.c2.loadModel('Models/dancer/dancer')
        self.c4.setPos(offset_x - st_x, offset_y + st_y + 7, offset_z + st_z)
        self.c4.reparentTo(render)
        self.c4.loadAnims({'win': 'Models/dancer/dancer'})
        self.c4.loop('win')

        #self.c2.setR(-90)

        #self.c2.loop('tireroll')
        #base.setSleep(0.5)
        self.c3 = Actor(
            "Models/cat-humans/bvw-f2004--ralph-egg/bvw-f2004--ralph/ralph")
        self.c3.setScale(2)
        self.c3.setPos(offset_x + 0, offset_y + 20, offset_z + (-1))
        self.c3.reparentTo(render)
        self.c3.listJoints()
        #self.c4.listJoints()
        self.actorRh = self.c3.controlJoint(None, 'modelRoot', 'RightShoulder')
        self.actorLh = self.c3.controlJoint(None, 'modelRoot', 'LeftShoulder')
        self.actorNeck = self.c3.controlJoint(None, 'modelRoot', 'Neck')

        self.actorNeck1 = self.c3.controlJoint(None, 'modelRoot', 'Neck')

        #self.actorNeck.hprInterval(3,Point3(0,90,0)).loop()
        self.actorLh.hprInterval(3, Point3(90, 0, 0)).loop()
        self.actorRh.hprInterval(3, Point3(0, 0, -180)).loop()
        #self.actorRh.hprInterval(3,Point3(0,90,0)).loop()
        self.actorRh.setHpr(180, 180, -60)  # For Both hands upward
        self.actorLh.setHpr(90, -90, 120)

        self.loadchar('', '')
        self.duckPlane = loader.loadModel('Models/plane/plane')
        self.duckPlane.setPos(offset_x - 2, offset_y + 8,
                              offset_z + 10)  #set its position
        self.duckPlane.reparentTo(render)  #reparent to render
        self.duckPlane.setTransparency(1)
        self.duckTexs = self.loadTextureMovie(24,
                                              'duck/duck_fly_left',
                                              'png',
                                              padding=2)
        self.duckTask = taskMgr.add(self.textureMovie, "duckTask")
        self.duckTask.fps = 36
        self.duckTask.obj = self.duckPlane
        self.duckTask.textures = self.duckTexs
        self.duckPlane.node().setEffect(BillboardEffect.makePointEye())

        self.expPlane = loader.loadModel(
            'Models/plane/plane')  #load the object
        self.expPlane.setScale(18, 10, 10)
        self.expPlane.setPos(offset_x + 0, offset_y + 22,
                             offset_z + 4)  #set the position
        self.expPlane.reparentTo(render)  #reparent to render
        self.expPlane.setTransparency(1)  #enable transparency

        self.expTexs = self.loadTextureMovie(50,
                                             'explosion/def',
                                             'png',
                                             padding=4)
        #create the animation task
        self.expTask = taskMgr.add(self.textureMovie, "movieTask")
        self.expTask.fps = 30  #set framerate
        self.expTask.obj = self.expPlane  #set object
        self.expTask.textures = self.expTexs  #set texture list
        #self.expPlane.node().setEffect(BillboardEffect.makePointEye())

        self.c1 = loader.loadModel("Models/Dynamite/Dynamite")
        self.c1.setPos(offset_x - 6, offset_y + 10, offset_z + 2)
        self.c1.reparentTo(render)

        self.expPlane1 = loader.loadModel(
            'Models/plane/plane')  #load the object
        #self.expPlane1.setScale(1,10,10)
        self.expPlane1.setPos(offset_x - 8, offset_y + 10,
                              offset_z + 3)  #set the position
        self.expPlane1.reparentTo(render)  #reparent to render
        self.expPlane1.setTransparency(1)

        self.expTexs1 = self.loadTextureMovie(50,
                                              'explosion1/explosion',
                                              'png',
                                              padding=4)
        #create the animation task
        self.expTask1 = taskMgr.add(self.textureExplosion, "explosionTask")
        self.expTask1.fps = 30  #set framerate
        self.expTask1.obj = self.expPlane1  #set object
        self.expTask1.textures = self.expTexs1  #set texture list
        self.expPlane1.node().setEffect(BillboardEffect.makePointEye())

        self.orientPlane = loader.loadModel(
            'Models/plane/plane')  #Load the object
        #self.orientPlane.setScale(1)
        self.orientTex = loader.loadTexture("Models/plane/textures/carpet.jpg")
        self.orientPlane.setTexture(self.orientTex, 1)  #Set the texture
        self.orientPlane.reparentTo(render)  #Parent to render
        #Set the position, orientation, and scale
        self.orientPlane.setPosHprScale(offset_x + 0, offset_y + 18, offset_z,
                                        0, -90, 0, 20, 20, 20)

    def textureMovie(self, task):
        currentFrame = int(task.time * task.fps)
        task.obj.setTexture(task.textures[currentFrame % len(task.textures)],
                            1)
        return Task.cont

    def textureExplosion(self, task):
        currentFrame = int(task.time * task.fps)
        #print "curr  "
        #print currentFrame%51
        if ((currentFrame % len(task.textures)) > 10):
            self.c1.hide()
        elif ((currentFrame % len(task.textures)) <= 0):
            self.c1.show()
        task.obj.setTexture(task.textures[currentFrame % len(task.textures)],
                            1)
        return Task.cont

    def takeSnapShot(self, task):
        if (task.time > self.nextclick):
            self.nextclick += 1.0 / self.clickrate
            if (self.nextclick < task.time):
                self.nextclick = task.time
            base.win.triggerCopy()
        return Task.cont

    def loadTextureMovie(self, frames, name, suffix, padding=1):
        return [
            loader.loadTexture(
                (name + "%0" + str(padding) + "d." + suffix) % i)
            for i in range(frames)
        ]

    def loadchar(self, main_char, txt):
        self.txt = txt
        if (txt == ''):
            self.t = loader.loadModel("Models/DJTable/DJTable")
            self.t.setPos(offset_x + 0, offset_y + 20, offset_z)
            self.t.setH(180)
            self.t.reparentTo(render)
            self.setupLights()
            self.loadParticleConfig('fountain2.ptf')
        else:
            self.t = main_char  #loader.loadModel("Models/cat-vehicles-road/bvw-f2004--girlscar-egg/bvw-f2004--girlscar/girlcar")#loader.loadModel("Models/cat-vehicles-road/bvw-f2004--carnsx-egg/bvw-f2004--carnsx/carnsx")
            #self.t.setPos(0,20,0)
            #self.t.reparentTo(render)
            self.setupLights()
            self.loadParticleConfig('steam.ptf')

    def loadParticleConfig(self, file):
        #Start of the code from steam.ptf
        self.p.cleanup()
        self.p = ParticleEffect()
        if (self.txt == ''):
            self.txt = ''
            self.p.loadConfig(Filename(file))
            self.p.setPos(0.000, 0, 2.500)
        elif (self.txt == 'blue'):
            self.txt = ''
            self.p.loadConfig(Filename('steam_front.ptf'))
            self.p.setPos(0.000, -1.8, -0.800)

        elif (self.txt == 'red'):
            self.txt = ''
            self.p.loadConfig(Filename(file))
            self.p.setPos(0.000, 1.800, 0.250)
        self.p.start(self.t)

    def setupLights(self):
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.4, .4, .35, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 8, -2.5))
        directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1))

        self.t.setLight(self.t.attachNewNode(directionalLight))
        self.t.setLight(self.t.attachNewNode(ambientLight))


#w = Effects()
#run()
Beispiel #11
0
class ActorParcial(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()

        # Instrucciones en pantalla
        self.Salir = addInstructions(.06, "[ESC]: Para Salir")
        self.Camara = addInstructions(.12,
                                      "[Q,E,A,D,W,S]: Para Controlar Camara")
        self.CabezaL = addInstructions(.18, "[G]: Para Mover Cabeza")
        self.CaderaL = addInstructions(.18, "[G]: Para Mover Cadera")

        # Cargar el Actor con sus animaciones
        self.Ralph = Actor("models/ralph")
        self.Ralph.setScale(.5, .5, .5)
        self.Ralph.setPos(
            0, 10,
            -1)  #(x   -IZQ  +DER   ,y   PROFUNDIDAD  ,z   +ARRIBA -ABAJO   )
        self.Ralph.reparentTo(self.render)

        # Declaración de partes del cuerpo
        self.Cabeza = self.Ralph.controlJoint(None, 'modelRoot', 'Neck')
        self.CaderaDerecha = self.Ralph.controlJoint(None, 'modelRoot',
                                                     'RightHip')
        self.CaderaIzquierda = self.Ralph.controlJoint(None, 'modelRoot',
                                                       'LeftHip')

        # Movimiento de Cabeza
        self.CabezaAbajo = self.Cabeza.hprInterval(0.5, Point3(0, 0, 0))
        self.CabezaArriba = self.Cabeza.hprInterval(0.5, Point3(20, 0, 0))

        # Movimientos de cadera derecha
        self.CaderaDerechaDerecha = self.CaderaDerecha.hprInterval(
            0.5, Point3(4.9762, 0, 120))
        self.CaderaDerechaNormal = self.CaderaDerecha.hprInterval(
            0.5, Point3(4.9762, 0, 90))

        # Movimientos de cadera izquierda
        self.CaderaIzquierdaIzquierda = self.CaderaIzquierda.hprInterval(
            0.5, Point3(5.02118, -0.862563, 62.9857))
        self.CaderaIzquierdaNormal = self.CaderaIzquierda.hprInterval(
            0.5, Point3(5.02118, -0.862563, 92.9857))

        # Secuencias de movimientos
        self.MoverCabeza = Sequence(self.CabezaArriba, self.CabezaAbajo)
        self.MoverCaderaDerechaIzquierda = Sequence(
            self.CaderaDerechaDerecha, self.CaderaDerechaNormal,
            self.CaderaIzquierdaIzquierda, self.CaderaIzquierdaNormal)

        # Eventos de los botones
        self.accept("escape", sys.exit)
        self.accept("q", self.camLeft)
        self.accept("e", self.camRight)
        self.accept("a", self.camIn)
        self.accept("d", self.camOut)
        self.accept("w", self.camUp)
        self.accept("s", self.camDown)
        self.accept("g", self.eventCabeza)
        self.accept("h", self.eventCadera)

    def eventCabeza(self):
        self.MoverCabeza.loop()

    def eventCadera(self):
        self.MoverCaderaDerechaIzquierda.loop()

    def camLeft(self):
        x = self.camera.getX()
        self.camera.setX(x - 2)

    def camRight(self):
        x = self.camera.getX()
        self.camera.setX(x + 2)

    def camUp(self):
        y = self.camera.getY()
        self.camera.setY(y + 2)

    def camDown(self):
        y = self.camera.getY()
        self.camera.setY(y - 2)

    def camIn(self):
        z = self.camera.getZ()
        self.camera.setZ(z + 2)

    def camOut(self):
        z = self.camera.getZ()
        self.camera.setZ(z - 2)
Beispiel #12
0
class Effects(ShowBase):
	def __init__(self):
		#ShowBase.__init__(self)
		
		#################fulscreen###############
		root = Tkinter.Tk()
		w = root.winfo_screenwidth()
		h = root.winfo_screenheight()
		props = WindowProperties() 
		props.setSize(w, h) 
		base.win.requestProperties(props)
		#################end####################3
		
		
		#camera.setPos(-500,-80,0)
		base.enableParticles()
		self.txt = ""
		self.p = ParticleEffect()
		
		st_x = 5.0 ####-515,-60,0
		st_y = 8.0
		st_z = 0.0
		
		
		self.c2 = Actor('Models/dancer/dancer')#Actor("Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve",{"run":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-run",	"jump":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-jump",	"offbalance":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-offbalance",	"tireroll":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-tireroll"})
		self.c2.setPos(offset_x+st_x,offset_y+st_y+7,offset_z+st_z)
		self.c2.reparentTo(render)
		self.c2.loadAnims({'win':'Models/dancer/dancer'})
		self.c2.loop('win')
		
		'''self.tex = Texture()
		self.tex.setMinfilter(Texture.FTLinear)
		base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture)
		
		self.backcam = base.makeCamera2d(base.win, sort=-10)
		self.background = NodePath("background")
		self.backcam.reparentTo(self.background)
		self.background.setDepthTest(0)
		self.background.setDepthWrite(0)
		self.backcam.node().getDisplayRegion(0).setClearDepthActive(0)
		
		#taskMgr.add(self.takeSnapShot, "takeSnapShot")
		
		self.bcard = base.win.getTextureCard()
		self.bcard.reparentTo(self.background)
		self.bcard.setTransparency(1)
		self.fcard = base.win.getTextureCard()
		self.fcard.reparentTo(render2d)
		self.fcard.setTransparency(1)
		
		base.setBackgroundColor(0,0,0,1)
		self.bcard.hide()
		self.fcard.show()
		self.fcard.setColor(1.0,1.0,1.0,0.99)
		self.fcard.setScale(1.00)
		self.fcard.setPos(0,0,0)
		self.fcard.setR(0)
		self.clickrate = 30
		self.nextclick = 0'''
		
		self.c4 = Actor('Models/dancer/dancer')
		#self.c2.loadModel('Models/dancer/dancer')
		self.c4.setPos(offset_x-st_x,offset_y+st_y+7,offset_z+st_z)
		self.c4.reparentTo(render)
		self.c4.loadAnims({'win':'Models/dancer/dancer'})
		self.c4.loop('win')
		
		#self.c2.setR(-90)
		
		#self.c2.loop('tireroll')
		#base.setSleep(0.5)
		self.c3 = Actor("Models/cat-humans/bvw-f2004--ralph-egg/bvw-f2004--ralph/ralph")
		self.c3.setScale(2)
		self.c3.setPos(offset_x+0,offset_y+20,offset_z+(-1))
		self.c3.reparentTo(render)
		self.c3.listJoints()
		#self.c4.listJoints()
		self.actorRh = self.c3.controlJoint(None, 'modelRoot', 'RightShoulder')
		self.actorLh = self.c3.controlJoint(None, 'modelRoot', 'LeftShoulder')
		self.actorNeck = self.c3.controlJoint(None, 'modelRoot', 'Neck')
		
		self.actorNeck1 = self.c3.controlJoint(None, 'modelRoot', 'Neck')
		
		#self.actorNeck.hprInterval(3,Point3(0,90,0)).loop()
		self.actorLh.hprInterval(3,Point3(90,0,0)).loop()
		self.actorRh.hprInterval(3,Point3(0,0,-180)).loop()
		#self.actorRh.hprInterval(3,Point3(0,90,0)).loop()
		self.actorRh.setHpr(180,180,-60) # For Both hands upward
		self.actorLh.setHpr(90,-90,120)
		
		
		self.loadchar('','')
		self.duckPlane = loader.loadModel('Models/plane/plane')
		self.duckPlane.setPos(offset_x-2, offset_y+8, offset_z+10)         #set its position
		self.duckPlane.reparentTo(render)       #reparent to render
		self.duckPlane.setTransparency(1)
		self.duckTexs = self.loadTextureMovie(24, 'duck/duck_fly_left',
                                          'png', padding = 2)
		self.duckTask = taskMgr.add(self.textureMovie, "duckTask")
		self.duckTask.fps = 36
		self.duckTask.obj = self.duckPlane  
		self.duckTask.textures = self.duckTexs
		self.duckPlane.node().setEffect(BillboardEffect.makePointEye())
		
		self.expPlane = loader.loadModel('Models/plane/plane')  #load the object
		self.expPlane.setScale(18,10,10)
		self.expPlane.setPos(offset_x+0, offset_y+22, offset_z+4)                         #set the position
		self.expPlane.reparentTo(render)                      #reparent to render
		self.expPlane.setTransparency(1)                      #enable transparency

		self.expTexs = self.loadTextureMovie(50, 'explosion/def','png', padding = 4)
    #create the animation task
		self.expTask = taskMgr.add(self.textureMovie, "movieTask")
		self.expTask.fps = 30                                 #set framerate
		self.expTask.obj = self.expPlane                      #set object
		self.expTask.textures = self.expTexs                  #set texture list
		#self.expPlane.node().setEffect(BillboardEffect.makePointEye())
		
		
		self.c1 = loader.loadModel("Models/Dynamite/Dynamite")
		self.c1.setPos(offset_x-6,offset_y+10,offset_z+2)
		self.c1.reparentTo(render)
		
		self.expPlane1 = loader.loadModel('Models/plane/plane')  #load the object
		#self.expPlane1.setScale(1,10,10)
		self.expPlane1.setPos(offset_x-8, offset_y+10, offset_z+3)                         #set the position
		self.expPlane1.reparentTo(render)                      #reparent to render
		self.expPlane1.setTransparency(1)
		
		self.expTexs1 = self.loadTextureMovie(50, 'explosion1/explosion','png', padding = 4)
    #create the animation task
		self.expTask1 = taskMgr.add(self.textureExplosion, "explosionTask")
		self.expTask1.fps = 30                                 #set framerate
		self.expTask1.obj = self.expPlane1                      #set object
		self.expTask1.textures = self.expTexs1                  #set texture list
		self.expPlane1.node().setEffect(BillboardEffect.makePointEye())
		
		self.orientPlane = loader.loadModel('Models/plane/plane') #Load the object
		#self.orientPlane.setScale(1)
		self.orientTex = loader.loadTexture("Models/plane/textures/carpet.jpg")
		self.orientPlane.setTexture(self.orientTex, 1)        #Set the texture
		self.orientPlane.reparentTo(render)		#Parent to render
    #Set the position, orientation, and scale
		self.orientPlane.setPosHprScale(offset_x+0, offset_y+18, offset_z, 0, -90, 0, 20, 20, 20)

	def textureMovie(self, task):
		currentFrame = int(task.time * task.fps)
		task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1)
		return Task.cont
	def textureExplosion(self, task):
		currentFrame = int(task.time * task.fps)
		#print "curr  "
		#print currentFrame%51
		if((currentFrame%len(task.textures)) > 10):
			self.c1.hide()
		elif((currentFrame%len(task.textures)) <= 0):
			self.c1.show()
		task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1)
		return Task.cont
	def takeSnapShot(self, task):
		if (task.time > self.nextclick):
			self.nextclick += 1.0 / self.clickrate
			if (self.nextclick < task.time):
				self.nextclick = task.time
			base.win.triggerCopy()
		return Task.cont
	def loadTextureMovie(self, frames, name, suffix, padding = 1):
		return [loader.loadTexture((name+"%0"+str(padding)+"d."+suffix) % i) 
        for i in range(frames)]
	def loadchar(self,main_char,txt):
		self.txt = txt
		if(txt == ''):
			self.t = loader.loadModel("Models/DJTable/DJTable")
			self.t.setPos(offset_x+0,offset_y+20,offset_z)
			self.t.setH(180)
			self.t.reparentTo(render)
			self.setupLights()
			self.loadParticleConfig('fountain2.ptf')
		else:
			self.t = main_char#loader.loadModel("Models/cat-vehicles-road/bvw-f2004--girlscar-egg/bvw-f2004--girlscar/girlcar")#loader.loadModel("Models/cat-vehicles-road/bvw-f2004--carnsx-egg/bvw-f2004--carnsx/carnsx")
			#self.t.setPos(0,20,0)
			#self.t.reparentTo(render)
			self.setupLights()
			self.loadParticleConfig('steam.ptf')
	def loadParticleConfig(self, file):
        #Start of the code from steam.ptf
		self.p.cleanup()
		self.p = ParticleEffect()
		if(self.txt == ''):
			self.txt = ''
			self.p.loadConfig(Filename(file))
			self.p.setPos(0.000, 0, 2.500)  
		elif(self.txt == 'blue'):
			self.txt = ''
			self.p.loadConfig(Filename('steam_front.ptf'))        
			self.p.setPos(0.000, -1.8, -0.800)
			
		elif(self.txt == 'red'):
			self.txt = ''
			self.p.loadConfig(Filename(file))
			self.p.setPos(0.000, 1.800, 0.250)
		self.p.start(self.t)
	def setupLights(self):
		ambientLight = AmbientLight("ambientLight")
		ambientLight.setColor(Vec4(.4, .4, .35, 1))
		directionalLight = DirectionalLight("directionalLight")
		directionalLight.setDirection(Vec3( 0, 8, -2.5 ) )
		directionalLight.setColor(Vec4( 0.9, 0.8, 0.9, 1 ) )
		
		self.t.setLight(self.t.attachNewNode(directionalLight))
		self.t.setLight(self.t.attachNewNode(ambientLight)) 
#w = Effects()
#run()
Beispiel #13
0
class Walker (PhysicalObject):

    collide_bits = SOLID_COLLIDE_BIT

    def __init__(self, incarnator, colordict=None, player=False):
        super(Walker, self).__init__()
        self.spawn_point = incarnator
        self.on_ground = False
        self.mass = 150.0 # 220.0 for heavy
        self.xz_velocity = Vec3(0, 0, 0)
        self.y_velocity = Vec3(0, 0, 0)
        self.factors = {
            'forward': 7.5,
            'backward': -7.5,
            'left': 2.0,
            'right': -2.0,
            'crouch': 0.0,
        }
        self.movement = {
            'forward': 0.0,
            'backward': 0.0,
            'left': 0.0,
            'right': 0.0,
            'crouch': 0.0,
        }
        self.head_height = Vec3(0, 1.5, 0)
        self.collides_with = MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT
        self.grenade_loaded = False
        self.energy = 1.0
        self.left_gun_charge = 1.0
        self.right_gun_charge = 1.0
        self.primary_color = [1,1,1,1]
        self.colordict = colordict if colordict else None
        self.crouching = False
        self.player = player
        self.can_jump = False
        self.crouch_impulse = 0

    def get_model_part(self, obj_name):
        return self.actor.find("**/%s" % obj_name)

    def create_node(self):
        self.actor = Actor('walker.egg')
        if self.colordict:
            self.setup_color(self.colordict)
        self.actor.set_pos(*self.spawn_point.pos)
        self.actor.look_at(*self.spawn_point.heading)
        self.spawn_point.was_used()


        self.left_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'left_barrel_bone')
        self.right_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'right_barrel_bone')

        return self.actor

    def create_solid(self):
        walker_capsule = BulletGhostNode(self.name + "_walker_cap")
        self.walker_capsule_shape = BulletCylinderShape(.7, .2, YUp)
        walker_bullet_np = self.actor.attach_new_node(walker_capsule)
        walker_bullet_np.node().add_shape(self.walker_capsule_shape)
        walker_bullet_np.node().set_kinematic(True)
        walker_bullet_np.set_pos(0,1.5,0)
        walker_bullet_np.wrt_reparent_to(self.actor)
        self.world.physics.attach_ghost(walker_capsule)
        walker_bullet_np.node().setIntoCollideMask(GHOST_COLLIDE_BIT)
        return None

    def setup_shape(self, gnodepath, bone, pname):
        shape = BulletConvexHullShape()

        gnode = gnodepath.node()
        geom = gnode.get_geom(0)
        shape.add_geom(geom)

        node = BulletRigidBodyNode(self.name + pname)
        np = self.actor.attach_new_node(node)
        np.node().add_shape(shape)
        np.node().set_kinematic(True)
        np.wrt_reparent_to(bone)
        self.world.physics.attach_rigid_body(node)
        return np

    def setup_color(self, colordict):
        if colordict.has_key('barrel_color'):
            color = colordict['barrel_color']
            self.get_model_part('left_barrel').setColor(*color)
            self.get_model_part('right_barrel').setColor(*color)
        if colordict.has_key('visor_color'):
            self.get_model_part('visor').setColor(*colordict['visor_color'])
        if colordict.has_key('body_primary_color'):
            color = colordict['body_primary_color']
            self.primary_color = color
            for part in ['hull_primary', 'rt_leg_primary',
                         'lt_leg_primary', 'lb_leg_primary', 'rb_leg_primary',
                         'left_barrel_ring', 'right_barrel_ring', 'hull_bottom']:
                self.get_model_part(part).setColor(*color)
        if colordict.has_key('body_secondary_color'):
            color = colordict['body_secondary_color']
            for part in ['hull_secondary', 'visor_stripe', 'rb_leg_secondary',
                         'rt_leg_secondary', 'lb_leg_secondary', 'lt_leg_secondary']:
                self.get_model_part(part).setColor(*color)
        return

    def attached(self):
        self.integrator = Integrator(self.world.gravity)
        #self.world.register_collider(self)
        self.world.register_updater(self)

        pelvis_bone = self.actor.controlJoint(None, 'modelRoot', 'pelvis_bone')

        left_foot_bone = self.actor.exposeJoint(None, 'modelRoot', 'left_foot_bone')
        left_foot_bone_origin_ref = self.actor.attach_new_node("left_foot_reference")
        left_foot_bone_origin_ref.set_pos(left_foot_bone.get_pos())
        #pelvis_bone.attach_new_node(left_foot_bone_origin_ref)

        right_foot_bone = self.actor.exposeJoint(None, 'modelRoot', 'right_foot_bone')
        right_foot_bone_origin_ref = self.actor.attach_new_node("right_foot_reference")
        right_foot_bone_origin_ref.set_pos(right_foot_bone.get_pos())
        #pelvis_bone.attach_new_node(right_foot_bone_origin_ref)

        left_bones = LegBones(
            self.world.scene, self.world.physics,
            self.actor.exposeJoint(None, 'modelRoot', 'left_hip_bone'),
            left_foot_bone,
            left_foot_bone_origin_ref,
            *[self.actor.controlJoint(None, 'modelRoot', name) for name in ['left_top_bone', 'left_bottom_bone']]
        )
        right_bones = LegBones(
            self.world.scene, self.world.physics,
            self.actor.exposeJoint(None, 'modelRoot', 'right_hip_bone'),
            right_foot_bone,
            right_foot_bone_origin_ref,
            *[self.actor.controlJoint(None, 'modelRoot', name) for name in  ['right_top_bone', 'right_bottom_bone']]
        )

        self.skeleton = Skeleton(left_bones, right_bones, pelvis_bone)
        self.skeleton.setup_footsteps(self.world.audio3d)
        self.head_bone = self.actor.controlJoint(None, 'modelRoot', 'head_bone')
        self.head_bone_joint = self.actor.exposeJoint(None, 'modelRoot', 'head_bone')
        self.loaded_missile = LoadedMissile(self.head_bone_joint, self.primary_color)
        self.loaded_grenade = LoadedGrenade(self.head_bone_joint, self.primary_color)
        if self.player:
            self.sights = Sights(self.left_barrel_joint, self.right_barrel_joint, self.world)



    def collision(self, other, manifold, first):
        world_pt = manifold.get_position_world_on_a() if first else manifold.get_position_world_on_b()
        print self, 'HIT BY', other, 'AT', world_pt

    def handle_command(self, cmd, pressed):
        if cmd is 'crouch' and pressed:
            self.crouching = True
            if self.on_ground:
                self.can_jump = True
        if cmd is 'crouch' and not pressed and self.on_ground and self.can_jump:
            self.crouching = False
            self.y_velocity = Vec3(0, 6.8, 0)
            self.can_jump = False
        if cmd is 'fire' and pressed:
            self.handle_fire()
            return
        if cmd is 'missile' and pressed:
            if self.loaded_grenade.can_fire():
                self.loaded_grenade.toggle_visibility()
            self.loaded_missile.toggle_visibility()
            return
        if cmd is 'grenade' and pressed:
            if self.loaded_missile.can_fire():
                self.loaded_missile.toggle_visibility()
            self.loaded_grenade.toggle_visibility()
            return
        if cmd is 'grenade_fire' and pressed:
            if self.loaded_missile.can_fire():
                self.loaded_missile.toggle_visibility()
            if not self.loaded_grenade.can_fire():
                self.loaded_grenade.toggle_visibility()
            walker_v = Vec3(self.xz_velocity)
            walker_v.y = self.y_velocity.y
            self.loaded_grenade.fire(self.world, walker_v)
            return
        self.movement[cmd] = self.factors[cmd] if pressed else 0.0

    def handle_fire(self):
        if self.loaded_missile.can_fire():
            self.loaded_missile.fire(self.world)
        elif self.loaded_grenade.can_fire():
            walker_v = self.xz_velocity
            walker_v.y = self.y_velocity.y
            self.loaded_grenade.fire(self.world, walker_v)
        else:
            p_energy = 0
            hpr = 0
            if self.left_gun_charge > self.right_gun_charge:
                origin = self.left_barrel_joint.get_pos(self.world.scene)
                hpr = self.left_barrel_joint.get_hpr(self.world.scene)
                p_energy = self.left_gun_charge
                if p_energy < MIN_PLASMA_CHARGE:
                    return
                self.left_gun_charge = 0
            else:
                origin = self.right_barrel_joint.get_pos(self.world.scene)
                hpr = self.right_barrel_joint.get_hpr(self.world.scene)
                p_energy = self.right_gun_charge
                if p_energy < MIN_PLASMA_CHARGE:
                    return
                self.right_gun_charge = 0
            hpr.y += 180
            plasma = self.world.attach(Plasma(origin, hpr, p_energy))

    def st_result(self, cur_pos, new_pos):
        return self.world.physics.sweepTestClosest(self.walker_capsule_shape, cur_pos, new_pos, self.collides_with, 0)

    def update(self, dt):
        dt = min(dt, 0.2) # let's just temporarily assume that if we're getting less than 5 fps, dt must be wrong.
        yaw = self.movement['left'] + self.movement['right']
        self.rotate_by(yaw * dt * 60, 0, 0)
        walk = self.movement['forward'] + self.movement['backward']
        start = self.position()
        cur_pos_ts = TransformState.make_pos(self.position() + self.head_height)

        if self.on_ground:
            friction = DEFAULT_FRICTION
        else:
            friction = AIR_FRICTION

        #to debug walk cycle (stay in place)
        #riction = 0

        speed = walk
        pos = self.position()
        self.move_by(0, 0, speed)
        direction = self.position() - pos
        newpos, self.xz_velocity = Friction(direction, friction).integrate(pos, self.xz_velocity, dt)
        self.move(newpos)

        # Cast a ray from just above our feet to just below them, see if anything hits.
        pt_from = self.position() + Vec3(0, 1, 0)
        pt_to = pt_from + Vec3(0, -1.1, 0)
        result = self.world.physics.ray_test_closest(pt_from, pt_to, MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT)

        # this should return 'on ground' information
        self.skeleton.update_legs(walk, dt, self.world.scene, self.world.physics)

        if self.y_velocity.get_y() <= 0 and result.has_hit():
            self.on_ground = True
            self.crouch_impulse = self.y_velocity.y
            self.y_velocity = Vec3(0, 0, 0)
            self.move(result.get_hit_pos())
            self.skeleton.left_leg_on_ground = True
            self.skeleton.right_leg_on_ground = True
        else:
            self.on_ground = False
            current_y = Point3(0, self.position().get_y(), 0)
            y, self.y_velocity = self.integrator.integrate(current_y, self.y_velocity, dt)
            self.move(self.position() + (y - current_y))

        if self.crouching and self.skeleton.crouch_factor < 1:
            self.skeleton.crouch_factor += (dt*60)/10
            self.skeleton.update_legs(0, dt, self.world.scene, self.world.physics)
        elif not self.crouching and self.skeleton.crouch_factor > 0:
            self.skeleton.crouch_factor -= (dt*60)/10
            self.skeleton.update_legs(0, dt, self.world.scene, self.world.physics)

        #if self.crouch_impulse < 0:

        goal = self.position()
        adj_dist = abs((start - goal).length())
        new_pos_ts = TransformState.make_pos(self.position() + self.head_height)

        sweep_result = self.st_result(cur_pos_ts, new_pos_ts)
        count = 0
        while sweep_result.has_hit() and count < 10:
            moveby = sweep_result.get_hit_normal()
            self.xz_velocity = -self.xz_velocity.cross(moveby).cross(moveby)
            moveby.normalize()
            moveby *= adj_dist * (1 - sweep_result.get_hit_fraction())
            self.move(self.position() + moveby)
            new_pos_ts = TransformState.make_pos(self.position() + self.head_height)
            sweep_result = self.st_result(cur_pos_ts, new_pos_ts)
            count += 1

        if self.energy > WALKER_MIN_CHARGE_ENERGY:
            if self.left_gun_charge < 1:
                self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0]
                self.left_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1]
            else:
                self.left_gun_charge = math.floor(self.left_gun_charge)

            if self.right_gun_charge < 1:
                self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0]
                self.right_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1]
            else:
                self.right_gun_charge = math.floor(self.right_gun_charge)

        if self.energy < 1:
            self.energy += WALKER_RECHARGE_FACTOR * (dt)

        if self.player:
            self.sights.update(self.left_barrel_joint, self.right_barrel_joint)
Beispiel #14
0
class World(DirectObject):
  def __init__(self):
    #This code puts the standard title and instruction text on screen
    self.title = OnscreenText(text="",
                              style=1, fg=(1,1,1,1),
                              pos=(0.7,-0.95), scale = .07)
    self.onekeyText   = genLabelText("ESC: Quit", 0)
    self.onekeyText   = genLabelText("[1]: Calibrate", 1)
      
    #setup key input
    self.accept('escape', sys.exit)
    self.accept('1', self.calibrate)

    base.disableMouse()                  #Disable mouse-based camera-control
    camera.setPos(0,-15, 2)              #Position the cameraffff

    self.eve = Actor("models/ralph") #Load our animated charachter
    self.eve.reparentTo(render)          #Put it in the scene

    #Now we use controlJoint to get a NodePath that's in control of her neck
    #This must be done before any animations are played

    self.joints = dict()    # mapping from names to NodePath objects
    self.modelQ = dict()    # mapping from names to default joint orientations in the model
    self.jointCal = dict()  # mapping from names to calibration quaternion
    self.jointCur = dict()  # mapping from names to current device orientation
    for name in jointNames:
        self.joints[name] = self.eve.controlJoint(None, 'modelRoot', name)
        self.modelQ[name] = self.joints[name].getQuat()
        self.jointCal[name] = self.modelQ[name].identQuat()
        self.jointCur[name] = self.modelQ[name].identQuat()

    #We now play an animation. An animation must be played, or at least posed
    #for the nodepath we just got from controlJoint to actually effect the model
    #self.eve.actorInterval("walk", playRate = 2).loop()
    print self.eve.listJoints()

    self.setupLights()                           #Put in some default lighting

    # setup socket
    self.udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    self.udpSocket.bind(("localhost", 5555))
    self.udpSocket.setblocking(0)
    taskMgr.add(self.checkSocket, "checkSocket")

  def checkSocket(self, task):
      r_read, r_write, r_error = select.select([self.udpSocket],[],[],0)

      while r_read:
          msg = self.udpSocket.recv(1024)
          #print msg
          msg_list = msg.split(',')
          node_id = int(msg_list[0])
          [w, x, y, z] = [float(val) for val in msg_list[1:5]]
          seqNum = int(msg_list[5])
          #print seqNum
          q = Quat()
          q.setR(w)
          q.setI(x)
          q.setJ(y)
          q.setK(z)

          self.jointCur[mapping[node_id]] = q

          # update root
          root = jointNames[0]
          self.joints[root].setQuat(self.modelQ[root]*(self.jointCal[root]*self.jointCur[root]))

          #other joints
          for name in jointNames[1:]:
              parentName = parents[name]
              _q = self.jointCal[parentName]*self.jointCur[parentName]
              _q = _q.conjugate()
              self.joints[name].setQuat((self.jointCal[name]*self.jointCur[name])*_q*self.modelQ[name])

          r_read, r_write, r_error = select.select([self.udpSocket],[],[],0)
      return Task.cont

  def calibrate(self):
      for name in jointNames:
          self.jointCal[name] = self.jointCur[name].conjugate()

  def setupLights(self):                    #Sets up some default lighting
    ambientLight = AmbientLight( "ambientLight" )
    ambientLight.setColor( Vec4(.4, .4, .35, 1) )
    directionalLight = DirectionalLight( "directionalLight" )
    directionalLight.setDirection( Vec3( 0, 8, -2.5 ) )
    directionalLight.setColor( Vec4( 0.9, 0.8, 0.9, 1 ) )
    render.setLight(render.attachNewNode( directionalLight ) )
    render.setLight(render.attachNewNode( ambientLight ) )
Beispiel #15
0
class Grenade (Projectile):
    def __init__(self, pos, hpr, color, walker_v, name=None):
        super(Grenade, self).__init__(name)
        self.pos = Vec3(*pos)
        self.hpr = hpr
        self.move_divisor = 9
        self.color = color
        self.forward_m = .25
        self.walker_v = walker_v

    def create_node(self):
        self.model = Actor('grenade.egg')
        self.shell = self.model.find('**/shell')
        self.shell.set_color(*self.color)
        self.inner_top = self.model.find('**/inner_top')
        self.inner_bottom = self.model.find('**/inner_bottom')
        self.inner_top.set_color(*random.choice(ENGINE_COLORS))
        self.inner_bottom.set_color(*random.choice(ENGINE_COLORS))
        self.model.set_scale(GRENADE_SCALE)
        self.model.set_hpr(0,0,0)
        self.spin_bone = self.model.controlJoint(None, 'modelRoot', 'grenade_bone')
        return self.model

    def create_solid(self):
        node = BulletRigidBodyNode(self.name)
        node.set_angular_damping(.9)
        node_shape = BulletSphereShape(.08)
        node.add_shape(node_shape)
        node.set_mass(.5)
        return node

    def attached(self):
        self.node.set_pos(self.pos)
        self.node.set_hpr(self.hpr)
        self.world.register_updater(self)
        self.world.register_collider(self)
        self.solid.setIntoCollideMask(NO_COLLISION_BITS)
        self.solid.set_gravity(DEFAULT_GRAVITY*4.5)
        grenade_iv = self.world.scene.get_relative_vector(self.node, Vec3(0,8.5,13.5))
        grenade_iv += (self.walker_v * 1/2)
        self.solid.apply_impulse(grenade_iv, Point3(*self.pos))

    def decompose(self):
        clist = list(self.color)
        clist.extend([1])
        expl_colors = [clist]
        expl_colors.extend(ENGINE_COLORS)
        expl_pos = self.node.get_pos(self.world.scene)
        for c in expl_colors:
            self.world.attach(TriangleExplosion(expl_pos, 1, size=.1, color=c, lifetime=40))
        self.world.garbage.add(self)

    def update(self, dt):
        self.inner_top.set_color(*random.choice(ENGINE_COLORS))
        self.inner_bottom.set_color(*random.choice(ENGINE_COLORS))
        result = self.world.physics.contact_test(self.solid)
        self.spin_bone.set_hpr(self.spin_bone, 0,0,10)
        contacts = result.getContacts()
        if len(contacts) > 0:
            hit_node = contacts[0].get_node1().get_name()
            if hit_node.endswith("_walker_cap"):
                return
            clist = list(self.color)
            clist.extend([1])
            expl_colors = [clist]
            expl_colors.extend(ENGINE_COLORS)
            expl_pos = self.node.get_pos(self.world.scene)
            for c in expl_colors:
                self.world.attach(TriangleExplosion(expl_pos, 3, size=.1, color=c, lifetime=80,))
            self.world.do_explosion(self.node, 3, 100)
            self.world.garbage.add(self)
Beispiel #16
0
class World(DirectObject):
  def __init__(self):
    #This code puts the standard title and instuction text on screen
    self.title = OnscreenText(text="Panda3D: Embots - Joint Manipulation",
                              style=1, fg=(1,1,1,1),
                              pos=(0.8,-0.95), scale = .07)            
    #setup key input
    self.accept('escape', sys.exit)
                              
    #base.disableMouse() #Disable mouse-based camera-control
    camera.setPos(0,-20,0)              #Position the camera

    self.teapot = loader.loadModel('models/teapot')
    self.teapot.reparentTo(render)
    self.teapot.setScale(0.2)

    self.tentacle = Actor("models/tentacle") #Load our animated charachter
    self.tentacle.reparentTo(render)          #Put it in the scene
    self.tentacle.setScale(1.0)

    self.setupLights()                        #Put in some default lighting

    self.tentacleBase = self.tentacle.controlJoint(None, 'modelRoot', 'Bone')

    self.tentacleIK = SMRPy.SmrKinematicChain(True,True,'tentacle');

    self.jointList = []
    self.constraintList = []

    self.createKinematicChain(self.tentacle, 'Bone', '', 0)

    myJoint = self.tentacleIK.getJointByName("Bone.006")

    self.myConstraint = SMRPy.SmrIKConstraint()
    self.myConstraint.setRelatedJointptr(myJoint)
    myConstraintPosition = SMRPy.SmrVector3(0.0,0.0,0.0)
    self.teapot.setPos(0.0,0.0,0.0)
    self.myConstraint.setPosition(myConstraintPosition)

    myConstraintPosition = SMRPy.SmrVector3(0.0,0.0,0.0)
    self.myConstraint.setOffset(myConstraintPosition)

    self.myKinematicSolver = SMRPy.SmrGSMMSolver(self.tentacleIK)
    self.myKinematicSolver.addConstraintPtr(self.myConstraint)

    taskMgr.add(self.ikStep, "ikStep")
    
  def ikStep(self, task):
    if base.mouseWatcherNode.hasMouse():
      mpos = base.mouseWatcherNode.getMouse()
      self.myConstraint.setPosition(SMRPy.SmrVector3(restrain(mpos.getX()) * 10, 0.0 , restrain(mpos.getY()) * 10 ))
      #self.tentacleBase.setR (restrain(mpos.getX()) * 20)
      self.teapot.setPos(restrain(mpos.getX()) * 10, 0.0 , restrain(mpos.getY()) * 10 )
    self.myKinematicSolver.process()
    self.updatePandaSkeleton(self.tentacle, self.tentacleIK, 'Bone')
    return Task.cont

  def createKinematicChain(self, _tentacle, _initialJointName, _parentName, _weight):
    #get the tentacle's currentJoint
    currentPandaJoint = _tentacle.getJoints(_initialJointName)
    currentPandaCJoint = self.tentacle.controlJoint(None, 'modelRoot', _initialJointName)
    #get the first joint's position
    position = currentPandaCJoint.getPos()

    if (currentPandaJoint[0].getNumChildren() == 0):
      newJoint = SMRPy.SmrKinematicJoint(True)
      newJoint.setEndVect(position.getX(),position.getY(),position.getZ());
    else:  
      newJoint = SMRPy.SmrKinematicJoint(False)

    newJoint.setPos(position.getX(),position.getY(),position.getZ())
    print "position", position.getX(), position.getY(), position.getZ()
    #newJoint.setRot(0,0,0)
    newJoint.setParentName(_parentName)
    newJoint.setName(_initialJointName)
    
    rotZ = (currentPandaCJoint.getH()/180.0)*3.14159;
    rotX = (currentPandaCJoint.getP()/180.0)*3.14159;
    rotY = (currentPandaCJoint.getR()/180.0)*3.14159;

    print rotX, rotY, rotZ, currentPandaCJoint.getName()
    # remove the setRot function veveal in C++, error prone

    newJoint.addDof(SMRPy.SmrVector3(0.0,0.0,1.0), rotZ - 1.0, rotZ + 1.0, rotZ, 0.01*_weight);
    newJoint.addDof(SMRPy.SmrVector3(1.0,0.0,0.0), rotX - 1.0, rotX + 1.0, rotX, 0.01*_weight);
    newJoint.addDof(SMRPy.SmrVector3(0.0,1.0,0.0), rotY, rotY, rotY, 0);

    _weight += 0.5


    print newJoint.getName()
    print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

    self.jointList.append(newJoint)
    self.tentacleIK.insertJoint(newJoint)
    for i in range(currentPandaJoint[0].getNumChildren()):
      childJoint = currentPandaJoint[0].getChild(i)
      childName = childJoint.getName()
      print(childName)
      self.createKinematicChain(_tentacle, childName, _initialJointName, _weight)


  def updatePandaSkeleton(self, _pandaSkeleton, _smrSkeleton, _startJointName):
    currentPandaJoint =  _pandaSkeleton.getJoints(_startJointName)
    currentPandaCJoint = _pandaSkeleton.controlJoint(None, 'modelRoot', _startJointName)
    currentSmrJoint = _smrSkeleton.getJointByName(_startJointName)

    self.synchronize(currentPandaCJoint, currentSmrJoint)

    for i in range(currentPandaJoint[0].getNumChildren()):
      childJoint = currentPandaJoint[0].getChild(i)
      childName = childJoint.getName()
      self.updatePandaSkeleton(_pandaSkeleton, _smrSkeleton, childName)

  def synchronize(self, _pandaCJoint, _smrJoint):
    #_smrJoint.setRot(3.14/20.0,0,0);
    smrQuaternion = _smrJoint.getRot()
    pandaQuaternion = Quat()
    pandaQuaternion.setI(smrQuaternion.getX())
    pandaQuaternion.setJ(smrQuaternion.getY())
    pandaQuaternion.setK(smrQuaternion.getZ())
    pandaQuaternion.setR(smrQuaternion.getW())
    _pandaCJoint.setQuat(pandaQuaternion)

#  def turnTentacle(self, task):
    #Check to make sure the mouse is readable
#    if base.mouseWatcherNode.hasMouse():
      #get the mouse position as a Vec2. The values for each axis are from -1 to
      #1. The top-left is (-1,-1), the bottom rightis (1,1)
#      mpos = base.mouseWatcherNode.getMouse()
      #Here we multiply the values to get the amount of degrees to turn
      #Restrain is used to make sure the values returned by getMouse are in the
      #valid range. If this particular model were to turn more than this,
      #significant tearing would be visable
      #self.tentacleBase.setP(restrain(mpos.getY()) * -50)
#      self.tentacleBase.setR (restrain(mpos.getX()) * 20)
#    return Task.cont                        #Task continues infinitely


  def setupLights(self):                    #Sets up some default lighting
    lAttrib = LightAttrib.makeAllOff()
    ambientLight = AmbientLight( "ambientLight" )
    ambientLight.setColor( Vec4(.4, .4, .35, 1) )
    lAttrib = lAttrib.addLight( ambientLight )
    directionalLight = DirectionalLight( "directionalLight" )
    directionalLight.setDirection( Vec3( 0, 8, -2.5 ) )
    directionalLight.setColor( Vec4( 0.9, 0.8, 0.9, 1 ) )
    lAttrib = lAttrib.addLight( directionalLight )
    render.attachNewNode( directionalLight.upcastToPandaNode() ) 
    render.attachNewNode( ambientLight.upcastToPandaNode() ) 
    render.node().setAttrib( lAttrib )
class Agent:
    def __init__( self, _name ):
        print "Creating agent " + _name
        self.name = _name
        self.loadLightingFromConfig = 0
        self.createShadowMap = 0
     
    def setDataPath( self, _dataPath ):
        self.dataPath = _dataPath;
        
    def setActor( self, _modelFileName, _animationFileNames, _morphTargetsFileName ):
        self.modelFileName = _modelFileName;
        self.animationFileNames = _animationFileNames;
        self.morphTargetsFileName = _morphTargetsFileName;
    
    def setRealizer( self, _realizer ):
        self.realizer = _realizer;
        
    def setCameraMask( self, _mask ):
        self.cameraMask = _mask
        
    def setShadowMapParameters( self, _index, _distance ):
        self.createShadowMap = 1
        self.shadowMapIndex = _index
        self.shadowMapDistance = _distance
        
    def setTransform( self, x, y, z, rx, ry, rz, scale ):
        self.agent.setPos( x, y, z )
        self.agent.setScale( scale )
        self.agent.setHpr( rx, ry, rz )
        self.positionX = x
        self.positionY = y
        self.positionZ = z

    def getPosition( self ):
        return self.agent.getPos()
        
    def setLightingConfiguration( self, _config, _name ):
        self.lightingConfig = _config
        self.lightingConfigName = _name
        self.loadLightingFromConfig = 1
        
    def init( self ):
        #load the agent and parent it to the world
        #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it
        self.animationAgent = Actor( self.modelFileName, self.animationFileNames )
        
        self.agent = Actor( self.modelFileName, self.morphTargetsFileName )
        
        self.targets = {#'Basis':[],                
                        'ExpSmileClosed':[],
                        'ExpAnger':[],
                        'ExpDisgust':[],
                        'ExpFear':[],
                        'ExpSad':[],
                        'ExpSurprise':[],
                        'ExpSmileOpen':[],
                        'ModBlinkLeft':[],
                        'ModBlinkRight':[],
                        'ModBrowDownLeft':[],
                        'ModBrowDownRight':[],
                        'ModBlinkRight':[],
                        'ModBrowInRight':[],
                        'ModBrowInLeft':[],
                        'ModBrowUpLeft':[],
                        'ModBrowUpRight':[],
                        'ModEarsOut':[],
                        'ModEyeSquintLeft':[],
                        'ModEyeSquintRight':[],
                        'ModLookDown':[],
                        'ModLookLeft':[],
                        'ModLookRight':[],
                        'ModLookUp':[],
                        'ModBlinkLeft':[],
                        'Phonaah':[],
                        'PhonB,M,P':[],
                        'Phonbigaah':[],
                        'Phonch,J,sh':[],
                        'PhonD,S,T':[],
                        'Phonee':[],
                        'Phoneh':[],
                        'PhonF,V':[],
                        'Phoni':[],
                        'PhonK':[],
                        'PhonN':[],
                        'Phonoh':[],
                        'Phonooh,Q':[],
                        'PhonR':[],
                        'Phonth':[],
                        'PhonW':[]}
        
        iter = self.targets.iteritems()
        while True :
            try: morphsItem = iter.next()
            except StopIteration:break
            for i in range(2,7):
                #print (str(i)+'_'+morphsItem[0])
                blendShape = self.agent.controlJoint(None, 'modelRoot', str(i)+'_'+morphsItem[0])
                if(blendShape):
                    morphsItem[1].append(blendShape)

        self.targets['inspire'] = [self.agent.controlJoint(None, 'modelRoot', 'inspire')]
        
         #instanciate a list in order to keep track of kinematic joints joints 
        #in python runtime
        #if nothing points towards those joints, they get flushed by
        #python's garbage collector
        self.jointList = []
        self.jointFKList = []
        self.agentControlJoints = []
        self.agentNodePaths = []

        self.agentSMRSkel = SMRPy.SMRSkeleton(True,True,'agent')
        self.createSkel( self.agent, self.agentSMRSkel, 'root', '' )
		#pascal: output of both skeletons amber and alfonse as chracter.bvh
        #SMRPy.exportSkeletonToBvh(self.name + '.bvh',self.agentSMRSkel);
        self.newSkeleton = SMRPy.SMRSkeleton(True,True,'pose')
        self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '')       
        self.realizer.addCharacter( self.name, self.agentSMRSkel );
    
        for key in self.targets.keys():
            self.realizer.addMorphTarget( self.name, key ) #TODO: declare morph targets into CharacterConfigurationFile
        
        self.realizer.addShaderParameter( self.name, 'blushing' ) #TODO: declare shader inputs into CharacterConfiguration file
                
        self.agent.reparentTo( render )
        #self.agent.hide( BitMask32.bit( self.cameraMask ) )
        
        #set lighting
        ambientColor = Vec4(0.0,0.0,0.0,0.0)
        self.lighting = shaders.Lighting( ambientColor )
        if self.loadLightingFromConfig == 1:
            self.lighting.loadFromConfig( self.lightingConfig, self.lightingConfigName )
        
        #shadow map
        if self.createShadowMap == 1:
            self.shadowMap = shadowmap.ShadowMap( self.shadowMapIndex, self.dataPath )
        
    def setShaders( self, _shaders ):
        self.shaders = _shaders
        
    def update( self ):
        self.realizer.skeletonRequested()
        self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel)
        
        for key in self.targets.keys():
            #print(key, "\n")
            weight = self.realizer.getMorphTargetWeight( self.name, key )
            morphTargets = self.targets[key]
            for morphTarget in morphTargets :
                #print(weight, "\n")
                morphTarget.setX(weight)
                
        #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' )
        #self.shaders.headShader.blushing.set( blushingValue )
        
        self.lighting.update()
        if self.createShadowMap == 1:
            self.shaders.update()
            self.shadowMap.setLighting( self.lighting, Vec3( self.positionX, self.positionY, self.positionZ ), self.shadowMapDistance )
            self.shaders.updateWithShadows( self.shadowMap )
        else:
            self.shaders.update()
        
    def addAnimation(self,_actorName,_animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range (self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName,i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation",_animationName,"added"
    
    def addAnimationWE(self,_actorName,_animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        agentSMRMotion = SMRPy.SMRMotion()
        agentSMRMotion.setTimeStep(0.04)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range (self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName,i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton)
            agentSMRMotion.insertSkeleton(self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation",_animationName,"added"
        SMRPy.exportMotionToBvh(_animationName+".bvh",agentSMRMotion)

     

    def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None,_initialJointName)

        currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName)
        self.agentControlJoints.append(currentPandaCJoint)
        #get the first joint's position
        position = currentPandaCJoint.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(),position.getY(),position.getZ());
        else:  
            newJoint = SMRPy.SMRJoint(False)

        rotZ = (currentPandaCJoint.getH()/180.0)*3.14159;
        rotX = (currentPandaCJoint.getP()/180.0)*3.14159;
        rotY = (currentPandaCJoint.getR()/180.0)*3.14159;

        quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,0.0,1.0),rotZ)
        quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0,0.0,0.0),rotX)
        quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,1.0,0.0),rotY)

        quatRot = quatZ.multiply(quatX)
        quatRot = quatRot.multiply(quatY)
        quatRot.normalize();

        #quatRot = currentPandaCJoint.getQuat()

        newJoint.setPos(position.getX(),position.getY(),position.getZ())
        #newJoint.setRotQuat(quatRot.getR(),quatRot.getI(),quatRot.getJ(),quatRot.getK())
        newJoint.setRotQuat(quatRot.getW(),quatRot.getX(),quatRot.getY(),quatRot.getZ())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

        self.jointList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName)
        
    def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName, "lodRoot", True)
        self.agentNodePaths.append(currentPandaJointPath)
        #get the first joint's position
        position = currentPandaJointPath.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(),position.getY(),position.getZ());
        else:  
            newJoint = SMRPy.SMRJoint(False)

        quatRot = currentPandaJointPath.getQuat()

        newJoint.setPos(position.getX(),position.getY(),position.getZ())
        newJoint.setRotQuat(quatRot.getR(),quatRot.getI(),quatRot.getJ(),quatRot.getK())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

        self.jointFKList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName)

    def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton):

        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentControlJoints[0]
        #position = SMRJoint.getPos() 
        #PANDAJoint.setPos(position.X(),position.Y(),position.Z());

        for i in range(_smrSkeleton.getNumjoints()):
          SMRJoint = _smrSkeleton.getJoint(i)
          PANDAJoint = agentControlJoints[i]
          self.synchronize(PANDAJoint,SMRJoint)

    def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton):
        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentNodePaths[0]
        position = PANDAJoint.getPos() 
        SMRJoint.setPos(position.getX(),position.getY(),position.getZ());

        for i in range(_smrSkeleton.getNumjoints()):
          SMRJoint = _smrSkeleton.getJoint(i)
          PANDAJoint = agentNodePaths[i]
          self.synchronizePandaToSMR(SMRJoint,PANDAJoint)

    def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint):
        pandaQuaternion = _PANDAJoint.getQuat()
        x = pandaQuaternion.getI()
        y = pandaQuaternion.getJ()
        z = pandaQuaternion.getK()
        w = pandaQuaternion.getR()
        _SMRJoint.setRotQuat(w,x,y,z)

    def synchronize(self, _pandaCJoint, _smrJoint):
        smrQuaternion = _smrJoint.getRot()
        pandaQuaternion = Quat()
        pandaQuaternion.setI(smrQuaternion.getX())
        pandaQuaternion.setJ(smrQuaternion.getY())
        pandaQuaternion.setK(smrQuaternion.getZ())
        pandaQuaternion.setR(smrQuaternion.getW())
        if not(pandaQuaternion.isNan()):
            _pandaCJoint.setQuat(pandaQuaternion)
Beispiel #18
0
class ArmatureUtils():

    def __init__( self ):

        # Set up the components required to create joints:
        self.char = Character("IKChain")
        self.bundle = self.char.getBundle(0)
        self.skeleton = PartGroup(self.bundle, "<skeleton>")

        self.charNodePath = NodePath( self.char )
        self.actor = None       # Will be initialized after all the joints are created

        self.joints = {}
        self.controlNodes = {}

    def createJoint( self, name, parentJoint=None, rotMat=None, rotAxis=None, rotAngRad=0, translate=None, controlNode=None, static=False ):
        """ Utility function which helps to create a joint.
        """

        if name in self.joints.keys():
            raise sys.Exception( f"Cannot create joint with name {name}, already exists!" )

        if rotAxis and rotMat:
            raise sys.Exception( "Only either rotMat or rotAxis can be used, not both!" )

        if rotAxis:
            rotMat = Mat4.rotateMat( rotAngRad/math.pi*180, rotAxis )

        if not rotMat:
            rotMat = Mat4.identMat()

        if translate:
            translateMat = Mat4.translateMat( translate )
        else:
            translateMat = Mat4.identMat()

        transformMat = rotMat*translateMat

        if not parentJoint:
            joint = CharacterJoint( self.char, self.bundle, self.skeleton, name, transformMat )
        else:
            joint = CharacterJoint( self.char, self.bundle, parentJoint, name, transformMat )

        self.joints[name] = joint
        
        return joint

    def finalize( self ):

        self.actor = Actor( self.charNodePath )

        for name, joint in self.joints.items():
            controlNode = self.actor.controlJoint( None, "modelRoot", name )
            self.controlNodes[name] = controlNode

    def getJoint( self, name ):
        return self.joints[name]

    def getControlNode( self, name ):
        return self.controlNodes[name]

    def getActor( self ):
        if not self.actor:
            raise sys.Exception( "Call 'finalize()' before calling 'getActor()'!" ) 
        return self.actor
Beispiel #19
0
class Parcial(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.disableMouse()

        # Instrucciones en pantalla
        self.Salir = addInstructions(.06, "[ESC]: Para Salir")
        self.Camara = addInstructions(.12, "[A]: Para Mover Cabeza")
        self.CabezaL = addInstructions(.18, "[S]: Para Mover Brazo Derecho")
        self.CabezaL = addInstructions(.24, "[D]: Para Mover Brazo Izquierdo")
        self.CaderaL = addInstructions(.30, "[F]: Para Mover Cadera")
        self.CaderaL = addInstructions(.36, "[G]: Para Mover Tronco")
        self.CaderaL = addInstructions(.42, "[H]: Para Girar")
        self.CaderaL = addInstructions(.48, "[Z]: Cabeza Cadera")
        self.CaderaL = addInstructions(.54, "[X]: Brazos")
        self.CaderaL = addInstructions(.60, "[C]: Giro Tronco")
        self.CaderaL = addInstructions(.66, "[V]: Todos a la vez")

        # Carga de un Actor
        self.Ralph = Actor("models/ralph", {
            "run": "models/ralph-run",
            "walk": "models/ralph-walk"
        })

        self.Ralph.setScale(.5, .5, .5)
        self.Ralph.setPos(
            0, 10,
            -1)  #(x   -IZQ  +DER   ,y   PROFUNDIDAD  ,z   +ARRIBA -ABAJO   )
        self.Ralph.reparentTo(self.render)

        # Giro de ralph
        self.GiroTotal = self.Ralph.hprInterval(1.5, Point3(0, 359, 0))

        # Declaración de partes del cuerpo
        self.Cabeza = self.Ralph.controlJoint(None, 'modelRoot', 'Neck')
        self.BrazoDerecho = self.Ralph.controlJoint(None, 'modelRoot',
                                                    'RightShoulder')
        self.BrazoIzquierdo = self.Ralph.controlJoint(None, 'modelRoot',
                                                      'LeftShoulder')
        self.CaderaDerecha = self.Ralph.controlJoint(None, 'modelRoot',
                                                     'RightHip')
        self.CaderaIzquierda = self.Ralph.controlJoint(None, 'modelRoot',
                                                       'LeftHip')
        self.Tronco = self.Ralph.controlJoint(None, 'modelRoot', 'Chest')

        # Movimiento de Cabeza
        self.CabezaAbajo = self.Cabeza.hprInterval(0.5, Point3(0, 0, 0))
        self.CabezaArriba = self.Cabeza.hprInterval(0.5, Point3(20, 0, 0))

        # Movimientos de brazo derecho
        self.BrazoDerechoAbajo = self.BrazoDerecho.hprInterval(
            1.0, Point3(72.2059, 106.186, -45))
        self.BrazoDerechoArriba = self.BrazoDerecho.hprInterval(
            1.0, Point3(72.2059, 76.186, 6.02231))

        # Movimientos de brazo izquierdo
        self.BrazoIzquierdoAbajo = self.BrazoIzquierdo.hprInterval(
            1.0, Point3(160.1401, -22.1706, 6.55722))
        self.BrazoIzquierdoArriba = self.BrazoIzquierdo.hprInterval(
            1.0, Point3(80.1401, -52.1706, 6.55722))

        # Movimientos de cadera derecha
        self.CaderaDerechaDerecha = self.CaderaDerecha.hprInterval(
            0.5, Point3(4.9762, 0, 120))
        self.CaderaDerechaNormal = self.CaderaDerecha.hprInterval(
            0.5, Point3(4.9762, 0, 90))

        # Movimientos de cadera derecha
        self.CaderaIzquierdaIzquierda = self.CaderaIzquierda.hprInterval(
            0.5, Point3(5.02118, -0.862563, 62.9857))
        self.CaderaIzquierdaNormal = self.CaderaIzquierda.hprInterval(
            0.5, Point3(5.02118, -0.862563, 92.9857))

        # Movimientos del tronco
        #self.Tronco.setHpr(0, 50, 0)
        self.TroncoIzquierda = self.Tronco.hprInterval(0.5, Point3(0, 50, 0))
        self.TroncoDerecha = self.Tronco.hprInterval(0.5, Point3(0, -50, 0))
        self.TroncoNormal = self.Tronco.hprInterval(0.5, Point3(0, 0, 0))

        # Secuencias de movimientos
        self.MoverCabeza = Sequence(self.CabezaArriba, self.CabezaAbajo)
        self.MoverBrazoDerecho = Sequence(self.BrazoDerechoAbajo,
                                          self.BrazoDerechoArriba)
        self.MoverBrazoIzquierdo = Sequence(self.BrazoIzquierdoAbajo,
                                            self.BrazoIzquierdoArriba)
        self.MoverCaderaDerechaIzquierda = Sequence(
            self.CaderaDerechaDerecha, self.CaderaDerechaNormal,
            self.CaderaIzquierdaIzquierda, self.CaderaIzquierdaNormal)
        self.MoverTronco = Sequence(self.TroncoDerecha, self.TroncoNormal,
                                    self.TroncoIzquierda)
        self.Giro = Sequence(self.GiroTotal)

        # Paralelos
        self.CaderaCabeza = Parallel(self.MoverCabeza,
                                     self.MoverCaderaDerechaIzquierda)
        self.Brazos = Parallel(self.MoverBrazoDerecho,
                               self.MoverBrazoIzquierdo)
        self.GiroTronco = Parallel(self.Giro, self.MoverTronco)
        self.Todos = Parallel(self.MoverCabeza,
                              self.MoverCaderaDerechaIzquierda,
                              self.MoverBrazoDerecho, self.MoverBrazoIzquierdo,
                              self.Giro, self.MoverTronco)

        self.accept("escape", sys.exit)
        self.accept("a", self.eCabeza)
        self.accept("s", self.eBrazoDerecho)
        self.accept("d", self.eBrazoIzquierdo)
        self.accept("f", self.eCadera)
        self.accept("g", self.eTronco)
        self.accept("h", self.eGiro)
        self.accept("z", self.eCadCab)
        self.accept("x", self.eBrazos)
        self.accept("c", self.eGiroT)
        self.accept("v", self.eTodos)

    def eCabeza(self):
        self.MoverCabeza.start()

    def eBrazoDerecho(self):
        self.MoverBrazoDerecho.start()

    def eBrazoIzquierdo(self):
        self.MoverBrazoIzquierdo.start()

    def eCadera(self):
        self.MoverCaderaDerechaIzquierda.start()

    def eTronco(self):
        self.MoverTronco.start()

    def eGiro(self):
        self.Giro.start()

    def eCadCab(self):
        self.CaderaCabeza.start()

    def eBrazos(self):
        self.Brazos.start()

    def eGiroT(self):
        self.GiroTronco.start()

    def eTodos(self):
        self.Todos.loop()
Beispiel #20
0
class TccSample(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        gltf.patch_loader(self.loader)
        self.disable_mouse()

        self.generateText()

        self.defineKeys()

        self.title = OnscreenText(text="Simulação do TCC",
                                  fg=(1, 1, 1, 1), parent=self.a2dBottomRight,
                                  align=TextNode.ARight, pos=(-0.1, 0.1),
                                  shadow=(0, 0, 0, .5), scale=.08)

        self.hand = Actor("models/Simple_Hand_AfterApply.gltf")

        self.hand.reparentTo(self.render)

        self.hand.setPos(0, 5, 0)

        self.loadHandJoints()

        self.taskMgr.add(self.setHandPostion, "HandTracking")
        print(self.camera.getPos())
        print(self.hand.getPos())


    def loadHandJoints(self):
        # Joints do dedo mindinho
        self.l2LittleFinger = self.hand.controlJoint(None, 'modelRoot', 'L2')
        self.l1LittleFinger = self.hand.controlJoint(None, 'modelRoot', 'L1')
        self.l0LittleFinger = self.hand.controlJoint(None, 'modelRoot', 'L0')

        # Joints do dedo anelar
        self.r2RingFinger = self.hand.controlJoint(None, 'modelRoot', 'R2')
        self.r1RingFinger = self.hand.controlJoint(None, 'modelRoot', 'R1')
        self.r0RingFinger = self.hand.controlJoint(None, 'modelRoot', 'R0')

        # Joints do dedo do meio
        self.m2MiddleFinger = self.hand.controlJoint(None, 'modelRoot', 'M2')
        self.m1MiddleFinger = self.hand.controlJoint(None, 'modelRoot', 'M1')
        self.m0MiddleFinger = self.hand.controlJoint(None, 'modelRoot', 'M0')

        # Joints do dedo indicador
        self.i2IndexFinger = self.hand.controlJoint(None, 'modelRoot', 'I2')
        self.i1IndexFinger = self.hand.controlJoint(None, 'modelRoot', 'I1')
        self.i0IndexFinger = self.hand.controlJoint(None, 'modelRoot', 'I0')

        # Joints do dedão da mão
        self.t2Thumb = self.hand.controlJoint(None, 'modelRoot', 'T2')
        self.t1Thumb = self.hand.controlJoint(None, 'modelRoot', 'T1')
        self.t0Thumb = self.hand.controlJoint(None, 'modelRoot', 'T0')


    def defineKeys(self):
        self.accept('escape', sys.exit)
        self.accept('1', self.changePerspective, [-60, -60])
        self.accept('2', self.changePerspective, [-60, 60])
        self.accept('3', self.moveFingers)
        self.accept('4', self.resetPerspective)
        self.accept('5', self.resetFinger)


    def generateText(self):
        self.onekeyText = genLabelText("ESC: Sair", 1, self)
        self.onekeyText = genLabelText("[1]: Muda a Perpectiva da câmera para o primeiro modo", 2, self)
        self.onekeyText = genLabelText("[2]: Muda a Perspectiva da câmera para o segundo modo", 3, self)
        self.onekeyText = genLabelText("[3]: Mexe os dedos", 4, self)
        self.onekeyText = genLabelText("[4]: Volta a perspectiva da mão para o formato original", 5, self)
        self.onekeyText = genLabelText("[5]: Volta os dedos para a posição inicial", 6, self)


    def setHandPostion(self, task):
        if self.mouseWatcherNode.hasMouse():
            mousePosition = self.mouseWatcherNode.getMouse()
            self.hand.setX(mousePosition.getX() * 2)
            self.hand.setZ(mousePosition.getY() * 1.5)
            #print(self.hand.getPos())
        return Task.cont

    def changePerspective(self, firstAngle, secondAngle):
        # Muda em Y e Z
        self.hand.setP(firstAngle)
        # Muda em X e Z
        self.hand.setR(secondAngle)
        # Muda em X e Y
        #self.hand.setH(60)

    def resetPerspective(self):
        self.hand.setP(0)
        self.hand.setR(0)

    def moveFingers(self):
        self.moveLittleFinger()
        self.moveRingFinger()
        self.moveMiddleFinger()
        self.moveIndexFinger()
        self.moveThumb()

    def moveLittleFinger(self):
        self.l0LittleFinger.setP(-20)
        self.l1LittleFinger.setP(-40)
        self.l2LittleFinger.setP(-30)

    def moveRingFinger(self):
        self.r0RingFinger.setP(-20)
        self.r1RingFinger.setP(-40)
        self.r2RingFinger.setP(-30)

    def moveMiddleFinger(self):
        self.m0MiddleFinger.setP(-20)
        self.m1MiddleFinger.setP(-40)
        self.m2MiddleFinger.setP(-30)

    def moveIndexFinger(self):
        self.i0IndexFinger.setP(-20)
        self.i1IndexFinger.setP(-40)
        self.i2IndexFinger.setP(-30)

    def moveThumb(self):
        self.t0Thumb.setP(-20)
        self.t1Thumb.setR(40)
        self.t2Thumb.setP(-30)
        self.t2Thumb.setR(40)

    def resetFinger(self):
        self.l0LittleFinger.setP(0)
        self.l1LittleFinger.setP(0)
        self.l2LittleFinger.setP(0)

        self.r0RingFinger.setP(0)
        self.r1RingFinger.setP(0)
        self.r2RingFinger.setP(0)

        self.m0MiddleFinger.setP(0)
        self.m1MiddleFinger.setP(0)
        self.m2MiddleFinger.setP(0)

        self.i0IndexFinger.setP(0)
        self.i1IndexFinger.setP(0)
        self.i2IndexFinger.setP(0)

        self.t0Thumb.setP(0)
        self.t1Thumb.setR(0)
        self.t2Thumb.setP(0)
        self.t2Thumb.setR(0)
Beispiel #21
0
class MyHand(ShowBase):
    def __init__(self, fingerInput):
        ShowBase.__init__(self)
        self.fingerPositions = fingerInput

        self.disableMouse()
        tex = loader.loadTexture('HandModel/HandTexture.png')

        self.Hand = Actor("HandModel/Hand.egg")
        self.Hand.setScale(1.5, 1.5, 1.5)
        self.Hand.setTexture(tex, 1)

        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
        self.taskMgr.add(self.moveFingers, "MoveFingerTask")
        #self.taskMgr.add(self.updateFingers(fingerInput), "UpdateFingerTask")

        self.Hand.reparentTo(self.render)

    def moveFingers(self, task):
        #self.Hand.listJoints()
        angleDegrees = self.fingerPositions.get()  #task.time * 100.0
        #print(angleDegrees)
        if angleDegrees != "quit":
            angleDegrees *= 90
        else:
            self.destroy()
            return task.done
        fingerList = ["pinky", "ring", "middle", "index", "thumb"]
        jointNumber = 3
        for finger in fingerList:
            if finger == "thumb":
                NodePath = self.Hand.controlJoint(None, "modelRoot",
                                                  finger + str(1))
                Init_Rot = NodePath.getHpr()
                NodePath.setHpr(
                    -15 * (sin(angleDegrees * pi / 180) + 1) + Init_Rot.getX(),
                    -5 * (sin(angleDegrees * pi / 180) - 2) + Init_Rot.getY(),
                    Init_Rot.getZ())
                NodePath = self.Hand.controlJoint(None, "modelRoot",
                                                  finger + str(2))
                Init_Rot = NodePath.getHpr()
                NodePath.setHpr(
                    Init_Rot.getX() + 15 * (sin(angleDegrees * pi / 180) - 1),
                    Init_Rot.getY() - 15 * (sin(angleDegrees * pi / 180) - 1),
                    Init_Rot.getZ())
                NodePath = self.Hand.controlJoint(None, "modelRoot",
                                                  finger + str(3))
                Init_Rot = NodePath.getHpr()
                NodePath.setHpr(
                    Init_Rot.getX() + 15 * (sin(angleDegrees * pi / 180) - 1),
                    Init_Rot.getY() - 5 * (sin(angleDegrees * pi / 180) - 1),
                    Init_Rot.getZ())
            else:
                for i in range(1, jointNumber + 1):
                    NodePath = self.Hand.controlJoint(None, "modelRoot",
                                                      finger + str(i))
                    NodePath.setHpr(45 * (sin(angleDegrees * pi / 180) - 1), 0,
                                    0)
        return task.cont

    #def updateFingers(self,task):
    #    self.fingerPositions = input.get()
    #    return task.cont
    def spinCameraTask(self, task):
        angleDegrees = 60
        angleRadians = angleDegrees * (pi / 180.0)
        self.camera.setPos(20 * sin(angleRadians), -20 * cos(angleRadians), 4)
        self.camera.setHpr(angleDegrees, 0, 0)
        return Task.done
Beispiel #22
0
class DemoBase(ShowBase, ABC):
    def __init__(self):
        super().__init__()

        # Allow panda to synthesize shaders. Make sure hardware-animated-vertices is set
        # to true in panda config.
        render.setShaderAuto()

        # Show FPS
        self.setFrameRateMeter(True)

        # Load character
        self.character = Actor('data/character/character')
        self.character.reparentTo(self.render)
        self.joints = []
        for name in JOINT_NAMES:
            j = self.character.controlJoint(None, 'modelRoot', name)
            j.reparentTo(self.render)
            self.joints.append(j)

        # Add lights
        dlight = core.DirectionalLight('DirectionalLight')
        dlight.setDirection(core.LVector3(2, 0, -1))
        dlight.setColor(core.LColor(1, 1, 1, 1))
        dlnp = self.render.attachNewNode(dlight)
        self.render.setLight(dlnp)

        alight = core.AmbientLight('AmbientLight')
        alight.setColor(core.LColor(0.6, 0.6, 0.6, 1))
        alnp = self.render.attachNewNode(alight)
        self.render.setLight(alnp)

        # Camera angle in xy-plane (degrees)
        self.camera_angle = 0

        # Camera control
        self.cam_left_pressed, self.cam_right_pressed = 0, 0
        self.accept('a', self.set_cam_left_pressed, [1])
        self.accept('a-up', self.set_cam_left_pressed, [0])
        self.accept('d', self.set_cam_right_pressed, [1])
        self.accept('d-up', self.set_cam_right_pressed, [0])

        # Pad display
        self.pad_radius = 60
        self.pad_outline = OnscreenImage('project/data/pad/pad_outline.png',
                                         (0, 0, 0))
        self.pad_outline.setTransparency(core.TransparencyAttrib.MAlpha)
        self.pad_outline.hide()
        self.pad_response_circle = OnscreenImage(
            'project/data/pad/pad_response_indicator.png', (0, 0, 0))
        self.pad_response_circle.setTransparency(
            core.TransparencyAttrib.MAlpha)
        self.pad_response_circle.hide()
        self.accept('window-event', self.handle_window_event)

        # Pad control
        self.mouse1_pressed, self.controlling_pad = False, False
        self.accept('mouse1', self.set_mouse1_pressed, [True])
        self.accept('mouse1-up', self.set_mouse1_pressed, [False])

        # Load terrain
        self.heightmaps = {}
        self.set_heightmap('hmap2', 'project/data/heightmaps/hmap2.npy')

        # Heightmap choice
        self.accept('1', self.set_heightmap,
                    ['hmap1', 'project/data/heightmaps/hmap1.npy'])
        self.accept('2', self.set_heightmap,
                    ['hmap2', 'project/data/heightmaps/hmap2.npy'])
        self.accept('3', self.set_heightmap,
                    ['hmap3', 'project/data/heightmaps/hmap3.npy'])
        self.accept('4', self.set_heightmap,
                    ['hmap4', 'project/data/heightmaps/hmap4.npy'])
        self.accept('5', self.set_heightmap,
                    ['hmap5', 'project/data/heightmaps/hmap5.npy'])

        # Tasks
        self.taskMgr.add(self.update_pad, 'UpdatePadTask', sort=1)
        self.last_update_char_time = 0
        self.taskMgr.add(self.update_character, 'UpdateCharacterTask', sort=2)
        self.last_update_cam_time = 0
        self.taskMgr.add(self.update_camera, 'UpdateCameraTask', sort=3)

    def set_cam_left_pressed(self, val):
        self.cam_left_pressed = val

    def set_cam_right_pressed(self, val):
        self.cam_right_pressed = val

    def set_mouse1_pressed(self, val):
        self.mouse1_pressed = val
        if self.mouse1_pressed and self.mouseWatcherNode.hasMouse():
            mpos = self.screen_coords_to_pixels(
                self.mouseWatcherNode.getMouse())
            diff = mpos - self.pad_center
            self.controlling_pad = diff.lengthSquared() <= self.pad_radius**2
        else:
            self.controlling_pad = False

    def handle_window_event(self, window):
        self.window_w, self.window_h = window.getSize()
        min_dim = min(self.window_w, self.window_h)

        self.pad_radius = min_dim * 0.1

        if self.window_w < 1300:
            self.pad_center = core.LVector2(min_dim * 0.15, min_dim * 0.15)
        else:
            self.pad_center = core.LVector2(self.window_w * 0.75,
                                            self.window_h * 0.5)

        self.pad_outline.setPos(self.pixels_to_im_coords(self.pad_center))
        self.pad_outline.setScale(2 * self.pad_radius / min_dim)
        self.pad_outline.show()

        self.pad_response_circle.setScale(0.2 * self.pad_radius / min_dim)

        # Propagate event
        self.windowEvent(window)

    # Converts from screen coords in the [-1, 1] range to pixel coords
    def screen_coords_to_pixels(self, point):
        x_frac, y_frac = (point + 1.0) / 2.0
        return core.LVector2(x_frac * self.window_w,
                             (1 - y_frac) * self.window_h)

    # Converts from pixel coords to coords that can be passed in to OnscreenImage.setPos()
    def pixels_to_im_coords(self, point):
        px, py = point
        px, py = px - self.window_w / 2, py - self.window_h / 2
        return core.LVector3(px, 0,
                             -py) * (2.0 / min(self.window_w, self.window_h))

    def update_pad(self, task):
        if self.controlling_pad and self.mouseWatcherNode.hasMouse():
            mpos = self.screen_coords_to_pixels(
                self.mouseWatcherNode.getMouse())

            pad_input = (mpos - self.pad_center) * PAD_SENSITIVITY
            if pad_input.lengthSquared() > 1:
                pad_input.normalize()

            resp_circle_pos = self.pad_center + pad_input * (self.pad_radius *
                                                             0.9)
            self.pad_response_circle.setPos(
                self.pixels_to_im_coords(resp_circle_pos))
            self.pad_response_circle.show()
        else:
            pad_input = core.LVector2()
            self.pad_response_circle.hide()

        pad_input.setY(-pad_input.getY())  # flip y
        self.pad_input = pad_input
        return Task.cont

    def set_joint_global_xforms(self, global_xforms):
        # Invert global transforms
        inverse_global_xforms = [None] * NUM_JOINTS
        for i in PARENT_JOINTS:
            inverse_global_xforms[i] = core.LMatrix4()
            inverse_global_xforms[i].invertAffineFrom(global_xforms[i])

        # Use each joint's global xform and the inverse of its parent's global xform to
        # compute and apply its local xform
        self.joints[0].setMat(global_xforms[0])
        for i in range(1, NUM_JOINTS):
            local_xform = global_xforms[i] * inverse_global_xforms[
                JOINT_PARENTS[i]]
            self.joints[i].setMat(local_xform)

    def update_character(self, task):
        dt = task.time - self.last_update_char_time

        self._update_character(task.time, dt)
        self.character.setPos(self.char_pos)
        self.set_joint_global_xforms([
            core.LMatrix4(*m)
            for m in self.joint_global_xforms.reshape(31, 16)
        ])

        self.last_update_char_time = task.time
        return Task.cont

    @abstractmethod
    def _update_character(self, t, dt):
        '''Should set self.char_pos and self.joint_global_xforms.'''
        raise NotImplementedError()

    def update_camera(self, task):
        dt = task.time - self.last_update_cam_time

        # Update camera angle
        self.camera_angle += 90 * (self.cam_right_pressed -
                                   self.cam_left_pressed) * dt

        # Reposition camera
        ang_rads = self.camera_angle * pi / 180
        cam_offset = core.LVector3(300 * cos(ang_rads), 300 * sin(ang_rads),
                                   320)
        self.camera.setPos(self.char_pos + cam_offset)
        self.camera.lookAt(self.char_pos + core.LVector3(0, 0, 80),
                           core.LVector3(0, 0, 1))

        self.last_update_cam_time = task.time
        return Task.cont

    def set_heightmap(self, name, fname):
        if name not in self.heightmaps:
            self.heightmaps[name] = Heightmap(name, fname, self.render)

        reset = False
        if hasattr(self, 'heightmap'):
            self.heightmap.model_np.stash()
            reset = True

        self.heightmap = self.heightmaps[name]
        self.heightmap.model_np.unstash()
        if reset: self.reset_level()

    def reset_level(self):
        self.camera_angle = 0
        self.char_pos = core.LVector3()
Beispiel #23
0
class MayaDemo(ShowBase):
    R_LEG_JOINTS = ["joint6", "joint7", "joint8"]
    L_LEG_JOINTS = ["joint10", "joint11", "joint12"]

    def __init__(self):
        ShowBase.__init__(self)

        self.bandit = Actor("banditRiggedNoHat.egg")
        self.bandit.makeSubpart("r_leg", self.R_LEG_JOINTS)
        self.bandit.makeSubpart("l_leg", self.L_LEG_JOINTS)

        headJoint = self.bandit.exposeJoint(None, "modelRoot", "joint5")
        hat = loader.loadModel("{}_hat.egg".format(random.randint(0, 7)))
        hat.setPos(0, 0, -0.08)
        hat.setHpr(-90, 0, 0)
        hat.setScale(0.35)
        hat.reparentTo(headJoint)

        self.bandit.reparentTo(render)

        r_hip_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[0])
        r_hip_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[0])
        r_knee_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[1])
        r_knee_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[1])
        r_ankle_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[2])
        r_ankle_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[2])
        distances = np.array([r_hip_ro.getDistance(r_knee_ro), r_knee_ro.getDistance(r_ankle_ro)])
        self.r_leg = Leg.Leg(r_hip_ro, r_hip_wo, r_knee_ro, r_knee_wo, r_ankle_ro, r_ankle_wo, distances)

        l_hip = self.bandit.controlJoint(None, "modelRoot", self.L_LEG_JOINTS[0])
        l_knee = self.bandit.controlJoint(None, "modelRoot", self.L_LEG_JOINTS[1])
        l_ankle = self.bandit.exposeJoint(None, "modelRoot", self.L_LEG_JOINTS[2])
        distances = np.array([l_hip.getDistance(l_knee), l_knee.getDistance(l_ankle)])
        #self.l_leg = Leg.Leg(l_hip, l_knee, l_ankle, distances)

        self.accept("arrow_up", self.r_leg.moveAnkle, [(0, 0, 0.1)])
        self.accept("arrow_down", self.r_leg.moveAnkle, [(0, 0, -0.1)])

        self.accept("arrow_left", self.r_leg.rotateAnkle, [(0, 0, 10)])
        self.accept("arrow_right", self.r_leg.rotateAnkle, [(0, 0, -10)])

        # Draws debug skeleton
        self.bandit.setBin('background', 1)
        self.walkJointHierarchy(self.bandit, self.bandit.getPartBundle('modelRoot'))

        self.stream = StreamRead("/dev/input/smartshoes")
        self.last_t = time.time()
        taskMgr.add(self.getDeviceData, 'Stream reader')

    def getDeviceData(self, task):
        records = self.stream.readFromStream()
        if records and len(records[0]) == 10:
            records = map(float, records[0])
            angular_velocity, acceleration, magnetic_field = [records[x:x+3] for x in range(0, 9, 3)]

            # Switch axis orientations
            angular_velocity[2], angular_velocity[0] = angular_velocity[0], angular_velocity[2]
            acceleration[2], acceleration[0] = acceleration[0], acceleration[2]
            magnetic_field[2], magnetic_field[0] = magnetic_field[0], magnetic_field[2]

            self.r_leg.ankle_rotation.rotationMagic(records[9], angular_velocity, acceleration, magnetic_field)
            self.r_leg.updateAnkleRotation()
        return task.again

    def walkJointHierarchy(self, actor, part, parentNode = None, indent = ""):
        if isinstance(part, CharacterJoint):
            np = actor.exposeJoint(None, 'modelRoot', part.getName())

            if parentNode and parentNode.getName() != "root":
                lines = LineSegs()
                lines.setThickness(3.0)
                lines.setColor(random.random(), random.random(), random.random())
                lines.moveTo(0, 0, 0)
                lines.drawTo(np.getPos(parentNode))
                lnp = parentNode.attachNewNode(lines.create())
                lnp.setBin("fixed", 40)
                lnp.setDepthWrite(False)
                lnp.setDepthTest(False)

            parentNode = np

        for child in part.getChildren():
            self.walkJointHierarchy(actor, child, parentNode, indent + "  ")
Beispiel #24
0
class LookingGrippingDemo(ShowBase):

    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)

        # This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Joint Manipulation",
                                  fg=(1, 1, 1, 1), parent=base.a2dBottomRight,
                                  align=TextNode.ARight, pos=(-0.1, 0.1),
                                  shadow=(0, 0, 0, .5), scale=.08)

        self.onekeyText = genLabelText("ESC: Quit", 1)
        self.onekeyText = genLabelText("[1]: Teapot", 2)
        self.twokeyText = genLabelText("[2]: Candy cane", 3)
        self.threekeyText = genLabelText("[3]: Banana", 4)
        self.fourkeyText = genLabelText("[4]: Sword", 5)

        # Set up key input
        self.accept('escape', sys.exit)
        self.accept('1', self.switchObject, [0])
        self.accept('2', self.switchObject, [1])
        self.accept('3', self.switchObject, [2])
        self.accept('4', self.switchObject, [3])

        base.disableMouse()  # Disable mouse-based camera-control
        camera.setPos(0, -15, 2)  # Position the camera

        self.eve = Actor("models/eve",  # Load our animated charachter
                         {'walk': "models/eve_walk"})
        self.eve.reparentTo(render)  # Put it in the scene

        # Now we use controlJoint to get a NodePath that's in control of her neck
        # This must be done before any animations are played
        self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck')

        # We now play an animation. An animation must be played, or at least posed
        # for the nodepath we just got from controlJoint to actually effect the
        # model
        self.eve.actorInterval("walk", playRate=2).loop()

        # Now we add a task that will take care of turning the head
        taskMgr.add(self.turnHead, "turnHead")

        # Now we will expose the joint the hand joint. ExposeJoint allows us to
        # get the position of a joint while it is animating. This is different than
        # controlJonit which stops that joint from animating but lets us move it.
        # This is particularly usefull for putting an object (like a weapon) in an
        # actor's hand
        self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand')

        # This is a table with models, positions, rotations, and scales of objects to
        # be attached to our exposed joint. These are stock models and so they needed
        # to be repositioned to look right.
        positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4),
                     ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1),
                     ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75),
                     ("models/sword", (.11, .19, .06), (0, 0, 90), 1)]

        self.models = []  # A list that will store our models objects
        for row in positions:
            np = loader.loadModel(row[0])  # Load the model
            np.setPos(row[1][0], row[1][1], row[1][2])  # Position it
            np.setHpr(row[2][0], row[2][1], row[2][2])  # Rotate it
            np.setScale(row[3])  # Scale it
            # Reparent the model to the exposed joint. That way when the joint moves,
            # the model we just loaded will move with it.
            np.reparentTo(self.rightHand)
            self.models.append(np)  # Add it to our models list

        self.switchObject(0)  # Make object 0 the first shown
        self.setupLights()  # Put in some default lighting

    # This is what we use to change which object it being held. It just hides all of
    # the objects and then unhides the one that was selected
    def switchObject(self, i):
        for np in self.models:
            np.hide()
        self.models[i].show()

    # This task gets the position of mouse each frame, and rotates the neck based
    # on it.
    def turnHead(self, task):
        # Check to make sure the mouse is readable
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position as a LVector2. The values for each axis are from -1 to
            # 1. The top-left is (-1,-1), the bottom right is (1,1)
            mpos = base.mouseWatcherNode.getMouse()
            # Here we multiply the values to get the amount of degrees to turn
            # Restrain is used to make sure the values returned by getMouse are in the
            # valid range. If this particular model were to turn more than this,
            # significant tearing would be visable
            self.eveNeck.setP(clamp(mpos.getX()) * 50)
            self.eveNeck.setH(clamp(mpos.getY()) * 20)

        return Task.cont  # Task continues infinitely

    def setupLights(self):  # Sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.4, .4, .35, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 8, -2.5))
        directionalLight.setColor((0.9, 0.8, 0.9, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Beispiel #25
0
class Monster():
    def __init__(self, setup_data, common, level=1.0, start_pos=(0,0,0)):
        common['monsterList'].append(self)
        id=len(common['monsterList'])-1
        self.monsterList=common['monsterList']
        self.waypoints_data=common['waypoints_data']
        self.waypoints=common['waypoints']
        self.audio3d=common['audio3d']
        self.common=common

        #root node
        self.node=render.attachNewNode("monster")
        self.sound_node=None
        self.soundset=None

        self.actor=Actor(setup_data["model"],setup_data["anim"] )
        self.actor.setBlend(frameBlend = True)
        self.actor.reparentTo(self.node)
        self.actor.setScale(setup_data["scale"]*random.uniform(0.9, 1.1))
        self.actor.setH(setup_data["heading"])
        self.actor.setBin("opaque", 10)

        self.rootBone=self.actor.exposeJoint(None, 'modelRoot', setup_data["root_bone"])

        #sounds
        self.soundID=self.common['soundPool'].get_id()
        self.common['soundPool'].set_target(self.soundID, self.node)
        self.sound_names={"hit":setup_data["hit_sfx"],
                          "arrow_hit":setup_data["arrowhit_sfx"],
                          "attack":setup_data["attack_sfx"],
                          "die":setup_data["die_sfx"]}

        self.vfx=setup_data["hit_vfx"]

        self.stats={"speed":setup_data["speed"],
                    "hp":setup_data["hp"]*level,
                    "armor":setup_data["armor"]*level,
                    "dmg":setup_data["dmg"]*level
                    }
        if self.stats['hp']>300:
            self.stats['hp']=300
        self.maxHP=self.stats['hp']
        self.HPring=Actor("models/ring_morph", {'anim' : 'models/ring_anim'})
        self.HPring.setScale(0.07)
        self.HPring.setZ(0.4)
        self.HPring.setLightOff()
        self.HPring.reparentTo(self.node)
        self.HPvis=self.HPring.controlJoint(None, 'modelRoot', 'morph01')
        self.HPvis.setX(self.stats['hp']/300)
        self.HPring.hide(BitMask32.bit(1))
        self.HPring.hide()
        #self.HPring.setColorScale(0.0, 1.0, 0.0, 1.0)

        #gamestate variables
        self.attack_pattern=setup_data["attack_pattern"]
        self.damage=setup_data["dmg"]
        #self.HP=setup_data["hp"]
        self.state="STOP"
        self.id=id
        self.nextWaypoint=None
        self.canSeePC=False
        self.PCisInRange=False
        self.PC=common['PC']
        self.speed_mode=random.randrange(0+int(level),42+int(level), 7)/100.0
        self.totalSpeed=self.stats['speed']+self.speed_mode
        self.sparkSum=0
        self.lastMagmaDmg=0
        self.DOT=0
        self.arrows=set()
        self.traverser=CollisionTraverser("Trav"+str(self.id))
        #self.traverser.showCollisions(render)
        self.queue = CollisionHandlerQueue()

        #bit masks:
        # 1  visibility polygons & coll-rays
        # 2  walls & radar-ray
        # 3  spheres

        #collision ray for testing visibility polygons
        coll=self.node.attachNewNode(CollisionNode('collRay'))
        coll.node().addSolid(CollisionRay(0, 0, 2, 0,0,-180))
        coll.setTag("id", str(id))
        coll.node().setIntoCollideMask(BitMask32.allOff())
        coll.node().setFromCollideMask(BitMask32.bit(1))
        self.traverser.addCollider(coll, self.queue)

        #radar collision ray
        self.radar=self.node.attachNewNode(CollisionNode('radarRay'))
        self.radar.node().addSolid(CollisionRay(0, 0, 1, 0,90,0))
        self.radar.node().setIntoCollideMask(BitMask32.allOff())
        self.radar.node().setFromCollideMask(BitMask32.bit(2))
        self.radar.setTag("radar", str(id))
        #self.radar.show()
        self.traverser.addCollider(self.radar, self.queue)

        #collision sphere
        self.coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere'))
        self.coll_sphere.node().addSolid(CollisionSphere(0, 0, 0.8, 0.8))
        self.coll_sphere.setTag("id", str(id))
        self.coll_sphere.node().setIntoCollideMask(BitMask32.bit(3))
        #coll_sphere.show()

        #other monster blocking
        self.coll_quad=loader.loadModel("models/plane")
        self.coll_quad.reparentTo(self.node)

        #coll_quad=render.attachNewNode(CollisionNode('monsterSphere'))
        #coll_quad.node().addSolid(CollisionPolygon(Point3(-.5, -.5, 2), Point3(-.5, .5, 0), Point3(.5, .5, 0), Point3(.5, .5, 2)))
        #coll_quad.setTag("id", str(id))
        #coll_quad.node().setIntoCollideMask(BitMask32.bit(2))
        #coll_quad.reparentTo(self.node)
        #coll_quad.show()

        Sequence(Wait(random.uniform(.6, .8)), Func(self.restart)).start()
        self.node.setPos(render,start_pos)
        taskMgr.add(self.runAI, "AIfor"+str(self.id))
        taskMgr.doMethodLater(.6, self.runCollisions,'collFor'+str(self.id))
        taskMgr.doMethodLater(1.0, self.damageOverTime,'DOTfor'+str(self.id))

    def damageOverTime(self, task):
        if self.state=="DIE":
            return task.done
        if self.DOT>0:
            self.doDamage(self.DOT)
            self.DOT=int((self.DOT*0.9)-1.0)
            if self.stats['hp']<1:
                self.actor.play("die")
                #self.common['soundPool'].play(self.soundID, self.sound_names["hit"])
                self.common['soundPool'].play(self.soundID, self.sound_names["die"])
                self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016, 24)
        return task.again

    def restart(self):
        self.state="SEEK"

    def check_stacking(self):
        for monster in self.monsterList:
            if monster and monster.id!=self.id :
                if self.node.getDistance(monster.node)< .8:
                    if monster.state!="STOP" and self.state=="SEEK":
                        if self.totalSpeed <= monster.totalSpeed:
                            self.state="STOP"
                            self.actor.stop()
                            Sequence(Wait(1.5), Func(self.restart)).start()
                            return True

    def doDamage(self, damage, igoreArmor=False):
        if self.state=="DIE":
            return
        if not igoreArmor:
            damage-=self.stats['armor']
        if damage<1:
            damage=1
        #print damage
        self.stats['hp']-=damage
        scale=self.stats['hp']/self.maxHP
        self.HPvis.setX(self.stats['hp']/300.0)
        #self.HPring.setColor(0.8*(1.0-scale), 0.8*scale, 0.0, 1.0)
        self.HPring.show()
        self.HPring.setColorScale((1.0-scale), scale, 0.0, 1.0)
        if self.stats['hp']<1:
            self.HPring.hide()

    def attack(self, pattern):
        if self.state=="DIE":
            return
        if not self.PC.node:
            return
        if pattern:
            next=pattern.pop()
        else:
            self.state="SEEK"
            self.PCisInRange=False
            return
        if self.PC.node and self.node:
            range= self.node.getDistance(self.PC.node)
        else:
            return
        #print range
        if range<1.8:
            self.PC.hit(self.damage)
        Sequence(Wait(next), Func(self.attack, pattern)).start()

    def onMagmaHit(self):
        if self.state=="DIE":
            return
        damage=self.lastMagmaDmg
        self.doDamage(damage)
        self.common['soundPool'].play(self.soundID, "onFire")
        vfx(self.node, texture="vfx/small_flame.png",scale=.6, Z=.7, depthTest=False, depthWrite=False).start(0.016, stopAtFrame=24) 
        if self.stats['hp']<1:
            self.actor.play("die")
            self.common['soundPool'].play(self.soundID, "die3")
            self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)

    def onPlasmaHit(self, damage):
        if self.state=="DIE":
            return
        self.doDamage(damage*1.5, True)
        #self.soundset["spark"].play()
        #self.common['soundPool'].play(self.soundID, "spark")
        if self.stats['hp']<1:
            self.actor.play("die")
            #self.soundset["die3"].play()
            self.common['soundPool'].play(self.soundID, "die3")
            self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)
        #else:
        #    short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03)

    def onSparkHit(self, damage):
        if self.state=="DIE":
            return
        #print damage
        self.doDamage(damage)
        #self.soundset["spark"].play()
        self.common['soundPool'].play(self.soundID, "spark")
        if self.stats['hp']<1:
            self.actor.play("die")
            #self.soundset["die3"].play()
            self.common['soundPool'].play(self.soundID, "die3")
            self.state="DIE"
            vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) 
        else:
            short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03) 

    def onHit(self, damage, sound="hit"):
        if self.state=="DIE":
            return
        self.doDamage(damage)
        #print damage
        vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016)         

        if self.stats['hp']<1:
            self.actor.play("die")
            #self.sounds["die"].play()
            if sound:
                self.common['soundPool'].play(self.soundID, self.sound_names[sound])
            self.common['soundPool'].play(self.soundID, self.sound_names["die"])
            self.state="DIE"
        else:
            #self.sounds["hit"].play()
            if sound:
                self.common['soundPool'].play(self.soundID, self.sound_names[sound])

    def findFirstWaypoint(self):
        min=100000
        nearest=None
        for waypoint in self.waypoints:
            dist=self.node.getDistance(waypoint)
            if dist<min:
                min=dist
                nearest=waypoint
        return nearest

    def runCollisions(self, task):
        if self.state=="DIE":
            return task.done
        if self.node.getDistance(self.PC.node) >50.0:
            self.nextWaypoint=None
            return task.again
        if self.check_stacking():
            return task.again
        self.radar.lookAt(self.PC.node)
        valid_waypoints=[]
        isFirstTest=True
        self.canSeePC=False
        self.traverser.traverse(render)
        self.queue.sortEntries()
        for entry in self.queue.getEntries():
            if entry.getFromNodePath().hasTag("id"): #it's the monsters collRay
                valid_waypoints.append(int(entry.getIntoNodePath().getTag("index"))) #visibility polygons
            elif entry.getFromNodePath().hasTag("radar"): #it's the radar-ray
                #print "radar hit", entry.getIntoNodePath()
                if isFirstTest:
                    isFirstTest=False
                    #print "first hit!"
                    #print "radar hit", entry.getIntoNodePath()
                    if entry.getIntoNodePath().hasTag("player"):
                        self.canSeePC=True
        '''distance={}
        for target in self.PC.myWaypoints:
            for waypoint in valid_waypoints:
                distance[target]=self.waypoints_data[target][waypoint]                
                print(target, distance[target])
        if distance:
            self.nextWaypoint=self.waypoints[min(distance, key=distance.get)]
        #print self.canSeePC'''
        if not valid_waypoints:
            #self.nextWaypoint=self.findFirstWaypoint()
            print(self.id, ": I'm lost!")
            valid_waypoints=[self.findFirstWaypoint()]
            #return task.again
        if self.state=="STOP":
            self.nextWaypoint=self.waypoints[random.choice(valid_waypoints)]
            return task.again
        best_distance=9000000
        target_node=None
        for target in self.PC.myWaypoints:
            for valid in valid_waypoints:
                distance=self.waypoints_data[target][valid]
                #print "target->valid=",target, valid, distance
                if distance<best_distance:
                    best_distance=distance
                    target_node=valid
        if target_node:
            self.nextWaypoint=self.waypoints[target_node]
        else:
            #print "no target", valid_waypoints
            self.nextWaypoint=self.findFirstWaypoint()
            #self.waypoints[random.choice(valid_waypoints)]
            #print self.nextWaypoint
        return task.again

    def runAI(self, task):
        #print self.state
        if self.state=="DIE":
            self.coll_sphere.node().setIntoCollideMask(BitMask32.allOff())
            self.coll_quad.removeNode()
            self.actor.play("die")
            self.common["kills"]-=1
            if self.common["kills"]==0:
                Interactive(self.common, data.items['key'], self.node.getPos(render))                    
            elif random.randrange(10)==0:
                Interactive(self.common, data.items['potion'], self.node.getPos(render))                 
            Sequence(Wait(2.0),LerpPosInterval(self.node, 2.0, VBase3(self.node.getX(),self.node.getY(),self.node.getZ()-5)),Func(self.destroy)).start()
            return task.done
        elif self.state=="STOP":
            target=self.nextWaypoint
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target)>0.3:
               self.node.setY(self.node, self.totalSpeed*globalClock.getDt())
               if(self.actor.getCurrentAnim()!="walk"):
                   self.actor.loop("walk")
            return task.again
        elif self.state=="ATTACK":
            self.node.headsUp(self.PC.node)
            if(self.actor.getCurrentAnim()!="attack"):
                self.actor.play("attack")
                #Sequence(Wait(self.attack_pattern[-1]+self.speed_mode), Func(self.attack, list(self.attack_pattern))).start()
                Sequence(Wait(self.attack_pattern[-1]), Func(self.attack, list(self.attack_pattern))).start()
            return task.again
        elif self.state=="SEEK":
            if self.PCisInRange:
                self.state="ATTACK"
                return task.again
            target=self.nextWaypoint
            if self.canSeePC and self.PC.HP>0:
                target=self.PC.node
                #print "target pc!"
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target)>0.3:
               self.node.setY(self.node, self.totalSpeed*globalClock.getDt())
               if(self.actor.getCurrentAnim()!="walk"):
                   self.actor.loop("walk")
               return task.again
            else:
                #print "I'm stuck?"
                #print target
                #print self.canSeePC
                self.nextWaypoint=self.PC.node
                return task.again

    def destroy(self):
        #for sound in self.soundset:
        #    self.soundset[sound].stop()
        #print  "destroy:",
        #self.sound_node.reparentTo(render)
        #self.common['soundPool'].append([self.sound_node,self.soundset])        
        self.common['soundPool'].set_free(self.soundID)
        #self.sounds=None
        #print  " sounds",
        self.arrows=None
        if self.actor:
            self.actor.cleanup()
            self.actor.removeNode()
            #print  " actor",
        if taskMgr.hasTaskNamed("AIfor"+str(self.id)):
            taskMgr.remove("AIfor"+str(self.id))
            #print  " AI",
        if taskMgr.hasTaskNamed('collFor'+str(self.id)):
            taskMgr.remove('collFor'+str(self.id))
            #print  " collision",
        if taskMgr.hasTaskNamed('DOTfor'+str(self.id)):
            taskMgr.remove('DOTfor'+str(self.id))
        if self.node:
            self.node.removeNode()
            #print  " node",
        self.monsterList[self.id]=None
        self.traverser=None
        self.queue=None
class Agent:
    def __init__(self, _name):
        print "Creating agent " + _name
        self.name = _name
        self.loadLightingFromConfig = 0
        self.createShadowMap = 0

    def setDataPath(self, _dataPath):
        self.dataPath = _dataPath

    def setActor(self, _modelFileName, _animationFileNames, _morphTargetsFileName):
        self.modelFileName = _modelFileName
        self.animationFileNames = _animationFileNames
        self.morphTargetsFileName = _morphTargetsFileName

    def setRealizer(self, _realizer):
        self.realizer = _realizer

    def setCameraMask(self, _mask):
        self.cameraMask = _mask

    def setShadowMapParameters(self, _index, _distance):
        self.createShadowMap = 1
        self.shadowMapIndex = _index
        self.shadowMapDistance = _distance

    def setTransform(self, x, y, z, rx, ry, rz, scale):
        self.agent.setPos(x, y, z)
        self.agent.setScale(scale)
        self.agent.setHpr(rx, ry, rz)
        self.positionX = x
        self.positionY = y
        self.positionZ = z

    def getPosition(self):
        return self.agent.getPos()

    def setLightingConfiguration(self, _config, _name):
        self.lightingConfig = _config
        self.lightingConfigName = _name
        self.loadLightingFromConfig = 1

    def init(self):
        # load the agent and parent it to the world
        # The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it
        self.animationAgent = Actor(self.modelFileName, self.animationFileNames)

        self.agent = Actor(self.modelFileName, self.morphTargetsFileName)

        self.targets = {  #'Basis':[],
            "ExpSmileClosed": [],
            "ExpAnger": [],
            "ExpDisgust": [],
            "ExpFear": [],
            "ExpSad": [],
            "ExpSurprise": [],
            "ExpSmileOpen": [],
            "ModBlinkLeft": [],
            "ModBlinkRight": [],
            "ModBrowDownLeft": [],
            "ModBrowDownRight": [],
            "ModBlinkRight": [],
            "ModBrowInRight": [],
            "ModBrowInLeft": [],
            "ModBrowUpLeft": [],
            "ModBrowUpRight": [],
            "ModEarsOut": [],
            "ModEyeSquintLeft": [],
            "ModEyeSquintRight": [],
            "ModLookDown": [],
            "ModLookLeft": [],
            "ModLookRight": [],
            "ModLookUp": [],
            "ModBlinkLeft": [],
            "Phonaah": [],
            "PhonB,M,P": [],
            "Phonbigaah": [],
            "Phonch,J,sh": [],
            "PhonD,S,T": [],
            "Phonee": [],
            "Phoneh": [],
            "PhonF,V": [],
            "Phoni": [],
            "PhonK": [],
            "PhonN": [],
            "Phonoh": [],
            "Phonooh,Q": [],
            "PhonR": [],
            "Phonth": [],
            "PhonW": [],
        }

        iter = self.targets.iteritems()
        while True:
            try:
                morphsItem = iter.next()
            except StopIteration:
                break
            for i in range(2, 7):
                # print (str(i)+'_'+morphsItem[0])
                blendShape = self.agent.controlJoint(None, "modelRoot", str(i) + "_" + morphsItem[0])
                if blendShape:
                    morphsItem[1].append(blendShape)

        self.targets["inspire"] = [self.agent.controlJoint(None, "modelRoot", "inspire")]

        # instanciate a list in order to keep track of kinematic joints joints
        # in python runtime
        # if nothing points towards those joints, they get flushed by
        # python's garbage collector
        self.jointList = []
        self.jointFKList = []
        self.agentControlJoints = []
        self.agentNodePaths = []

        self.agentSMRSkel = SMRPy.SMRSkeleton(True, True, "agent")
        self.createSkel(self.agent, self.agentSMRSkel, "root", "")
        # SMRPy.exportSkeletonToBvh('exportedPose.bvh',self.agentSMRSkel);
        self.newSkeleton = SMRPy.SMRSkeleton(True, True, "pose")
        self.createFKSkel(self.animationAgent, self.newSkeleton, "root", "")

        self.realizer.addCharacter(self.name, self.agentSMRSkel)

        for key in self.targets.keys():
            self.realizer.addMorphTarget(self.name, key)

        self.realizer.addShaderParameter(self.name, "blushing")

        self.addAnimation(self.name, "breathing")
        self.addAnimation(self.name, "hands_claw")
        self.addAnimation(self.name, "hands_fist")
        self.addAnimation(self.name, "hands_index")
        self.addAnimation(self.name, "hands_open-relaxed")
        self.addAnimation(self.name, "hands_open-spread")
        self.addAnimation(self.name, "hands_open-straight")
        self.addAnimation(self.name, "hands_purse")
        self.addAnimation(self.name, "hands_ring")
        self.addAnimation(self.name, "poseNeutral")
        # self.addAnimation(self.name,'endian')

        if "default" in self.animationFileNames:
            self.addAnimation(self.name, "default")

        # self.realizer.addCharacterSkeleton( self.name,  );

        self.agent.reparentTo(render)
        self.agent.hide(BitMask32.bit(self.cameraMask))

        # set lighting
        ambientColor = Vec4(0.0, 0.0, 0.0, 0.0)
        self.lighting = shaders.Lighting(ambientColor, self.agent)
        if self.loadLightingFromConfig == 1:
            self.lighting.loadFromConfig(self.lightingConfig, self.lightingConfigName)

        # shadow map
        if self.createShadowMap == 1:
            self.shadowMap = shadowmap.ShadowMap(self.shadowMapIndex, self.dataPath)

    def setShaders(self, _shaders):
        self.shaders = _shaders

    def update(self):
        self.realizer.skeletonRequested()
        self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel)

        for key in self.targets.keys():
            # print(key, "\n")
            weight = self.realizer.getMorphTargetWeight(self.name, key)
            morphTargets = self.targets[key]
            for morphTarget in morphTargets:
                # print(weight, "\n")
                morphTarget.setX(weight)

        # blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' )
        # self.shaders.headShader.blushing.set( blushingValue )

        self.lighting.update()
        if self.createShadowMap == 1:
            self.shadowMap.setLighting(
                self.lighting, Vec3(self.positionX, self.positionY, self.positionZ), self.shadowMapDistance
            )
            self.shaders.updateWithShadows(self.shadowMap)
        else:
            self.shaders.update()

    def addAnimation(self, _actorName, _animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range(self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName, i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation", _animationName, "added"

    def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName):
        # get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaCJoint = _pandaAgent.controlJoint(None, "modelRoot", _initialJointName)
        self.agentControlJoints.append(currentPandaCJoint)
        # get the first joint's position
        position = currentPandaCJoint.getPos()

        if currentPandaJoint[0].getNumChildren() == 0:
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(), position.getZ())
        else:
            newJoint = SMRPy.SMRJoint(False)

        rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159
        rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159
        rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159

        quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 0.0, 1.0), rotZ)
        quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0, 0.0, 0.0), rotX)
        quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 1.0, 0.0), rotY)

        quatRot = quatZ.multiply(quatX)
        quatRot = quatRot.multiply(quatY)
        quatRot.normalize()

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        newJoint.setRotQuat(quatRot.getW(), quatRot.getX(), quatRot.getY(), quatRot.getZ())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        # print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

        self.jointList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            # print(childName)
            self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName)

    def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName):
        # get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaJointPath = _pandaAgent.exposeJoint(None, "modelRoot", _initialJointName, "lodRoot", True)

        # currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName)
        # if (_parentName == 'root' or _parentName == '' or _parentName == 'Bone.001'):
        #    currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName)
        # else:
        #    print(_parentName)
        #    currentPandaJointPath = _pandaAgent.exposeJoint(None, _parentName, _initialJointName)

        # if (_initialJointName == "lhand"):
        #    self.rhand = currentPandaJointPath

        self.agentNodePaths.append(currentPandaJointPath)

        # get the first joint's position
        position = currentPandaJointPath.getPos()

        if currentPandaJoint[0].getNumChildren() == 0:
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(), position.getZ())
        else:
            newJoint = SMRPy.SMRJoint(False)

        quatRot = currentPandaJointPath.getQuat()

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        newJoint.setRotQuat(quatRot.getR(), quatRot.getI(), quatRot.getJ(), quatRot.getK())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        # print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

        self.jointFKList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            # print(childName)
            self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName)

    def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton):

        # synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentControlJoints[0]
        position = SMRJoint.getPos()
        # PANDAJoint.setPos(position.X() + 0.65 ,position.Y()-0.35,position.Z() - 1.4);
        PANDAJoint.setPos(position.X(), position.Y(), position.Z())

        for i in range(_smrSkeleton.getNumjoints()):
            SMRJoint = _smrSkeleton.getJoint(i)
            PANDAJoint = agentControlJoints[i]
            self.synchronize(PANDAJoint, SMRJoint)

    def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton):
        # synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentNodePaths[0]
        position = PANDAJoint.getPos()
        SMRJoint.setPos(position.getX(), position.getY(), position.getZ())

        for i in range(_smrSkeleton.getNumjoints()):
            SMRJoint = _smrSkeleton.getJoint(i)
            PANDAJoint = agentNodePaths[i]
            self.synchronizePandaToSMR(SMRJoint, PANDAJoint)

    def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint):
        pandaQuaternion = _PANDAJoint.getQuat()
        x = pandaQuaternion.getI()
        y = pandaQuaternion.getJ()
        z = pandaQuaternion.getK()
        w = pandaQuaternion.getR()
        _SMRJoint.setRotQuat(w, x, y, z)

    def synchronize(self, _pandaCJoint, _smrJoint):
        smrQuaternion = _smrJoint.getRot()
        pandaQuaternion = Quat()
        pandaQuaternion.setI(smrQuaternion.getX())
        pandaQuaternion.setJ(smrQuaternion.getY())
        pandaQuaternion.setK(smrQuaternion.getZ())
        pandaQuaternion.setR(smrQuaternion.getW())
        if not (pandaQuaternion.isNan()):
            _pandaCJoint.setQuat(pandaQuaternion)
Beispiel #27
0
class PlayerBase(DirectObject):
    def __init__(self):
        # Player Model setup
        self.player = Actor("Player",
                            {"Run":"Player-Run",
                            "Sidestep":"Player-Sidestep",
                            "Idle":"Player-Idle"})
        self.player.setBlend(frameBlend = True)
        self.player.setPos(0, 0, 0)
        self.player.pose("Idle", 0)
        self.player.reparentTo(render)
        self.player.hide()

        self.footstep = base.audio3d.loadSfx('footstep.ogg')
        self.footstep.setLoop(True)
        base.audio3d.attachSoundToObject(self.footstep, self.player)

        # Create a brush to paint on the texture
        splat = PNMImage("../data/Splat.png")
        self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1)

        CamMask = BitMask32.bit(0)
        AvBufMask = BitMask32.bit(1)
        self.avbuf = None
        if base.win:
            self.avbufTex = Texture('avbuf')
            self.avbuf = base.win.makeTextureBuffer('avbuf', 256, 256, self.avbufTex, True)
            cam = Camera('avbuf')
            cam.setLens(base.camNode.getLens())
            self.avbufCam = base.cam.attachNewNode(cam)
            dr = self.avbuf.makeDisplayRegion()
            dr.setCamera(self.avbufCam)
            self.avbuf.setActive(False)
            self.avbuf.setClearColor((1, 0, 0, 1))
            cam.setCameraMask(AvBufMask)
            base.camNode.setCameraMask(CamMask)

            # avbuf renders everything it sees with the gradient texture.
            tex = loader.loadTexture('gradient.png')
            np = NodePath('np')
            np.setTexture(tex, 100)
            np.setColor((1, 1, 1, 1), 100)
            np.setColorScaleOff(100)
            np.setTransparency(TransparencyAttrib.MNone, 100)
            np.setLightOff(100)
            cam.setInitialState(np.getState())
            #render.hide(AvBufMask)

        # Setup a texture stage to paint on the player
        self.paintTs = TextureStage('paintTs')
        self.paintTs.setMode(TextureStage.MDecal)
        self.paintTs.setSort(10)
        self.paintTs.setPriority(10)

        self.tex = Texture('paint_av_%s'%id(self))

        # Setup a PNMImage that will hold the paintable texture of the player
        self.imageSizeX = 64
        self.imageSizeY = 64
        self.p = PNMImage(self.imageSizeX, self.imageSizeY, 4)
        self.p.fill(1)
        self.p.alphaFill(0)
        self.tex.load(self.p)
        self.tex.setWrapU(self.tex.WMClamp)
        self.tex.setWrapV(self.tex.WMClamp)

        # Apply the paintable texture to the avatar
        self.player.setTexture(self.paintTs, self.tex)

        # team
        self.playerTeam = ""
        # A lable that will display the players team
        self.lblTeam = DirectLabel(
            scale = 1,
            pos = (0, 0, 3),
            frameColor = (0, 0, 0, 0),
            text = "TEAM",
            text_align = TextNode.ACenter,
            text_fg = (0,0,0,1))
        self.lblTeam.reparentTo(self.player)
        self.lblTeam.setBillboardPointEye()

        # basic player values
        self.maxHits = 3
        self.currentHits = 0
        self.isOut = False

        self.TorsorControl = self.player.controlJoint(None,"modelRoot","Torsor")

        # setup the collision detection
        # wall and object collision
        self.playerSphere = CollisionSphere(0, 0, 1, 1)
        self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision%d"%id(self)))
        self.playerCollision.node().addSolid(self.playerSphere)
        base.pusher.addCollider(self.playerCollision, self.player)
        base.cTrav.addCollider(self.playerCollision, base.pusher)
        # foot (walk) collision
        self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision%d"%id(self)))
        self.playerFootRay.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -1))
        self.playerFootRay.node().setIntoCollideMask(0)
        self.lifter = CollisionHandlerFloor()
        self.lifter.addCollider(self.playerFootRay, self.player)
        base.cTrav.addCollider(self.playerFootRay, self.lifter)

        # Player weapon setup
        self.gunAttach = self.player.exposeJoint(None, "modelRoot", "WeaponSlot_R")
        self.color = LPoint3f(1, 1, 1)
        self.gun = Gun(id(self))
        self.gun.reparentTo(self.gunAttach)
        self.gun.hide()
        self.gun.setColor(self.color)

        self.hud = None

        # Player controls setup
        self.keyMap = {"left":0, "right":0, "forward":0, "backward":0}
        # screen sizes
        self.winXhalf = base.win.getXSize() / 2
        self.winYhalf = base.win.getYSize() / 2
        self.mouseSpeedX = 0.1
        self.mouseSpeedY = 0.1
        # AI controllable variables
        self.AIP = 0.0
        self.AIH = 0.0

        self.movespeed = 5.0

        self.userControlled = False

        self.accept("Bulet-hit-playerCollision%d" % id(self), self.hit)
        self.accept("window-event", self.recalcAspectRatio)

    def runBase(self):
        self.player.show()
        self.gun.show()
        taskMgr.add(self.move, "moveTask%d"%id(self), priority=-4)

    def stopBase(self):
        taskMgr.remove("moveTask%d"%id(self))
        self.ignoreAll()
        self.gun.remove()
        self.footstep.stop()
        base.audio3d.detachSound(self.footstep)
        self.player.delete()

    def setKey(self, key, value):
        self.keyMap[key] = value

    def setPos(self, pos):
        self.player.setPos(pos)

    def setColor(self, color=LPoint3f(0,0,0)):
        self.color = color
        self.gun.setColor(color)
        c = (color[0], color[1], color[2], 1.0)
        self.lblTeam["text_fg"] = c

    def setTeam(self, team):
        self.playerTeam = team
        self.lblTeam["text"] = team


    def shoot(self, shotVec=None):
        self.gun.shoot(shotVec)
        if self.hud != None:
            self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition)

    def reload(self):
        self.gun.reload()
        if self.hud != None:
            self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition)

    def recalcAspectRatio(self, window):
        self.winXhalf = window.getXSize() / 2
        self.winYhalf = window.getYSize() / 2

    def hit(self, entry, color):
        self.currentHits += 1

        # Create a brush to paint on the texture
        splat = PNMImage("../data/Splat.png")
        splat = splat * LColorf(color[0], color[1], color[2], 1.0)
        self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1)

        self.paintAvatar(entry)

        if self.currentHits >= self.maxHits:
            base.messenger.send("GameOver-player%d" % id(self))
            self.isOut = True

    def __paint(self, s, t):
        """ Paints a point on the avatar at texture coordinates (s, t). """
        x = (s * self.p.getXSize())
        y = ((1.0 - t) * self.p.getYSize())

        # Draw in color directly on the avatar
        p1 = PNMPainter(self.p)
        p1.setPen(self.colorBrush)
        p1.drawPoint(x, y)

        self.tex.load(self.p)
        self.tex.setWrapU(self.tex.WMClamp)
        self.tex.setWrapV(self.tex.WMClamp)

        self.paintDirty = True

    def paintAvatar(self, entry):
        """ Paints onto an avatar.  Returns true on success, false on
        failure (because there are no avatar pixels under the mouse,
        for instance). """

        # First, we have to render the avatar in its false-color
        # image, to determine which part of its texture is under the
        # mouse.
        if not self.avbuf:
            return False

        #mpos = base.mouseWatcherNode.getMouse()
        mpos = entry.getSurfacePoint(self.player)
        ppos = entry.getSurfacePoint(render)

        self.player.showThrough(BitMask32.bit(1))
        self.avbuf.setActive(True)
        base.graphicsEngine.renderFrame()
        self.player.show(BitMask32.bit(1))
        self.avbuf.setActive(False)

        # Now we have the rendered image in self.avbufTex.
        if not self.avbufTex.hasRamImage():
            print "Weird, no image in avbufTex."
            return False
        p = PNMImage()
        self.avbufTex.store(p)
        ix = int((1 + mpos.getX()) * p.getXSize() * 0.5)
        iy = int((1 - mpos.getY()) * p.getYSize() * 0.5)
        x = 1
        if ix >= 0 and ix < p.getXSize() and iy >= 0 and iy < p.getYSize():
            s = p.getBlue(ix, iy)
            t = p.getGreen(ix, iy)
            x = p.getRed(ix, iy)
        if x > 0.5:
            # Off the avatar.
            return False

        # At point (s, t) on the avatar's map.

        self.__paint(s, t)
        return True

    def move(self, task):
        if self is None: return task.done
        if self.userControlled:
            if not base.mouseWatcherNode.hasMouse(): return task.cont
            self.pointer = base.win.getPointer(0)
            mouseX = self.pointer.getX()
            mouseY = self.pointer.getY()

            if base.win.movePointer(0, self.winXhalf, self.winYhalf):
                p = self.TorsorControl.getP() + (mouseY - self.winYhalf) * self.mouseSpeedY
                if p <-80:
                    p = -80
                elif p > 90:
                    p = 90
                self.TorsorControl.setP(p)

                h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX
                if h <-360:
                    h = 360
                elif h > 360:
                    h = -360
                self.player.setH(h)
        else:
            self.TorsorControl.setP(self.AIP)
            self.player.setH(self.AIH)

        forward =  self.keyMap["forward"] != 0
        backward = self.keyMap["backward"] != 0

        if self.keyMap["left"] != 0:
            if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward):
                self.player.loop("Sidestep")
                self.player.setPlayRate(5, "Sidestep")
            self.player.setX(self.player, self.movespeed * globalClock.getDt())
        elif self.keyMap["right"] != 0:
            if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward):
                self.player.loop("Sidestep")
                self.player.setPlayRate(5, "Sidestep")
            self.player.setX(self.player, -self.movespeed * globalClock.getDt())
        else:
            self.player.stop("Sidestep")
        if forward:
            if self.player.getCurrentAnim() != "Run":
                self.player.loop("Run")
                self.player.setPlayRate(5, "Run")
            self.player.setY(self.player, -self.movespeed * globalClock.getDt())
        elif backward:
            if self.player.getCurrentAnim() != "Run":
                self.player.loop("Run")
                self.player.setPlayRate(-5, "Run")
            self.player.setY(self.player, self.movespeed * globalClock.getDt())
        else:
            self.player.stop("Run")

        if not (self.keyMap["left"] or self.keyMap["right"] or
                self.keyMap["forward"] or self.keyMap["backward"] or
                self.player.getCurrentAnim() == "Idle"):
            self.player.loop("Idle")
            self.footstep.stop()
        else:
            self.footstep.play()

        return task.cont
class Agent:
    def __init__(self, _name):
        print "Creating agent " + _name
        self.name = _name

    def setDataPath(self, _dataPath):
        self.dataPath = _dataPath

    def setActor(self, _modelFileName, _animationFileNames,
                 _morphTargetsFileName):
        self.modelFileName = _modelFileName
        self.animationFileNames = _animationFileNames
        self.morphTargetsFileName = _morphTargetsFileName

    def setRealizer(self, _realizer):
        self.realizer = _realizer

    def setTransform(self, x, y, z, rx, ry, rz, scale):
        self.agent.setPos(x, y, z)
        self.agent.setScale(scale)
        self.agent.setHpr(rx, ry, rz)
        self.positionX = x
        self.positionY = y
        self.positionZ = z

    def getPosition(self):
        return self.agent.getPos()

    def init(self):
        #load the agent and parent it to the world
        #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it
        self.animationAgent = Actor(self.modelFileName,
                                    self.animationFileNames)

        self.agent = Actor(self.modelFileName, self.morphTargetsFileName)

        maxMorphTargets = {
            'MT_Jaw_Open':
            self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Open'),
            'MT_Jaw_L':
            self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_L'),
            'MT_Jaw_R':
            self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_R'),
            'MT_Jaw_Fwd':
            self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Fwd'),
            'MT_WideL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_WideL'),
            'MT_WideR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_WideR'),
            'MT_NarrowL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowL'),
            'MT_NarrowR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowR'),
            'MT_FrownL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_FrownL'),
            'MT_FrownR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_FrownR'),
            'MT_SneerL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_SneerL'),
            'MT_SneerR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_SneerR'),
            'MT_SquintL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_SquintL'),
            'MT_SquintR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_SquintR'),
            'MT_BrowUpL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpL'),
            'MT_BrowUpR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpR'),
            'MT_BrowDnL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'),
            'MT_BrowDnR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'),
            'MT_MBrowUp':
            self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowUp'),
            'MT_BrowDnR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'),
            'MT_BrowDnL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'),
            'MT_MBrowDn':
            self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowDn'),
            'MT_BrowSqueeze':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BrowSqueeze'),
            'MT_MouthL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_MouthL'),
            'MT_MouthR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_MouthR'),
            'MT_UprLipUpL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpL'),
            'MT_UprLipUpR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpR'),
            'MT_UprLipDnL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnL'),
            'MT_UprLipDnR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnR'),
            'MT_LwrLipUpL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpL'),
            'MT_LwrLipUpR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpR'),
            'MT_LwrLipDnL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnL'),
            'MT_LwrLipDnR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnR'),
            'MT_BlowCheeksL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksL'),
            'MT_BlowCheeksR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksR'),
            'MT_TongueOut':
            self.agent.controlJoint(None, 'modelRoot', 'MT_TongueOut'),
            'MT_TongueUp':
            self.agent.controlJoint(None, 'modelRoot', 'MT_TongueUp'),
            'MT_TongueTipUp':
            self.agent.controlJoint(None, 'modelRoot', 'MT_TongueTipUp'),
            'MT_TongueL':
            self.agent.controlJoint(None, 'modelRoot', 'MT_TongueL'),
            'MT_TongueR':
            self.agent.controlJoint(None, 'modelRoot', 'MT_TongueR'),
            'MT_Blink_L':
            self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_L'),
            'MT_Blink_R':
            self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_R')
        }

        self.targets = {  #'Basis':[],                
            'ExpSmileClosed': {
                maxMorphTargets['MT_WideR']: 1.0,
                maxMorphTargets['MT_WideL']: 1.0
            },
            'ExpAnger': {
                maxMorphTargets['MT_Jaw_Open']: -0.07,
                maxMorphTargets['MT_Jaw_Fwd']: 0.25,
                maxMorphTargets['MT_NarrowL']: 0.30,
                maxMorphTargets['MT_NarrowR']: 0.30,
                maxMorphTargets['MT_SquintL']: 0.60,
                maxMorphTargets['MT_SquintR']: 0.60,
                maxMorphTargets['MT_MBrowDn']: 1.0,
                maxMorphTargets['MT_BrowDnL']: 0.7,
                maxMorphTargets['MT_BrowDnR']: 0.7,
                maxMorphTargets['MT_SneerL']: 0.8,
                maxMorphTargets['MT_SneerR']: 0.8,
                maxMorphTargets['MT_FrownL']: 0.2,
                maxMorphTargets['MT_FrownR']: 0.2,
                maxMorphTargets['MT_UprLipDnL']: 0.45,
                maxMorphTargets['MT_UprLipDnR']: 0.45,
                maxMorphTargets['MT_LwrLipUpL']: 1.0,
                maxMorphTargets['MT_LwrLipUpR']: 1.0
            },
            'ExpDisgust': {
                maxMorphTargets['MT_WideL']: 0.25,
                maxMorphTargets['MT_WideR']: 0.15,
                maxMorphTargets['MT_SquintL']: 0.40,
                maxMorphTargets['MT_SquintR']: 0.40,
                maxMorphTargets['MT_MBrowDn']: 0.25,
                maxMorphTargets['MT_BrowSqueeze']: 0.45,
                maxMorphTargets['MT_WideL']: 0.25,
                maxMorphTargets['MT_BrowDnL']: 0.50,
                maxMorphTargets['MT_BrowDnR']: 0.50,
                maxMorphTargets['MT_SneerL']: 2.0,
                maxMorphTargets['MT_SneerR']: 2.0,
                maxMorphTargets['MT_FrownL']: 0.25,
                maxMorphTargets['MT_FrownR']: 0.25,
                maxMorphTargets['MT_UprLipUpL']: 0.66,
                maxMorphTargets['MT_UprLipUpR']: 0.33,
                maxMorphTargets['MT_LwrLipUpL']: 0.40,
                maxMorphTargets['MT_LwrLipUpR']: 0.40
            },
            'ExpFear': {
                maxMorphTargets['MT_Jaw_Open']: 0.15,
                maxMorphTargets['MT_Jaw_Fwd']: -0.3,
                maxMorphTargets['MT_NarrowL']: 0.24,
                maxMorphTargets['MT_NarrowR']: 0.24,
                maxMorphTargets['MT_SquintL']: -0.4,
                maxMorphTargets['MT_SquintR']: -0.4,
                maxMorphTargets['MT_BrowUpL']: 0.36,
                maxMorphTargets['MT_BrowUpR']: 0.36,
                maxMorphTargets['MT_MBrowUp']: 1.30,
                maxMorphTargets['MT_BrowSqueeze']: 0.40,
                maxMorphTargets['MT_FrownL']: 0.35,
                maxMorphTargets['MT_FrownR']: 0.35,
                maxMorphTargets['MT_UprLipDnL']: 0.25,
                maxMorphTargets['MT_UprLipDnR']: 0.25,
                maxMorphTargets['MT_LwrLipUpL']: 0.35,
                maxMorphTargets['MT_LwrLipUpR']: 0.35
            },
            'ExpSad': {
                maxMorphTargets['MT_NarrowL']: 0.20,
                maxMorphTargets['MT_NarrowR']: 0.20,
                maxMorphTargets['MT_SquintL']: 0.20,
                maxMorphTargets['MT_SquintR']: 0.20,
                maxMorphTargets['MT_MBrowUp']: 0.40,
                maxMorphTargets['MT_BrowSqueeze']: 0.66,
                maxMorphTargets['MT_BrowDnL']: 0.66,
                maxMorphTargets['MT_BrowDnR']: 0.66,
                maxMorphTargets['MT_BlowCheeksL']: -0.25,
                maxMorphTargets['MT_BlowCheeksR']: -0.25,
                maxMorphTargets['MT_FrownL']: 0.66,
                maxMorphTargets['MT_FrownR']: 0.66,
                maxMorphTargets['MT_UprLipDnL']: 0.50,
                maxMorphTargets['MT_UprLipDnR']: 0.50,
                maxMorphTargets['MT_LwrLipUpL']: 0.66,
                maxMorphTargets['MT_LwrLipUpR']: 0.66
            },
            'ExpSurprise': {
                maxMorphTargets['MT_Jaw_Open']: 0.25,
                maxMorphTargets['MT_NarrowL']: 0.24,
                maxMorphTargets['MT_NarrowR']: 0.24,
                maxMorphTargets['MT_SquintL']: -0.20,
                maxMorphTargets['MT_SquintR']: -0.20,
                maxMorphTargets['MT_BrowUpL']: 0.92,
                maxMorphTargets['MT_BrowUpR']: 0.92,
                maxMorphTargets['MT_MBrowUp']: 0.66
            },
            'ExpSmileOpen': {
                maxMorphTargets['MT_Jaw_Open']: 0.16,
                maxMorphTargets['MT_WideL']: 0.740,
                maxMorphTargets['MT_WideR']: 0.740,
                maxMorphTargets['MT_SneerL']: 0.280,
                maxMorphTargets['MT_SneerR']: 0.280,
                maxMorphTargets['MT_BrowUpL']: 0.360,
                maxMorphTargets['MT_BrowUpR']: 0.360
            },
            'ExpHappy': {
                maxMorphTargets['MT_Jaw_Open']: 0.22,
                maxMorphTargets['MT_WideL']: 0.75,
                maxMorphTargets['MT_WideR']: 0.75,
                maxMorphTargets['MT_SquintL']: 0.35,
                maxMorphTargets['MT_SquintR']: 0.35,
                maxMorphTargets['MT_BrowDnL']: 0.08,
                maxMorphTargets['MT_BrowDnR']: 0.08,
                maxMorphTargets['MT_UprLipUpL']: 0.15,
                maxMorphTargets['MT_UprLipUpR']: 0.15,
                maxMorphTargets['MT_LwrLipUpL']: 0.15,
                maxMorphTargets['MT_LwrLipUpR']: 0.15,
                maxMorphTargets['MT_BrowUpL']: 0.360,
                maxMorphTargets['MT_BrowUpR']: 0.360
            },
            'ModBlinkLeft': {
                maxMorphTargets['MT_Blink_L']: 1.0
            },
            'ModBlinkRight': {
                maxMorphTargets['MT_Blink_R']: 1.0
            },
            'ModBrowDownLeft': {
                maxMorphTargets['MT_BrowDnL']: 1.0
            },
            'ModBrowDownRight': {
                maxMorphTargets['MT_BrowDnR']: 1.0
            },
            'ModBrowInRight': {
                maxMorphTargets['MT_BrowSqueeze']: 1.0
            },
            'ModBrowInLeft': {
                maxMorphTargets['MT_BrowSqueeze']: 1.0
            },
            'ModBrowUpLeft': {
                maxMorphTargets['MT_BrowUpL']: 1.0
            },
            'ModBrowUpRight': {
                maxMorphTargets['MT_BrowUpR']: 1.0
            },
            #'ModEarsOut':[],
            'ModEyeSquintLeft': {
                maxMorphTargets['MT_SquintL']: 1.0
            },
            'ModEyeSquintRight': {
                maxMorphTargets['MT_SquintR']: 1.0
            },
            'Phonaah': {
                maxMorphTargets['MT_Jaw_Open']: 1.0
            },
            'PhonB,M,P': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5
            },
            'Phonbigaah': {
                maxMorphTargets['MT_Jaw_Open']: 1.0
            },
            'Phonch,J,sh': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5
            },
            'PhonD,S,T': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5,
                maxMorphTargets['MT_Jaw_Open']: 0.2
            },
            'Phonee': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5
            },
            'Phoneh': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5,
                maxMorphTargets['MT_Jaw_Open']: 0.2
            },
            'PhonF,V': {
                maxMorphTargets['MT_WideL']: 0.2,
                maxMorphTargets['MT_WideR']: 0.2,
                maxMorphTargets['MT_Jaw_Open']: 0.3,
                maxMorphTargets['MT_UprLipDnL']: 0.3,
                maxMorphTargets['MT_UprLipDnR']: 0.3
            },
            'Phoni': {
                maxMorphTargets['MT_WideL']: 0.2,
                maxMorphTargets['MT_WideR']: 0.2,
                maxMorphTargets['MT_Jaw_Open']: 0.3
            },
            'PhonK': {
                maxMorphTargets['MT_Jaw_Open']: 0.4
            },
            'PhonN': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5
            },
            'Phonoh': {
                maxMorphTargets['MT_Jaw_Open']: 0.4,
                maxMorphTargets['MT_NarrowL']: 0.55,
                maxMorphTargets['MT_NarrowR']: 0.55
            },
            'Phonooh,Q': {
                maxMorphTargets['MT_Jaw_Open']: 0.4,
                maxMorphTargets['MT_NarrowL']: 0.55,
                maxMorphTargets['MT_NarrowR']: 0.55
            },
            'PhonR': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5,
                maxMorphTargets['MT_Jaw_Open']: 0.2
            },
            'Phonth': {
                maxMorphTargets['MT_WideL']: 0.5,
                maxMorphTargets['MT_WideR']: 0.5,
                maxMorphTargets['MT_Jaw_Open']: 0.2
            },
            'PhonW': {
                maxMorphTargets['MT_Jaw_Open']: 0.3,
                maxMorphTargets['MT_NarrowL']: 0.7,
                maxMorphTargets['MT_NarrowR']: 0.7
            },
            'AU26_MT_Jaw_Open': {
                maxMorphTargets['MT_Jaw_Open']: 1.0
            },
            'AU30_MT_Jaw_L': {
                maxMorphTargets['MT_Jaw_L']: 1.0
            },
            'AU30_MT_Jaw_R': {
                maxMorphTargets['MT_Jaw_R']: 1.0
            },
            'AU31_MT_Jaw_Fwd': {
                maxMorphTargets['MT_Jaw_Fwd']: 1.0
            },
            'AU27_MT_WideL': {
                maxMorphTargets['MT_WideL']: 1.0
            },
            'AU27_MT_WideR': {
                maxMorphTargets['MT_WideR']: 1.0
            },
            'AU18_MT_NarrowL': {
                maxMorphTargets['MT_NarrowL']: 1.0
            },
            'AU18_MT_NarrowR': {
                maxMorphTargets['MT_NarrowL']: 1.0
            },
            'AU42_MT_FrownL': {
                maxMorphTargets['MT_FrownL']: 1.0
            },
            'AU42_MT_FrownR': {
                maxMorphTargets['MT_FrownR']: 1.0
            },
            'AU9_MT_SneerL': {
                maxMorphTargets['MT_SneerL']: 1.0
            },
            'AU9_MT_SneerR': {
                maxMorphTargets['MT_SneerR']: 1.0
            },
            'AU46_MT_SquintL': {
                maxMorphTargets['MT_SquintL']: 1.0
            },
            'AU46_MT_SquintR': {
                maxMorphTargets['MT_SquintR']: 1.0
            },
            'AU2_MT_BrowUpL': {
                maxMorphTargets['MT_BrowUpL']: 1.0
            },
            'AU2_MT_BrowUpR': {
                maxMorphTargets['MT_BrowUpR']: 1.0
            },
            'AU4_MT_BrowDnL': {
                maxMorphTargets['MT_BrowDnL']: 1.0
            },
            'AU4_MT_BrowDnR': {
                maxMorphTargets['MT_BrowDnR']: 1.0
            },
            'AU4_MT_MBrowUp': {
                maxMorphTargets['MT_MBrowUp']: 1.0
            },
            'AU1_MT_BrowDnR': {
                maxMorphTargets['MT_BrowDnR']: 1.0
            },
            'AU1_MT_BrowDnL': {
                maxMorphTargets['MT_BrowDnL']: 1.0
            },
            'AU1_MT_MBrowDn': {
                maxMorphTargets['MT_MBrowDn']: 1.0
            },
            'AU44_MT_BrowSqueeze': {
                maxMorphTargets['MT_BrowSqueeze']: 1.0
            },
            'AU12_MT_MouthL': {
                maxMorphTargets['MT_MouthL']: 1.0
            },
            'AU12_MT_MouthR': {
                maxMorphTargets['MT_MouthR']: 1.0
            },
            'AU5_MT_UprLipUpL': {
                maxMorphTargets['MT_UprLipUpL']: 1.0
            },
            'AU5_MT_UprLipUpR': {
                maxMorphTargets['MT_UprLipUpR']: 1.0
            },
            'MT_UprLipDnL': {
                maxMorphTargets['MT_UprLipDnL']: 1.0
            },
            'MT_UprLipDnR': {
                maxMorphTargets['MT_UprLipDnR']: 1.0
            },
            'MT_LwrLipUpL': {
                maxMorphTargets['MT_LwrLipUpL']: 1.0
            },
            'MT_LwrLipUpR': {
                maxMorphTargets['MT_LwrLipUpR']: 1.0
            },
            'MT_LwrLipDnL': {
                maxMorphTargets['MT_LwrLipDnL']: 1.0
            },
            'MT_LwrLipDnR': {
                maxMorphTargets['MT_LwrLipDnR']: 1.0
            },
            'AU33_MT_BlowCheeksL': {
                maxMorphTargets['MT_BlowCheeksL']: 1.0
            },
            'AU33_MT_BlowCheeksR': {
                maxMorphTargets['MT_BlowCheeksR']: 1.0
            },
            'AU36_MT_TongueOut': {
                maxMorphTargets['MT_TongueOut']: 1.0
            },
            'AU36_MT_TongueUp': {
                maxMorphTargets['MT_TongueUp']: 1.0
            },
            'AU36_MT_TongueTipUp': {
                maxMorphTargets['MT_TongueTipUp']: 1.0
            },
            'AU36_MT_TongueL': {
                maxMorphTargets['MT_TongueL']: 1.0
            },
            'AU36_MT_TongueR': {
                maxMorphTargets['MT_TongueR']: 1.0
            },
            'AU45_MT_Blink_L': {
                maxMorphTargets['MT_Blink_L']: 1.0
            },
            'AU45_MT_Blink_R': {
                maxMorphTargets['MT_Blink_R']: 1.0
            }
        }

        #instanciate a list in order to keep track of kinematic joints joints
        #in python runtime
        #if nothing points towards those joints, they get flushed by
        #python's garbage collector
        self.jointList = []
        self.jointFKList = []
        self.agentControlJoints = []
        self.agentNodePaths = []

        self.agentSMRSkel = SMRPy.SMRSkeleton(True, True, 'agent')
        self.createSkel(self.agent, self.agentSMRSkel, 'root', '')
        #Pascal: output of both skeletons amber and alfonse as chracter.bvh
        #SMRPy.exportSkeletonToBvh(self.name + '.bvh',self.agentSMRSkel);
        self.newSkeleton = SMRPy.SMRSkeleton(True, True, 'pose')
        self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '')
        self.realizer.addCharacter(self.name, self.agentSMRSkel)

        for key in self.targets.keys():
            self.realizer.addMorphTarget(
                self.name, key
            )  #TODO: declare morph targets into CharacterConfigurationFile

        #self.realizer.addShaderParameter( self.name, 'blushing' ) #TODO: declare shader inputs into CharacterConfiguration file

        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_claw',
            open('./animations/hands_claw.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_index',
            open('./animations/hands_index.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_open-relaxed',
            open('./animations/hands_open-relaxed.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_open-spread',
            open('./animations/hands_open-spread.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_open-straight',
            open('./animations/hands_open-straight.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_purse',
            open('./animations/hands_purse.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ring',
            open('./animations/hands_ring.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'poseNeutral',
            open('./animations/poseNeutral.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'shrug',
            open('./animations/shrug.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_A',
            open('./animations/hands_DGS_A.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_B',
            open('./animations/hands_DGS_B.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_C',
            open('./animations/hands_DGS_C.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_D',
            open('./animations/hands_DGS_D.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_E',
            open('./animations/hands_DGS_E.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_F',
            open('./animations/hands_DGS_F.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_G',
            open('./animations/hands_DGS_G.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_H',
            open('./animations/hands_DGS_H.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_I',
            open('./animations/hands_DGS_I.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_J',
            open('./animations/hands_DGS_J.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_K',
            open('./animations/hands_DGS_K.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_L',
            open('./animations/hands_DGS_L.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_M',
            open('./animations/hands_DGS_M.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_N',
            open('./animations/hands_DGS_N.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_O',
            open('./animations/hands_DGS_O.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_P',
            open('./animations/hands_DGS_P.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_Q',
            open('./animations/hands_DGS_Q.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_R',
            open('./animations/hands_DGS_R.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_T',
            open('./animations/hands_DGS_T.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_U',
            open('./animations/hands_DGS_U.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_W',
            open('./animations/hands_DGS_W.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_X',
            open('./animations/hands_DGS_X.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_Y',
            open('./animations/hands_DGS_Y.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_Z',
            open('./animations/hands_DGS_Z.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_DGS_SCH',
            open('./animations/hands_DGS_SCH.bvh', "r").read())

        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_A',
            open('./animations/hands_ASL_A.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_B',
            open('./animations/hands_ASL_B.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_C',
            open('./animations/hands_ASL_C.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_D',
            open('./animations/hands_ASL_D.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_E',
            open('./animations/hands_ASL_E.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_F',
            open('./animations/hands_ASL_F.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_G',
            open('./animations/hands_ASL_G.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_H',
            open('./animations/hands_ASL_H.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_I',
            open('./animations/hands_ASL_I.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_J',
            open('./animations/hands_ASL_J.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_K',
            open('./animations/hands_ASL_K.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_L',
            open('./animations/hands_ASL_L.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_M',
            open('./animations/hands_ASL_M.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_N',
            open('./animations/hands_ASL_N.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_O',
            open('./animations/hands_ASL_O.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_P',
            open('./animations/hands_ASL_P.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_Q',
            open('./animations/hands_ASL_Q.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_R',
            open('./animations/hands_ASL_R.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_T',
            open('./animations/hands_ASL_T.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_U',
            open('./animations/hands_ASL_U.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_V',
            open('./animations/hands_ASL_V.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_W',
            open('./animations/hands_ASL_W.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_X',
            open('./animations/hands_ASL_X.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_Y',
            open('./animations/hands_ASL_Y.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_Z',
            open('./animations/hands_ASL_Z.bvh', "r").read())

        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_1CL',
            open('./animations/hands_ASL_1CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_2CL',
            open('./animations/hands_ASL_2CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_3CL',
            open('./animations/hands_ASL_3CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_4CL',
            open('./animations/hands_ASL_4CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_5aCL',
            open('./animations/hands_ASL_5aCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_5bCL',
            open('./animations/hands_ASL_5bCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_ACL',
            open('./animations/hands_ASL_ACL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_BCL',
            open('./animations/hands_ASL_BCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_CCL',
            open('./animations/hands_ASL_CCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_FCL',
            open('./animations/hands_ASL_FCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_ICL',
            open('./animations/hands_ASL_ICL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_ILYCL',
            open('./animations/hands_ASL_ILYCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_SCL',
            open('./animations/hands_ASL_SCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_VaCL',
            open('./animations/hands_ASL_VaCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_VbCL',
            open('./animations/hands_ASL_VbCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_YCL',
            open('./animations/hands_ASL_YCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_CbCL',
            open('./animations/hands_ASL_CbCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(
            self.name, 'hands_ASL_TCL',
            open('./animations/hands_ASL_TCL.bvh', "r").read())

        firingstevenhigh = open('./animations/alfonse-FiringStevenHigh.bvh',
                                "r").read()

        self.realizer.addBVHMotionToCharacter(self.name, 'FiringStevenHigh',
                                              firingstevenhigh)

        print("done")

        self.agent.reparentTo(render)

    def update(self):
        self.realizer.skeletonRequested()
        skeletonHasBeenUpdated = False
        while (not skeletonHasBeenUpdated):
            #wait until skeleton can be displayed
            if (self.realizer.skeletonIsReadyToBeDisplayed(self.name)):
                self.updatePandaSkeleton(self.agentControlJoints,
                                         self.agentSMRSkel)
                skeletonHasBeenUpdated = True

        for key in self.realizer.getModifiedMorphTargets(
                self.name
        ):  #self.targets.keys(): # Only update the targets that have actually changed here
            #print key, "\n"
            weight = self.realizer.getMorphTargetWeight(self.name, key)
            morphTargets = self.targets[key]
            for morphTargetKey in morphTargets.keys():
                #print(weight*morphTargets[morphTargetKey])
                morphTargetKey.setX(weight * morphTargets[morphTargetKey])

        #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' )
        #self.shaders.headShader.blushing.set( blushingValue )

    def addAnimation(self, _actorName, _animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range(self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName, i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName,
                                             self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation", _animationName, "added"

    def addAnimationWE(self, _actorName, _animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        agentSMRMotion = SMRPy.SMRMotion()
        agentSMRMotion.setTimeStep(0.04)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range(self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName, i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName,
                                             self.newSkeleton)
            agentSMRMotion.insertSkeleton(self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation", _animationName, "added"
        SMRPy.exportMotionToBvh(_animationName + ".bvh", agentSMRMotion)

    def createSkel(self, _pandaAgent, _smrSkel, _initialJointName,
                   _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot',
                                                      _initialJointName)
        self.agentControlJoints.append(currentPandaCJoint)
        #get the first joint's position
        position = currentPandaCJoint.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(),
                                position.getZ())
        else:
            newJoint = SMRPy.SMRJoint(False)

        rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159
        rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159
        rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159

        quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 0.0, 1.0), rotZ)
        quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0, 0.0, 0.0), rotX)
        quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 1.0, 0.0), rotY)

        quatRot = quatZ.multiply(quatX)
        quatRot = quatRot.multiply(quatY)
        quatRot.normalize()

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        newJoint.setRotQuat(quatRot.getW(), quatRot.getX(), quatRot.getY(),
                            quatRot.getZ())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        self.jointList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createSkel(_pandaAgent, _smrSkel, childName,
                            _initialJointName)

    def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName,
                     _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaJointPath = _pandaAgent.exposeJoint(
            None, 'modelRoot', _initialJointName, "lodRoot", True)
        self.agentNodePaths.append(currentPandaJointPath)
        #get the first joint's position
        position = currentPandaJointPath.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(),
                                position.getZ())
        else:
            newJoint = SMRPy.SMRJoint(False)

        quatRot = currentPandaJointPath.getQuat()

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        newJoint.setRotQuat(quatRot.getR(), quatRot.getI(), quatRot.getJ(),
                            quatRot.getK())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        self.jointFKList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createFKSkel(_pandaAgent, _smrSkel, childName,
                              _initialJointName)

    def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton):

        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentControlJoints[0]
        position = SMRJoint.getPos()
        PANDAJoint.setPos(position.X(), position.Y(), position.Z())

        for i in range(_smrSkeleton.getNumjoints()):
            SMRJoint = _smrSkeleton.getJoint(i)
            PANDAJoint = agentControlJoints[i]
            self.synchronize(PANDAJoint, SMRJoint)

    def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton):
        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentNodePaths[0]
        position = PANDAJoint.getPos()
        SMRJoint.setPos(position.getX(), position.getY(), position.getZ())

        for i in range(_smrSkeleton.getNumjoints()):
            SMRJoint = _smrSkeleton.getJoint(i)
            PANDAJoint = agentNodePaths[i]
            self.synchronizePandaToSMR(SMRJoint, PANDAJoint)

    def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint):
        pandaQuaternion = _PANDAJoint.getQuat()
        x = pandaQuaternion.getI()
        y = pandaQuaternion.getJ()
        z = pandaQuaternion.getK()
        w = pandaQuaternion.getR()
        _SMRJoint.setRotQuat(w, x, y, z)

    def synchronize(self, _pandaCJoint, _smrJoint):
        smrQuaternion = _smrJoint.getRot()
        pandaQuaternion = Quat()
        pandaQuaternion.setI(smrQuaternion.getX())
        pandaQuaternion.setJ(smrQuaternion.getY())
        pandaQuaternion.setK(smrQuaternion.getZ())
        pandaQuaternion.setR(smrQuaternion.getW())
        if not (pandaQuaternion.isNan()):
            _pandaCJoint.setQuat(pandaQuaternion)
Beispiel #29
0
class Grenade (Projectile):
    def __init__(self, pos, hpr, color, walker_v, name=None):
        super(Grenade, self).__init__(name)
        self.pos = Vec3(*pos)
        self.hpr = hpr
        self.move_divisor = 9
        self.color = color
        self.forward_m = .25
        self.walker_v = walker_v

    def create_node(self):
        self.model = Actor('grenade.egg')
        self.shell = self.model.find('**/shell')
        self.shell.set_color(*self.color)
        self.inner_top = self.model.find('**/inner_top')
        self.inner_bottom = self.model.find('**/inner_bottom')
        self.inner_top.set_color(*random.choice(ENGINE_COLORS))
        self.inner_bottom.set_color(*random.choice(ENGINE_COLORS))
        self.model.set_scale(GRENADE_SCALE)
        self.model.set_hpr(0,0,0)
        self.spin_bone = self.model.controlJoint(None, 'modelRoot', 'grenade_bone')
        return self.model

    def create_solid(self):
        node = BulletRigidBodyNode(self.name)
        node.set_angular_damping(.9)
        node_shape = BulletSphereShape(.08)
        node.add_shape(node_shape)
        node.set_mass(.5)
        return node

    def attached(self):
        self.node.set_pos(self.pos)
        self.node.set_hpr(self.hpr)
        self.world.register_updater(self)
        self.world.register_collider(self)
        self.solid.setIntoCollideMask(NO_COLLISION_BITS)
        self.solid.set_gravity(DEFAULT_GRAVITY*4.5)
        grenade_iv = render.get_relative_vector(self.node, Vec3(0,8.5,13.5))
        grenade_iv += (self.walker_v * 1/2)
        self.solid.apply_impulse(grenade_iv, Point3(*self.pos))

    def decompose(self):
        clist = list(self.color)
        clist.extend([1])
        expl_colors = [clist]
        expl_colors.extend(ENGINE_COLORS)
        expl_pos = self.node.get_pos(self.world.render)
        for c in expl_colors:
            self.world.attach(TriangleExplosion(expl_pos, 1, size=.1, color=c, lifetime=40))
        self.world.garbage.add(self)

    def update(self, dt):
        self.inner_top.set_color(*random.choice(ENGINE_COLORS))
        self.inner_bottom.set_color(*random.choice(ENGINE_COLORS))
        result = self.world.physics.contact_test(self.solid)
        self.spin_bone.set_hpr(self.spin_bone, 0,0,10)
        contacts = result.getContacts()
        if len(contacts) > 0:
            hit_node = contacts[0].get_node1().get_name()
            if hit_node.endswith("_walker_cap"):
                return
            clist = list(self.color)
            clist.extend([1])
            expl_colors = [clist]
            expl_colors.extend(ENGINE_COLORS)
            expl_pos = self.node.get_pos(self.world.render)
            for c in expl_colors:
                self.world.attach(TriangleExplosion(expl_pos, 3, size=.1, color=c, lifetime=80,))
            self.world.do_explosion(self.node, 3, 100)
            self.world.garbage.add(self)
Beispiel #30
0
class WatchMe(ShowBase):
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)

        # Put the standard title and instruction text on screen
        self.modeText = OnscreenText(text="Optical Flow",
                                     fg=(1, 1, 1, 1),
                                     parent=base.a2dBottomRight,
                                     align=TextNode.ARight,
                                     pos=(-0.1, 0.1),
                                     shadow=(0, 0, 0, .5),
                                     scale=.08)

        instr0 = addInstructions(0.06, "Press ESC to exit")
        instr1 = addInstructions(0.12, "Press 1: Facial Recognition")
        instr1 = addInstructions(0.18, "Press 2: Optical Flow")

        # Set up key input
        self.accept('escape', self.destroy)
        self.accept('1', self.chooseFacialRec)
        self.accept('2', self.chooseOpticalFlow)

        self.mode = 'opticalFlow'

        self.environ = loader.loadModel("models/world")
        self.environ.reparentTo(render)

        # Disable mouse-based camera-control
        base.disableMouse()

        self.eve = Actor("models/eve")

        self.eve.setScale(.7)
        self.eve.setPos(5, 5, 3)

        # Put it in the scene
        self.eve.reparentTo(render)

        self.camDistance = 15
        self.camHeight = 5

        # Position the camera
        camera.setPos(self.eve.getPos() +
                      (0, -1 * self.camDistance, self.camHeight))

        # Now we use controlJoint to get a NodePath that's in control of her neck
        # This must be done before any animations are played
        self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck')

        self.camera.lookAt(self.eve)
        self.camBaseZ = self.camera.getZ()
        self.camBaseX = self.camera.getX()

        self.pitchOffset = self.camDistance
        self.headingOffset = self.camDistance

        # Now we add a task that will take care of turning the head
        taskMgr.add(self.turnHead, "turnHead")

        # Put in some default lighting
        self.setupLights()

        self.video = cv2.VideoCapture(0)
        check, self.prev_frame = self.video.read()
        self.prev_frame = downsample(self.prev_frame)
        self.total_displacement = [0, 0]

        self.prev_face_x = None
        self.prev_face_y = None
        self.total_face_displacement = [0, 0]

        # Moving averages
        self.xQueueSize = 20
        self.xQueue = collections.deque([0, 0, 0, 0, 0], self.xQueueSize)
        self.xQueueSum = 0

        self.yQueueSize = 20
        self.yQueue = collections.deque([0, 0, 0, 0, 0], self.yQueueSize)
        self.yQueueSum = 0

    def updateModeText(self, text):
        self.modeText.setText(text)

    def chooseFacialRec(self):
        self.mode = 'face'
        self.updateModeText('Facial Recognition')

    def chooseOpticalFlow(self):
        self.mode = 'opticalFlow'
        self.updateModeText('Optical Flow')

    # Clean up
    def destroy(self):
        self.video.release()
        cv2.destroyAllWindows
        sys.exit

    # Move camera based on displacement
    # Turn eve's head to look at new camera position
    def turnHead(self, task):

        # Move camera up and down relative to displacement
        # between frames (scaled arbitrarily for good practical results)
        # Move eve's head to look at camera
        if self.mode == 'opticalFlow':
            self.getDisplacement()
            self.camera.setX(self.camBaseX +
                             self.total_displacement[0] * -0.35)
            self.eveNeck.setP(self.getP())
            self.camera.setZ(self.camBaseZ +
                             self.total_displacement[1] * -0.35)
            self.eveNeck.setH(self.getH())
        elif self.mode == 'face':
            self.getFaces()
            self.camera.setX(self.camBaseX +
                             self.total_face_displacement[0] * -0.1)
            self.eveNeck.setP(self.getP())
            self.camera.setZ(self.camBaseZ +
                             self.total_face_displacement[1] * -0.1)
            self.eveNeck.setH(self.getH())
        else:
            print('Unrecognized mode')

        # Rotate camera to center on eve
        self.camera.lookAt(self.eve)

        # Task continues infinitely
        return Task.cont

    # Trig to get heading of eve's head, looking at camera
    def getH(self):
        A = self.pitchOffset
        O = self.camera.getZ() - self.camBaseZ + self.camHeight
        H = math.sqrt(A**2 + O**2)
        self.headingOffset = H
        return np.degrees(np.arctan(O / A))

    # Trig to get pitch of eve's head, looking at camera
    def getP(self):
        A = self.headingOffset
        O = self.camera.getX() - self.camBaseX
        H = math.sqrt(A**2 + O**2)
        self.headingOffset = H
        return np.degrees(np.arctan(O / A))

    def getFaces(self):
        check, frame = self.video.read()
        f = faces(frame)
        # Only use the first detected face
        if (len(f) > 0):
            x = f[0][0]
            y = f[0][1]
            w = f[0][2]
            h = f[0][3]
            frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0),
                                  2)
            if not self.prev_face_x is None:
                delta = self.prev_face_x - x
                minus = self.xQueue.popleft()
                self.xQueue.append(delta)
                self.xQueueSum -= minus
                self.xQueueSum += delta
                average = self.xQueueSum / self.xQueueSize
                self.total_face_displacement[0] -= average
            self.prev_face_x = x
            if not self.prev_face_y is None:
                delta = self.prev_face_y - y
                minus = self.yQueue.popleft()
                self.yQueue.append(delta)
                self.yQueueSum -= minus
                self.yQueueSum += delta
                average = self.yQueueSum / self.yQueueSize
                self.total_face_displacement[1] -= average
            self.prev_face_y = y

        cv2.imshow("Faces", frame)
        return f

    def getDisplacement(self):
        check, frame = self.video.read()
        frame = downsample(frame)
        # Compute displacement between current and previous frame
        d = displacement(np.array([self.prev_frame, frame]))
        self.total_displacement += d
        self.prev_frame = frame
        cv2.imshow("Capturing", frame)
        return d

    # Sets up some default lighting
    def setupLights(self):
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.4, .4, .35, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 8, -2.5))
        directionalLight.setColor((0.9, 0.8, 0.9, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Beispiel #31
0
class Monster():
    def __init__(self, setup_data, common, level=1.0, start_pos=(0, 0, 0)):
        common['monsterList'].append(self)
        id = len(common['monsterList']) - 1
        self.monsterList = common['monsterList']
        self.waypoints_data = common['waypoints_data']
        self.waypoints = common['waypoints']
        self.audio3d = common['audio3d']
        self.common = common

        #root node
        self.node = render.attachNewNode("monster")
        self.sound_node = None
        self.soundset = None

        self.actor = Actor(setup_data["model"], setup_data["anim"])
        self.actor.setBlend(frameBlend=True)
        self.actor.reparentTo(self.node)
        self.actor.setScale(setup_data["scale"] * random.uniform(0.9, 1.1))
        self.actor.setH(setup_data["heading"])
        self.actor.setBin("opaque", 10)

        self.rootBone = self.actor.exposeJoint(None, 'modelRoot',
                                               setup_data["root_bone"])

        #sounds
        self.soundID = self.common['soundPool'].get_id()
        self.common['soundPool'].set_target(self.soundID, self.node)
        self.sound_names = {
            "hit": setup_data["hit_sfx"],
            "arrow_hit": setup_data["arrowhit_sfx"],
            "attack": setup_data["attack_sfx"],
            "die": setup_data["die_sfx"]
        }

        self.vfx = setup_data["hit_vfx"]

        self.stats = {
            "speed": setup_data["speed"],
            "hp": setup_data["hp"] * level,
            "armor": setup_data["armor"] * level,
            "dmg": setup_data["dmg"] * level
        }
        if self.stats['hp'] > 300:
            self.stats['hp'] = 300
        self.maxHP = self.stats['hp']
        self.HPring = Actor("models/ring_morph", {'anim': 'models/ring_anim'})
        self.HPring.setScale(0.07)
        self.HPring.setZ(0.4)
        self.HPring.setLightOff()
        self.HPring.reparentTo(self.node)
        self.HPvis = self.HPring.controlJoint(None, 'modelRoot', 'morph01')
        self.HPvis.setX(self.stats['hp'] / 300)
        self.HPring.hide(BitMask32.bit(1))
        self.HPring.hide()
        #self.HPring.setColorScale(0.0, 1.0, 0.0, 1.0)

        #gamestate variables
        self.attack_pattern = setup_data["attack_pattern"]
        self.damage = setup_data["dmg"]
        #self.HP=setup_data["hp"]
        self.state = "STOP"
        self.id = id
        self.nextWaypoint = None
        self.canSeePC = False
        self.PCisInRange = False
        self.PC = common['PC']
        self.speed_mode = random.randrange(0 + int(level), 42 + int(level),
                                           7) / 100.0
        self.totalSpeed = self.stats['speed'] + self.speed_mode
        self.sparkSum = 0
        self.lastMagmaDmg = 0
        self.DOT = 0
        self.arrows = set()
        self.traverser = CollisionTraverser("Trav" + str(self.id))
        #self.traverser.showCollisions(render)
        self.queue = CollisionHandlerQueue()

        #bit masks:
        # 1  visibility polygons & coll-rays
        # 2  walls & radar-ray
        # 3  spheres

        #collision ray for testing visibility polygons
        coll = self.node.attachNewNode(CollisionNode('collRay'))
        coll.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -180))
        coll.setTag("id", str(id))
        coll.node().setIntoCollideMask(BitMask32.allOff())
        coll.node().setFromCollideMask(BitMask32.bit(1))
        self.traverser.addCollider(coll, self.queue)

        #radar collision ray
        self.radar = self.node.attachNewNode(CollisionNode('radarRay'))
        self.radar.node().addSolid(CollisionRay(0, 0, 1, 0, 90, 0))
        self.radar.node().setIntoCollideMask(BitMask32.allOff())
        self.radar.node().setFromCollideMask(BitMask32.bit(2))
        self.radar.setTag("radar", str(id))
        #self.radar.show()
        self.traverser.addCollider(self.radar, self.queue)

        #collision sphere
        self.coll_sphere = self.node.attachNewNode(
            CollisionNode('monsterSphere'))
        self.coll_sphere.node().addSolid(CollisionSphere(0, 0, 0.8, 0.8))
        self.coll_sphere.setTag("id", str(id))
        self.coll_sphere.node().setIntoCollideMask(BitMask32.bit(3))
        #coll_sphere.show()

        #other monster blocking
        self.coll_quad = loader.loadModel("models/plane")
        self.coll_quad.reparentTo(self.node)

        #coll_quad=render.attachNewNode(CollisionNode('monsterSphere'))
        #coll_quad.node().addSolid(CollisionPolygon(Point3(-.5, -.5, 2), Point3(-.5, .5, 0), Point3(.5, .5, 0), Point3(.5, .5, 2)))
        #coll_quad.setTag("id", str(id))
        #coll_quad.node().setIntoCollideMask(BitMask32.bit(2))
        #coll_quad.reparentTo(self.node)
        #coll_quad.show()

        Sequence(Wait(random.uniform(.6, .8)), Func(self.restart)).start()
        self.node.setPos(render, start_pos)
        taskMgr.add(self.runAI, "AIfor" + str(self.id))
        taskMgr.doMethodLater(.6, self.runCollisions, 'collFor' + str(self.id))
        taskMgr.doMethodLater(1.0, self.damageOverTime,
                              'DOTfor' + str(self.id))

    def damageOverTime(self, task):
        if self.state == "DIE":
            return task.done
        if self.DOT > 0:
            self.doDamage(self.DOT)
            self.DOT = int((self.DOT * 0.9) - 1.0)
            if self.stats['hp'] < 1:
                self.actor.play("die")
                #self.common['soundPool'].play(self.soundID, self.sound_names["hit"])
                self.common['soundPool'].play(self.soundID,
                                              self.sound_names["die"])
                self.state = "DIE"
            vfx(self.node,
                texture=self.vfx,
                scale=.5,
                Z=1.0,
                depthTest=True,
                depthWrite=True).start(0.016, 24)
        return task.again

    def restart(self):
        self.state = "SEEK"

    def check_stacking(self):
        for monster in self.monsterList:
            if monster and monster.id != self.id:
                if self.node.getDistance(monster.node) < .8:
                    if monster.state != "STOP" and self.state == "SEEK":
                        if self.totalSpeed <= monster.totalSpeed:
                            self.state = "STOP"
                            self.actor.stop()
                            Sequence(Wait(1.5), Func(self.restart)).start()
                            return True

    def doDamage(self, damage, igoreArmor=False):
        if self.state == "DIE":
            return
        if not igoreArmor:
            damage -= self.stats['armor']
        if damage < 1:
            damage = 1
        #print damage
        self.stats['hp'] -= damage
        scale = self.stats['hp'] / self.maxHP
        self.HPvis.setX(self.stats['hp'] / 300.0)
        #self.HPring.setColor(0.8*(1.0-scale), 0.8*scale, 0.0, 1.0)
        self.HPring.show()
        self.HPring.setColorScale((1.0 - scale), scale, 0.0, 1.0)
        if self.stats['hp'] < 1:
            self.HPring.hide()

    def attack(self, pattern):
        if self.state == "DIE":
            return
        if not self.PC.node:
            return
        if pattern:
            next = pattern.pop()
        else:
            self.state = "SEEK"
            self.PCisInRange = False
            return
        if self.PC.node and self.node:
            range = self.node.getDistance(self.PC.node)
        else:
            return
        #print range
        if range < 1.8:
            self.PC.hit(self.damage)
        Sequence(Wait(next), Func(self.attack, pattern)).start()

    def onMagmaHit(self):
        if self.state == "DIE":
            return
        damage = self.lastMagmaDmg
        self.doDamage(damage)
        self.common['soundPool'].play(self.soundID, "onFire")
        vfx(self.node,
            texture="vfx/small_flame.png",
            scale=.6,
            Z=.7,
            depthTest=False,
            depthWrite=False).start(0.016, stopAtFrame=24)
        if self.stats['hp'] < 1:
            self.actor.play("die")
            self.common['soundPool'].play(self.soundID, "die3")
            self.state = "DIE"
            vfx(self.node,
                texture=self.vfx,
                scale=.5,
                Z=1.0,
                depthTest=True,
                depthWrite=True).start(0.016)

    def onPlasmaHit(self, damage):
        if self.state == "DIE":
            return
        self.doDamage(damage * 1.5, True)
        #self.soundset["spark"].play()
        #self.common['soundPool'].play(self.soundID, "spark")
        if self.stats['hp'] < 1:
            self.actor.play("die")
            #self.soundset["die3"].play()
            self.common['soundPool'].play(self.soundID, "die3")
            self.state = "DIE"
            vfx(self.node,
                texture=self.vfx,
                scale=.5,
                Z=1.0,
                depthTest=True,
                depthWrite=True).start(0.016)
        #else:
        #    short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03)

    def onSparkHit(self, damage):
        if self.state == "DIE":
            return
        #print damage
        self.doDamage(damage)
        #self.soundset["spark"].play()
        self.common['soundPool'].play(self.soundID, "spark")
        if self.stats['hp'] < 1:
            self.actor.play("die")
            #self.soundset["die3"].play()
            self.common['soundPool'].play(self.soundID, "die3")
            self.state = "DIE"
            vfx(self.node,
                texture=self.vfx,
                scale=.5,
                Z=1.0,
                depthTest=True,
                depthWrite=True).start(0.016)
        else:
            short_vfx(self.node,
                      texture="vfx/short_spark.png",
                      scale=.5,
                      Z=1.0,
                      depthTest=True,
                      depthWrite=True).start(0.03)

    def onHit(self, damage, sound="hit"):
        if self.state == "DIE":
            return
        self.doDamage(damage)
        #print damage
        vfx(self.node,
            texture=self.vfx,
            scale=.5,
            Z=1.0,
            depthTest=True,
            depthWrite=True).start(0.016)

        if self.stats['hp'] < 1:
            self.actor.play("die")
            #self.sounds["die"].play()
            if sound:
                self.common['soundPool'].play(self.soundID,
                                              self.sound_names[sound])
            self.common['soundPool'].play(self.soundID,
                                          self.sound_names["die"])
            self.state = "DIE"
        else:
            #self.sounds["hit"].play()
            if sound:
                self.common['soundPool'].play(self.soundID,
                                              self.sound_names[sound])

    def findFirstWaypoint(self):
        min = 100000
        nearest = None
        for waypoint in self.waypoints:
            dist = self.node.getDistance(waypoint)
            if dist < min:
                min = dist
                nearest = waypoint
        return nearest

    def runCollisions(self, task):
        if self.state == "DIE":
            return task.done
        if self.node.getDistance(self.PC.node) > 50.0:
            self.nextWaypoint = None
            return task.again
        if self.check_stacking():
            return task.again
        self.radar.lookAt(self.PC.node)
        valid_waypoints = []
        isFirstTest = True
        self.canSeePC = False
        self.traverser.traverse(render)
        self.queue.sortEntries()
        for entry in self.queue.getEntries():
            if entry.getFromNodePath().hasTag(
                    "id"):  #it's the monsters collRay
                valid_waypoints.append(
                    int(entry.getIntoNodePath().getTag(
                        "index")))  #visibility polygons
            elif entry.getFromNodePath().hasTag("radar"):  #it's the radar-ray
                #print "radar hit", entry.getIntoNodePath()
                if isFirstTest:
                    isFirstTest = False
                    #print "first hit!"
                    #print "radar hit", entry.getIntoNodePath()
                    if entry.getIntoNodePath().hasTag("player"):
                        self.canSeePC = True
        '''distance={}
        for target in self.PC.myWaypoints:
            for waypoint in valid_waypoints:
                distance[target]=self.waypoints_data[target][waypoint]                
                print(target, distance[target])
        if distance:
            self.nextWaypoint=self.waypoints[min(distance, key=distance.get)]
        #print self.canSeePC'''
        if not valid_waypoints:
            #self.nextWaypoint=self.findFirstWaypoint()
            print(self.id, ": I'm lost!")
            valid_waypoints = [self.findFirstWaypoint()]
            #return task.again
        if self.state == "STOP":
            self.nextWaypoint = self.waypoints[random.choice(valid_waypoints)]
            return task.again
        best_distance = 9000000
        target_node = None
        for target in self.PC.myWaypoints:
            for valid in valid_waypoints:
                distance = self.waypoints_data[target][valid]
                #print "target->valid=",target, valid, distance
                if distance < best_distance:
                    best_distance = distance
                    target_node = valid
        if target_node:
            self.nextWaypoint = self.waypoints[target_node]
        else:
            #print "no target", valid_waypoints
            self.nextWaypoint = self.findFirstWaypoint()
            #self.waypoints[random.choice(valid_waypoints)]
            #print self.nextWaypoint
        return task.again

    def runAI(self, task):
        #print self.state
        if self.state == "DIE":
            self.coll_sphere.node().setIntoCollideMask(BitMask32.allOff())
            self.coll_quad.removeNode()
            self.actor.play("die")
            self.common["kills"] -= 1
            if self.common["kills"] == 0:
                Interactive(self.common, data.items['key'],
                            self.node.getPos(render))
            elif random.randrange(10) == 0:
                Interactive(self.common, data.items['potion'],
                            self.node.getPos(render))
            Sequence(
                Wait(2.0),
                LerpPosInterval(
                    self.node, 2.0,
                    VBase3(self.node.getX(), self.node.getY(),
                           self.node.getZ() - 5)), Func(self.destroy)).start()
            return task.done
        elif self.state == "STOP":
            target = self.nextWaypoint
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target) > 0.3:
                self.node.setY(self.node,
                               self.totalSpeed * globalClock.getDt())
                if (self.actor.getCurrentAnim() != "walk"):
                    self.actor.loop("walk")
            return task.again
        elif self.state == "ATTACK":
            self.node.headsUp(self.PC.node)
            if (self.actor.getCurrentAnim() != "attack"):
                self.actor.play("attack")
                #Sequence(Wait(self.attack_pattern[-1]+self.speed_mode), Func(self.attack, list(self.attack_pattern))).start()
                Sequence(Wait(self.attack_pattern[-1]),
                         Func(self.attack, list(self.attack_pattern))).start()
            return task.again
        elif self.state == "SEEK":
            if self.PCisInRange:
                self.state = "ATTACK"
                return task.again
            target = self.nextWaypoint
            if self.canSeePC and self.PC.HP > 0:
                target = self.PC.node
                #print "target pc!"
            if not target:
                return task.again
            self.node.headsUp(target)
            if self.node.getDistance(target) > 0.3:
                self.node.setY(self.node,
                               self.totalSpeed * globalClock.getDt())
                if (self.actor.getCurrentAnim() != "walk"):
                    self.actor.loop("walk")
                return task.again
            else:
                #print "I'm stuck?"
                #print target
                #print self.canSeePC
                self.nextWaypoint = self.PC.node
                return task.again

    def destroy(self):
        #for sound in self.soundset:
        #    self.soundset[sound].stop()
        #print  "destroy:",
        #self.sound_node.reparentTo(render)
        #self.common['soundPool'].append([self.sound_node,self.soundset])
        self.common['soundPool'].set_free(self.soundID)
        #self.sounds=None
        #print  " sounds",
        self.arrows = None
        if self.actor:
            self.actor.cleanup()
            self.actor.removeNode()
            #print  " actor",
        if taskMgr.hasTaskNamed("AIfor" + str(self.id)):
            taskMgr.remove("AIfor" + str(self.id))
            #print  " AI",
        if taskMgr.hasTaskNamed('collFor' + str(self.id)):
            taskMgr.remove('collFor' + str(self.id))
            #print  " collision",
        if taskMgr.hasTaskNamed('DOTfor' + str(self.id)):
            taskMgr.remove('DOTfor' + str(self.id))
        if self.node:
            self.node.removeNode()
            #print  " node",
        self.monsterList[self.id] = None
        self.traverser = None
        self.queue = None
Beispiel #32
0
class World(DirectObject):
    def __init__(self):
        #This code puts the standard title and instuction text on screen
        self.title = OnscreenText(text="Panda3D: Embots - Joint Manipulation",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  pos=(0.8, -0.95),
                                  scale=.07)
        #setup key input
        self.accept('escape', sys.exit)

        #base.disableMouse() #Disable mouse-based camera-control
        camera.setPos(0, -20, 0)  #Position the camera

        self.teapot = loader.loadModel('models/teapot')
        self.teapot.reparentTo(render)
        self.teapot.setScale(0.2)

        self.tentacle = Actor("models/tentacle")  #Load our animated charachter
        self.tentacle.reparentTo(render)  #Put it in the scene
        self.tentacle.setScale(1.0)

        self.setupLights()  #Put in some default lighting

        self.tentacleBase = self.tentacle.controlJoint(None, 'modelRoot',
                                                       'Bone')

        self.tentacleIK = SMRPy.SmrKinematicChain(True, True, 'tentacle')

        self.jointList = []
        self.constraintList = []

        self.createKinematicChain(self.tentacle, 'Bone', '', 0)

        myJoint = self.tentacleIK.getJointByName("Bone.006")

        self.myConstraint = SMRPy.SmrIKConstraint()
        self.myConstraint.setRelatedJointptr(myJoint)
        myConstraintPosition = SMRPy.SmrVector3(0.0, 0.0, 0.0)
        self.teapot.setPos(0.0, 0.0, 0.0)
        self.myConstraint.setPosition(myConstraintPosition)

        myConstraintPosition = SMRPy.SmrVector3(0.0, 0.0, 0.0)
        self.myConstraint.setOffset(myConstraintPosition)

        self.myKinematicSolver = SMRPy.SmrGSMMSolver(self.tentacleIK)
        self.myKinematicSolver.addConstraintPtr(self.myConstraint)

        taskMgr.add(self.ikStep, "ikStep")

    def ikStep(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.myConstraint.setPosition(
                SMRPy.SmrVector3(
                    restrain(mpos.getX()) * 10, 0.0,
                    restrain(mpos.getY()) * 10))
            #self.tentacleBase.setR (restrain(mpos.getX()) * 20)
            self.teapot.setPos(
                restrain(mpos.getX()) * 10, 0.0,
                restrain(mpos.getY()) * 10)
        self.myKinematicSolver.process()
        self.updatePandaSkeleton(self.tentacle, self.tentacleIK, 'Bone')
        return Task.cont

    def createKinematicChain(self, _tentacle, _initialJointName, _parentName,
                             _weight):
        #get the tentacle's currentJoint
        currentPandaJoint = _tentacle.getJoints(_initialJointName)
        currentPandaCJoint = self.tentacle.controlJoint(
            None, 'modelRoot', _initialJointName)
        #get the first joint's position
        position = currentPandaCJoint.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SmrKinematicJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(),
                                position.getZ())
        else:
            newJoint = SMRPy.SmrKinematicJoint(False)

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        print "position", position.getX(), position.getY(), position.getZ()
        #newJoint.setRot(0,0,0)
        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159
        rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159
        rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159

        print rotX, rotY, rotZ, currentPandaCJoint.getName()
        # remove the setRot function veveal in C++, error prone

        newJoint.addDof(SMRPy.SmrVector3(0.0, 0.0, 1.0), rotZ - 1.0,
                        rotZ + 1.0, rotZ, 0.01 * _weight)
        newJoint.addDof(SMRPy.SmrVector3(1.0, 0.0, 0.0), rotX - 1.0,
                        rotX + 1.0, rotX, 0.01 * _weight)
        newJoint.addDof(SMRPy.SmrVector3(0.0, 1.0, 0.0), rotY, rotY, rotY, 0)

        _weight += 0.5

        print newJoint.getName()
        print _initialJointName, 'numchildren : ', currentPandaJoint[
            0].getNumChildren()

        self.jointList.append(newJoint)
        self.tentacleIK.insertJoint(newJoint)
        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            print(childName)
            self.createKinematicChain(_tentacle, childName, _initialJointName,
                                      _weight)

    def updatePandaSkeleton(self, _pandaSkeleton, _smrSkeleton,
                            _startJointName):
        currentPandaJoint = _pandaSkeleton.getJoints(_startJointName)
        currentPandaCJoint = _pandaSkeleton.controlJoint(
            None, 'modelRoot', _startJointName)
        currentSmrJoint = _smrSkeleton.getJointByName(_startJointName)

        self.synchronize(currentPandaCJoint, currentSmrJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            self.updatePandaSkeleton(_pandaSkeleton, _smrSkeleton, childName)

    def synchronize(self, _pandaCJoint, _smrJoint):
        #_smrJoint.setRot(3.14/20.0,0,0);
        smrQuaternion = _smrJoint.getRot()
        pandaQuaternion = Quat()
        pandaQuaternion.setI(smrQuaternion.getX())
        pandaQuaternion.setJ(smrQuaternion.getY())
        pandaQuaternion.setK(smrQuaternion.getZ())
        pandaQuaternion.setR(smrQuaternion.getW())
        _pandaCJoint.setQuat(pandaQuaternion)


#  def turnTentacle(self, task):
#Check to make sure the mouse is readable
#    if base.mouseWatcherNode.hasMouse():
#get the mouse position as a Vec2. The values for each axis are from -1 to
#1. The top-left is (-1,-1), the bottom rightis (1,1)
#      mpos = base.mouseWatcherNode.getMouse()
#Here we multiply the values to get the amount of degrees to turn
#Restrain is used to make sure the values returned by getMouse are in the
#valid range. If this particular model were to turn more than this,
#significant tearing would be visable
#self.tentacleBase.setP(restrain(mpos.getY()) * -50)
#      self.tentacleBase.setR (restrain(mpos.getX()) * 20)
#    return Task.cont                        #Task continues infinitely

    def setupLights(self):  #Sets up some default lighting
        lAttrib = LightAttrib.makeAllOff()
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.4, .4, .35, 1))
        lAttrib = lAttrib.addLight(ambientLight)
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 8, -2.5))
        directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1))
        lAttrib = lAttrib.addLight(directionalLight)
        render.attachNewNode(directionalLight.upcastToPandaNode())
        render.attachNewNode(ambientLight.upcastToPandaNode())
        render.node().setAttrib(lAttrib)
Beispiel #33
0
class MayaDemo(ShowBase):
    R_LEG_JOINTS = ["joint6", "joint7", "joint8"]
    L_LEG_JOINTS = ["joint10", "joint11", "joint12"]

    def __init__(self):
        ShowBase.__init__(self)

        self.bandit = Actor("banditRiggedNoHat.egg")
        self.bandit.makeSubpart("r_leg", self.R_LEG_JOINTS)
        self.bandit.makeSubpart("l_leg", self.L_LEG_JOINTS)

        headJoint = self.bandit.exposeJoint(None, "modelRoot", "joint5")
        hat = loader.loadModel("{}_hat.egg".format(random.randint(0, 7)))
        hat.setPos(0, 0, -0.08)
        hat.setHpr(-90, 0, 0)
        hat.setScale(0.35)
        hat.reparentTo(headJoint)

        self.bandit.reparentTo(render)

        r_hip_ro = self.bandit.exposeJoint(None, "modelRoot",
                                           self.R_LEG_JOINTS[0])
        r_hip_wo = self.bandit.controlJoint(None, "modelRoot",
                                            self.R_LEG_JOINTS[0])
        r_knee_ro = self.bandit.exposeJoint(None, "modelRoot",
                                            self.R_LEG_JOINTS[1])
        r_knee_wo = self.bandit.controlJoint(None, "modelRoot",
                                             self.R_LEG_JOINTS[1])
        r_ankle_ro = self.bandit.exposeJoint(None, "modelRoot",
                                             self.R_LEG_JOINTS[2])
        r_ankle_wo = self.bandit.controlJoint(None, "modelRoot",
                                              self.R_LEG_JOINTS[2])
        distances = np.array([
            r_hip_ro.getDistance(r_knee_ro),
            r_knee_ro.getDistance(r_ankle_ro)
        ])
        self.r_leg = Leg.Leg(r_hip_ro, r_hip_wo, r_knee_ro, r_knee_wo,
                             r_ankle_ro, r_ankle_wo, distances)

        l_hip = self.bandit.controlJoint(None, "modelRoot",
                                         self.L_LEG_JOINTS[0])
        l_knee = self.bandit.controlJoint(None, "modelRoot",
                                          self.L_LEG_JOINTS[1])
        l_ankle = self.bandit.exposeJoint(None, "modelRoot",
                                          self.L_LEG_JOINTS[2])
        distances = np.array(
            [l_hip.getDistance(l_knee),
             l_knee.getDistance(l_ankle)])
        #self.l_leg = Leg.Leg(l_hip, l_knee, l_ankle, distances)

        self.accept("arrow_up", self.r_leg.moveAnkle, [(0, 0, 0.1)])
        self.accept("arrow_down", self.r_leg.moveAnkle, [(0, 0, -0.1)])

        self.accept("arrow_left", self.r_leg.rotateAnkle, [(0, 0, 10)])
        self.accept("arrow_right", self.r_leg.rotateAnkle, [(0, 0, -10)])

        # Draws debug skeleton
        self.bandit.setBin('background', 1)
        self.walkJointHierarchy(self.bandit,
                                self.bandit.getPartBundle('modelRoot'))

        self.stream = StreamRead("/dev/input/smartshoes")
        self.last_t = time.time()
        taskMgr.add(self.getDeviceData, 'Stream reader')

    def getDeviceData(self, task):
        records = self.stream.readFromStream()
        if records and len(records[0]) == 10:
            records = map(float, records[0])
            angular_velocity, acceleration, magnetic_field = [
                records[x:x + 3] for x in range(0, 9, 3)
            ]

            # Switch axis orientations
            angular_velocity[2], angular_velocity[0] = angular_velocity[
                0], angular_velocity[2]
            acceleration[2], acceleration[0] = acceleration[0], acceleration[2]
            magnetic_field[2], magnetic_field[0] = magnetic_field[
                0], magnetic_field[2]

            self.r_leg.ankle_rotation.rotationMagic(records[9],
                                                    angular_velocity,
                                                    acceleration,
                                                    magnetic_field)
            self.r_leg.updateAnkleRotation()
        return task.again

    def walkJointHierarchy(self, actor, part, parentNode=None, indent=""):
        if isinstance(part, CharacterJoint):
            np = actor.exposeJoint(None, 'modelRoot', part.getName())

            if parentNode and parentNode.getName() != "root":
                lines = LineSegs()
                lines.setThickness(3.0)
                lines.setColor(random.random(), random.random(),
                               random.random())
                lines.moveTo(0, 0, 0)
                lines.drawTo(np.getPos(parentNode))
                lnp = parentNode.attachNewNode(lines.create())
                lnp.setBin("fixed", 40)
                lnp.setDepthWrite(False)
                lnp.setDepthTest(False)

            parentNode = np

        for child in part.getChildren():
            self.walkJointHierarchy(actor, child, parentNode, indent + "  ")
Beispiel #34
0
class Walker (PhysicalObject):

    collide_bits = SOLID_COLLIDE_BIT

    def __init__(self, incarnator, colordict=None, player=False):
        super(Walker, self).__init__()
        self.spawn_point = incarnator
        self.on_ground = False
        self.mass = 150.0 # 220.0 for heavy
        self.xz_velocity = Vec3(0, 0, 0)
        self.y_velocity = Vec3(0, 0, 0)
        self.factors = {
            'forward': 7.5,
            'backward': -7.5,
            'left': 2.0,
            'right': -2.0,
            'crouch': 0.0,
        }
        self.movement = {
            'forward': 0.0,
            'backward': 0.0,
            'left': 0.0,
            'right': 0.0,
            'crouch': 0.0,
        }
        self.head_height = Vec3(0, 1.5, 0)
        self.collides_with = MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT
        self.grenade_loaded = False
        self.energy = 1.0
        self.left_gun_charge = 1.0
        self.right_gun_charge = 1.0
        self.primary_color = [1,1,1,1]
        self.colordict = colordict if colordict else None
        self.crouching = False
        self.player = player
        self.can_jump = False
        self.crouch_impulse = 0

    def get_model_part(self, obj_name):
        return self.actor.find("**/%s" % obj_name)

    def create_node(self):
        self.actor = Actor('walker.egg')
        if self.colordict:
            self.setup_color(self.colordict)
        self.actor.set_pos(*self.spawn_point.pos)
        self.actor.look_at(*self.spawn_point.heading)
        self.spawn_point.was_used()


        self.left_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'left_barrel_bone')
        self.right_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'right_barrel_bone')

        return self.actor

    def create_solid(self):
        walker_capsule = BulletGhostNode(self.name + "_walker_cap")
        self.walker_capsule_shape = BulletCylinderShape(.7, .2, YUp)
        walker_bullet_np = self.actor.attach_new_node(walker_capsule)
        walker_bullet_np.node().add_shape(self.walker_capsule_shape)
        walker_bullet_np.node().set_kinematic(True)
        walker_bullet_np.set_pos(0,1.5,0)
        walker_bullet_np.wrt_reparent_to(self.actor)
        self.world.physics.attach_ghost(walker_capsule)
        walker_bullet_np.node().setIntoCollideMask(GHOST_COLLIDE_BIT)
        return None

    def setup_shape(self, gnodepath, bone, pname):
        shape = BulletConvexHullShape()

        gnode = gnodepath.node()
        geom = gnode.get_geom(0)
        shape.add_geom(geom)

        node = BulletRigidBodyNode(self.name + pname)
        np = self.actor.attach_new_node(node)
        np.node().add_shape(shape)
        np.node().set_kinematic(True)
        np.wrt_reparent_to(bone)
        self.world.physics.attach_rigid_body(node)
        return np

    def setup_color(self, colordict):
        if colordict.has_key('barrel_color'):
            color = colordict['barrel_color']
            self.get_model_part('left_barrel').setColor(*color)
            self.get_model_part('right_barrel').setColor(*color)
        if colordict.has_key('visor_color'):
            self.get_model_part('visor').setColor(*colordict['visor_color'])
        if colordict.has_key('body_primary_color'):
            color = colordict['body_primary_color']
            self.primary_color = color
            for part in ['hull_primary', 'rt_leg_primary',
                         'lt_leg_primary', 'lb_leg_primary', 'rb_leg_primary',
                         'left_barrel_ring', 'right_barrel_ring', 'hull_bottom']:
                self.get_model_part(part).setColor(*color)
        if colordict.has_key('body_secondary_color'):
            color = colordict['body_secondary_color']
            for part in ['hull_secondary', 'visor_stripe', 'rb_leg_secondary',
                         'rt_leg_secondary', 'lb_leg_secondary', 'lt_leg_secondary']:
                self.get_model_part(part).setColor(*color)
        return

    def attached(self):
        self.integrator = Integrator(self.world.gravity)
        self.world.register_collider(self)
        self.world.register_updater(self)
        left_bones = LegBones(
            self.world.render, self.world.physics,
            self.actor.exposeJoint(None, 'modelRoot', 'left_hip_bone'),
            self.actor.exposeJoint(None, 'modelRoot', 'left_foot_bone'),
            *[self.actor.controlJoint(None, 'modelRoot', name) for name in ['left_top_bone', 'left_bottom_bone']]
        )
        right_bones = LegBones(
            self.world.render, self.world.physics,
            self.actor.exposeJoint(None, 'modelRoot', 'right_hip_bone'),
            self.actor.exposeJoint(None, 'modelRoot', 'right_foot_bone'),
            *[self.actor.controlJoint(None, 'modelRoot', name) for name in  ['right_top_bone', 'right_bottom_bone']]
        )

        self.skeleton = Skeleton(left_bones, right_bones, self.actor.controlJoint(None, 'modelRoot', 'pelvis_bone'))
        self.skeleton.setup_footsteps(self.world.audio3d)
        self.head_bone = self.actor.controlJoint(None, 'modelRoot', 'head_bone')
        self.head_bone_joint = self.actor.exposeJoint(None, 'modelRoot', 'head_bone')
        self.loaded_missile = Hat(self.head_bone_joint, self.primary_color)
        self.loaded_grenade = Sack(self.head_bone_joint, self.primary_color)
        if self.player:
            self.sights = Sights(self.left_barrel_joint, self.right_barrel_joint, self.world.render, self.world.physics)



    def collision(self, other, manifold, first):
        world_pt = manifold.get_position_world_on_a() if first else manifold.get_position_world_on_b()
        print self, 'HIT BY', other, 'AT', world_pt

    def handle_command(self, cmd, pressed):
        if cmd is 'crouch' and pressed:
            self.crouching = True
            if self.on_ground:
                self.can_jump = True
        if cmd is 'crouch' and not pressed and self.on_ground and self.can_jump:
            self.crouching = False
            self.y_velocity = Vec3(0, 6.8, 0)
            self.can_jump = False
        if cmd is 'fire' and pressed:
            self.handle_fire()
            return
        if cmd is 'missile' and pressed:
            if self.loaded_grenade.can_fire():
                self.loaded_grenade.toggle_visibility()
            self.loaded_missile.toggle_visibility()
            return
        if cmd is 'grenade' and pressed:
            if self.loaded_missile.can_fire():
                self.loaded_missile.toggle_visibility()
            self.loaded_grenade.toggle_visibility()
            return
        if cmd is 'grenade_fire' and pressed:
            if self.loaded_missile.can_fire():
                self.loaded_missile.toggle_visibility()
            if not self.loaded_grenade.can_fire():
                self.loaded_grenade.toggle_visibility()
            walker_v = Vec3(self.xz_velocity)
            walker_v.y = self.y_velocity.y
            self.loaded_grenade.fire(self.world, walker_v)
            return
        self.movement[cmd] = self.factors[cmd] if pressed else 0.0

    def handle_fire(self):
        if self.loaded_missile.can_fire():
            self.loaded_missile.fire(self.world)
        elif self.loaded_grenade.can_fire():
            walker_v = self.xz_velocity
            walker_v.y = self.y_velocity.y
            self.loaded_grenade.fire(self.world, walker_v)
        else:
            p_energy = 0
            hpr = 0
            if self.left_gun_charge > self.right_gun_charge:
                origin = self.left_barrel_joint.get_pos(self.world.render)
                hpr = self.left_barrel_joint.get_hpr(self.world.render)
                p_energy = self.left_gun_charge
                if p_energy < MIN_PLASMA_CHARGE:
                    return
                self.left_gun_charge = 0
            else:
                origin = self.right_barrel_joint.get_pos(self.world.render)
                hpr = self.right_barrel_joint.get_hpr(self.world.render)
                p_energy = self.right_gun_charge
                if p_energy < MIN_PLASMA_CHARGE:
                    return
                self.right_gun_charge = 0
            hpr.y += 180
            plasma = self.world.attach(Plasma(origin, hpr, p_energy))

    def st_result(self, cur_pos, new_pos):
        return self.world.physics.sweepTestClosest(self.walker_capsule_shape, cur_pos, new_pos, self.collides_with, 0)

    def update(self, dt):
        dt = min(dt, 0.2) # let's just temporarily assume that if we're getting less than 5 fps, dt must be wrong.
        yaw = self.movement['left'] + self.movement['right']
        self.rotate_by(yaw * dt * 60, 0, 0)
        walk = self.movement['forward'] + self.movement['backward']
        start = self.position()
        cur_pos_ts = TransformState.make_pos(self.position() + self.head_height)

        if self.on_ground:
            friction = DEFAULT_FRICTION
        else:
            friction = AIR_FRICTION

        speed = walk
        pos = self.position()
        self.move_by(0, 0, speed)
        direction = self.position() - pos
        newpos, self.xz_velocity = Friction(direction, friction).integrate(pos, self.xz_velocity, dt)
        self.move(newpos)

        # Cast a ray from just above our feet to just below them, see if anything hits.
        pt_from = self.position() + Vec3(0, 1, 0)
        pt_to = pt_from + Vec3(0, -1.1, 0)
        result = self.world.physics.ray_test_closest(pt_from, pt_to, MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT)

        #this should return 'on ground' information
        self.skeleton.update_legs(walk, dt, self.world.render, self.world.physics)

        if self.y_velocity.get_y() <= 0 and result.has_hit():
            self.on_ground = True
            self.crouch_impulse = self.y_velocity.y
            self.y_velocity = Vec3(0, 0, 0)
            self.move(result.get_hit_pos())
        else:
            self.on_ground = False
            current_y = Point3(0, self.position().get_y(), 0)
            y, self.y_velocity = self.integrator.integrate(current_y, self.y_velocity, dt)
            self.move(self.position() + (y - current_y))

        if self.crouching and self.skeleton.crouch_factor < 1:
            self.skeleton.crouch_factor += (dt*60)/10
            self.skeleton.update_legs(0, dt, self.world.render, self.world.physics)
        elif not self.crouching and self.skeleton.crouch_factor > 0:
            self.skeleton.crouch_factor -= (dt*60)/10
            self.skeleton.update_legs(0, dt, self.world.render, self.world.physics)

        #if self.crouch_impulse < 0:

        goal = self.position()
        adj_dist = abs((start - goal).length())
        new_pos_ts = TransformState.make_pos(self.position() + self.head_height)

        sweep_result = self.st_result(cur_pos_ts, new_pos_ts)
        count = 0
        while sweep_result.has_hit() and count < 10:
            moveby = sweep_result.get_hit_normal()
            self.xz_velocity = -self.xz_velocity.cross(moveby).cross(moveby)
            moveby.normalize()
            moveby *= adj_dist * (1 - sweep_result.get_hit_fraction())
            self.move(self.position() + moveby)
            new_pos_ts = TransformState.make_pos(self.position() + self.head_height)
            sweep_result = self.st_result(cur_pos_ts, new_pos_ts)
            count += 1

        if self.energy > WALKER_MIN_CHARGE_ENERGY:
            if self.left_gun_charge < 1:
                self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0]
                self.left_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1]
            else:
                self.left_gun_charge = math.floor(self.left_gun_charge)

            if self.right_gun_charge < 1:
                self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0]
                self.right_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1]
            else:
                self.right_gun_charge = math.floor(self.right_gun_charge)

        if self.energy < 1:
            self.energy += WALKER_RECHARGE_FACTOR * (dt)

        if self.player:
            self.sights.update(self.left_barrel_joint, self.right_barrel_joint)
Beispiel #35
0
class RoamingRalphDemo(ShowBase):
    def __init__(self):
        # Set up the window, camera, etc.
        ShowBase.__init__(self)

        # Set the background color to black
        self.win.setClearColor((0, 0, 0, 1))

        # This is used to store which keys are currently pressed.
        self.keyMap = {
            "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0}

        # Post the instructions
        self.title = addTitle(
            "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)")
        self.inst1 = addInstructions(0.06, "[ESC]: Quit")
        self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left")
        self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right")
        self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward")
        self.inst6 = addInstructions(0.30, "[A]: Rotate Camera Left")
        self.inst7 = addInstructions(0.36, "[S]: Rotate Camera Right")
        self.dirText = addInstructions(0.42, "pos")
        self.anglesText = addInstructions(0.48, "angle")

        # Set up the environment
        #
        # This environment model contains collision meshes.  If you look
        # in the egg file, you will see the following:
        #
        #    <Collide> { Polyset keep descend }
        #
        # This tag causes the following mesh to be converted to a collision
        # mesh -- a mesh which is optimized for collision, not rendering.
        # It also keeps the original mesh, so there are now two copies ---
        # one optimized for rendering, one for collisions.

        #self.environ = loader.loadModel("models/world")
        #self.environ.reparentTo(render)

        self.createArm()

        # Create the main character, Ralph

        #ralphStartPos = self.environ.find("**/start_point").getPos()
        self.ralph = Actor("models/ralph",
                           {"run": "models/ralph-run",
                            "walk": "models/ralph-walk"})
        self.ralph.reparentTo(render)
        self.ralph.setScale(.2)
        #self.ralph.setPos(ralphStartPos + (0, 0, 0.5))

        # Create a floater object, which floats 2 units above ralph.  We
        # use this as a target for the camera to look at.

        self.floater = NodePath(PandaNode("floater"))
        self.floater.reparentTo(self.ralph)
        self.floater.setZ(2.0)

        # Accept the control keys for movement and rotation

        self.accept("escape", self.exitButton)
        self.accept("arrow_left", self.setKey, ["left", True])
        self.accept("arrow_right", self.setKey, ["right", True])
        self.accept("arrow_up", self.setKey, ["forward", True])
        self.accept("a", self.setKey, ["cam-left", True])
        self.accept("s", self.setKey, ["cam-right", True])
        self.accept("arrow_left-up", self.setKey, ["left", False])
        self.accept("arrow_right-up", self.setKey, ["right", False])
        self.accept("arrow_up-up", self.setKey, ["forward", False])
        self.accept("a-up", self.setKey, ["cam-left", False])
        self.accept("s-up", self.setKey, ["cam-right", False])

        taskMgr.add(self.move, "moveTask")

        # Game state variables
        self.isMoving = False

        # Set up the camera
        self.disableMouse()
        self.camera.setPos(15, 0, 3)#self.ralph.getX(), self.ralph.getY() + 10, 2)
        self.camera.setHpr(90, -5, 0)

        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  One ray will
        # start above ralph's head, and the other will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.
        self.cTrav = CollisionTraverser()

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

        self.camGroundRay = CollisionRay()
        self.camGroundRay.setOrigin(0, 0, 9)
        self.camGroundRay.setDirection(0, 0, -1)
        self.camGroundCol = CollisionNode('camRay')
        self.camGroundCol.addSolid(self.camGroundRay)
        self.camGroundCol.setFromCollideMask(CollideMask.bit(0))
        self.camGroundCol.setIntoCollideMask(CollideMask.allOff())
        self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol)
        self.camGroundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

        # Uncomment this line to see the collision rays
        #self.ralphGroundColNp.show()
        #self.camGroundColNp.show()

        # Uncomment this line to show a visual representation of the
        # collisions occuring
        #self.cTrav.showCollisions(render)

        # Create some lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((-5, -5, -5))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))

    def exitButton(self):
      servos.exit()
      __import__('sys').exit()

    def createArm(self):
        self.robotarm = Actor("models/robotarm")
        self.robotarm.reparentTo(render)
        self.robotarm.setPos(0,0,0)
        self.robotarm.setScale(.2)
        self.jointForearm = self.robotarm.controlJoint(None, "modelRoot", "forearm")
        self.jointBase = self.robotarm.controlJoint(None, "modelRoot", "base")
        taskMgr.add(self.monitorArm, "robot arm")

        inc = 15
        self.accept("i", self.setForearm, [inc])
        self.accept("u", self.setForearm, [-inc])
        self.accept("j", self.setBase, [inc])
        self.accept("k", self.setBase, [-inc])

    def monitorArm(self, task):
        def clamp1(x): return min(1, max(-1, x))

        direction = self.ralph.get_pos() - self.robotarm.get_pos()
        direction.z += 1
        direction.normalize()

        # camera starts facing along x
        dec = math.asin(direction.x)
        cosdec = math.cos(dec) 
        if cosdec > 1e-05:
          ra = math.asin(clamp1(direction.z / cosdec))
          ra2 = math.acos(clamp1(direction.y / cosdec))
        else: ra = ra2 = math.pi/2#float('nan')
        #print(cosdec, direction)
        #print(dec, ra, ra2, cosdec)

        if direction.z < 0: 
          if ra2 < math.pi/2: ra2 = 0
          else: ra2 = math.pi

        self.jointForearm.setH(-dec * 180/math.pi)
        self.jointBase.setP(ra2 * 180/math.pi) 

        self.dirText.setText(str(direction)) 
        self.anglesText.setText(str((dec, ra, ra2, cosdec)))

        a = self.jointForearm.getH() / 90.0 * 300 + 512
        b = self.jointBase.getP()    / 90.0 * 300 + 212
        #print(a, b)
        baseID = 9
        servos.setAngle({baseID:int(round(b)), (baseID+1):int(round(a))})
        return task.again

    def monitorArmServos(self, task):
        baseID = 9
        a = self.jointForearm.getH() / 90.0 * 300 + 512
        b = self.jointBase.getP()    / 90.0 * 300 + 212
        #print(a, b)
        servos.setAngle({baseID:int(round(a)), (baseID+1):int(round(b))})

#	frac = task.time - int(task.time) 
#        if frac > .9 and frac < .99:
        #print(self.jointForearm.getH(), self.jointBase.getP())
        return task.again

    def setForearm(self, inc):
        #self.jointForearm.setH(random.random()*180-90)
        self.jointForearm.setH(self.jointForearm.getH() + inc)
    def setBase(self, inc):
        #self.jointBase.setP(random.random()*180)
        self.jointBase.setP(self.jointBase.getP() + inc)


    # Records the state of the arrow keys
    def setKey(self, key, value):
        self.keyMap[key] = value

    # Accepts arrow keys to move either the player or the menu cursor,
    # Also deals with grid checking and collision detection
    def move(self, task):

        # Get the time that elapsed since last frame.  We multiply this with
        # the desired speed in order to find out with which distance to move
        # in order to achieve that desired speed.
        dt = globalClock.getDt()

        # If the camera-left key is pressed, move camera left.
        # If the camera-right key is pressed, move camera right.

        if self.keyMap["cam-left"]:
            self.camera.setX(self.camera, -20 * dt)
        if self.keyMap["cam-right"]:
            self.camera.setX(self.camera, +20 * dt)

        # save ralph's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        startpos = self.ralph.getPos()

        # If a move-key is pressed, move ralph in the specified direction.

        if self.keyMap["left"]:
            self.ralph.setH(self.ralph.getH() + 300 * dt)
        if self.keyMap["right"]:
            self.ralph.setH(self.ralph.getH() - 300 * dt)
        if self.keyMap["forward"]:
            self.ralph.setY(self.ralph, -25 * dt)

        # If ralph is moving, loop the run animation.
        # If he is standing still, stop the animation.

        if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap["right"]:
            if self.isMoving is False:
                self.ralph.loop("run")
                self.isMoving = True
        else:
            if self.isMoving:
                self.ralph.stop()
                self.ralph.pose("walk", 5)
                self.isMoving = False

        # If the camera is too far from ralph, move it closer.
        # If the camera is too close to ralph, move it farther.

        """camvec = self.ralph.getPos() - self.camera.getPos()
        camvec.setZ(0)
        camdist = camvec.length()
        camvec.normalize()
        if camdist > 10.0:
            self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10))
            camdist = 10.0
        if camdist < 5.0:
            self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist))
            camdist = 5.0

        # Normally, we would have to call traverse() to check for collisions.
        # However, the class ShowBase that we inherit from has a task to do
        # this for us, if we assign a CollisionTraverser to self.cTrav.
        #self.cTrav.traverse(render)

        # Adjust ralph's Z coordinate.  If ralph's ray hit terrain,
        # update his Z. If it hit anything else, or didn't hit anything, put
        # him back where he was last frame.

        entries = list(self.ralphGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.ralph.setPos(startpos)

        # Keep the camera at one foot above the terrain,
        # or two feet above ralph, whichever is greater.

        entries = list(self.camGroundHandler.getEntries())
        entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0)
        if self.camera.getZ() < self.ralph.getZ() + 2.0:
            self.camera.setZ(self.ralph.getZ() + 2.0)

        # The camera should look in ralph's direction,
        # but it should also try to stay horizontal, so look at
        # a floater which hovers above ralph's head.
        self.camera.lookAt(self.floater)"""

        return task.cont
class DistributedPartyTrampolineActivity(DistributedPartyActivity):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity')

    def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None):
        DistributedPartyTrampolineActivity.notify.debug('__init__')
        DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True)
        self.doJellyBeans = doJellyBeans
        self.doTricks = doTricks
        self.texture = texture
        self.toon = None
        self.trampHeight = 3.6
        self.trampK = 400.0
        self.normalTrampB = 2.5
        self.leavingTrampB = 8.0
        self.trampB = self.normalTrampB
        self.g = -32.0
        self.jumpBoost = 330.0
        self.beginningBoost = 500.0
        self.beginningBoostThreshold = self.trampHeight + 1.5
        self.earlyJumpThreshold = 75.0
        self.boingThreshold = 300.0
        self.turnFactor = 120.0
        self.stepDT = 0.001
        self.targetCameraPos = Point3(0.0, 40.0, 10.0)
        self.cameraSpeed = 2.0
        self.hopOffPos = Point3(16.0, 0.0, 0.0)
        self.indicatorFactor = 0.0095
        self.dropShadowCutoff = 15.0
        self.minHeightForText = 15.0
        self.heightTextOffset = -0.065
        self.beanOffset = 0.5
        self.guiBeanOffset = -0.02
        self.jumpTextShown = False
        self.toonJumped = False
        self.turnLeft = False
        self.turnRight = False
        self.leavingTrampoline = False
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.lastPeak = 0.0
        self.beginRoundInterval = None
        self.hopOnAnim = None
        self.hopOffAnim = None
        self.flashTextInterval = None
        self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans
        self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus
        self.jellyBeanStartHeight = 20.0
        self.jellyBeanStopHeight = 90.0
        self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0),
         VBase4(0.5, 1.0, 0.5, 1.0),
         VBase4(0.5, 1.0, 1.0, 1.0),
         VBase4(1.0, 1.0, 0.4, 1.0),
         VBase4(0.4, 0.4, 1.0, 1.0),
         VBase4(1.0, 0.5, 1.0, 1.0)]
        delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1)
        self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ]
        self.doSimulateStep = False
        return

    def load(self):
        DistributedPartyTrampolineActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.loadModels()
        self.loadCollision()
        self.loadGUI()
        self.loadSounds()
        self.loadIntervals()
        self.activityFSM = TrampolineActivityFSM(self)
        self.activityFSM.request('Idle')
        self.animFSM = TrampolineAnimFSM(self)
        self.setBestHeightInfo('', 0)

    def loadModels(self):
        self.tramp = self.root.attachNewNode(self.uniqueName('tramp'))
        self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'})
        self.trampActor.reparentTo(self.tramp)
        if self.texture:
            reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode')
            reskinNode.setTexture(loader.loadTexture(self.texture), 100)
        self.surface = NodePath(self.uniqueName('trampSurface'))
        self.surface.reparentTo(self.tramp)
        self.surface.setZ(self.trampHeight)
        self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1')
        self.sign.setPos(PartyGlobals.TrampolineSignOffset)
        self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ]
        for bean in self.beans:
            bean.find('**/jellybean').setP(-35.0)
            bean.setScale(3.0)
            bean.setTransparency(True)
            bean.reparentTo(self.tramp)
            bean.stash()

        self.beans[-1].setScale(8.0)

    def loadCollision(self):
        collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4)
        collTube.setTangible(True)
        self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision'))
        self.trampolineCollision.addSolid(collTube)
        self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask)
        self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision)
        collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0)
        collSphere.setTangible(False)
        self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger'))
        self.trampolineTrigger.addSolid(collSphere)
        self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger)
        self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger)

    def loadGUI(self):
        self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI')
        self.gui.reparentTo(base.a2dTopLeft)
        self.gui.setPos(0.115, 0, -1)
        self.gui.hide()
        self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar')
        jumpLineLocator = self.gui.find('**/jumpLine_locator')
        guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean')
        self.gui.find('**/trampolineGUI_GreenJellyBean').stash()
        self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ]
        self.guiBeans[-1].setScale(1.5)
        heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode'))
        heightTextNode.setFont(ToontownGlobals.getSignFont())
        heightTextNode.setAlign(TextNode.ALeft)
        heightTextNode.setText('0.0')
        heightTextNode.setShadow(0.05, 0.05)
        heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0)
        heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0)
        self.heightText = jumpLineLocator.attachNewNode(heightTextNode)
        self.heightText.setX(0.15)
        self.heightText.setScale(0.1)
        self.heightText.setAlphaScale(0.0)
        self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui')
        quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp')
        quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown')
        quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover')
        self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline)
        self.quitEarlyButton.stash()
        self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True)
        self.timer = PartyUtils.getNewToontownTimer()
        self.timer.posInTopRightCorner()
        return

    def loadSounds(self):
        self.jellyBeanSound = base.loadSfx('phase_4/audio/sfx/sparkly.ogg')
        self.boingSound = base.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg')
        self.whistleSound = base.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg')

    def loadIntervals(self):

        def prepareHeightText():
            self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ()))
            self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset)

        self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0))

    def unload(self):
        DistributedPartyTrampolineActivity.notify.debug('unload')
        if self.hopOnAnim and self.hopOnAnim.isPlaying():
            self.hopOnAnim.finish()
        if self.hopOffAnim and self.hopOffAnim.isPlaying():
            self.hopOffAnim.finish()
        if self.beginRoundInterval and self.beginRoundInterval.isPlaying():
            self.beginRoundInterval.finish()
        if self.flashTextInterval and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        if self.heightTextInterval and self.heightTextInterval.isPlaying():
            self.heightTextInterval.finish()
        self.timer.stop()
        DistributedPartyActivity.unload(self)
        taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask'))
        taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask'))
        self.ignoreAll()
        del self.heightTextInterval
        del self.beginRoundInterval
        del self.hopOnAnim
        del self.hopOffAnim
        del self.flashTextInterval
        if hasattr(self, 'beanAnims'):
            self.cleanupJellyBeans()
        self.quitEarlyButton.destroy()
        del self.quitEarlyButton
        del self.gui
        del self.activityFSM
        del self.animFSM
        return

    def setBestHeightInfo(self, toonName, height):
        self.bestHeightInfo = (toonName, height)
        DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height))
        if height > 0:
            self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo)
        else:
            self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet)

    def leaveTrampoline(self):
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp)
            self.leavingTrampoline = True
            self.timer.reset()
            self.trampB = self.leavingTrampB
            self.ignore('control')
            self.quitEarlyButton.stash()
            self.gui.hide()
        return

    def requestAnim(self, request):
        self.animFSM.request(request)

    def b_requestAnim(self, request):
        self.requestAnim(request)
        self.sendUpdate('requestAnim', [request])

    def requestAnimEcho(self, request):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.requestAnim(request)
        return

    def removeBeans(self, beansToRemove):
        for i in beansToRemove:
            height, bean, guiBean, beanAnim = self.beanDetails[i]
            guiBean.stash()
            if i in self.beansToCollect:
                self.beansToCollect.remove(i)
            else:
                self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i)
            self.poofBean(bean, beanAnim)

    def b_removeBeans(self, beansToRemove):
        self.removeBeans(beansToRemove)
        self.sendUpdate('removeBeans', [beansToRemove])

    def removeBeansEcho(self, beansToRemove):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.removeBeans(beansToRemove)
        return

    def joinRequestDenied(self, reason):
        DistributedPartyActivity.joinRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny)
        base.cr.playGame.getPlace().fsm.request('walk')

    def exitRequestDenied(self, reason):
        DistributedPartyActivity.exitRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny)

    def setState(self, newState, timestamp):
        DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        self.activityFSM.request(newState)

    def startIdle(self):
        DistributedPartyTrampolineActivity.notify.debug('startIdle')

    def finishIdle(self):
        DistributedPartyTrampolineActivity.notify.debug('finishIdle')

    def startRules(self):
        DistributedPartyTrampolineActivity.notify.debug('startRules')
        if self.doJellyBeans:
            self.setupJellyBeans()
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self.acquireToon()
        return

    def startActive(self):
        DistributedPartyTrampolineActivity.notify.debug('startActive')
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            base.setCellsActive(base.bottomCells, True)
            self.accept('arrow_left', self.onLeft)
            self.accept('arrow_left-up', self.onLeftUp)
            self.accept('arrow_right', self.onRight)
            self.accept('arrow_right-up', self.onRightUp)
            self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound))
            self.beginRoundInterval.start()
        return

    def finishActive(self):
        DistributedPartyTrampolineActivity.notify.debug('finishActive')
        if self.doJellyBeans:
            self.cleanupJellyBeans()

    def setupJellyBeans(self):
        self.beanAnims = []
        self.beansToCollect = []
        self.beanDetails = []
        self.numBeansCollected = 0
        for i in xrange(self.numJellyBeans):
            bean = self.beans[i]
            guiBean = self.guiBeans[i]
            height = self.jellyBeanPositions[i]
            color = random.choice(self.jellyBeanColors)
            bean.find('**/jellybean').setColor(color)
            if self.toon.doId == base.localAvatar.doId:
                bean.setAlphaScale(1.0)
            else:
                bean.setAlphaScale(0.5)
            guiBean.setColor(color)
            bean.setZ(height + self.toon.getHeight() + self.beanOffset)
            guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset)
            bean.setH(0.0)
            bean.unstash()
            guiBean.unstash()
            beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0))
            beanAnim.loop()
            self.beanAnims.append(beanAnim)
            self.beanDetails.append((height,
             bean,
             guiBean,
             beanAnim))

        self.beansToCollect = range(self.numJellyBeans)

    def cleanupJellyBeans(self):
        for bean in self.beans:
            bean.stash()

        for guiBean in self.guiBeans:
            guiBean.stash()

        if hasattr(self, 'beanAnims'):
            for beanAnim in self.beanAnims:
                beanAnim.finish()

            del self.beanAnims
            del self.beansToCollect

    def beginRound(self):
        base.playSfx(self.whistleSound)
        self.timer.setTime(PartyGlobals.TrampolineDuration)
        self.timer.countdown(PartyGlobals.TrampolineDuration)
        self.timer.show()
        self.gui.show()
        self.quitEarlyButton.unstash()
        self.notify.debug('Accepting contorl')
        self.accept('control', self.onJump)
        self.notify.debug('setting simulate step to true')
        self.doSimulateStep = True

    def acquireToon(self):
        self.toon.disableSmartCameraViews()
        self.toon.stopUpdateSmartCamera()
        camera.wrtReparentTo(render)
        self.toon.dropShadow.reparentTo(hidden)
        self.toon.startPosHprBroadcast(period=0.2)
        self.toonAcceleration = 0.0
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.trampB = self.normalTrampB
        self.leavingTrampoline = False
        self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn))
        self.hopOnAnim.start()

    def postHopOn(self):
        self.toon.setH(self.toon.getH() + 90.0)
        self.toon.dropShadow.reparentTo(self.surface)
        self.timeLeftToSimulate = 0.0
        self.doSimulateStep = False
        taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask'))
        base.setCellsActive(base.leftCells, False)
        base.setCellsActive(base.bottomCells, False)
        DistributedPartyActivity.startRules(self)

    def releaseToon(self):
        self._hideFlashMessage()
        self.ignore('arrow_left')
        self.ignore('arrow_left-up')
        self.ignore('arrow_right')
        self.ignore('arrow_right-up')
        taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask'))
        self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff))
        self.hopOffAnim.start()

    def postHopOff(self):
        base.setCellsActive(base.leftCells, True)
        self.timer.stop()
        self.timer.hide()
        self.toon.dropShadow.reparentTo(self.toon.getShadowJoint())
        self.toon.dropShadow.setAlphaScale(1.0)
        self.toon.dropShadow.setScale(1.0)
        self.b_requestAnim('Off')
        camera.reparentTo(base.localAvatar)
        base.localAvatar.startUpdateSmartCamera()
        base.localAvatar.enableSmartCameraViews()
        base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex)
        place = base.cr.playGame.getPlace()
        if self.doJellyBeans:
            self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)])
            if int(self.topHeight) > self.bestHeightInfo[1]:
                self.sendUpdate('reportHeightInformation', [int(self.topHeight)])
        self.d_toonExitDemand()

    def onTrampolineTrigger(self, collEntry):
        if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk':
            base.cr.playGame.getPlace().fsm.request('activity')
            self.d_toonJoinRequest()
        else:
            self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0)
        return

    def onJump(self):
        self.notify.debug('got onJump')
        if self.toon != None and self.toon.getZ() < self.trampHeight:
            self.toonJumped = True
            self.b_requestAnim('Jump')
        else:
            self.notify.debug('z is less than tramp height')
        return

    def onLeft(self):
        self.turnLeft = True

    def onLeftUp(self):
        self.turnLeft = False

    def onRight(self):
        self.turnRight = True

    def onRightUp(self):
        self.turnRight = False

    def handleToonJoined(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonJoined')
        self.toon = self.getAvatar(toonId)
        if self.toon != None and not self.toon.isEmpty():
            self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat')
            self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land')
            self.toon.setPlayRate(2.5, 'jump-squat')
            self.toon.setPlayRate(2.0, 'jump-land')
            self.turnLeft = False
            self.turnRight = False
            self.activityFSM.request('Rules')
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask'))
        else:
            self.notify.warning('handleToonJoined could not get toon %d' % toonId)
        return

    def handleToonExited(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonExited')
        if self.toon != None:
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask'))
            self.surface.setZ(self.trampHeight)
            self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat')
            self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land')
            self.toon = None
        return

    def handleToonDisabled(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled')
        DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled')
        if base.localAvatar.doId == toonId:
            self.releaseToon()

    def handleRulesDone(self):
        self.sendUpdate('toonReady')
        self.finishRules()

    def getTitle(self):
        if self.doJellyBeans:
            return TTLocalizer.PartyTrampolineJellyBeanTitle
        elif self.doTricks:
            return TTLocalizer.PartyTrampolineTricksTitle
        else:
            return DistributedPartyActivity.getTitle(self)

    def getInstructions(self):
        return TTLocalizer.PartyTrampolineActivityInstructions

    def updateTask(self, task):
        z = self.toon.getZ()
        dt = globalClock.getDt()
        if self.doSimulateStep:
            self.timeLeftToSimulate += dt
            while self.timeLeftToSimulate >= self.stepDT:
                z, a = self.simulateStep(z)
                self.timeLeftToSimulate -= self.stepDT

        self.toon.setZ(z)
        if z <= self.trampHeight:
            self.surface.setZ(z)
        else:
            self.surface.setZ(self.trampHeight)
        self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor)
        if self.turnLeft:
            self.toon.setH(self.toon.getH() + self.turnFactor * dt)
        if self.turnRight:
            self.toon.setH(self.toon.getH() - self.turnFactor * dt)
        currentPos = base.camera.getPos(self.toon)
        vec = self.targetCameraPos - currentPos
        newPos = currentPos + vec * (dt * self.cameraSpeed)
        base.camera.setPos(self.toon, newPos)
        base.camera.lookAt(self.toon)
        #if z > self.trampHeight:
        #    heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff)
        #    self.toon.dropShadow.setAlphaScale(heightFactor)
        #    self.toon.dropShadow.setScale(max(0.1, heightFactor))
        #else:
        #    self.toon.dropShadow.setAlphaScale(1.0)
        #    self.toon.dropShadow.setScale(1.0)
        if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1:
            self.releaseToon()
        return Task.cont

    def simulateStep(self, z):
        if z >= self.trampHeight:
            a = self.g
            self.toonJumped = False
        else:
            a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity
            if self.toonJumped:
                if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0:
                    a += self.jumpBoost
                    if self.lastPeak < self.beginningBoostThreshold:
                        a += self.beginningBoost
        lastVelocity = self.toonVelocity
        self.toonVelocity += a * self.stepDT
        if lastVelocity > 0.0 and self.toonVelocity <= 0.0:
            topOfJump = True
            bottomOfJump = False
        elif lastVelocity < 0.0 and self.toonVelocity >= 0.0:
            topOfJump = False
            bottomOfJump = True
        else:
            topOfJump = False
            bottomOfJump = False
        newZ = z + self.toonVelocity * self.stepDT
        if newZ > self.topHeight:
            self.topHeight = newZ
            if self.doJellyBeans:
                self.collectJellyBeans(newZ)
        if topOfJump:
            self.lastPeak = newZ
            if newZ >= self.minHeightForText:
                self.heightTextInterval.start()
        if topOfJump:
            if newZ > self.trampHeight + 20.0:
                self.b_requestAnim('Falling')
            elif self.animFSM.state == 'Jump':
                self.b_requestAnim('Falling')
        if newZ <= self.trampHeight and z > self.trampHeight:
            if self.animFSM.state == 'Falling':
                self.b_requestAnim('Land')
            elif self.animFSM.state != 'Neutral':
                self.b_requestAnim('Neutral')
        if bottomOfJump and a > self.boingThreshold:
            base.playSfx(self.boingSound)
        return (newZ, a)

    def collectJellyBeans(self, z):
        beansToRemove = []
        for i in self.beansToCollect:
            height = self.beanDetails[i][0]
            if height <= z:
                beansToRemove.append(i)

        if len(beansToRemove) > 0:
            base.playSfx(self.jellyBeanSound)
            self.numBeansCollected += len(beansToRemove)
            self.b_removeBeans(beansToRemove)

    def remoteUpdateTask(self, task):
        if self.toon != None and not self.toon.isEmpty():
            z = self.toon.getZ()
            if z <= self.trampHeight:
                self.surface.setZ(z)
            else:
                self.surface.setZ(self.trampHeight)
        return Task.cont

    def poofBean(self, bean, beanAnim):
        if bean == None:
            self.notify.warning('poofBean, returning immediately as bean is None')
            return
        if bean.isEmpty():
            self.notify.warning('poofBean, returning immediately as bean is empty')
            return
        currentAlpha = bean.getColorScale()[3]
        currentScale = bean.getScale()
        poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale))
        poofAnim.start()
        return

    def _showFlashMessage(self, message):
        if self.isDisabled():
            return
        if self.flashTextInterval is not None and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        self.flashText.setText(message)
        self.flashText.setAlphaScale(1.0)
        self.flashText.unstash()
        return

    def _hideFlashMessage(self, duration = 0.0):
        if self.isDisabled():
            pass
        self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash))
        self.flashTextInterval.start()

    def flashMessage(self, message, duration = 0.5):
        self._showFlashMessage(message)
        self._hideFlashMessage(duration)
class Agent:
    def __init__( self, _name ):
        print "Creating agent " + _name
        self.name = _name
     
    def setDataPath( self, _dataPath ):
        self.dataPath = _dataPath;
        
    def setActor( self, _modelFileName, _animationFileNames, _morphTargetsFileName ):
        self.modelFileName = _modelFileName;
        self.animationFileNames = _animationFileNames;
        self.morphTargetsFileName = _morphTargetsFileName;
    
    def setRealizer( self, _realizer ):
        self.realizer = _realizer;
        
    def setTransform( self, x, y, z, rx, ry, rz, scale ):
        self.agent.setPos( x, y, z )
        self.agent.setScale( scale )
        self.agent.setHpr( rx, ry, rz )
        self.positionX = x
        self.positionY = y
        self.positionZ = z

    def getPosition( self ):
        return self.agent.getPos()
        
    def init( self ):
        #load the agent and parent it to the world
        #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it
        self.animationAgent = Actor( self.modelFileName, self.animationFileNames )
        
        self.agent = Actor( self.modelFileName, self.morphTargetsFileName )

        maxMorphTargets={'MT_Jaw_Open':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Open'),
                         'MT_Jaw_L':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_L'),
                         'MT_Jaw_R':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_R'),
                         'MT_Jaw_Fwd':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Fwd'),
                         'MT_WideL':self.agent.controlJoint(None, 'modelRoot', 'MT_WideL'),
                         'MT_WideR':self.agent.controlJoint(None, 'modelRoot', 'MT_WideR'),
                         'MT_NarrowL':self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowL'),
                         'MT_NarrowR':self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowR'),
                         'MT_FrownL':self.agent.controlJoint(None, 'modelRoot', 'MT_FrownL'),
                         'MT_FrownR':self.agent.controlJoint(None, 'modelRoot', 'MT_FrownR'),
                         'MT_SneerL':self.agent.controlJoint(None, 'modelRoot', 'MT_SneerL'),
                         'MT_SneerR':self.agent.controlJoint(None, 'modelRoot', 'MT_SneerR'),
                         'MT_SquintL':self.agent.controlJoint(None, 'modelRoot', 'MT_SquintL'),
                         'MT_SquintR':self.agent.controlJoint(None, 'modelRoot', 'MT_SquintR'),
                         'MT_BrowUpL':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpL'),
                         'MT_BrowUpR':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpR'),
                         'MT_BrowDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'),
                         'MT_BrowDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'),
                         'MT_MBrowUp':self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowUp'),
                         'MT_BrowDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'),
                         'MT_BrowDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'),
                         'MT_MBrowDn':self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowDn'),
                         'MT_BrowSqueeze':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowSqueeze'),
                         'MT_MouthL':self.agent.controlJoint(None, 'modelRoot', 'MT_MouthL'),
                         'MT_MouthR':self.agent.controlJoint(None, 'modelRoot', 'MT_MouthR'),
                         'MT_UprLipUpL':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpL'),
                         'MT_UprLipUpR':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpR'),
                         'MT_UprLipDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnL'),
                         'MT_UprLipDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnR'),
                         'MT_LwrLipUpL':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpL'),
                         'MT_LwrLipUpR':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpR'),
                         'MT_LwrLipDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnL'),
                         'MT_LwrLipDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnR'),
                         'MT_BlowCheeksL':self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksL'),
                         'MT_BlowCheeksR':self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksR'),
                         'MT_TongueOut':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueOut'),
                         'MT_TongueUp':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueUp'),
                         'MT_TongueTipUp':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueTipUp'),
                         'MT_TongueL':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueL'),
                         'MT_TongueR':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueR'),
                         'MT_Blink_L':self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_L'),
                         'MT_Blink_R':self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_R')}
                         

        self.targets = {#'Basis':[],                
                        'ExpSmileClosed':{maxMorphTargets['MT_WideR']:1.0,maxMorphTargets['MT_WideL']:1.0},
                        'ExpAnger':{maxMorphTargets['MT_Jaw_Open']:-0.07,maxMorphTargets['MT_Jaw_Fwd']:0.25,maxMorphTargets['MT_NarrowL']:0.30,maxMorphTargets['MT_NarrowR']:0.30,maxMorphTargets['MT_SquintL']:0.60,maxMorphTargets['MT_SquintR']:0.60,maxMorphTargets['MT_MBrowDn']:1.0,maxMorphTargets['MT_BrowDnL']:0.7,maxMorphTargets['MT_BrowDnR']:0.7,maxMorphTargets['MT_SneerL']:0.8,maxMorphTargets['MT_SneerR']:0.8,maxMorphTargets['MT_FrownL']:0.2,maxMorphTargets['MT_FrownR']:0.2,maxMorphTargets['MT_UprLipDnL']:0.45,maxMorphTargets['MT_UprLipDnR']:0.45,maxMorphTargets['MT_LwrLipUpL']:1.0,maxMorphTargets['MT_LwrLipUpR']:1.0},
                        'ExpDisgust':{maxMorphTargets['MT_WideL']:0.25,maxMorphTargets['MT_WideR']:0.15,maxMorphTargets['MT_SquintL']:0.40,maxMorphTargets['MT_SquintR']:0.40,maxMorphTargets['MT_MBrowDn']:0.25,maxMorphTargets['MT_BrowSqueeze']:0.45,maxMorphTargets['MT_WideL']:0.25,maxMorphTargets['MT_BrowDnL']:0.50,maxMorphTargets['MT_BrowDnR']:0.50,maxMorphTargets['MT_SneerL']:2.0,maxMorphTargets['MT_SneerR']:2.0,maxMorphTargets['MT_FrownL']:0.25,maxMorphTargets['MT_FrownR']:0.25,maxMorphTargets['MT_UprLipUpL']:0.66,maxMorphTargets['MT_UprLipUpR']:0.33,maxMorphTargets['MT_LwrLipUpL']:0.40,maxMorphTargets['MT_LwrLipUpR']:0.40 },
                        'ExpFear':{maxMorphTargets['MT_Jaw_Open']:0.15,maxMorphTargets['MT_Jaw_Fwd']:-0.3,maxMorphTargets['MT_NarrowL']:0.24,maxMorphTargets['MT_NarrowR']:0.24,maxMorphTargets['MT_SquintL']:-0.4,maxMorphTargets['MT_SquintR']:-0.4,maxMorphTargets['MT_BrowUpL']:0.36,maxMorphTargets['MT_BrowUpR']:0.36,maxMorphTargets['MT_MBrowUp']:1.30,maxMorphTargets['MT_BrowSqueeze']:0.40,maxMorphTargets['MT_FrownL']:0.35,maxMorphTargets['MT_FrownR']:0.35,maxMorphTargets['MT_UprLipDnL']:0.25,maxMorphTargets['MT_UprLipDnR']:0.25,maxMorphTargets['MT_LwrLipUpL']:0.35,maxMorphTargets['MT_LwrLipUpR']:0.35},
                        'ExpSad':{maxMorphTargets['MT_NarrowL']:0.20,maxMorphTargets['MT_NarrowR']:0.20,maxMorphTargets['MT_SquintL']:0.20,maxMorphTargets['MT_SquintR']:0.20,maxMorphTargets['MT_MBrowUp']:0.40,maxMorphTargets['MT_BrowSqueeze']:0.66,maxMorphTargets['MT_BrowDnL']:0.66,maxMorphTargets['MT_BrowDnR']:0.66,maxMorphTargets['MT_BlowCheeksL']:-0.25,maxMorphTargets['MT_BlowCheeksR']:-0.25,maxMorphTargets['MT_FrownL']:0.66,maxMorphTargets['MT_FrownR']:0.66,maxMorphTargets['MT_UprLipDnL']:0.50,maxMorphTargets['MT_UprLipDnR']:0.50,maxMorphTargets['MT_LwrLipUpL']:0.66,maxMorphTargets['MT_LwrLipUpR']:0.66},
                        'ExpSurprise':{maxMorphTargets['MT_Jaw_Open']:0.25,maxMorphTargets['MT_NarrowL']:0.24,maxMorphTargets['MT_NarrowR']:0.24,maxMorphTargets['MT_SquintL']:-0.20,maxMorphTargets['MT_SquintR']:-0.20,maxMorphTargets['MT_BrowUpL']:0.92,maxMorphTargets['MT_BrowUpR']:0.92,maxMorphTargets['MT_MBrowUp']:0.66},
                        'ExpSmileOpen':{maxMorphTargets['MT_Jaw_Open']:0.16,maxMorphTargets['MT_WideL']:0.740,maxMorphTargets['MT_WideR']:0.740,maxMorphTargets['MT_SneerL']:0.280,maxMorphTargets['MT_SneerR']:0.280,maxMorphTargets['MT_BrowUpL']:0.360,maxMorphTargets['MT_BrowUpR']:0.360},
                        'ExpHappy':{maxMorphTargets['MT_Jaw_Open']:0.22,maxMorphTargets['MT_WideL']:0.75,maxMorphTargets['MT_WideR']:0.75,maxMorphTargets['MT_SquintL']:0.35,maxMorphTargets['MT_SquintR']:0.35,maxMorphTargets['MT_BrowDnL']:0.08,maxMorphTargets['MT_BrowDnR']:0.08,maxMorphTargets['MT_UprLipUpL']:0.15,maxMorphTargets['MT_UprLipUpR']:0.15,maxMorphTargets['MT_LwrLipUpL']:0.15,maxMorphTargets['MT_LwrLipUpR']:0.15,maxMorphTargets['MT_BrowUpL']:0.360,maxMorphTargets['MT_BrowUpR']:0.360},
                        'ModBlinkLeft':{maxMorphTargets['MT_Blink_L']:1.0},
                        'ModBlinkRight':{maxMorphTargets['MT_Blink_R']:1.0},
                        'ModBrowDownLeft':{maxMorphTargets['MT_BrowDnL']:1.0},
                        'ModBrowDownRight':{maxMorphTargets['MT_BrowDnR']:1.0},
                        'ModBrowInRight':{maxMorphTargets['MT_BrowSqueeze']:1.0},
                        'ModBrowInLeft':{maxMorphTargets['MT_BrowSqueeze']:1.0},
                        'ModBrowUpLeft':{maxMorphTargets['MT_BrowUpL']:1.0},
                        'ModBrowUpRight':{maxMorphTargets['MT_BrowUpR']:1.0},
                        #'ModEarsOut':[],
                        'ModEyeSquintLeft':{maxMorphTargets['MT_SquintL']:1.0},
                        'ModEyeSquintRight':{maxMorphTargets['MT_SquintR']:1.0},
                        'Phonaah':{maxMorphTargets['MT_Jaw_Open']:1.0},
                        'PhonB,M,P':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5},
                        'Phonbigaah':{maxMorphTargets['MT_Jaw_Open']:1.0},
                        'Phonch,J,sh':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5},
                        'PhonD,S,T':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 },
                        'Phonee':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5},
                        'Phoneh':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 },
                        'PhonF,V':{maxMorphTargets['MT_WideL']:0.2,maxMorphTargets['MT_WideR']:0.2,maxMorphTargets['MT_Jaw_Open']:0.3,maxMorphTargets['MT_UprLipDnL']:0.3,maxMorphTargets['MT_UprLipDnR']:0.3},
                        'Phoni':{maxMorphTargets['MT_WideL']:0.2,maxMorphTargets['MT_WideR']:0.2,maxMorphTargets['MT_Jaw_Open']:0.3 },
                        'PhonK':{maxMorphTargets['MT_Jaw_Open']:0.4},
                        'PhonN':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5},
                        'Phonoh':{maxMorphTargets['MT_Jaw_Open']:0.4,maxMorphTargets['MT_NarrowL']:0.55,maxMorphTargets['MT_NarrowR']:0.55},
                        'Phonooh,Q':{maxMorphTargets['MT_Jaw_Open']:0.4,maxMorphTargets['MT_NarrowL']:0.55,maxMorphTargets['MT_NarrowR']:0.55},
                        'PhonR':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 },
                        'Phonth':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 },
                        'PhonW':{maxMorphTargets['MT_Jaw_Open']:0.3,maxMorphTargets['MT_NarrowL']:0.7,maxMorphTargets['MT_NarrowR']:0.7},
                        'AU26_MT_Jaw_Open':{maxMorphTargets['MT_Jaw_Open']:1.0},
                        'AU30_MT_Jaw_L':{maxMorphTargets['MT_Jaw_L']:1.0},
                        'AU30_MT_Jaw_R':{maxMorphTargets['MT_Jaw_R']:1.0},
                        'AU31_MT_Jaw_Fwd':{maxMorphTargets['MT_Jaw_Fwd']:1.0},
                        'AU27_MT_WideL':{maxMorphTargets['MT_WideL']:1.0},
                        'AU27_MT_WideR':{maxMorphTargets['MT_WideR']:1.0},
                        'AU18_MT_NarrowL':{maxMorphTargets['MT_NarrowL']:1.0},
                        'AU18_MT_NarrowR':{maxMorphTargets['MT_NarrowL']:1.0},
                        'AU42_MT_FrownL':{maxMorphTargets['MT_FrownL']:1.0},
                        'AU42_MT_FrownR':{maxMorphTargets['MT_FrownR']:1.0},
                        'AU9_MT_SneerL':{maxMorphTargets['MT_SneerL']:1.0},
                        'AU9_MT_SneerR':{maxMorphTargets['MT_SneerR']:1.0},
                        'AU46_MT_SquintL':{maxMorphTargets['MT_SquintL']:1.0},
                        'AU46_MT_SquintR':{maxMorphTargets['MT_SquintR']:1.0},
                        'AU2_MT_BrowUpL':{maxMorphTargets['MT_BrowUpL']:1.0},
                        'AU2_MT_BrowUpR':{maxMorphTargets['MT_BrowUpR']:1.0},
                        'AU4_MT_BrowDnL':{maxMorphTargets['MT_BrowDnL']:1.0},
                        'AU4_MT_BrowDnR':{maxMorphTargets['MT_BrowDnR']:1.0},
                        'AU4_MT_MBrowUp':{maxMorphTargets['MT_MBrowUp']:1.0},
                        'AU1_MT_BrowDnR':{maxMorphTargets['MT_BrowDnR']:1.0},
                        'AU1_MT_BrowDnL':{maxMorphTargets['MT_BrowDnL']:1.0},
                        'AU1_MT_MBrowDn':{maxMorphTargets['MT_MBrowDn']:1.0},
                        'AU44_MT_BrowSqueeze':{maxMorphTargets['MT_BrowSqueeze']:1.0},
                        'AU12_MT_MouthL':{maxMorphTargets['MT_MouthL']:1.0},
                        'AU12_MT_MouthR':{maxMorphTargets['MT_MouthR']:1.0},
                        'AU5_MT_UprLipUpL':{maxMorphTargets['MT_UprLipUpL']:1.0},
                        'AU5_MT_UprLipUpR':{maxMorphTargets['MT_UprLipUpR']:1.0},
                        'MT_UprLipDnL':{maxMorphTargets['MT_UprLipDnL']:1.0},
                        'MT_UprLipDnR':{maxMorphTargets['MT_UprLipDnR']:1.0},
                        'MT_LwrLipUpL':{maxMorphTargets['MT_LwrLipUpL']:1.0},
                        'MT_LwrLipUpR':{maxMorphTargets['MT_LwrLipUpR']:1.0},
                        'MT_LwrLipDnL':{maxMorphTargets['MT_LwrLipDnL']:1.0},
                        'MT_LwrLipDnR':{maxMorphTargets['MT_LwrLipDnR']:1.0},
                        'AU33_MT_BlowCheeksL':{maxMorphTargets['MT_BlowCheeksL']:1.0},
                        'AU33_MT_BlowCheeksR':{maxMorphTargets['MT_BlowCheeksR']:1.0},
                        'AU36_MT_TongueOut':{maxMorphTargets['MT_TongueOut']:1.0},
                        'AU36_MT_TongueUp':{maxMorphTargets['MT_TongueUp']:1.0},
                        'AU36_MT_TongueTipUp':{maxMorphTargets['MT_TongueTipUp']:1.0},
                        'AU36_MT_TongueL':{maxMorphTargets['MT_TongueL']:1.0},
                        'AU36_MT_TongueR':{maxMorphTargets['MT_TongueR']:1.0},
                        'AU45_MT_Blink_L':{maxMorphTargets['MT_Blink_L']:1.0},
                        'AU45_MT_Blink_R':{maxMorphTargets['MT_Blink_R']:1.0}
                        }
        
        #instanciate a list in order to keep track of kinematic joints joints 
        #in python runtime
        #if nothing points towards those joints, they get flushed by
        #python's garbage collector
        self.jointList = []
        self.jointFKList = []
        self.agentControlJoints = []
        self.agentNodePaths = []

        self.agentSMRSkel = SMRPy.SMRSkeleton(True,True,'agent')
        self.createSkel( self.agent, self.agentSMRSkel, 'root', '' )
	#Pascal: output of both skeletons amber and alfonse as chracter.bvh
        #SMRPy.exportSkeletonToBvh(self.name + '.bvh',self.agentSMRSkel);
        self.newSkeleton = SMRPy.SMRSkeleton(True,True,'pose')
        self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '')       
        self.realizer.addCharacter( self.name, self.agentSMRSkel );
            
        for key in self.targets.keys():
            self.realizer.addMorphTarget( self.name, key ) #TODO: declare morph targets into CharacterConfigurationFile
        
        #self.realizer.addShaderParameter( self.name, 'blushing' ) #TODO: declare shader inputs into CharacterConfiguration file


        self.realizer.addBVHMotionToCharacter(self.name, 'hands_claw', open('./animations/hands_claw.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_index', open('./animations/hands_index.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_open-relaxed', open('./animations/hands_open-relaxed.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_open-spread', open('./animations/hands_open-spread.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_open-straight', open('./animations/hands_open-straight.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_purse', open('./animations/hands_purse.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ring', open('./animations/hands_ring.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'poseNeutral', open('./animations/poseNeutral.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'shrug', open('./animations/shrug.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_A', open('./animations/hands_DGS_A.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_B', open('./animations/hands_DGS_B.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_C', open('./animations/hands_DGS_C.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_D', open('./animations/hands_DGS_D.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_E', open('./animations/hands_DGS_E.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_F', open('./animations/hands_DGS_F.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_G', open('./animations/hands_DGS_G.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_H', open('./animations/hands_DGS_H.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_I', open('./animations/hands_DGS_I.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_J', open('./animations/hands_DGS_J.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_K', open('./animations/hands_DGS_K.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_L', open('./animations/hands_DGS_L.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_M', open('./animations/hands_DGS_M.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_N', open('./animations/hands_DGS_N.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_O', open('./animations/hands_DGS_O.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_P', open('./animations/hands_DGS_P.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_Q', open('./animations/hands_DGS_Q.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_R', open('./animations/hands_DGS_R.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_T', open('./animations/hands_DGS_T.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_U', open('./animations/hands_DGS_U.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_W', open('./animations/hands_DGS_W.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_X', open('./animations/hands_DGS_X.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_Y', open('./animations/hands_DGS_Y.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_Z', open('./animations/hands_DGS_Z.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_SCH', open('./animations/hands_DGS_SCH.bvh', "r").read())

        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_A', open('./animations/hands_ASL_A.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_B', open('./animations/hands_ASL_B.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_C', open('./animations/hands_ASL_C.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_D', open('./animations/hands_ASL_D.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_E', open('./animations/hands_ASL_E.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_F', open('./animations/hands_ASL_F.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_G', open('./animations/hands_ASL_G.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_H', open('./animations/hands_ASL_H.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_I', open('./animations/hands_ASL_I.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_J', open('./animations/hands_ASL_J.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_K', open('./animations/hands_ASL_K.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_L', open('./animations/hands_ASL_L.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_M', open('./animations/hands_ASL_M.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_N', open('./animations/hands_ASL_N.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_O', open('./animations/hands_ASL_O.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_P', open('./animations/hands_ASL_P.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_Q', open('./animations/hands_ASL_Q.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_R', open('./animations/hands_ASL_R.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_T', open('./animations/hands_ASL_T.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_U', open('./animations/hands_ASL_U.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_V', open('./animations/hands_ASL_V.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_W', open('./animations/hands_ASL_W.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_X', open('./animations/hands_ASL_X.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_Y', open('./animations/hands_ASL_Y.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_Z', open('./animations/hands_ASL_Z.bvh', "r").read())

        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_1CL', open('./animations/hands_ASL_1CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_2CL', open('./animations/hands_ASL_2CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_3CL', open('./animations/hands_ASL_3CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_4CL', open('./animations/hands_ASL_4CL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_5aCL', open('./animations/hands_ASL_5aCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_5bCL', open('./animations/hands_ASL_5bCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_ACL', open('./animations/hands_ASL_ACL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_BCL', open('./animations/hands_ASL_BCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_CCL', open('./animations/hands_ASL_CCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_FCL', open('./animations/hands_ASL_FCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_ICL', open('./animations/hands_ASL_ICL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_ILYCL', open('./animations/hands_ASL_ILYCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_SCL', open('./animations/hands_ASL_SCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_VaCL', open('./animations/hands_ASL_VaCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_VbCL', open('./animations/hands_ASL_VbCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_YCL', open('./animations/hands_ASL_YCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_CbCL', open('./animations/hands_ASL_CbCL.bvh', "r").read())
        self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_TCL', open('./animations/hands_ASL_TCL.bvh', "r").read())
        
        firingstevenhigh = open('./animations/alfonse-FiringStevenHigh.bvh', "r").read()

        self.realizer.addBVHMotionToCharacter(self.name, 'FiringStevenHigh', firingstevenhigh )

        print("done")

        self.agent.reparentTo( render )
        
    def update( self ):
        self.realizer.skeletonRequested()
        skeletonHasBeenUpdated = False
        while(not skeletonHasBeenUpdated):
            #wait until skeleton can be displayed
            if(self.realizer.skeletonIsReadyToBeDisplayed(self.name)):
                self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel)
                skeletonHasBeenUpdated = True
                
        for key in self.realizer.getModifiedMorphTargets(self.name): #self.targets.keys(): # Only update the targets that have actually changed here
            #print key, "\n"
            weight = self.realizer.getMorphTargetWeight( self.name, key )
            morphTargets = self.targets[key]
            for morphTargetKey in morphTargets.keys() :
                #print(weight*morphTargets[morphTargetKey])
                morphTargetKey.setX(weight*morphTargets[morphTargetKey])
                
        #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' )
        #self.shaders.headShader.blushing.set( blushingValue )
        
    def addAnimation(self,_actorName,_animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range (self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName,i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation",_animationName,"added"
    
    def addAnimationWE(self,_actorName,_animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        agentSMRMotion = SMRPy.SMRMotion()
        agentSMRMotion.setTimeStep(0.04)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range (self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName,i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton)
            agentSMRMotion.insertSkeleton(self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation",_animationName,"added"
        SMRPy.exportMotionToBvh(_animationName+".bvh",agentSMRMotion)

    def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None,_initialJointName)

        currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName)
        self.agentControlJoints.append(currentPandaCJoint)
        #get the first joint's position
        position = currentPandaCJoint.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(),position.getY(),position.getZ());
        else:  
            newJoint = SMRPy.SMRJoint(False)

        rotZ = (currentPandaCJoint.getH()/180.0)*3.14159;
        rotX = (currentPandaCJoint.getP()/180.0)*3.14159;
        rotY = (currentPandaCJoint.getR()/180.0)*3.14159;

        quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,0.0,1.0),rotZ)
        quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0,0.0,0.0),rotX)
        quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,1.0,0.0),rotY)

        quatRot = quatZ.multiply(quatX)
        quatRot = quatRot.multiply(quatY)
        quatRot.normalize();

        newJoint.setPos(position.getX(),position.getY(),position.getZ())
        newJoint.setRotQuat(quatRot.getW(),quatRot.getX(),quatRot.getY(),quatRot.getZ())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        self.jointList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName)
        
    def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName, "lodRoot", True)
        self.agentNodePaths.append(currentPandaJointPath)
        #get the first joint's position
        position = currentPandaJointPath.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(),position.getY(),position.getZ());
        else:  
            newJoint = SMRPy.SMRJoint(False)

        quatRot = currentPandaJointPath.getQuat()

        newJoint.setPos(position.getX(),position.getY(),position.getZ())
        newJoint.setRotQuat(quatRot.getR(),quatRot.getI(),quatRot.getJ(),quatRot.getK())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        self.jointFKList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName)

    def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton):

        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentControlJoints[0]
        position = SMRJoint.getPos() 
        PANDAJoint.setPos(position.X(),position.Y(),position.Z());

        for i in range(_smrSkeleton.getNumjoints()):
          SMRJoint = _smrSkeleton.getJoint(i)
          PANDAJoint = agentControlJoints[i]
          self.synchronize(PANDAJoint,SMRJoint)

    def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton):
        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentNodePaths[0]
        position = PANDAJoint.getPos() 
        SMRJoint.setPos(position.getX(),position.getY(),position.getZ());

        for i in range(_smrSkeleton.getNumjoints()):
          SMRJoint = _smrSkeleton.getJoint(i)
          PANDAJoint = agentNodePaths[i]
          self.synchronizePandaToSMR(SMRJoint,PANDAJoint)

    def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint):
        pandaQuaternion = _PANDAJoint.getQuat()
        x = pandaQuaternion.getI()
        y = pandaQuaternion.getJ()
        z = pandaQuaternion.getK()
        w = pandaQuaternion.getR()
        _SMRJoint.setRotQuat(w,x,y,z)

    def synchronize(self, _pandaCJoint, _smrJoint):
        smrQuaternion = _smrJoint.getRot()
        pandaQuaternion = Quat()
        pandaQuaternion.setI(smrQuaternion.getX())
        pandaQuaternion.setJ(smrQuaternion.getY())
        pandaQuaternion.setK(smrQuaternion.getZ())
        pandaQuaternion.setR(smrQuaternion.getW())
        if not(pandaQuaternion.isNan()):
            _pandaCJoint.setQuat(pandaQuaternion)
Beispiel #38
0
class Character:

    """A character with an animated avatar that moves left, right or forward
       according to the controls turned on or off in self.controlMap.

    Public fields:
    self.controlMap -- The character's movement controls
    self.actor -- The character's Actor (3D animated model)

    Public functions:
    __init__ -- Initialise the character
    move -- Move and animate the character for one frame. This is a task
            function that is called every frame by Panda3D.
    setControl -- Set one of the character's controls on or off.

    """
    
    
    def __init__(self, agent_simulator, model, actions, startPos, scale):
        """Initialize the character.

        Arguments:
        model -- The path to the character's model file (string)
           run : The path to the model's run animation (string)
           walk : The path to the model's walk animation (string)
           startPos : Where in the world the character will begin (pos)
           scale : The amount by which the size of the model will be scaled 
                   (float)

           """

        self.agent_simulator = agent_simulator
	
        self.controlMap = {"turn_left":0, "turn_right":0, "move_forward":0, "move_backward":0,\
                           "look_up":0, "look_down":0, "look_left":0, "look_right":0}

        self.actor = Actor(model,actions)
        self.actor.reparentTo(render)
        self.actor.setScale(scale)
        self.actor.setPos(startPos)
        
        self.actor.setHpr(0,0,0)
    

        # Expose agent's right hand joint to attach objects to 
        self.actor_right_hand = self.actor.exposeJoint(None, 'modelRoot', 'RightHand')
        self.actor_left_hand  = self.actor.exposeJoint(None, 'modelRoot', 'LeftHand')
        
        self.right_hand_holding_object = False
        self.left_hand_holding_object  = False

        # speech bubble
        self.last_spoke = 0
        self.speech_bubble=DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3,3), relief=None, text_scale=(.5,.5), pos = (0,0,6), frameColor=(.6,.2,.1,.5), textMayChange=1, text_frame=(0,0,0,1), text_bg=(1,1,1,1))
        self.speech_bubble.component('text0').textNode.setCardDecal(1)
        self.speech_bubble.setBillboardAxis()
        
        # visual processing
        self.actor_eye = self.actor.exposeJoint(None, 'modelRoot', 'LeftEyeLid')
        # put a camera on ralph
        self.fov = NodePath(Camera('RaphViz'))
        self.fov.reparentTo(self.actor_eye)
        self.fov.setHpr(180,0,0)
        #lens = OrthographicLens()
        #lens.setFilmSize(20,15)
        #self.fov.node().setLens(lens)
        lens = self.fov.node().getLens()
        lens.setFov(60) #  degree field of view (expanded from 40)
        lens.setNear(0.2)
        #self.fov.node().showFrustum() # displays a box around his head


        self.actor_neck = self.actor.controlJoint(None, 'modelRoot', 'Neck')
	
        # Define subpart of agent for when he's standing around
        self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"])
        taskMgr.add(self.move,"moveTask") # Note: deriving classes DO NOT need
                                          # to add their own move tasks to the
                                          # task manager. If they override
                                          # self.move, then their own self.move
                                          # function will get called by the
                                          # task manager (they must then
                                          # explicitly call Character.move in
                                          # that function if they want it).
        self.prevtime = 0
        self.isMoving = False
	
        self.current_frame_count = 0.0
	
        # We will detect the height of the terrain by creating a collision
        # ray and casting it downward toward the terrain.  One ray will
        # start above ralph's head, and the other will start above the camera.
        # A ray may hit the terrain, or it may hit a rock or a tree.  If it
        # hits the terrain, we can detect the height.  If it hits anything
        # else, we rule that the move is illegal.
        
        self.initialize_collision_handling()

    def initialize_collision_handling(self):
        self.collision_handling_mutex = Lock()
        
        self.cTrav = CollisionTraverser()
        
        self.groundRay = CollisionRay()
        self.groundRay.setOrigin(0,0,1000)
        self.groundRay.setDirection(0,0,-1)
        self.groundCol = CollisionNode('ralphRay')
        self.groundCol.setIntoCollideMask(BitMask32.bit(0))
        self.groundCol.setFromCollideMask(BitMask32.bit(0))
        self.groundCol.addSolid(self.groundRay)
        self.groundColNp = self.actor.attachNewNode(self.groundCol)
        self.groundHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.groundColNp, self.groundHandler)

        # Uncomment this line to see the collision rays
        # self.groundColNp.show()

        #Uncomment this line to show a visual representation of the 
        #collisions occuring
        # self.cTrav.showCollisions(render)

    def destroy_collision_handling(self):
        self.collision_handling_mutex.acquire()
    
    def handle_collisions(self):
        self.collision_handling_mutex.acquire()
        self.groundCol.setIntoCollideMask(BitMask32.bit(0))
        self.groundCol.setFromCollideMask(BitMask32.bit(1))

        # Now check for collisions.
        self.cTrav.traverse(render)
        
        # Adjust the character's Z coordinate.  If the character's ray hit terrain,
        # update his Z. If it hit anything else, or didn't hit anything, put
        # him back where he was last frame.
        
        entries = []
        for i in range(self.groundHandler.getNumEntries()):
            entry = self.groundHandler.getEntry(i)
            entries.append(entry)
        entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                     x.getSurfacePoint(render).getZ()))
        if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
            self.actor.setZ(entries[0].getSurfacePoint(render).getZ())
        else:
            self.actor.setPos(self.startpos)
        
        self.groundCol.setIntoCollideMask(BitMask32.bit(0))
        self.groundCol.setFromCollideMask(BitMask32.bit(0))
        self.collision_handling_mutex.release()

    def position(self):
        return self.actor.getPos()
	
    def forward_normal_vector(self):
        backward = self.actor.getNetTransform().getMat().getRow3(1)
        backward.setZ(0)
        backward.normalize()
        return -backward

    def step_simulation_time(self, seconds):
        # save the character's initial position so that we can restore it,
        # in case he falls off the map or runs into something.

        self.startpos = self.actor.getPos()

        def bound(i, mn = -1, mx = 1): return min(max(i, mn), mx) # enforces bounds on a numeric value
        # move the character if any of the move controls are activated.

        if (self.controlMap["turn_left"]!=0):
            self.actor.setH(self.actor.getH() + seconds*30)
        if (self.controlMap["turn_right"]!=0):
            self.actor.setH(self.actor.getH() - seconds*30)
        if (self.controlMap["move_forward"]!=0):
            self.actor.setPos(self.actor.getPos() + self.forward_normal_vector() * (seconds*0.5))
        if (self.controlMap["move_backward"]!=0):
            self.actor.setPos(self.actor.getPos() - self.forward_normal_vector() * (seconds*0.5))
        if (self.controlMap["look_left"]!=0):
            self.actor_neck.setP(bound(self.actor_neck.getP(),-60,60)+1*(seconds*50))
        if (self.controlMap["look_right"]!=0):
            self.actor_neck.setP(bound(self.actor_neck.getP(),-60,60)-1*(seconds*50))
        if (self.controlMap["look_up"]!=0):
            self.actor_neck.setH(bound(self.actor_neck.getH(),-60,80)+1*(seconds*50))
        if (self.controlMap["look_down"]!=0):
            self.actor_neck.setH(bound(self.actor_neck.getH(),-60,80)-1*(seconds*50))

        # allow dialogue window to gradually decay (changing transparancy) and then disappear
        self.last_spoke += seconds
        self.speech_bubble['text_bg']=(1,1,1,1/(2*self.last_spoke+0.01))
        self.speech_bubble['frameColor']=(.6,.2,.1,.5/(2*self.last_spoke+0.01))
        if self.last_spoke > 2:
            self.speech_bubble['text'] = ""

        # If the character is moving, loop the run animation.
        # If he is standing still, stop the animation.
	
        if (self.controlMap["move_forward"]!=0) or (self.controlMap["move_backward"]!=0):
            if self.isMoving is False:
                self.isMoving = True
        else:
            if self.isMoving:
                self.current_frame_count = 5.0
                self.isMoving = False
	
	total_frame_num = self.actor.getNumFrames('walk')
	if self.isMoving:
		self.current_frame_count = self.current_frame_count + (seconds*10.0)
		while (self.current_frame_count >= total_frame_num + 1):
			self.current_frame_count -= total_frame_num
		while (self.current_frame_count < 0):
			self.current_frame_count += total_frame_num
	self.actor.pose('walk', self.current_frame_count)
	
        self.handle_collisions()

    def move(self, task):
        """Move and animate the character for one frame.

        This is a task function that is called every frame by Panda3D.
        The character is moved according to which of it's movement controls
        are set, and the function keeps the character's feet on the ground
        and stops the character from moving if a collision is detected.
        This function also handles playing the characters movement
        animations.

        Arguments:
        task -- A direct.task.Task object passed to this function by Panda3D.

        Return:
        Task.cont -- To tell Panda3D to call this task function again next
                     frame.
        """

        elapsed = task.time - self.prevtime

        # Store the task time and continue.
        self.prevtime = task.time
        return Task.cont
    
    def setControl(self, control, value):
        """Set the state of one of the character's movement controls.

        Arguments
        See self.controlMap in __init__.
        control -- The control to be set, must be a string matching one of
                   the strings in self.controlMap.
        value -- The value to set the control to.

        """

        # FIXME: this function is duplicated in Camera and Character, and
        # keyboard control settings are spread throughout the code. Maybe
        # add a Controllable class?

        self.controlMap[control] = value

    # these are simple commands that can be exported over xml-rpc (or attached to the keyboard)


    def get_objects(self):
        """ Looks up all of the model nodes that are 'isInView' of the camera
        and returns them in the in_view dictionary (as long as they are also
        in the self.world_objects -- otherwise this includes points defined
        within the environment/terrain). 

        TODO:  1) include more geometric information about the object (size, mass, etc)
        """

        def map3dToAspect2d(node, point):
            """Maps the indicated 3-d point (a Point3), which is relative to 
            the indicated NodePath, to the corresponding point in the aspect2d 
            scene graph. Returns the corresponding Point3 in aspect2d. 
            Returns None if the point is not onscreen. """ 
            # Convert the point to the 3-d space of the camera 
            p3 = self.fov.getRelativePoint(node, point) 

            # Convert it through the lens to render2d coordinates 
            p2 = Point2()
            if not self.fov.node().getLens().project(p3, p2):
                return None 
            r2d = Point3(p2[0], 0, p2[1])
            # And then convert it to aspect2d coordinates 
            a2d = aspect2d.getRelativePoint(render2d, r2d)
            return a2d

        objs = render.findAllMatches("**/+ModelNode")
        in_view = {}
        for o in objs:
            o.hideBounds() # in case previously turned on
            o_pos = o.getPos(self.fov)
            if self.fov.node().isInView(o_pos):
                if self.agent_simulator.world_objects.has_key(o.getName()):
                    b_min, b_max =  o.getTightBounds()
                    a_min = map3dToAspect2d(render, b_min)
                    a_max = map3dToAspect2d(render, b_max)
                    if a_min == None or a_max == None:
                        continue
                    x_diff = math.fabs(a_max[0]-a_min[0])
                    y_diff = math.fabs(a_max[2]-a_min[2])
                    area = 100*x_diff*y_diff  # percentage of screen
                    object_dict = {'x_pos': (a_min[2]+a_max[2])/2.0,\
                                   'y_pos': (a_min[0]+a_max[0])/2.0,\
                                   'distance':o.getDistance(self.fov), \
                                   'area':area,\
                                   'orientation': o.getH(self.fov)}
                    in_view[o.getName()]=object_dict
                    print o.getName(), object_dict
        return in_view

    def control__turn_left__start(self):
        self.setControl("turn_left",  1)
        self.setControl("turn_right", 0)

    def control__turn_left__stop(self):
        self.setControl("turn_left",  0)

    def control__turn_right__start(self):
        self.setControl("turn_left",  0)
        self.setControl("turn_right", 1)

    def control__turn_right__stop(self):
        self.setControl("turn_right", 0)

    def control__move_forward__start(self):
        self.setControl("move_forward",  1)
        self.setControl("move_backward", 0)

    def control__move_forward__stop(self):
        self.setControl("move_forward",  0)

    def control__move_backward__start(self):
        self.setControl("move_forward",  0)
        self.setControl("move_backward", 1)

    def control__move_backward__stop(self):
        self.setControl("move_backward", 0)

    def control__look_left__start(self):
        self.setControl("look_left",  1)
        self.setControl("look_right", 0)

    def control__look_left__stop(self):
        self.setControl("look_left",  0)

    def control__look_right__start(self):
        self.setControl("look_right",  1)
        self.setControl("look_left", 0)

    def control__look_right__stop(self):
        self.setControl("look_right",  0)

    def control__look_up__start(self):
        self.setControl("look_up",  1)
        self.setControl("look_down", 0)

    def control__look_up__stop(self):
        self.setControl("look_up",  0)
    
    def control__look_down__start(self):
        self.setControl("look_down",  1)
        self.setControl("look_up",  0)
    
    def control__look_down__stop(self):
        self.setControl("look_down",  0)

    def can_grasp(self, object_name):
        objects = self.get_objects()
        if objects.has_key(object_name):
            object_view = objects[object_name]
            distance = object_view['distance']
            if (distance < 5.0):
                return True
        return False

    def control__say(self, message):
       self.speech_bubble['text'] = message
       self.last_spoke = 0

    def control__pick_up_with_right_hand(self, pick_up_object):
        print "attempting to pick up " + pick_up_object + " with right hand.\n"
        if self.right_hand_holding_object:
            return 'right hand is already holding ' + self.right_hand_holding_object.getName() + '.'
	if self.can_grasp(pick_up_object):
	    world_object = self.agent_simulator.world_objects[pick_up_object]
	    object_parent = world_object.getParent()
	    if (object_parent == self.agent_simulator.env):
		world_object.wrtReparentTo(self.actor_right_hand)
		world_object.setPos(0, 0, 0)
		world_object.setHpr(0, 0, 0)
		self.right_hand_holding_object = world_object
		return 'success'
	    else:
		return 'object (' + pick_up_object + ') is already held by something or someone.'
	else:
	    return 'object (' + pick_up_object + ') is not graspable (i.e. in view and close enough).'

    def put_object_in_empty_left_hand(self, object_name):
	if (self.left_hand_holding_object is not False):
	    return False
	world_object = self.agent_simulator.world_objects[object_name]
	world_object.wrtReparentTo(self.actor_left_hand)
	world_object.setPos(0, 0, 0)
	world_object.setHpr(0, 0, 0)
	self.left_hand_holding_object = world_object
	return True
    
    def control__pick_up_with_left_hand(self, pick_up_object):
        print "attempting to pick up " + pick_up_object + " with left hand.\n"
        if self.left_hand_holding_object:
            return 'left hand is already holding ' + self.left_hand_holding_object.getName() + '.'
        if self.can_grasp(pick_up_object):
	    world_object = self.agent_simulator.world_objects[pick_up_object]
	    object_parent = world_object.getParent()
	    if (object_parent == self.agent_simulator.env):
		self.put_object_in_empty_left_hand(pick_up_object)
		return 'success'
	    else:
		return 'object (' + pick_up_object + ') is already held by something or someone.'
        else:
            return 'object (' + pick_up_object + ') is not graspable (i.e. in view and close enough).'

    def control__drop_from_right_hand(self):
        print "attempting to drop object from right hand.\n"
        if self.right_hand_holding_object is False:
            return 'right hand is not holding an object.'
        world_object = self.right_hand_holding_object
        self.right_hand_holding_object = False
        world_object.wrtReparentTo(self.agent_simulator.env)
        world_object.setHpr(0, 0, 0)
        world_object.setPos(self.position() + self.forward_normal_vector() * 0.5)
        world_object.setZ(world_object.getZ() + 1.0)
        return 'success'
    
    def control__drop_from_left_hand(self):
        print "attempting to drop object from left hand.\n"
        if self.left_hand_holding_object is False:
            return 'left hand is not holding an object.'
        world_object = self.left_hand_holding_object
        self.left_hand_holding_object = False
        world_object.wrtReparentTo(self.agent_simulator.env)
        world_object.setHpr(0, 0, 0)
        world_object.setPos(self.position() + self.forward_normal_vector() * 0.5)
        world_object.setZ(world_object.getZ() + 1.0)
	return 'success'

    def is_holding(self, object_name):
	return ((self.left_hand_holding_object  and (self.left_hand_holding_object.getName()  == object_name)) or
		(self.right_hand_holding_object and (self.right_hand_holding_object.getName() == object_name)))
    
    def empty_hand(self):
        if (self.left_hand_holding_object is False):
            return self.actor_left_hand
        elif (self.right_hand_holding_object is False):
            return self.actor_right_hand
        return False

    def has_empty_hand(self):
        return (self.empty_hand() is not False)

    def control__use_object_with_object(self, use_object, with_object):
	if ((use_object == 'knife') and (with_object == 'loaf_of_bread')):
	    if self.is_holding('knife'):
		if self.can_grasp('loaf_of_bread'):
		    if self.has_empty_hand():
			empty_hand      = self.empty_hand()
			new_object_name = self.agent_simulator.create_object__slice_of_bread([float(x) for x in empty_hand.getPos()])
			if (empty_hand == self.actor_left_hand):
			    self.put_object_in_empty_left_hand(new_object_name)
			elif (empty_hand == self.actor_right_hand):
			    self.put_object_in_empty_right_hand(new_object_name)
			else:
			    return "simulator error: empty hand is not left or right.  (are there others?)"
			return 'success'
		    else:
			return 'failure: one hand must be empty to hold loaf_of_bread in place while using knife.'
		else:
		    return 'failure: loaf of bread is not graspable (in view and close enough)'
	    else:
		return 'failure: must be holding knife object to use it.'
        return 'failure: don\'t know how to use ' + use_object + ' with ' + with_object + '.'
Beispiel #39
0
class LookingGrippingDemo(ShowBase):
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)

        # This code puts the standard title and instruction text on screen
        self.title = OnscreenText(
            text="Panda3D: Tutorial - Joint Manipulation",
            fg=(1, 1, 1, 1),
            parent=base.a2dBottomRight,
            align=TextNode.ARight,
            pos=(-0.1, 0.1),
            shadow=(0, 0, 0, .5),
            scale=.08)

        self.onekeyText = genLabelText("ESC: Quit", 1)
        self.onekeyText = genLabelText("[1]: Teapot", 2)
        self.twokeyText = genLabelText("[2]: Candy cane", 3)
        self.threekeyText = genLabelText("[3]: Banana", 4)
        self.fourkeyText = genLabelText("[4]: Sword", 5)

        # Set up key input
        self.accept('escape', sys.exit)
        self.accept('1', self.switchObject, [0])
        self.accept('2', self.switchObject, [1])
        self.accept('3', self.switchObject, [2])
        self.accept('4', self.switchObject, [3])

        base.disableMouse()  # Disable mouse-based camera-control
        camera.setPos(0, -15, 2)  # Position the camera

        self.eve = Actor(
            "models/eve",  # Load our animated charachter
            {'walk': "models/eve_walk"})
        self.eve.reparentTo(render)  # Put it in the scene

        # Now we use controlJoint to get a NodePath that's in control of her neck
        # This must be done before any animations are played
        self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck')

        # We now play an animation. An animation must be played, or at least posed
        # for the nodepath we just got from controlJoint to actually effect the
        # model
        self.eve.actorInterval("walk", playRate=2).loop()

        # Now we add a task that will take care of turning the head
        taskMgr.add(self.turnHead, "turnHead")

        # Now we will expose the joint the hand joint. ExposeJoint allows us to
        # get the position of a joint while it is animating. This is different than
        # controlJonit which stops that joint from animating but lets us move it.
        # This is particularly usefull for putting an object (like a weapon) in an
        # actor's hand
        self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand')

        # This is a table with models, positions, rotations, and scales of objects to
        # be attached to our exposed joint. These are stock models and so they needed
        # to be repositioned to look right.
        positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4),
                     ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1),
                     ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75),
                     ("models/sword", (.11, .19, .06), (0, 0, 90), 1)]

        self.models = []  # A list that will store our models objects
        for row in positions:
            np = loader.loadModel(row[0])  # Load the model
            np.setPos(row[1][0], row[1][1], row[1][2])  # Position it
            np.setHpr(row[2][0], row[2][1], row[2][2])  # Rotate it
            np.setScale(row[3])  # Scale it
            # Reparent the model to the exposed joint. That way when the joint moves,
            # the model we just loaded will move with it.
            np.reparentTo(self.rightHand)
            self.models.append(np)  # Add it to our models list

        self.switchObject(0)  # Make object 0 the first shown
        self.setupLights()  # Put in some default lighting

    # This is what we use to change which object it being held. It just hides all of
    # the objects and then unhides the one that was selected
    def switchObject(self, i):
        for np in self.models:
            np.hide()
        self.models[i].show()

    # This task gets the position of mouse each frame, and rotates the neck based
    # on it.
    def turnHead(self, task):
        # Check to make sure the mouse is readable
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position as a LVector2. The values for each axis are from -1 to
            # 1. The top-left is (-1,-1), the bottom right is (1,1)
            mpos = base.mouseWatcherNode.getMouse()
            # Here we multiply the values to get the amount of degrees to turn
            # Restrain is used to make sure the values returned by getMouse are in the
            # valid range. If this particular model were to turn more than this,
            # significant tearing would be visable
            self.eveNeck.setP(clamp(mpos.getX()) * 50)
            self.eveNeck.setH(clamp(mpos.getY()) * 20)

        return Task.cont  # Task continues infinitely

    def setupLights(self):  # Sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.4, .4, .35, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 8, -2.5))
        directionalLight.setColor((0.9, 0.8, 0.9, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Beispiel #40
0
    def __init__(self):
        ShowBase.__init__(self)

        self.dirTypes = ['heading', 'pitch', 'roll']
        self.dirType = 0

        # Display instructions
        add_title("Panda3D Tutorial: Portal Culling")
        add_instructions(0.06, "[Esc]: Quit")
        self.posText = add_instructions(0.12, "pos")
        self.anglesText = add_instructions(0.18, "angle")
        self.armHprText = add_instructions(0.24, "hpr")
        self.dirText = add_instructions(.30, self.dirTypes[0])
        self.forearmText = add_instructions(0.36, "angle")
        self.baseText = add_instructions(0.42, "angle")
        """add_instructions(0.12, "[W]: Move Forward")
        add_instructions(0.18, "[A]: Move Left")
        add_instructions(0.24, "[S]: Move Right")
        add_instructions(0.30, "[D]: Move Back")
        add_instructions(0.36, "Arrow Keys: Look Around")
        add_instructions(0.42, "[F]: Toggle Wireframe")
        add_instructions(0.48, "[X]: Toggle X-Ray Mode")
        add_instructions(0.54, "[B]: Toggle Bounding Volumes")"""

        # Setup controls
        self.keys = {}
        for key in ['arrow_left', 'arrow_right', 'arrow_up', 'arrow_down',
                    'a', 'd', 'w', 's', 'q', 'e']:
            self.keys[key] = 0
            self.accept(key, self.push_key, [key, 1])
            self.accept('shift-%s' % key, self.push_key, [key, 1])
            self.accept('%s-up' % key, self.push_key, [key, 0])

        self.accept("b", self.push_key, ["Rleft", True])
        self.accept("b-up", self.push_key, ["Rleft", False])
        self.accept("n", self.push_key, ["Rright", True])
        self.accept("n-up", self.push_key, ["Rright", False])
        self.accept("h", self.push_key, ["Rforward", True])
        self.accept("h-up", self.push_key, ["Rforward", False])
        self.keys['Rleft'] = self.keys['Rright'] = self.keys['Rforward'] = 0

        self.accept('escape', self.exitButton)
        self.accept('p', self.selectDir)
        self.accept('[', self.incDir, [-15])
        self.accept(']', self.incDir, [15])
        #self.disableMouse()

        # Setup camera
        lens = PerspectiveLens()
        lens.setFov(60)
        lens.setNear(0.01)
        lens.setFar(1000.0)
        self.cam.node().setLens(lens)
        self.camera.setPos(-50, 0, 0)
        self.pitch = 0.0
        self.heading = 0
        
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.3, .3, .3, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection((-5, -5, -5))
        directionalLight.setColor((1, 1, 1, 1))
        directionalLight.setSpecularColor((1, 1, 1, 1))
        render.setLight(render.attachNewNode(ambientLight))
        render.setLight(render.attachNewNode(directionalLight))

        # Load level geometry
        self.level = self.loader.loadModel('models/theater')
        self.level.reparentTo(self.render)

        self.isMoving = False
        self.ralph = Actor("models/ralph",
                           {"run": "models/ralph-run",
                            "walk": "models/ralph-walk"})
        self.ralph.reparentTo(render)
        self.ralph.setScale(.2)


        self.arms = []
        idMap = {0:9, 1:11, 2:17, 3:27, 4:29}

        for node in self.level.get_children():
          if not node.getName().startswith('arm'): continue
          arm = Actor("models/robotarm")
          self.arms.append(arm)
          arm.reparentTo(render)
          arm.setName(node.getName())
          arm.setPos(node.getPos())
          arm.setHpr(node.getHpr())
          #arm.setScale(.2)

          tokens = node.getName().split('.')
          try: id = int(tokens[1])
          except: id = 0
          arm.baseID = idMap[id]

          arm.jointForearm = arm.controlJoint(None, "modelRoot", "forearm")
          arm.jointBase = arm.controlJoint(None, "modelRoot", "base")
          print node.getName(), str(node.getPos()), str(node.getHpr())
   
        taskMgr.add(self.printLoc, "printLoc")
        taskMgr.add(self.monitorArms, "robot arms")
        self.taskMgr.add(self.update, 'main loop')
Beispiel #41
0
class DistributedPartyTrampolineActivity(DistributedPartyActivity):
    notify = DirectNotifyGlobal.directNotify.newCategory(
        "DistributedPartyTrampolineActivity")

    def __init__(self, cr, doJellyBeans=True, doTricks=False, texture=None):
        DistributedPartyTrampolineActivity.notify.debug("__init__")
        DistributedPartyActivity.__init__(
            self,
            cr,
            PartyGlobals.ActivityIds.PartyTrampoline,
            PartyGlobals.ActivityTypes.GuestInitiated,
            wantLever=False,
            wantRewardGui=True,
        )

        self.doJellyBeans = doJellyBeans
        self.doTricks = doTricks
        self.texture = texture

        self.toon = None
        self.trampHeight = 3.6
        self.trampK = 400.0  # spring constant
        self.normalTrampB = 2.5  # spring damping
        self.leavingTrampB = 8.0  # increase damping to slow toon faster when leaving
        self.trampB = self.normalTrampB
        self.g = -32.0  # acceleration due to gravity
        self.jumpBoost = 330.0
        self.beginningBoost = 500.0
        self.beginningBoostThreshold = self.trampHeight + 1.5
        self.earlyJumpThreshold = 75.0
        self.boingThreshold = 300.0
        self.turnFactor = 120.0
        self.stepDT = 0.001
        self.targetCameraPos = Point3(0.0, 40.0, 10.0)  # relative to toon
        self.cameraSpeed = 2.0
        self.hopOffPos = Point3(16.0, 0.0, 0.0)  # relative to tramp
        self.indicatorFactor = 0.0095
        self.dropShadowCutoff = 15.0
        self.minHeightForText = 15.0
        self.heightTextOffset = -0.065
        self.beanOffset = 0.5
        self.guiBeanOffset = -0.02

        self.jumpTextShown = False
        self.toonJumped = False
        self.turnLeft = False
        self.turnRight = False
        self.leavingTrampoline = False
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.lastPeak = 0.0
        self.beginRoundInterval = None
        self.hopOnAnim = None
        self.hopOffAnim = None
        self.flashTextInterval = None

        # Jelly Beans
        self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans  # These are in PartyGlobals so they can be available to the AI.
        self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus
        self.jellyBeanStartHeight = 20.0
        self.jellyBeanStopHeight = 90.0
        self.jellyBeanColors = [
            VBase4(1.0, 0.5, 0.5, 1.0),
            VBase4(0.5, 1.0, 0.5, 1.0),
            VBase4(0.5, 1.0, 1.0, 1.0),
            VBase4(1.0, 1.0, 0.4, 1.0),
            VBase4(0.4, 0.4, 1.0, 1.0),
            VBase4(1.0, 0.5, 1.0, 1.0),
        ]
        delta = (self.jellyBeanStopHeight -
                 self.jellyBeanStartHeight) / (self.numJellyBeans - 1)
        self.jellyBeanPositions = [
            self.jellyBeanStartHeight + n * delta
            for n in range(self.numJellyBeans)
        ]
        self.doSimulateStep = False

#        import sys
#        sys.path.append( "C:\\pratt\\SchellGames\\perforce\\depot\\Tools\\PandaMisc" )
#        from Reloader import Reloader
#        self.reloader = Reloader( "C:\\cygwin\\home\\pratt\\player_working\\toontown\\src\\parties" )

#---------------------------------------------------
# Loading
#---------------------------------------------------

    def load(self):
        DistributedPartyTrampolineActivity.notify.debug("load")
        DistributedPartyActivity.load(self)

        self.loadModels()
        self.loadCollision()
        self.loadGUI()
        self.loadSounds()
        self.loadIntervals()

        self.activityFSM = TrampolineActivityFSM(self)
        self.activityFSM.request("Idle")

        self.animFSM = TrampolineAnimFSM(self)

        self.setBestHeightInfo("", 0)

    def loadModels(self):
        self.tramp = self.root.attachNewNode(self.uniqueName("tramp"))

        self.screenPlaneElements = NodePath(self.uniqueName("screenPlane"))

        self.trampActor = Actor(
            "phase_13/models/parties/trampoline_model",
            {"emptyAnim": "phase_13/models/parties/trampoline_anim"},
        )
        self.trampActor.reparentTo(self.tramp)

        # Allow reskinning.
        if self.texture:
            reskinNode = self.tramp.find(
                "**/trampoline/__Actor_modelRoot/-GeomNode")
            reskinNode.setTexture(loader.loadTexture(self.texture), 100)

        self.surface = NodePath(self.uniqueName("trampSurface"))
        self.surface.reparentTo(self.tramp)
        self.surface.setZ(self.trampHeight)
        self.trampActor.controlJoint(self.surface, "modelRoot",
                                     "trampoline_joint1")

        self.sign.setPos(PartyGlobals.TrampolineSignOffset)

        self.beans = [
            loader.loadModelCopy("phase_4/models/props/jellybean4")
            for i in range(self.numJellyBeans)
        ]
        for bean in self.beans:
            bean.find("**/jellybean").setP(-35.0)
            bean.setScale(3.0)
            bean.setTransparency(True)
            bean.reparentTo(self.tramp)
            bean.stash()
        self.beans[-1].setScale(8.0)

    def loadCollision(self):
        collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4)
        collTube.setTangible(True)
        self.trampolineCollision = CollisionNode(
            self.uniqueName("TrampolineCollision"))
        self.trampolineCollision.addSolid(collTube)
        self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask
                                                | OTPGlobals.WallBitmask)
        self.trampolineCollisionNP = self.tramp.attachNewNode(
            self.trampolineCollision)

        collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0)
        collSphere.setTangible(False)
        self.trampolineTrigger = CollisionNode(
            self.uniqueName("TrampolineTrigger"))
        self.trampolineTrigger.addSolid(collSphere)
        self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.trampolineTriggerNP = self.tramp.attachNewNode(
            self.trampolineTrigger)
        self.accept("enter%s" % self.uniqueName("TrampolineTrigger"),
                    self.onTrampolineTrigger)

    def loadGUI(self):
        self.gui = loader.loadModel("phase_13/models/parties/trampolineGUI")
        self.gui.reparentTo(base.a2dTopLeft)
        self.gui.setPos(0.115, 0, -1)
        self.gui.hide()

        self.toonIndicator = self.gui.find("**/trampolineGUI_MovingBar")
        jumpLineLocator = self.gui.find("**/jumpLine_locator")
        guiBean = self.gui.find("**/trampolineGUI_GreenJellyBean")

        self.gui.find("**/trampolineGUI_GreenJellyBean").stash(
        )  # sadly, the white jelly bean is named GreenJellyBean

        self.guiBeans = [
            guiBean.instanceUnderNode(jumpLineLocator,
                                      self.uniqueName("guiBean%d" % i))
            for i in range(self.numJellyBeans)
        ]
        self.guiBeans[-1].setScale(1.5)

        heightTextNode = TextNode(
            self.uniqueName("TrampolineActivity.heightTextNode"))
        heightTextNode.setFont(ToontownGlobals.getSignFont())
        heightTextNode.setAlign(TextNode.ALeft)
        heightTextNode.setText("0.0")
        heightTextNode.setShadow(0.05, 0.05)
        heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0)
        heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0)
        self.heightText = jumpLineLocator.attachNewNode(heightTextNode)
        self.heightText.setX(0.15)
        self.heightText.setScale(0.1)
        self.heightText.setAlphaScale(0.0)

        self.quitEarlyButtonModels = loader.loadModel(
            "phase_3.5/models/gui/inventory_gui")
        quitEarlyUp = self.quitEarlyButtonModels.find("**//InventoryButtonUp")
        quitEarlyDown = self.quitEarlyButtonModels.find(
            "**/InventoryButtonDown")
        quitEarlyRollover = self.quitEarlyButtonModels.find(
            "**/InventoryButtonRollover")
        self.quitEarlyButton = DirectButton(
            parent=base.a2dTopRight,
            relief=None,
            text=TTLocalizer.PartyTrampolineQuitEarlyButton,
            text_fg=(1, 1, 0.65, 1),
            text_pos=(0, -0.23),
            text_scale=0.7,
            image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover),
            image_color=(1, 0, 0, 1),
            image_scale=(20, 1, 11),
            pos=(-0.183, 0, -0.4),
            scale=0.09,
            command=self.leaveTrampoline,
        )
        self.quitEarlyButton.stash()

        self.flashText = OnscreenText(
            text="",
            pos=(0.0, -0.45),
            scale=0.2,
            fg=(1.0, 1.0, 0.65, 1.0),
            align=TextNode.ACenter,
            font=ToontownGlobals.getSignFont(),
            mayChange=True,
        )

        self.timer = PartyUtils.getNewToontownTimer()
        self.timer.reparentTo(self.screenPlaneElements)

    def loadSounds(self):
        self.jellyBeanSound = base.loader.loadSfx(
            "phase_4/audio/sfx/sparkly.mp3")
        self.boingSound = base.loader.loadSfx(
            "phase_4/audio/sfx/target_trampoline_2.mp3")
        self.whistleSound = base.loader.loadSfx(
            "phase_4/audio/sfx/AA_sound_whistle.mp3")

    def loadIntervals(self):
        def prepareHeightText():
            self.heightText.node().setText(
                TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ()))
            self.heightText.setZ(self.indicatorFactor * self.toon.getZ() +
                                 self.heightTextOffset)

        self.heightTextInterval = Sequence(
            Func(prepareHeightText),
            LerpFunc(self.heightText.setAlphaScale,
                     fromData=1.0,
                     toData=0.0,
                     duration=1.0),
        )

    def unload(self):
        DistributedPartyTrampolineActivity.notify.debug("unload")
        if self.hopOnAnim and self.hopOnAnim.isPlaying():
            self.hopOnAnim.finish()
        if self.hopOffAnim and self.hopOffAnim.isPlaying():
            self.hopOffAnim.finish()
        if self.beginRoundInterval and self.beginRoundInterval.isPlaying():
            self.beginRoundInterval.finish()
        if self.flashTextInterval and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        if self.heightTextInterval and self.heightTextInterval.isPlaying():
            self.heightTextInterval.finish()
        self.timer.stop()
        DistributedPartyActivity.unload(self)

        # Unload tasks
        taskMgr.remove(self.uniqueName("TrampolineActivity.updateTask"))
        taskMgr.remove(self.uniqueName("TrampolineActivity.remoteUpdateTask"))

        # Unload events
        self.ignoreAll()

        # Unload intervals
        del self.heightTextInterval
        del self.beginRoundInterval
        del self.hopOnAnim
        del self.hopOffAnim
        del self.flashTextInterval

        if hasattr(self, 'beanAnims'):
            # we need to cleanup the jelly bean interval
            self.cleanupJellyBeans()

        # Unload gui stuff
        self.quitEarlyButton.destroy()
        del self.quitEarlyButton
        if self.screenPlaneElements:
            self.screenPlaneElements.removeNode()
            self.screenPlaneElements = None

        # Unload fsms
        del self.activityFSM
        del self.animFSM

    #---------------------------------------------------
    # Distributed
    #---------------------------------------------------
    def setBestHeightInfo(self, toonName, height):

        if GMUtils.testGMIdentity(toonName):
            toonName = GMUtils.handleGMName(toonName)

        self.bestHeightInfo = (toonName, height)
        DistributedPartyTrampolineActivity.notify.debug(
            "%s has the best height of %d" % (toonName, height))

        if height > 0:
            self.setSignNote(TTLocalizer.PartyTrampolineBestHeight %
                             self.bestHeightInfo)
        else:
            self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet)

    def leaveTrampoline(self):
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp)
            self.leavingTrampoline = True
            self.timer.reset()
            self.trampB = self.leavingTrampB
            self.ignore("control")
            self.quitEarlyButton.stash()
            self.gui.hide()

    def requestAnim(self, request):
        self.animFSM.request(request)

    def b_requestAnim(self, request):
        self.requestAnim(request)
        self.sendUpdate("requestAnim", [request])

    def requestAnimEcho(self, request):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.requestAnim(request)

    def removeBeans(self, beansToRemove):
        for i in beansToRemove:
            height, bean, guiBean, beanAnim = self.beanDetails[i]
            guiBean.stash()
            if i in self.beansToCollect:
                self.beansToCollect.remove(i)
            else:
                self.notify.warning(
                    "removeBeans avoided a crash, %d not in self.beansToCollect"
                    % i)
            self.poofBean(bean, beanAnim)
#            bean.stash()
#            beanAnim.finish()

    def b_removeBeans(self, beansToRemove):
        self.removeBeans(beansToRemove)
        self.sendUpdate("removeBeans", [beansToRemove])

    def removeBeansEcho(self, beansToRemove):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.removeBeans(beansToRemove)

    def joinRequestDenied(self, reason):
        DistributedPartyActivity.joinRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny)
        base.cr.playGame.getPlace().fsm.request("walk")

    def exitRequestDenied(self, reason):
        DistributedPartyActivity.exitRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny)

    def setState(self, newState, timestamp):
        DistributedPartyTrampolineActivity.notify.debug(
            "setState( newState=%s, ... )" % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        self.activityFSM.request(newState)

    #---------------------------------------------------
    # FSM handling
    #---------------------------------------------------
    def startIdle(self):
        DistributedPartyTrampolineActivity.notify.debug("startIdle")

    def finishIdle(self):
        DistributedPartyTrampolineActivity.notify.debug("finishIdle")

    def startRules(self):
        DistributedPartyTrampolineActivity.notify.debug("startRules")
        if self.doJellyBeans:
            self.setupJellyBeans()
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self.acquireToon()

    def startActive(self):
        DistributedPartyTrampolineActivity.notify.debug("startActive")
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            base.setCellsAvailable(base.bottomCells, True)

            self.accept("arrow_left", self.onLeft)
            self.accept("arrow_left-up", self.onLeftUp)
            self.accept("arrow_right", self.onRight)
            self.accept("arrow_right-up", self.onRightUp)

            self.beginRoundInterval = Sequence(
                Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady),
                Wait(1.2),
                Func(self.flashMessage, TTLocalizer.PartyTrampolineGo),
                Func(self.beginRound))
            self.beginRoundInterval.start()

    def finishActive(self):
        DistributedPartyTrampolineActivity.notify.debug("finishActive")
        if self.doJellyBeans:
            self.cleanupJellyBeans()

    #---------------------------------------------------
    # FSM extras
    #---------------------------------------------------
    def setupJellyBeans(self):
        self.beanAnims = []
        self.beansToCollect = []
        self.beanDetails = []
        self.numBeansCollected = 0
        for i in range(self.numJellyBeans):
            bean = self.beans[i]
            guiBean = self.guiBeans[i]
            height = self.jellyBeanPositions[i]
            color = random.choice(self.jellyBeanColors)
            bean.find("**/jellybean").setColor(color)
            if self.toon.doId == base.localAvatar.doId:
                bean.setAlphaScale(1.0)
            else:
                bean.setAlphaScale(0.5)
            guiBean.setColor(color)
            bean.setZ(height + self.toon.getHeight() + self.beanOffset)
            guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset)
            bean.setH(0.0)
            bean.unstash()
            guiBean.unstash()
            beanAnim = bean.hprInterval(
                1.5, VBase3((((i % 2) * 2) - 1) * 360.0, 0.0, 0.0)
            )  # the (((i % 2)*2) - 1) makes adjacent beans spin opposite directions
            beanAnim.loop()
            self.beanAnims.append(beanAnim)
            self.beanDetails.append((height, bean, guiBean, beanAnim))
        self.beansToCollect = list(range(self.numJellyBeans))

    def cleanupJellyBeans(self):
        for bean in self.beans:
            bean.stash()
        for guiBean in self.guiBeans:
            guiBean.stash()
        # If handleToonJoined hasn't been sent toonId on some clients
        if hasattr(self, 'beanAnims'):
            for beanAnim in self.beanAnims:
                beanAnim.finish()
            del self.beanAnims
            del self.beansToCollect

    def beginRound(self):
        base.playSfx(self.whistleSound)

        self.timer.setTime(PartyGlobals.TrampolineDuration)
        self.timer.countdown(PartyGlobals.TrampolineDuration)
        self.timer.show()

        self.gui.show()

        self.quitEarlyButton.unstash()

        self.notify.debug("Accepting contorl")
        self.accept("control", self.onJump)
        self.notify.debug("setting simulate step to true")
        self.doSimulateStep = True

    def acquireToon(self):
        #        self.dataLog = open( "dataLog.txt", "w" )

        self.toon.disableSmartCameraViews()
        self.toon.stopUpdateSmartCamera()
        camera.wrtReparentTo(render)

        self.toon.dropShadow.reparentTo(hidden)
        self.toon.startPosHprBroadcast(period=0.2)

        self.toonAcceleration = 0.0
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.trampB = self.normalTrampB
        self.leavingTrampoline = False
        self.hopOnAnim = Sequence(
            Func(self.toon.b_setAnimState, "jump", 1.0),
            Wait(0.4),
            PartyUtils.arcPosInterval(0.75, self.toon,
                                      Point3(0.0, 0.0, self.trampHeight), 5.0,
                                      self.tramp),
            Func(self.postHopOn),
        )
        self.hopOnAnim.start()

    def postHopOn(self):
        self.toon.setH(self.toon.getH() +
                       90.0)  # makes camera adjustment less jarring
        self.toon.dropShadow.reparentTo(self.surface)
        self.screenPlaneElements.reparentTo(aspect2d)
        self.timeLeftToSimulate = 0.0
        self.doSimulateStep = False
        taskMgr.add(self.updateTask,
                    self.uniqueName("TrampolineActivity.updateTask"))
        base.setCellsAvailable(base.leftCells, False)
        base.setCellsAvailable(base.bottomCells, False)
        DistributedPartyActivity.startRules(self)

    def releaseToon(self):
        self._hideFlashMessage()

        self.ignore("arrow_left")
        self.ignore("arrow_left-up")
        self.ignore("arrow_right")
        self.ignore("arrow_right-up")

        taskMgr.remove(self.uniqueName("TrampolineActivity.updateTask"))
        self.hopOffAnim = Sequence(
            self.toon.hprInterval(0.5,
                                  VBase3(-90.0, 0.0, 0.0),
                                  other=self.tramp),
            Func(self.toon.b_setAnimState, "jump", 1.0),
            Func(self.toon.dropShadow.reparentTo, hidden),
            Wait(0.4),
            PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0,
                                      self.tramp),
            Func(self.postHopOff),
        )
        self.hopOffAnim.start()

    def postHopOff(self):
        self.screenPlaneElements.reparentTo(hidden)
        base.setCellsAvailable(base.leftCells, True)
        self.timer.stop()
        self.timer.hide()

        self.toon.dropShadow.reparentTo(self.toon.getShadowJoint())
        self.toon.dropShadow.setAlphaScale(1.0)
        self.toon.dropShadow.setScale(1.0)

        # Continue broadcasting so remote toons see us reach the final hop off position.
        #self.toon.stopPosHprBroadcast()
        self.b_requestAnim("Off")

        camera.reparentTo(base.localAvatar)
        base.localAvatar.startUpdateSmartCamera()
        base.localAvatar.enableSmartCameraViews()
        base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex)
        place = base.cr.playGame.getPlace()

        if self.doJellyBeans:
            self.sendUpdate("awardBeans",
                            [self.numBeansCollected,
                             int(self.topHeight)])
            if int(self.topHeight) > self.bestHeightInfo[1]:
                self.sendUpdate("reportHeightInformation",
                                [int(self.topHeight)])

        self.d_toonExitDemand()

    #---------------------------------------------------
    # Event Handling
    #---------------------------------------------------
    def onTrampolineTrigger(self, collEntry):
        if (self.activityFSM._state == "Idle") and (self.toon == None) and (
                base.cr.playGame.getPlace().fsm.getCurrentState().getName()
                == "walk"):
            base.cr.playGame.getPlace().fsm.request("activity")
            self.d_toonJoinRequest()
        else:
            self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied,
                              duration=2.0)

    def onJump(self):
        self.notify.debug("got onJump")
        if self.toon != None and self.toon.getZ() < self.trampHeight:
            # Have to be on the trampoline
            self.toonJumped = True
            self.b_requestAnim("Jump")
        else:
            self.notify.debug("z is less than tramp height")

    def onLeft(self):
        self.turnLeft = True

    def onLeftUp(self):
        self.turnLeft = False

    def onRight(self):
        self.turnRight = True

    def onRightUp(self):
        self.turnRight = False

    #---------------------------------------------------
    # Super class functionality
    #---------------------------------------------------
    def handleToonJoined(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug("handleToonJoined")
        self.toon = self.getAvatar(toonId)
        if self.toon != None and not self.toon.isEmpty():
            self.oldJumpSquatPlayRate = self.toon.getPlayRate("jump-squat")
            self.oldJumpLandPlayRate = self.toon.getPlayRate("jump-land")
            self.toon.setPlayRate(2.5, "jump-squat")
            self.toon.setPlayRate(2.0, "jump-land")

            self.turnLeft = False
            self.turnRight = False

            self.activityFSM.request("Rules")

            if self.toon.doId != base.localAvatar.doId:
                taskMgr.add(
                    self.remoteUpdateTask,
                    self.uniqueName("TrampolineActivity.remoteUpdateTask"))
        else:
            self.notify.warning("handleToonJoined could not get toon %d" %
                                toonId)

    def handleToonExited(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug("handleToonExited")

        if self.toon != None:
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.remove(
                    self.uniqueName("TrampolineActivity.remoteUpdateTask"))

            self.surface.setZ(self.trampHeight)

            self.toon.setPlayRate(self.oldJumpSquatPlayRate, "jump-squat")
            self.toon.setPlayRate(self.oldJumpLandPlayRate, "jump-land")

            self.toon = None

    def handleToonDisabled(self, toonId):
        """
        A toon dropped unexpectedly from the game. Handle it!
        """
        DistributedPartyTrampolineActivity.notify.debug("handleToonDisabled")
        DistributedPartyTrampolineActivity.notify.debug("avatar " +
                                                        str(toonId) +
                                                        " disabled")

        if base.localAvatar.doId == toonId:
            self.releaseToon()

    def handleRulesDone(self):
        self.sendUpdate("toonReady")
        self.finishRules()

    def getTitle(self):
        if self.doJellyBeans:
            return TTLocalizer.PartyTrampolineJellyBeanTitle
        elif self.doTricks:
            return TTLocalizer.PartyTrampolineTricksTitle
        else:
            return DistributedPartyActivity.getTitle(self)

    def getInstructions(self):
        return TTLocalizer.PartyTrampolineActivityInstructions

    #---------------------------------------------------
    # Simulation
    #---------------------------------------------------
    def updateTask(self, task):
        # Only run on local client
        z = self.toon.getZ()
        dt = globalClock.getDt()
        if self.doSimulateStep:
            self.timeLeftToSimulate += dt
            while self.timeLeftToSimulate >= self.stepDT:
                z, a = self.simulateStep(z)
                self.timeLeftToSimulate -= self.stepDT

        self.toon.setZ(z)

        # Move tramp surface
        if z <= self.trampHeight:
            self.surface.setZ(z)
        else:
            self.surface.setZ(self.trampHeight)

        # Move toon indicator
        self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor)

        # Turn left or right
        if self.turnLeft:
            self.toon.setH(self.toon.getH() + self.turnFactor * dt)
        if self.turnRight:
            self.toon.setH(self.toon.getH() - self.turnFactor * dt)

        # Update camera
        currentPos = base.camera.getPos(self.toon)
        vec = self.targetCameraPos - currentPos
        newPos = currentPos + vec * (dt * self.cameraSpeed)
        base.camera.setPos(self.toon, newPos)
        base.camera.lookAt(self.toon)

        # Fade and scale drop shadow
        if z > self.trampHeight:
            heightFactor = 1.0 - min(
                1.0, (z - self.trampHeight) / self.dropShadowCutoff)
            self.toon.dropShadow.setAlphaScale(heightFactor)
            self.toon.dropShadow.setScale(max(0.1, heightFactor))
        else:
            self.toon.dropShadow.setAlphaScale(1.0)
            self.toon.dropShadow.setScale(1.0)

        # Leave trampoline if necessary
        if self.leavingTrampoline and (z < self.trampHeight) and (abs(a) <
                                                                  0.1):
            self.releaseToon()

# Simulate poor framerate
#        time.sleep( 0.03 )

        return Task.cont

    def simulateStep(self, z):
        # Calculate acceleration
        if z >= self.trampHeight:
            # Above the trampoline; only use gravity.
            a = self.g
            # Clear jumped flag
            self.toonJumped = False
        else:
            # On the trampoline; use gravity + spring + damping
            a = self.g + self.trampK * (self.trampHeight -
                                        z) - self.trampB * self.toonVelocity
            # Add jump acceleration if necessary
            if self.toonJumped:
                # Don't penalize early jumps.
                # If we're above the earlyJumpThreshold, go ahead and add jump
                # acceleration, even if the toon hasn't bottomed out (which
                # will reduce the effectiveness of the jump).
                # Otherwise, only add jump acceleration, if the toon has
                # bottomed out (toonVelocity >= 0.0).
                #self.notify.debug("self.lastPeak=%s earlyJumpThreshold=%s toonVelocity=%s" %(self.lastPeak, self.earlyJumpThreshold, self.toonVelocity ))
                if (self.lastPeak > self.earlyJumpThreshold) or (
                        self.toonVelocity >= -3E5):
                    a += self.jumpBoost
                    # Add beginning boost if necessary.
                    if self.lastPeak < self.beginningBoostThreshold:
                        a += self.beginningBoost

        # Calculate velocity
        #import pdb; pdb.set_trace()
        lastVelocity = self.toonVelocity
        self.toonVelocity += a * self.stepDT

        if (lastVelocity > 0.0) and (self.toonVelocity <= 0.0):
            topOfJump = True
            bottomOfJump = False
        elif (lastVelocity < 0.0) and (self.toonVelocity >= 0.0):
            topOfJump = False
            bottomOfJump = True
        else:
            topOfJump = False
            bottomOfJump = False

        # optimal jumping


#        if bottomOfJump and self.isAccepting( "control" ):
#            self.toonJumped = True
#            print z

# Calculate position
        newZ = z + self.toonVelocity * self.stepDT
        if newZ > self.topHeight:
            self.topHeight = newZ
            if self.doJellyBeans:
                self.collectJellyBeans(newZ)

        if topOfJump:
            # Set lastPeak
            self.lastPeak = newZ

            # Show height text if necessary
            if newZ >= self.minHeightForText:
                self.heightTextInterval.start()

        # Set anim state
        if topOfJump:
            if newZ > (self.trampHeight + 20.0):
                self.b_requestAnim("Falling")
            elif self.animFSM._state == "Jump":
                self.b_requestAnim("Falling")
        if (newZ <= self.trampHeight) and (z > self.trampHeight):
            if self.animFSM._state == "Falling":
                self.b_requestAnim("Land")
            elif self.animFSM._state != "Neutral":
                self.b_requestAnim("Neutral")

        # Play "boing" sound.
        if bottomOfJump and (a > self.boingThreshold):
            base.playSfx(self.boingSound)

        return newZ, a

    def collectJellyBeans(self, z):
        beansToRemove = []
        for i in self.beansToCollect:
            height = self.beanDetails[i][0]
            if height <= z:
                beansToRemove.append(i)

        if len(beansToRemove) > 0:
            base.playSfx(self.jellyBeanSound)
            self.numBeansCollected += len(beansToRemove)
            self.b_removeBeans(beansToRemove)

    def remoteUpdateTask(self, task):
        # Only run on remote clients

        # Move tramp surface
        if self.toon != None and not self.toon.isEmpty():
            z = self.toon.getZ()
            if z <= self.trampHeight:
                self.surface.setZ(z)
            else:
                self.surface.setZ(self.trampHeight)

        return Task.cont

    #---------------------------------------------------
    # Misc
    #---------------------------------------------------
    def poofBean(self, bean, beanAnim):
        if bean == None:
            self.notify.warning(
                "poofBean, returning immediately as bean is None")
            return
        if bean.isEmpty():
            self.notify.warning(
                "poofBean, returning immediately as bean is empty")
            return
        currentAlpha = bean.getColorScale()[3]
        currentScale = bean.getScale()
        poofAnim = Sequence(
            Parallel(
                LerpFunc(bean.setAlphaScale,
                         fromData=currentAlpha,
                         toData=0.0,
                         duration=0.25),
                LerpFunc(bean.setScale,
                         fromData=currentScale,
                         toData=currentScale * 5.0,
                         duration=0.25),
            ),
            Func(bean.stash),
            Func(beanAnim.finish),
            Func(bean.setAlphaScale, currentAlpha),
            Func(bean.setScale, currentScale),
        )
        poofAnim.start()

    def _showFlashMessage(self, message):
        if self.isDisabled():
            assert self.notify.debug(
                "_showFlasMessage disabled, not showing %s" % message)
            return

        if (self.flashTextInterval
                is not None) and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        self.flashText.setText(message)
        self.flashText.setAlphaScale(1.0)
        self.flashText.unstash()

    def _hideFlashMessage(self, duration=0.0):
        if self.isDisabled():
            assert self.notify.debug(
                "_hideFlashMessage we're disabled, but still hiding self.flashText"
            )
            # return

        self.flashTextInterval = Sequence(
            Wait(duration),
            LerpFunc(self.flashText.setAlphaScale,
                     fromData=1.0,
                     toData=0.0,
                     duration=1.0),
            Func(self.flashText.stash),
        )
        self.flashTextInterval.start()

    def flashMessage(self, message, duration=0.5):
        self._showFlashMessage(message)
        self._hideFlashMessage(duration)
Beispiel #42
0
class IsisAgent(kinematicCharacterController, DirectObject):
    @classmethod
    def setPhysics(cls, physics):
        """ This method is set in src.loader when the generators are loaded
        into the namespace.  This frees the environment definitions (in 
        scenario files) from having to pass around the physics parameter 
        that is required for all IsisObjects """
        cls.physics = physics

    def __init__(self, name, queueSize=100):

        # load the model and the different animations for the model into an Actor object.
        self.actor = Actor(
            "media/models/boxman", {"walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle"}
        )
        self.actor.setScale(1.0)
        self.actor.setH(0)
        # self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params
        self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0)
        self.actorNodePath = NodePath("agent-%s" % name)
        self.activeModel = self.actorNodePath

        self.actorNodePath.reparentTo(render)

        self.actor.reparentTo(self.actorNodePath)
        self.name = name
        self.isMoving = False

        # initialize ODE controller
        kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath)
        self.setGeomPos(self.actorNodePath.getPos(render))
        """
        Additional Direct Object that I use for convenience.
        """
        self.specialDirectObject = DirectObject()

        """
        How high above the center of the capsule you want the camera to be
        when walking and when crouching. It's related to the values in KCC.
        """
        self.walkCamH = 0.7
        self.crouchCamH = 0.2
        self.camH = self.walkCamH

        """
        This tells the Player Controller what we're aiming at.
        """
        self.aimed = None

        self.isSitting = False
        self.isDisabled = False

        """
        The special direct object is used for trigger messages and the like.
        """
        # self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True])
        # self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False])

        self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"])

        # Expose agent's right hand joint to attach objects to
        self.player_right_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.R")
        self.player_left_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.L")

        self.right_hand_holding_object = None
        self.left_hand_holding_object = None

        # don't change the color of things you pick up
        self.player_right_hand.setColorScaleOff()
        self.player_left_hand.setColorScaleOff()

        self.player_head = self.actor.exposeJoint(None, "modelRoot", "Head")
        self.neck = self.actor.controlJoint(None, "modelRoot", "Head")

        self.controlMap = {
            "turn_left": 0,
            "turn_right": 0,
            "move_forward": 0,
            "move_backward": 0,
            "move_right": 0,
            "move_left": 0,
            "look_up": 0,
            "look_down": 0,
            "look_left": 0,
            "look_right": 0,
            "jump": 0,
        }
        # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left]
        # turns are in degrees per second, moves are in units per second
        self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60]

        self.originalPos = self.actor.getPos()

        bubble = loader.loadTexture("media/textures/thought_bubble.png")
        # bubble.setTransparency(TransparencyAttrib.MAlpha)

        self.speech_bubble = DirectLabel(
            parent=self.actor,
            text="",
            text_wordwrap=10,
            pad=(3, 3),
            relief=None,
            text_scale=(0.3, 0.3),
            pos=(0, 0, 3.6),
            frameColor=(0.6, 0.2, 0.1, 0.5),
            textMayChange=1,
            text_frame=(0, 0, 0, 1),
            text_bg=(1, 1, 1, 1),
        )
        # self.myImage=
        self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.speech_bubble.setColorScaleOff()
        self.speech_bubble.component("text0").textNode.setCardDecal(1)
        self.speech_bubble.setBillboardAxis()
        # hide the speech bubble from IsisAgent's own camera
        self.speech_bubble.hide(BitMask32.bit(1))

        self.thought_bubble = DirectLabel(
            parent=self.actor,
            text="",
            text_wordwrap=9,
            text_frame=(1, 0, -2, 1),
            text_pos=(0, 0.5),
            text_bg=(1, 1, 1, 0),
            relief=None,
            frameSize=(0, 1.5, -2, 3),
            text_scale=(0.18, 0.18),
            pos=(0, 0.2, 3.6),
            textMayChange=1,
            image=bubble,
            image_pos=(0, 0.1, 0),
            sortOrder=5,
        )
        self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.thought_bubble.setColorScaleOff()
        self.thought_bubble.component("text0").textNode.setFrameColor(1, 1, 1, 0)
        self.thought_bubble.component("text0").textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1)
        self.thought_bubble.component("text0").textNode.setCardDecal(1)
        self.thought_bubble.setBillboardAxis()
        # hide the thought bubble from IsisAgent's own camera
        self.thought_bubble.hide(BitMask32.bit(1))
        # disable by default
        self.thought_bubble.hide()
        self.thought_filter = {}  # only show thoughts whose values are in here
        self.last_spoke = 0  # timers to keep track of last thought/speech and
        self.last_thought = 0  # hide visualizations

        # put a camera on ralph
        self.fov = NodePath(Camera("RaphViz"))
        self.fov.node().setCameraMask(BitMask32.bit(1))

        # position the camera to be infront of Boxman's face.
        self.fov.reparentTo(self.player_head)
        # x,y,z are not in standard orientation when parented to player-Head
        self.fov.setPos(0, 0.2, 0)
        # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face.
        self.fov.setHpr(0, -90, 0)

        lens = self.fov.node().getLens()
        lens.setFov(60)  #  degree field of view (expanded from 40)
        lens.setNear(0.2)
        # self.fov.node().showFrustum() # displays a box around his head
        # self.fov.place()

        self.prevtime = 0
        self.current_frame_count = 0

        self.isSitting = False
        self.isDisabled = False
        self.msg = None
        self.actorNodePath.setPythonTag("agent", self)

        # Initialize the action queue, with a maximum length of queueSize
        self.queue = []
        self.queueSize = queueSize
        self.lastSense = 0

    def setLayout(self, layout):
        """ Dummy method called by spatial methods for use with objects. 
        Doesn't make sense for an agent that can move around."""
        pass

    def setPos(self, pos):
        """ Wrapper to set the position of the ODE geometry, which in turn 
        sets the visual model's geometry the next time the update() method
        is called. """
        self.setGeomPos(pos)

    def setPosition(self, pos):
        self.setPos(pos)

    def reparentTo(self, parent):
        self.actorNodePath.reparentTo(parent)

    def setControl(self, control, value):
        """Set the state of one of the character's movement controls.  """
        self.controlMap[control] = value

    def get_objects_in_field_of_vision(self, exclude=["isisobject"]):
        """ This works in an x-ray style. Fast. Works best if you listen to
        http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while
        you use it.
        
        needs to exclude isisobjects since they cannot be serialized  
        """
        objects = {}
        for obj in base.render.findAllMatches("**/IsisObject*"):
            if not obj.hasPythonTag("isisobj"):
                continue
            o = obj.getPythonTag("isisobj")
            bounds = o.activeModel.getBounds()
            bounds.xform(o.activeModel.getMat(self.fov))
            if self.fov.node().isInView(o.activeModel.getPos(self.fov)):
                pos = o.activeModel.getPos(render)
                pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2)
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1]))
                object_dict = {}
                if "x_pos" not in exclude:
                    object_dict["x_pos"] = p3[0]
                if "y_pos" not in exclude:
                    object_dict["y_pos"] = p3[2]
                if "distance" not in exclude:
                    object_dict["distance"] = o.activeModel.getDistance(self.fov)
                if "orientation" not in exclude:
                    object_dict["orientation"] = o.activeModel.getH(self.fov)
                if "actions" not in exclude:
                    object_dict["actions"] = o.list_actions()
                if "isisobject" not in exclude:
                    object_dict["isisobject"] = o
                # add item to dinctionary
                objects[o] = object_dict
        return objects

    def get_agents_in_field_of_vision(self):
        """ This works in an x-ray vision style as well"""
        agents = {}
        for agent in base.render.findAllMatches("**/agent-*"):
            if not agent.hasPythonTag("agent"):
                continue
            a = agent.getPythonTag("agent")
            bounds = a.actorNodePath.getBounds()
            bounds.xform(a.actorNodePath.getMat(self.fov))
            pos = a.actorNodePath.getPos(self.fov)
            if self.fov.node().isInView(pos):
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1]))
                agentDict = {
                    "x_pos": p3[0],
                    "y_pos": p3[2],
                    "distance": a.actorNodePath.getDistance(self.fov),
                    "orientation": a.actorNodePath.getH(self.fov),
                }
                agents[a] = agentDict
        return agents

    def in_view(self, isisobj):
        """ Returns true iff a particular isisobject is in view """
        return len(
            filter(lambda x: x["isisobject"] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values())
        )

    def get_objects_in_view(self):
        """ Gets objects through ray tracing.  Slow"""
        return self.picker.get_objects_in_view()

    def control__turn_left__start(self, speed=None):
        self.setControl("turn_left", 1)
        self.setControl("turn_right", 0)
        if speed:
            self.speeds[0] = speed
        return "success"

    def control__turn_left__stop(self):
        self.setControl("turn_left", 0)
        return "success"

    def control__turn_right__start(self, speed=None):
        self.setControl("turn_left", 0)
        self.setControl("turn_right", 1)
        if speed:
            self.speeds[1] = speed
        return "success"

    def control__turn_right__stop(self):
        self.setControl("turn_right", 0)
        return "success"

    def control__move_forward__start(self, speed=None):
        self.setControl("move_forward", 1)
        self.setControl("move_backward", 0)
        if speed:
            self.speeds[2] = speed
        return "success"

    def control__move_forward__stop(self):
        self.setControl("move_forward", 0)
        return "success"

    def control__move_backward__start(self, speed=None):
        self.setControl("move_forward", 0)
        self.setControl("move_backward", 1)
        if speed:
            self.speeds[3] = speed
        return "success"

    def control__move_backward__stop(self):
        self.setControl("move_backward", 0)
        return "success"

    def control__move_left__start(self, speed=None):
        self.setControl("move_left", 1)
        self.setControl("move_right", 0)
        if speed:
            self.speeds[4] = speed
        return "success"

    def control__move_left__stop(self):
        self.setControl("move_left", 0)
        return "success"

    def control__move_right__start(self, speed=None):
        self.setControl("move_right", 1)
        self.setControl("move_left", 0)
        if speed:
            self.speeds[5] = speed
        return "success"

    def control__move_right__stop(self):
        self.setControl("move_right", 0)
        return "success"

    def control__look_left__start(self, speed=None):
        self.setControl("look_left", 1)
        self.setControl("look_right", 0)
        if speed:
            self.speeds[9] = speed
        return "success"

    def control__look_left__stop(self):
        self.setControl("look_left", 0)
        return "success"

    def control__look_right__start(self, speed=None):
        self.setControl("look_right", 1)
        self.setControl("look_left", 0)
        if speed:
            self.speeds[8] = speed
        return "success"

    def control__look_right__stop(self):
        self.setControl("look_right", 0)
        return "success"

    def control__look_up__start(self, speed=None):
        self.setControl("look_up", 1)
        self.setControl("look_down", 0)
        if speed:
            self.speeds[6] = speed
        return "success"

    def control__look_up__stop(self):
        self.setControl("look_up", 0)
        return "success"

    def control__look_down__start(self, speed=None):
        self.setControl("look_down", 1)
        self.setControl("look_up", 0)
        if speed:
            self.speeds[7] = speed
        return "success"

    def control__look_down__stop(self):
        self.setControl("look_down", 0)
        return "success"

    def control__jump(self):
        self.setControl("jump", 1)
        return "success"

    def control__view_objects(self):
        """ calls a raytrace to to all objects in view """
        objects = self.get_objects_in_field_of_vision()
        self.control__say("If I were wearing x-ray glasses, I could see %i items" % len(objects))
        print "Objects in view:", objects
        return objects

    def control__sense(self):
        """ perceives the world, returns percepts dict """
        percepts = dict()
        # eyes: visual matricies
        # percepts['vision'] = self.sense__get_vision()
        # objects in purview (cheating object recognition)
        percepts["objects"] = self.sense__get_objects()
        # global position in environment - our robots can have GPS :)
        percepts["position"] = self.sense__get_position()
        # language: get last utterances that were typed
        percepts["language"] = self.sense__get_utterances()
        # agents: returns a map of agents to a list of actions that have been sensed
        percepts["agents"] = self.sense__get_agents()
        print percepts
        return percepts

    def control__think(self, message, layer=0):
        """ Changes the contents of an agent's thought bubble"""
        # only say things that are checked in the controller
        if self.thought_filter.has_key(layer):
            self.thought_bubble.show()
            self.thought_bubble["text"] = message
            # self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05)
            # self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer])
            self.last_thought = 0
        return "success"

    def control__say(self, message="Hello!"):
        self.speech_bubble["text"] = message
        self.last_spoke = 0
        return "success"

    """

    Methods explicitly for IsisScenario files 

    """

    def put_in_front_of(self, isisobj):
        # find open direction
        pos = isisobj.getGeomPos()
        direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0))
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom])
        print "CLOSEST", closestEntry, closestObject
        if closestObject == None:
            self.setPosition(pos + Vec3(0, 2, 0))
        else:
            print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject)
            direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0))
            closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom])
            if closestEntry == None:
                self.setPosition(pos + Vec3(0, -2, 0))
            else:
                print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (isisobj, closestObject)
                direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0))
                closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
                    "aimRay", 5, [pos, direction], [isisobj.geom]
                )
                if closestEntry == None:
                    self.setPosition(pos + Vec3(2, 0, 0))
                else:
                    print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject)
                    # there's only one option left, do it anyway
                    self.setPosition(pos + Vec3(-2, 0, 0))
        # rotate agent to look at it
        self.actorNodePath.setPos(self.getGeomPos())
        self.actorNodePath.lookAt(pos)
        self.setH(self.actorNodePath.getH())

    def put_in_right_hand(self, target):
        return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand)

    def put_in_left_hand(self, target):
        return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand)

    def __get_object_in_center_of_view(self):
        direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
        pos = self.fov.getPos(render)
        exclude = []  # [base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom]
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], exclude)
        return closestObject

    def pick_object_up_with(self, target, hand_slot, hand_joint):
        """ Attaches an IsisObject, target, to the hand joint.  Does not check anything first,
        other than the fact that the hand joint is not currently holding something else."""
        if hand_slot != None:
            print "already holding " + hand_slot.getName() + "."
            return None
        else:
            if target.layout:
                target.layout.remove(target)
                target.layout = None
            # store original position
            target.originalHpr = target.getHpr(render)
            target.disable()  # turn off physics
            if target.body:
                target.body.setGravityMode(0)
            target.reparentTo(hand_joint)
            target.setPosition(hand_joint.getPos(render))
            target.setTag("heldBy", self.name)
            if hand_joint == self.player_right_hand:
                self.right_hand_holding_object = target
            elif hand_joint == self.player_left_hand:
                self.left_hand_holding_object = target
            hand_slot = target
            return target

    def control__pick_up_with_right_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return "error: no target in reach"
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with right hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand)
        else:
            print "object (" + target.name + ") is not graspable (i.e. in view and close enough)."
            return "error: object not graspable"

    def control__pick_up_with_left_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with left hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand)
        else:
            print "object (" + target.name + ") is not graspable (i.e. in view and close enough)."
            return "error: object not graspable"

    def control__drop_from_right_hand(self):
        print "attempting to drop object from right hand.\n"

        if self.right_hand_holding_object is None:
            print "right hand is not holding an object."
            return False
        if self.right_hand_holding_object.getNetTag("heldBy") == self.name:
            self.right_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_right_hand.getPos(render)
            heldPos = self.right_hand_holding_object.geom.getPosition()
            self.right_hand_holding_object.setPosition(pos)
            self.right_hand_holding_object.synchPosQuatToNode()
            self.right_hand_holding_object.setTag("heldBy", "")
            self.right_hand_holding_object.setRotation(self.right_hand_holding_object.originalHpr)
            self.right_hand_holding_object.enable()
            if self.right_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.right_hand_holding_object.body.setGravityMode(1)
                self.right_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0)))
            self.right_hand_holding_object = None
            return "success"
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__drop_from_left_hand(self):
        print "attempting to drop object from left hand.\n"
        if self.left_hand_holding_object is None:
            return "left hand is not holding an object."
        if self.left_hand_holding_object.getNetTag("heldBy") == self.name:
            self.left_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_left_hand.getPos(render)
            heldPos = self.left_hand_holding_object.geom.getPosition()
            self.left_hand_holding_object.setPosition(pos)
            self.left_hand_holding_object.synchPosQuatToNode()
            self.left_hand_holding_object.setTag("heldBy", "")
            self.left_hand_holding_object.setRotation(self.left_hand_holding_object.originalHpr)
            self.left_hand_holding_object.enable()
            if self.left_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.left_hand_holding_object.body.setGravityMode(1)
                self.left_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0)))
            self.left_hand_holding_object = None
            return "success"
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__use_right_hand(self, target=None, action=None):
        # TODO, rename this to use object with
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "Trying to use object", target
        if self.can_grasp(target):
            if target.call(self, action, self.right_hand_holding_object) or (
                self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target)
            ):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def control__use_left_hand(self, target=None, action=None):
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        if self.can_grasp(target):
            if target.call(self, action, self.left_hand_holding_object) or (
                self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target)
            ):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def can_grasp(self, isisobject):
        distance = isisobject.activeModel.getDistance(self.fov)
        print "distance = ", distance
        return distance < 5.0

    def is_holding(self, object_name):
        return (
            self.left_hand_holding_object
            and (self.left_hand_holding_object.getPythonTag("isisobj").name == object_name)
        ) or (
            self.right_hand_holding_object
            and (self.right_hand_holding_object.getPythonTag("isisobj").name == object_name)
        )

    def empty_hand(self):
        if self.left_hand_holding_object is None:
            return self.player_left_hand
        elif self.right_hand_holding_object is None:
            return self.player_right_hand
        return False

    def has_empty_hand(self):
        return self.empty_hand() is not False

    def control__use_aimed(self):
        """
        Try to use the object that we aim at, by calling its callback method.
        """
        target = self.__get_object_in_center_of_view()
        if target.selectionCallback:
            target.selectionCallback(self, dir)
        return "success"

    def sense__get_position(self):
        x, y, z = self.actorNodePath.getPos()
        h, p, r = self.actorNodePath.getHpr()
        # FIXME
        # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr()
        left_hand_obj = ""
        right_hand_obj = ""
        if self.left_hand_holding_object:
            left_hand_obj = self.left_hand_holding_object.getName()
        if self.right_hand_holding_object:
            right_hand_obj = self.right_hand_holding_object.getName()
        return {
            "body_x": x,
            "body_y": y,
            "body_z": z,
            "body_h": h,
            "body_p": p,
            "body_r": r,
            "in_left_hand": left_hand_obj,
            "in_right_hand": right_hand_obj,
        }

    def sense__get_vision(self):
        self.fov.node().saveScreenshot("temp.jpg")
        image = Image.open("temp.jpg")
        os.remove("temp.jpg")
        return image

    def sense__get_objects(self):
        return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items())

    def sense__get_agents(self):
        curSense = time()
        agents = {}
        for k, v in self.get_agents_in_field_of_vision().items():
            v["actions"] = k.get_other_agents_actions(self.lastSense, curSense)
            agents[k.name] = v
        self.lastSense = curSense
        return agents

    def sense__get_utterances(self):
        """ Clear out the buffer of things that the teacher has typed,
        FIXME: this doesn't work right now """
        return []
        utterances = self.teacher_utterances
        self.teacher_utterances = []
        return utterances

    def debug__print_objects(self):
        text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys())
        print text

    def add_action_to_history(self, action, args, result=0):
        self.queue.append((time(), action, args, result))
        if len(self.queue) > self.queueSize:
            self.queue.pop(0)

    def get_other_agents_actions(self, start=0, end=None):
        if not end:
            end = time()
        actions = []
        for act in self.queue:
            if act[0] >= start:
                if act[0] < end:
                    actions.append(act)
                else:
                    break
        return actions

    def update(self, stepSize=0.1):
        self.speed = [0.0, 0.0]
        self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70))
        self.actorNodePath.setQuat(self.getQuat())
        # the values in self.speeds are used as coefficientes for turns and movements
        if self.controlMap["turn_left"] != 0:
            self.addToH(stepSize * self.speeds[0])
        if self.controlMap["turn_right"] != 0:
            self.addToH(-stepSize * self.speeds[1])
        if self.verticalState == "ground":
            # these actions require contact with the ground
            if self.controlMap["move_forward"] != 0:
                self.speed[1] = self.speeds[2]
            if self.controlMap["move_backward"] != 0:
                self.speed[1] = -self.speeds[3]
            if self.controlMap["move_left"] != 0:
                self.speed[0] = -self.speeds[4]
            if self.controlMap["move_right"] != 0:
                self.speed[0] = self.speeds[5]
            if self.controlMap["jump"] != 0:
                kinematicCharacterController.jump(self)
                # one jump at a time!
                self.controlMap["jump"] = 0
        if self.controlMap["look_left"] != 0:
            self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80)
        if self.controlMap["look_right"] != 0:
            self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80)
        if self.controlMap["look_up"] != 0:
            self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80)
        if self.controlMap["look_down"] != 0:
            self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80)

        kinematicCharacterController.update(self, stepSize)

        """
        Update the held object position to be in the hands
        """
        if self.right_hand_holding_object != None:
            self.right_hand_holding_object.setPosition(self.player_right_hand.getPos(render))
        if self.left_hand_holding_object != None:
            self.left_hand_holding_object.setPosition(self.player_left_hand.getPos(render))

        # Update the dialog box and thought windows
        # This allows dialogue window to gradually decay (changing transparancy) and then disappear
        self.last_spoke += stepSize / 2
        self.last_thought += stepSize / 2
        self.speech_bubble["text_bg"] = (1, 1, 1, 1 / (self.last_spoke + 0.01))
        self.speech_bubble["frameColor"] = (0.6, 0.2, 0.1, 0.5 / (self.last_spoke + 0.01))
        if self.last_spoke > 2:
            self.speech_bubble["text"] = ""
        if self.last_thought > 1:
            self.thought_bubble.hide()

        # If the character is moving, loop the run animation.
        # If he is standing still, stop the animation.
        if (
            (self.controlMap["move_forward"] != 0)
            or (self.controlMap["move_backward"] != 0)
            or (self.controlMap["move_left"] != 0)
            or (self.controlMap["move_right"] != 0)
        ):
            if self.isMoving is False:
                self.isMoving = True
        else:
            if self.isMoving:
                self.current_frame_count = 5.0
                self.isMoving = False

        total_frame_num = self.actor.getNumFrames("walk")
        if self.isMoving:
            self.current_frame_count = self.current_frame_count + (stepSize * 250.0)
            if self.current_frame_count > total_frame_num:
                self.current_frame_count = self.current_frame_count % total_frame_num
            self.actor.pose("walk", self.current_frame_count)
        elif self.current_frame_count != 0:
            self.current_frame_count = 0
            self.actor.pose("idle", 0)
        return Task.cont

    def destroy(self):
        self.disable()
        self.specialDirectObject.ignoreAll()
        self.actorNodePath.removeNode()
        del self.specialDirectObject

        kinematicCharacterController.destroy(self)

    def disable(self):
        self.isDisabled = True
        self.geom.disable()
        self.footRay.disable()

    def enable(self):
        self.footRay.enable()
        self.geom.enable()
        self.isDisabled = False

    """
    Set camera to correct height above the center of the capsule
    when crouching and when standing up.
    """

    def crouch(self):
        kinematicCharacterController.crouch(self)
        self.camH = self.crouchCamH

    def crouchStop(self):
        """
        Only change the camera's placement when the KCC allows standing up.
        See the KCC to find out why it might not allow it.
        """
        if kinematicCharacterController.crouchStop(self):
            self.camH = self.walkCamH
Beispiel #43
0
class Agent:
    def __init__(self, _name):
        print "Creating agent " + _name
        self.name = _name
        self.loadLightingFromConfig = 0
        self.createShadowMap = 0

    def setDataPath(self, _dataPath):
        self.dataPath = _dataPath

    def setActor(self, _modelFileName, _animationFileNames,
                 _morphTargetsFileName):
        self.modelFileName = _modelFileName
        self.animationFileNames = _animationFileNames
        self.morphTargetsFileName = _morphTargetsFileName

    def setRealizer(self, _realizer):
        self.realizer = _realizer

    def setCameraMask(self, _mask):
        self.cameraMask = _mask

    def setShadowMapParameters(self, _index, _distance):
        self.createShadowMap = 1
        self.shadowMapIndex = _index
        self.shadowMapDistance = _distance

    def setTransform(self, x, y, z, rx, ry, rz, scale):
        self.agent.setPos(x, y, z)
        self.agent.setScale(scale)
        self.agent.setHpr(rx, ry, rz)
        self.positionX = x
        self.positionY = y
        self.positionZ = z

    def getPosition(self):
        return self.agent.getPos()

    def setLightingConfiguration(self, _config, _name):
        self.lightingConfig = _config
        self.lightingConfigName = _name
        self.loadLightingFromConfig = 1

    def init(self):
        #load the agent and parent it to the world
        #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it
        self.animationAgent = Actor(self.modelFileName,
                                    self.animationFileNames)

        self.agent = Actor(self.modelFileName, self.morphTargetsFileName)

        self.targets = {  #'Basis':[],                
            'ExpSmileClosed': [],
            'ExpAnger': [],
            'ExpDisgust': [],
            'ExpFear': [],
            'ExpSad': [],
            'ExpSurprise': [],
            'ExpSmileOpen': [],
            'ModBlinkLeft': [],
            'ModBlinkRight': [],
            'ModBrowDownLeft': [],
            'ModBrowDownRight': [],
            'ModBlinkRight': [],
            'ModBrowInRight': [],
            'ModBrowInLeft': [],
            'ModBrowUpLeft': [],
            'ModBrowUpRight': [],
            'ModEarsOut': [],
            'ModEyeSquintLeft': [],
            'ModEyeSquintRight': [],
            'ModLookDown': [],
            'ModLookLeft': [],
            'ModLookRight': [],
            'ModLookUp': [],
            'ModBlinkLeft': [],
            'Phonaah': [],
            'PhonB,M,P': [],
            'Phonbigaah': [],
            'Phonch,J,sh': [],
            'PhonD,S,T': [],
            'Phonee': [],
            'Phoneh': [],
            'PhonF,V': [],
            'Phoni': [],
            'PhonK': [],
            'PhonN': [],
            'Phonoh': [],
            'Phonooh,Q': [],
            'PhonR': [],
            'Phonth': [],
            'PhonW': []
        }

        iter = self.targets.iteritems()
        while True:
            try:
                morphsItem = iter.next()
            except StopIteration:
                break
            for i in range(2, 7):
                #print (str(i)+'_'+morphsItem[0])
                blendShape = self.agent.controlJoint(
                    None, 'modelRoot',
                    str(i) + '_' + morphsItem[0])
                if (blendShape):
                    morphsItem[1].append(blendShape)

        self.targets['inspire'] = [
            self.agent.controlJoint(None, 'modelRoot', 'inspire')
        ]

        #instanciate a list in order to keep track of kinematic joints joints
        #in python runtime
        #if nothing points towards those joints, they get flushed by
        #python's garbage collector
        self.jointList = []
        self.jointFKList = []
        self.agentControlJoints = []
        self.agentNodePaths = []

        self.agentSMRSkel = SMRPy.SMRSkeleton(True, True, 'agent')
        self.createSkel(self.agent, self.agentSMRSkel, 'root', '')
        #SMRPy.exportSkeletonToBvh('exportedPose.bvh',self.agentSMRSkel);
        self.newSkeleton = SMRPy.SMRSkeleton(True, True, 'pose')
        self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '')

        self.realizer.addCharacter(self.name, self.agentSMRSkel)

        for key in self.targets.keys():
            self.realizer.addMorphTarget(self.name, key)

        self.realizer.addShaderParameter(self.name, 'blushing')

        self.addAnimation(self.name, 'breathing')
        self.addAnimation(self.name, 'hands_claw')
        self.addAnimation(self.name, 'hands_fist')
        self.addAnimation(self.name, 'hands_index')
        self.addAnimation(self.name, 'hands_open-relaxed')
        self.addAnimation(self.name, 'hands_open-spread')
        self.addAnimation(self.name, 'hands_open-straight')
        self.addAnimation(self.name, 'hands_purse')
        self.addAnimation(self.name, 'hands_ring')
        self.addAnimation(self.name, 'poseNeutral')
        #self.addAnimation(self.name,'endian')

        if 'default' in self.animationFileNames:
            self.addAnimation(self.name, 'default')

        #self.realizer.addCharacterSkeleton( self.name,  );

        self.agent.reparentTo(render)
        self.agent.hide(BitMask32.bit(self.cameraMask))

        #set lighting
        ambientColor = Vec4(0.0, 0.0, 0.0, 0.0)
        self.lighting = shaders.Lighting(ambientColor, self.agent)
        if self.loadLightingFromConfig == 1:
            self.lighting.loadFromConfig(self.lightingConfig,
                                         self.lightingConfigName)

        #shadow map
        if self.createShadowMap == 1:
            self.shadowMap = shadowmap.ShadowMap(self.shadowMapIndex,
                                                 self.dataPath)

    def setShaders(self, _shaders):
        self.shaders = _shaders

    def update(self):
        self.realizer.skeletonRequested()
        self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel)

        for key in self.targets.keys():
            #print(key, "\n")
            weight = self.realizer.getMorphTargetWeight(self.name, key)
            morphTargets = self.targets[key]
            for morphTarget in morphTargets:
                #print(weight, "\n")
                morphTarget.setX(weight)

        #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' )
        #self.shaders.headShader.blushing.set( blushingValue )

        self.lighting.update()
        if self.createShadowMap == 1:
            self.shadowMap.setLighting(
                self.lighting,
                Vec3(self.positionX, self.positionY, self.positionZ),
                self.shadowMapDistance)
            self.shaders.updateWithShadows(self.shadowMap)
        else:
            self.shaders.update()

    def addAnimation(self, _actorName, _animationName):
        self.animationAgent.reparentTo(render)
        self.animationAgent.setScale(10)
        self.realizer.addAnimation(_actorName, _animationName)
        for i in range(self.animationAgent.getNumFrames(_animationName)):
            self.animationAgent.pose(_animationName, i)
            base.graphicsEngine.renderFrame()
            self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton)
            self.realizer.addPoseToAnimation(_actorName, _animationName,
                                             self.newSkeleton)
        self.animationAgent.detachNode()
        print "animation", _animationName, "added"

    def createSkel(self, _pandaAgent, _smrSkel, _initialJointName,
                   _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot',
                                                      _initialJointName)
        self.agentControlJoints.append(currentPandaCJoint)
        #get the first joint's position
        position = currentPandaCJoint.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(),
                                position.getZ())
        else:
            newJoint = SMRPy.SMRJoint(False)

        rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159
        rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159
        rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159

        quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 0.0, 1.0), rotZ)
        quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0, 0.0, 0.0), rotX)
        quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 1.0, 0.0), rotY)

        quatRot = quatZ.multiply(quatX)
        quatRot = quatRot.multiply(quatY)
        quatRot.normalize()

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        newJoint.setRotQuat(quatRot.getW(), quatRot.getX(), quatRot.getY(),
                            quatRot.getZ())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

        self.jointList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createSkel(_pandaAgent, _smrSkel, childName,
                            _initialJointName)

    def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName,
                     _parentName):
        #get the agent's currentJoint
        currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName)

        currentPandaJointPath = _pandaAgent.exposeJoint(
            None, 'modelRoot', _initialJointName, "lodRoot", True)

        #currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName)
        #if (_parentName == 'root' or _parentName == '' or _parentName == 'Bone.001'):
        #    currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName)
        #else:
        #    print(_parentName)
        #    currentPandaJointPath = _pandaAgent.exposeJoint(None, _parentName, _initialJointName)

        #if (_initialJointName == "lhand"):
        #    self.rhand = currentPandaJointPath

        self.agentNodePaths.append(currentPandaJointPath)

        #get the first joint's position
        position = currentPandaJointPath.getPos()

        if (currentPandaJoint[0].getNumChildren() == 0):
            newJoint = SMRPy.SMRJoint(True)
            newJoint.setEndVect(position.getX(), position.getY(),
                                position.getZ())
        else:
            newJoint = SMRPy.SMRJoint(False)

        quatRot = currentPandaJointPath.getQuat()

        newJoint.setPos(position.getX(), position.getY(), position.getZ())
        newJoint.setRotQuat(quatRot.getR(), quatRot.getI(), quatRot.getJ(),
                            quatRot.getK())

        newJoint.setParentName(_parentName)
        newJoint.setName(_initialJointName)

        #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren()

        self.jointFKList.append(newJoint)
        _smrSkel.insertJoint(newJoint)

        for i in range(currentPandaJoint[0].getNumChildren()):
            childJoint = currentPandaJoint[0].getChild(i)
            childName = childJoint.getName()
            #print(childName)
            self.createFKSkel(_pandaAgent, _smrSkel, childName,
                              _initialJointName)

    def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton):

        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentControlJoints[0]
        position = SMRJoint.getPos()
        #PANDAJoint.setPos(position.X() + 0.65 ,position.Y()-0.35,position.Z() - 1.4);
        PANDAJoint.setPos(position.X(), position.Y(), position.Z())

        for i in range(_smrSkeleton.getNumjoints()):
            SMRJoint = _smrSkeleton.getJoint(i)
            PANDAJoint = agentControlJoints[i]
            self.synchronize(PANDAJoint, SMRJoint)

    def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton):
        #synchronize root joint
        SMRJoint = _smrSkeleton.getJoint(0)
        PANDAJoint = agentNodePaths[0]
        position = PANDAJoint.getPos()
        SMRJoint.setPos(position.getX(), position.getY(), position.getZ())

        for i in range(_smrSkeleton.getNumjoints()):
            SMRJoint = _smrSkeleton.getJoint(i)
            PANDAJoint = agentNodePaths[i]
            self.synchronizePandaToSMR(SMRJoint, PANDAJoint)

    def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint):
        pandaQuaternion = _PANDAJoint.getQuat()
        x = pandaQuaternion.getI()
        y = pandaQuaternion.getJ()
        z = pandaQuaternion.getK()
        w = pandaQuaternion.getR()
        _SMRJoint.setRotQuat(w, x, y, z)

    def synchronize(self, _pandaCJoint, _smrJoint):
        smrQuaternion = _smrJoint.getRot()
        pandaQuaternion = Quat()
        pandaQuaternion.setI(smrQuaternion.getX())
        pandaQuaternion.setJ(smrQuaternion.getY())
        pandaQuaternion.setK(smrQuaternion.getZ())
        pandaQuaternion.setR(smrQuaternion.getW())
        if not (pandaQuaternion.isNan()):
            _pandaCJoint.setQuat(pandaQuaternion)
Beispiel #44
0
class IKChain():
    def __init__(self, parent):

        # Create a character.
        self.char = Character('IKChain')
        self.bundle = self.char.getBundle(0)
        self.skeleton = PartGroup(self.bundle, '<skeleton>')

        self.root = CharacterJoint(self.char, self.bundle, self.skeleton,
                                   'root', Mat4.identMat())

        self.bones = []
        self.target = None
        self.targetReached = False
        self.parent = parent

    def addBone(self,
                offset,
                rotAxis=None,
                minAng=0,
                maxAng=0,
                parentBone=None):

        name = "joint" + str(len(self.bones))

        if parentBone is None:
            transform = Mat4.identMat()
            joint = CharacterJoint(self.char, self.bundle, self.root, name,
                                   transform)
        else:
            transform = Mat4.translateMat(parentBone.offset)
            joint = CharacterJoint(self.char, self.bundle, parentBone.joint,
                                   name, transform)

        if rotAxis:
            rotAxis = rotAxis.normalized()
        bone = Bone(offset, rotAxis, minAng, maxAng, joint, parent=parentBone)

        self.bones.append(bone)

        return bone

    def finalize(self):

        self.charNodePath = NodePath(self.char)
        self.actor = Actor(self.charNodePath)  #, {'simplechar' : anim})
        self.actor.reparentTo(self.parent)
        self.rootExposedNode = self.actor.exposeJoint(None, "modelRoot",
                                                      self.root.getName())

        # Root of the chain
        parentIKNode = self.rootExposedNode

        # For each bone, create:
        # - a control node which will be used to update the bone position after IK solving
        # - an exposed node which we can attach things to, to render them
        # - a normal NodePath node called ikNode, which we'll use during IK solving
        for bone in self.bones:
            name = bone.joint.getName()
            controlNode = self.actor.controlJoint(None, "modelRoot", name)
            bone.controlNode = controlNode
            exposedNode = self.actor.exposeJoint(None, "modelRoot", name)
            bone.exposedNode = exposedNode
            # Separate nodes for IK:
            ikNode = parentIKNode.attachNewNode(name)
            # Same local pos as the exposed joints:
            ikNode.setPos(controlNode.getPos())
            bone.ikNode = ikNode
            parentIKNode = ikNode

        self.endEffector = self.bones[-1].ikNode.attachNewNode("EndEffector")
        self.endEffector.setPos(self.bones[-1].offset)

    def updateIK(self):

        # Solve the IK chain for the IK nodes:
        if self.target:
            self.inverseKinematicsCCD()

        # Copy the data from the IK chain to the actual bones.
        # This will end up affecting the actual mesh.
        for bone in self.bones:
            bone.controlNode.setQuat(bone.ikNode.getQuat())

    def inverseKinematicsCCD(self,
                             threshold=1e-2,
                             minIterations=1,
                             maxIterations=10):

        self.targetReached = False
        for i in range(maxIterations):

            if i >= minIterations:
                err = (self.target.getPos(render) -
                       self.endEffector.getPos(render)).lengthSquared()
                if err < threshold:
                    self.targetReached = True
                    break

            for j in range(len(self.bones)):
                bone = self.bones[-j - 1]

                boneNode = bone.ikNode
                if bone.parent:
                    parentNode = bone.parent.ikNode
                else:
                    parentNode = self.rootExposedNode

                target = self.target.getPos(boneNode)

                pos = LPoint3.zero()
                ee = self.endEffector.getPos(boneNode)

                d1 = target - pos
                d2 = ee - pos

                cross = d1.cross(d2).normalized()
                if cross.lengthSquared() < 1e-9:
                    continue

                ang = d2.normalized().signedAngleRad(d1.normalized(), cross)
                q = Quat()
                q.setFromAxisAngleRad(ang, cross)
                # Add this rotation to the current rotation:
                qOld = boneNode.getQuat()
                qNew = q * qOld
                qNew.normalize()
                #boneNode.setQuat( qNew )

                # Correct rotation for hinge:
                if bone.axis:
                    #qInv = boneNode.getQuat()
                    #qInv.invertInPlace()
                    #myAxisInParentSpace = qInv.xform( bone.axis )
                    myAxisInParentSpace = bone.axis
                    swing, twist = swingTwistDecomposition(
                        qNew, -myAxisInParentSpace)
                    qNew = twist

                rotAxis = qNew.getAxis()
                rotAxis.normalize()
                ang = qNew.getAngleRad()
                if rotAxis.lengthSquared() > 1e-3 and not math.isnan(
                        ang) and abs(ang) > 0:  # valid rotation axis?
                    # reduce the angle
                    ang = ang % (math.pi * 2)
                    # force into the minimum absolute value residue class, so that -180 < angle <= 180
                    if ang > math.pi:
                        ang -= 2 * math.pi

                    if abs(ang) > 1e-6 and abs(ang) < math.pi * 2:
                        if bone.axis and (rotAxis -
                                          bone.axis).lengthSquared() > 0.5:
                            # Clamp the rotation value:
                            ang = max(-bone.maxAng, min(-bone.minAng, ang))
                        else:
                            # Clamp the rotation value:
                            ang = max(bone.minAng, min(bone.maxAng, ang))
                            #ang = -ang
                            #rotAxis = -rotAxis

                    #annealing = (j+1)/len(self.bones)
                    #print("annealing", annealing)
                    #q = qOld + (qNew-qOld)*annealing

                    qNew.setFromAxisAngleRad(ang, rotAxis)

                    boneNode.setQuat(qNew)

    def setTarget(self, node):
        self.target = node

    def debugDisplay(self):

        for bone in self.bones:

            col = (random.random(), random.random(), random.random())
            #col = (0,0,0)

            lines = LineSegs()
            lines.setThickness(6)
            lines.setColor(col[0], col[1], col[2])
            lines.moveTo(0, 0, 0)
            #lines.drawTo(np.getPos(parentNode))
            lnp = bone.exposedNode.attachNewNode(lines.create())
            lnp.setBin("fixed", 40)
            #lnp.setDepthWrite(False)
            #lnp.setDepthTest(False)

            lines = LineSegs()
            lines.setThickness(12)
            lines.setColor(col[0], col[1], col[2])
            lines.moveTo(0, 0, 0)
            lines.drawTo(bone.offset)
            #lines.drawTo(np.getPos(parentNode))
            lnp = bone.exposedNode.attachNewNode(lines.create())
            lnp.setBin("fixed", 40)
            #lnp.setDepthWrite(False)
            #lnp.setDepthTest(False)

            if bone.parent:
                parentNode = bone.parent.exposedNode
            else:
                parentNode = self.rootExposedNode

            lines = LineSegs()
            lines.setColor(0.6, 0.2, 0.2)
            #lines.setColor( 0.02, 0.02, 0.02 )
            myPos = bone.exposedNode.getPos(parentNode)
            if bone.axis:
                qMin = Quat()
                qMin.setFromAxisAngleRad(bone.minAng, bone.axis)
                qMax = Quat()
                qMax.setFromAxisAngleRad(bone.maxAng, bone.axis)
                l = bone.offset.normalized() * 0.3
                lines.moveTo(myPos)
                lines.drawTo(myPos + qMin.xform(l))
                lines.moveTo(myPos)
                lines.drawTo(myPos + qMax.xform(l))
            else:
                qMin = Quat()
                qMin.setFromAxisAngleRad(bone.minAng, LVector3f.unitY())
                qMax = Quat()
                qMax.setFromAxisAngleRad(bone.maxAng, LVector3f.unitY())
                l = bone.offset.normalized() * 0.3
                lines.moveTo(myPos)
                lines.drawTo(myPos + qMin.xform(l))
                lines.moveTo(myPos)
                lines.drawTo(myPos + qMax.xform(l))
                qMin = Quat()
                qMin.setFromAxisAngleRad(bone.minAng, LVector3f.unitZ())
                qMax = Quat()
                qMax.setFromAxisAngleRad(bone.maxAng, LVector3f.unitZ())
                lines.moveTo(myPos)
                lines.drawTo(myPos + qMin.xform(l))
                lines.moveTo(myPos)
                lines.drawTo(myPos + qMax.xform(l))

            lnp = parentNode.attachNewNode(lines.create())
            lnp.setBin("fixed", 40)
            #lnp.setDepthWrite(False)
            #lnp.setDepthTest(False)

            if bone.axis:
                lines = LineSegs()
                lines.setColor(0.6, 0.6, 0.6)
                lines.setThickness(3)
                lines.moveTo(myPos)
                lines.drawTo(myPos + bone.axis.normalized() * 0.3)

                lnp = parentNode.attachNewNode(lines.create())
                lnp.setBin("fixed", 40)
Beispiel #45
0
class DistributedPartyTrampolineActivity(DistributedPartyActivity):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity')

    def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None):
        DistributedPartyTrampolineActivity.notify.debug('__init__')
        DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True)
        self.doJellyBeans = doJellyBeans
        self.doTricks = doTricks
        self.texture = texture
        self.toon = None
        self.trampHeight = 3.6
        self.trampK = 400.0
        self.normalTrampB = 2.5
        self.leavingTrampB = 8.0
        self.trampB = self.normalTrampB
        self.g = -32.0
        self.jumpBoost = 330.0
        self.beginningBoost = 500.0
        self.beginningBoostThreshold = self.trampHeight + 1.5
        self.earlyJumpThreshold = 75.0
        self.boingThreshold = 300.0
        self.turnFactor = 120.0
        self.stepDT = 0.001
        self.targetCameraPos = Point3(0.0, 40.0, 10.0)
        self.cameraSpeed = 2.0
        self.hopOffPos = Point3(16.0, 0.0, 0.0)
        self.indicatorFactor = 0.0095
        self.dropShadowCutoff = 15.0
        self.minHeightForText = 15.0
        self.heightTextOffset = -0.065
        self.beanOffset = 0.5
        self.guiBeanOffset = -0.02
        self.jumpTextShown = False
        self.toonJumped = False
        self.turnLeft = False
        self.turnRight = False
        self.leavingTrampoline = False
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.lastPeak = 0.0
        self.beginRoundInterval = None
        self.hopOnAnim = None
        self.hopOffAnim = None
        self.flashTextInterval = None
        self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans
        self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus
        self.jellyBeanStartHeight = 20.0
        self.jellyBeanStopHeight = 90.0
        self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0),
         VBase4(0.5, 1.0, 0.5, 1.0),
         VBase4(0.5, 1.0, 1.0, 1.0),
         VBase4(1.0, 1.0, 0.4, 1.0),
         VBase4(0.4, 0.4, 1.0, 1.0),
         VBase4(1.0, 0.5, 1.0, 1.0)]
        delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1)
        self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ]
        self.doSimulateStep = False
        return

    def load(self):
        DistributedPartyTrampolineActivity.notify.debug('load')
        DistributedPartyActivity.load(self)
        self.loadModels()
        self.loadCollision()
        self.loadGUI()
        self.loadSounds()
        self.loadIntervals()
        self.activityFSM = TrampolineActivityFSM(self)
        self.activityFSM.request('Idle')
        self.animFSM = TrampolineAnimFSM(self)
        self.setBestHeightInfo('', 0)

    def loadModels(self):
        self.tramp = self.root.attachNewNode(self.uniqueName('tramp'))
        self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'})
        self.trampActor.reparentTo(self.tramp)
        if self.texture:
            reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode')
            reskinNode.setTexture(loader.loadTexture(self.texture), 100)
        self.surface = NodePath(self.uniqueName('trampSurface'))
        self.surface.reparentTo(self.tramp)
        self.surface.setZ(self.trampHeight)
        self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1')
        self.sign.setPos(PartyGlobals.TrampolineSignOffset)
        self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ]
        for bean in self.beans:
            bean.find('**/jellybean').setP(-35.0)
            bean.setScale(3.0)
            bean.setTransparency(True)
            bean.reparentTo(self.tramp)
            bean.stash()

        self.beans[-1].setScale(8.0)

    def loadCollision(self):
        collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4)
        collTube.setTangible(True)
        self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision'))
        self.trampolineCollision.addSolid(collTube)
        self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask)
        self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision)
        collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0)
        collSphere.setTangible(False)
        self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger'))
        self.trampolineTrigger.addSolid(collSphere)
        self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask)
        self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger)
        self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger)

    def loadGUI(self):
        self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI')
        self.gui.reparentTo(base.a2dTopLeft)
        self.gui.setPos(0.115, 0, -1)
        self.gui.hide()
        self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar')
        jumpLineLocator = self.gui.find('**/jumpLine_locator')
        guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean')
        self.gui.find('**/trampolineGUI_GreenJellyBean').stash()
        self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ]
        self.guiBeans[-1].setScale(1.5)
        heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode'))
        heightTextNode.setFont(ToontownGlobals.getSignFont())
        heightTextNode.setAlign(TextNode.ALeft)
        heightTextNode.setText('0.0')
        heightTextNode.setShadow(0.05, 0.05)
        heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0)
        heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0)
        self.heightText = jumpLineLocator.attachNewNode(heightTextNode)
        self.heightText.setX(0.15)
        self.heightText.setScale(0.1)
        self.heightText.setAlphaScale(0.0)
        self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui')
        quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp')
        quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown')
        quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover')
        self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline)
        self.quitEarlyButton.stash()
        self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True)
        self.timer = PartyUtils.getNewToontownTimer()
        self.timer.posInTopRightCorner()
        return

    def loadSounds(self):
        self.jellyBeanSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg')
        self.boingSound = base.loader.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg')
        self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg')

    def loadIntervals(self):

        def prepareHeightText():
            self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ()))
            self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset)

        self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0))

    def unload(self):
        DistributedPartyTrampolineActivity.notify.debug('unload')
        if self.hopOnAnim and self.hopOnAnim.isPlaying():
            self.hopOnAnim.finish()
        if self.hopOffAnim and self.hopOffAnim.isPlaying():
            self.hopOffAnim.finish()
        if self.beginRoundInterval and self.beginRoundInterval.isPlaying():
            self.beginRoundInterval.finish()
        if self.flashTextInterval and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        if self.heightTextInterval and self.heightTextInterval.isPlaying():
            self.heightTextInterval.finish()
        self.timer.stop()
        DistributedPartyActivity.unload(self)
        taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask'))
        taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask'))
        self.ignoreAll()
        del self.heightTextInterval
        del self.beginRoundInterval
        del self.hopOnAnim
        del self.hopOffAnim
        del self.flashTextInterval
        if hasattr(self, 'beanAnims'):
            self.cleanupJellyBeans()
        self.quitEarlyButton.destroy()
        del self.quitEarlyButton
        del self.gui
        del self.activityFSM
        del self.animFSM
        return

    def setBestHeightInfo(self, toonName, height):
        self.bestHeightInfo = (toonName, height)
        DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height))
        if height > 0:
            self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo)
        else:
            self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet)

    def leaveTrampoline(self):
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp)
            self.leavingTrampoline = True
            self.timer.reset()
            self.trampB = self.leavingTrampB
            self.ignore('control')
            self.quitEarlyButton.stash()
            self.gui.hide()
        return

    def requestAnim(self, request):
        self.animFSM.request(request)

    def b_requestAnim(self, request):
        self.requestAnim(request)
        self.sendUpdate('requestAnim', [request])

    def requestAnimEcho(self, request):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.requestAnim(request)
        return

    def removeBeans(self, beansToRemove):
        for i in beansToRemove:
            height, bean, guiBean, beanAnim = self.beanDetails[i]
            guiBean.stash()
            if i in self.beansToCollect:
                self.beansToCollect.remove(i)
            else:
                self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i)
            self.poofBean(bean, beanAnim)

    def b_removeBeans(self, beansToRemove):
        self.removeBeans(beansToRemove)
        self.sendUpdate('removeBeans', [beansToRemove])

    def removeBeansEcho(self, beansToRemove):
        if self.toon != None and self.toon.doId != base.localAvatar.doId:
            self.removeBeans(beansToRemove)
        return

    def joinRequestDenied(self, reason):
        DistributedPartyActivity.joinRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny)
        base.cr.playGame.getPlace().fsm.request('walk')

    def exitRequestDenied(self, reason):
        DistributedPartyActivity.exitRequestDenied(self, reason)
        self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny)

    def setState(self, newState, timestamp):
        DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState)
        DistributedPartyActivity.setState(self, newState, timestamp)
        self.activityFSM.request(newState)

    def startIdle(self):
        DistributedPartyTrampolineActivity.notify.debug('startIdle')

    def finishIdle(self):
        DistributedPartyTrampolineActivity.notify.debug('finishIdle')

    def startRules(self):
        DistributedPartyTrampolineActivity.notify.debug('startRules')
        if self.doJellyBeans:
            self.setupJellyBeans()
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            self.acquireToon()
        return

    def startActive(self):
        DistributedPartyTrampolineActivity.notify.debug('startActive')
        if self.toon != None and self.toon.doId == base.localAvatar.doId:
            base.setCellsActive(base.bottomCells, True)
            self.accept('arrow_left', self.onLeft)
            self.accept('arrow_left-up', self.onLeftUp)
            self.accept('arrow_right', self.onRight)
            self.accept('arrow_right-up', self.onRightUp)
            self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound))
            self.beginRoundInterval.start()
        return

    def finishActive(self):
        DistributedPartyTrampolineActivity.notify.debug('finishActive')
        if self.doJellyBeans:
            self.cleanupJellyBeans()

    def setupJellyBeans(self):
        self.beanAnims = []
        self.beansToCollect = []
        self.beanDetails = []
        self.numBeansCollected = 0
        for i in xrange(self.numJellyBeans):
            bean = self.beans[i]
            guiBean = self.guiBeans[i]
            height = self.jellyBeanPositions[i]
            color = random.choice(self.jellyBeanColors)
            bean.find('**/jellybean').setColor(color)
            if self.toon.doId == base.localAvatar.doId:
                bean.setAlphaScale(1.0)
            else:
                bean.setAlphaScale(0.5)
            guiBean.setColor(color)
            bean.setZ(height + self.toon.getHeight() + self.beanOffset)
            guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset)
            bean.setH(0.0)
            bean.unstash()
            guiBean.unstash()
            beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0))
            beanAnim.loop()
            self.beanAnims.append(beanAnim)
            self.beanDetails.append((height,
             bean,
             guiBean,
             beanAnim))

        self.beansToCollect = range(self.numJellyBeans)

    def cleanupJellyBeans(self):
        for bean in self.beans:
            bean.stash()

        for guiBean in self.guiBeans:
            guiBean.stash()

        if hasattr(self, 'beanAnims'):
            for beanAnim in self.beanAnims:
                beanAnim.finish()

            del self.beanAnims
            del self.beansToCollect

    def beginRound(self):
        base.playSfx(self.whistleSound)
        self.timer.setTime(PartyGlobals.TrampolineDuration)
        self.timer.countdown(PartyGlobals.TrampolineDuration)
        self.timer.show()
        self.gui.show()
        self.quitEarlyButton.unstash()
        self.notify.debug('Accepting contorl')
        self.accept('control', self.onJump)
        self.notify.debug('setting simulate step to true')
        self.doSimulateStep = True

    def acquireToon(self):
        self.toon.disableSmartCameraViews()
        self.toon.stopUpdateSmartCamera()
        camera.wrtReparentTo(render)
        self.toon.dropShadow.reparentTo(hidden)
        self.toon.startPosHprBroadcast(period=0.2)
        self.toonAcceleration = 0.0
        self.toonVelocity = 0.0
        self.topHeight = 0.0
        self.trampB = self.normalTrampB
        self.leavingTrampoline = False
        self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn))
        self.hopOnAnim.start()

    def postHopOn(self):
        self.toon.setH(self.toon.getH() + 90.0)
        self.toon.dropShadow.reparentTo(self.surface)
        self.timeLeftToSimulate = 0.0
        self.doSimulateStep = False
        taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask'))
        base.setCellsActive(base.leftCells, False)
        base.setCellsActive(base.bottomCells, False)
        DistributedPartyActivity.startRules(self)

    def releaseToon(self):
        self._hideFlashMessage()
        self.ignore('arrow_left')
        self.ignore('arrow_left-up')
        self.ignore('arrow_right')
        self.ignore('arrow_right-up')
        taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask'))
        self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff))
        self.hopOffAnim.start()

    def postHopOff(self):
        base.setCellsActive(base.leftCells, True)
        self.timer.stop()
        self.timer.hide()
        self.toon.dropShadow.reparentTo(self.toon.getShadowJoint())
        self.toon.dropShadow.setAlphaScale(1.0)
        self.toon.dropShadow.setScale(1.0)
        self.b_requestAnim('Off')
        camera.reparentTo(base.localAvatar)
        base.localAvatar.startUpdateSmartCamera()
        base.localAvatar.enableSmartCameraViews()
        base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex)
        place = base.cr.playGame.getPlace()
        if self.doJellyBeans:
            self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)])
            if int(self.topHeight) > self.bestHeightInfo[1]:
                self.sendUpdate('reportHeightInformation', [int(self.topHeight)])
        self.d_toonExitDemand()

    def onTrampolineTrigger(self, collEntry):
        if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk':
            base.cr.playGame.getPlace().fsm.request('activity')
            self.d_toonJoinRequest()
        else:
            self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0)
        return

    def onJump(self):
        self.notify.debug('got onJump')
        if self.toon != None and self.toon.getZ() < self.trampHeight:
            self.toonJumped = True
            self.b_requestAnim('Jump')
        else:
            self.notify.debug('z is less than tramp height')
        return

    def onLeft(self):
        self.turnLeft = True

    def onLeftUp(self):
        self.turnLeft = False

    def onRight(self):
        self.turnRight = True

    def onRightUp(self):
        self.turnRight = False

    def handleToonJoined(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonJoined')
        self.toon = self.getAvatar(toonId)
        if self.toon != None and not self.toon.isEmpty():
            self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat')
            self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land')
            self.toon.setPlayRate(2.5, 'jump-squat')
            self.toon.setPlayRate(2.0, 'jump-land')
            self.turnLeft = False
            self.turnRight = False
            self.activityFSM.request('Rules')
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask'))
        else:
            self.notify.warning('handleToonJoined could not get toon %d' % toonId)
        return

    def handleToonExited(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonExited')
        if self.toon != None:
            if self.toon.doId != base.localAvatar.doId:
                taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask'))
            self.surface.setZ(self.trampHeight)
            self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat')
            self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land')
            self.toon = None
        return

    def handleToonDisabled(self, toonId):
        DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled')
        DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled')
        if base.localAvatar.doId == toonId:
            self.releaseToon()

    def handleRulesDone(self):
        self.sendUpdate('toonReady')
        self.finishRules()

    def getTitle(self):
        if self.doJellyBeans:
            return TTLocalizer.PartyTrampolineJellyBeanTitle
        elif self.doTricks:
            return TTLocalizer.PartyTrampolineTricksTitle
        else:
            return DistributedPartyActivity.getTitle(self)

    def getInstructions(self):
        return TTLocalizer.PartyTrampolineActivityInstructions

    def updateTask(self, task):
        z = self.toon.getZ()
        dt = globalClock.getDt()
        if self.doSimulateStep:
            self.timeLeftToSimulate += dt
            while self.timeLeftToSimulate >= self.stepDT:
                z, a = self.simulateStep(z)
                self.timeLeftToSimulate -= self.stepDT

        self.toon.setZ(z)
        if z <= self.trampHeight:
            self.surface.setZ(z)
        else:
            self.surface.setZ(self.trampHeight)
        self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor)
        if self.turnLeft:
            self.toon.setH(self.toon.getH() + self.turnFactor * dt)
        if self.turnRight:
            self.toon.setH(self.toon.getH() - self.turnFactor * dt)
        currentPos = base.camera.getPos(self.toon)
        vec = self.targetCameraPos - currentPos
        newPos = currentPos + vec * (dt * self.cameraSpeed)
        base.camera.setPos(self.toon, newPos)
        base.camera.lookAt(self.toon)
        #if z > self.trampHeight:
        #    heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff)
        #    self.toon.dropShadow.setAlphaScale(heightFactor)
        #    self.toon.dropShadow.setScale(max(0.1, heightFactor))
        #else:
        #    self.toon.dropShadow.setAlphaScale(1.0)
        #    self.toon.dropShadow.setScale(1.0)
        if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1:
            self.releaseToon()
        return Task.cont

    def simulateStep(self, z):
        if z >= self.trampHeight:
            a = self.g
            self.toonJumped = False
        else:
            a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity
            if self.toonJumped:
                if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0:
                    a += self.jumpBoost
                    if self.lastPeak < self.beginningBoostThreshold:
                        a += self.beginningBoost
        lastVelocity = self.toonVelocity
        self.toonVelocity += a * self.stepDT
        if lastVelocity > 0.0 and self.toonVelocity <= 0.0:
            topOfJump = True
            bottomOfJump = False
        elif lastVelocity < 0.0 and self.toonVelocity >= 0.0:
            topOfJump = False
            bottomOfJump = True
        else:
            topOfJump = False
            bottomOfJump = False
        newZ = z + self.toonVelocity * self.stepDT
        if newZ > self.topHeight:
            self.topHeight = newZ
            if self.doJellyBeans:
                self.collectJellyBeans(newZ)
        if topOfJump:
            self.lastPeak = newZ
            if newZ >= self.minHeightForText:
                self.heightTextInterval.start()
        if topOfJump:
            if newZ > self.trampHeight + 20.0:
                self.b_requestAnim('Falling')
            elif self.animFSM.state == 'Jump':
                self.b_requestAnim('Falling')
        if newZ <= self.trampHeight and z > self.trampHeight:
            if self.animFSM.state == 'Falling':
                self.b_requestAnim('Land')
            elif self.animFSM.state != 'Neutral':
                self.b_requestAnim('Neutral')
        if bottomOfJump and a > self.boingThreshold:
            base.playSfx(self.boingSound)
        return (newZ, a)

    def collectJellyBeans(self, z):
        beansToRemove = []
        for i in self.beansToCollect:
            height = self.beanDetails[i][0]
            if height <= z:
                beansToRemove.append(i)

        if len(beansToRemove) > 0:
            base.playSfx(self.jellyBeanSound)
            self.numBeansCollected += len(beansToRemove)
            self.b_removeBeans(beansToRemove)

    def remoteUpdateTask(self, task):
        if self.toon != None and not self.toon.isEmpty():
            z = self.toon.getZ()
            if z <= self.trampHeight:
                self.surface.setZ(z)
            else:
                self.surface.setZ(self.trampHeight)
        return Task.cont

    def poofBean(self, bean, beanAnim):
        if bean == None:
            self.notify.warning('poofBean, returning immediately as bean is None')
            return
        if bean.isEmpty():
            self.notify.warning('poofBean, returning immediately as bean is empty')
            return
        currentAlpha = bean.getColorScale()[3]
        currentScale = bean.getScale()
        poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale))
        poofAnim.start()
        return

    def _showFlashMessage(self, message):
        if self.isDisabled():
            return
        if self.flashTextInterval is not None and self.flashTextInterval.isPlaying():
            self.flashTextInterval.finish()
        self.flashText.setText(message)
        self.flashText.setAlphaScale(1.0)
        self.flashText.unstash()
        return

    def _hideFlashMessage(self, duration = 0.0):
        if self.isDisabled():
            pass
        self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash))
        self.flashTextInterval.start()

    def flashMessage(self, message, duration = 0.5):
        self._showFlashMessage(message)
        self._hideFlashMessage(duration)
Beispiel #46
0
class IsisAgent(kinematicCharacterController, DirectObject):
    @classmethod
    def setPhysics(cls, physics):
        """ This method is set in src.loader when the generators are loaded
        into the namespace.  This frees the environment definitions (in 
        scenario files) from having to pass around the physics parameter 
        that is required for all IsisObjects """
        cls.physics = physics

    def __init__(self, name, queueSize=100):

        # load the model and the different animations for the model into an Actor object.
        self.actor = Actor("media/models/boxman", {
            "walk": "media/models/boxman-walk",
            "idle": "media/models/boxman-idle"
        })
        self.actor.setScale(1.0)
        self.actor.setH(0)
        #self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params
        self.actor.setColorScale(random.random(), random.random(),
                                 random.random(), 1.0)
        self.actorNodePath = NodePath('agent-%s' % name)
        self.activeModel = self.actorNodePath

        self.actorNodePath.reparentTo(render)

        self.actor.reparentTo(self.actorNodePath)
        self.name = name
        self.isMoving = False

        # initialize ODE controller
        kinematicCharacterController.__init__(self, IsisAgent.physics,
                                              self.actorNodePath)
        self.setGeomPos(self.actorNodePath.getPos(render))
        """
        Additional Direct Object that I use for convenience.
        """
        self.specialDirectObject = DirectObject()
        """
        How high above the center of the capsule you want the camera to be
        when walking and when crouching. It's related to the values in KCC.
        """
        self.walkCamH = 0.7
        self.crouchCamH = 0.2
        self.camH = self.walkCamH
        """
        This tells the Player Controller what we're aiming at.
        """
        self.aimed = None

        self.isSitting = False
        self.isDisabled = False
        """
        The special direct object is used for trigger messages and the like.
        """
        #self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True])
        #self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False])

        self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"])

        # Expose agent's right hand joint to attach objects to
        self.player_right_hand = self.actor.exposeJoint(
            None, 'modelRoot', 'Hand.R')
        self.player_left_hand = self.actor.exposeJoint(None, 'modelRoot',
                                                       'Hand.L')

        self.right_hand_holding_object = None
        self.left_hand_holding_object = None

        # don't change the color of things you pick up
        self.player_right_hand.setColorScaleOff()
        self.player_left_hand.setColorScaleOff()

        self.player_head = self.actor.exposeJoint(None, 'modelRoot', 'Head')
        self.neck = self.actor.controlJoint(None, 'modelRoot', 'Head')

        self.controlMap = {
            "turn_left": 0,
            "turn_right": 0,
            "move_forward": 0,
            "move_backward": 0,
            "move_right": 0,
            "move_left": 0,
            "look_up": 0,
            "look_down": 0,
            "look_left": 0,
            "look_right": 0,
            "jump": 0
        }
        # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left]
        # turns are in degrees per second, moves are in units per second
        self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60]

        self.originalPos = self.actor.getPos()

        bubble = loader.loadTexture("media/textures/thought_bubble.png")
        #bubble.setTransparency(TransparencyAttrib.MAlpha)

        self.speech_bubble = DirectLabel(parent=self.actor,
                                         text="",
                                         text_wordwrap=10,
                                         pad=(3, 3),
                                         relief=None,
                                         text_scale=(.3, .3),
                                         pos=(0, 0, 3.6),
                                         frameColor=(.6, .2, .1, .5),
                                         textMayChange=1,
                                         text_frame=(0, 0, 0, 1),
                                         text_bg=(1, 1, 1, 1))
        #self.myImage=
        self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.speech_bubble.setColorScaleOff()
        self.speech_bubble.component('text0').textNode.setCardDecal(1)
        self.speech_bubble.setBillboardAxis()
        # hide the speech bubble from IsisAgent's own camera
        self.speech_bubble.hide(BitMask32.bit(1))

        self.thought_bubble = DirectLabel(parent=self.actor,
                                          text="",
                                          text_wordwrap=9,
                                          text_frame=(1, 0, -2, 1),
                                          text_pos=(0, .5),
                                          text_bg=(1, 1, 1, 0),
                                          relief=None,
                                          frameSize=(0, 1.5, -2, 3),
                                          text_scale=(.18, .18),
                                          pos=(0, 0.2, 3.6),
                                          textMayChange=1,
                                          image=bubble,
                                          image_pos=(0, 0.1, 0),
                                          sortOrder=5)
        self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha)
        # stop the speech bubble from being colored like the agent
        self.thought_bubble.setColorScaleOff()
        self.thought_bubble.component('text0').textNode.setFrameColor(
            1, 1, 1, 0)
        self.thought_bubble.component('text0').textNode.setFrameAsMargin(
            0.1, 0.1, 0.1, 0.1)
        self.thought_bubble.component('text0').textNode.setCardDecal(1)
        self.thought_bubble.setBillboardAxis()
        # hide the thought bubble from IsisAgent's own camera
        self.thought_bubble.hide(BitMask32.bit(1))
        # disable by default
        self.thought_bubble.hide()
        self.thought_filter = {}  # only show thoughts whose values are in here
        self.last_spoke = 0  # timers to keep track of last thought/speech and
        self.last_thought = 0  # hide visualizations

        # put a camera on ralph
        self.fov = NodePath(Camera('RaphViz'))
        self.fov.node().setCameraMask(BitMask32.bit(1))

        # position the camera to be infront of Boxman's face.
        self.fov.reparentTo(self.player_head)
        # x,y,z are not in standard orientation when parented to player-Head
        self.fov.setPos(0, 0.2, 0)
        # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face.
        self.fov.setHpr(0, -90, 0)

        lens = self.fov.node().getLens()
        lens.setFov(60)  #  degree field of view (expanded from 40)
        lens.setNear(0.2)
        #self.fov.node().showFrustum() # displays a box around his head
        #self.fov.place()

        self.prevtime = 0
        self.current_frame_count = 0

        self.isSitting = False
        self.isDisabled = False
        self.msg = None
        self.actorNodePath.setPythonTag("agent", self)

        # Initialize the action queue, with a maximum length of queueSize
        self.queue = []
        self.queueSize = queueSize
        self.lastSense = 0

    def setLayout(self, layout):
        """ Dummy method called by spatial methods for use with objects. 
        Doesn't make sense for an agent that can move around."""
        pass

    def setPos(self, pos):
        """ Wrapper to set the position of the ODE geometry, which in turn 
        sets the visual model's geometry the next time the update() method
        is called. """
        self.setGeomPos(pos)

    def setPosition(self, pos):
        self.setPos(pos)

    def reparentTo(self, parent):
        self.actorNodePath.reparentTo(parent)

    def setControl(self, control, value):
        """Set the state of one of the character's movement controls.  """
        self.controlMap[control] = value

    def get_objects_in_field_of_vision(self, exclude=['isisobject']):
        """ This works in an x-ray style. Fast. Works best if you listen to
        http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while
        you use it.
        
        needs to exclude isisobjects since they cannot be serialized  
        """
        objects = {}
        for obj in base.render.findAllMatches("**/IsisObject*"):
            if not obj.hasPythonTag("isisobj"):
                continue
            o = obj.getPythonTag("isisobj")
            bounds = o.activeModel.getBounds()
            bounds.xform(o.activeModel.getMat(self.fov))
            if self.fov.node().isInView(o.activeModel.getPos(self.fov)):
                pos = o.activeModel.getPos(render)
                pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2)
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d,
                                               Point3(p2[0], 0, p2[1]))
                object_dict = {}
                if 'x_pos' not in exclude: object_dict['x_pos'] = p3[0]
                if 'y_pos' not in exclude: object_dict['y_pos'] = p3[2]
                if 'distance' not in exclude:
                    object_dict['distance'] = o.activeModel.getDistance(
                        self.fov)
                if 'orientation' not in exclude:
                    object_dict['orientation'] = o.activeModel.getH(self.fov)
                if 'actions' not in exclude:
                    object_dict['actions'] = o.list_actions()
                if 'isisobject' not in exclude: object_dict['isisobject'] = o
                # add item to dinctionary
                objects[o] = object_dict
        return objects

    def get_agents_in_field_of_vision(self):
        """ This works in an x-ray vision style as well"""
        agents = {}
        for agent in base.render.findAllMatches("**/agent-*"):
            if not agent.hasPythonTag("agent"):
                continue
            a = agent.getPythonTag("agent")
            bounds = a.actorNodePath.getBounds()
            bounds.xform(a.actorNodePath.getMat(self.fov))
            pos = a.actorNodePath.getPos(self.fov)
            if self.fov.node().isInView(pos):
                p1 = self.fov.getRelativePoint(render, pos)
                p2 = Point2()
                self.fov.node().getLens().project(p1, p2)
                p3 = aspect2d.getRelativePoint(render2d,
                                               Point3(p2[0], 0, p2[1]))
                agentDict = {'x_pos': p3[0],\
                             'y_pos': p3[2],\
                             'distance':a.actorNodePath.getDistance(self.fov),\
                             'orientation': a.actorNodePath.getH(self.fov)}
                agents[a] = agentDict
        return agents

    def in_view(self, isisobj):
        """ Returns true iff a particular isisobject is in view """
        return len(
            filter(lambda x: x['isisobject'] == isisobj,
                   self.get_objects_in_field_of_vision(exclude=[]).values()))

    def get_objects_in_view(self):
        """ Gets objects through ray tracing.  Slow"""
        return self.picker.get_objects_in_view()

    def control__turn_left__start(self, speed=None):
        self.setControl("turn_left", 1)
        self.setControl("turn_right", 0)
        if speed:
            self.speeds[0] = speed
        return "success"

    def control__turn_left__stop(self):
        self.setControl("turn_left", 0)
        return "success"

    def control__turn_right__start(self, speed=None):
        self.setControl("turn_left", 0)
        self.setControl("turn_right", 1)
        if speed:
            self.speeds[1] = speed
        return "success"

    def control__turn_right__stop(self):
        self.setControl("turn_right", 0)
        return "success"

    def control__move_forward__start(self, speed=None):
        self.setControl("move_forward", 1)
        self.setControl("move_backward", 0)
        if speed:
            self.speeds[2] = speed
        return "success"

    def control__move_forward__stop(self):
        self.setControl("move_forward", 0)
        return "success"

    def control__move_backward__start(self, speed=None):
        self.setControl("move_forward", 0)
        self.setControl("move_backward", 1)
        if speed:
            self.speeds[3] = speed
        return "success"

    def control__move_backward__stop(self):
        self.setControl("move_backward", 0)
        return "success"

    def control__move_left__start(self, speed=None):
        self.setControl("move_left", 1)
        self.setControl("move_right", 0)
        if speed:
            self.speeds[4] = speed
        return "success"

    def control__move_left__stop(self):
        self.setControl("move_left", 0)
        return "success"

    def control__move_right__start(self, speed=None):
        self.setControl("move_right", 1)
        self.setControl("move_left", 0)
        if speed:
            self.speeds[5] = speed
        return "success"

    def control__move_right__stop(self):
        self.setControl("move_right", 0)
        return "success"

    def control__look_left__start(self, speed=None):
        self.setControl("look_left", 1)
        self.setControl("look_right", 0)
        if speed:
            self.speeds[9] = speed
        return "success"

    def control__look_left__stop(self):
        self.setControl("look_left", 0)
        return "success"

    def control__look_right__start(self, speed=None):
        self.setControl("look_right", 1)
        self.setControl("look_left", 0)
        if speed:
            self.speeds[8] = speed
        return "success"

    def control__look_right__stop(self):
        self.setControl("look_right", 0)
        return "success"

    def control__look_up__start(self, speed=None):
        self.setControl("look_up", 1)
        self.setControl("look_down", 0)
        if speed:
            self.speeds[6] = speed
        return "success"

    def control__look_up__stop(self):
        self.setControl("look_up", 0)
        return "success"

    def control__look_down__start(self, speed=None):
        self.setControl("look_down", 1)
        self.setControl("look_up", 0)
        if speed:
            self.speeds[7] = speed
        return "success"

    def control__look_down__stop(self):
        self.setControl("look_down", 0)
        return "success"

    def control__jump(self):
        self.setControl("jump", 1)
        return "success"

    def control__view_objects(self):
        """ calls a raytrace to to all objects in view """
        objects = self.get_objects_in_field_of_vision()
        self.control__say(
            "If I were wearing x-ray glasses, I could see %i items" %
            len(objects))
        print "Objects in view:", objects
        return objects

    def control__sense(self):
        """ perceives the world, returns percepts dict """
        percepts = dict()
        # eyes: visual matricies
        #percepts['vision'] = self.sense__get_vision()
        # objects in purview (cheating object recognition)
        percepts['objects'] = self.sense__get_objects()
        # global position in environment - our robots can have GPS :)
        percepts['position'] = self.sense__get_position()
        # language: get last utterances that were typed
        percepts['language'] = self.sense__get_utterances()
        # agents: returns a map of agents to a list of actions that have been sensed
        percepts['agents'] = self.sense__get_agents()
        print percepts
        return percepts

    def control__think(self, message, layer=0):
        """ Changes the contents of an agent's thought bubble"""
        # only say things that are checked in the controller
        if self.thought_filter.has_key(layer):
            self.thought_bubble.show()
            self.thought_bubble['text'] = message
            #self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05)
            #self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer])
            self.last_thought = 0
        return "success"

    def control__say(self, message="Hello!"):
        self.speech_bubble['text'] = message
        self.last_spoke = 0
        return "success"

    """

    Methods explicitly for IsisScenario files 

    """

    def put_in_front_of(self, isisobj):
        # find open direction
        pos = isisobj.getGeomPos()
        direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0))
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
            'aimRay', 5, [pos, direction], [isisobj.geom])
        print "CLOSEST", closestEntry, closestObject
        if closestObject == None:
            self.setPosition(pos + Vec3(0, 2, 0))
        else:
            print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (
                isisobj, closestObject)
            direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0))
            closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
                'aimRay', 5, [pos, direction], [isisobj.geom])
            if closestEntry == None:
                self.setPosition(pos + Vec3(0, -2, 0))
            else:
                print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (
                    isisobj, closestObject)
                direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0))
                closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
                    'aimRay', 5, [pos, direction], [isisobj.geom])
                if closestEntry == None:
                    self.setPosition(pos + Vec3(2, 0, 0))
                else:
                    print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (
                        isisobj, closestObject)
                    # there's only one option left, do it anyway
                    self.setPosition(pos + Vec3(-2, 0, 0))
        # rotate agent to look at it
        self.actorNodePath.setPos(self.getGeomPos())
        self.actorNodePath.lookAt(pos)
        self.setH(self.actorNodePath.getH())

    def put_in_right_hand(self, target):
        return self.pick_object_up_with(target, self.right_hand_holding_object,
                                        self.player_right_hand)

    def put_in_left_hand(self, target):
        return self.pick_object_up_with(target, self.left_hand_holding_object,
                                        self.player_left_hand)

    def __get_object_in_center_of_view(self):
        direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
        pos = self.fov.getPos(render)
        exclude = [
        ]  #[base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom]
        closestEntry, closestObject = IsisAgent.physics.doRaycastNew(
            'aimRay', 5, [pos, direction], exclude)
        return closestObject

    def pick_object_up_with(self, target, hand_slot, hand_joint):
        """ Attaches an IsisObject, target, to the hand joint.  Does not check anything first,
        other than the fact that the hand joint is not currently holding something else."""
        if hand_slot != None:
            print 'already holding ' + hand_slot.getName() + '.'
            return None
        else:
            if target.layout:
                target.layout.remove(target)
                target.layout = None
            # store original position
            target.originalHpr = target.getHpr(render)
            target.disable()  #turn off physics
            if target.body: target.body.setGravityMode(0)
            target.reparentTo(hand_joint)
            target.setPosition(hand_joint.getPos(render))
            target.setTag('heldBy', self.name)
            if hand_joint == self.player_right_hand:
                self.right_hand_holding_object = target
            elif hand_joint == self.player_left_hand:
                self.left_hand_holding_object = target
            hand_slot = target
            return target

    def control__pick_up_with_right_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return "error: no target in reach"
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with right hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target,
                                            self.right_hand_holding_object,
                                            self.player_right_hand)
        else:
            print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).'
            return 'error: object not graspable'

    def control__pick_up_with_left_hand(self, target=None):
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag("isisobj")
        print "attempting to pick up " + target.name + " with left hand.\n"
        if self.can_grasp(target):  # object within distance
            return self.pick_object_up_with(target,
                                            self.left_hand_holding_object,
                                            self.player_left_hand)
        else:
            print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).'
            return 'error: object not graspable'

    def control__drop_from_right_hand(self):
        print "attempting to drop object from right hand.\n"

        if self.right_hand_holding_object is None:
            print 'right hand is not holding an object.'
            return False
        if self.right_hand_holding_object.getNetTag('heldBy') == self.name:
            self.right_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_right_hand.getPos(render)
            heldPos = self.right_hand_holding_object.geom.getPosition()
            self.right_hand_holding_object.setPosition(pos)
            self.right_hand_holding_object.synchPosQuatToNode()
            self.right_hand_holding_object.setTag('heldBy', '')
            self.right_hand_holding_object.setRotation(
                self.right_hand_holding_object.originalHpr)
            self.right_hand_holding_object.enable()
            if self.right_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.right_hand_holding_object.body.setGravityMode(1)
                self.right_hand_holding_object.getBody().setForce(
                    quat.xform(Vec3(0, force, 0)))
            self.right_hand_holding_object = None
            return 'success'
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__drop_from_left_hand(self):
        print "attempting to drop object from left hand.\n"
        if self.left_hand_holding_object is None:
            return 'left hand is not holding an object.'
        if self.left_hand_holding_object.getNetTag('heldBy') == self.name:
            self.left_hand_holding_object.reparentTo(render)
            direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0))
            pos = self.player_left_hand.getPos(render)
            heldPos = self.left_hand_holding_object.geom.getPosition()
            self.left_hand_holding_object.setPosition(pos)
            self.left_hand_holding_object.synchPosQuatToNode()
            self.left_hand_holding_object.setTag('heldBy', '')
            self.left_hand_holding_object.setRotation(
                self.left_hand_holding_object.originalHpr)
            self.left_hand_holding_object.enable()
            if self.left_hand_holding_object.body:
                quat = self.getQuat()
                # throw object
                force = 5
                self.left_hand_holding_object.body.setGravityMode(1)
                self.left_hand_holding_object.getBody().setForce(
                    quat.xform(Vec3(0, force, 0)))
            self.left_hand_holding_object = None
            return 'success'
        else:
            return "Error: not being held by agent %s" % (self.name)

    def control__use_right_hand(self, target=None, action=None):
        # TODO, rename this to use object with
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag('isisobj')
        print "Trying to use object", target
        if self.can_grasp(target):
            if (target.call(self, action, self.right_hand_holding_object) or
                (self.right_hand_holding_object and
                 self.right_hand_holding_object.call(self, action, target))):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def control__use_left_hand(self, target=None, action=None):
        if not action:
            if self.msg:
                action = self.msg
            else:
                action = "divide"
        if not target:
            target = self.__get_object_in_center_of_view()
            if not target:
                print "no target in reach"
                return
        else:
            target = render.find("**/*" + target + "*").getPythonTag('isisobj')
        if self.can_grasp(target):
            if (target.call(self, action, self.left_hand_holding_object) or
                (self.left_hand_holding_object and
                 self.left_hand_holding_object.call(self, action, target))):
                return "success"
            return str(action) + " not associated with either target or object"
        return "target not within reach"

    def can_grasp(self, isisobject):
        distance = isisobject.activeModel.getDistance(self.fov)
        print "distance = ", distance
        return distance < 5.0

    def is_holding(self, object_name):
        return ((self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag('isisobj').name  == object_name)) \
             or (self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag('isisobj').name == object_name)))

    def empty_hand(self):
        if (self.left_hand_holding_object is None):
            return self.player_left_hand
        elif (self.right_hand_holding_object is None):
            return self.player_right_hand
        return False

    def has_empty_hand(self):
        return (self.empty_hand() is not False)

    def control__use_aimed(self):
        """
        Try to use the object that we aim at, by calling its callback method.
        """
        target = self.__get_object_in_center_of_view()
        if target.selectionCallback:
            target.selectionCallback(self, dir)
        return "success"

    def sense__get_position(self):
        x, y, z = self.actorNodePath.getPos()
        h, p, r = self.actorNodePath.getHpr()
        #FIXME
        # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr()
        left_hand_obj = ""
        right_hand_obj = ""
        if self.left_hand_holding_object:
            left_hand_obj = self.left_hand_holding_object.getName()
        if self.right_hand_holding_object:
            right_hand_obj = self.right_hand_holding_object.getName()
        return {'body_x': x, 'body_y': y, 'body_z': z,'body_h':h,\
                'body_p': p, 'body_r': r,  'in_left_hand': left_hand_obj, 'in_right_hand':right_hand_obj}

    def sense__get_vision(self):
        self.fov.node().saveScreenshot("temp.jpg")
        image = Image.open("temp.jpg")
        os.remove("temp.jpg")
        return image

    def sense__get_objects(self):
        return dict([x.getName(), y]
                    for (x,
                         y) in self.get_objects_in_field_of_vision().items())

    def sense__get_agents(self):
        curSense = time()
        agents = {}
        for k, v in self.get_agents_in_field_of_vision().items():
            v['actions'] = k.get_other_agents_actions(self.lastSense, curSense)
            agents[k.name] = v
        self.lastSense = curSense
        return agents

    def sense__get_utterances(self):
        """ Clear out the buffer of things that the teacher has typed,
        FIXME: this doesn't work right now """
        return []
        utterances = self.teacher_utterances
        self.teacher_utterances = []
        return utterances

    def debug__print_objects(self):
        text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys())
        print text

    def add_action_to_history(self, action, args, result=0):
        self.queue.append((time(), action, args, result))
        if len(self.queue) > self.queueSize:
            self.queue.pop(0)

    def get_other_agents_actions(self, start=0, end=None):
        if not end:
            end = time()
        actions = []
        for act in self.queue:
            if act[0] >= start:
                if act[0] < end:
                    actions.append(act)
                else:
                    break
        return actions

    def update(self, stepSize=0.1):
        self.speed = [0.0, 0.0]
        self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70))
        self.actorNodePath.setQuat(self.getQuat())
        # the values in self.speeds are used as coefficientes for turns and movements
        if (self.controlMap["turn_left"] != 0):
            self.addToH(stepSize * self.speeds[0])
        if (self.controlMap["turn_right"] != 0):
            self.addToH(-stepSize * self.speeds[1])
        if self.verticalState == 'ground':
            # these actions require contact with the ground
            if (self.controlMap["move_forward"] != 0):
                self.speed[1] = self.speeds[2]
            if (self.controlMap["move_backward"] != 0):
                self.speed[1] = -self.speeds[3]
            if (self.controlMap["move_left"] != 0):
                self.speed[0] = -self.speeds[4]
            if (self.controlMap["move_right"] != 0):
                self.speed[0] = self.speeds[5]
            if (self.controlMap["jump"] != 0):
                kinematicCharacterController.jump(self)
                # one jump at a time!
                self.controlMap["jump"] = 0
        if (self.controlMap["look_left"] != 0):
            self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80)
        if (self.controlMap["look_right"] != 0):
            self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80)
        if (self.controlMap["look_up"] != 0):
            self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80)
        if (self.controlMap["look_down"] != 0):
            self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80)

        kinematicCharacterController.update(self, stepSize)
        """
        Update the held object position to be in the hands
        """
        if self.right_hand_holding_object != None:
            self.right_hand_holding_object.setPosition(
                self.player_right_hand.getPos(render))
        if self.left_hand_holding_object != None:
            self.left_hand_holding_object.setPosition(
                self.player_left_hand.getPos(render))

        #Update the dialog box and thought windows
        #This allows dialogue window to gradually decay (changing transparancy) and then disappear
        self.last_spoke += stepSize / 2
        self.last_thought += stepSize / 2
        self.speech_bubble['text_bg'] = (1, 1, 1, 1 / (self.last_spoke + 0.01))
        self.speech_bubble['frameColor'] = (.6, .2, .1,
                                            .5 / (self.last_spoke + 0.01))
        if self.last_spoke > 2:
            self.speech_bubble['text'] = ""
        if self.last_thought > 1:
            self.thought_bubble.hide()

        # If the character is moving, loop the run animation.
        # If he is standing still, stop the animation.
        if (self.controlMap["move_forward"] !=
                0) or (self.controlMap["move_backward"] !=
                       0) or (self.controlMap["move_left"] !=
                              0) or (self.controlMap["move_right"] != 0):
            if self.isMoving is False:
                self.isMoving = True
        else:
            if self.isMoving:
                self.current_frame_count = 5.0
                self.isMoving = False

        total_frame_num = self.actor.getNumFrames('walk')
        if self.isMoving:
            self.current_frame_count = self.current_frame_count + (stepSize *
                                                                   250.0)
            if self.current_frame_count > total_frame_num:
                self.current_frame_count = self.current_frame_count % total_frame_num
            self.actor.pose('walk', self.current_frame_count)
        elif self.current_frame_count != 0:
            self.current_frame_count = 0
            self.actor.pose('idle', 0)
        return Task.cont

    def destroy(self):
        self.disable()
        self.specialDirectObject.ignoreAll()
        self.actorNodePath.removeNode()
        del self.specialDirectObject

        kinematicCharacterController.destroy(self)

    def disable(self):
        self.isDisabled = True
        self.geom.disable()
        self.footRay.disable()

    def enable(self):
        self.footRay.enable()
        self.geom.enable()
        self.isDisabled = False

    """
    Set camera to correct height above the center of the capsule
    when crouching and when standing up.
    """

    def crouch(self):
        kinematicCharacterController.crouch(self)
        self.camH = self.crouchCamH

    def crouchStop(self):
        """
        Only change the camera's placement when the KCC allows standing up.
        See the KCC to find out why it might not allow it.
        """
        if kinematicCharacterController.crouchStop(self):
            self.camH = self.walkCamH