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

entry.py (14966B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\achievement_system\client\ui\window\page\rewards\entry.py
      2 import datetimeutils
      3 import eveicon
      4 import eveui
      5 import gametime
      6 import math
      7 import threadutils
      8 import uthread2
      9 from achievement_system.client.model.definition.reward.type import RewardType
     10 from carbonui import Align, ButtonStyle, Density, PickState, TextColor, uiconst
     11 from carbonui.control.button import Button
     12 from carbonui.primitives.container import Container
     13 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     14 from carbonui.primitives.frame import Frame
     15 from carbonui.primitives.line import Line
     16 from carbonui.primitives.sprite import Sprite
     17 from carbonui.text.styles import TextBody
     18 from carbonui.util.color import Color
     19 from eve.client.script.ui import eveColor
     20 from eve.client.script.ui.control.gauge import Gauge
     21 from eve.client.script.ui.control.tooltips import TooltipPanel
     22 from eveicon import IconData
     23 from eveui.animation.curve import CurveType
     24 from localization import GetByLabel
     25 from menucheckers import SessionChecker
     26 GLOW_IDLE = 0.5
     27 GLOW_HOVER = 1.0
     28 OPACITY_IDLE = 0.1
     29 OPACITY_HOVER = 0.2
     30 FLAIR_SIZE = 300
     31 DEFAULT_FLAIR_TEXTURE = 'res:/UI/Texture/Shared/CareerPaths/unclassified_flair.png'
     32 REWARD_WIDTH_RATIO = 0.45
     33 
     34 class RewardClaimButton(Button):
     35     default_display = True
     36     default_style = ButtonStyle.SUCCESS
     37 
     38     def __init__(self, func = None, label_claim = None, label_claimed = None, *args, **kwargs):
     39         self._label_claim = label_claim or GetByLabel('UI/Generic/Claim')
     40         self._label_claimed = label_claimed or GetByLabel('UI/Generic/Claimed')
     41         kwargs.setdefault('func', func)
     42         super(RewardClaimButton, self).__init__(*args, **kwargs)
     43         self.set_claimable()
     44 
     45     def set_claimable(self):
     46         self.Show()
     47         self.enable()
     48         self.busy = False
     49         self.hint = None
     50         self.label = self._label_claim
     51 
     52     def set_claimed(self):
     53         self.disable()
     54         self.busy = False
     55         self.label = self._label_claimed
     56 
     57     def start_claim_sequence(self):
     58         self.busy = True
     59 
     60     def flag_error(self, error_text = None):
     61         self.disable()
     62         self.busy = False
     63         self.label = error_text or GetByLabel('UI/Inflight/JumpThroughError')
     64 
     65 
     66 def _get_hours_until(timestamp):
     67     timestamp_datetime = datetimeutils.filetime_to_datetime(timestamp)
     68     remaining_time_delta = timestamp_datetime - gametime.now()
     69     remaining_seconds = remaining_time_delta.total_seconds()
     70     return int(float(remaining_seconds) / 3600)
     71 
     72 
     73 def _get_time_color_icon(timestamp):
     74     if timestamp is None:
     75         return TextColor.DISABLED
     76     remaining_hours = _get_hours_until(timestamp)
     77     if remaining_hours < 6:
     78         return eveColor.CHERRY_RED
     79     if remaining_hours < 24:
     80         return eveColor.DUSKY_ORANGE
     81     return TextColor.DISABLED
     82 
     83 
     84 def _get_time_color_text(timestamp):
     85     if timestamp is None:
     86         return TextColor.SECONDARY
     87     remaining_hours = _get_hours_until(timestamp)
     88     if remaining_hours < 6:
     89         return eveColor.CHERRY_RED
     90     if remaining_hours < 24:
     91         return eveColor.DUSKY_ORANGE
     92     return TextColor.SECONDARY
     93 
     94 
     95 def _get_time_color_time(timestamp):
     96     if timestamp is None:
     97         return Color.RGBtoHex(*TextColor.NORMAL)
     98     remaining_hours = _get_hours_until(timestamp)
     99     if remaining_hours < 6:
    100         return eveColor.DANGER_RED_HEX
    101     if remaining_hours < 24:
    102         return eveColor.WARNING_ORANGE_HEX
    103     return Color.RGBtoHex(*TextColor.NORMAL)
    104 
    105 
    106 def _get_default_expiration_text(expiration_time):
    107     time_now = gametime.GetWallclockTime()
    108     time_remaining = expiration_time - time_now
    109     if time_remaining <= 0:
    110         return GetByLabel('UI/Generic/Expired')
    111     else:
    112         return GetByLabel('UI/Generic/ExpiresIn', color=_get_time_color_time(expiration_time), remaining=time_remaining)
    113 
    114 
    115 class ExpirationTooltip(TooltipPanel):
    116 
    117     def __init__(self, expiration_time, get_text = None):
    118         super(ExpirationTooltip, self).__init__()
    119         self._expiration_time = expiration_time
    120         self._get_text = get_text or _get_default_expiration_text
    121 
    122     def ApplyAttributes(self, attributes):
    123         super(ExpirationTooltip, self).ApplyAttributes(attributes)
    124         self.LoadGeneric1ColumnTemplate()
    125         self._timer_label = self.AddLabelMedium()
    126         uthread2.start_tasklet(self._time_remaining_routine)
    127 
    128     def _time_remaining_routine(self):
    129         while not self.destroyed:
    130             self._timer_label.color = _get_time_color_text(self._expiration_time)
    131             self._timer_label.text = self._get_text(self._expiration_time)
    132             remaining = self._expiration_time - gametime.GetWallclockTime()
    133             if remaining <= 0:
    134                 break
    135             uthread2.sleep(1)
    136 
    137 
    138 class ExpirationIcon(ContainerAutoSize):
    139     default_align = Align.TORIGHT
    140     default_state = uiconst.UI_NORMAL
    141 
    142     def __init__(self, expiration_time, icon_size = 16, get_text = None, *args, **kwargs):
    143         super(ExpirationIcon, self).__init__(*args, **kwargs)
    144         self._expiration_time = expiration_time
    145         self._get_text = get_text or _get_default_expiration_text
    146         self._expiration_icon = Sprite(name='expiration_icon', parent=self, state=uiconst.UI_DISABLED, align=Align.CENTER, width=icon_size, height=icon_size, texturePath=eveicon.hourglass, color=_get_time_color_icon(self._expiration_time), opacity=TextColor.NORMAL.opacity)
    147         uthread2.start_tasklet(self._time_remaining_routine)
    148 
    149     def _time_remaining_routine(self):
    150         while not self.destroyed:
    151             self._refresh_color()
    152             remaining = self._expiration_time - gametime.GetWallclockTime()
    153             if remaining <= 0:
    154                 break
    155             uthread2.sleep(5)
    156 
    157     def _refresh_color(self):
    158         self._expiration_icon.color = _get_time_color_icon(self._expiration_time)
    159 
    160     def OnMouseEnter(self, *args):
    161         super(ExpirationIcon, self).OnMouseEnter(*args)
    162         self._refresh_color()
    163 
    164     def ConstructTooltipPanel(self):
    165         return ExpirationTooltip(self._expiration_time, self._get_text)
    166 
    167 
    168 class AchievementRewardEntry(Container):
    169     default_width = 300
    170     default_height = 46
    171     default_state = uiconst.UI_NORMAL
    172     default_clipChildren = True
    173     default_padding = (0, 4, 0, 4)
    174 
    175     def __init__(self, controller, progress = 1.0, theme_color = None, flair_texture = None, on_claim = None, expiration_time = None, *args, **kwargs):
    176         self.controller = controller
    177         self._progress = progress
    178         self._theme_color = theme_color or eveColor.SUCCESS_GREEN[:3]
    179         self._flair_texture = flair_texture or DEFAULT_FLAIR_TEXTURE
    180         self._on_claim = on_claim
    181         self._expiration_time = expiration_time
    182         super(AchievementRewardEntry, self).__init__(*args, **kwargs)
    183         self.construct_layout()
    184         self.update()
    185 
    186     def construct_layout(self):
    187         self.construct_base_layout()
    188         self.construct_right_wrapper()
    189         self.construct_left_layout()
    190         self.construct_left_side()
    191         self.construct_right_layout()
    192         self.construct_right_side()
    193         self.construct_underlay()
    194 
    195     def construct_base_layout(self):
    196         self._left_line = Line(name='leftLine', parent=self, align=Align.TOLEFT, color=eveColor.PLATINUM_GREY, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, opacity=0.6, glowBrightness=GLOW_IDLE)
    197         self._left_line.rgb = self._theme_color
    198         self.content = Container(name='content', parent=self)
    199         self.flair_cont = Container(name='flairCont', parent=self, pickState=PickState.OFF, clipChildren=True)
    200 
    201     def construct_right_wrapper(self):
    202         self._right_wrapper = Container(name='right_wrapper', parent=self.content, align=Align.TORIGHT_PROP, width=REWARD_WIDTH_RATIO)
    203 
    204     def construct_left_layout(self):
    205         self.left_container_outer = Container(name='left_container_outer', parent=self.content, align=Align.TOALL, clipChildren=True)
    206         self.left_container = Container(name='left_container', parent=self.left_container_outer, align=Align.TOALL, padLeft=16, padRight=16, clipChildren=True)
    207 
    208     def construct_left_side(self):
    209         self.construct_gauge(self.left_container)
    210         self._construct_title_icons(self.left_container)
    211         title_container = Container(parent=self.left_container, align=Align.TOALL, clipChildren=True)
    212         self._title_label = TextBody(parent=title_container, align=Align.CENTERLEFT, maxLines=1, bold=True, autoFadeSides=16)
    213 
    214     def _construct_title_icons(self, container):
    215         icon = self.controller.icon
    216         if icon is None:
    217             return
    218         container = Container(name='title_icons_container', parent=container, align=Align.TOLEFT, padRight=8, width=16, height=16, pickState=PickState.ON)
    219         Sprite(parent=container, texturePath=icon, align=Align.CENTER, width=16, height=16, color=TextColor.SECONDARY, pickState=PickState.OFF)
    220         container.OnClick = self.OnClick
    221 
    222     def construct_gauge(self, parent):
    223         gauge_container = ContainerAutoSize(name='gauge_container', parent=parent, align=Align.TORIGHT, height=self.height)
    224         self._gauge = Gauge(name='gauge', parent=gauge_container, align=Align.CENTERRIGHT, gaugeHeight=2, width=37)
    225         self._gauge_label = TextBody(name='gauge_label', parent=gauge_container, align=Align.CENTERRIGHT, padRight=45)
    226 
    227     def construct_right_layout(self):
    228         self.right_container = Container(name='right_container', parent=self._right_wrapper, align=Align.TOALL, padLeft=16, padRight=16)
    229 
    230     def construct_right_side(self):
    231         cta_cont = ContainerAutoSize(name='cta_cont', parent=self.right_container, align=Align.TORIGHT, padLeft=8)
    232         self._claim_button = RewardClaimButton(name='claim_button', parent=cta_cont, align=Align.CENTERLEFT, density=Density.COMPACT, func=lambda *_: self._on_claim(entry=self))
    233         self._claim_button.set_claimable()
    234         if self._expiration_time is not None:
    235             ExpirationIcon(name='expiration_icon', parent=self.right_container, align=Align.TORIGHT, expiration_time=self._expiration_time, padLeft=4)
    236         self.right_content_container = Container(name='right_content_container', parent=self.right_container, align=Align.TOALL, clipChildren=True)
    237         self.rewards_container = ContainerAutoSize(name='rewards_container', parent=self.right_content_container, align=Align.TOLEFT)
    238 
    239     def construct_underlay(self):
    240         Frame(bgParent=self, texturePath='res:/UI/Texture/classes/Opportunities/card_mask.png', cornerSize=16, color=(0, 0, 0, 0.9))
    241         flair_pos = (-FLAIR_SIZE / 2 + 25,
    242          -FLAIR_SIZE / 2 + 25,
    243          FLAIR_SIZE,
    244          FLAIR_SIZE)
    245         self._bg_flair = Sprite(name='bgFlair', parent=self.flair_cont, texturePath=self._flair_texture, color=eveColor.SILVER_GREY, align=Align.TOPLEFT, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=0.0, opacity=0.7, pos=flair_pos)
    246         self._bg_flair.rgb = self._theme_color
    247         self._hover_frame = Frame(parent=self, texturePath='res:/UI/Texture/classes/Opportunities/card_mask.png', cornerSize=16, color=eveColor.PLATINUM_GREY, opacity=OPACITY_IDLE)
    248         self._hover_frame.rgb = self._theme_color
    249         self._right_frame = Frame(bgParent=self._right_wrapper, texturePath='res:/UI/Texture/classes/Opportunities/list_entry_mask.png', cornerSize=16, color=eveColor.WHITE, opacity=0.05)
    250 
    251     @threadutils.highlander_threaded
    252     def update(self):
    253         self._title_label.text = self.controller.name
    254         self.update_rewards()
    255         self.update_gauge(animate=False)
    256 
    257     def update_rewards(self):
    258         self.rewards_container.Flush()
    259         reward_data = self.controller.reward_data
    260         has_multiple_rewards = len(reward_data) > 1
    261         has_item_reward = False
    262         for reward in reward_data:
    263             self.add_reward(reward)
    264             if reward.is_item:
    265                 has_item_reward = True
    266 
    267         if has_multiple_rewards or has_item_reward:
    268             self.rewards_container.state = uiconst.UI_NORMAL
    269             self.rewards_container.LoadTooltipPanel = lambda tooltipPanel, *args: RewardsTooltip(tooltipPanel=tooltipPanel, reward_data=reward_data)
    270         if has_item_reward:
    271             self._claim_button.GetHint = self.claim_button_item_hint
    272         else:
    273             self._claim_button.GetHint = lambda : None
    274 
    275     def update_gauge(self, animate = True):
    276         color = eveColor.SUCCESS_GREEN if self._progress >= 1.0 else eveColor.CRYO_BLUE
    277         self._gauge.SetColor(color)
    278         self._gauge.SetValue(self._progress, animate=animate)
    279         self._gauge_label.text = '{:.0%}'.format(self._progress)
    280         self._gauge_label.color = color
    281 
    282     def add_reward(self, reward):
    283         cont = ContainerAutoSize(parent=self.rewards_container, align=Align.TOLEFT, padRight=8)
    284         Sprite(parent=cont, align=Align.CENTERLEFT, state=uiconst.UI_DISABLED, pos=(0, 0, 16, 16), texturePath=reward.icon)
    285         self.reward_label = TextBody(parent=cont, align=Align.CENTERLEFT, state=uiconst.UI_DISABLED if reward.is_item else uiconst.UI_PICKCHILDREN, left=20, maxLines=1, autoFadeSides=16, text=reward.hint if reward.is_title else reward.text, color=TextColor.NORMAL)
    286 
    287     def claim_button_item_hint(self):
    288         if SessionChecker(session, sm).IsPilotDocked():
    289             return GetByLabel('UI/Achievements/Window/Rewards/ClaimItemHintDocked')
    290         else:
    291             return GetByLabel('UI/Achievements/Window/Rewards/ClaimItemHintUndocked')
    292 
    293     def OnMouseEnter(self, *args):
    294         eveui.Sound.entry_hover.play()
    295         eveui.fade_in(self._hover_frame, end_value=OPACITY_HOVER, duration=0.2)
    296         eveui.animate(self._left_line, 'glowBrightness', GLOW_HOVER, duration=0.2)
    297         eveui.animate(self._bg_flair, 'glowBrightness', 0.3, duration=0.2)
    298         eveui.animate(self._bg_flair, 'rotation', end_value=self._bg_flair.rotation + 2 * math.pi, duration=80.0, curve_type=CurveType.linear)
    299 
    300     def OnMouseExit(self, *args):
    301         eveui.fade(self._hover_frame, end_value=OPACITY_IDLE, duration=0.2)
    302         eveui.animate(self._left_line, 'glowBrightness', GLOW_IDLE, duration=0.2)
    303         eveui.animate(self._bg_flair, 'glowBrightness', 0.0, duration=0.2)
    304         eveui.animate(self._bg_flair, 'rotation', end_value=self._bg_flair.rotation + 0.025, duration=0.2)
    305 
    306 
    307 def RewardsTooltip(tooltipPanel, reward_data):
    308     tooltipPanel.LoadStandardSpacing()
    309     tooltipPanel.columns = 2
    310     for reward in reward_data:
    311         label_text = reward.hint
    312         if label_text is None:
    313             continue
    314         if isinstance(reward.icon, IconData):
    315             icon = reward.icon.resolve(16)
    316         else:
    317             icon = reward.icon
    318         _, labelObj = tooltipPanel.AddIconLabel(icon=icon, iconSize=20 if reward.reward_type == RewardType.SP else 16, label=label_text)
    319         if reward.is_item:
    320             tooltipPanel.state = uiconst.UI_NORMAL
    321             labelObj.state = uiconst.UI_NORMAL