Beispiel #1
0
def make_boss(head, torso, path=""):
    """Return any cog boss as an Actor.

    Args:
        head (str): The name of the boss' suit to be used for its head.
        torse (str): The name of the boss' suit to be used for its torso.
        path (str, optional): The file path to the Toontown phase files.
            Defaults to Panda3D's search path.

    Examples:
        from toontown import make_boss

        CFO = make_boss("cash", "cash")
        CFO.loop("Ff_neutral")

    Returns:
        An instance of Panda3D's Actor class.
    """
    if path:
        path = pfile.fromOsSpecific("%s/" % path).getFullpath()

    boss_dict = {
        "sell": "phase_9/models/char/sellbotBoss",
        "cash": "phase_10/models/char/cashbotBoss",
        "law": "phase_11/models/char/lawbotBoss",
        "boss": "phase_12/models/char/bossbotBoss"
    }

    head_dict, torso_dict, legs_dict = cog_animation("Boss", path)

    animation = {
        "head": head_dict,
        "torso": torso_dict,
        "legs": legs_dict
    }

    parts = {
        "head": "%s%s-head-zero.bam" % (path, boss_dict[head]),
        "torso": "%s%s-torso-zero.bam" % (path, boss_dict[torso]),
        "legs": "%sphase_9/models/char/bossCog-legs-zero.bam" % path
    }

    boss = Actor(parts, animation)
    treads = loader.loadModel(
        "%sphase_9/models/char/bossCog-treads.bam" % path
    )
    boss.attach("head", "torso", "joint34")
    boss.attach("torso", "legs", "joint_pelvis")
    treads.reparentTo(boss.find("**/joint_axle"))
    boss.reparentTo(render)
    return boss
Beispiel #2
0
def make_boss(head, torso, path=""):
    """Return any cog boss as an Actor.

    Args:
        head (str): The name of the boss' suit to be used for its head.
        torse (str): The name of the boss' suit to be used for its torso.
        path (str, optional): The file path to the Toontown phase files.
            Defaults to Panda3D's search path.

    Examples:
        from toontown import make_boss

        CFO = make_boss("cash", "cash")
        CFO.loop("Ff_neutral")

    Returns:
        An instance of Panda3D's Actor class.
    """
    if path:
        path = pfile.fromOsSpecific("%s/" % path).getFullpath()

    boss_dict = {
        "sell": "phase_9/models/char/sellbotBoss",
        "cash": "phase_10/models/char/cashbotBoss",
        "law": "phase_11/models/char/lawbotBoss",
        "boss": "phase_12/models/char/bossbotBoss"
    }

    head_dict, torso_dict, legs_dict = cog_animation("Boss", path)

    animation = {"head": head_dict, "torso": torso_dict, "legs": legs_dict}

    parts = {
        "head": "%s%s-head-zero.bam" % (path, boss_dict[head]),
        "torso": "%s%s-torso-zero.bam" % (path, boss_dict[torso]),
        "legs": "%sphase_9/models/char/bossCog-legs-zero.bam" % path
    }

    boss = Actor(parts, animation)
    treads = loader.loadModel("%sphase_9/models/char/bossCog-treads.bam" %
                              path)
    boss.attach("head", "torso", "joint34")
    boss.attach("torso", "legs", "joint_pelvis")
    treads.reparentTo(boss.find("**/joint_axle"))
    boss.reparentTo(render)
    return boss
Beispiel #3
0
class ToonMaker:
    def ToonMaker(self, legs, torso, head, shirtText, sleeveText, pantsText,
                  number, gender):
        if gender == 'm':
            gender = 'shorts'
        elif gender == 'f':
            gender = 'skirt'
        self.Toon = Actor(
            {
                'legs':
                'phase_3/models/char/tt_a_chr_dg%s_shorts_legs_1000.bam' %
                (legs),
                'torso':
                'phase_3/models/char/tt_a_chr_dg%s_%s_torso_1000.bam' %
                (torso, gender),
                'head':
                'phase_3/models/char/tt_a_chr_dg%s_shorts_head_1000.bam' %
                (head)
            }, {
                'legs': {
                    'neutral':
                    'phase_3/models/char/tt_a_chr_dg%s_shorts_legs_neutral.bam'
                    % (legs)
                },
                'torso': {
                    'neutral':
                    'phase_3/models/char/tt_a_chr_dg%s_%s_torso_neutral.bam' %
                    (torso, gender)
                },
                'head': {
                    'neutral':
                    'phase_3/models/char/tt_a_chr_dg%s_shorts_head_neutral.bam'
                    % (head)
                }
            })
        self.Toon.reparentTo(render)
        self.Toon.attach("head", "torso", "def_head")
        self.Toon.attach("torso", "legs", "joint_hips")
        self.Toon.loop('neutral')
        self.Toon.setBlend(frameBlend=True)
        self.Toon.find('**/hands').setColor(1, 1, 1, 1)
        self.Toon.find('**/shoes').removeNode()
        self.Toon.find('**/boots_short').removeNode()
        self.Toon.find('**/boots_long').removeNode()

        shirt = loader.loadTexture(shirtText)
        sleeve = loader.loadTexture(sleeveText)
        pants = loader.loadTexture(pantsText)
        self.Toon.find('**/torso-top').setTexture(shirt, 1)
        self.Toon.find('**/sleeves').setTexture(sleeve, 1)
        self.Toon.find('**/torso-bot').setTexture(pants, 1)

        fur = (.75, .25, .25, 1)
        self.Toon.find('**/feet').setColor(fur)
        self.Toon.find('**/legs').setColor(fur)
        self.Toon.find('**/arms').setColor(fur)
        self.Toon.find('**/neck').setColor(fur)
        self.Toon.find('**/head').setColor(fur)
        self.Toon.find('**/head-front').setColor(fur)
        self.Toon.setPos(number, 0, 0)
        self.Toon.setH(180)

        Hat = loader.loadModel(
            'phase_4/models/accessories/tt_m_chr_avt_acc_hat_bowler.bam')
        Hat.setColor(1)
        Hat.reparentTo(self.Toon.find('**/head'))
        Hat.setZ(0.30)
        Hat.setHpr(180.00, 330.00, 0.00)
        Hat.setScale(0.35)
        self.Toon.find('**/head').removeNode()
        self.Toon.find('**/head-front').removeNode()
        self.Toon.find('**/muzzle').removeNode()
        self.Toon.find('**/nose').removeNode()
        self.Toon.find('**/eyes').removeNode()
        self.Toon.find('**/ears').removeNode()
Beispiel #4
0
class Avatar(DirectObject):
    
    def __init__(self):
        self.data = {
        'Animal' : None,
        'Gender' : None,
        'Weight' : None,
        'Height' : None,
        'Color' : None,
        'HeadType' : None,
        'HeadLength' : None,
        'Shirt' : None,
        'Bottoms' : None
        }
        
    def setData(self, key, value):
        self.data[key] = value
        
    def getData(self):
        return self.data
        
    def generateAnims(self, torso = False, legs = False):
        anims = {}
        if(torso):
            for anim in Anims:
                anims[anim] = loader.loadModel('phase_3/models/char/%s-torso-%s-%s.bam' % (self.data['Weight'], self.data['Gender'], anim))
        if(legs):
            for anim in Anims:
                anims[anim] = loader.loadModel('phase_3/models/char/%s-legs-%s.bam' % (self.data['Height'], anim))
        return anims
    
    def removeOtherParts(self, nodepath, impotent):
        if(impotent == None):
            matches = nodepath
            for part in range(0, matches.getNumPaths()):
                name = matches.getPath(part).getName()
                if(name):
                    if(name == 'muzzle-short-neutral' and self.data['Animal'] == 'mouse'):
                        if(self.data['HeadType'] == 500 or self.data['HeadType'] == 1000):
                            return
                    matches.getPath(part).removeNode()
        else:
            matches = nodepath
            for part in range(0, matches.getNumPaths()):
                if(part != impotent):
                    if(matches.getPath(part).getName()):
                        matches.getPath(part).removeNode()
    
    def setColor(self):
        colorEarAnimals = {'dog', 'horse', 'monkey'}
        body = ['**/head-*', '**/neck', '**/arms', '**/legs', '**/feet', '**/head']
        if(self.data['Animal'] not in colorEarAnimals):
            body.append('**/*ears*')
        for part in range(len(body)):
            self.Avatar.findAllMatches(body[part]).setColor(self.data['Color'])
        self.Avatar.findAllMatches("**/hands").setColor(AvatarAttributes().getColor('white'))
        
    def generate(self):
        head = loader.loadModel('phase_3/models/char/%s-heads-%s.bam' % (self.data['Animal'], self.data['HeadType']))
        torso = loader.loadModel('phase_3/models/char/%s-torso-%s.bam' % (self.data['Weight'], self.data['Gender']))
        legs = loader.loadModel('phase_3/models/char/%s-legs.bam' % (self.data['Height']))
        
        if(self.data['HeadLength'] == 'short'):
            self.removeOtherParts(head.findAllMatches('**/*long*'), None)
        else:
            self.removeOtherParts(head.findAllMatches('**/*short*'), None)
        muzzleParts = head.findAllMatches('**/*muzzle*')
        if(self.data['Animal'] != 'dog'):
            for partNum in range(0, muzzleParts.getNumPaths()):
                part = muzzleParts.getPath(partNum)
                if not 'neutral' in part.getName():
                    part.hide()
        self.removeOtherParts(legs.findAllMatches('**/boots*') + legs.findAllMatches('**/shoes'), None)
        torsoAnims = self.generateAnims(torso=True)
        legsAnims = self.generateAnims(legs=True)
        self.Avatar = Actor({'head' : head, 'torso' : torso, 'legs' : legs}, {'torso' : torsoAnims, 'legs' : legsAnims})
        self.Avatar.attach('head', 'torso', 'def_head')
        self.Avatar.attach('torso', 'legs', 'joint_hips')
        if(self.data['Gender'] == 'girl'):
            femaleEyes = loader.loadTexture('phase_3/maps/eyesFemale.jpg', 'phase_3/maps/eyesFemale_a.rgb')
            try:
                self.Avatar.find('**/eyes').setTexture(femaleEyes, 1)
            except: pass
            try:
                self.Avatar.find('**/eyes-%s' % (self.data['HeadLength'])).setTexture(femaleEyes, 1)
            except: pass
        # Reseat pupils of old head models
        pupils = head.findAllMatches('**/*pupil*')
        for pupil in pupils:
            pupil.setY(0.02)
        self.setColor()
        shadow = ShadowCaster(self.Avatar)
        shadow.initializeDropShadow()
        self.Avatar.setPythonTag("AvatarInstance", self)
        
    def getAvatar(self):
        return self.Avatar
        
        
Beispiel #5
0
class Toon(DirectObject.DirectObject):
	def __init__(self, taskMgr):
		#Establish where the current directory of the running file is
		self.currentDirectory = os.path.abspath(sys.path[0])
		self.pandaDirectory = Filename.fromOsSpecific(self.currentDirectory).getFullpath()
		
		#Define variables, particularly to tell if the model is moving
		self.isThrowing = False
		self.isMovingInY = False
		self.isTurning = False
		self.pieIsThrown = False
		self.movementHeading = ''
		self.turnHeading = ''
		self.speed = 0.0
		self.turnSpeed = 0.0
		self.health = 100
		
		#Set object variable to point to the global task manager
		self.taskMgr = taskMgr
		
		#Define pie node, which will serve as the flying part of the pie. Put it far enough away to not cause problems
		self.pieNode = NodePath('pieNode')
		self.pieNode.reparentTo(render)
		self.pieNode.setPos(100, 0, 0)
		
		#Load the pie model and define its scaling motion
		self.pie = loader.loadModel(self.pandaDirectory + "/resources/toon/models/tart.bam")
		self.scalePie = LerpScaleInterval(self.pie, 1, 1, 0)
		
		#Set up the Actor
		self.initActor()
		
		#Initialize animations
		self.toon.loop('neutral', 'torso')
		self.toon.loop('neutral', 'legs')
		
		#Define Y (Forwards/backwards) movement
		self.accept('arrow_up', self.moveInYStart, ['forward'])
		self.accept('arrow_up-up', self.moveInYEnd, ['forward'])
		self.accept('arrow_down', self.moveInYStart, ['backward'])
		self.accept('arrow_down-up', self.moveInYEnd, ['backward'])
		
		#Define turning movement
		self.accept('arrow_right', self.turnStart, ['right'])
		self.accept('arrow_right-up', self.turnEnd, ['right'])
		self.accept('arrow_left', self.turnStart, ['left'])
		self.accept('arrow_left-up', self.turnEnd, ['left'])
		
		#Define pie throwing animation control
		self.accept('control', self.attackStart)
		
		#Set up throwing interval and sequence
		self.throwTorso = self.toon.actorInterval('attackTorso', loop=0)
		self.throw = Sequence(Func(self.toggleIsThrowing),
									Parallel(self.throwTorso, self.scalePie),
									Func(self.toggleIsThrowing),
									Func(self.attackEnd)
									)
		
		#Tell the taskmanager to keep track of this task
		self.taskMgr.add(self.updateToon, 'Update Toon')
		
	def updateToon(self, task):
		#Update the player's position and heading
		if self.isMovingInY:
			self.toon.setY(self.toon, self.speed)
			
		if self.isTurning:
			self.toon.setH(self.toon, self.turnSpeed)
		
		return task.cont
		
	def toggleIsThrowing(self):
		self.isThrowing = not(self.isThrowing)
	
	def attackStart(self):
		#If the player is already throwing, ignore new request
		if self.isThrowing:
			return
		
		#Determine which group of animations to play
		if not self.isMovingInY and not self.isTurning:
			self.toon.loop('attackLegs')
		
		#Render the pie, then throw it!
		self.pie.setHpr(0,0,0)
		self.pie.reparentTo(self.toon.find('**/def_joint_right_hold'))
		self.taskMgr.doMethodLater(2.7, self.throwPie, 'throw pie')
		
		#Call the pre-defined sequence
		self.throw.start()
	
	def attackEnd(self):
		#Determine which animation to play after throwing
		if self.isMovingInY and self.speed > 0:
			self.toon.loop('run', 'torso')
			
		elif self.isMovingInY and self.speed < 0:
			self.toon.loop('walk', 'torso')
		
		elif self.isTurning:
			self.toon.loop('walk', 'torso')
		
		else:
			self.toon.loop('neutral', 'torso')
	
	def throwPie(self, task):
		#Get the current position and hpr of the pie for the pieNode
		self.pieNode.setPos(self.pie.getPos(render))
		pieHpr = Point3(self.toon.getH(render) + 90, self.pie.getP(render), 80)
		
		#Reparent the pie to the pieNode
		self.pie.reparentTo(self.pieNode)
		self.pie.setHpr(pieHpr)
		
		#Arch that pieNode puppy!
		self.flyingPie = ProjectileInterval(self.pieNode, startPos=self.pieNode.getPos(), 
											startVel=render.getRelativeVector(self.pie,Vec3(0,0,75)), duration=5)
		self.flyingPie.start()
		
		self.pieIsThrown = True
		
		return task.done
	
	def turnStart(self, direction):
		#If the player is already turning, ignore the new request
		if self.isTurning:
			return
		
		#Set the object heading to prevent pressing the right and left keys at the same time
		self.turnHeading = direction
		
		#If the player is moving in the Y direction...
		if self.isMovingInY:
			#And the player is moving backwards...
			if self.speed < 0:
				#Replace the run animation with walk and play it backwards
				self.toon.setPlayRate(-1, 'walk')
				
		#If the player is not moving
		else:
			#Play the forward plain walking animations
			self.toon.setPlayRate(1, 'walk')
			self.toon.loop('walk', 'torso')
			self.toon.loop('walk', 'legs')
		
		#Determine which heading the player will turn
		if direction == 'right':
			self.turnSpeed = -0.7
		elif direction == 'left':
			self.turnSpeed = 0.7
		
		#Tell task manager to start turning
		self.isTurning = True
		
	def turnEnd(self, direction):
		#If the requested direction conflicts with the heading, ignore the request
		if direction != self.turnHeading:
			return
			
		#If the player is not moving in the Y direction...
		if not self.isMovingInY:
			#Make the animation play neutral before stopping to turn
			self.toon.loop('neutral', 'torso')
			self.toon.loop('neutral', 'legs')
		
		#Tell task manager to stop turning
		self.isTurning = False
		
	def moveInYStart(self, direction):
		#If the player is already moving, ignore the new request
		if self.isMovingInY:
			return
		
		#Set the object heading to prevent pressing the up and down keys at the same time
		self.movementHeading = direction
		
		#If the up key is pressed...
		if direction == 'forward':
			#Set a positive speed and make the player run
			self.speed = 0.6
			self.toon.loop('run', 'torso')
			self.toon.loop('run', 'legs')
		
		#Otherwise...
		elif direction == 'backward':
			#Set a negative speed and make the player walk backwards
			self.speed = -0.3
			self.toon.setPlayRate(-1, 'walk')
			self.toon.loop('walk', 'torso')
			self.toon.loop('walk', 'legs')
		
		#Tell the task manager to start moving in local Y
		self.isMovingInY = True
			
	def moveInYEnd(self, direction):
		#If the requested direction conflicts with the heading, ignore the request
		if direction != self.movementHeading:
			return
		
		#If the player is not turning...
		if not self.isTurning:
			#Set the speed to positive and have the player idle
			self.speed = 0.6
			self.toon.loop('neutral', 'torso')
			self.toon.loop('neutral', 'legs')
			
		#Otherwise...
		else:
			#Make the player walk instead
			self.toon.setPlayRate(1, 'walk')
			self.speed = 0.6
			self.toon.loop('walk', 'torso')
			self.toon.loop('walk', 'legs')
		
		#Tell the task manager to stop moving in local Y
		self.isMovingInY = False
		
	def initActor(self):
		#Create the toon!
		self.toon = Actor({'torso': self.pandaDirectory + '/resources/toon/models/tt_a_chr_dgl_shorts_torso_1000.bam',
							'legs': self.pandaDirectory + '/resources/toon/models/tt_a_chr_dgm_shorts_legs_1000.bam'},
							{'torso':{
							'neutral': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgl_shorts_torso_neutral.bam',
							'run': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgl_shorts_torso_run.bam',
							'attackTorso': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgl_shorts_torso_pie-throw.bam',
							'walk': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgl_shorts_torso_walk.bam'
							},
							'legs':{
							'neutral': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgm_shorts_legs_neutral.bam',
							'run': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgm_shorts_legs_run.bam',
							'attackLegs': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgm_shorts_legs_pie-throw.bam',
							'walk': self.pandaDirectory + '/resources/toon/animations/tt_a_chr_dgm_shorts_legs_walk.bam'
							}})
		self.toon.attach('torso', 'legs', 'joint_hips')
		self.toon.find('**/neck').setColor(1, 1, 0)
		self.toon.find('**/legs').setColor(1, 1, 0)
		self.toon.find('**/arms').setColor(1, 1, 0)
		self.toon.find('**/hands').setColor(1, 1, 1)
		
		#Set textures and remove unnecessary models
		self.toon.find('**/sleeves').setTexture(loader.loadTexture(self.pandaDirectory + '/resources/toon/textures/ttr_t_chr_avt_shirtSleeve_cashbotCrusher.jpg'),1)
		self.toon.find('**/torso-top').setTexture(loader.loadTexture(self.pandaDirectory + '/resources/toon/textures/ttr_t_chr_avt_shirt_cashbotCrusher.jpg'),1)
		self.toon.find('**/torso-bot').setTexture(loader.loadTexture(self.pandaDirectory + '/resources/toon/textures/ttr_t_chr_avt_shorts_cashbotCrusher.jpg'),1)
		self.toon.find('**/shoes').setTexture(loader.loadTexture(self.pandaDirectory + '/resources/toon/textures/ttr_t_chr_avt_acc_sho_cashbotCrusher.jpg'),1)
		self.toon.find('**/feet').removeNode()
		self.toon.find('**/boots_short').removeNode()
		self.toon.find('**/boots_long').removeNode()
		
		#Create the toon head!
		self.toonHead = loader.loadModel(self.pandaDirectory + '/resources/toon/models/tt_a_chr_dgm_skirt_head_1000.bam')
		self.toonHead.reparentTo(self.toon.find('**/def_head'))
		self.toonHead.find('**/head').setColor(1, 1, 0)
		self.toonHead.find('**/head-front').setColor(1, 1, 0)
		
		#Add a cute hat
		self.topHat = loader.loadModel(self.pandaDirectory + '/resources/toon/models/tt_m_chr_avt_acc_hat_topHat.bam')
		self.topHat.reparentTo(self.toonHead.find('**/head'))
		self.topHat.setZ(0.5)
		self.topHat.setHpr(180,-45,0)
		self.topHat.setTexture(loader.loadTexture(self.pandaDirectory + '/resources/toon/textures/tt_t_chr_avt_acc_hat_topHatQuizmaster.jpg'),1)
		self.topHat.setScale(0.35)
    otherParts.getPath(partNum).removeNode()
ntrlMuzzle = catHead.find('**/*muzzle*neutral')
otherParts = catHead.findAllMatches('**/*muzzle*')
for partNum in range(0, otherParts.getNumPaths()):
    part = otherParts.getPath(partNum)
    if part != ntrlMuzzle:
        otherParts.getPath(partNum).removeNode()
catTorso = loader.loadModel('phase_3/models/char/tt_a_chr_dgl_skirt_torso_1000.bam')
catLegs  = loader.loadModel('phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
otherParts = catLegs.findAllMatches('**/boots*')+catLegs.findAllMatches('**/shoes')
for partNum in range(0, otherParts.getNumPaths()):
    otherParts.getPath(partNum).removeNode()
 
catBody = Actor({'head':catHead, 'torso':catTorso, 'legs':catLegs},
                {'torso':torsoAnimDict, 'legs':legsAnimDict})
catBody.attach('head', 'torso', 'def_head')
catBody.attach('torso', 'legs', 'joint_hips')
 
gloves = catBody.findAllMatches('**/hands')
ears = catBody.findAllMatches('**/*ears*')
head = catBody.findAllMatches('**/head-*')
sleeves = catBody.findAllMatches('**/sleeves')
shirt = catBody.findAllMatches('**/torso-top')
skirt = catBody.findAllMatches('**/torso-bot')
neck = catBody.findAllMatches('**/neck')
arms = catBody.findAllMatches('**/arms')
legs = catBody.findAllMatches('**/legs')
feet = catBody.findAllMatches('**/feet')
 
bodyNodes = []
bodyNodes += [gloves]
Beispiel #7
0
class CharacterCreator(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        base.win.set_clear_color((0, 0, 0, 0))
        simplepbr.init()
        self.multitex_reducer = MultitexReducer()

        #load textures
        self.textures = {}
        texture_files = "plaid", "shirtnjeans", "jacket"
        for file in texture_files:
            self.textures[file] = loader.loadTexture(
                "textures/{}.png".format(file))

        # camera/control
        self.cam_pivot = NodePath("cam pivot")
        self.cam_pivot.reparentTo(render)
        base.cam.reparent_to(self.cam_pivot)
        base.cam.set_pos(0, -2.7, 1.8)
        self.cam_pivot.set_h(180)
        self.cam_pivot.set_y(0.2)
        self.move_speed = 0.5
        self.zoom_speed = 0.5
        self.last_mouse = [0, 0]
        self.accept("wheel_up", self.zoom_in)
        self.accept("wheel_down", self.zoom_out)
        self.taskMgr.add(self.update_camera)

        # sliders
        self.sliders = {}
        self.y_pos = 0.9

        # jan model
        self.jan = Actor(
            {
                "body": "jan/jan.bam",
                "palisa": "jan/acc/palisa-mije.bam",
                "hair": "jan/acc/hair_raz.bam",
                "clothing": "jan/clothing.bam",
            }, {
                "body": {},
                "palisa": {},
                "hair": {},
                "clothing": {},
            })
        self.jan.attach("hair", "body", "head")
        self.jan.attach("palisa", "body", "waist")
        self.jan.attach("clothing", "body", "root")
        self.jan.play("loop")
        self.jan.setTwoSided(True)
        self.jan.hide_part("palisa")
        self.make_sliders(self.jan)
        #self.jan.flatten_strong()
        #self.jan.post_flatten()
        #self.multitex_reducer.scan(self.jan)
        #self.multitex_reducer.flatten(base.win)

        self.jan.reparent_to(render)
        self.jan.set_transparency(True)

        # talk
        gender = "mije"  #meli
        self.speech = Speech(loader.loadSfx("toki-{}-a.wav".format(gender)))
        self.speech.say("to ki")
        self.speech.say("mi to ki po na")
        self.speech.say("mi o li n si na")
        self.taskMgr.add(self.speech.update)

        self.light_scene()
        render.ls()
        render.analyze()

    def set_shapekey_slider(self, node, shapekey):
        self.set_shapekey(node, shapekey, self.sliders[shapekey]['value'])

    def set_shapekey(self, node, shapekey, value):
        chars = node.find_all_matches('**/+Character')
        for char in chars:
            char.node().get_bundle(0).freeze_joint(shapekey, value)

    def zoom_out(self):
        new_zoom = base.cam.get_y() - self.zoom_speed
        base.cam.set_y(new_zoom)

    def zoom_in(self):
        new_zoom = base.cam.get_y() + self.zoom_speed
        if new_zoom > -1.2:
            new_zoom = -1.2
        base.cam.set_y(new_zoom)

    def update_camera(self, task):
        if base.mouseWatcherNode.is_button_down(MouseButton.three()):
            new_x = base.mouseWatcherNode.getMouseX()
            new_y = base.mouseWatcherNode.getMouseY()
            x = self.last_mouse[0] - new_x
            y = self.last_mouse[1] - new_y
            self.last_mouse = [new_x, new_y]
            pivot = self.cam_pivot
            pivot.set_z(pivot.get_z() + (y * self.move_speed))
            pivot.set_h(pivot.get_h() + (x * (self.move_speed * 640)))
        else:
            self.last_mouse = [0, 0]
        return task.cont

    def make_sliders(self, node):
        for j, joint in enumerate(node.getJoints()):
            if type(joint) == CharacterSlider:
                if not joint.name in self.sliders:
                    self.set_shapekey(node, joint.name, 0)
                    self.sliders[joint.name] = DirectSlider(
                        range=(0, 1),
                        value=0,
                        pageSize=0.2,
                        command=self.set_shapekey_slider,
                        extraArgs=[node, joint.name])
                    self.y_pos -= 0.05
                    slider = self.sliders[joint.name]
                    # slider["value"] = 0.5
                    slider.set_scale(0.25)
                    slider.set_x(-1.5)
                    slider.set_z(self.y_pos)
                    slider_label = OnscreenText(joint.name,
                                                pos=(-1.25, self.y_pos, 0),
                                                scale=0.04,
                                                fg=(1, 1, 1, 1),
                                                align=TextNode.ALeft)

    def light_scene(self):
        sun = DirectionalLight("sun")
        sun.set_color((1, 0.8, 0.8, 1))
        sun_np = render.attachNewNode(sun)
        render.set_light(sun_np)
        sun_np.set_h(185)
        sun_np.set_p(-50)

        moon = DirectionalLight("moon")
        moon.set_color((0.8, 0.8, 1, 1))
        moon_np = render.attachNewNode(moon)
        render.set_light(moon_np)
        moon_np.set_p(-50)
Beispiel #8
0
class CTBase(DirectObject):
    def __init__(self):
        world = World()
        self.loadChar()
        self.SetupKeyControl()
    def loadChar(self):

        self.model = Actor(
            {"head":"phase_3/models/char/mouse-heads-1000.bam",
             "torso":"phase_3/models/char/tt_a_chr_dgm_shorts_torso_1000.bam",
             "legs":"phase_3/models/char/tt_a_chr_dgm_shorts_legs_1000.bam"},

            {"torso":{"run":"phase_3/models/char/tt_a_chr_dgm_shorts_torso_run.bam",
                      "neutral":"phase_3/models/char/tt_a_chr_dgm_shorts_torso_neutral.bam"},
             "legs":{"run":"phase_3/models/char/tt_a_chr_dgm_shorts_legs_run.bam",
                     "neutral":"phase_3/models/char/tt_a_chr_dgm_shorts_legs_neutral.bam"}
            })
        self.model.reparentTo(render)

        self.fishingshirt = loader.loadTexture("phase_4/maps/tt_t_chr_avt_shirt_fishing1.jpg")
        self.sleeve = loader.loadTexture("phase_4/maps/tt_t_chr_avt_shirtSleeve_fishing1.jpg")
        self.shorts = loader.loadTexture("phase_3/maps/desat_shorts_10.jpg")

        self.model.attach("head", "torso", "joint_head")
        self.model.attach("torso", "legs", "joint_hips")
        self.model.find('**/arms').setColor(0, 0, 255)
        self.model.find('**/head-short').setColor(0, 255, 255)
        self.model.find('**/neck').setColor(0, 255, 255)
        self.model.find('**/head-front-short').setColor(0, 255, 255)
        self.model.find('**/ears-short').setColor(0, 255, 255)
        self.model.find('**/hands').setColor(255, 255, 255)
        self.model.find('**/legs').setColor(255, 0, 0)
        self.model.find('**/feet').setColor(255, 0, 0)
        self.model.find('**/torso-top').setTexture(self.fishingshirt, 1)
        self.model.find('**/sleeves').setTexture(self.sleeve, 1)
        self.model.find('**/torso-bot').setTexture(self.shorts, 1)
        self.model.setHpr(-90,0,0)
        self.model.find('**/muzzle-short-smile').removeNode()
        self.model.find('**/muzzle-short-surprise').removeNode()
        self.model.find('**/muzzle-short-angry').removeNode()
        self.model.find('**/muzzle-short-laugh').removeNode()
        self.model.find('**/muzzle-short-sad').removeNode()
        self.model.find('**/head-long').removeNode()
        self.model.find('**/head-front-long').removeNode()
        self.model.find('**/eyes-long').removeNode()
        self.model.find('**/ears-long').removeNode()
        self.model.loop('neutral', 'legs')
        self.model.loop('neutral', 'torso')
        base.disableMouse()
        base.camera.setPos(self.model, 0, -8, 4)
        base.camera.setHpr(-90, 0, 0)



    def SetupKeyControl(self):
        self.accept('arrow_up', self.ArrowUpPress)
        self.accept('arrow_up-repeat', self.ArrowUpPress)
        self.accept('arrow_up-up', self.ArrowUpRelease)
        self.accept('arrow_left', self.ArrowLeftPress)
        self.accept('arrow_left-repeat', self.ArrowLeftPress)
        self.accept('arrow_right', self.ArrowRightPress)
        self.accept('arrow_right-repeat', self.ArrowRightPress)
        self.accept('arrow_down', self.ArrowDownPress)
        self.accept('arrow_down-repeat', self.ArrowDownPress)

    def ArrowUpPress(self):
        self.model.setPos(self.model, 0, 1, 0)
        self.animName = self.model.getCurrentAnim()
        base.camera.setPos(self.model, 0, -8, 4)
        if self.animName == "run":
            pass
        else :
            self.model.loop('run', 'legs')
            self.model.loop('run', 'torso')

    def ArrowDownPress(self):
        self.model.setPos(self.model, 0, -.5, 0)
        base.camera.setPos(self.model, 0, -8, 4)

    def ArrowRightPress(self):
        base.camera.setHpr(base.camera,-3, 0, 0)
        self.model.setHpr(self.model, -3, 0, 0)
        base.camera.setPos(self.model, 0, -8, 4)


    def ArrowLeftPress(self):
        base.camera.setHpr(base.camera,3, 0, 0)
        self.model.setHpr(self.model, 3, 0, 0)
        base.camera.setPos(self.model, 0, -8, 4)

    def ArrowUpRelease(self):
        self.model.loop('neutral', 'legs')
        self.model.loop('neutral', 'torso')
Beispiel #9
0
mouseLegs = loader.loadModel(
    'phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
otherParts = mouseLegs.findAllMatches('**/boots*') + mouseLegs.findAllMatches(
    '**/shoes')
for partNum in range(0, otherParts.getNumPaths()):
    otherParts.getPath(partNum).removeNode()

mouseBody = Actor({
    'head': mouseHead,
    'torso': mouseTorso,
    'legs': mouseLegs
}, {
    'torso': torsoAnimDict,
    'legs': legsAnimDict
})
mouseBody.attach('head', 'torso', 'def_head')
mouseBody.attach('torso', 'legs', 'joint_hips')

#Gloves
gloves = mouseBody.findAllMatches('**/hands')
#Ears
ears = mouseBody.findAllMatches('**/*ears*')
#Head
head = mouseBody.findAllMatches('**/head-*')
#Sleeves
sleeves = mouseBody.findAllMatches('**/sleeves')
#Shirt
shirt = mouseBody.findAllMatches('**/torso-top')
#Shorts
shorts = mouseBody.findAllMatches('**/torso-bot')
#Neck
class SnapshotRenderer:
    def __init__(self, dnaString):
        self.dnaString = dnaString
        loadModels()
        compileGlobalAnimList()
        self.makeFromNetString(dnaString)
        self.toon = Actor()
        self.generateToon()
        self.renderSnapshot()

    def makeFromNetString(self, string):
        dg = PyDatagram(string)
        dgi = PyDatagramIterator(dg)
        self.type = dgi.getFixedString(1)
        if self.type == 't':
            headIndex = dgi.getUint8()
            torsoIndex = dgi.getUint8()
            legsIndex = dgi.getUint8()
            self.head = toonHeadTypes[headIndex]
            self.torso = toonTorsoTypes[torsoIndex]
            self.legs = toonLegTypes[legsIndex]
            gender = dgi.getUint8()
            if gender == 1:
                self.gender = 'm'
            else:
                self.gender = 'f'
            self.topTex = dgi.getUint8()
            self.topTexColor = dgi.getUint8()
            self.sleeveTex = dgi.getUint8()
            self.sleeveTexColor = dgi.getUint8()
            self.botTex = dgi.getUint8()
            self.botTexColor = dgi.getUint8()
            self.armColor = dgi.getUint8()
            self.gloveColor = dgi.getUint8()
            self.legColor = dgi.getUint8()
            self.headColor = dgi.getUint8()
        else:
            notify.error('unknown avatar type: ', self.type)

    def getAnimal(self):
        if self.head[0] == 'd':
            return 'dog'
        elif self.head[0] == 'c':
            return 'cat'
        elif self.head[0] == 'm':
            return 'mouse'
        elif self.head[0] == 'h':
            return 'horse'
        elif self.head[0] == 'r':
            return 'rabbit'
        elif self.head[0] == 'f':
            return 'duck'
        elif self.head[0] == 'p':
            return 'monkey'
        elif self.head[0] == 'b':
            return 'bear'
        elif self.head[0] == 's':
            return 'pig'
        else:
            notify.error('unknown headStyle: ', self.head[0])

    def getArmColor(self):
        try:
            return allColorsList[self.armColor]
        except:
            return allColorsList[0]

    def getLegColor(self):
        try:
            return allColorsList[self.legColor]
        except:
            return allColorsList[0]

    def getHeadColor(self):
        try:
            return allColorsList[self.headColor]
        except:
            return allColorsList[0]

    def getGloveColor(self):
        try:
            return allColorsList[self.gloveColor]
        except:
            return allColorsList[0]

    def getGender(self):
        return self.gender

    def generateToon(self):
        self.setLODs()
        self.generateToonLegs()
        self.generateToonHead(1, ('1000', '500', '250'))
        self.generateToonTorso()
        self.generateToonColor()
        self.parentToonParts()
        # self.rescaleToon()
        # self.resetHeight()
        # self.setupToonNodes()
        self.toon.reparentTo(render)
        self.toon.setPos(0, 5, -3)
        self.toon.setH(180)
        self.toon.getPart('head', '1000').setR(10)
        self.toon.pose('neutral', 0)

    def generateToonLegs(self, copy=1):
        global Preloaded
        legStyle = self.legs
        filePrefix = LegDict.get(legStyle)
        if filePrefix is None:
            print('unknown leg style: %s' % legStyle)
        self.toon.loadModel(Preloaded[filePrefix + '-1000'], 'legs', '1000',
                            True)
        self.toon.loadModel(Preloaded[filePrefix + '-500'], 'legs', '500',
                            True)
        self.toon.loadModel(Preloaded[filePrefix + '-250'], 'legs', '250',
                            True)
        if not copy:
            self.toon.showPart('legs', '1000')
            self.toon.showPart('legs', '500')
            self.toon.showPart('legs', '250')
        self.toon.loadAnims(LegsAnimDict[legStyle], 'legs', '1000')
        self.toon.loadAnims(LegsAnimDict[legStyle], 'legs', '500')
        self.toon.loadAnims(LegsAnimDict[legStyle], 'legs', '250')
        self.toon.findAllMatches('**/boots_short').stash()
        self.toon.findAllMatches('**/boots_long').stash()
        self.toon.findAllMatches('**/shoes').stash()
        return

    def generateToonTorso(self, copy=1, genClothes=1):
        global Preloaded
        torsoStyle = self.torso
        filePrefix = TorsoDict.get(torsoStyle)
        if filePrefix is None:
            self.notify.error('unknown torso style: %s' % torsoStyle)
        self.toon.loadModel(Preloaded[filePrefix + '-1000'], 'torso', '1000',
                            True)
        if len(torsoStyle) == 1:
            self.toon.loadModel(Preloaded[filePrefix + '-1000'], 'torso',
                                '500', True)
            self.toon.loadModel(Preloaded[filePrefix + '-1000'], 'torso',
                                '250', True)
        else:
            self.toon.loadModel(Preloaded[filePrefix + '-500'], 'torso', '500',
                                True)
            self.toon.loadModel(Preloaded[filePrefix + '-250'], 'torso', '250',
                                True)
        if not copy:
            self.toon.showPart('torso', '1000')
            self.toon.showPart('torso', '500')
            self.toon.showPart('torso', '250')
        self.toon.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '1000')
        self.toon.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '500')
        self.toon.loadAnims(TorsoAnimDict[torsoStyle], 'torso', '250')
        if genClothes == 1 and not len(torsoStyle) == 1:
            self.generateToonClothes()
        return

    def generateToonClothes(self, fromNet=0):
        swappedTorso = 0
        if self.toon.hasLOD():
            if self.getGender() == 'f' and fromNet == 0:
                try:
                    bottomPair = GirlBottoms[self.botTex]
                except:
                    bottomPair = GirlBottoms[0]
            try:
                texName = Shirts[self.topTex]
            except:
                texName = Shirts[0]

            shirtTex = loader.loadTexture(texName, okMissing=True)
            if shirtTex is None:
                shirtTex = loader.loadTexture(Shirts[0])
            shirtTex.setMinfilter(Texture.FTLinearMipmapLinear)
            shirtTex.setMagfilter(Texture.FTLinear)
            try:
                shirtColor = ClothesColors[self.topTexColor]
            except:
                shirtColor = ClothesColors[0]

            try:
                texName = Sleeves[self.sleeveTex]
            except:
                texName = Sleeves[0]

            sleeveTex = loader.loadTexture(texName, okMissing=True)
            if sleeveTex is None:
                self.sendLogSuspiciousEvent('failed to load texture %s' %
                                            texName)
                sleeveTex = loader.loadTexture(Sleeves[0])
            sleeveTex.setMinfilter(Texture.FTLinearMipmapLinear)
            sleeveTex.setMagfilter(Texture.FTLinear)
            try:
                sleeveColor = ClothesColors[self.sleeveTexColor]
            except:
                sleeveColor = ClothesColors[0]

            if self.getGender() == 'm':
                try:
                    texName = BoyShorts[self.botTex]
                except:
                    texName = BoyShorts[0]

            else:
                try:
                    texName = GirlBottoms[self.botTex][0]
                except:
                    texName = GirlBottoms[0][0]

            bottomTex = loader.loadTexture(texName, okMissing=True)
            if bottomTex is None:
                self.sendLogSuspiciousEvent('failed to load texture %s' %
                                            texName)
                if self.getGender() == 'm':
                    bottomTex = loader.loadTexture(BoyShorts[0])
                else:
                    bottomTex = loader.loadTexture(GirlBottoms[0][0])
            bottomTex.setMinfilter(Texture.FTLinearMipmapLinear)
            bottomTex.setMagfilter(Texture.FTLinear)
            try:
                bottomColor = ClothesColors[self.botTexColor]
            except:
                bottomColor = ClothesColors[0]

            darkBottomColor = bottomColor * 0.5
            darkBottomColor.setW(1.0)
            for lodName in self.toon.getLODNames():
                thisPart = self.toon.getPart('torso', lodName)
                top = thisPart.find('**/torso-top')
                top.setTexture(shirtTex, 1)
                top.setColor(shirtColor)
                sleeves = thisPart.find('**/sleeves')
                sleeves.setTexture(sleeveTex, 1)
                sleeves.setColor(sleeveColor)
                bottoms = thisPart.findAllMatches('**/torso-bot')
                for bottomNum in xrange(0, bottoms.getNumPaths()):
                    bottom = bottoms.getPath(bottomNum)
                    bottom.setTexture(bottomTex, 1)
                    bottom.setColor(bottomColor)

                caps = thisPart.findAllMatches('**/torso-bot-cap')
                caps.setColor(darkBottomColor)

        return swappedTorso

    def generateToonColor(self):
        parts = self.toon.findAllMatches('**/head*')
        parts.setColor(self.getHeadColor())
        animalType = self.getAnimal()
        if animalType == 'cat' or animalType == 'rabbit' or animalType == 'bear' or animalType == 'mouse' or animalType == 'pig':
            parts = self.toon.findAllMatches('**/ear?-*')
            parts.setColor(self.getHeadColor())

        armColor = self.getArmColor()
        gloveColor = self.getGloveColor()
        legColor = self.getLegColor()
        for lodName in self.toon.getLODNames():
            torso = self.toon.getPart('torso', lodName)
            if len(self.torso) == 1:
                parts = torso.findAllMatches('**/torso*')
                parts.setColor(armColor)
            for pieceName in ('arms', 'neck'):
                piece = torso.find('**/' + pieceName)
                piece.setColor(armColor)

            hands = torso.find('**/hands')
            hands.setColor(gloveColor)
            legs = self.toon.getPart('legs', lodName)
            for pieceName in ('legs', 'feet'):
                piece = legs.find('**/%s;+s' % pieceName)
                piece.setColor(legColor)

    def generateToonHead(self, copy, lods):
        headStyle = self.head
        fix = None
        if headStyle == 'dls':
            filePrefix = HeadDict['dls']
            headHeight = 0.75
        elif headStyle == 'dss':
            filePrefix = HeadDict['dss']
            headHeight = 0.5
        elif headStyle == 'dsl':
            filePrefix = HeadDict['dsl']
            headHeight = 0.5
        elif headStyle == 'dll':
            filePrefix = HeadDict['dll']
            headHeight = 0.75
        elif headStyle == 'cls':
            filePrefix = HeadDict['c']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'css':
            filePrefix = HeadDict['c']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'csl':
            filePrefix = HeadDict['c']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'cll':
            filePrefix = HeadDict['c']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == 'hls':
            filePrefix = HeadDict['h']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'hss':
            filePrefix = HeadDict['h']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'hsl':
            filePrefix = HeadDict['h']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'hll':
            filePrefix = HeadDict['h']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == 'mls':
            filePrefix = HeadDict['m']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'mss':
            filePrefix = HeadDict['m']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'rls':
            filePrefix = HeadDict['r']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'rss':
            filePrefix = HeadDict['r']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'rsl':
            filePrefix = HeadDict['r']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'rll':
            filePrefix = HeadDict['r']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == 'fls':
            filePrefix = HeadDict['f']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'fss':
            filePrefix = HeadDict['f']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'fsl':
            filePrefix = HeadDict['f']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'fll':
            filePrefix = HeadDict['f']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == 'pls':
            filePrefix = HeadDict['p']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'pss':
            filePrefix = HeadDict['p']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'psl':
            filePrefix = HeadDict['p']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'pll':
            filePrefix = HeadDict['p']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == 'bls':
            filePrefix = HeadDict['b']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'bss':
            filePrefix = HeadDict['b']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'bsl':
            filePrefix = HeadDict['b']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'bll':
            filePrefix = HeadDict['b']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == 'sls':
            filePrefix = HeadDict['s']
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == 'sss':
            filePrefix = HeadDict['s']
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == 'ssl':
            filePrefix = HeadDict['s']
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == 'sll':
            filePrefix = HeadDict['s']
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        else:
            ToonHead.notify.error('unknown head style: %s' % headStyle)
        if len(lods) == 1:
            self.toon.loadModel(filePrefix + lods[0], 'head', 'lodRoot', copy)
            if not copy:
                self.toon.showAllParts('head')
            if fix != None:
                fix(None, copy)
            self.__lods = lods
            self.__headStyle = headStyle
            self.__copy = copy
        else:
            for lod in lods:
                self.toon.loadModel(filePrefix + lod, 'head', lod, copy)
                if not copy:
                    self.toon.showAllParts('head', lod)
                if fix != None:
                    fix(lod, copy)
                self.__lods = lods
                self.__headStyle = headStyle
                self.__copy = copy

        # self.setupEyelashes()
        self.setupMuzzles()
        return headHeight

    def setupMuzzles(self):
        self.__muzzles = []
        self.__surpriseMuzzles = []
        self.__angryMuzzles = []
        self.__sadMuzzles = []
        self.__smileMuzzles = []
        self.__laughMuzzles = []

        def hideAddNonEmptyItemToList(item, list):
            if not item.isEmpty():
                item.hide()
                list.append(item)

        def hideNonEmptyItem(item):
            if not item.isEmpty():
                item.hide()

        if self.toon.hasLOD():
            for lodName in self.toon.getLODNames():
                animal = self.getAnimal()
                if animal != 'dog':
                    muzzle = self.toon.find('**/' + lodName +
                                            '/**/muzzle*neutral')
                else:
                    muzzle = self.toon.find('**/' + lodName + '/**/muzzle*')
                    if lodName == '1000' or lodName == '500':
                        filePrefix = DogMuzzleDict[self.head]
                        muzzles = self.toon.loadModel(filePrefix + lodName)
                        if base.config.GetBool('want-new-anims', 1):
                            if not self.toon.find(
                                    '**/' + lodName +
                                    '/**/__Actor_head/def_head').isEmpty():
                                muzzles.reparentTo(
                                    self.toon.find(
                                        '**/' + lodName +
                                        '/**/__Actor_head/def_head'))
                            else:
                                muzzles.reparentTo(
                                    self.toon.find('**/' + lodName +
                                                   '/**/joint_toHead'))
                        elif self.toon.find('**/' + lodName +
                                            '/**/joint_toHead'):
                            muzzles.reparentTo(
                                self.toon.find('**/' + lodName +
                                               '/**/joint_toHead'))
                surpriseMuzzle = self.toon.find('**/' + lodName +
                                                '/**/muzzle*surprise')
                angryMuzzle = self.toon.find('**/' + lodName +
                                             '/**/muzzle*angry')
                sadMuzzle = self.toon.find('**/' + lodName + '/**/muzzle*sad')
                smileMuzzle = self.toon.find('**/' + lodName +
                                             '/**/muzzle*smile')
                laughMuzzle = self.toon.find('**/' + lodName +
                                             '/**/muzzle*laugh')
                self.__muzzles.append(muzzle)
                hideAddNonEmptyItemToList(surpriseMuzzle,
                                          self.__surpriseMuzzles)
                hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles)
                hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles)
                hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles)
                hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles)

    def setupEyelashes(self):
        animal = self.head[0]
        model = self.toon.loadModel(EyelashDict[animal])
        if self.toon.hasLOD():
            head = self.toon.getPart('head', '1000')
        else:
            head = self.toon.getPart('head', 'lodRoot')
        length = self.head[1]
        if length == 'l':
            openString = 'open-long'
            closedString = 'closed-long'
        else:
            openString = 'open-short'
            closedString = 'closed-short'
        self.__eyelashOpen = model.find('**/' + openString).copyTo(head)
        self.__eyelashClosed = model.find('**/' + closedString).copyTo(head)
        model.removeNode()
        return

    def parentToonParts(self):
        if self.toon.hasLOD():
            for lodName in self.toon.getLODNames():
                if base.config.GetBool('want-new-anims', 1):
                    if not self.toon.getPart(
                            'torso', lodName).find('**/def_head').isEmpty():
                        self.toon.attach('head', 'torso', 'def_head', lodName)
                    else:
                        self.toon.attach('head', 'torso', 'joint_head',
                                         lodName)
                else:
                    self.toon.attach('head', 'torso', 'joint_head', lodName)
                self.toon.attach('torso', 'legs', 'joint_hips', lodName)
        else:
            self.toon.attach('head', 'torso', 'joint_head')
            self.toon.attach('torso', 'legs', 'joint_hips')

    def __fixHeadLongLong(self, lodName=None, copy=1):
        if lodName == None:
            searchRoot = self.toon
        else:
            searchRoot = self.toon.find('**/' + str(lodName))
        otherParts = searchRoot.findAllMatches('**/*short*')
        for partNum in xrange(0, otherParts.getNumPaths()):
            if copy:
                otherParts.getPath(partNum).removeNode()
            else:
                otherParts.getPath(partNum).stash()

        return

    def __fixHeadLongShort(self, lodName=None, copy=1):
        animalType = self.getAnimal()
        headStyle = self.head
        if lodName == None:
            searchRoot = self.toon
        else:
            searchRoot = self.toon.find('**/' + str(lodName))
        if animalType != 'duck' and animalType != 'horse':
            if animalType == 'rabbit':
                if copy:
                    searchRoot.find('**/ears-long').removeNode()
                else:
                    searchRoot.find('**/ears-long').hide()
            elif copy:
                searchRoot.find('**/ears-short').removeNode()
            else:
                searchRoot.find('**/ears-short').hide()
        if animalType != 'rabbit':
            if copy:
                searchRoot.find('**/eyes-short').removeNode()
            else:
                searchRoot.find('**/eyes-short').hide()
        if animalType != 'dog':
            if copy:
                searchRoot.find('**/joint_pupilL_short').removeNode()
                searchRoot.find('**/joint_pupilR_short').removeNode()
            else:
                searchRoot.find('**/joint_pupilL_short').stash()
                searchRoot.find('**/joint_pupilR_short').stash()
        if animalType != 'rabbit':
            muzzleParts = searchRoot.findAllMatches('**/muzzle-long*')
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        else:
            muzzleParts = searchRoot.findAllMatches('**/muzzle-short*')
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        return

    def __fixHeadShortLong(self, lodName=None, copy=1):
        animalType = self.getAnimal()
        headStyle = self.head
        if lodName == None:
            searchRoot = self.toon
        else:
            searchRoot = self.toon.find('**/' + str(lodName))
        if animalType != 'duck' and animalType != 'horse':
            if animalType == 'rabbit':
                if copy:
                    searchRoot.find('**/ears-short').removeNode()
                else:
                    searchRoot.find('**/ears-short').hide()
            elif copy:
                searchRoot.find('**/ears-long').removeNode()
            else:
                searchRoot.find('**/ears-long').hide()
        if animalType != 'rabbit':
            if copy:
                searchRoot.find('**/eyes-long').removeNode()
            else:
                searchRoot.find('**/eyes-long').hide()
        if animalType != 'dog':
            if copy:
                searchRoot.find('**/joint_pupilL_long').removeNode()
                searchRoot.find('**/joint_pupilR_long').removeNode()
            else:
                searchRoot.find('**/joint_pupilL_long').stash()
                searchRoot.find('**/joint_pupilR_long').stash()
        if copy:
            searchRoot.find('**/head-long').removeNode()
            searchRoot.find('**/head-front-long').removeNode()
        else:
            searchRoot.find('**/head-long').hide()
            searchRoot.find('**/head-front-long').hide()
        if animalType != 'rabbit':
            muzzleParts = searchRoot.findAllMatches('**/muzzle-short*')
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        else:
            muzzleParts = searchRoot.findAllMatches('**/muzzle-long*')
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        return

    def __fixHeadShortShort(self, lodName=None, copy=1):
        if lodName == None:
            searchRoot = self
        else:
            searchRoot = self.toon.find('**/' + str(lodName))
        otherParts = searchRoot.findAllMatches('**/*long*')
        for partNum in xrange(0, otherParts.getNumPaths()):
            if copy:
                otherParts.getPath(partNum).removeNode()
            else:
                otherParts.getPath(partNum).stash()

        return

    def setLODs(self):
        self.toon.setLODNode()
        levelOneIn = base.config.GetInt('lod1-in', 20)
        levelOneOut = base.config.GetInt('lod1-out', 0)
        levelTwoIn = base.config.GetInt('lod2-in', 80)
        levelTwoOut = base.config.GetInt('lod2-out', 20)
        levelThreeIn = base.config.GetInt('lod3-in', 280)
        levelThreeOut = base.config.GetInt('lod3-out', 80)
        self.toon.addLOD(1000, levelOneIn, levelOneOut)
        self.toon.addLOD(500, levelTwoIn, levelTwoOut)
        self.toon.addLOD(250, levelThreeIn, levelThreeOut)

    def loadPhaseAnims(self, phaseStr='phase_3', loadFlag=1):
        if phaseStr == 'phase_3':
            animList = Phase3AnimList
        elif phaseStr == 'phase_3.5':
            animList = Phase3_5AnimList
        elif phaseStr == 'phase_4':
            animList = Phase4AnimList
        elif phaseStr == 'phase_5':
            animList = Phase5AnimList
        elif phaseStr == 'phase_5.5':
            animList = Phase5_5AnimList
        elif phaseStr == 'phase_6':
            animList = Phase6AnimList
        elif phaseStr == 'phase_9':
            animList = Phase9AnimList
        elif phaseStr == 'phase_10':
            animList = Phase10AnimList
        elif phaseStr == 'phase_12':
            animList = Phase12AnimList
        else:
            self.notify.error('Unknown phase string %s' % phaseStr)
        for key in LegDict.keys():
            for anim in animList:
                if loadFlag:
                    pass
                elif anim[0] in LegsAnimDict[key]:
                    if self.legs == key:
                        self.toon.unloadAnims([anim[0]], 'legs', None)

        for key in TorsoDict.keys():
            for anim in animList:
                if loadFlag:
                    pass
                elif anim[0] in TorsoAnimDict[key]:
                    if self.torso == key:
                        self.toon.unloadAnims([anim[0]], 'torso', None)

        for key in HeadDict.keys():
            if key.find('d') >= 0:
                for anim in animList:
                    if loadFlag:
                        pass
                    elif anim[0] in HeadAnimDict[key]:
                        if self.head == key:
                            self.toon.unloadAnims([anim[0]], 'head', None)

    def renderSnapshot(self):
        print 'Rendering Snapshot...'
        base.graphicsEngine.renderFrame()
        base.screenshot(namePrefix='snapshot-render',
                        defaultFilename=1,
                        source=None,
                        imageComment="")
class SnapshotRenderer:
    def __init__(self, dnaString):
        self.dnaString = dnaString
        loadModels()
        compileGlobalAnimList()
        self.makeFromNetString(dnaString)
        self.toon = Actor()
        self.generateToon()
        self.renderSnapshot()

    def makeFromNetString(self, string):
        dg = PyDatagram(string)
        dgi = PyDatagramIterator(dg)
        self.type = dgi.getFixedString(1)
        if self.type == "t":
            headIndex = dgi.getUint8()
            torsoIndex = dgi.getUint8()
            legsIndex = dgi.getUint8()
            self.head = toonHeadTypes[headIndex]
            self.torso = toonTorsoTypes[torsoIndex]
            self.legs = toonLegTypes[legsIndex]
            gender = dgi.getUint8()
            if gender == 1:
                self.gender = "m"
            else:
                self.gender = "f"
            self.topTex = dgi.getUint8()
            self.topTexColor = dgi.getUint8()
            self.sleeveTex = dgi.getUint8()
            self.sleeveTexColor = dgi.getUint8()
            self.botTex = dgi.getUint8()
            self.botTexColor = dgi.getUint8()
            self.armColor = dgi.getUint8()
            self.gloveColor = dgi.getUint8()
            self.legColor = dgi.getUint8()
            self.headColor = dgi.getUint8()
        else:
            notify.error("unknown avatar type: ", self.type)

    def getAnimal(self):
        if self.head[0] == "d":
            return "dog"
        elif self.head[0] == "c":
            return "cat"
        elif self.head[0] == "m":
            return "mouse"
        elif self.head[0] == "h":
            return "horse"
        elif self.head[0] == "r":
            return "rabbit"
        elif self.head[0] == "f":
            return "duck"
        elif self.head[0] == "p":
            return "monkey"
        elif self.head[0] == "b":
            return "bear"
        elif self.head[0] == "s":
            return "pig"
        else:
            notify.error("unknown headStyle: ", self.head[0])

    def getArmColor(self):
        try:
            return allColorsList[self.armColor]
        except:
            return allColorsList[0]

    def getLegColor(self):
        try:
            return allColorsList[self.legColor]
        except:
            return allColorsList[0]

    def getHeadColor(self):
        try:
            return allColorsList[self.headColor]
        except:
            return allColorsList[0]

    def getGloveColor(self):
        try:
            return allColorsList[self.gloveColor]
        except:
            return allColorsList[0]

    def getGender(self):
        return self.gender

    def generateToon(self):
        self.setLODs()
        self.generateToonLegs()
        self.generateToonHead(1, ("1000", "500", "250"))
        self.generateToonTorso()
        self.generateToonColor()
        self.parentToonParts()
        # self.rescaleToon()
        # self.resetHeight()
        # self.setupToonNodes()
        self.toon.reparentTo(render)
        self.toon.setPos(0, 5, -3)
        self.toon.setH(180)
        self.toon.getPart("head", "1000").setR(10)
        self.toon.pose("neutral", 0)

    def generateToonLegs(self, copy=1):
        global Preloaded
        legStyle = self.legs
        filePrefix = LegDict.get(legStyle)
        if filePrefix is None:
            print ("unknown leg style: %s" % legStyle)
        self.toon.loadModel(Preloaded[filePrefix + "-1000"], "legs", "1000", True)
        self.toon.loadModel(Preloaded[filePrefix + "-500"], "legs", "500", True)
        self.toon.loadModel(Preloaded[filePrefix + "-250"], "legs", "250", True)
        if not copy:
            self.toon.showPart("legs", "1000")
            self.toon.showPart("legs", "500")
            self.toon.showPart("legs", "250")
        self.toon.loadAnims(LegsAnimDict[legStyle], "legs", "1000")
        self.toon.loadAnims(LegsAnimDict[legStyle], "legs", "500")
        self.toon.loadAnims(LegsAnimDict[legStyle], "legs", "250")
        self.toon.findAllMatches("**/boots_short").stash()
        self.toon.findAllMatches("**/boots_long").stash()
        self.toon.findAllMatches("**/shoes").stash()
        return

    def generateToonTorso(self, copy=1, genClothes=1):
        global Preloaded
        torsoStyle = self.torso
        filePrefix = TorsoDict.get(torsoStyle)
        if filePrefix is None:
            self.notify.error("unknown torso style: %s" % torsoStyle)
        self.toon.loadModel(Preloaded[filePrefix + "-1000"], "torso", "1000", True)
        if len(torsoStyle) == 1:
            self.toon.loadModel(Preloaded[filePrefix + "-1000"], "torso", "500", True)
            self.toon.loadModel(Preloaded[filePrefix + "-1000"], "torso", "250", True)
        else:
            self.toon.loadModel(Preloaded[filePrefix + "-500"], "torso", "500", True)
            self.toon.loadModel(Preloaded[filePrefix + "-250"], "torso", "250", True)
        if not copy:
            self.toon.showPart("torso", "1000")
            self.toon.showPart("torso", "500")
            self.toon.showPart("torso", "250")
        self.toon.loadAnims(TorsoAnimDict[torsoStyle], "torso", "1000")
        self.toon.loadAnims(TorsoAnimDict[torsoStyle], "torso", "500")
        self.toon.loadAnims(TorsoAnimDict[torsoStyle], "torso", "250")
        if genClothes == 1 and not len(torsoStyle) == 1:
            self.generateToonClothes()
        return

    def generateToonClothes(self, fromNet=0):
        swappedTorso = 0
        if self.toon.hasLOD():
            if self.getGender() == "f" and fromNet == 0:
                try:
                    bottomPair = GirlBottoms[self.botTex]
                except:
                    bottomPair = GirlBottoms[0]
            try:
                texName = Shirts[self.topTex]
            except:
                texName = Shirts[0]

            shirtTex = loader.loadTexture(texName, okMissing=True)
            if shirtTex is None:
                shirtTex = loader.loadTexture(Shirts[0])
            shirtTex.setMinfilter(Texture.FTLinearMipmapLinear)
            shirtTex.setMagfilter(Texture.FTLinear)
            try:
                shirtColor = ClothesColors[self.topTexColor]
            except:
                shirtColor = ClothesColors[0]

            try:
                texName = Sleeves[self.sleeveTex]
            except:
                texName = Sleeves[0]

            sleeveTex = loader.loadTexture(texName, okMissing=True)
            if sleeveTex is None:
                self.sendLogSuspiciousEvent("failed to load texture %s" % texName)
                sleeveTex = loader.loadTexture(Sleeves[0])
            sleeveTex.setMinfilter(Texture.FTLinearMipmapLinear)
            sleeveTex.setMagfilter(Texture.FTLinear)
            try:
                sleeveColor = ClothesColors[self.sleeveTexColor]
            except:
                sleeveColor = ClothesColors[0]

            if self.getGender() == "m":
                try:
                    texName = BoyShorts[self.botTex]
                except:
                    texName = BoyShorts[0]

            else:
                try:
                    texName = GirlBottoms[self.botTex][0]
                except:
                    texName = GirlBottoms[0][0]

            bottomTex = loader.loadTexture(texName, okMissing=True)
            if bottomTex is None:
                self.sendLogSuspiciousEvent("failed to load texture %s" % texName)
                if self.getGender() == "m":
                    bottomTex = loader.loadTexture(BoyShorts[0])
                else:
                    bottomTex = loader.loadTexture(GirlBottoms[0][0])
            bottomTex.setMinfilter(Texture.FTLinearMipmapLinear)
            bottomTex.setMagfilter(Texture.FTLinear)
            try:
                bottomColor = ClothesColors[self.botTexColor]
            except:
                bottomColor = ClothesColors[0]

            darkBottomColor = bottomColor * 0.5
            darkBottomColor.setW(1.0)
            for lodName in self.toon.getLODNames():
                thisPart = self.toon.getPart("torso", lodName)
                top = thisPart.find("**/torso-top")
                top.setTexture(shirtTex, 1)
                top.setColor(shirtColor)
                sleeves = thisPart.find("**/sleeves")
                sleeves.setTexture(sleeveTex, 1)
                sleeves.setColor(sleeveColor)
                bottoms = thisPart.findAllMatches("**/torso-bot")
                for bottomNum in xrange(0, bottoms.getNumPaths()):
                    bottom = bottoms.getPath(bottomNum)
                    bottom.setTexture(bottomTex, 1)
                    bottom.setColor(bottomColor)

                caps = thisPart.findAllMatches("**/torso-bot-cap")
                caps.setColor(darkBottomColor)

        return swappedTorso

    def generateToonColor(self):
        parts = self.toon.findAllMatches("**/head*")
        parts.setColor(self.getHeadColor())
        animalType = self.getAnimal()
        if (
            animalType == "cat"
            or animalType == "rabbit"
            or animalType == "bear"
            or animalType == "mouse"
            or animalType == "pig"
        ):
            parts = self.toon.findAllMatches("**/ear?-*")
            parts.setColor(self.getHeadColor())

        armColor = self.getArmColor()
        gloveColor = self.getGloveColor()
        legColor = self.getLegColor()
        for lodName in self.toon.getLODNames():
            torso = self.toon.getPart("torso", lodName)
            if len(self.torso) == 1:
                parts = torso.findAllMatches("**/torso*")
                parts.setColor(armColor)
            for pieceName in ("arms", "neck"):
                piece = torso.find("**/" + pieceName)
                piece.setColor(armColor)

            hands = torso.find("**/hands")
            hands.setColor(gloveColor)
            legs = self.toon.getPart("legs", lodName)
            for pieceName in ("legs", "feet"):
                piece = legs.find("**/%s;+s" % pieceName)
                piece.setColor(legColor)

    def generateToonHead(self, copy, lods):
        headStyle = self.head
        fix = None
        if headStyle == "dls":
            filePrefix = HeadDict["dls"]
            headHeight = 0.75
        elif headStyle == "dss":
            filePrefix = HeadDict["dss"]
            headHeight = 0.5
        elif headStyle == "dsl":
            filePrefix = HeadDict["dsl"]
            headHeight = 0.5
        elif headStyle == "dll":
            filePrefix = HeadDict["dll"]
            headHeight = 0.75
        elif headStyle == "cls":
            filePrefix = HeadDict["c"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "css":
            filePrefix = HeadDict["c"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "csl":
            filePrefix = HeadDict["c"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "cll":
            filePrefix = HeadDict["c"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == "hls":
            filePrefix = HeadDict["h"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "hss":
            filePrefix = HeadDict["h"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "hsl":
            filePrefix = HeadDict["h"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "hll":
            filePrefix = HeadDict["h"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == "mls":
            filePrefix = HeadDict["m"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "mss":
            filePrefix = HeadDict["m"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "rls":
            filePrefix = HeadDict["r"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "rss":
            filePrefix = HeadDict["r"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "rsl":
            filePrefix = HeadDict["r"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "rll":
            filePrefix = HeadDict["r"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == "fls":
            filePrefix = HeadDict["f"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "fss":
            filePrefix = HeadDict["f"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "fsl":
            filePrefix = HeadDict["f"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "fll":
            filePrefix = HeadDict["f"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == "pls":
            filePrefix = HeadDict["p"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "pss":
            filePrefix = HeadDict["p"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "psl":
            filePrefix = HeadDict["p"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "pll":
            filePrefix = HeadDict["p"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == "bls":
            filePrefix = HeadDict["b"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "bss":
            filePrefix = HeadDict["b"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "bsl":
            filePrefix = HeadDict["b"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "bll":
            filePrefix = HeadDict["b"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        elif headStyle == "sls":
            filePrefix = HeadDict["s"]
            fix = self.__fixHeadLongShort
            headHeight = 0.75
        elif headStyle == "sss":
            filePrefix = HeadDict["s"]
            fix = self.__fixHeadShortShort
            headHeight = 0.5
        elif headStyle == "ssl":
            filePrefix = HeadDict["s"]
            fix = self.__fixHeadShortLong
            headHeight = 0.5
        elif headStyle == "sll":
            filePrefix = HeadDict["s"]
            fix = self.__fixHeadLongLong
            headHeight = 0.75
        else:
            ToonHead.notify.error("unknown head style: %s" % headStyle)
        if len(lods) == 1:
            self.toon.loadModel(filePrefix + lods[0], "head", "lodRoot", copy)
            if not copy:
                self.toon.showAllParts("head")
            if fix != None:
                fix(None, copy)
            self.__lods = lods
            self.__headStyle = headStyle
            self.__copy = copy
        else:
            for lod in lods:
                self.toon.loadModel(filePrefix + lod, "head", lod, copy)
                if not copy:
                    self.toon.showAllParts("head", lod)
                if fix != None:
                    fix(lod, copy)
                self.__lods = lods
                self.__headStyle = headStyle
                self.__copy = copy

        # self.setupEyelashes()
        self.setupMuzzles()
        return headHeight

    def setupMuzzles(self):
        self.__muzzles = []
        self.__surpriseMuzzles = []
        self.__angryMuzzles = []
        self.__sadMuzzles = []
        self.__smileMuzzles = []
        self.__laughMuzzles = []

        def hideAddNonEmptyItemToList(item, list):
            if not item.isEmpty():
                item.hide()
                list.append(item)

        def hideNonEmptyItem(item):
            if not item.isEmpty():
                item.hide()

        if self.toon.hasLOD():
            for lodName in self.toon.getLODNames():
                animal = self.getAnimal()
                if animal != "dog":
                    muzzle = self.toon.find("**/" + lodName + "/**/muzzle*neutral")
                else:
                    muzzle = self.toon.find("**/" + lodName + "/**/muzzle*")
                    if lodName == "1000" or lodName == "500":
                        filePrefix = DogMuzzleDict[self.head]
                        muzzles = self.toon.loadModel(filePrefix + lodName)
                        if base.config.GetBool("want-new-anims", 1):
                            if not self.toon.find("**/" + lodName + "/**/__Actor_head/def_head").isEmpty():
                                muzzles.reparentTo(self.toon.find("**/" + lodName + "/**/__Actor_head/def_head"))
                            else:
                                muzzles.reparentTo(self.toon.find("**/" + lodName + "/**/joint_toHead"))
                        elif self.toon.find("**/" + lodName + "/**/joint_toHead"):
                            muzzles.reparentTo(self.toon.find("**/" + lodName + "/**/joint_toHead"))
                surpriseMuzzle = self.toon.find("**/" + lodName + "/**/muzzle*surprise")
                angryMuzzle = self.toon.find("**/" + lodName + "/**/muzzle*angry")
                sadMuzzle = self.toon.find("**/" + lodName + "/**/muzzle*sad")
                smileMuzzle = self.toon.find("**/" + lodName + "/**/muzzle*smile")
                laughMuzzle = self.toon.find("**/" + lodName + "/**/muzzle*laugh")
                self.__muzzles.append(muzzle)
                hideAddNonEmptyItemToList(surpriseMuzzle, self.__surpriseMuzzles)
                hideAddNonEmptyItemToList(angryMuzzle, self.__angryMuzzles)
                hideAddNonEmptyItemToList(sadMuzzle, self.__sadMuzzles)
                hideAddNonEmptyItemToList(smileMuzzle, self.__smileMuzzles)
                hideAddNonEmptyItemToList(laughMuzzle, self.__laughMuzzles)

    def setupEyelashes(self):
        animal = self.head[0]
        model = self.toon.loadModel(EyelashDict[animal])
        if self.toon.hasLOD():
            head = self.toon.getPart("head", "1000")
        else:
            head = self.toon.getPart("head", "lodRoot")
        length = self.head[1]
        if length == "l":
            openString = "open-long"
            closedString = "closed-long"
        else:
            openString = "open-short"
            closedString = "closed-short"
        self.__eyelashOpen = model.find("**/" + openString).copyTo(head)
        self.__eyelashClosed = model.find("**/" + closedString).copyTo(head)
        model.removeNode()
        return

    def parentToonParts(self):
        if self.toon.hasLOD():
            for lodName in self.toon.getLODNames():
                if base.config.GetBool("want-new-anims", 1):
                    if not self.toon.getPart("torso", lodName).find("**/def_head").isEmpty():
                        self.toon.attach("head", "torso", "def_head", lodName)
                    else:
                        self.toon.attach("head", "torso", "joint_head", lodName)
                else:
                    self.toon.attach("head", "torso", "joint_head", lodName)
                self.toon.attach("torso", "legs", "joint_hips", lodName)
        else:
            self.toon.attach("head", "torso", "joint_head")
            self.toon.attach("torso", "legs", "joint_hips")

    def __fixHeadLongLong(self, lodName=None, copy=1):
        if lodName == None:
            searchRoot = self.toon
        else:
            searchRoot = self.toon.find("**/" + str(lodName))
        otherParts = searchRoot.findAllMatches("**/*short*")
        for partNum in xrange(0, otherParts.getNumPaths()):
            if copy:
                otherParts.getPath(partNum).removeNode()
            else:
                otherParts.getPath(partNum).stash()

        return

    def __fixHeadLongShort(self, lodName=None, copy=1):
        animalType = self.getAnimal()
        headStyle = self.head
        if lodName == None:
            searchRoot = self.toon
        else:
            searchRoot = self.toon.find("**/" + str(lodName))
        if animalType != "duck" and animalType != "horse":
            if animalType == "rabbit":
                if copy:
                    searchRoot.find("**/ears-long").removeNode()
                else:
                    searchRoot.find("**/ears-long").hide()
            elif copy:
                searchRoot.find("**/ears-short").removeNode()
            else:
                searchRoot.find("**/ears-short").hide()
        if animalType != "rabbit":
            if copy:
                searchRoot.find("**/eyes-short").removeNode()
            else:
                searchRoot.find("**/eyes-short").hide()
        if animalType != "dog":
            if copy:
                searchRoot.find("**/joint_pupilL_short").removeNode()
                searchRoot.find("**/joint_pupilR_short").removeNode()
            else:
                searchRoot.find("**/joint_pupilL_short").stash()
                searchRoot.find("**/joint_pupilR_short").stash()
        if animalType != "rabbit":
            muzzleParts = searchRoot.findAllMatches("**/muzzle-long*")
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        else:
            muzzleParts = searchRoot.findAllMatches("**/muzzle-short*")
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        return

    def __fixHeadShortLong(self, lodName=None, copy=1):
        animalType = self.getAnimal()
        headStyle = self.head
        if lodName == None:
            searchRoot = self.toon
        else:
            searchRoot = self.toon.find("**/" + str(lodName))
        if animalType != "duck" and animalType != "horse":
            if animalType == "rabbit":
                if copy:
                    searchRoot.find("**/ears-short").removeNode()
                else:
                    searchRoot.find("**/ears-short").hide()
            elif copy:
                searchRoot.find("**/ears-long").removeNode()
            else:
                searchRoot.find("**/ears-long").hide()
        if animalType != "rabbit":
            if copy:
                searchRoot.find("**/eyes-long").removeNode()
            else:
                searchRoot.find("**/eyes-long").hide()
        if animalType != "dog":
            if copy:
                searchRoot.find("**/joint_pupilL_long").removeNode()
                searchRoot.find("**/joint_pupilR_long").removeNode()
            else:
                searchRoot.find("**/joint_pupilL_long").stash()
                searchRoot.find("**/joint_pupilR_long").stash()
        if copy:
            searchRoot.find("**/head-long").removeNode()
            searchRoot.find("**/head-front-long").removeNode()
        else:
            searchRoot.find("**/head-long").hide()
            searchRoot.find("**/head-front-long").hide()
        if animalType != "rabbit":
            muzzleParts = searchRoot.findAllMatches("**/muzzle-short*")
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        else:
            muzzleParts = searchRoot.findAllMatches("**/muzzle-long*")
            for partNum in xrange(0, muzzleParts.getNumPaths()):
                if copy:
                    muzzleParts.getPath(partNum).removeNode()
                else:
                    muzzleParts.getPath(partNum).hide()

        return

    def __fixHeadShortShort(self, lodName=None, copy=1):
        if lodName == None:
            searchRoot = self
        else:
            searchRoot = self.toon.find("**/" + str(lodName))
        otherParts = searchRoot.findAllMatches("**/*long*")
        for partNum in xrange(0, otherParts.getNumPaths()):
            if copy:
                otherParts.getPath(partNum).removeNode()
            else:
                otherParts.getPath(partNum).stash()

        return

    def setLODs(self):
        self.toon.setLODNode()
        levelOneIn = base.config.GetInt("lod1-in", 20)
        levelOneOut = base.config.GetInt("lod1-out", 0)
        levelTwoIn = base.config.GetInt("lod2-in", 80)
        levelTwoOut = base.config.GetInt("lod2-out", 20)
        levelThreeIn = base.config.GetInt("lod3-in", 280)
        levelThreeOut = base.config.GetInt("lod3-out", 80)
        self.toon.addLOD(1000, levelOneIn, levelOneOut)
        self.toon.addLOD(500, levelTwoIn, levelTwoOut)
        self.toon.addLOD(250, levelThreeIn, levelThreeOut)

    def loadPhaseAnims(self, phaseStr="phase_3", loadFlag=1):
        if phaseStr == "phase_3":
            animList = Phase3AnimList
        elif phaseStr == "phase_3.5":
            animList = Phase3_5AnimList
        elif phaseStr == "phase_4":
            animList = Phase4AnimList
        elif phaseStr == "phase_5":
            animList = Phase5AnimList
        elif phaseStr == "phase_5.5":
            animList = Phase5_5AnimList
        elif phaseStr == "phase_6":
            animList = Phase6AnimList
        elif phaseStr == "phase_9":
            animList = Phase9AnimList
        elif phaseStr == "phase_10":
            animList = Phase10AnimList
        elif phaseStr == "phase_12":
            animList = Phase12AnimList
        else:
            self.notify.error("Unknown phase string %s" % phaseStr)
        for key in LegDict.keys():
            for anim in animList:
                if loadFlag:
                    pass
                elif anim[0] in LegsAnimDict[key]:
                    if self.legs == key:
                        self.toon.unloadAnims([anim[0]], "legs", None)

        for key in TorsoDict.keys():
            for anim in animList:
                if loadFlag:
                    pass
                elif anim[0] in TorsoAnimDict[key]:
                    if self.torso == key:
                        self.toon.unloadAnims([anim[0]], "torso", None)

        for key in HeadDict.keys():
            if key.find("d") >= 0:
                for anim in animList:
                    if loadFlag:
                        pass
                    elif anim[0] in HeadAnimDict[key]:
                        if self.head == key:
                            self.toon.unloadAnims([anim[0]], "head", None)

    def renderSnapshot(self):
        print "Rendering Snapshot..."
        base.graphicsEngine.renderFrame()
        base.screenshot(namePrefix="snapshot-render", defaultFilename=1, source=None, imageComment="")
Beispiel #12
0
duckLegs = loader.loadModel(
    'phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
otherParts = duckLegs.findAllMatches('**/boots*') + duckLegs.findAllMatches(
    '**/shoes')
for partNum in range(0, otherParts.getNumPaths()):
    otherParts.getPath(partNum).removeNode()

duckBody = Actor({
    'head': duckHead,
    'torso': duckTorso,
    'legs': duckLegs
}, {
    'torso': torsoAnimDict,
    'legs': legsAnimDict
})
duckBody.attach('head', 'torso', 'def_head')
duckBody.attach('torso', 'legs', 'joint_hips')

gloves = duckBody.findAllMatches('**/hands')
ears = duckBody.findAllMatches('**/*ears*')
head = duckBody.findAllMatches('**/head-*')
sleeves = duckBody.findAllMatches('**/sleeves')
shirt = duckBody.findAllMatches('**/torso-top')
shorts = duckBody.findAllMatches('**/torso-bot')
neck = duckBody.findAllMatches('**/neck')
arms = duckBody.findAllMatches('**/arms')
legs = duckBody.findAllMatches('**/legs')
feet = duckBody.findAllMatches('**/feet')

bodyNodes = []
bodyNodes += [gloves]
Beispiel #13
0
class Main(ShowBase, object):
    def __init__(self):
        super(Main, self).__init__()

        self.load_ttc()

        self.key_map = {'forward': 0, 'backward': 0, 'left': 0, 'right': 0}

        self.player_legs = Actor("phase_3/models/char/tt_a_chr_dgs_shorts_legs_250.bam")
        self.player_torso = Actor("phase_3/models/char/tt_a_chr_dgs_shorts_torso_250.bam")
        self.player_head = Actor("phase_3/models/char/tt_a_chr_dgs_shorts_head_250.bam")

        legs = 'legs'
        torso = 'torso'
        head = 'head'
        self.neutral = 'neutral'
        self.running = 'running'
        self.walk = 'walk'

        parts = {legs: self.player_legs, torso: self.player_torso, head: self.player_head}

        animations = {legs: {self.neutral: "phase_3/models/char/tt_a_chr_dgs_shorts_legs_neutral.bam",
                             self.running: "phase_3/models/char/tt_a_chr_dgs_shorts_legs_run.bam",
                             self.walk: "phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_walk.bam"},
                      torso: {self.neutral: "phase_3/models/char/tt_a_chr_dgs_shorts_torso_neutral.bam",
                              self.running: "phase_3/models/char/tt_a_chr_dgs_shorts_torso_run.bam"},
                      head: {self.neutral: "phase_3/models/char/tt_a_chr_dgs_shorts_head_neutral.bam",
                             self.running: "phase_3/models/char/tt_a_chr_dgs_shorts_head_run.bam"}}

        self.player_body = Actor(parts, animations)

        self.player_body.listJoints(head)
        # Attach our torso and legs to our model's hips.
        self.player_body.attach(torso, legs, 'joint_hips')
        # Attach the head and torso to the model's neck.
        self.player_body.attach(head, torso, 'def_head')
        self.player_body.setPos(0, 0, 5)
        self.player_body.reparentTo(self.render)
        self.player_body.loop(self.neutral)

        self.cog_head = Actor("phase_9/models/char/sellbotBoss-head-zero.bam")
        self.cog_torso = Actor("phase_9/models/char/sellbotBoss-torso-zero.bam")

        cog_torso = 'torso'
        cog_head = 'head'
        cog_neutral = 'neutral'
        self.cog_body = Actor({cog_torso: self.cog_torso, cog_head: self.cog_head},
                              {cog_torso: {cog_neutral: "phase_9/models/char/bossCog-torso-Ff_speech.bam"},
                               cog_head: {cog_neutral: "phase_9/models/char/bossCog-head-Ff_speech.bam"}})

        self.cog_body.listJoints(cog_torso)
        self.cog_body.attach(cog_torso, cog_head, 'joint9_9')
        self.cog_body.setPos(-20, 4, 3)
        self.cog_body.reparentTo(self.render)
        self.cog_body.loop(cog_neutral)

        self.disableMouse()
        # self.create_new_task(self.camera_mover, "Camera mover")
        # self.create_new_task(self.toon_mover, "Toon mover")
        # self.taskMgr.doMethodLater(5, self.toon_mover, 'Toon mover delayed')
        # self.create_new_task(self.sound_stopper, "Sound stopper")

        self.accept('w', self.set_key, ["forward", True])
        self.accept('s', self.set_key, ["backward", True])
        self.accept('a', self.set_key, ["left", True])
        self.accept('d', self.set_key, ["right", True])
        self.accept("w-up", self.set_key, ["forward", False])
        self.accept("s-up", self.set_key, ["backward", False])
        self.accept("a-up", self.set_key, ["left", False])
        self.accept("d-up", self.set_key, ["right", False])

        self.hadle_collisions()

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

        # self.accept("a", self.setKey, ["cam-left", True])

        self.is_moving = False

        self.load_and_play_music()

    def create_new_task(self, function_name, name):
        self.taskMgr.add(function_name, name)

    def load_ttc(self):
        self.toontown_central = self.loader.loadModel("phase_4/models/neighborhoods/toontown_central_full.bam")
        self.toontown_central.reparentTo(self.render)

        self.sky = self.loader.loadModel("phase_12/models/bossbotHQ/ttr_m_bossbothq_sky.bam")
        self.sky.reparentTo(self.render)

    def load_and_play_music(self):
        sound1 = self.loader.loadSfx('phase_7/audio/bgm/tt_elevator.ogg')
        sound2 = self.loader.loadSfx('phase_9/audio/bgm/CHQ_FACT_bg.ogg')
        sound3 = self.loader.loadSfx('phase_8/audio/bgm/TB_SZ.ogg')
        sound4 = self.loader.loadSfx('phase_6/audio/bgm/MM_SZ.ogg')
        sound5 = self.loader.loadSfx('phase_13/audio/bgm/party_generic_theme_jazzy.ogg')

        self.music_sequence = Sequence(SoundInterval(sound1), SoundInterval(sound2), SoundInterval(sound3),
                                       SoundInterval(sound4), SoundInterval(sound5), name='Sound Sequence')
        self.music_sequence.loop()

    def camera_mover(self, task):
        angle_radians = (task.time * 50) * (pi / 180)
        self.camera.setPos(0, 0, float(20 * sin(angle_radians) + 5))
        return Task.cont

    def toon_mover(self, task):
        speed = 50
        angle_radians = (task.time * speed) * (pi / 180)

        x = float(200 * cos(5 * angle_radians)) + 8
        y = 0
        z = float(200 * sin(5 * angle_radians)) + 60

        self.player_body.setPos(x, y, z)
        return Task.cont

    def sound_stopper(self, task):
        if self.music_sequence.isPlaying():
            self.music_sequence.finish()
            return Task.done
        else:
            return Task.cont

    # Records keyboard input.
    def set_key(self, key , value):
        self.key_map[key] = value

    def toon_move(self, task):
        # save toons's initial position so that we can restore it,
        # in case he falls off the map or runs into something.
        startpos = self.player_body.getPos()

        # Here, we are setting our camera to follow the player from behind.
        self.camera.setPos(self.player_body.getX(), self.player_body.getY() - 10, 10)
        self.camera.setHpr(0, -15, self.player_body.getR())
        # self.camera.lookAt(self.player_body)

        # This constant will make our player run in a desirable pace.
        dt = .25

        if self.key_map["left"]:
            self.player_body.setH(self.player_body.getH() + 10 * dt)
            print 'left'

        if self.key_map["right"]:
            self.player_body.setH(self.player_body.getH() - 10 * dt)
            print 'right'

        if self.key_map["forward"]:
            self.player_body.setY(self.player_body, 2 * dt)
            print 'forward'

        if self.key_map["backward"]:
            self.player_body.setY(self.player_body, -2 * .1)
            print 'backward'

        if self.key_map["forward"] or self.key_map["left"] or self.key_map["right"]:
            if self.is_moving is False:
                self.player_body.stop()
                self.player_body.loop(self.running)
                print 'moving!'
                self.is_moving = True

        elif self.key_map["backward"]:
            if self.is_moving is False:
                self.player_body.stop()
                self.player_body.loop(self.walk)
                print 'moving -- backwards!'
                self.is_moving = True
        else:
            if self.is_moving:
                self.player_body.stop()
                self.player_body.loop(self.neutral)
                print "neutral!"
                self.is_moving = False

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

        if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain":
            self.player_body.setZ(entries[0].getSurfacePoint(self.render).getZ())
        else:
            pass
        return task.cont

    def hadle_collisions(self):
        self.cTrav = CollisionTraverser()
        self.player_ground_ray = CollisionRay()
        self.player_ground_ray.setOrigin(0, 0, 9)
        self.player_ground_ray.setDirection(0, 0, -1)
        self.player_ground_collider = CollisionNode('PlayerRay')
        self.player_ground_collider.addSolid(self.player_ground_ray)
        self.player_ground_collider.setFromCollideMask(CollideMask.bit(0))
        self.player_ground_collider.setIntoCollideMask(CollideMask.allOff())
        self.player_ground_collision_handle = self.player_body.attachNewNode(self.player_ground_collider)
        self.player_ground_handler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.player_ground_collision_handle, self.player_ground_handler)

        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)
Beispiel #14
0
    otherParts.getPath(partNum).removeNode()
ntrlMuzzle = duckHead.find('**/*muzzle*neutral')
otherParts = duckHead.findAllMatches('**/*muzzle*')
for partNum in range(0, otherParts.getNumPaths()):
    part = otherParts.getPath(partNum)
    if part != ntrlMuzzle:
        otherParts.getPath(partNum).removeNode()
duckTorso = loader.loadModel('phase_3/models/char/tt_a_chr_dgl_shorts_torso_1000.bam')
duckLegs  = loader.loadModel('phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
otherParts = duckLegs.findAllMatches('**/boots*')+duckLegs.findAllMatches('**/shoes')
for partNum in range(0, otherParts.getNumPaths()):
    otherParts.getPath(partNum).removeNode()
 
duckBody = Actor({'head':duckHead, 'torso':duckTorso, 'legs':duckLegs},
                {'torso':torsoAnimDict, 'legs':legsAnimDict})
duckBody.attach('head', 'torso', 'def_head')
duckBody.attach('torso', 'legs', 'joint_hips')
 
gloves = duckBody.findAllMatches('**/hands')
ears = duckBody.findAllMatches('**/*ears*')
head = duckBody.findAllMatches('**/head-*')
sleeves = duckBody.findAllMatches('**/sleeves')
shirt = duckBody.findAllMatches('**/torso-top')
shorts = duckBody.findAllMatches('**/torso-bot')
neck = duckBody.findAllMatches('**/neck')
arms = duckBody.findAllMatches('**/arms')
legs = duckBody.findAllMatches('**/legs')
feet = duckBody.findAllMatches('**/feet')
 
bodyNodes = []
bodyNodes += [gloves]
Beispiel #15
0
DuckLegs = loader.loadModel(
    'phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
otherParts = DuckLegs.findAllMatches('**/boots*') + DuckLegs.findAllMatches(
    '**/shoes')
for partNum in range(0, otherParts.getNumPaths()):
    otherParts.getPath(partNum).removeNode()

DuckBody = Actor({
    'head': DuckHead,
    'torso': DuckTorso,
    'legs': DuckLegs
}, {
    'torso': torsoAnimDict,
    'legs': legsAnimDict
})
DuckBody.attach('head', 'torso', 'def_head')
DuckBody.attach('torso', 'legs', 'joint_hips')

gloves = DuckBody.findAllMatches('**/hands')
ears = DuckBody.findAllMatches('**/*ears*')
head = DuckBody.findAllMatches('**/head-*')
sleeves = DuckBody.findAllMatches('**/sleeves')
shirt = DuckBody.findAllMatches('**/torso-top')
shorts = DuckBody.findAllMatches('**/torso-bot')
neck = DuckBody.findAllMatches('**/neck')
arms = DuckBody.findAllMatches('**/arms')
legs = DuckBody.findAllMatches('**/legs')
feet = DuckBody.findAllMatches('**/feet')

bodyNodes = []
bodyNodes += [gloves]
Beispiel #16
0
class Toon:
    notify = DirectNotifyGlobal.directNotify.newCategory("Toon")
    def __init__(self):
        self.name = "Flippy"

        legsAnimDict = {'right-hand-start': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-hand-start.bam', 'firehose': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_firehose.bam', 'rotateL-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_rotateL-putt.bam', 'slip-forward': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_slip-forward.bam', 'catch-eatnrun': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_eatnrun.bam', 'tickle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_tickle.bam', 'water-gun': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_water-gun.bam', 'leverNeutral': 'phase_10/models/char/tt_a_chr_dgs_shorts_legs_leverNeutral.bam', 'swim': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_swim.bam', 'catch-run': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_gamerun.bam', 'sad-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_sad-neutral.bam', 'pet-loop': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_petloop.bam', 'jump-squat': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-zstart.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_wave.bam', 'reel-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_reelneutral.bam', 'pole-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_poleneutral.bam', 'bank': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_jellybeanJar.bam', 'scientistGame': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistGame.bam', 'right-hand': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-hand.bam', 'lookloop-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_lookloop-putt.bam', 'victory': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_victory-dance.bam', 'lose': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_lose.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_cringe.bam', 'right': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_right.bam', 'headdown-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_headdown-putt.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_conked.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump.bam', 'into-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_into-putt.bam', 'fish-end': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fishEND.bam', 'running-jump-land': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_leap_zend.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_shrug.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_sprinkle-dust.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_hold-bottle.bam', 'takePhone': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_takePhone.bam', 'melt': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_melt.bam', 'pet-start': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_petin.bam', 'look-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_look-putt.bam', 'loop-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_loop-putt.bam', 'good-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_good-putt.bam', 'juggle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_juggle.bam', 'run': 'phase_3/models/char/tt_a_chr_dgs_shorts_legs_run.bam', 'pushbutton': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_press-button.bam', 'sidestep-right': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-back-right.bam', 'water': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_water.bam', 'right-point-start': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-point-start.bam', 'bad-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_bad-putt.bam', 'struggle': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_struggle.bam', 'running-jump': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_running-jump.bam', 'callPet': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_callPet.bam', 'throw': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_pie-throw.bam', 'catch-eatneutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_eat_neutral.bam', 'tug-o-war': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_tug-o-war.bam', 'bow': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_bow.bam', 'swing': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_swing.bam', 'climb': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_climb.bam', 'scientistWork': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistWork.bam', 'think': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_think.bam', 'catch-intro-throw': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_gameThrow.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_walk.bam', 'down': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_down.bam', 'pole': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_pole.bam', 'periscope': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_periscope.bam', 'duck': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_duck.bam', 'curtsy': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_curtsy.bam', 'jump-land': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-zend.bam', 'loop-dig': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_loop_dig.bam', 'angry': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_angry.bam', 'bored': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_bored.bam', 'swing-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_swing-putt.bam', 'pet-end': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_petend.bam', 'spit': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_spit.bam', 'right-point': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_right-point.bam', 'start-dig': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_into_dig.bam', 'castlong': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_castlong.bam', 'confused': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_confused.bam', 'neutral': 'phase_3/models/char/tt_a_chr_dgs_shorts_legs_neutral.bam', 'jump-idle': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_jump-zhang.bam', 'reel': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_reel.bam', 'slip-backward': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_slip-backward.bam', 'sound': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_shout.bam', 'sidestep-left': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_sidestep-left.bam', 'up': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_up.bam', 'fish-again': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fishAGAIN.bam', 'cast': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_cast.bam', 'phoneBack': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_phoneBack.bam', 'phoneNeutral': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_phoneNeutral.bam', 'scientistJealous': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistJealous.bam', 'battlecast': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fish.bam', 'sit-start': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_intoSit.bam', 'toss': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_toss.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_happy-dance.bam', 'running-jump-squat': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_leap_zstart.bam', 'teleport': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_teleport.bam', 'sit': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_sit.bam', 'sad-walk': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_losewalk.bam', 'give-props-start': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_give-props-start.bam', 'book': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_book.bam', 'running-jump-idle': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_leap_zhang.bam', 'scientistEmcee': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_scientistEmcee.bam', 'leverPull': 'phase_10/models/char/tt_a_chr_dgs_shorts_legs_leverPull.bam', 'tutorial-neutral': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_tutorial-neutral.bam', 'badloop-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_badloop-putt.bam', 'give-props': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_give-props.bam', 'hold-magnet': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_hold-magnet.bam', 'hypnotize': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_hypnotize.bam', 'left-point': 'phase_3.5/models/char/tt_a_chr_dgs_shorts_legs_left-point.bam', 'leverReach': 'phase_10/models/char/tt_a_chr_dgs_shorts_legs_leverReach.bam', 'feedPet': 'phase_5.5/models/char/tt_a_chr_dgs_shorts_legs_feedPet.bam', 'reel-H': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_reelH.bam', 'applause': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_applause.bam', 'smooch': 'phase_5/models/char/tt_a_chr_dgs_shorts_legs_smooch.bam', 'rotateR-putt': 'phase_6/models/char/tt_a_chr_dgs_shorts_legs_rotateR-putt.bam', 'fish-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_fishneutral.bam', 'push': 'phase_9/models/char/tt_a_chr_dgs_shorts_legs_push.bam', 'catch-neutral': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_gameneutral.bam', 'left': 'phase_4/models/char/tt_a_chr_dgs_shorts_legs_left.bam'}
         
        torsoAnimDict = {'right-hand-start': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-hand-start.bam', 'firehose': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_firehose.bam', 'rotateL-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_rotateL-putt.bam', 'slip-forward': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_slip-forward.bam', 'catch-eatnrun': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_eatnrun.bam', 'tickle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_tickle.bam', 'water-gun': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_water-gun.bam', 'leverNeutral': 'phase_10/models/char/tt_a_chr_dgl_shorts_torso_leverNeutral.bam', 'swim': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_swim.bam', 'catch-run': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_gamerun.bam', 'sad-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_sad-neutral.bam', 'pet-loop': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_petloop.bam', 'jump-squat': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-zstart.bam', 'wave': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_wave.bam', 'reel-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_reelneutral.bam', 'pole-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_poleneutral.bam', 'bank': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_jellybeanJar.bam', 'scientistGame': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistGame.bam', 'right-hand': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-hand.bam', 'lookloop-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_lookloop-putt.bam', 'victory': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_victory-dance.bam', 'lose': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_lose.bam', 'cringe': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_cringe.bam', 'right': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_right.bam', 'headdown-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_headdown-putt.bam', 'conked': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_conked.bam', 'jump': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump.bam', 'into-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_into-putt.bam', 'fish-end': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fishEND.bam', 'running-jump-land': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_leap_zend.bam', 'shrug': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_shrug.bam', 'sprinkle-dust': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_sprinkle-dust.bam', 'hold-bottle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_hold-bottle.bam', 'takePhone': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_takePhone.bam', 'melt': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_melt.bam', 'pet-start': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_petin.bam', 'look-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_look-putt.bam', 'loop-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_loop-putt.bam', 'good-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_good-putt.bam', 'juggle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_juggle.bam', 'run': 'phase_3/models/char/tt_a_chr_dgl_shorts_torso_run.bam', 'pushbutton': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_press-button.bam', 'sidestep-right': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-back-right.bam', 'water': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_water.bam', 'right-point-start': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-point-start.bam', 'bad-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_bad-putt.bam', 'struggle': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_struggle.bam', 'running-jump': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_running-jump.bam', 'callPet': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_callPet.bam', 'throw': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_pie-throw.bam', 'catch-eatneutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_eat_neutral.bam', 'tug-o-war': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_tug-o-war.bam', 'bow': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_bow.bam', 'swing': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_swing.bam', 'climb': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_climb.bam', 'scientistWork': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistWork.bam', 'think': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_think.bam', 'catch-intro-throw': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_gameThrow.bam', 'walk': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_walk.bam', 'down': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_down.bam', 'pole': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_pole.bam', 'periscope': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_periscope.bam', 'duck': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_duck.bam', 'curtsy': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_curtsy.bam', 'jump-land': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-zend.bam', 'loop-dig': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_loop_dig.bam', 'angry': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_angry.bam', 'bored': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_bored.bam', 'swing-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_swing-putt.bam', 'pet-end': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_petend.bam', 'spit': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_spit.bam', 'right-point': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_right-point.bam', 'start-dig': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_into_dig.bam', 'castlong': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_castlong.bam', 'confused': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_confused.bam', 'neutral': 'phase_3/models/char/tt_a_chr_dgl_shorts_torso_neutral.bam', 'jump-idle': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_jump-zhang.bam', 'reel': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_reel.bam', 'slip-backward': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_slip-backward.bam', 'sound': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_shout.bam', 'sidestep-left': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_sidestep-left.bam', 'up': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_up.bam', 'fish-again': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fishAGAIN.bam', 'cast': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_cast.bam', 'phoneBack': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_phoneBack.bam', 'phoneNeutral': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_phoneNeutral.bam', 'scientistJealous': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistJealous.bam', 'battlecast': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fish.bam', 'sit-start': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_intoSit.bam', 'toss': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_toss.bam', 'happy-dance': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_happy-dance.bam', 'running-jump-squat': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_leap_zstart.bam', 'teleport': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_teleport.bam', 'sit': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_sit.bam', 'sad-walk': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_losewalk.bam', 'give-props-start': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_give-props-start.bam', 'book': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_book.bam', 'running-jump-idle': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_leap_zhang.bam', 'scientistEmcee': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_scientistEmcee.bam', 'leverPull': 'phase_10/models/char/tt_a_chr_dgl_shorts_torso_leverPull.bam', 'tutorial-neutral': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_tutorial-neutral.bam', 'badloop-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_badloop-putt.bam', 'give-props': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_give-props.bam', 'hold-magnet': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_hold-magnet.bam', 'hypnotize': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_hypnotize.bam', 'left-point': 'phase_3.5/models/char/tt_a_chr_dgl_shorts_torso_left-point.bam', 'leverReach': 'phase_10/models/char/tt_a_chr_dgl_shorts_torso_leverReach.bam', 'feedPet': 'phase_5.5/models/char/tt_a_chr_dgl_shorts_torso_feedPet.bam', 'reel-H': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_reelH.bam', 'applause': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_applause.bam', 'smooch': 'phase_5/models/char/tt_a_chr_dgl_shorts_torso_smooch.bam', 'rotateR-putt': 'phase_6/models/char/tt_a_chr_dgl_shorts_torso_rotateR-putt.bam', 'fish-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_fishneutral.bam', 'push': 'phase_9/models/char/tt_a_chr_dgl_shorts_torso_push.bam', 'catch-neutral': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_gameneutral.bam', 'left': 'phase_4/models/char/tt_a_chr_dgl_shorts_torso_left.bam'}
         
        self.toonHead = loader.loadModel('phase_3/models/char/horse-heads-1000.bam')
        otherParts = self.toonHead.findAllMatches('**/*long*')
        for partNum in range(0, otherParts.getNumPaths()):
            if not 'muzzle' in str(otherParts.getPath(partNum)):
                otherParts.getPath(partNum).removeNode()
        ntrlMuzzle = self.toonHead.find('**/*muzzle*neutral')
        otherParts = self.toonHead.findAllMatches('**/*muzzle*')
        for partNum in range(0, otherParts.getNumPaths()):
            part = otherParts.getPath(partNum)
            if part != ntrlMuzzle:
                otherParts.getPath(partNum).removeNode()
        self.toonTorso = loader.loadModel('phase_3/models/char/tt_a_chr_dgl_shorts_torso_1000.bam')
        self.toonLegs  = loader.loadModel('phase_3/models/char/tt_a_chr_dgs_shorts_legs_1000.bam')
        otherParts = self.toonLegs.findAllMatches('**/boots*')+self.toonLegs.findAllMatches('**/shoes')
        for partNum in range(0, otherParts.getNumPaths()):
            otherParts.getPath(partNum).removeNode()

        self.toonActor = Actor({'head':self.toonHead, 'torso':self.toonTorso, 'legs':self.toonLegs},
                        {'torso':torsoAnimDict, 'legs':legsAnimDict})
        self.toonActor.setBlend(frameBlend = True)
        self.toonActor.attach('head', 'torso', 'def_head')
        self.toonActor.attach('torso', 'legs', 'joint_hips')

        gloves = self.toonActor.findAllMatches('**/hands')
        ears = self.toonActor.findAllMatches('**/*ears*')
        head = self.toonActor.findAllMatches('**/head-*')
        sleeves = self.toonActor.findAllMatches('**/sleeves')
        shirt = self.toonActor.findAllMatches('**/torso-top')
        shorts = self.toonActor.findAllMatches('**/torso-bot')
        neck = self.toonActor.findAllMatches('**/neck')
        arms = self.toonActor.findAllMatches('**/arms')
        legs = self.toonActor.findAllMatches('**/legs')
        feet = self.toonActor.findAllMatches('**/feet')
 
        self.bodyNodes = []
        self.bodyNodes += [gloves]
        self.bodyNodes += [head, ears]
        self.bodyNodes += [sleeves, shirt, shorts]
        self.bodyNodes += [neck, arms, legs, feet]
        self.bodyNodes[0].setColor(1, 1, 1, 1)
        self.bodyNodes[1].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[2].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[3].setColor(1, 1, 1, 1)
        self.bodyNodes[4].setColor(1, 1, 1, 1)
        self.bodyNodes[5].setColor(1, 1, 1, 1)
        self.bodyNodes[6].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[7].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[8].setColor(0.18, 0.54, 0.34, 1)
        self.bodyNodes[9].setColor(0.18, 0.54, 0.34, 1)

        topTex = loader.loadTexture('phase_4/maps/ContestfishingVestShirt2.jpg')
        botTex = loader.loadTexture('phase_4/maps/CowboyShorts1.jpg')
        sleeveTex = loader.loadTexture('phase_4/maps/ContestfishingVestSleeve1.jpg')

        self.bodyNodes[3].setTexture(sleeveTex, 1)
        self.bodyNodes[4].setTexture(topTex, 1)
        self.bodyNodes[5].setTexture(botTex, 1)
        self.height = 3.2375

        self.runNoise = loader.loadSfx('phase_3.5/audio/sfx/AV_footstep_runloop' + base.sfxExt2)
        self.runNoise.setLoop(True)
        self.walkNoise = loader.loadSfx('phase_3.5/audio/sfx/AV_footstep_walkloop' + base.sfxExt2)
        self.walkNoise.setLoop(True)

        self.loop('neutral')
        self.toonActor.reparentTo(render)


    def loop(self, anim):
        self.runNoise.stop()
        self.walkNoise.stop()
        self.toonActor.loop(anim)
        if anim == 'run':
            self.runNoise.play()
        elif anim == 'walk':
            self.walkNoise.play()

    def remove(self):
        self.toonActor.cleanup()
        self.toonActor.removeNode()
        del self
    def makeToon(self, gender, torso):
        if gender == "boy":
            torso += "_shorts"
        elif gender == "girl":
            torso += "_skirt"

        toon = Actor(None, None, None, flattenable=0, setFinal=1)

        # head mdl + anim
        toon.loadModel('phase_3/models/char/tt_a_chr_dgm_skirt_head_1000.bam',
                       'head')
        toon.loadAnims(
            {
                "neutral":
                "phase_3/models/char/tt_a_chr_dgm_skirt_head_neutral.bam"
            }, 'head')
        # torso mdl + anim
        toon.loadModel(
            'phase_3/models/char/tt_a_chr_' + torso + '_torso_1000.bam',
            'torso')
        toon.loadAnims(
            {
                'neutral':
                'phase_3/models/char/tt_a_chr_' + torso + '_torso_neutral.bam'
            }, 'torso')
        # legs mdl + anim
        toon.loadModel('phase_3/models/char/tt_a_chr_dgm_shorts_legs_1000.bam',
                       'legs')
        toon.loadAnims(
            {
                'neutral':
                'phase_3/models/char/tt_a_chr_dgm_shorts_legs_neutral.bam'
            }, 'legs')

        # attach parts
        toon.attach('head', 'torso', 'def_head')
        toon.attach('torso', 'legs', 'joint_hips')

        color = (0.347656, 0.820312, 0.953125, 1.0)
        toon.find('**/arms').setColor(color)
        toon.find('**/legs').setColor(color)
        toon.find('**/feet').setColor(color)
        toon.find('**/neck').setColor(color)
        toon.find('**/head').setColor(color)
        toon.find('**/head-front').setColor(color)
        toon.find('**/hands').setColor((1, 1, 1, 1))
        toon.find('**/shoes').removeNode()
        toon.find('**/boots_long').removeNode()
        toon.find('**/boots_short').removeNode()

        shirt = loader.loadTexture('phase_4/maps/4thJulyShirt2.jpg')
        sleeve = loader.loadTexture('phase_4/maps/4thJulySleeve2.jpg')
        if gender == "boy":
            bottom = loader.loadTexture('phase_4/maps/4thJulyShorts1.jpg')
        elif gender == "girl":
            bottom = loader.loadTexture('phase_4/maps/4thJulySkirt1.jpg')

        toon.find('**/torso-top').setTexture(shirt, 1)
        toon.find('**/sleeves').setTexture(sleeve, 1)
        toon.find('**/torso-bot').setTexture(bottom, 1)

        glasses = loader.loadModel(
            'phase_4/models/accessories/tt_m_chr_avt_acc_msk_dorkGlasses.bam')
        glassesNode = toon.getPart('head').attachNewNode('glassesNode')
        glasses.reparentTo(glassesNode)
        glasses.setScale(0.27, 0.2, 0.35)
        glasses.setH(180)
        glasses.setZ(0.27)
        glasses.setY(0.2)

        shadow = loader.loadModel('phase_3/models/props/drop_shadow.bam')
        shadow.reparentTo(toon.find('**/joint_shadow'))
        shadow.setScale(0.4)
        shadow.flattenMedium()
        shadow.setBillboardAxis(4)
        shadow.setColor(0, 0, 0, 0.5, 1)

        toon.reparentTo(render)
        toon.loop('neutral')

        return toon