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

paperDollLOD.py (9572B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\paperDoll\paperDollLOD.py
      2 import blue
      3 import trinity
      4 import uthread
      5 import weakref
      6 import log
      7 import locks
      8 import time
      9 from eve.common.script.paperDoll.paperDollConfiguration import PerformanceOptions
     10 LoadingStubPath = 'res:/Graphics/Character/Global/LowLODs/Female/BasicFemale/BasicFemale.red'
     11 
     12 class LodQueue(object):
     13     instance = None
     14     magicLOD = 99
     15 
     16     class QueueEntry:
     17 
     18         def __init__(self, avatarBluePythonWeakRef, dollWeakref, factoryWeakref, lodWanted):
     19             self.avatar = avatarBluePythonWeakRef
     20             self.doll = dollWeakref
     21             self.factory = factoryWeakref
     22             self.lodWanted = lodWanted
     23             self.timeAddToQueue = time.time()
     24             self.timeUpdateStarted = 0
     25 
     26     def __init__(self):
     27         self.queue = []
     28         self.inCallback = False
     29         self.updateEvent = locks.Event(name='LodQueueEvent')
     30         self.__freezeQueue = False
     31         uthread.new(LodQueue.QueueMonitorThread, weakref.ref(self))
     32         self.queueSizeStat = blue.statistics.Find('paperDoll/queueSize')
     33         if not self.queueSizeStat:
     34             self.queueSizeStat = blue.CcpStatisticsEntry()
     35             self.queueSizeStat.name = 'paperDoll/queueSize'
     36             self.queueSizeStat.type = 1
     37             self.queueSizeStat.resetPerFrame = False
     38             self.queueSizeStat.description = 'The length of the LOD switching queue'
     39             blue.statistics.Register(self.queueSizeStat)
     40         self.queueActiveUpStat = blue.statistics.Find('paperDoll/queueActiveUp')
     41         if not self.queueActiveUpStat:
     42             self.queueActiveUpStat = blue.CcpStatisticsEntry()
     43             self.queueActiveUpStat.name = 'paperDoll/queueActiveUp'
     44             self.queueActiveUpStat.type = 1
     45             self.queueActiveUpStat.resetPerFrame = False
     46             self.queueActiveUpStat.description = 'Number of LOD switches to higher quality in progress'
     47             blue.statistics.Register(self.queueActiveUpStat)
     48         self.queueActiveDownStat = blue.statistics.Find('paperDoll/queueActiveDown')
     49         if not self.queueActiveDownStat:
     50             self.queueActiveDownStat = blue.CcpStatisticsEntry()
     51             self.queueActiveDownStat.name = 'paperDoll/queueActiveDown'
     52             self.queueActiveDownStat.type = 1
     53             self.queueActiveDownStat.resetPerFrame = False
     54             self.queueActiveDownStat.description = 'Number of LOD switches to lower quality in progress'
     55             blue.statistics.Register(self.queueActiveDownStat)
     56 
     57     def getFreezeQueue(self):
     58         return self.__freezeQueue
     59 
     60     def setFreezeQueue(self, freeze):
     61         self.__freezeQueue = freeze
     62         LodQueue.OnDollUpdateDoneStatic()
     63 
     64     freezeQueue = property(getFreezeQueue, setFreezeQueue)
     65 
     66     def __del__(self):
     67         self.updateEvent.set()
     68 
     69     @staticmethod
     70     def OnDollUpdateDoneStatic():
     71         if LodQueue.instance is None:
     72             return
     73         LodQueue.instance.updateEvent.set()
     74 
     75     @staticmethod
     76     def QueueMonitorThread(weakSelf):
     77         while weakSelf():
     78             weakSelf().updateEvent.wait()
     79             wakeUpTime = time.time()
     80             self = weakSelf()
     81             if self is None:
     82                 break
     83             self.updateEvent.clear()
     84             busyUp, busyDown = self.UpdateQueue(wakeUpTime)
     85             if not self.__freezeQueue:
     86                 maxBusyUp = PerformanceOptions.maxLodQueueActiveUp
     87                 maxBusyDown = PerformanceOptions.maxLodQueueActiveDown
     88                 scan = 0
     89                 max = len(self.queue)
     90                 while busyDown < maxBusyDown and busyUp < maxBusyUp and scan < max:
     91                     doll = self.queue[scan].doll()
     92                     if doll is not None and not doll.busyUpdating:
     93                         doll = self.queue[scan].doll()
     94                         goingUp = True
     95                         if doll is not None:
     96                             goingUp = self.queue[scan].lodWanted < doll.overrideLod
     97                         if self.ProcessRequest(self.queue[scan], allowUp=busyUp < maxBusyUp):
     98                             if goingUp:
     99                                 busyUp = busyUp + 1
    100                             else:
    101                                 busyDown = busyDown + 1
    102                     scan = scan + 1
    103 
    104             self.queueActiveUpStat.Set(busyUp)
    105             self.queueActiveDownStat.Set(busyDown)
    106 
    107     def UpdateQueue(self, wakeUpTime):
    108         i = 0
    109         busyUp = 0
    110         busyDown = 0
    111         while i < len(self.queue):
    112             doll = self.queue[i].doll()
    113             factory = self.queue[i].factory()
    114             avatar = self.queue[i].avatar.object
    115             if doll is None:
    116                 self.queue.pop(i)
    117             elif doll.busyUpdating:
    118                 if doll.previousLOD != LodQueue.magicLOD and doll.previousLOD <= self.queue[i].lodWanted:
    119                     busyDown = busyDown + 1
    120                 else:
    121                     busyUp = busyUp + 1
    122                 i = i + 1
    123             elif doll.overrideLod == self.queue[i].lodWanted:
    124                 q = self.queue.pop(i)
    125                 if PerformanceOptions.logLodPerformance:
    126                     log.LogInfo('LOD switch to', q.lodWanted, 'took', wakeUpTime - q.timeUpdateStarted, 'secs; wait in queue', q.timeUpdateStarted - q.timeAddToQueue, 'secs')
    127             else:
    128                 i = i + 1
    129 
    130         self.queueSizeStat.Set(len(self.queue))
    131         return (busyUp, busyDown)
    132 
    133     def AddToQueue(self, avatarBluePythonWeakRef, dollWeakref, factoryWeakref, lodWanted):
    134         if type(avatarBluePythonWeakRef) != blue.BluePythonWeakRef:
    135             avatarBluePythonWeakRef = blue.BluePythonWeakRef(avatarBluePythonWeakRef)
    136         if type(dollWeakref) != weakref.ref:
    137             dollWeakref = weakref.ref(dollWeakref)
    138         if type(factoryWeakref) != weakref.ref:
    139             factoryWeakref = weakref.ref(factoryWeakref)
    140         for i in xrange(len(self.queue)):
    141             q = self.queue[i]
    142             if q.doll() == dollWeakref() and q.factory() == factoryWeakref() and q.avatar.object == avatarBluePythonWeakRef.object:
    143                 q.lodWanted = lodWanted
    144                 if q.doll().busyUpdating:
    145                     q.doll().Update(q.factory(), q.avatar.object)
    146                 break
    147         else:
    148             entry = self.QueueEntry(avatarBluePythonWeakRef, dollWeakref, factoryWeakref, lodWanted)
    149             self.queue.append(entry)
    150 
    151         self.updateEvent.set()
    152 
    153     def ProcessRequest(self, queueEntry, allowUp):
    154         doll = queueEntry.doll()
    155         factory = queueEntry.factory()
    156         avatar = queueEntry.avatar.object
    157         if doll is None or factory is None or avatar is None:
    158             return False
    159         if queueEntry.lodWanted == doll.overrideLod:
    160             return False
    161         if queueEntry.lodWanted < doll.overrideLod and not allowUp:
    162             return False
    163         doll.overrideLod = queueEntry.lodWanted
    164         doll.AddUpdateDoneListener(LodQueue.OnDollUpdateDoneStatic)
    165         queueEntry.timeUpdateStarted = time.time()
    166         doll.Update(factory, avatar)
    167         return True
    168 
    169 
    170 def SetupLODFromPaperdoll(avatar, doll, factory, animation, loadStub = True):
    171     if doll is None or avatar is None:
    172         return
    173     stub = None
    174     if loadStub:
    175         if type(avatar) == trinity.Tr2IntSkinnedObject:
    176             stub = blue.resMan.LoadObject(LoadingStubPath)
    177     if hasattr(stub, 'visualModel'):
    178         stub = stub.visualModel
    179 
    180     class InPlaceBuilder:
    181 
    182         def __init__(self, avatar, doll, factory, stub):
    183             self.avatar = blue.BluePythonWeakRef(avatar)
    184             self.doll = weakref.ref(doll)
    185             self.factory = weakref.ref(factory)
    186             doll.overrideLod = LodQueue.magicLOD
    187 
    188             def MakeBuilder(lod):
    189                 lodBuilder = blue.BlueObjectBuilderPython()
    190                 lodBuilder.SetCreateMethod(lambda objectMarker, callingProxy: self.DoCreate(callingProxy, lod))
    191                 lodBuilder.SetSelectedHandler(lambda objectMarker, callingProxy: self.OnSelected(callingProxy, lod))
    192                 proxy = blue.BlueObjectProxy()
    193                 proxy.builder = lodBuilder
    194                 return proxy
    195 
    196             avatar.highDetailModel = MakeBuilder(0)
    197             avatar.mediumDetailModel = MakeBuilder(1)
    198             avatar.lowDetailModel = MakeBuilder(2)
    199             factory.AppendMeshesToVisualModel(avatar.visualModel, stub.meshes)
    200 
    201         def DoCreate(self, callingProxy, lod):
    202             if self.avatar.object is None:
    203                 return
    204             return self.avatar.object.visualModel
    205 
    206         def OnSelected(self, callingProxy, lod):
    207             doll = self.doll()
    208             factory = self.factory()
    209             avatar = self.avatar.object
    210             if doll is None or factory is None or avatar is None:
    211                 return
    212             if doll.overrideLod != lod:
    213                 if LodQueue.instance is None:
    214                     doll.overrideLod = lod
    215                     doll.Update(factory, avatar)
    216                 else:
    217                     LodQueue.instance.AddToQueue(self.avatar, self.doll, self.factory, lod)
    218 
    219     simpleBuilder = InPlaceBuilder(avatar, doll, factory, stub)
    220 
    221 
    222 def AbortAllLod(avatar):
    223     if avatar is None:
    224         return
    225     if avatar.highDetailModel is not None:
    226         avatar.highDetailModel.object = None
    227     if avatar.mediumDetailModel is not None:
    228         avatar.mediumDetailModel.object = None
    229     if avatar.lowDetailModel is not None:
    230         avatar.lowDetailModel.object = None