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

infoPanelAchievement.py (20177B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\infoPanels\infoPanelAchievement.py
      2 import eveicon
      3 import threadutils
      4 from achievement_system.client.api.error import DefinitionNotFoundError
      5 from achievement_system.client.api.repository import get_repository
      6 from achievement_system.client.api.signal import on_achievement_tracked, on_achievement_untracked, on_achievement_progressed, on_achievement_completed, on_achievement_milestone_reached, on_admin_achievement_reset, on_admin_achievement_reset_all, on_achievement_milestone_reward_claimed
      7 from achievement_system.client.model.definition.achievement.entry import AchievementDefinitionEntry
      8 from achievement_system.client.ui.controller.achievement_entry import AchievementEntryController
      9 from achievement_system.client.ui.window.const import TRANSITION_DURATION
     10 from achievement_system.client.ui.window.window import AchievementsWindow
     11 from carbon.common.script.util.format import FmtAmt
     12 from carbonui import Align, ButtonFrameType, Density, TextColor, uiconst, PickState, ButtonStyle
     13 from carbonui.button.menu import MenuButtonIcon
     14 from carbonui.control.button import Button
     15 from carbonui.control.contextMenu.menuData import MenuData
     16 from carbonui.primitives.container import Container
     17 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     18 from carbonui.primitives.fill import Fill
     19 from carbonui.primitives.gridcontainer import GridContainer
     20 from carbonui.primitives.sprite import Sprite
     21 from carbonui.text.styles import TextBody, TextDetail
     22 from carbonui.uianimations import animations
     23 from carbonui.uiconst import OutputMode
     24 from eve.client.script.ui import eveColor
     25 from eve.client.script.ui.control.eveLabel import EveLabelLarge
     26 from eve.client.script.ui.control.gauge import Gauge
     27 from eve.client.script.ui.shared.infoPanels.InfoPanelBase import InfoPanelBase
     28 from eve.client.script.ui.shared.infoPanels.const import infoPanelConst, infoPanelUIConst
     29 from localization import GetByLabel
     30 from signals import Signal
     31 from uihider import UiHiderMixin
     32 from uihighlighting.uniqueNameConst import UNIQUE_NAME_ACHIEVEMENT_INFO_PANEL
     33 on_infopanel_achievement_expanded = Signal('on_infopanel_achievement_expanded')
     34 
     35 class InfoPanelAchievement(UiHiderMixin, InfoPanelBase):
     36     __guid__ = 'uicls.InfoPanelAchievement'
     37     default_name = 'InfoPanelAchievement'
     38     uniqueUiName = UNIQUE_NAME_ACHIEVEMENT_INFO_PANEL
     39     panelTypeID = infoPanelConst.PANEL_ACHIEVEMENT
     40     label = 'UI/Achievements/Window/Title'
     41     default_iconTexturePath = 'res:/UI/Texture/WindowIcons/achievements.png'
     42     default_mode = infoPanelConst.MODE_NORMAL
     43 
     44     def ApplyAttributes(self, attributes):
     45         super(InfoPanelAchievement, self).ApplyAttributes(attributes)
     46         self.construct_layout()
     47         self.connect_signals()
     48 
     49     def Close(self):
     50         try:
     51             self.disconnect_signals()
     52         finally:
     53             super(InfoPanelAchievement, self).Close()
     54 
     55     def connect_signals(self):
     56         on_achievement_tracked.connect(self.on_achievement_tracked)
     57 
     58     def disconnect_signals(self):
     59         on_achievement_tracked.disconnect(self.on_achievement_tracked)
     60 
     61     def construct_layout(self):
     62         self.mainCont.padTop = 4
     63         self.headerCls(name='header_label', parent=self.headerCont, align=uiconst.CENTERLEFT, text=GetByLabel('UI/Achievements/Window/Title'))
     64         tracked_achievement_ids = get_repository().activity.get_tracked_achievements()
     65         auto_expand = len(tracked_achievement_ids) == 1
     66         for achievement_id in tracked_achievement_ids:
     67             self.add_achievement(achievement_id, auto_expand)
     68 
     69     @staticmethod
     70     def IsAvailable():
     71         return get_repository().activity.has_tracked_achievements()
     72 
     73     def ConstructHeaderButton(self):
     74         button = self.ConstructSimpleHeaderButton()
     75         button.OnClick = self.on_header_button_click
     76 
     77     def add_achievement(self, achievement_id, auto_expand = False):
     78         controller = self.get_achievement_entry_controller(achievement_id)
     79         if controller is None:
     80             return
     81         TrackedAchievement(name='tracked_achievement', parent=self.mainCont, align=Align.TOTOP, controller=controller, auto_expand=auto_expand, padBottom=8)
     82 
     83     def get_achievement_entry_controller(self, achievement_id):
     84         if achievement_id is None:
     85             return
     86         try:
     87             achievement_attributes = get_repository().definitions.get_achievement(achievement_id)
     88         except DefinitionNotFoundError:
     89             return
     90 
     91         achievement_entry = AchievementDefinitionEntry(achievement_id, achievement_attributes)
     92         return AchievementEntryController(achievement_entry)
     93 
     94     def on_header_button_click(self, *args):
     95         wnd = AchievementsWindow.GetIfOpen()
     96         if wnd and not wnd.destroyed:
     97             wnd.Maximize()
     98         else:
     99             AchievementsWindow.Open()
    100 
    101     def on_achievement_tracked(self, achievement_id):
    102         self.add_achievement(achievement_id, auto_expand=True)
    103 
    104 
    105 class TrackedAchievement(ContainerAutoSize):
    106 
    107     def __init__(self, controller, auto_expand = False, *args, **kwargs):
    108         super(TrackedAchievement, self).__init__(*args, **kwargs)
    109         self.controller = controller
    110         self.auto_expand = auto_expand
    111         self.is_expanded = False
    112         self.construct_layout()
    113         self.update(animate=False)
    114         self.connect_signals()
    115 
    116     def Close(self):
    117         try:
    118             self.disconnect_signals()
    119         finally:
    120             super(TrackedAchievement, self).Close()
    121 
    122     def connect_signals(self):
    123         on_achievement_progressed.connect(self.on_achievement_progressed)
    124         on_admin_achievement_reset.connect(self.on_reset)
    125         on_admin_achievement_reset_all.connect(self.on_reset_all)
    126         on_achievement_completed.connect(self.on_achievement_completed)
    127         on_achievement_milestone_reached.connect(self.on_milestone_reached)
    128         on_achievement_milestone_reward_claimed.connect(self.on_achievement_milestone_reward_claimed)
    129         on_achievement_untracked.connect(self.on_achievement_untracked)
    130         on_infopanel_achievement_expanded.connect(self.on_infopanel_achievement_expanded)
    131         self.on_size_changed.connect(self.on_size_changed_signal)
    132 
    133     def disconnect_signals(self):
    134         on_achievement_progressed.disconnect(self.on_achievement_progressed)
    135         on_admin_achievement_reset.disconnect(self.on_reset)
    136         on_admin_achievement_reset_all.disconnect(self.on_reset_all)
    137         on_achievement_completed.disconnect(self.on_achievement_completed)
    138         on_achievement_milestone_reached.disconnect(self.on_milestone_reached)
    139         on_achievement_milestone_reward_claimed.disconnect(self.on_achievement_milestone_reward_claimed)
    140         on_achievement_untracked.disconnect(self.on_achievement_untracked)
    141         on_infopanel_achievement_expanded.disconnect(self.on_infopanel_achievement_expanded)
    142         self.on_size_changed.disconnect(self.on_size_changed_signal)
    143 
    144     def construct_layout(self):
    145         self.content_container = ContainerAutoSize(name='content_container', parent=self, align=uiconst.TOTOP, alignMode=Align.TOTOP)
    146         self.construct_header()
    147         self.construct_details()
    148 
    149     def construct_header(self):
    150         self.header_container = Container(name='header_container', parent=self.content_container, align=Align.TOTOP)
    151         Fill(bgParent=self.header_container, color=eveColor.BLACK, opacity=0.35)
    152         header_contents = Container(name='header_contents', parent=self.header_container, padding=(8, 0, 8, 0))
    153         header_icon_container = Container(name='header_icon_container', parent=header_contents, align=Align.TOLEFT, width=16)
    154         self.header_icon = Sprite(name='header_icon', parent=header_icon_container, align=Align.CENTER, color=eveColor.WHITE, outputMode=OutputMode.COLOR_AND_GLOW, glowBrightness=0.0, opacity=0.75, hint=GetByLabel('UI/Achievements/ViewCategory'), pos=(0, 0, 16, 16))
    155         self.header_icon.OnClick = self.on_header_icon_click
    156         self.header_icon.OnMouseEnter = self.on_header_icon_enter
    157         self.header_icon.OnMouseExit = self.on_header_icon_exit
    158         self.menu_container = Container(name='menu_container', parent=header_contents, align=Align.TORIGHT, clipChildren=True, width=0)
    159         MenuButtonIcon(name='menu_button_icon', parent=self.menu_container, align=Align.CENTERRIGHT, get_menu_func=self.get_options_menu, hint=None, width=16)
    160         self.header_label_container = Container(name='header_label_container', parent=header_contents, align=Align.VERTICALLY_CENTERED, padLeft=8)
    161         self.header_progress_label = EveLabelLarge(name='header_progress_label', parent=self.header_label_container, align=Align.TORIGHT, state=uiconst.UI_NORMAL, padLeft=8)
    162         self.header_progress_label.OnClick = self.on_header_clicked
    163         self.header_name_label = EveLabelLarge(name='header_name_label', parent=self.header_label_container, align=Align.VERTICALLY_CENTERED, color=TextColor.HIGHLIGHT, maxLines=1, showEllipsis=True)
    164         header_interaction_container = Container(name='header_interaction_container', parent=self.header_container, state=uiconst.UI_NORMAL)
    165         header_interaction_container.OnClick = self.on_header_clicked
    166 
    167     def construct_details(self):
    168         self.details_container = Container(name='details_container', parent=self.content_container, align=Align.TOTOP, clipChildren=True, height=0)
    169         Fill(bgParent=self.details_container, color=eveColor.BLACK, opacity=0.25)
    170         self.details_contents = ContainerAutoSize(name='details_contents', parent=self.details_container, align=Align.TOTOP, padding=(8, 4, 8, 0))
    171         self.description_label = TextBody(parent=self.details_contents, name='description_label', align=Align.TOTOP)
    172         if self.controller.has_multiple_milestones:
    173             self.milestones = Milestones(name='milestones', parent=self.details_contents, align=Align.TOTOP, controller=self.controller, padTop=8)
    174         self.progress = Progress(name='progress', parent=self.details_contents, align=Align.TOTOP, controller=self.controller, padTop=8)
    175         self.construct_claim_button()
    176 
    177     def construct_claim_button(self):
    178         self.claim_button = ClaimButton(parent=self.details_contents, name='claim_button', align=Align.TOTOP, padTop=16, display=False)
    179 
    180     @threadutils.highlander_threaded
    181     def update(self, animate = True):
    182         self.update_header()
    183         self.update_details(animate)
    184 
    185     def update_header(self):
    186         name_text = self.controller.name
    187         _, header_text_height = EveLabelLarge.MeasureTextSize(name_text)
    188         self.header_label_container.height = header_text_height
    189         self.header_container.height = header_text_height + 16
    190         self.header_icon.texturePath = self.controller.category_icon
    191         self.header_name_label.text = name_text
    192         self.header_progress_label.text = self.controller.progress_score_text_for_current_milestone
    193         self.header_progress_label.hint = self.controller.progress_score_hint_for_current_milestone
    194         self.header_progress_label.display = not self.is_expanded
    195 
    196     def update_details(self, animate):
    197         self.description_label.text = self.controller.description
    198         if self.controller.has_multiple_milestones:
    199             self.milestones.update()
    200         self.progress.update()
    201         self.claim_button.display = self.controller.is_completed and self.controller.has_unclaimed_rewards
    202         if animate:
    203             self.animate_details_container()
    204         else:
    205             self.details_container.height = self.details_target_height
    206 
    207     def animate_details_container(self):
    208         animations.MorphScalar(obj=self.details_container, attrName='height', startVal=self.details_container.height, endVal=self.details_target_height, duration=TRANSITION_DURATION)
    209 
    210     @property
    211     def details_target_height(self):
    212         if not self.is_expanded:
    213             return 0
    214         measure_width = infoPanelUIConst.PANELWIDTH - infoPanelUIConst.LEFTPAD - 16
    215         _, text_height = TextBody.MeasureTextSize(self.controller.description, width=measure_width)
    216         if self.controller.is_completed and self.controller.has_unclaimed_rewards:
    217             text_height += self.claim_button.height + self.claim_button.padTop
    218         if self.controller.has_multiple_milestones:
    219             text_height += self.milestones.height + self.milestones.padTop
    220         return text_height + 12 + self.progress.height + self.progress.padTop
    221 
    222     def get_options_menu(self):
    223         data = MenuData()
    224         data.AddEntry(text=GetByLabel('UI/Achievements/ViewDetails'), func=self.on_menu_view_details)
    225         data.AddEntry(text=GetByLabel('UI/Common/Untrack'), func=self.on_menu_untrack, texturePath=eveicon.camera_untrack)
    226         return data
    227 
    228     def on_menu_view_details(self, *args):
    229         AchievementsWindow.open_achievement(self.controller.achievement_entry.identifier)
    230         wnd = AchievementsWindow.GetIfOpen()
    231         if wnd:
    232             wnd.Maximize()
    233 
    234     def on_menu_untrack(self, *args):
    235         self.controller.untrack()
    236 
    237     def on_size_changed_signal(self, width, height):
    238         if not self.auto_expand:
    239             return
    240         self.auto_expand = False
    241         self.on_header_clicked()
    242 
    243     def on_header_clicked(self, *args):
    244         self.is_expanded = not self.is_expanded
    245         self.update()
    246         if self.is_expanded:
    247             on_infopanel_achievement_expanded(self.controller.achievement_entry.identifier)
    248 
    249     def on_header_icon_click(self, *args):
    250         AchievementsWindow.open_category(self.controller.achievement_entry.attributes.parent_category)
    251 
    252     def on_header_icon_enter(self, *args):
    253         animations.MorphScalar(obj=self.header_icon, attrName='glowBrightness', startVal=self.header_icon.glowBrightness, endVal=0.3, duration=TRANSITION_DURATION * 0.5)
    254 
    255     def on_header_icon_exit(self, *args):
    256         animations.MorphScalar(obj=self.header_icon, attrName='glowBrightness', startVal=self.header_icon.glowBrightness, endVal=0.0, duration=TRANSITION_DURATION * 0.5)
    257 
    258     def on_achievement_progressed(self, achievement_id, achievement_state):
    259         if achievement_id == self.controller.achievement_entry.identifier:
    260             self.update()
    261 
    262     def on_achievement_completed(self, achievement_id):
    263         if achievement_id == self.controller.achievement_entry.identifier:
    264             self.update()
    265 
    266     def on_milestone_reached(self, achievement_id, milestone_id):
    267         if achievement_id == self.controller.achievement_entry.identifier:
    268             self.update()
    269 
    270     def on_reset(self, achievement_id):
    271         if achievement_id == self.controller.achievement_entry.identifier:
    272             self.update()
    273 
    274     def on_reset_all(self):
    275         self.update()
    276 
    277     def on_untrack_button_clicked(self, *args):
    278         self.controller.untrack()
    279 
    280     def on_achievement_milestone_reward_claimed(self, achievement_id, milestone_id):
    281         if achievement_id == self.controller.achievement_entry.identifier:
    282             if self.controller.is_completed and not self.controller.has_unclaimed_rewards:
    283                 self.controller.untrack()
    284 
    285     def on_achievement_untracked(self, achievement_id):
    286         if achievement_id == self.controller.achievement_entry.identifier:
    287             self.Close()
    288 
    289     def on_infopanel_achievement_expanded(self, achievement_id):
    290         if achievement_id != self.controller.achievement_entry.identifier:
    291             self.is_expanded = False
    292             self.update()
    293 
    294     def OnMouseEnter(self, *args):
    295         animations.MorphScalar(obj=self.menu_container, attrName='width', startVal=self.menu_container.width, endVal=20, duration=TRANSITION_DURATION * 0.5)
    296 
    297     def OnMouseExit(self, *args):
    298         animations.MorphScalar(obj=self.menu_container, attrName='width', startVal=self.menu_container.width, endVal=0, duration=TRANSITION_DURATION * 0.5)
    299 
    300     def OnGlobalFontSizeChanged(self):
    301         super(TrackedAchievement, self).OnGlobalFontSizeChanged()
    302         self.update()
    303 
    304 
    305 class Milestones(ContainerAutoSize):
    306     default_alignMode = Align.TOTOP
    307 
    308     def __init__(self, controller, *args, **kwargs):
    309         super(Milestones, self).__init__(*args, **kwargs)
    310         self.controller = controller
    311         self.construct_layout()
    312 
    313     def construct_layout(self):
    314         label_container = ContainerAutoSize(name='label_container', parent=self, align=Align.TOTOP, alignMode=Align.TOTOP)
    315         self.progress_label = TextDetail(name='progress_label', parent=label_container, align=Align.TORIGHT, padLeft=8)
    316         TextDetail(name='title_label', parent=label_container, align=Align.TOTOP, text=GetByLabel('UI/Achievements/Window/Card/CurrentMilestone'))
    317         self.marker_container = GridContainer(name='marker_container', parent=self, align=uiconst.TOTOP, height=4, contentSpacing=(4, 4), padTop=4)
    318 
    319     def construct_markers(self):
    320         self.marker_container.Flush()
    321         total_milestones = self.controller.total_milestones
    322         if total_milestones == 0:
    323             return
    324         self.marker_container.columns = min(total_milestones, 5)
    325         for index in range(0, self.controller.total_milestones):
    326             is_completed = index < self.controller.completed_milestones
    327             is_current = index == self.controller.current_milestone_index
    328             if is_completed:
    329                 color = eveColor.SUCCESS_GREEN
    330             elif is_current:
    331                 color = eveColor.FOCUS_BLUE
    332             else:
    333                 color = eveColor.WHITE
    334             if is_completed or is_current:
    335                 opacity = 1.0
    336                 glow_brightness = 0.5
    337             else:
    338                 opacity = 0.2
    339                 glow_brightness = 0.0
    340             Fill(parent=self.marker_container, color=color, outputMode=OutputMode.COLOR_AND_GLOW, glowBrightness=glow_brightness, opacity=opacity)
    341 
    342     @threadutils.highlander_threaded
    343     def update(self):
    344         self.progress_label.text = '(%s/%s)' % (self.controller.current_milestone_index + 1, self.controller.total_milestones)
    345         self.construct_markers()
    346 
    347 
    348 class Progress(ContainerAutoSize):
    349     default_alignMode = Align.TOTOP
    350 
    351     def __init__(self, controller, *args, **kwargs):
    352         super(Progress, self).__init__(*args, **kwargs)
    353         self.controller = controller
    354         self.construct_layout()
    355 
    356     def construct_layout(self):
    357         label_container = ContainerAutoSize(name='label_container', parent=self, align=Align.TOTOP, alignMode=Align.TOTOP)
    358         self.progress_label = TextDetail(name='progress_label', parent=label_container, align=Align.TORIGHT, state=uiconst.UI_NORMAL, padLeft=8)
    359         TextDetail(name='title_label', parent=label_container, align=Align.TOTOP, text=GetByLabel('UI/Achievements/Progress'))
    360         self.progress_bar = Gauge(name='progress_bar', parent=self, align=Align.TOTOP, gaugeHeight=4, padTop=4)
    361 
    362     @threadutils.highlander_threaded
    363     def update(self):
    364         progress = self.controller.progress
    365         target = self.controller.target_for_milestone_index(self.controller.current_milestone_index)
    366         if target <= 100000:
    367             progress_text = FmtAmt(progress)
    368             target_text = FmtAmt(target)
    369         else:
    370             progress_text = FmtAmt(progress, fmt='sn')
    371             target_text = FmtAmt(target, fmt='sn')
    372         self.progress_label.hint = self.controller.progress_score_hint_for_current_milestone
    373         self.progress_label.text = '%s/%s' % (progress_text, target_text)
    374         self.progress_bar.SetColor(self.controller.progress_bar_color)
    375         self.progress_bar.SetValue(self.controller.percent_progress_towards_current_milestone)
    376 
    377 
    378 class ClaimButton(Button):
    379     default_pickState = PickState.ON
    380     default_label = GetByLabel('UI/Achievements/Window/Rewards/ClaimRewards')
    381     default_density = Density.COMPACT
    382     default_style = ButtonStyle.SUCCESS
    383     default_frame_type = ButtonFrameType.CUT_BOTTOM_LEFT_RIGHT
    384 
    385     def __init__(self, *args, **kwargs):
    386         super(ClaimButton, self).__init__(*args, **kwargs)
    387         self.func = self.on_claim_rewards_clicked
    388 
    389     def on_claim_rewards_clicked(self, *args):
    390         AchievementsWindow.open_unclaimed_rewards()