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

sprite.py (36641B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\primitives\sprite.py
      2 import logging
      3 import weakref
      4 from collections import Sequence
      5 import audio2
      6 import blue
      7 import eveexceptions
      8 import eveicon
      9 import trinity
     10 import uthread
     11 import videoplayer
     12 from carbon.common.script.util.timerstuff import AutoTimer
     13 from carbonui import uiconst
     14 from carbonui.primitives.base import Base
     15 from carbonui.primitives.message_bus.videoMessenger import VideoMessenger
     16 from carbonui.uicore import uicore
     17 from carbonui.util import colorblind
     18 from carbonui.util.dpi import reverse_scale_dpi
     19 GameWorld = None
     20 DEFAULTCOLOR = (1.0,
     21  1.0,
     22  1.0,
     23  1.0)
     24 logger = logging.getLogger(__name__)
     25 
     26 class VisibleBase(Base):
     27     __renderObject__ = None
     28     default_left = 0
     29     default_top = 0
     30     default_color = DEFAULTCOLOR
     31     default_opacity = None
     32     default_blendMode = trinity.TR2_SBM_BLEND
     33     default_outputMode = trinity.Tr2SpriteTarget.COLOR
     34     default_glowBrightness = 1.0
     35     default_depth = 0.0
     36     default_ignoreColorBlindMode = False
     37     _blendMode = None
     38     _color = None
     39     _depth = None
     40     _glowBrightness = None
     41     _outputMode = None
     42 
     43     def ApplyAttributes(self, attributes):
     44         super(VisibleBase, self).ApplyAttributes(attributes)
     45         self.ignoreColorBlindMode = attributes.get('ignoreColorBlindMode', self.default_ignoreColorBlindMode)
     46         self.initialColor = attributes.get('color', self.default_color)
     47         if self.initialColor not in (None, DEFAULTCOLOR):
     48             self.SetRGBA(*self.initialColor)
     49         self.blendMode = attributes.get('blendMode', self.default_blendMode)
     50         self.outputMode = attributes.get('outputMode', self.default_outputMode)
     51         self.glowBrightness = attributes.get('glowBrightness', self.default_glowBrightness)
     52         self.depth = attributes.get('depth', self.default_depth)
     53         opacity = attributes.get('opacity', self.default_opacity)
     54         if opacity is not None:
     55             self.opacity = opacity
     56 
     57     def Close(self):
     58         self._color = None
     59         Base.Close(self)
     60 
     61     @property
     62     def blendMode(self):
     63         return self._blendMode
     64 
     65     @blendMode.setter
     66     def blendMode(self, value):
     67         self._blendMode = value
     68         ro = self.renderObject
     69         if ro:
     70             ro.blendMode = value
     71 
     72     @property
     73     def outputMode(self):
     74         return self._outputMode
     75 
     76     @outputMode.setter
     77     def outputMode(self, value):
     78         self._outputMode = value
     79         if self.renderObject:
     80             self.renderObject.spriteTarget = value
     81 
     82     @property
     83     def glowBrightness(self):
     84         return self._glowBrightness
     85 
     86     @glowBrightness.setter
     87     def glowBrightness(self, value):
     88         self._glowBrightness = value
     89         if self.renderObject:
     90             self.renderObject.glowBrightness = value
     91 
     92     @property
     93     def color(self):
     94         self._InitializeColor()
     95         return self._color
     96 
     97     @color.setter
     98     def color(self, value):
     99         if isinstance(value, Sequence):
    100             if len(value) == 3:
    101                 self.SetRGB(*value)
    102             else:
    103                 self.SetRGBA(*value)
    104         elif isinstance(value, PyColor):
    105             self._color = value
    106             self._ApplyColor()
    107 
    108     @color.deleter
    109     def color(self):
    110         self._color = None
    111 
    112     def _InitializeColor(self):
    113         if self._color is None:
    114             self._color = PyColor(self)
    115             self._ApplyColor()
    116 
    117     @property
    118     def rgb(self):
    119         self._InitializeColor()
    120         return self._color.GetRGB()
    121 
    122     @rgb.setter
    123     def rgb(self, value):
    124         try:
    125             self.color.SetRGB(*value)
    126         except Exception:
    127             logger.exception('Invalid color: %s' % repr(value))
    128 
    129     @property
    130     def rgba(self):
    131         self._InitializeColor()
    132         return self._color.GetRGBA()
    133 
    134     @rgba.setter
    135     def rgba(self, value):
    136         try:
    137             self.color.SetRGBA(*value)
    138         except Exception:
    139             logger.exception('Invalid color: %s' % repr(value))
    140 
    141     def _ApplyColor(self):
    142         ro = self.renderObject
    143         if ro and self._color:
    144             ro.color = self.CheckReplaceColor(self._color.GetRGBA())
    145 
    146     @property
    147     def opacity(self):
    148         return self.color.a
    149 
    150     @opacity.setter
    151     def opacity(self, value):
    152         self.color.a = value
    153 
    154     @property
    155     def depth(self):
    156         return self._depth
    157 
    158     @depth.setter
    159     def depth(self, value):
    160         self._depth = value
    161         ro = self.renderObject
    162         if ro:
    163             ro.depth = value
    164 
    165     def SetRGB(self, *color):
    166         try:
    167             self.color.SetRGB(*color)
    168         except Exception:
    169             logger.exception('Invalid color: %s' % repr(color))
    170 
    171     def SetRGBA(self, *color):
    172         try:
    173             self.color.SetRGBA(*color)
    174         except Exception:
    175             logger.exception('Invalid color: %s' % repr(color))
    176 
    177     def CheckReplaceColor(self, color):
    178         if not self.ignoreColorBlindMode:
    179             color = colorblind.CheckReplaceColor(color)
    180         return color
    181 
    182     def GetRGB(self):
    183         return self.color.GetRGB()
    184 
    185     def GetRGBA(self):
    186         return self.color.GetRGBA()
    187 
    188     def SetAlpha(self, alpha):
    189         self.color.SetAlpha(alpha)
    190 
    191     def GetAlpha(self):
    192         return self.color.GetAlpha()
    193 
    194 
    195 class TexturedBase(VisibleBase):
    196     __renderObject__ = None
    197     default_noScale = 0
    198     default_texturePath = None
    199     default_textureSecondaryPath = None
    200     default_translationPrimary = (0.0, 0.0)
    201     default_translationSecodary = (0.0, 0.0)
    202     default_glowFactor = 0.0
    203     default_glowExpand = 0.0
    204     default_glowColor = (1, 1, 1, 1)
    205     default_shadowOffset = (0, 0)
    206     default_shadowColor = (0, 0, 0, 0.5)
    207     default_spriteEffect = trinity.TR2_SFX_COPY
    208     default_rotation = 0.0
    209     default_tileX = False
    210     default_tileY = False
    211     _glowColor = None
    212     _glowExpand = None
    213     _glowFactor = None
    214     _rectHeight = None
    215     _rectLeft = None
    216     _rectTop = None
    217     _rectWidth = None
    218     _shadowColor = None
    219     _shadowOffset = None
    220     _spriteEffect = None
    221     _texture = None
    222     _textureSecondary = None
    223 
    224     def ApplyAttributes(self, attributes):
    225         super(TexturedBase, self).ApplyAttributes(attributes)
    226         self.texture = trinity.Tr2Sprite2dTexture()
    227         texturePath = attributes.get('texturePath', self.default_texturePath)
    228         if texturePath:
    229             self.SetTexturePath(texturePath)
    230         secondaryPath = attributes.get('textureSecondaryPath', self.default_textureSecondaryPath)
    231         if secondaryPath:
    232             self.SetSecondaryTexturePath(secondaryPath)
    233         self.glowFactor = attributes.get('glowFactor', self.default_glowFactor)
    234         self.glowExpand = attributes.get('glowExpand', self.default_glowExpand)
    235         self.glowColor = attributes.get('glowColor', self.default_glowColor)
    236         self.shadowOffset = attributes.get('shadowOffset', self.default_shadowOffset)
    237         self.shadowColor = attributes.get('shadowColor', self.default_shadowColor)
    238         rectLeft = attributes.rectLeft
    239         if rectLeft:
    240             self.rectLeft = rectLeft
    241         rectTop = attributes.rectTop
    242         if rectTop:
    243             self.rectLeft = rectTop
    244         rectWidth = attributes.rectWidth
    245         if rectWidth:
    246             self.rectWidth = rectWidth
    247         rectHeight = attributes.rectHeight
    248         if rectHeight:
    249             self.rectHeight = rectHeight
    250         self.translationPrimary = attributes.get('translationPrimary', self.default_translationPrimary)
    251         self.translationSecondary = attributes.get('translationSecondary', self.default_translationSecodary)
    252         self.spriteEffect = attributes.get('spriteEffect', self.default_spriteEffect)
    253         self.rotation = attributes.get('rotation', self.default_rotation)
    254         self.tileX = attributes.get('tileX', self.default_tileX)
    255         self.tileY = attributes.get('tileY', self.default_tileY)
    256 
    257     def Close(self):
    258         self._texture = None
    259         self._textureSecondary = None
    260         super(TexturedBase, self).Close()
    261 
    262     @property
    263     def spriteEffect(self):
    264         return self._spriteEffect
    265 
    266     @spriteEffect.setter
    267     def spriteEffect(self, value):
    268         self._spriteEffect = value
    269         ro = self.renderObject
    270         if ro and hasattr(ro, 'spriteEffect'):
    271             ro.spriteEffect = value
    272 
    273     @property
    274     def texture(self):
    275         return self._texture
    276 
    277     @texture.setter
    278     def texture(self, value):
    279         self._texture = value
    280         ro = self.renderObject
    281         if ro:
    282             ro.texturePrimary = self._texture
    283 
    284     @property
    285     def textureSecondary(self):
    286         return self._textureSecondary
    287 
    288     @textureSecondary.setter
    289     def textureSecondary(self, value):
    290         self._textureSecondary = value
    291         ro = self.renderObject
    292         if ro and value is not None:
    293             ro.textureSecondary = value
    294 
    295     @property
    296     def rectLeft(self):
    297         return self._rectLeft
    298 
    299     @rectLeft.setter
    300     def rectLeft(self, value):
    301         self._rectLeft = value
    302         ro = self.renderObject
    303         if ro and ro.texturePrimary:
    304             ro.texturePrimary.srcX = value
    305 
    306     @property
    307     def rectTop(self):
    308         return self._rectTop
    309 
    310     @rectTop.setter
    311     def rectTop(self, value):
    312         self._rectTop = value
    313         ro = self.renderObject
    314         if ro and ro.texturePrimary:
    315             ro.texturePrimary.srcY = value
    316 
    317     @property
    318     def rectWidth(self):
    319         return self._rectWidth
    320 
    321     @rectWidth.setter
    322     def rectWidth(self, value):
    323         self._rectWidth = value
    324         ro = self.renderObject
    325         if ro and ro.texturePrimary:
    326             ro.texturePrimary.srcWidth = value
    327 
    328     @property
    329     def rectHeight(self):
    330         return self._rectHeight
    331 
    332     @rectHeight.setter
    333     def rectHeight(self, value):
    334         self._rectHeight = value
    335         ro = self.renderObject
    336         if ro and ro.texturePrimary:
    337             ro.texturePrimary.srcHeight = value
    338 
    339     @property
    340     def rectSecondary(self):
    341         if self.textureSecondary:
    342             return (self.textureSecondary.srcX,
    343              self.textureSecondary.srcY,
    344              self.textureSecondary.srcWidth,
    345              self.textureSecondary.srcHeight)
    346 
    347     @rectSecondary.setter
    348     def rectSecondary(self, value):
    349         if self.textureSecondary:
    350             self.textureSecondary.srcX, self.textureSecondary.srcY, self.textureSecondary.srcWidth, self.textureSecondary.srcHeight = value
    351 
    352     @property
    353     def translationPrimary(self):
    354         if self.texture:
    355             return self.texture.translation
    356 
    357     @translationPrimary.setter
    358     def translationPrimary(self, value):
    359         if self.texture:
    360             self.texture.translation = value
    361             if value != (0, 0):
    362                 self.texture.useTransform = True
    363                 self._EnableStandAloneTexture(self.texture)
    364 
    365     @property
    366     def translationSecondary(self):
    367         if self.textureSecondary:
    368             return self.textureSecondary.translation
    369 
    370     @translationSecondary.setter
    371     def translationSecondary(self, value):
    372         if self.textureSecondary:
    373             self.textureSecondary.translation = value
    374             if value != (0, 0):
    375                 self.__EnableSecondaryTransform()
    376 
    377     @property
    378     def rotationSecondary(self):
    379         if self.textureSecondary:
    380             return self.textureSecondary.rotation
    381 
    382     @rotationSecondary.setter
    383     def rotationSecondary(self, value):
    384         if self.textureSecondary:
    385             self.textureSecondary.rotation = value
    386             if value != 0.0:
    387                 self.__EnableSecondaryTransform()
    388 
    389     @property
    390     def scaleSecondary(self):
    391         if self.textureSecondary:
    392             return self.textureSecondary.scale
    393 
    394     @scaleSecondary.setter
    395     def scaleSecondary(self, value):
    396         if self.textureSecondary:
    397             self.textureSecondary.scale = value
    398             if value != (1.0, 1.0):
    399                 self.__EnableSecondaryTransform()
    400 
    401     @property
    402     def scalingCenterSecondary(self):
    403         if self.textureSecondary:
    404             return self.textureSecondary.scalingCenter
    405 
    406     @scalingCenterSecondary.setter
    407     def scalingCenterSecondary(self, value):
    408         if self.textureSecondary:
    409             self.textureSecondary.scalingCenter = value
    410 
    411     @property
    412     def glowFactor(self):
    413         return self._glowFactor
    414 
    415     @glowFactor.setter
    416     def glowFactor(self, value):
    417         self._glowFactor = value
    418         ro = self.renderObject
    419         if ro:
    420             ro.glowFactor = value
    421 
    422     @property
    423     def glowExpand(self):
    424         return self._glowExpand
    425 
    426     @glowExpand.setter
    427     def glowExpand(self, value):
    428         self._glowExpand = value
    429         ro = self.renderObject
    430         if ro:
    431             ro.glowExpand = value
    432 
    433     @property
    434     def glowColor(self):
    435         return self._glowColor
    436 
    437     @glowColor.setter
    438     def glowColor(self, value):
    439         self._glowColor = value
    440         ro = self.renderObject
    441         if ro:
    442             ro.glowColor = value
    443 
    444     @property
    445     def shadowOffset(self):
    446         return self._shadowOffset
    447 
    448     @shadowOffset.setter
    449     def shadowOffset(self, value):
    450         self._shadowOffset = value
    451         ro = self.renderObject
    452         if ro:
    453             ro.shadowOffset = value
    454 
    455     @property
    456     def shadowColor(self):
    457         return self._shadowColor
    458 
    459     @shadowColor.setter
    460     def shadowColor(self, value):
    461         self._shadowColor = value
    462         ro = self.renderObject
    463         if ro:
    464             ro.shadowColor = value
    465 
    466     @property
    467     def rotation(self):
    468         if self.texture:
    469             return self.texture.rotation
    470         else:
    471             return 0
    472 
    473     @rotation.setter
    474     def rotation(self, value):
    475         if self.texture:
    476             self.texture.rotation = value
    477             if value != 0.0:
    478                 self.texture.useTransform = True
    479                 self._EnableStandAloneTexture(self.texture)
    480 
    481     @property
    482     def scale(self):
    483         if self.texture:
    484             return self.texture.scale
    485 
    486     @scale.setter
    487     def scale(self, value):
    488         if self.texture:
    489             self.texture.scale = value
    490             if value != (1.0, 1.0):
    491                 self.texture.useTransform = True
    492                 self._EnableStandAloneTexture(self.texture)
    493 
    494     @property
    495     def scalingCenter(self):
    496         if self.texture:
    497             return self.texture.scalingCenter
    498 
    499     @scalingCenter.setter
    500     def scalingCenter(self, value):
    501         if self.texture:
    502             self.texture.scalingCenter = value
    503 
    504     @property
    505     def tileX(self):
    506         if self.texture:
    507             return self.texture.tileX
    508 
    509     @tileX.setter
    510     def tileX(self, value):
    511         if self.texture:
    512             self.texture.tileX = value
    513             if value:
    514                 self.texture.useTransform = True
    515                 self._EnableStandAloneTexture(self.texture)
    516 
    517     @property
    518     def tileY(self):
    519         if self.texture:
    520             return self.texture.tileY
    521 
    522     @tileY.setter
    523     def tileY(self, value):
    524         if self.texture:
    525             self.texture.tileY = value
    526             if value:
    527                 self.texture.useTransform = True
    528                 self._EnableStandAloneTexture(self.texture)
    529 
    530     @property
    531     def tileXSecondary(self):
    532         if self.textureSecondary:
    533             return self.textureSecondary.tileX
    534 
    535     @tileXSecondary.setter
    536     def tileXSecondary(self, value):
    537         if self.textureSecondary:
    538             self.textureSecondary.tileX = value
    539             if value:
    540                 self.textureSecondary.useTransform = True
    541                 self._EnableStandAloneTexture(self.textureSecondary)
    542 
    543     @property
    544     def tileYSecondary(self):
    545         if self.textureSecondary:
    546             return self.textureSecondary.tileY
    547 
    548     @tileYSecondary.setter
    549     def tileYSecondary(self, value):
    550         if self.textureSecondary:
    551             self.textureSecondary.tileY = value
    552             if value:
    553                 self.textureSecondary.useTransform = True
    554                 self._EnableStandAloneTexture(self.textureSecondary)
    555 
    556     def _EnableStandAloneTexture(self, texture):
    557         if getattr(texture, 'atlasTexture', None) is not None:
    558             texture.atlasTexture.isStandAlone = True
    559 
    560     def __EnableSecondaryTransform(self):
    561         self.textureSecondary.useTransform = True
    562         self._EnableStandAloneTexture(self.textureSecondary)
    563 
    564     def ReloadTexture(self):
    565         if self.texture:
    566             if self.texture.atlasTexture:
    567                 self.texture.atlasTexture.Reload()
    568 
    569     def ReloadSecondaryTexture(self):
    570         if self.textureSecondary:
    571             if self.textureSecondary.atlasTexture:
    572                 self.textureSecondary.atlasTexture.Reload()
    573 
    574     def SetTexturePath(self, texturePath):
    575         if self.texture:
    576             newPath = str(texturePath or '')
    577             if newPath != self.texture.resPath:
    578                 self.texture.resPath = newPath
    579 
    580     LoadTexture = SetTexturePath
    581 
    582     def GetTexturePath(self):
    583         if self.texture:
    584             return self.texture.resPath
    585 
    586     texturePath = property(GetTexturePath, SetTexturePath)
    587 
    588     def SetSecondaryTexturePath(self, texturePath):
    589         if not self.textureSecondary:
    590             self.textureSecondary = trinity.Tr2Sprite2dTexture()
    591         self.textureSecondary.resPath = str(texturePath or '')
    592 
    593     def GetSecondaryTexturePath(self):
    594         if self.textureSecondary:
    595             return self.textureSecondary.resPath
    596 
    597     def SetRect(self, rectLeft, rectTop, rectWidth, rectHeight):
    598         self.rectLeft = rectLeft
    599         self.rectTop = rectTop
    600         self.rectWidth = rectWidth
    601         self.rectHeight = rectHeight
    602 
    603     def LoadIcon(self, iconNo, ignoreSize = False):
    604         if self.destroyed:
    605             return
    606         if iconNo.startswith('res:') or iconNo.startswith('cache:'):
    607             self.SetTexturePath(iconNo)
    608             return
    609         if iconNo.startswith('ui_'):
    610             root, sheetNo, iconSize, icon = iconNo.split('_')
    611             resPath = 'res:/ui/texture/icons/%s_%s_%s.png' % (int(sheetNo), int(iconSize), int(icon))
    612             iconSize = int(iconSize)
    613             self.SetTexturePath(resPath)
    614             if not ignoreSize and self.GetAlign() != uiconst.TOALL and self.texture.atlasTexture:
    615                 self.width = iconSize
    616                 self.height = iconSize
    617             return
    618         return iconNo
    619 
    620 
    621 class Sprite(TexturedBase):
    622     __guid__ = 'uiprimitives.Sprite'
    623     __renderObject__ = trinity.Tr2Sprite2d
    624     isDragObject = True
    625     default_noScale = 0
    626     default_left = 0
    627     default_top = 0
    628     default_width = 0
    629     default_height = 0
    630     default_pickRadius = 0
    631     default_saturation = 1.0
    632     default_effectOpacity = 1.0
    633     default_useSizeFromTexture = False
    634     _sprite = None
    635     _effectOpacity = None
    636     _pickRadius = None
    637     _saturation = None
    638     _texturePath = None
    639     _useSizeFromTexture = None
    640 
    641     def ApplyAttributes(self, attributes):
    642         super(Sprite, self).ApplyAttributes(attributes)
    643         self.pickRadius = attributes.get('pickRadius', self.default_pickRadius)
    644         self.saturation = attributes.get('saturation', self.default_saturation)
    645         self.effectOpacity = attributes.get('effectOpacity', self.default_effectOpacity)
    646         self.useSizeFromTexture = attributes.get('useSizeFromTexture', self.default_useSizeFromTexture)
    647 
    648     @property
    649     def pickRadius(self):
    650         return self._pickRadius
    651 
    652     @pickRadius.setter
    653     def pickRadius(self, value):
    654         self._pickRadius = value
    655         ro = self.renderObject
    656         if ro and hasattr(ro, 'pickRadius'):
    657             if value < 0:
    658                 ro.pickRadius = value
    659             else:
    660                 ro.pickRadius = uicore.ScaleDpi(value) or 0.0
    661 
    662     @property
    663     def useSizeFromTexture(self):
    664         return self._useSizeFromTexture
    665 
    666     @useSizeFromTexture.setter
    667     def useSizeFromTexture(self, value):
    668         self._useSizeFromTexture = value
    669         if self.renderObject:
    670             self.renderObject.useSizeFromTexture = value
    671 
    672     @property
    673     def saturation(self):
    674         return self._saturation
    675 
    676     @saturation.setter
    677     def saturation(self, value):
    678         self._saturation = value
    679         ro = self.renderObject
    680         if ro:
    681             ro.saturation = value or 0.0
    682 
    683     @property
    684     def effectOpacity(self):
    685         return self._effectOpacity
    686 
    687     @effectOpacity.setter
    688     def effectOpacity(self, value):
    689         self._effectOpacity = value
    690         ro = self.renderObject
    691         if ro:
    692             ro.effectOpacity = value or 0.0
    693 
    694     def SetTexturePath(self, texturePath):
    695         self._texturePath = texturePath
    696         if isinstance(texturePath, eveicon.IconData):
    697             texturePath = self._resolve_icon_data_texture(texturePath)
    698         super(Sprite, self).SetTexturePath(texturePath)
    699 
    700     LoadTexture = SetTexturePath
    701     texturePath = property(TexturedBase.GetTexturePath, SetTexturePath)
    702 
    703     def _resolve_icon_data_texture(self, icon_data):
    704         size = max(reverse_scale_dpi(self.displayWidth), reverse_scale_dpi(self.displayHeight))
    705         return icon_data.resolve(size)
    706 
    707     def UpdateAlignment(self, budgetLeft = 0, budgetTop = 0, budgetWidth = 0, budgetHeight = 0, updateChildrenOnly = False):
    708         result_budget_left, result_budget_top, result_budget_width, result_budget_height, size_changed = super(Sprite, self).UpdateAlignment(budgetLeft, budgetTop, budgetWidth, budgetHeight, updateChildrenOnly)
    709         if size_changed and isinstance(self._texturePath, eveicon.IconData):
    710             new_texture_path = self._resolve_icon_data_texture(self._texturePath)
    711             super(Sprite, self).SetTexturePath(new_texture_path)
    712         return (result_budget_left,
    713          result_budget_top,
    714          result_budget_width,
    715          result_budget_height,
    716          size_changed)
    717 
    718 
    719 class RenderTargetSprite(Sprite):
    720     __guid__ = 'uiprimitives.RenderTargetSprite'
    721     __renderObject__ = trinity.Tr2Sprite2d
    722     default_spriteEffect = trinity.TR2_SFX_NOALPHA
    723 
    724     def ApplyAttributes(self, attributes):
    725         Sprite.ApplyAttributes(self, attributes)
    726         self._viewport_width = attributes.viewportWidth
    727         self._viewport_height = attributes.viewportHeight
    728         RO = self.GetRenderObject()
    729         self._construct_render_target()
    730         if 'pos' in attributes:
    731             default_pos = (self.default_left,
    732              self.default_top,
    733              self.default_width,
    734              self.default_height)
    735             pos = attributes.get('pos', default_pos)
    736             RO.displayX, RO.displayY, RO.displayWidth, RO.displayHeight = pos
    737 
    738     def _construct_render_target(self):
    739         self._texture_res = trinity.TriTextureRes()
    740         self.render_target = trinity.Tr2RenderTarget(self._viewport_width, self._viewport_height, 1, trinity.PIXEL_FORMAT.B8G8R8X8_UNORM)
    741         self._texture_res.CreateEmptyTexture(self.width, self.height, 1, trinity.PIXEL_FORMAT.B8G8R8A8_UNORM)
    742         self._texture_res.SetFromRenderTarget(self.render_target)
    743         self.texture.atlasTexture = trinity.Tr2AtlasTexture()
    744         self.texture.atlasTexture.textureRes = self._texture_res
    745 
    746     def Close(self, *args, **kwds):
    747         self._texture_res = None
    748         self.render_target = None
    749         super(RenderTargetSprite, self).Close()
    750 
    751 
    752 class StreamingVideoSprite(Sprite):
    753     __guid__ = 'uiprimitives.StreamingVideoSprite'
    754     __renderObject__ = trinity.Tr2Sprite2d
    755     __notifyevents__ = ['OnAudioActivated', 'OnAudioDeactivated']
    756     default_disableAudio = False
    757     default_videoPath = ''
    758     default_videoLoop = False
    759     default_videoAutoPlay = True
    760     default_muteAudio = False
    761     default_spriteEffect = trinity.TR2_SFX_NOALPHA
    762     default_sendAnalytics = None
    763 
    764     def ApplyAttributes(self, attributes):
    765         Sprite.ApplyAttributes(self, attributes)
    766         sm.RegisterNotify(self)
    767         self._sendAnalytics = attributes.get('sendAnalytics', self.default_sendAnalytics)
    768         self.textureRes = trinity.TriTextureRes()
    769         self.texture = trinity.Tr2Sprite2dTexture()
    770         self.player = None
    771         self.path = None
    772         self.audioTrack = 0
    773         self.videoLoop = False
    774         self.emitter = None
    775         self._oldPosition = 0
    776         self.loopChecker = None
    777         self._updateStep = None
    778         self._isFetchingFile = False
    779         RO = self.GetRenderObject()
    780         self.disableAudio = attributes.get('disableAudio', self.default_disableAudio)
    781         self._positionComponent = attributes.get('positionComponent', None)
    782         self.positionComponent = None
    783         self._auto_play = attributes.get('videoAutoPlay', self.default_videoAutoPlay)
    784         if 'videoPath' in attributes and attributes['videoPath']:
    785             self.SetVideoPath(attributes['videoPath'], attributes.get('audioTrack', 0), attributes.get('videoLoop', self.default_videoLoop))
    786         if 'pos' in attributes:
    787             default_pos = (self.default_left,
    788              self.default_top,
    789              self.default_width,
    790              self.default_height)
    791             pos = attributes.get('pos', default_pos)
    792             RO.displayX, RO.displayY, RO.displayWidth, RO.displayHeight = pos
    793 
    794     def Close(self, *args, **kwds):
    795         self._DestroyVideo()
    796         super(StreamingVideoSprite, self).Close()
    797 
    798     def OnVideoSizeAvailable(self, width, height):
    799         pass
    800 
    801     def OnVideoDurationAvailable(self):
    802         pass
    803 
    804     def OnVideoFinished(self):
    805         pass
    806 
    807     def _OnCreateTextures(self, player, width, height):
    808         if not self.texture:
    809             return
    810         try:
    811             self.textureRes = trinity.TriTextureRes()
    812             self.textureRes.CreateEmptyTexture(width, height, 1, trinity.PIXEL_FORMAT.B8G8R8A8_UNORM)
    813             player.bgra_texture = self.textureRes
    814             self.texture.atlasTexture = trinity.Tr2AtlasTexture()
    815             self.texture.atlasTexture.textureRes = self.textureRes
    816         except Exception:
    817             logging.exception('Exception in VideoPlayer.on_create_textures')
    818 
    819     def _OnVideoStateChange(self, player):
    820         try:
    821             logging.debug('Video player state changed to %s', videoplayer.State.GetNameFromValue(player.state))
    822             if player.state == videoplayer.State.INITIAL_BUFFERING:
    823                 info = self.player.get_video_info()
    824                 self.OnVideoSizeAvailable(info['width'], info['height'])
    825                 self.OnVideoDurationAvailable()
    826                 self.StartLoopChecker()
    827             elif player.state == videoplayer.State.DONE:
    828                 self._LogVideoProtoEventStopped(played_to=int(self.GetPositionRatioInVideo() * 100))
    829                 self.OnVideoFinished()
    830                 self.StopLoopChecker()
    831         except Exception:
    832             logging.exception('Exception in VideoPlayer.on_state_change')
    833 
    834     def _OnVideoError(self, *args):
    835         try:
    836             self.player.validate()
    837         except RuntimeError:
    838             logging.exception('Video player error')
    839 
    840     def _DestroyVideo(self):
    841         self._LogVideoProtoEventStopped(played_to=int(self.GetPositionRatioInVideo() * 100))
    842         if self.positionComponent:
    843             self.positionComponent.UnRegisterPlacementObserverWrapper(self.positionObserver)
    844             self.positionComponent = None
    845             self.positionObserver = None
    846         self.emitter = None
    847         self.player = None
    848         self._updateStep = None
    849         self.textureRes = trinity.TriTextureRes()
    850 
    851     @eveexceptions.EatsExceptions('protoClientLogs')
    852     def _LogVideoProtoEvent(self, event_class, *args, **kwargs):
    853         if self._sendAnalytics and self.path:
    854             proto_event = event_class(hierarchy_path=self.analyticContext, video_path=self.path, *args, **kwargs)
    855             sm.GetService('publicGatewaySvc').publish_event(proto_event)
    856 
    857     @eveexceptions.EatsExceptions('protoClientLogs')
    858     def _LogVideoProtoEventStarted(self):
    859         if self._sendAnalytics and self.path:
    860             message_bus = VideoMessenger(sm.GetService('publicGatewaySvc'))
    861             message_bus.video_started(hierarchy_path=self.analyticContext, video_path=self.path)
    862 
    863     @eveexceptions.EatsExceptions('protoClientLogs')
    864     def _LogVideoProtoEventLooped(self):
    865         if self._sendAnalytics and self.path:
    866             message_bus = VideoMessenger(sm.GetService('publicGatewaySvc'))
    867             message_bus.video_looped(hierarchy_path=self.analyticContext, video_path=self.path)
    868 
    869     @eveexceptions.EatsExceptions('protoClientLogs')
    870     def _LogVideoProtoEventStopped(self, played_to):
    871         if self._sendAnalytics and self.path:
    872             message_bus = VideoMessenger(sm.GetService('publicGatewaySvc'))
    873             message_bus.video_stopped(hierarchy_path=self.analyticContext, video_path=self.path, played_to=played_to)
    874 
    875     @eveexceptions.EatsExceptions('protoClientLogs')
    876     def _LogVideoProtoEventSeeked(self, new_position):
    877         if self._sendAnalytics and self.path:
    878             message_bus = VideoMessenger(sm.GetService('publicGatewaySvc'))
    879             message_bus.video_seeked(hierarchy_path=self.analyticContext, video_path=self.path, new_position=new_position)
    880 
    881     def OnAudioActivated(self):
    882         if self.path and not self._isFetchingFile:
    883             self.SetVideoPath(self.path, self.audioTrack, self.videoLoop)
    884 
    885     def OnAudioDeactivated(self):
    886         if self.path and not self._isFetchingFile:
    887             self.SetVideoPath(self.path, self.audioTrack, self.videoLoop)
    888 
    889     def SetPositionComponent(self, positionComponent):
    890         if self.emitter and positionComponent and GameWorld:
    891             self.positionObserver = GameWorld.PlacementObserverWrapper(self.emitter)
    892             positionComponent.RegisterPlacementObserverWrapper(self.positionObserver)
    893             return positionComponent
    894 
    895     def GetVideoSize(self):
    896         try:
    897             info = self.player.get_video_info()
    898             return (info['width'], info['height'])
    899         except (AttributeError, videoplayer.VideoPlayerError):
    900             pass
    901 
    902     def SetVideoPath(self, path, audioTrack = 0, videoLoop = False):
    903         self._DestroyVideo()
    904         self.path = path
    905         self.audioTrack = audioTrack
    906         self.videoLoop = videoLoop
    907 
    908         def prefetch():
    909             blue.paths.GetFileContentsWithYield(path)
    910             if self._isFetchingFile and path == self.path:
    911                 self._isFetchingFile = False
    912                 self.SetVideoPath(path, audioTrack, videoLoop)
    913 
    914         if path.lower().startswith('res:/'):
    915             if blue.remoteFileCache.FileExists(path):
    916                 if not blue.paths.FileExistsLocally(path):
    917                     self._isFetchingFile = True
    918                     uthread.new(prefetch)
    919                     return
    920         if not self.disableAudio:
    921             is3D = self._positionComponent is not None
    922             self.positionComponent = self.SetPositionComponent(self._positionComponent)
    923         if path.lower().startswith('res:/') or path.find(':') < 2:
    924             stream = blue.paths.open(path)
    925         else:
    926             stream = blue.BlueNetworkStream(unicode(path).encode('utf-8'))
    927         if uicore.audioHandler.active and not self.disableAudio:
    928             inputMgr = audio2.AudioInputMgr()
    929             sink = videoplayer.WwiseAudioSink(inputMgr)
    930         else:
    931             sink = None
    932         self.player = videoplayer.VideoPlayer(stream, sink, audioTrack, videoLoop)
    933         self.player.on_state_change = self._OnVideoStateChange
    934         self.player.on_create_textures = self._OnCreateTextures
    935         self.player.on_error = self._OnVideoError
    936         if not self._auto_play:
    937             self.player.pause()
    938             self.player.seek(0)
    939         self._LogVideoProtoEventStarted()
    940 
    941     def StartLoopChecker(self):
    942         self.loopChecker = AutoTimer(1, self.HasLooped)
    943 
    944     def StopLoopChecker(self):
    945         if not self.loopChecker:
    946             return
    947         self._oldPosition = 0
    948         self.loopChecker.KillTimer()
    949 
    950     def Play(self):
    951         if self.player:
    952             self.player.resume()
    953             self.StartLoopChecker()
    954 
    955     def Pause(self):
    956         if self.player:
    957             self.player.pause()
    958             self.StopLoopChecker()
    959 
    960     def MuteAudio(self):
    961         try:
    962             self.player.audio_sink.volume = 0
    963         except AttributeError:
    964             pass
    965 
    966     def UnmuteAudio(self):
    967         try:
    968             self.player.audio_sink.volume = 1.0
    969         except AttributeError:
    970             pass
    971 
    972     def GetVolume(self):
    973         try:
    974             return self.player.audio_sink.volume
    975         except AttributeError:
    976             return 1
    977 
    978     def SetVolume(self, volume):
    979         try:
    980             self.player.audio_sink.volume = volume
    981         except AttributeError:
    982             pass
    983 
    984     def Seek(self, nanoseconds):
    985         self.StopLoopChecker()
    986         try:
    987             self.player.seek(nanoseconds)
    988         except AttributeError:
    989             pass
    990         else:
    991             isMouseDown = uicore.uilib.leftbtn
    992             if not isMouseDown:
    993                 self._LogVideoProtoEventSeeked(new_position=int(self.GetPositionRatioInVideo() * 100))
    994             self.StartLoopChecker()
    995 
    996     def GetPositionRatioInVideo(self):
    997         if not self.mediaTime or not self.duration:
    998             return 0
    999         secondsInNano = 1000000
   1000         duration = float((self.duration or 1) / secondsInNano)
   1001         if duration == 0:
   1002             duration = 1
   1003         try:
   1004             new_position = min(float((self.mediaTime % self.duration or 0) / secondsInNano) / duration, 1)
   1005         except TypeError:
   1006             return 0
   1007 
   1008         return new_position
   1009 
   1010     def HasLooped(self):
   1011         if self.player and self.player.duration:
   1012             time = self.player.media_time % self.player.duration or 0
   1013             if time and time < self._oldPosition:
   1014                 self._LogVideoProtoEventLooped()
   1015             self._oldPosition = time
   1016         return False
   1017 
   1018     @property
   1019     def isMuted(self):
   1020         try:
   1021             return self.player.audio_sink.volume == 0
   1022         except AttributeError:
   1023             return None
   1024 
   1025     @property
   1026     def isPaused(self):
   1027         if self.player:
   1028             return self.player.is_paused
   1029 
   1030     @property
   1031     def isFinished(self):
   1032         if self.destroyed:
   1033             return True
   1034         if self._isFetchingFile:
   1035             return False
   1036         if self.player:
   1037             return self.player.state == videoplayer.State.DONE
   1038 
   1039     @property
   1040     def mediaTime(self):
   1041         if self.player:
   1042             return self.player.media_time
   1043 
   1044     @property
   1045     def duration(self):
   1046         if self.player:
   1047             return self.player.duration
   1048 
   1049     @property
   1050     def downloadedTime(self):
   1051         if self.player:
   1052             return self.player.downloaded_media_time
   1053 
   1054 
   1055 class PyColor(object):
   1056 
   1057     def __init__(self, owner, r = 1.0, g = 1.0, b = 1.0, a = 1.0):
   1058         self.owner = weakref.ref(owner)
   1059         self._r = r
   1060         self._g = g
   1061         self._b = b
   1062         self._a = a
   1063 
   1064     def __len__(self):
   1065         return 4
   1066 
   1067     def __getitem__(self, index):
   1068         components = (self.r,
   1069          self.g,
   1070          self.b,
   1071          self.a)
   1072         if isinstance(index, slice):
   1073             return components[index]
   1074         if isinstance(index, int):
   1075             return components[index]
   1076         raise TypeError('Index must be an integer or a slice.')
   1077 
   1078     def UpdateOwner(self):
   1079         owner = self.owner()
   1080         owner._ApplyColor()
   1081 
   1082     @property
   1083     def r(self):
   1084         return self._r
   1085 
   1086     @r.setter
   1087     def r(self, value):
   1088         self._r = value
   1089         self.UpdateOwner()
   1090 
   1091     @property
   1092     def g(self):
   1093         return self._g
   1094 
   1095     @g.setter
   1096     def g(self, value):
   1097         self._g = value
   1098         self.UpdateOwner()
   1099 
   1100     @property
   1101     def b(self):
   1102         return self._b
   1103 
   1104     @b.setter
   1105     def b(self, value):
   1106         self._b = value
   1107         self.UpdateOwner()
   1108 
   1109     @property
   1110     def a(self):
   1111         return self._a
   1112 
   1113     @a.setter
   1114     def a(self, value):
   1115         self._a = value
   1116         self.UpdateOwner()
   1117 
   1118     def SetRGB(self, r, g, b):
   1119         self._r = r
   1120         self._g = g
   1121         self._b = b
   1122         self.UpdateOwner()
   1123 
   1124     def SetRGBA(self, r, g, b, a = 1.0):
   1125         self._r = r
   1126         self._g = g
   1127         self._b = b
   1128         self._a = a
   1129         self.UpdateOwner()
   1130 
   1131     def GetRGB(self):
   1132         return (self.r, self.g, self.b)
   1133 
   1134     def GetRGBA(self):
   1135         return (self.r,
   1136          self.g,
   1137          self.b,
   1138          self.a)
   1139 
   1140     def SetAlpha(self, a):
   1141         self.a = a
   1142 
   1143     def GetAlpha(self):
   1144         return self.a
   1145 
   1146     def GetHSV(self):
   1147         return trinity.TriColor(*self.GetRGBA()).GetHSV()
   1148 
   1149     def SetHSV(self, h, s, v):
   1150         c = trinity.TriColor()
   1151         c.SetHSV(h, s, v)
   1152         self.SetRGB(c.r, c.g, c.b)
   1153 
   1154     def GetBrightness(self):
   1155         return (self.r + self.g + self.b) / 3.0