tooltip.py (14764B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\achievement_system\client\ui\window\card\tooltip.py 2 import threadutils 3 import uthread2 4 from achievement_system.client.api.signal import on_achievement_completed, on_achievement_progressed, on_admin_achievement_reset, on_admin_achievement_reset_all 5 from achievement_system.client.qa import is_qa 6 from achievement_system.client.qa.actions import qa_complete_achievement, qa_progress_achievement, qa_reset_achievement, qa_show_hero_notification 7 from achievement_system.client.ui.controller.achievement_entry import AchievementEntryController 8 from achievement_system.client.ui.link.drag_data import AchievementDragData 9 from achievement_system.client.ui.window.card.components.expiry import AchievementExpiryTimer 10 from achievement_system.client.ui.window.card.components.icon import AchievementIcon 11 from achievement_system.client.ui.window.card.components.milestones import AchievementMilestonesHover 12 from achievement_system.client.ui.window.card.components.labels import HoverAchievementLabels 13 from achievement_system.client.ui.window.card.components.pin_button import CompactPinButton 14 from achievement_system.client.ui.window.card.components.progress import AchievementProgressHover 15 from achievement_system.client.ui.window.card.components.rewards import AchievementRewardsHover 16 from achievement_system.client.ui.window.card.components.track_button import CompactTrackButton 17 from achievement_system.client.ui.window.const import COMPACT_CARD_WIDTH, COMPACT_CARD_TOOLTIP_WIDTH, TRANSITION_DURATION 18 from achievement_system.client.ui.window.signal import on_achievement_selected 19 from carbonui import Align, Density, uiconst 20 from carbonui.button.group import ButtonGroup, ButtonSizeMode 21 from carbonui.control.contextMenu.menuData import MenuData 22 from carbonui.control.contextMenu.menuUtil import ClearMenuLayer 23 from carbonui.primitives.container import Container 24 from carbonui.primitives.containerAutoSize import ContainerAutoSize 25 from carbonui.primitives.sprite import Sprite 26 from carbonui.primitives.stretchspritevertical import StretchSpriteVertical 27 from carbonui.primitives.transform import Transform 28 from carbonui.uianimations import animations 29 from carbonui.uicore import uicore 30 from carbonui.util.dpi import ScaleDpi 31 from eve.client.script.ui import eveColor 32 ANIMATION_INTRO_DURATION = 0.2 33 ANIMATION_SEQUENCE_TOP = -16 34 ANIMATION_SEQUENCE_DURATION = 0.2 35 ANIMATION_SEQUENCE_INCREASE = 0.075 36 CONTENT_SIDE_PADDING = 16 37 38 class CompactAchievementCardTooltip(ContainerAutoSize): 39 default_width = COMPACT_CARD_TOOLTIP_WIDTH 40 default_align = Align.TOPLEFT 41 default_alignMode = Align.TOTOP 42 default_opacity = 0.0 43 44 def __init__(self, anchor, controller, *args, **kwargs): 45 super(CompactAchievementCardTooltip, self).__init__(*args, **kwargs) 46 self.anchor = anchor 47 self.controller = controller 48 self.content_container = None 49 self.labels = None 50 self.animation_sequence_offset = 0.0 51 self.construct_layout() 52 self.update() 53 self.connect_signals() 54 self.poll_async() 55 56 def Close(self): 57 try: 58 ClearMenuLayer() 59 self.disconnect_signals() 60 finally: 61 super(CompactAchievementCardTooltip, self).Close() 62 63 def connect_signals(self): 64 on_achievement_completed.connect(self.on_achievement_completed) 65 on_achievement_progressed.connect(self.on_achievement_progressed) 66 on_admin_achievement_reset.connect(self.on_achievement_reset) 67 on_admin_achievement_reset_all.connect(self.on_achievement_reset_all) 68 self.controller.on_selected_milestone_changed.connect(self.on_selected_milestone_changed) 69 self.on_size_changed.connect(self.on_size_changed_signal) 70 if self.labels is not None: 71 self.labels.on_name_click.connect(self.on_name_click) 72 if self.content_container is not None: 73 self.content_container.on_size_changed.connect(self.on_content_size_changed_signal) 74 75 def disconnect_signals(self): 76 on_achievement_completed.disconnect(self.on_achievement_completed) 77 on_achievement_progressed.disconnect(self.on_achievement_progressed) 78 on_admin_achievement_reset.disconnect(self.on_achievement_reset) 79 on_admin_achievement_reset_all.disconnect(self.on_achievement_reset_all) 80 self.controller.on_selected_milestone_changed.disconnect(self.on_selected_milestone_changed) 81 self.on_size_changed.disconnect(self.on_size_changed_signal) 82 if self.labels is not None: 83 self.labels.on_name_click.disconnect(self.on_name_click) 84 if self.content_container is not None: 85 self.content_container.on_size_changed.disconnect(self.on_content_size_changed_signal) 86 87 def construct_layout(self): 88 self.construct_containers() 89 self.construct_icon() 90 self.construct_labels() 91 self.construct_milestones() 92 self.construct_progress() 93 self.construct_rewards() 94 self.construct_buttons() 95 self.construct_expiry() 96 self.construct_hover_area() 97 98 def construct_containers(self): 99 self.content_container = ContainerAutoSize(name='content_container', parent=self, align=Align.TOTOP, alignMode=Align.TOTOP, padding=(CONTENT_SIDE_PADDING, 100 8, 101 CONTENT_SIDE_PADDING, 102 22)) 103 self.background_container = TooltipBackground(name='background_container', parent=self, controller=self.controller) 104 105 def construct_icon(self): 106 self.icon_container = Container(name='icon_container', parent=self.content_container, align=Align.TOTOP, height=128, top=36) 107 self.icon = AchievementIcon(name='icon', parent=self.icon_container, align=Align.CENTER, controller=self.controller) 108 109 def construct_labels(self): 110 self.labels = HoverAchievementLabels(name='labels', parent=self.content_container, align=Align.TOTOP, controller=self.controller, padding=(self.compact_padding, 111 8, 112 self.compact_padding, 113 0)) 114 115 def construct_milestones(self): 116 if not self.controller.has_multiple_milestones: 117 return 118 self.milestones = AchievementMilestonesHover(name='milestones', parent=self.content_container, align=Align.TOTOP, controller=self.controller, top=-50, padTop=8, opacity=0.0) 119 120 def construct_progress(self): 121 self.progress = AchievementProgressHover(name='progress', parent=self.content_container, align=Align.TOTOP, controller=self.controller, top=ANIMATION_SEQUENCE_TOP, padTop=16, opacity=0.0) 122 123 def construct_rewards(self): 124 self.rewards = AchievementRewardsHover(name='rewards', parent=self.content_container, align=Align.TOTOP, controller=self.controller, top=ANIMATION_SEQUENCE_TOP, padTop=16, opacity=0.0) 125 126 def construct_buttons(self): 127 self.button_group = ButtonGroup(name='button_group', parent=self.content_container, align=Align.TOTOP, density=Density.COMPACT, button_size_mode=ButtonSizeMode.STRETCH, top=ANIMATION_SEQUENCE_TOP, padTop=16, opacity=0.0) 128 CompactTrackButton(name='track_button', parent=self.button_group, controller=self.controller) 129 CompactPinButton(name='pin_button', parent=self.button_group, controller=self.controller) 130 131 def construct_expiry(self): 132 if not self.controller.is_time_limited: 133 return 134 self.expiry_container = Container(name='expiry_container', parent=self.content_container, align=Align.TOTOP, height=AchievementExpiryTimer.default_height, top=ANIMATION_SEQUENCE_TOP, padTop=16, opacity=0.0) 135 AchievementExpiryTimer(name='expiry_timer', parent=self.expiry_container, align=Align.CENTER, controller=self.controller, use_verbose_text=False) 136 137 def construct_hover_area(self): 138 self.hover_area = Container(name='hover_area', parent=self.content_container, align=Align.CENTER, state=uiconst.UI_NORMAL, opacity=0.0) 139 self.hover_area.OnClick = self.on_hover_area_click 140 self.hover_area.MakeDragObject() 141 self.hover_area.GetDragData = lambda : AchievementDragData(self.controller.achievement_entry.identifier) 142 self.hover_area.GetMenu = self.GetMenu 143 144 def on_hover_area_click(self): 145 on_achievement_selected(self.controller.achievement_entry) 146 self.Close() 147 148 def on_achievement_completed(self, achievement_id): 149 if achievement_id == self.controller.achievement_entry.identifier: 150 self.update_progress() 151 152 def on_achievement_progressed(self, achievement_id, achievement_state): 153 if achievement_id == self.controller.achievement_entry.identifier: 154 self.update_progress() 155 156 def on_achievement_reset(self, achievement_id): 157 if achievement_id == self.controller.achievement_entry.identifier: 158 self.update() 159 160 def on_achievement_reset_all(self): 161 self.update() 162 163 def on_selected_milestone_changed(self): 164 self.update() 165 166 def on_name_click(self, *args): 167 self.on_hover_area_click() 168 169 def on_size_changed_signal(self, width, height): 170 self.background_container.width = width 171 self.background_container.height = height 172 173 def on_content_size_changed_signal(self, width, height): 174 self.hover_area.width = width 175 self.hover_area.height = height 176 177 @threadutils.highlander_threaded 178 def update(self): 179 self.background_container.update() 180 self.SetPosition(0, 0) 181 self.labels.update() 182 self.update_progress() 183 self.icon.update() 184 self.rewards.update() 185 self.animate_in() 186 187 def update_progress(self): 188 self.progress.update() 189 190 def animate_in(self): 191 self.opacity = 1.0 192 animations.MorphScalar(obj=self.icon_container, attrName='top', startVal=self.icon_container.top, endVal=16, duration=ANIMATION_INTRO_DURATION) 193 self.labels.animate_in(duration=ANIMATION_INTRO_DURATION) 194 if self.controller.has_multiple_milestones: 195 self.animate_sequence_component(self.milestones) 196 self.animate_sequence_component(self.progress) 197 self.animate_sequence_component(self.rewards) 198 self.animate_sequence_component(self.button_group) 199 if self.controller.is_time_limited: 200 self.animate_sequence_component(self.expiry_container) 201 202 def animate_sequence_component(self, component): 203 animations.FadeIn(obj=component, duration=ANIMATION_SEQUENCE_DURATION, timeOffset=self.animation_sequence_offset) 204 animations.MorphScalar(obj=component, attrName='top', startVal=component.top, endVal=0, duration=ANIMATION_SEQUENCE_DURATION, timeOffset=self.animation_sequence_offset) 205 self.animation_sequence_offset += ANIMATION_SEQUENCE_INCREASE 206 207 @threadutils.highlander_threaded 208 def poll_async(self): 209 while not self.destroyed: 210 if self.anchor is None or self.anchor.destroyed: 211 self.Close() 212 return 213 if self.is_cursor_inside_hover_area: 214 uthread2.sleep(0.05) 215 else: 216 self.Close() 217 218 @property 219 def is_cursor_inside_hover_area(self): 220 x, y, w, h = self.GetAbsolute() 221 hx, hy, hw, hh = self.hover_area.GetAbsolute() 222 shx = ScaleDpi(hx) 223 shy = ScaleDpi(hy) 224 shw = ScaleDpi(hw) 225 shh = ScaleDpi(hh) 226 if shx < ScaleDpi(x) or shy < ScaleDpi(y): 227 return False 228 cursor_x, cursor_y = uicore.uilib.cursorPos 229 is_inside_x = shx <= cursor_x <= shx + shw 230 is_inside_y = shy <= cursor_y <= shy + shh 231 return is_inside_x and is_inside_y 232 233 @property 234 def compact_padding(self): 235 return (self.default_width - COMPACT_CARD_WIDTH) * 0.5 - CONTENT_SIDE_PADDING 236 237 def SetPosition(self, left, top): 238 anchor_left, anchor_top, anchor_width, anchor_height = self.anchor.GetAbsolute() 239 center_left = anchor_left + anchor_width * 0.5 240 center_top = anchor_top + anchor_height * 0.5 241 self.left = center_left - self.width * 0.5 242 self.top = center_top - 108 243 244 def GetMenu(self): 245 menu_data = MenuData() 246 if is_qa(): 247 menu_data.AddEntry('QA: Complete Achievement', lambda : qa_complete_achievement(self.controller.achievement_entry.identifier)) 248 menu_data.AddEntry('QA: Progress Achievement', lambda : qa_progress_achievement(self.controller.achievement_entry.identifier)) 249 menu_data.AddEntry('QA: Reset Achievement', lambda : qa_reset_achievement(self.controller.achievement_entry.identifier)) 250 menu_data.AddEntry('QA: Show Hero Notification', lambda : qa_show_hero_notification(self.controller.achievement_entry.identifier)) 251 return menu_data 252 253 254 class TooltipBackground(Transform): 255 default_opacity = 1.0 256 default_scalingCenter = (0.5, 0.5) 257 default_scale = (0.8, 0.8) 258 259 def __init__(self, controller, *args, **kwargs): 260 super(TooltipBackground, self).__init__(*args, **kwargs) 261 self.controller = controller 262 self.construct_layout() 263 self.update() 264 self.connect_signals() 265 266 def Close(self): 267 try: 268 self.disconnect_signals() 269 finally: 270 super(TooltipBackground, self).Close() 271 272 def connect_signals(self): 273 self.on_size_changed.connect(self.on_size_changed_signal) 274 275 def disconnect_signals(self): 276 self.on_size_changed.disconnect(self.on_size_changed_signal) 277 278 def construct_layout(self): 279 Sprite(parent=self, align=Align.CENTERTOP, texturePath='res:/UI/Texture/classes/Achievements/card_frame_beacon.png', pos=(-114, 67, 42, 42)) 280 Sprite(parent=self, align=Align.CENTERTOP, texturePath='res:/UI/Texture/classes/Achievements/card_frame_beacon.png', pos=(114, 67, -42, 42)) 281 self.background_frame = StretchSpriteVertical(parent=self, texturePath='res:/UI/Texture/classes/Achievements/card/tooltip_bg_frame.png', topEdgeSize=114, bottomEdgeSize=26) 282 self.background_fill = StretchSpriteVertical(parent=self, texturePath='res:/UI/Texture/classes/Achievements/card/tooltip_bg_fill.png', topEdgeSize=114, bottomEdgeSize=26) 283 284 @threadutils.highlander_threaded 285 def update(self): 286 self.background_frame.color = eveColor.SUCCESS_GREEN if self.controller.is_completed else eveColor.WHITE 287 duration = TRANSITION_DURATION * 0.5 288 animations.FadeIn(self, duration=duration) 289 animations.MorphVector2(obj=self, attrName='scale', startVal=self.scale, endVal=(1.0, 1.0), duration=duration) 290 291 def on_size_changed_signal(self, width, height): 292 self.background_frame.width = width 293 self.background_frame.height = height 294 self.background_fill.width = width 295 self.background_fill.height = height