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