NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

paperDollSpawnWrappers.py (14869B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\paperDoll\paperDollSpawnWrappers.py
      2 import trinity
      3 import uthread
      4 import eve.common.script.paperDoll.paperDollDefinitions as pdDef
      5 import eve.common.script.paperDoll.paperDollDataManagement as pdDm
      6 import eve.client.script.paperDoll.commonClientFunctions as pdCcf
      7 import eve.common.script.paperDoll.paperDollCommonFunctions as pdCf
      8 import eve.client.script.paperDoll.paperDollImpl as pdImpl
      9 import eve.client.script.paperDoll.paperDollLOD as pdLod
     10 import eve.client.script.paperDoll.paperDollPortrait as pdPor
     11 import blue
     12 import telemetry
     13 import yaml
     14 import log
     15 
     16 class PaperDollManager(object):
     17     __metaclass__ = telemetry.ZONE_PER_METHOD
     18 
     19     def __init__(self, factory, keyFunc = None):
     20         self.factory = factory
     21         self.keyFunc = keyFunc
     22         self.__pdc = {}
     23 
     24     def __del__(self):
     25         self.ClearDolls()
     26 
     27     def __iter__(self):
     28         for pdc in self.__pdc.itervalues():
     29             yield pdc
     30 
     31     def Count(self):
     32         return len(self.__pdc)
     33 
     34     def GetPaperDollCharacterByDoll(self, doll):
     35         for pdc in iter(self):
     36             if pdImpl.Doll.InstanceEquals(pdc.doll, doll):
     37                 return pdc
     38 
     39     def GetPaperDollCharacterByAvatar(self, avatar):
     40         for pdc in iter(self):
     41             if pdc.avatar == avatar:
     42                 return pdc
     43 
     44     def GetPaperDollCharacterByKey(self, key):
     45         return self.__pdc.get(key)
     46 
     47     def RemovePaperDollCharacter(self, pdc):
     48         key = self.__GetKey(pdc)
     49         if key in self.__pdc:
     50             del self.__pdc[key]
     51 
     52     def ClearDolls(self):
     53         self.__pdc.clear()
     54 
     55     def __GetKey(self, pdc):
     56         doll = pdc.GetDoll()
     57         if self.keyFunc:
     58             return self.keyFunc(doll)
     59         else:
     60             return doll.instanceID
     61 
     62     def SpawnPaperDollCharacterFromDNA(self, scene, dollName, dollDNA, position = None, rotation = None, lodEnabled = False, compressionSettings = None, gender = pdDef.GENDER.FEMALE, textureResolution = None, updateDoll = True, spawnAtLOD = 0):
     63         pdc = PaperDollCharacter(self.factory)
     64         pdc.LoadDollFromDNA(dollDNA, dollName=dollName, lodEnabled=lodEnabled, compressionSettings=compressionSettings)
     65         if textureResolution:
     66             pdc.doll.SetTextureSize(textureResolution)
     67         if lodEnabled:
     68             pdc.SpawnLOD(scene, point=position, rotation=rotation, gender=gender)
     69         else:
     70             pdc.Spawn(scene, point=position, rotation=rotation, gender=gender, updateDoll=updateDoll, lod=spawnAtLOD)
     71         self.__pdc[self.__GetKey(pdc)] = pdc
     72         sm.ScatterEvent('OnDollCreated', self.__GetKey(pdc))
     73         return pdc
     74 
     75     def SpawnRandomDoll(self, scene, **kwargs):
     76         pdc = PaperDollCharacter(self.factory)
     77         pdc.MakeRandomDoll()
     78         autoLod = kwargs.get('autoLOD')
     79         if autoLod:
     80             pdc.SpawnLOD(scene, **kwargs)
     81         else:
     82             pdc.Spawn(scene, **kwargs)
     83         self.__pdc[self.__GetKey(pdc)] = pdc
     84         sm.ScatterEvent('OnDollCreated', self.__GetKey(pdc))
     85         return pdc
     86 
     87     def SpawnDoll(self, scene, **kwargs):
     88         doll = kwargs.get('doll')
     89         autoLod = kwargs.get('autoLOD')
     90         pdc = PaperDollCharacter(self.factory, doll=doll)
     91         if autoLod:
     92             pdc.SpawnLOD(scene, **kwargs)
     93         else:
     94             pdc.Spawn(scene, **kwargs)
     95         self.__pdc[self.__GetKey(pdc)] = pdc
     96         sm.ScatterEvent('OnDollCreated', self.__GetKey(pdc))
     97         return pdc
     98 
     99     def SpawnDollFromRes(self, scene, resPath, **kwargs):
    100         pdc = PaperDollCharacter(self.factory)
    101         pdc.LoadFromRes(resPath)
    102         pdc.Spawn(scene, **kwargs)
    103         self.__pdc[self.__GetKey(pdc)] = pdc
    104         sm.ScatterEvent('OnDollCreated', self.__GetKey(pdc))
    105         return pdc
    106 
    107     def GetAllDolls(self):
    108         dolls = []
    109         for dc in self.__pdc.itervalues():
    110             dollInfo = {}
    111             dollInfo['name'] = dc.doll.name
    112             dollInfo['translation'] = dc.avatar.translation
    113             dollInfo['rotation'] = dc.avatar.rotation
    114             dollInfo['dna'] = dc.GetDNA()
    115             dollInfo['doll'] = dc
    116             dolls.append(dollInfo)
    117 
    118         return dolls
    119 
    120     def RestoreDollsFromDnaToScene(self, dolls, scene):
    121         for dc in dolls:
    122             self.SpawnPaperDollCharacterFromDNA(scene, dc['name'], dc['dna'], position=dc['translation'], rotation=dc['rotation'])
    123 
    124     def WaitForAllDolls(self):
    125         for dc in self.__pdc.itervalues():
    126             dc.WaitForUpdate()
    127 
    128 
    129 class PaperDollCharacter(object):
    130     __metaclass__ = telemetry.ZONE_PER_METHOD
    131     __DEFAULT_NAME = 'Spawned Character'
    132 
    133     def setscene(self, scene):
    134         self.__scene = blue.BluePythonWeakRef(scene)
    135 
    136     scene = property(fget=lambda self: self.__scene.object, fset=lambda self, x: self.setscene(x))
    137 
    138     def __init__(self, factory, doll = None, avatar = None, visualModel = None):
    139         self.factory = factory
    140         self.doll = None
    141         self.factory.WaitUntilLoaded()
    142         self.doll = doll
    143         self.avatar = avatar
    144         self.visualModel = visualModel
    145         if not visualModel and hasattr(avatar, 'visualModel'):
    146             self.visualModel = avatar.visualModel
    147         self.__scene = blue.BluePythonWeakRef(None)
    148         self.autoLod = False
    149         self.disableDel = False
    150         trinity.device.RegisterResource(self)
    151 
    152     def __del__(self):
    153         if self.disableDel:
    154             return
    155         del self.doll
    156         del self.visualModel
    157         if self.scene:
    158             self.factory.RemoveAvatarFromScene(self.avatar, self.scene)
    159         if self.avatar:
    160             self.avatar.visualModel = None
    161         if self.autoLod:
    162             pdLod.AbortAllLod(self.avatar)
    163         del self.avatar
    164 
    165     def OnInvalidate(self, dev):
    166         pass
    167 
    168     def OnCreate(self, dev):
    169         if self.doll and self.avatar:
    170             self.doll.KillUpdate()
    171             self.doll.mapBundle.ReCreate()
    172             for modifier in self.doll.buildDataManager.GetModifiersAsList():
    173                 modifier.IsDirty |= modifier.decalData is not None or modifier.IsMeshDirty()
    174 
    175             self.doll.decalBaker = None
    176             uthread.new(self.doll.Update, self.factory, self.avatar)
    177 
    178     def ExportCharacter(self, resPath):
    179 
    180         def fun():
    181             path = resPath
    182 
    183             def GetMapResourcePath(map):
    184                 return path + '/' + pdDef.MAPNAMES[map] + '.dds'
    185 
    186             for map in pdDef.MAPS:
    187                 texture = self.doll.mapBundle[map]
    188                 texture.SaveAsync(GetMapResourcePath(map))
    189                 texture.WaitForSave()
    190 
    191             meshGeometryResPaths = {}
    192             for modifier in self.doll.buildDataManager.GetSortedModifiers():
    193                 meshGeometryResPaths.update(modifier.meshGeometryResPaths)
    194 
    195             for mesh in self.avatar.visualModel.meshes:
    196                 mesh.geometryResPath = meshGeometryResPaths.get(mesh.name, '')
    197                 for fx in pdCcf.GetEffectsFromMesh(mesh):
    198                     fx.StartUpdate()
    199                     try:
    200                         for resource in fx.resources:
    201                             if resource.name in pdDef.MAPNAMES:
    202                                 resource.resourcePath = GetMapResourcePath(pdDef.MAPNAMES.index(resource.name))
    203 
    204                     finally:
    205                         fx.EndUpdate()
    206 
    207             trinity.Save(self.avatar, path + '/unique.red')
    208             morphTargets = {}
    209             for modifier in self.doll.buildDataManager.GetSortedModifiers():
    210                 if modifier.categorie in pdDef.BLENDSHAPE_CATEGORIES:
    211                     morphTargets[modifier.name] = modifier.weight
    212 
    213             bsFilePath = blue.paths.ResolvePath(path + '/blendshapes.yaml')
    214             f = file(bsFilePath, 'w')
    215             yaml.dump(morphTargets, f)
    216             f.close()
    217             animOffsets = {}
    218             for bone in self.doll.boneOffsets:
    219                 trans = self.doll.boneOffsets[bone]['translation']
    220                 animOffsets[bone] = trans
    221 
    222             aoFilePath = blue.paths.ResolvePath(path + '/animationOffsets.yaml')
    223             f = file(aoFilePath, 'w')
    224             yaml.dump(animOffsets, f)
    225             f.close()
    226 
    227         uthread.new(fun)
    228 
    229     @staticmethod
    230     def ImportCharacter(factory, scene, resPath, **kwargs):
    231         blocking = kwargs.get('blocking')
    232         callBack = kwargs.get('callBack')
    233         rotation = kwargs.get('rotation')
    234         position = kwargs.get('point')
    235         pdc = PaperDollCharacter(factory)
    236         pdc.scene = scene
    237         pdc.avatar = trinity.Load(resPath + '/unique.red')
    238         if pdc.avatar is None:
    239             log.LogInfo('Import failed on ' + resPath + '/unique.red')
    240             return
    241         pdc.visualModel = pdc.avatar.visualModel
    242         slash = resPath.rfind('/')
    243         pdc.avatar.name = str(resPath[slash + 1:] + ' (import)')
    244         if position:
    245             pdc.avatar.translation = position
    246         if rotation:
    247             pdc.avatar.rotation = rotation
    248         rf = blue.ResFile()
    249         bsPath = resPath + '/blendshapes.yaml'
    250         meshes = None
    251         morphTargets = pdDm.LoadYamlFileNicely(bsPath)
    252         if morphTargets:
    253             meshes = pdc.visualModel.meshes
    254 
    255         def fun():
    256             if meshes:
    257                 factory.ApplyMorphTargetsToMeshes(meshes, morphTargets)
    258                 if trinity.GetShaderModel() == 'SM_2_0_LO':
    259                     pdPor.PortraitTools.RebindDXT5ShadersForSM2(meshes)
    260             if callBack:
    261                 callBack()
    262 
    263         if blocking:
    264             fun()
    265         else:
    266             uthread.worker('paperDoll::PaperDollCharacter::ImportCharacter', fun)
    267         scene.AddDynamic(pdc.avatar)
    268         pdc.avatar.explicitMinBounds = (-5, -5, -5)
    269         pdc.avatar.explicitMaxBounds = (5, 5, 5)
    270         pdc.avatar.useExplicitBounds = True
    271         return pdc
    272 
    273     def GetDoll(self):
    274         return self.doll
    275 
    276     def GetAvatar(self):
    277         return self.avatar
    278 
    279     def MakeRandomDoll(self):
    280         self.doll = pdCcf.CreateRandomDoll(self.doll.name if self.doll else PaperDollCharacter.__DEFAULT_NAME, self.factory)
    281         if self.avatar:
    282             self.doll.Update(self.factory, self.avatar)
    283 
    284     def MakeDollNude(self):
    285         self.doll.buildDataManager = pdDm.BuildDataManager()
    286         if self.avatar:
    287             self.doll.Update(self.factory, self.avatar)
    288 
    289     def LoadFromRes(self, resPath):
    290         self.doll = pdImpl.Doll(PaperDollCharacter.__DEFAULT_NAME)
    291         while not self.factory.IsLoaded:
    292             pdCf.Yield()
    293 
    294         self.doll.Load(resPath, self.factory)
    295         if self.avatar:
    296             self.doll.Update(self.factory, self.avatar)
    297 
    298     def LoadDollFromDNA(self, dollDNA, dollName = None, lodEnabled = True, compressionSettings = None):
    299         name = dollName if dollName is not None else PaperDollCharacter.__DEFAULT_NAME
    300         self.doll = pdImpl.Doll(name)
    301         self.doll.LoadDNA(dollDNA, self.factory)
    302         if compressionSettings:
    303             self.doll.compressionSettings = compressionSettings
    304         if self.avatar:
    305             gender = pdDef.GENDER.MALE if self.doll.gender else pdDef.GENDER.FEMALE
    306             networkToLoad = const.FEMALE_MORPHEME_PATH if gender == pdDef.GENDER.FEMALE else const.MALE_MORPHEME_PATH
    307             if lodEnabled:
    308                 uthread.worker('^PaperDollCharacter::LoadFromDNA', pdLod.SetupLODFromPaperdoll, self.avatar, self.doll, self.factory, networkToLoad)
    309             else:
    310                 uthread.worker('^PaperDollCharacter::LoadFromDNA', self.doll.Update, self.factory, self.avatar)
    311 
    312     def GetDNA(self):
    313         return self.doll.GetDNA()
    314 
    315     def __PrepareAvatar(self, scene, point = None, rotation = None, name = None):
    316         if scene is None:
    317             raise ValueError('None type passed as scene to paperDoll::__PrepareAvatar!')
    318         oldAnimation = None
    319         sceneTypesDifferent = getattr(self.scene, '__typename__', None) != getattr(scene, '__typename__', None)
    320         if self.avatar:
    321             oldAnimation = self.avatar.animationUpdater
    322             if self.scene:
    323                 self.factory.RemoveAvatarFromScene(self.avatar, self.scene)
    324             if sceneTypesDifferent:
    325                 pdLod.AbortAllLod(self.avatar)
    326                 del self.avatar
    327         if type(scene) in (trinity.Tr2InteriorScene, trinity.WodBakingScene) and type(self.scene) is not type(scene):
    328             self.avatar = trinity.Tr2IntSkinnedObject()
    329             if name:
    330                 self.avatar.name = name
    331             self.doll.avatarType = 'interior'
    332         self.factory.AddAvatarToScene(self.avatar, scene)
    333         if point:
    334             self.avatar.translation = point
    335         if rotation:
    336             self.avatar.rotation = rotation
    337         if oldAnimation is not None:
    338             self.avatar.animationUpdater = oldAnimation
    339         if getattr(self.avatar.animationUpdater, 'network', None):
    340             if self.doll.gender == pdDef.GENDER.MALE and self.avatar.animationUpdater.network.GetAnimationSetCount() > 1:
    341                 self.avatar.animationUpdater.network.SetAnimationSetIndex(1)
    342             else:
    343                 self.avatar.animationUpdater.network.SetAnimationSetIndex(0)
    344 
    345     def SpawnLOD(self, scene, **kwargs):
    346         self.Spawn(scene, spawnLod=True, **kwargs)
    347 
    348     def Spawn(self, scene, **kwargs):
    349         gender = pdDef.GENDER.FEMALE
    350         if 'gender' in kwargs:
    351             gender = kwargs['gender']
    352         if self.doll is None:
    353             self.doll = pdImpl.Doll(PaperDollCharacter.__DEFAULT_NAME, gender=gender)
    354         else:
    355             gender = self.doll.gender
    356         spawnLod = kwargs.get('spawnLod', False)
    357         if 'lod' in kwargs and not spawnLod:
    358             self.doll.overrideLod = kwargs['lod']
    359         if self.visualModel is None:
    360             self.visualModel = self.factory.CreateVisualModel(gender=gender)
    361         self.__PrepareAvatar(scene, point=kwargs.get('point'), rotation=kwargs.get('rotation'), name=kwargs.get('name', None))
    362         self.scene = scene
    363         self.avatar.visualModel = self.visualModel
    364         if spawnLod:
    365             networkToLoad = const.FEMALE_MORPHEME_PATH if gender == pdDef.GENDER.FEMALE else const.MALE_MORPHEME_PATH
    366             pdLod.SetupLODFromPaperdoll(self.avatar, self.doll, self.factory, networkToLoad)
    367         elif kwargs.get('updateDoll', True):
    368             self.doll.Update(self.factory, self.avatar)
    369 
    370     def MoveToScene(self, scene, point = None):
    371         if scene and self.doll:
    372             self.Spawn(scene, point=point, updateDoll=False)
    373 
    374     def Update(self, channel = None):
    375         return self.doll.Update(self.factory, self.avatar, channel=channel)
    376 
    377     def UpdateClothSimulationStatus(self):
    378         self.doll.buildDataManager.SetAllAsDirty(clearMeshes=True)
    379         self.Update()
    380 
    381     def WaitForUpdate(self):
    382         while self.doll.busyUpdating:
    383             pdCf.Yield()