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

countdownTimer.py (11253B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\countdownTimer.py
      2 from math import pi
      3 from carbonui.primitives import container
      4 from carbonui.primitives import transform
      5 from carbonui.primitives import sprite
      6 from carbonui import const as uiconst
      7 import uthread
      8 import blue
      9 import trinity
     10 from carbonui.primitives.transform import Transform
     11 from carbonui.uicore import uicore
     12 ALPHA_EMPTY = 0.2
     13 BLINK_BEFORE_DONE_TIME = const.SEC * 5
     14 REWIND_SPEED = 500
     15 TEXT_OFFSET = -17
     16 TIMER_RUNNING_OUT_NO_ANIMATION = 1
     17 TIMER_RUNNING_OUT_BLINK_ALL = 2
     18 TIMER_RUNNING_OUT_BLINK_ICON = 4
     19 
     20 def FormatCounterTime(timeLeft):
     21     timeLeft = max(0, timeLeft / const.SEC)
     22     minutes, seconds = divmod(timeLeft, 60)
     23     hours, minutes = divmod(minutes, 60)
     24     if hours > 0:
     25         return '%02d:%02d:%02d' % (hours, minutes, seconds)
     26     else:
     27         return '%02d:%02d' % (minutes, seconds)
     28 
     29 
     30 class CountdownTimer(Transform):
     31     default_width = 32
     32     default_height = 32
     33     default_align = uiconst.CENTER
     34     default_state = uiconst.UI_DISABLED
     35     default_scalingCenter = (0.5, 0.5)
     36     sound_loop_play_event = None
     37     sound_loop_stop_event = None
     38 
     39     def ApplyAttributes(self, attributes):
     40         Transform.ApplyAttributes(self, attributes)
     41         self.SetupVariables(attributes)
     42         self.CreateMainContentLayout()
     43         self.CreateIconLayout(attributes)
     44         self.CreateTimerCycleLayout()
     45         self.SetTimerColor(self.color)
     46         self.SetExpiryTime(None, 0.0)
     47         self.PlayEntryAnimation()
     48 
     49     def SetupVariables(self, attributes):
     50         self.countsDown = attributes.Get('countsDown', False)
     51         self.GetTime = attributes.Get('timerFunc', blue.os.GetSimTime)
     52         self.color = attributes.Get('color', (1, 1, 1, 1))
     53         self.maxTimeout = attributes.maxTimeout
     54         self.resetAudioEvent = attributes.Get('resetAudioEvent', None)
     55         self.endingAudioEvent = attributes.Get('endingAudioEvent', None)
     56         self.timerRunningOutAnimation = attributes.Get('timerRunningOutAnimation', TIMER_RUNNING_OUT_BLINK_ICON)
     57         self.icon = None
     58         self.iconBlink = None
     59         self.rewind = False
     60         self.paused = None
     61         self.ratio = 1.0
     62         self.animationThread = None
     63         self.activeAnimationCurves = None
     64 
     65     def CreateMainContentLayout(self):
     66         self.content = transform.Transform(parent=self, name='content', align=uiconst.CENTER, pos=(0, 0, 32, 32), state=uiconst.UI_NORMAL)
     67         self.content.OnMouseEnter = self.OnMouseEnter
     68 
     69     def CreateIconLayout(self, attributes):
     70         if attributes.icon:
     71             self.iconTransform = transform.Transform(parent=self.content, name='iconTransform', align=uiconst.CENTER, width=16, height=16, state=uiconst.UI_DISABLED)
     72             self.icon = sprite.Sprite(name='icon', parent=self.iconTransform, pos=(0, 0, 16, 16), texturePath=attributes.icon, state=uiconst.UI_DISABLED, align=uiconst.CENTER)
     73             self.iconTransform.scalingCenter = (0.5, 0.5)
     74         else:
     75             self.icon = None
     76 
     77     def CreateTimerCycleLayout(self):
     78         self.circleSprite = sprite.Sprite(name='icon', parent=self.content, pos=(0, 0, 32, 32), texturePath='res:/UI/Texture/Crimewatch/Crimewatch_TimerCircle.png', state=uiconst.UI_DISABLED, align=uiconst.CENTER, opacity=ALPHA_EMPTY)
     79         self.halfCircleSprite = sprite.Sprite(name='half_circle', parent=self.content, width=32, height=32, rotation=0 if self.countsDown else pi, texturePath='res:/UI/Texture/Crimewatch/Crimewatch_TimerHalfCircle.png', state=uiconst.UI_DISABLED)
     80         self.clipContainer = container.Container(name='clipper', parent=self.content, width=16, align=uiconst.TOLEFT, clipChildren=True, state=uiconst.UI_DISABLED)
     81         self.cycleContainer = transform.Transform(name='cycle_container', parent=self.clipContainer, width=32, height=32)
     82         self.cycleSprite = sprite.Sprite(name='cycle_half_circle', parent=self.cycleContainer, width=32, height=32, rotation=pi if self.countsDown else 0, texturePath='res:/UI/Texture/Crimewatch/Crimewatch_TimerHalfCircle.png', state=uiconst.UI_DISABLED)
     83         self.pointerContainer = transform.Transform(name='pointer_container', parent=self.content, width=32, height=32, idx=0)
     84         self.pointerClipper = container.Container(parent=self.pointerContainer, pos=(9, -10, 15, 13), clipChildren=True, align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED)
     85         self.pointerSprite = sprite.Sprite(name='cycle_pointer', parent=self.pointerClipper, pos=(0, 0, 15, 19), texturePath='res:/UI/Texture/Crimewatch/Crimewatch_TimerPoint_WithShadow.png', align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED)
     86 
     87     def PlayEntryAnimation(self):
     88         uicore.animations.FadeIn(self, duration=0.25, endVal=1.0)
     89         if self.icon:
     90             uicore.animations.Tr2DScaleTo(self.iconTransform, startScale=(0.8, 0.8), endScale=(1.0, 1.0), duration=0.75, curveType=uiconst.ANIM_OVERSHOT)
     91 
     92     def SetTimerColor(self, color):
     93         r, g, b, a = color
     94         self.circleSprite.SetRGBA(r, g, b, 0.5)
     95         self.halfCircleSprite.SetRGBA(r, g, b, a)
     96         self.cycleSprite.SetRGBA(r, g, b, a)
     97         self.pointerSprite.SetRGBA(r, g, b, a)
     98         if self.icon:
     99             self.icon.SetRGBA(r, g, b, a)
    100 
    101     def SetRatio(self, ratio):
    102         self.ratio = min(1.0, max(0.0, ratio))
    103         if self.ratio > 0.5:
    104             self.clipContainer.SetAlign(uiconst.TORIGHT)
    105             self.cycleContainer.left = -16
    106             self.halfCircleSprite.display = True if self.countsDown else False
    107         else:
    108             self.clipContainer.SetAlign(uiconst.TOLEFT)
    109             self.cycleContainer.left = 0
    110             self.halfCircleSprite.display = False if self.countsDown else True
    111         rotation = 2 * pi * self.ratio
    112         self.pointerContainer.rotation = rotation
    113         self.cycleContainer.rotation = rotation
    114 
    115     def SetExpiryTime(self, timerExpiryTime, timerDuration, timerPaused = None, doAlert = False):
    116         self.Reset(timerExpiryTime, timerDuration, doAlert)
    117         self.paused = timerPaused
    118         if timerExpiryTime is None:
    119             self.PlayActiveAnimation()
    120         else:
    121             self.animationThread = uthread.new(self.Animate_Thread, timerExpiryTime, timerDuration)
    122 
    123     def GetCurrentTime(self):
    124         return self.paused or self.GetTime()
    125 
    126     def Reset(self, resetTo, timerDuration, doAlert):
    127         if self.animationThread is not None:
    128             self.animationThread.kill()
    129         uthread.new(self.Rewind_Thread, resetTo, timerDuration, doAlert)
    130 
    131     def Rewind_Thread(self, resetTo, timerDuration, doAlert):
    132         if self.rewind:
    133             return
    134         if doAlert and self.resetAudioEvent:
    135             sm.GetService('audio').SendUIEvent(self.resetAudioEvent)
    136         self.rewind = True
    137         ratio = self.ratio
    138         startTime = self.GetCurrentTime()
    139         distance = 1 - ratio
    140         cycleSpeed = float(distance * REWIND_SPEED)
    141         while not self.destroyed and cycleSpeed > 0:
    142             if resetTo is not None:
    143                 resetRatio = self.GetRatio(resetTo - self.GetCurrentTime(), timerDuration)
    144                 if self.ratio >= resetRatio:
    145                     break
    146             elapsedTime = blue.os.TimeDiffInMs(startTime, self.GetCurrentTime())
    147             toAdd = elapsedTime / cycleSpeed
    148             self.SetRatio(ratio + toAdd)
    149             blue.pyos.synchro.SleepWallclock(25)
    150 
    151         self.rewind = False
    152 
    153     def FlipFlop(self, sprite, duration = 1.0, startValue = 0.0, endValue = 1.0, loops = 5):
    154         curve = trinity.Tr2CurveScalar()
    155         curve.AddKey(0, startValue, trinity.Tr2CurveInterpolation.LINEAR)
    156         curve.AddKey(0.01 * duration, endValue, trinity.Tr2CurveInterpolation.LINEAR)
    157         curve.AddKey(0.5 * duration, endValue, trinity.Tr2CurveInterpolation.LINEAR)
    158         curve.AddKey(0.51 * duration, startValue, trinity.Tr2CurveInterpolation.LINEAR)
    159         curve.AddKey(duration, startValue, trinity.Tr2CurveInterpolation.LINEAR)
    160         return uicore.animations.Play(curve, sprite, 'opacity', loops, None, False)
    161 
    162     def GetRatio(self, timeLeft, duration):
    163         ratio = timeLeft / float(duration)
    164         ratio = min(1.0, max(0.0, ratio))
    165         return ratio
    166 
    167     def Animate_Thread(self, expiryTime, duration):
    168         self.StopActiveAnimation()
    169         self.StartSoundLoop()
    170         while not self.destroyed and expiryTime is not None:
    171             if not self.rewind:
    172                 if self.ratio <= 0.0:
    173                     break
    174                 timeLeft = expiryTime - self.GetCurrentTime()
    175                 ratio = self.GetRatio(timeLeft, duration)
    176                 self.SetRatio(ratio)
    177                 if timeLeft < BLINK_BEFORE_DONE_TIME:
    178                     self.PlayTimerRunningOutAnimation()
    179                 else:
    180                     self.StopTimerRunningOutAnimation()
    181             blue.pyos.synchro.SleepWallclock(50)
    182 
    183         self.StopActiveAnimation()
    184         self.StopSoundLoop()
    185 
    186     def PlayTimerRunningOutAnimation(self):
    187         if self.timerRunningOutAnimation == TIMER_RUNNING_OUT_NO_ANIMATION:
    188             return
    189         if self.iconBlink is not None:
    190             return
    191         if self.timerRunningOutAnimation == TIMER_RUNNING_OUT_BLINK_ICON:
    192             animationSprite = self.icon
    193         else:
    194             animationSprite = self.content
    195         self.iconBlink = self.FlipFlop(animationSprite, startValue=1.0, endValue=0.0)
    196         if self.endingAudioEvent:
    197             sm.GetService('audio').SendUIEvent(self.endingAudioEvent)
    198 
    199     def StopTimerRunningOutAnimation(self):
    200         if self.iconBlink is not None:
    201             self.iconBlink.Stop()
    202             self.iconBlink = None
    203 
    204     def EndAnimation(self):
    205         self.SetRatio(0.0)
    206         uicore.animations.FadeOut(self, duration=0.5, timeOffset=0.5)
    207         uicore.animations.MoveOutBottom(self.pointerSprite, amount=9, duration=0.3, sleep=False)
    208         self.content.scalingCenter = (0.5, 0.5)
    209         uicore.animations.Tr2DScaleTo(self.content, startScale=(1.0, 1.0), endScale=(0.8, 0.8), duration=0.4, sleep=True)
    210 
    211     def PlayActiveAnimation(self):
    212         self.activeAnimationCurves = ((self.halfCircleSprite, self.FlipFlop(self.halfCircleSprite, startValue=1.0, endValue=0.75, duration=1.0, loops=uiconst.ANIM_REPEAT)), (self.cycleSprite, self.FlipFlop(self.cycleSprite, startValue=1.0, endValue=0.75, duration=1.0, loops=uiconst.ANIM_REPEAT)), (self.pointerSprite, self.FlipFlop(self.pointerSprite, startValue=1.0, endValue=0.75, duration=1.0, loops=uiconst.ANIM_REPEAT)))
    213 
    214     def StopActiveAnimation(self):
    215         if self.activeAnimationCurves is not None:
    216             for sprite, animationCurve in self.activeAnimationCurves:
    217                 animationCurve.Stop()
    218                 sprite.opacity = 1.0
    219 
    220             self.activeAnimationCurves = None
    221 
    222     def SetSoundLoop(self, playEvent, stopEvent):
    223         self.sound_loop_play_event = playEvent
    224         self.sound_loop_stop_event = stopEvent
    225 
    226     def StartSoundLoop(self):
    227         if self.sound_loop_play_event is not None:
    228             sm.GetService('audio').SendUIEvent(self.sound_loop_play_event)
    229 
    230     def StopSoundLoop(self):
    231         if self.sound_loop_stop_event is not None:
    232             sm.GetService('audio').SendUIEvent(self.sound_loop_stop_event)