from direct.actor import Actor from direct.task import Task from toontown.toonbase import ToontownGlobals import string import random from pandac.PandaModules import * from direct.interval.IntervalGlobal import * from direct.fsm.ClassicFSM import ClassicFSM from direct.fsm.State import State from direct.directnotify import DirectNotifyGlobal if not base.config.GetBool('want-new-anims', 1): HeadDict = {'dls': '/models/char/dogMM_Shorts-head-', 'dss': '/models/char/dogMM_Skirt-head-', 'dsl': '/models/char/dogSS_Shorts-head-', 'dll': '/models/char/dogLL_Shorts-head-', 'c': '/models/char/cat-heads-', 'h': '/models/char/horse-heads-', 'm': '/models/char/mouse-heads-', 'r': '/models/char/rabbit-heads-', 'f': '/models/char/duck-heads-', 'p': '/models/char/monkey-heads-', 'b': '/models/char/bear-heads-', 's': '/models/char/pig-heads-'} else: HeadDict = {'dls': '/models/char/tt_a_chr_dgm_shorts_head_', 'dss': '/models/char/tt_a_chr_dgm_skirt_head_', 'dsl': '/models/char/tt_a_chr_dgs_shorts_head_', 'dll': '/models/char/tt_a_chr_dgl_shorts_head_', 'c': '/models/char/cat-heads-', 'h': '/models/char/horse-heads-', 'm': '/models/char/mouse-heads-', 'r': '/models/char/rabbit-heads-', 'f': '/models/char/duck-heads-', 'p': '/models/char/monkey-heads-', 'b': '/models/char/bear-heads-', 's': '/models/char/pig-heads-'} EyelashDict = {'d': '/models/char/dog-lashes', 'c': '/models/char/cat-lashes', 'h': '/models/char/horse-lashes', 'm': '/models/char/mouse-lashes', 'r': '/models/char/rabbit-lashes', 'f': '/models/char/duck-lashes', 'p': '/models/char/monkey-lashes', 'b': '/models/char/bear-lashes', 's': '/models/char/pig-lashes'} DogMuzzleDict = {'dls': '/models/char/dogMM_Shorts-headMuzzles-', 'dss': '/models/char/dogMM_Skirt-headMuzzles-', 'dsl': '/models/char/dogSS_Shorts-headMuzzles-', 'dll': '/models/char/dogLL_Shorts-headMuzzles-'} PreloadHeads = {} def preloadToonHeads(): global PreloadHeads if not PreloadHeads: print 'Preloading Toon heads...' for key in HeadDict.keys(): fileRoot = HeadDict[key] PreloadHeads['phase_3' + fileRoot + '1000'] = loader.loadModel('phase_3' + fileRoot + '1000') PreloadHeads['phase_3' + fileRoot + '1000'].flattenMedium() PreloadHeads['phase_3' + fileRoot + '500'] = loader.loadModel('phase_3' + fileRoot + '500') PreloadHeads['phase_3' + fileRoot + '500'].flattenMedium() PreloadHeads['phase_3' + fileRoot + '250'] = loader.loadModel('phase_3' + fileRoot + '250') PreloadHeads['phase_3' + fileRoot + '250'].flattenMedium() preloadToonHeads() class ToonHead(Actor.Actor): notify = DirectNotifyGlobal.directNotify.newCategory('ToonHead') EyesOpen = loader.loadTexture('phase_3/maps/eyes.jpg', 'phase_3/maps/eyes_a.rgb') EyesOpen.setMinfilter(Texture.FTLinear) EyesOpen.setMagfilter(Texture.FTLinear) EyesClosed = loader.loadTexture('phase_3/maps/eyesClosed.jpg', 'phase_3/maps/eyesClosed_a.rgb') EyesClosed.setMinfilter(Texture.FTLinear) EyesClosed.setMagfilter(Texture.FTLinear) EyesSadOpen = loader.loadTexture('phase_3/maps/eyesSad.jpg', 'phase_3/maps/eyesSad_a.rgb') EyesSadOpen.setMinfilter(Texture.FTLinear) EyesSadOpen.setMagfilter(Texture.FTLinear) EyesSadClosed = loader.loadTexture('phase_3/maps/eyesSadClosed.jpg', 'phase_3/maps/eyesSadClosed_a.rgb') EyesSadClosed.setMinfilter(Texture.FTLinear) EyesSadClosed.setMagfilter(Texture.FTLinear) EyesAngryOpen = loader.loadTexture('phase_3/maps/eyesAngry.jpg', 'phase_3/maps/eyesAngry_a.rgb') EyesAngryOpen.setMinfilter(Texture.FTLinear) EyesAngryOpen.setMagfilter(Texture.FTLinear) EyesAngryClosed = loader.loadTexture('phase_3/maps/eyesAngryClosed.jpg', 'phase_3/maps/eyesAngryClosed_a.rgb') EyesAngryClosed.setMinfilter(Texture.FTLinear) EyesAngryClosed.setMagfilter(Texture.FTLinear) EyesSurprised = loader.loadTexture('phase_3/maps/eyesSurprised.jpg', 'phase_3/maps/eyesSurprised_a.rgb') EyesSurprised.setMinfilter(Texture.FTLinear) EyesSurprised.setMagfilter(Texture.FTLinear) Muzzle = loader.loadTexture('phase_3/maps/muzzleShrtGeneric.jpg') Muzzle.setMinfilter(Texture.FTLinear) Muzzle.setMagfilter(Texture.FTLinear) MuzzleSurprised = loader.loadTexture('phase_3/maps/muzzleShortSurprised.jpg') MuzzleSurprised.setMinfilter(Texture.FTLinear) MuzzleSurprised.setMagfilter(Texture.FTLinear) LeftA = Point3(0.06, 0.0, 0.14) LeftB = Point3(-0.13, 0.0, 0.1) LeftC = Point3(-0.05, 0.0, 0.0) LeftD = Point3(0.06, 0.0, 0.0) RightA = Point3(0.13, 0.0, 0.1) RightB = Point3(-0.06, 0.0, 0.14) RightC = Point3(-0.06, 0.0, 0.0) RightD = Point3(0.05, 0.0, 0.0) LeftAD = Point3(LeftA[0] - LeftA[2] * (LeftD[0] - LeftA[0]) / (LeftD[2] - LeftA[2]), 0.0, 0.0) LeftBC = Point3(LeftB[0] - LeftB[2] * (LeftC[0] - LeftB[0]) / (LeftC[2] - LeftB[2]), 0.0, 0.0) RightAD = Point3(RightA[0] - RightA[2] * (RightD[0] - RightA[0]) / (RightD[2] - RightA[2]), 0.0, 0.0) RightBC = Point3(RightB[0] - RightB[2] * (RightC[0] - RightB[0]) / (RightC[2] - RightB[2]), 0.0, 0.0) def __init__(self): try: self.ToonHead_initialized except: self.ToonHead_initialized = 1 Actor.Actor.__init__(self) self.toonName = 'ToonHead-' + str(self.this) self.__blinkName = 'blink-' + self.toonName self.__stareAtName = 'stareAt-' + self.toonName self.__lookName = 'look-' + self.toonName self.lookAtTrack = None self.__eyes = None self.__eyelashOpen = None self.__eyelashClosed = None self.__lod500Eyes = None self.__lod250Eyes = None self.__lpupil = None self.__lod500lPupil = None self.__lod250lPupil = None self.__rpupil = None self.__lod500rPupil = None self.__lod250rPupil = None self.__muzzle = None self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed self.__height = 0.0 self.__eyelashesHiddenByGlasses = False self.randGen = random.Random() self.randGen.seed(random.random()) self.eyelids = ClassicFSM('eyelids', [State('off', self.enterEyelidsOff, self.exitEyelidsOff, ['open', 'closed', 'surprised']), State('open', self.enterEyelidsOpen, self.exitEyelidsOpen, ['closed', 'surprised', 'off']), State('surprised', self.enterEyelidsSurprised, self.exitEyelidsSurprised, ['open', 'closed', 'off']), State('closed', self.enterEyelidsClosed, self.exitEyelidsClosed, ['open', 'surprised', 'off'])], 'off', 'off') self.eyelids.enterInitialState() self.emote = None self.__stareAtNode = NodePath() self.__defaultStarePoint = Point3(0, 0, 0) self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = 0 self.lookAtPositionCallbackArgs = None return def delete(self): try: self.ToonHead_deleted except: self.ToonHead_deleted = 1 taskMgr.remove(self.__blinkName) taskMgr.remove(self.__lookName) taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None del self.eyelids del self.__stareAtNode del self.__stareAtPoint if self.__eyes: del self.__eyes if self.__lpupil: del self.__lpupil if self.__rpupil: del self.__rpupil if self.__eyelashOpen: del self.__eyelashOpen if self.__eyelashClosed: del self.__eyelashClosed self.lookAtPositionCallbackArgs = None Actor.Actor.delete(self) return def setupHead(self, dna, forGui = 0): self.__height = self.generateToonHead(1, dna, ('1000',), forGui) self.generateToonColor(dna) animalStyle = dna.getAnimal() bodyScale = ToontownGlobals.toonBodyScales[animalStyle] headScale = ToontownGlobals.toonHeadScales[animalStyle] self.getGeomNode().setScale(headScale[0] * bodyScale * 1.3, headScale[1] * bodyScale * 1.3, headScale[2] * bodyScale * 1.3) if forGui: self.getGeomNode().setDepthWrite(1) self.getGeomNode().setDepthTest(1) if dna.getAnimal() == 'dog': self.loop('neutral') def fitAndCenterHead(self, maxDim, forGui = 0): p1 = Point3() p2 = Point3() self.calcTightBounds(p1, p2) if forGui: h = 180 t = p1[0] p1.setX(-p2[0]) p2.setX(-t) else: h = 0 d = p2 - p1 biggest = max(d[0], d[2]) s = maxDim / biggest mid = (p1 + d / 2.0) * s self.setPosHprScale(-mid[0], -mid[1] + 1, -mid[2], h, 0, 0, s, s, s) def setLookAtPositionCallbackArgs(self, argTuple): self.lookAtPositionCallbackArgs = argTuple def getHeight(self): return self.__height def getRandomForwardLookAtPoint(self): x = self.randGen.choice((-0.8, -0.5, 0, 0.5, 0.8)) z = self.randGen.choice((-0.5, 0, 0.5, 0.8)) return Point3(x, 1.5, z) def findSomethingToLookAt(self): if self.lookAtPositionCallbackArgs != None: pnt = self.lookAtPositionCallbackArgs[0].getLookAtPosition(self.lookAtPositionCallbackArgs[1], self.lookAtPositionCallbackArgs[2]) self.startStareAt(self, pnt) return if self.randGen.random() < 0.33: lookAtPnt = self.getRandomForwardLookAtPoint() else: lookAtPnt = self.__defaultStarePoint self.lerpLookAt(lookAtPnt, blink=1) return def generateToonHead(self, copy, style, lods, forGui = 0): global PreloadHeads headStyle = style.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: filepath = 'phase_3' + filePrefix + lods[0] self.loadModel(PreloadHeads[filepath], 'head', 'lodRoot', copy = True) if not forGui: pLoaded = self.loadPumpkin(headStyle[1], None, copy) self.loadSnowMan(headStyle[1], None, copy) if not copy: self.showAllParts('head') if fix != None: fix(style, None, copy) if not forGui: if pLoaded: self.__fixPumpkin(style, None, copy) else: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = copy else: for lod in lods: filepath = 'phase_3' + filePrefix + lod self.loadModel(PreloadHeads[filepath], 'head', lod, True) if not forGui: pLoaded = self.loadPumpkin(headStyle[1], lod, copy) self.loadSnowMan(headStyle[1], lod, copy) if not copy: self.showAllParts('head', lod) if fix != None: fix(style, lod, copy) if not forGui: if pLoaded: self.__fixPumpkin(style, lod, copy) else: self.__lods = lods self.__style = style self.__headStyle = headStyle self.__copy = copy self.__fixEyes(style, forGui) self.setupEyelashes(style) self.eyelids.request('closed') self.eyelids.request('open') self.setupMuzzles(style) return headHeight def loadPumpkin(self, headStyle, lod, copy): if hasattr(base, 'launcher') and (not base.launcher or base.launcher and base.launcher.getPhaseComplete(4)): if not hasattr(self, 'pumpkins'): self.pumpkins = NodePathCollection() ppath = 'phase_4/models/estate/pumpkin_' if headStyle is 'l': if copy: pmodel = loader.loadModel(ppath + 'tall') else: pmodel = loader.loadModel(ppath + 'tall') ptype = 'tall' else: if copy: pmodel = loader.loadModel(ppath + 'short') else: pmodel = loader.loadModel(ppath + 'short') ptype = 'short' if pmodel: p = pmodel.find('**/pumpkin_' + ptype + '*') p.setScale(0.5) p.setZ(-0.5) p.setH(180) if lod: p.reparentTo(self.find('**/' + lod + '/**/__Actor_head')) else: p.reparentTo(self.find('**/__Actor_head')) self.pumpkins.addPath(p) pmodel.removeNode() return True else: del self.pumpkins return False else: ToonHead.notify.debug('phase_4 not complete yet. Postponing pumpkin head load.') def loadSnowMan(self, headStyle, lod, copy): if hasattr(base, 'launcher') and (not base.launcher or base.launcher and base.launcher.getPhaseComplete(4)): if not hasattr(self, 'snowMen'): self.snowMen = NodePathCollection() snowManPath = 'phase_4/models/props/tt_m_efx_snowmanHead_' if headStyle is 'l': snowManPath = snowManPath + 'tall' else: snowManPath = snowManPath + 'short' model = loader.loadModel(snowManPath) if model: model.setZ(-0.5) model.setH(180) if lod: model.reparentTo(self.getPart('head', lod)) else: model.reparentTo(self.find('**/__Actor_head')) self.snowMen.addPath(model) model.stash() return True else: del self.snowMen return False else: ToonHead.notify.debug('phase_4 not loaded yet.') def __fixPumpkin(self, style, lodName = None, copy = 1): if lodName == None: searchRoot = self else: searchRoot = self.find('**/' + str(lodName)) pumpkin = searchRoot.find('**/__Actor_head/pumpkin*') pumpkin.stash() return def enablePumpkins(self, enable): if not hasattr(self, 'pumpkins'): if len(self.__lods) == 1: pLoaded = self.loadPumpkin(self.__headStyle[1], None, self.__copy) if pLoaded: self.__fixPumpkin(self.__style, None, self.__copy) else: for lod in self.__lods: pLoaded = self.loadPumpkin(self.__headStyle[1], lod, self.__copy) if pLoaded: self.__fixPumpkin(self.__style, lod, self.__copy) if hasattr(self, 'pumpkins'): for x in ['__lods', '__style', '__headStyle', '__copy']: if hasattr(self, '_ToonHead' + x): delattr(self, '_ToonHead' + x) if hasattr(self, 'pumpkins'): if enable: if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.pumpkins.unstash() else: if not self.__eyelashesHiddenByGlasses: if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.pumpkins.stash() return def enableSnowMen(self, enable): if not hasattr(self, 'snowMen'): if len(self.__lods) == 1: self.loadSnowMan(self.__headStyle[1], None, self.__copy) else: for lod in self.__lds: self.loadSnowMan(self.__headStyle[1], lod, self.__copy) if hasattr(self, 'snowMen'): if enable: if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.snowMen.unstash() else: if not self.__eyelashesHiddenByGlasses: if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.snowMen.stash() return def hideEars(self): self.findAllMatches('**/ears*;+s').stash() def showEars(self): self.findAllMatches('**/ears*;+s').unstash() def hideEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.stash() if self.__eyelashClosed: self.__eyelashClosed.stash() self.__eyelashesHiddenByGlasses = True def showEyelashes(self): if self.__eyelashOpen: self.__eyelashOpen.unstash() if self.__eyelashClosed: self.__eyelashClosed.unstash() self.__eyelashesHiddenByGlasses = False def generateToonColor(self, style): parts = self.findAllMatches('**/head*') parts.setColor(style.getHeadColor()) animalType = style.getAnimal() if animalType == 'cat' or animalType == 'rabbit' or animalType == 'bear' or animalType == 'mouse' or animalType == 'pig': parts = self.findAllMatches('**/ear?-*') parts.setColor(style.getHeadColor()) def __fixEyes(self, style, forGui = 0): mode = -3 if forGui: mode = -2 if self.hasLOD(): for lodName in self.getLODNames(): self.drawInFront('eyes*', 'head-front*', mode, lodName=lodName) if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) else: self.drawInFront('def_*_pupil', 'eyes*', -1, lodName=lodName) else: self.drawInFront('joint_pupil*', 'eyes*', -1, lodName=lodName) self.__eyes = self.getLOD(1000).find('**/eyes*') self.__lod500Eyes = self.getLOD(500).find('**/eyes*') self.__lod250Eyes = self.getLOD(250).find('**/eyes*') if self.__lod500Eyes.isEmpty(): self.__lod500Eyes = None else: self.__lod500Eyes.setColorOff() if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): self.__lod500lPupil = self.__lod500Eyes.find('**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find('**/joint_pupilR*') else: self.__lod500lPupil = self.__lod500Eyes.find('**/def_left_pupil*') self.__lod500rPupil = self.__lod500Eyes.find('**/def_right_pupil*') else: self.__lod500lPupil = self.__lod500Eyes.find('**/joint_pupilL*') self.__lod500rPupil = self.__lod500Eyes.find('**/joint_pupilR*') if self.__lod250Eyes.isEmpty(): self.__lod250Eyes = None else: self.__lod250Eyes.setColorOff() if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): self.__lod250lPupil = self.__lod250Eyes.find('**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find('**/joint_pupilR*') else: self.__lod250lPupil = self.__lod250Eyes.find('**/def_left_pupil*') self.__lod250rPupil = self.__lod250Eyes.find('**/def_right_pupil*') else: self.__lod250lPupil = self.__lod250Eyes.find('**/joint_pupilL*') self.__lod250rPupil = self.__lod250Eyes.find('**/joint_pupilR*') else: self.drawInFront('eyes*', 'head-front*', mode) if base.config.GetBool('want-new-anims', 1): if not self.find('joint_pupil*').isEmpty(): self.drawInFront('joint_pupil*', 'eyes*', -1) else: self.drawInFront('def_*_pupil', 'eyes*', -1) else: self.drawInFront('joint_pupil*', 'eyes*', -1) self.__eyes = self.find('**/eyes*') if not self.__eyes.isEmpty(): self.__eyes.setColorOff() self.__lpupil = None self.__rpupil = None if base.config.GetBool('want-new-anims', 1): if not self.find('**/joint_pupilL*').isEmpty(): if self.getLOD(1000): lp = self.getLOD(1000).find('**/joint_pupilL*') rp = self.getLOD(1000).find('**/joint_pupilR*') else: lp = self.find('**/joint_pupilL*') rp = self.find('**/joint_pupilR*') elif not self.getLOD(1000): lp = self.find('**/def_left_pupil*') rp = self.find('**/def_right_pupil*') else: lp = self.getLOD(1000).find('**/def_left_pupil*') rp = self.getLOD(1000).find('**/def_right_pupil*') else: lp = self.__eyes.find('**/joint_pupilL*') rp = self.__eyes.find('**/joint_pupilR*') if lp.isEmpty() or rp.isEmpty(): print 'Unable to locate pupils.' else: leye = self.__eyes.attachNewNode('leye') reye = self.__eyes.attachNewNode('reye') lmat = Mat4(0.802174, 0.59709, 0, 0, -0.586191, 0.787531, 0.190197, 0, 0.113565, -0.152571, 0.981746, 0, -0.233634, 0.418062, 0.0196875, 1) leye.setMat(lmat) rmat = Mat4(0.786788, -0.617224, 0, 0, 0.602836, 0.768447, 0.214658, 0, -0.132492, -0.16889, 0.976689, 0, 0.233634, 0.418062, 0.0196875, 1) reye.setMat(rmat) self.__lpupil = leye.attachNewNode('lpupil') self.__rpupil = reye.attachNewNode('rpupil') lpt = self.__eyes.attachNewNode('') rpt = self.__eyes.attachNewNode('') lpt.wrtReparentTo(self.__lpupil) rpt.wrtReparentTo(self.__rpupil) lp.reparentTo(lpt) rp.reparentTo(rpt) self.__lpupil.adjustAllPriorities(1) self.__rpupil.adjustAllPriorities(1) if self.__lod500Eyes: self.__lod500lPupil.adjustAllPriorities(1) self.__lod500rPupil.adjustAllPriorities(1) if self.__lod250Eyes: self.__lod250lPupil.adjustAllPriorities(1) self.__lod250rPupil.adjustAllPriorities(1) animalType = style.getAnimal() if animalType != 'dog': self.__lpupil.flattenStrong() self.__rpupil.flattenStrong() return def __setPupilDirection(self, x, y): if y < 0.0: y2 = -y left1 = self.LeftAD + (self.LeftD - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftC - self.LeftBC) * y2 right1 = self.RightAD + (self.RightD - self.RightAD) * y2 right2 = self.RightBC + (self.RightC - self.RightBC) * y2 else: y2 = y left1 = self.LeftAD + (self.LeftA - self.LeftAD) * y2 left2 = self.LeftBC + (self.LeftB - self.LeftBC) * y2 right1 = self.RightAD + (self.RightA - self.RightAD) * y2 right2 = self.RightBC + (self.RightB - self.RightBC) * y2 left0 = Point3(0.0, 0.0, left1[2] - left1[0] * (left2[2] - left1[2]) / (left2[0] - left1[0])) right0 = Point3(0.0, 0.0, right1[2] - right1[0] * (right2[2] - right1[2]) / (right2[0] - right1[0])) if x < 0.0: x2 = -x left = left0 + (left2 - left0) * x2 right = right0 + (right2 - right0) * x2 else: x2 = x left = left0 + (left1 - left0) * x2 right = right0 + (right1 - right0) * x2 self.__lpupil.setPos(left) self.__rpupil.setPos(right) def __lookPupilsAt(self, node, point): if node != None: mat = node.getMat(self.__eyes) point = mat.xformPoint(point) distance = 1.0 recip_z = 1.0 / max(0.1, point[1]) x = distance * point[0] * recip_z y = distance * point[2] * recip_z x = min(max(x, -1), 1) y = min(max(y, -1), 1) self.__setPupilDirection(x, y) return def __lookHeadAt(self, node, point, frac = 1.0, lod = None): reachedTarget = 1 if lod == None: head = self.getPart('head', self.getLODNames()[0]) else: head = self.getPart('head', lod) if node != None: headParent = head.getParent() mat = node.getMat(headParent) point = mat.xformPoint(point) rot = Mat3(0, 0, 0, 0, 0, 0, 0, 0, 0) lookAt(rot, Vec3(point), Vec3(0, 0, 1), CSDefault) scale = VBase3(0, 0, 0) hpr = VBase3(0, 0, 0) if decomposeMatrix(rot, scale, hpr, CSDefault): hpr = VBase3(min(max(hpr[0], -60), 60), min(max(hpr[1], -20), 30), 0) if frac != 1: currentHpr = head.getHpr() reachedTarget = abs(hpr[0] - currentHpr[0]) < 1.0 and abs(hpr[1] - currentHpr[1]) < 1.0 hpr = currentHpr + (hpr - currentHpr) * frac if lod == None: for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(hpr) else: head.setHpr(hpr) return reachedTarget def setupEyelashes(self, style): if style.getGender() == 'm': if self.__eyelashOpen: self.__eyelashOpen.removeNode() self.__eyelashOpen = None if self.__eyelashClosed: self.__eyelashClosed.removeNode() self.__eyelashClosed = None else: if self.__eyelashOpen: self.__eyelashOpen.removeNode() if self.__eyelashClosed: self.__eyelashClosed.removeNode() animal = style.head[0] model = loader.loadModel('phase_3' + EyelashDict[animal]) if self.hasLOD(): head = self.getPart('head', '1000') else: head = self.getPart('head', 'lodRoot') length = style.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 __fixHeadLongLong(self, style, lodName = None, copy = 1): if lodName == None: searchRoot = self else: searchRoot = self.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, style, lodName = None, copy = 1): animalType = style.getAnimal() headStyle = style.head if lodName == None: searchRoot = self else: searchRoot = self.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 copy: self.find('**/head-short').removeNode() self.find('**/head-front-short').removeNode() else: self.find('**/head-short').hide() self.find('**/head-front-short').hide() 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, style, lodName = None, copy = 1): animalType = style.getAnimal() headStyle = style.head if lodName == None: searchRoot = self else: searchRoot = self.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, style, lodName = None, copy = 1): if lodName == None: searchRoot = self else: searchRoot = self.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 __blinkOpenEyes(self, task): if self.eyelids.getCurrentState().getName() == 'closed': self.eyelids.request('open') r = self.randGen.random() if r < 0.1: t = 0.2 else: t = r * 4.0 + 1.0 taskMgr.doMethodLater(t, self.__blinkCloseEyes, self.__blinkName) return Task.done def __blinkCloseEyes(self, task): if self.eyelids.getCurrentState().getName() != 'open': taskMgr.doMethodLater(4.0, self.__blinkCloseEyes, self.__blinkName) else: self.eyelids.request('closed') taskMgr.doMethodLater(0.125, self.__blinkOpenEyes, self.__blinkName) return Task.done def startBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.openEyes() taskMgr.doMethodLater(self.randGen.random() * 4.0 + 1, self.__blinkCloseEyes, self.__blinkName) def stopBlink(self): taskMgr.remove(self.__blinkName) if self.__eyes: self.eyelids.request('open') def closeEyes(self): self.eyelids.request('closed') def openEyes(self): self.eyelids.request('open') def surpriseEyes(self): self.eyelids.request('surprised') def sadEyes(self): self.__eyesOpen = ToonHead.EyesSadOpen self.__eyesClosed = ToonHead.EyesSadClosed def angryEyes(self): self.__eyesOpen = ToonHead.EyesAngryOpen self.__eyesClosed = ToonHead.EyesAngryClosed def normalEyes(self): self.__eyesOpen = ToonHead.EyesOpen self.__eyesClosed = ToonHead.EyesClosed def blinkEyes(self): taskMgr.remove(self.__blinkName) self.eyelids.request('closed') taskMgr.doMethodLater(0.1, self.__blinkOpenEyes, self.__blinkName) def __stareAt(self, task): frac = 2 * globalClock.getDt() reachedTarget = self.__lookHeadAt(self.__stareAtNode, self.__stareAtPoint, frac) self.__lookPupilsAt(self.__stareAtNode, self.__stareAtPoint) if reachedTarget and self.__stareAtNode == None: return Task.done else: return Task.cont return def doLookAroundToStareAt(self, node, point): self.startStareAt(node, point) self.startLookAround() def startStareAtHeadPoint(self, point): self.startStareAt(self, point) def startStareAt(self, node, point): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None self.__stareAtNode = node if point != None: self.__stareAtPoint = point else: self.__stareAtPoint = self.__defaultStarePoint self.__stareAtTime = globalClock.getFrameTime() taskMgr.add(self.__stareAt, self.__stareAtName) return def lerpLookAt(self, point, time = 1.0, blink = 0): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None lodNames = self.getLODNames() if lodNames: lodName = lodNames[0] else: return 0 head = self.getPart('head', lodName) startHpr = head.getHpr() startLpupil = self.__lpupil.getPos() startRpupil = self.__rpupil.getPos() self.__lookHeadAt(None, point, lod=lodName) self.__lookPupilsAt(None, point) endHpr = head.getHpr() endLpupil = self.__lpupil.getPos() * 0.5 endRpupil = self.__rpupil.getPos() * 0.5 head.setHpr(startHpr) self.__lpupil.setPos(startLpupil) self.__rpupil.setPos(startRpupil) if startHpr.almostEqual(endHpr, 10): return 0 if blink: self.blinkEyes() lookToTgt_TimeFraction = 0.2 lookToTgtTime = time * lookToTgt_TimeFraction returnToEyeCenterTime = time - lookToTgtTime - 0.5 origin = Point3(0, 0, 0) blendType = 'easeOut' self.lookAtTrack = Parallel(Sequence(LerpPosInterval(self.__lpupil, lookToTgtTime, endLpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__lpupil, returnToEyeCenterTime, origin, blendType=blendType)), Sequence(LerpPosInterval(self.__rpupil, lookToTgtTime, endRpupil, blendType=blendType), Wait(0.5), LerpPosInterval(self.__rpupil, returnToEyeCenterTime, origin, blendType=blendType)), name=self.__stareAtName) for lodName in self.getLODNames(): head = self.getPart('head', lodName) self.lookAtTrack.append(LerpHprInterval(head, time, endHpr, blendType='easeInOut')) self.lookAtTrack.start() return 1 def stopStareAt(self): self.lerpLookAt(Vec3.forward()) def stopStareAtNow(self): taskMgr.remove(self.__stareAtName) if self.lookAtTrack: self.lookAtTrack.finish() self.lookAtTrack = None if self.__lpupil and self.__rpupil: self.__setPupilDirection(0, 0) for lodName in self.getLODNames(): head = self.getPart('head', lodName) head.setHpr(0, 0, 0) return def __lookAround(self, task): self.findSomethingToLookAt() t = self.randGen.random() * 4.0 + 3.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) return Task.done def startLookAround(self): taskMgr.remove(self.__lookName) t = self.randGen.random() * 5.0 + 2.0 taskMgr.doMethodLater(t, self.__lookAround, self.__lookName) def stopLookAround(self): taskMgr.remove(self.__lookName) self.stopStareAt() def stopLookAroundNow(self): taskMgr.remove(self.__lookName) self.stopStareAtNow() def enterEyelidsOff(self): pass def exitEyelidsOff(self): pass def enterEyelidsOpen(self): if not self.__eyes.isEmpty(): self.__eyes.setTexture(self.__eyesOpen, 1) if self.__eyelashOpen: self.__eyelashOpen.show() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesOpen, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesOpen, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsOpen(self): pass def enterEyelidsClosed(self): if not self.__eyes.isEmpty() and self.__eyesClosed: self.__eyes.setTexture(self.__eyesClosed, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.show() if self.__lod500Eyes: self.__lod500Eyes.setTexture(self.__eyesClosed, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(self.__eyesClosed, 1) if self.__lpupil: self.__lpupil.hide() self.__rpupil.hide() if self.__lod500lPupil: self.__lod500lPupil.hide() self.__lod500rPupil.hide() if self.__lod250lPupil: self.__lod250lPupil.hide() self.__lod250rPupil.hide() def exitEyelidsClosed(self): pass def enterEyelidsSurprised(self): if not self.__eyes.isEmpty() and ToonHead.EyesSurprised: self.__eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__eyelashOpen: self.__eyelashOpen.hide() if self.__eyelashClosed: self.__eyelashClosed.hide() if self.__lod500Eyes: self.__lod500Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__lod250Eyes: self.__lod250Eyes.setTexture(ToonHead.EyesSurprised, 1) if self.__muzzle: self.__muzzle.setTexture(ToonHead.MuzzleSurprised, 1) if self.__lpupil: self.__lpupil.show() self.__rpupil.show() if self.__lod500lPupil: self.__lod500lPupil.show() self.__lod500rPupil.show() if self.__lod250lPupil: self.__lod250lPupil.show() self.__lod250rPupil.show() def exitEyelidsSurprised(self): if self.__muzzle: self.__muzzle.setTexture(ToonHead.Muzzle, 1) def setupMuzzles(self, style): 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.hasLOD(): for lodName in self.getLODNames(): animal = style.getAnimal() if animal != 'dog': muzzle = self.find('**/' + lodName + '/**/muzzle*neutral') else: muzzle = self.find('**/' + lodName + '/**/muzzle*') if lodName == '1000' or lodName == '500': filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + lodName) if base.config.GetBool('want-new-anims', 1): if not self.find('**/' + lodName + '/**/__Actor_head/def_head').isEmpty(): muzzles.reparentTo(self.find('**/' + lodName + '/**/__Actor_head/def_head')) else: muzzles.reparentTo(self.find('**/' + lodName + '/**/joint_toHead')) elif self.find('**/' + lodName + '/**/joint_toHead'): muzzles.reparentTo(self.find('**/' + lodName + '/**/joint_toHead')) surpriseMuzzle = self.find('**/' + lodName + '/**/muzzle*surprise') angryMuzzle = self.find('**/' + lodName + '/**/muzzle*angry') sadMuzzle = self.find('**/' + lodName + '/**/muzzle*sad') smileMuzzle = self.find('**/' + lodName + '/**/muzzle*smile') laughMuzzle = self.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) else: if style.getAnimal() != 'dog': muzzle = self.find('**/muzzle*neutral') else: muzzle = self.find('**/muzzle*') filePrefix = DogMuzzleDict[style.head] muzzles = loader.loadModel('phase_3' + filePrefix + '1000') if base.config.GetBool('want-new-anims', 1): if not self.find('**/def_head').isEmpty(): muzzles.reparentTo(self.find('**/def_head')) else: muzzles.reparentTo(self.find('**/joint_toHead')) else: muzzles.reparentTo(self.find('**/joint_toHead')) surpriseMuzzle = self.find('**/muzzle*surprise') angryMuzzle = self.find('**/muzzle*angry') sadMuzzle = self.find('**/muzzle*sad') smileMuzzle = self.find('**/muzzle*smile') laughMuzzle = self.find('**/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 getMuzzles(self): return self.__muzzles def getSurpriseMuzzles(self): return self.__surpriseMuzzles def getAngryMuzzles(self): return self.__angryMuzzles def getSadMuzzles(self): return self.__sadMuzzles def getSmileMuzzles(self): return self.__smileMuzzles def getLaughMuzzles(self): return self.__laughMuzzles def showNormalMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__muzzles)): self.__muzzles[muzzleNum].show() def hideNormalMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__muzzles)): self.__muzzles[muzzleNum].hide() def showAngryMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideAngryMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__angryMuzzles)): self.__angryMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSadMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSadMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__sadMuzzles)): self.__sadMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSmileMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSmileMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__smileMuzzles)): self.__smileMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showLaughMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideLaughMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__laughMuzzles)): self.__laughMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def showSurpriseMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].show() self.__muzzles[muzzleNum].hide() def hideSurpriseMuzzle(self): if self.isIgnoreCheesyEffect(): return for muzzleNum in xrange(len(self.__surpriseMuzzles)): self.__surpriseMuzzles[muzzleNum].hide() self.__muzzles[muzzleNum].show() def isIgnoreCheesyEffect(self): if hasattr(self, 'savedCheesyEffect'): if self.savedCheesyEffect == 10 or self.savedCheesyEffect == 11 or self.savedCheesyEffect == 12 or self.savedCheesyEffect == 13 or self.savedCheesyEffect == 14: return True return False