milestones.py (19784B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\achievement_system\client\ui\window\card\components\milestones.py 2 import math 3 import threadutils 4 from achievement_system.client.api.signal import on_achievement_completed, on_achievement_milestone_reached, on_admin_achievement_reset, on_admin_achievement_reset_all 5 from achievement_system.client.ui.window.const import TRANSITION_DURATION, HISTORIC_COMPLETE_COLOR, HISTORIC_INCOMPLETE_COLOR 6 from carbonui import Align, AxisAlignment, uiconst, TextColor 7 from carbonui.control.buttonIcon import ButtonIcon 8 from carbonui.primitives.container import Container 9 from carbonui.primitives.containerAutoSize import ContainerAutoSize 10 from carbonui.primitives.fill import Fill 11 from carbonui.primitives.flowcontainer import FlowContainer 12 from carbonui.primitives.gridcontainer import GridContainer 13 from carbonui.primitives.sprite import Sprite 14 from carbonui.text.styles import TextBody, TextDetail 15 from carbonui.uianimations import animations 16 from eve.client.script.ui import eveColor 17 from eve.client.script.ui.control.infoIcon import GlyphIcon 18 from localization import GetByLabel 19 BUTTON_SIZE = 16 20 BUTTON_PADDING = 4 21 BAR_MARKER_WIDTH = 4 22 BAR_MARKER_HEIGHT = 16 23 BAR_MARKER_HEIGHT_SELECTED = 24 24 BAR_MARKER_SPACING = 8 25 DOT_MARKER_WIDTH = 4 26 DOT_MARKER_HEIGHT = 8 27 DOT_MARKER_SPACING = 8 28 29 class MilestoneMarker(Container): 30 default_state = uiconst.UI_NORMAL 31 32 def __init__(self, controller, milestone_index, *args, **kwargs): 33 super(MilestoneMarker, self).__init__(*args, **kwargs) 34 self.milestone_index = milestone_index 35 self.controller = controller 36 self.is_hovered = False 37 self.construct_layout() 38 self.update() 39 self.connect_signals() 40 41 def Close(self): 42 try: 43 self.disconnect_signals() 44 finally: 45 super(MilestoneMarker, self).Close() 46 47 def connect_signals(self): 48 on_achievement_completed.connect(self.on_achievement_completed) 49 on_admin_achievement_reset.connect(self.on_achievement_reset) 50 on_admin_achievement_reset_all.connect(self.on_achievement_reset_all) 51 on_achievement_milestone_reached.connect(self.on_achievement_milestone_reached) 52 self.controller.on_selected_milestone_changed.connect(self.on_selected_milestone_changed) 53 54 def disconnect_signals(self): 55 on_achievement_completed.disconnect(self.on_achievement_completed) 56 on_admin_achievement_reset.disconnect(self.on_achievement_reset) 57 on_admin_achievement_reset_all.disconnect(self.on_achievement_reset_all) 58 on_achievement_milestone_reached.disconnect(self.on_achievement_milestone_reached) 59 self.controller.on_selected_milestone_changed.disconnect(self.on_selected_milestone_changed) 60 61 def construct_layout(self): 62 self.fill = Fill(parent=self) 63 self.glyph_container = Container(parent=self, align=Align.CENTER, pos=(0, 0, 16, 16)) 64 65 def construct_glyph(self): 66 self.glyph_container.Flush() 67 self.glyph = GlyphIcon(parent=self.glyph_container, align=Align.CENTER, state=uiconst.UI_DISABLED, frameTexture='res:/ui/Texture/classes/Menu/Icons/circleBG.png', frameColor=self.glyph_frame_color, glyphTexture=self.glyph_texture, glowAmount=self.glyph_glow_amount) 68 69 @threadutils.highlander_threaded 70 def update(self): 71 self.fill.color = self.fill_color 72 self.update_fill_opacity() 73 self.construct_glyph() 74 75 @threadutils.highlander_threaded 76 def update_fill_opacity(self): 77 self.fill.opacity = self.fill_opacity 78 79 @property 80 def fill_color(self): 81 if self.is_completed: 82 if self.is_historic: 83 return HISTORIC_COMPLETE_COLOR 84 return eveColor.SUCCESS_GREEN 85 elif self.is_historic: 86 return HISTORIC_INCOMPLETE_COLOR 87 elif self.is_current: 88 return eveColor.FOCUS_BLUE 89 else: 90 return eveColor.WHITE 91 92 @property 93 def fill_opacity(self): 94 if self.is_selected or self.is_hovered: 95 if self.is_completed: 96 return 0.6 97 return 0.2 98 elif self.is_completed: 99 return 0.3 100 else: 101 return 0.1 102 103 @property 104 def glyph_texture(self): 105 if self.is_completed: 106 return 'res:/ui/Texture/classes/Menu/Icons/checkmark.png' 107 108 @property 109 def glyph_frame_color(self): 110 if self.is_completed: 111 return eveColor.SUCCESS_GREEN 112 if self.is_current: 113 return eveColor.FOCUS_BLUE 114 return TextColor.SECONDARY 115 116 @property 117 def glyph_glow_amount(self): 118 if self.is_completed or self.is_current: 119 return 0.5 120 return 0 121 122 @property 123 def is_completed(self): 124 return self.milestone_index < self.controller.completed_milestones 125 126 @property 127 def is_selected(self): 128 return self.milestone_index == self.controller.selected_milestone_index 129 130 @property 131 def is_current(self): 132 return self.milestone_index == self.controller.current_milestone_index 133 134 @property 135 def is_historic(self): 136 return self.controller.is_historic 137 138 def on_achievement_completed(self, achievement_id): 139 if achievement_id == self.controller.achievement_entry.identifier: 140 self.update() 141 142 def on_achievement_reset(self, achievement_id): 143 if achievement_id == self.controller.achievement_entry.identifier: 144 self.update() 145 146 def on_achievement_reset_all(self): 147 self.update() 148 149 def on_achievement_milestone_reached(self, achievement_id, milestone_id): 150 if achievement_id == self.controller.achievement_entry.identifier: 151 self.update() 152 153 def on_selected_milestone_changed(self): 154 self.update() 155 156 def OnClick(self, *args): 157 self.controller.set_selected_milestone_index(self.milestone_index) 158 159 def OnMouseEnter(self, *args): 160 self.is_hovered = True 161 self.update_fill_opacity() 162 163 def OnMouseExit(self, *args): 164 self.is_hovered = False 165 self.update_fill_opacity() 166 167 168 class MilestoneMarkerExpanded(MilestoneMarker): 169 170 def construct_layout(self): 171 self.fill = Fill(parent=self) 172 self.glyph_container = Container(parent=self, align=Align.TOLEFT, pos=(0, 0, 16, 16), padLeft=8) 173 label_container = Container(name='label_container', parent=self) 174 self.label = TextBody(name='label', parent=label_container, align=Align.CENTERLEFT, state=uiconst.UI_NORMAL, padLeft=8) 175 self.label.OnClick = self.OnClick 176 177 @threadutils.highlander_threaded 178 def update(self): 179 super(MilestoneMarkerExpanded, self).update() 180 self.label.text = self.controller.progress_score_text_for_milestone(self.milestone_index) 181 self.label.hint = self.controller.progress_score_hint_for_milestone(self.milestone_index) 182 183 184 class AchievementMilestonesHover(ContainerAutoSize): 185 label_container_height = 16 186 label_class = TextDetail 187 marker_container_height = 24 188 marker_class = MilestoneMarker 189 max_columns = 5 190 191 def __init__(self, controller, *args, **kwargs): 192 super(AchievementMilestonesHover, self).__init__(*args, **kwargs) 193 self.controller = controller 194 self.construct_layout() 195 self.update() 196 self.connect_signals() 197 198 def Close(self): 199 try: 200 self.disconnect_signals() 201 finally: 202 super(AchievementMilestonesHover, self).Close() 203 204 def connect_signals(self): 205 self.controller.on_selected_milestone_changed.connect(self.on_selected_milestone_changed) 206 207 def disconnect_signals(self): 208 self.controller.on_selected_milestone_changed.disconnect(self.on_selected_milestone_changed) 209 210 def construct_layout(self): 211 label_container = Container(name='label_container', parent=self, align=Align.TOTOP, height=self.label_container_height) 212 self.title_label = self.label_class(name='title_label', parent=label_container, align=Align.TOLEFT, text=GetByLabel('UI/Achievements/Window/Card/SelectedMilestone'), color=TextColor.SECONDARY) 213 self.index_label = self.label_class(name='index_label', parent=label_container, align=Align.TOLEFT, padLeft=4) 214 self.marker_container = GridContainer(name='marker_container', parent=self, align=uiconst.TOTOP, contentSpacing=(8, 8), padTop=4) 215 216 def construct_markers(self): 217 self.marker_container.Flush() 218 total_milestones = self.controller.total_milestones 219 if total_milestones == 0: 220 return 221 self.marker_container.columns = min(total_milestones, self.max_columns) 222 num_rows = math.ceil(total_milestones / self.max_columns) 223 if num_rows > 1: 224 height_from_rows = num_rows * self.marker_container_height 225 height_from_padding = (num_rows - 1) * self.marker_container.contentSpacing[1] 226 self.marker_container.height = height_from_rows + height_from_padding 227 else: 228 self.marker_container.height = self.marker_container_height 229 for index in range(0, self.controller.total_milestones): 230 self.marker_class(parent=self.marker_container, milestone_index=index, controller=self.controller) 231 232 @threadutils.highlander_threaded 233 def update(self): 234 self.update_label() 235 self.construct_markers() 236 237 @threadutils.highlander_threaded 238 def update_label(self): 239 self.index_label.text = '(%s/%s)' % (self.controller.selected_milestone_index + 1, self.controller.total_milestones) 240 241 def on_selected_milestone_changed(self): 242 self.update_label() 243 244 245 class AchievementMilestonesExpanded(AchievementMilestonesHover): 246 label_container_height = 20 247 label_class = TextBody 248 marker_container_height = 28 249 marker_class = MilestoneMarkerExpanded 250 251 252 class BarAchievementMilestones(ContainerAutoSize): 253 default_height = BAR_MARKER_HEIGHT_SELECTED 254 255 def __init__(self, controller, *args, **kwargs): 256 super(BarAchievementMilestones, self).__init__(*args, **kwargs) 257 self.controller = controller 258 self.markers = [] 259 self.construct_layout() 260 self.update() 261 self.connect_signals() 262 263 def Close(self): 264 try: 265 self.disconnect_signals() 266 finally: 267 super(BarAchievementMilestones, self).Close() 268 269 def connect_signals(self): 270 on_achievement_completed.connect(self.on_achievement_completed) 271 on_achievement_milestone_reached.connect(self.on_achievement_milestone_reached) 272 on_admin_achievement_reset.connect(self.on_achievement_reset) 273 on_admin_achievement_reset_all.connect(self.on_achievement_reset_all) 274 self.controller.on_selected_milestone_changed.connect(self.on_selected_milestone_changed) 275 276 def disconnect_signals(self): 277 on_achievement_completed.disconnect(self.on_achievement_completed) 278 on_achievement_milestone_reached.disconnect(self.on_achievement_milestone_reached) 279 on_admin_achievement_reset.disconnect(self.on_achievement_reset) 280 on_admin_achievement_reset_all.disconnect(self.on_achievement_reset_all) 281 self.controller.on_selected_milestone_changed.disconnect(self.on_selected_milestone_changed) 282 283 def construct_layout(self): 284 self.back_button_container = Container(name='back_button_container', parent=self, align=Align.TOLEFT, width=BUTTON_SIZE) 285 ButtonIcon(name='back_button', parent=self.back_button_container, align=Align.CENTER, texturePath='res:/UI/Texture/classes/Achievements/chevron_back.png', iconSize=BUTTON_SIZE, width=BUTTON_SIZE, func=self.on_milestone_back_clicked) 286 self.label_container = ContainerAutoSize(name='label_container', parent=self, align=Align.TOLEFT, padLeft=BUTTON_PADDING) 287 TextBody(name='milestone_label', parent=self.label_container, align=Align.CENTER, color=TextColor.SECONDARY, text='%s:' % GetByLabel('UI/Achievements/Window/Card/Milestone'), padTop=-1) 288 total_width = self.controller.total_milestones * BAR_MARKER_WIDTH + self.controller.total_milestones * BAR_MARKER_SPACING 289 self.milestone_bar_container = FlowContainer(name='milestone_bar_container', parent=self, align=Align.TOLEFT, width=total_width, height=BAR_MARKER_HEIGHT_SELECTED, contentSpacing=(BAR_MARKER_SPACING, 0), contentAlignment=AxisAlignment.CENTER, crossAxisAlignment=AxisAlignment.CENTER, padLeft=5) 290 self.right_button_container = Container(name='right_button_container', parent=self, align=Align.TOLEFT, width=BUTTON_SIZE, padLeft=-2) 291 ButtonIcon(name='next_button', parent=self.right_button_container, align=Align.CENTER, texturePath='res:/UI/Texture/classes/Achievements/chevron_front.png', iconSize=BUTTON_SIZE, width=BUTTON_SIZE, padLeft=BUTTON_PADDING, func=self.on_milestone_next_clicked) 292 293 @threadutils.highlander_threaded 294 def update(self): 295 self.milestone_bar_container.Flush() 296 self.markers = [] 297 for index in range(0, self.controller.total_milestones): 298 marker = BarMilestoneMarker(parent=self.milestone_bar_container, is_completed=index < self.controller.completed_milestones, is_selected=index == self.controller.selected_milestone_index, is_historic=self.controller.is_historic) 299 self.markers.append(marker) 300 301 def on_milestone_back_clicked(self): 302 index = self.controller.selected_milestone_index 303 if index >= 1: 304 self.controller.set_selected_milestone_index(max(index - 1, 0)) 305 306 def on_milestone_next_clicked(self): 307 index = self.controller.selected_milestone_index 308 if index + 1 == self.controller.total_milestones: 309 return 310 if index < self.controller.total_milestones: 311 self.controller.set_selected_milestone_index(min(index + 1, self.controller.total_milestones)) 312 313 def on_achievement_completed(self, achievement_id): 314 if achievement_id == self.controller.achievement_entry.identifier: 315 self.update() 316 317 def on_achievement_milestone_reached(self, achievement_id, milestone_id): 318 if achievement_id == self.controller.achievement_entry.identifier: 319 self.update() 320 321 def on_achievement_reset(self, achievement_id): 322 if achievement_id == self.controller.achievement_entry.identifier: 323 self.update() 324 325 def on_achievement_reset_all(self): 326 self.update() 327 328 def on_selected_milestone_changed(self): 329 for index, marker in enumerate(self.markers): 330 marker.is_completed = index < self.controller.completed_milestones 331 is_selected = index == self.controller.selected_milestone_index 332 if is_selected: 333 marker.select() 334 else: 335 marker.deselect() 336 337 338 class BarMilestoneMarker(Container): 339 default_height = BAR_MARKER_HEIGHT_SELECTED 340 default_width = BAR_MARKER_WIDTH 341 342 def __init__(self, is_completed = False, is_selected = False, is_historic = False, *args, **kwargs): 343 super(BarMilestoneMarker, self).__init__(*args, **kwargs) 344 self.is_completed = is_completed 345 self.is_selected = is_selected 346 self.is_historic = is_historic 347 self.construct_layout() 348 349 def construct_layout(self): 350 self.fill = Fill(parent=self, align=Align.CENTER, color=self.fill_color, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=self.glow_brightness, width=BAR_MARKER_WIDTH, height=self.fill_height) 351 352 @property 353 def fill_height(self): 354 if self.is_selected: 355 return BAR_MARKER_HEIGHT_SELECTED 356 return BAR_MARKER_HEIGHT 357 358 @property 359 def fill_color(self): 360 if self.is_completed: 361 if not self.is_historic: 362 return eveColor.SUCCESS_GREEN 363 return HISTORIC_COMPLETE_COLOR 364 elif not self.is_historic: 365 return eveColor.FOCUS_BLUE 366 else: 367 return HISTORIC_INCOMPLETE_COLOR 368 369 @property 370 def glow_brightness(self): 371 if self.is_selected: 372 return 0.3 373 return 0.0 374 375 def select(self): 376 self.is_selected = True 377 self.animate() 378 379 def deselect(self): 380 self.is_selected = False 381 self.animate() 382 383 def animate(self): 384 animations.MorphScalar(obj=self.fill, attrName='height', startVal=self.fill.height, endVal=self.fill_height, duration=TRANSITION_DURATION) 385 animations.MorphScalar(obj=self.fill, attrName='glowBrightness', startVal=self.fill.glowBrightness, endVal=self.glow_brightness, duration=TRANSITION_DURATION) 386 animations.SpColorMorphTo(obj=self.fill, startColor=self.fill.color, endColor=self.fill_color, duration=TRANSITION_DURATION) 387 388 389 class DotAchievementMilestones(Container): 390 default_height = DOT_MARKER_HEIGHT 391 392 def __init__(self, controller, *args, **kwargs): 393 super(DotAchievementMilestones, self).__init__(*args, **kwargs) 394 self.controller = controller 395 self.construct_layout() 396 self.update() 397 self.connect_signals() 398 399 def Close(self): 400 try: 401 self.disconnect_signals() 402 finally: 403 super(DotAchievementMilestones, self).Close() 404 405 def connect_signals(self): 406 on_achievement_milestone_reached.connect(self.on_achievement_milestone_reached) 407 408 def disconnect_signals(self): 409 on_achievement_milestone_reached.disconnect(self.on_achievement_milestone_reached) 410 411 def construct_layout(self): 412 self.marker_container = FlowContainer(name='marker_container', parent=self, contentSpacing=(DOT_MARKER_SPACING, 0), contentAlignment=AxisAlignment.CENTER, crossAxisAlignment=AxisAlignment.CENTER) 413 414 @threadutils.highlander_threaded 415 def update(self): 416 self.marker_container.Flush() 417 for index in range(0, self.controller.total_milestones): 418 DotMilestoneMarker(parent=self.marker_container, is_completed=index < self.controller.completed_milestones, is_selected=index == self.controller.selected_milestone_index, is_historic=self.controller.is_historic) 419 420 def on_achievement_milestone_reached(self, achievement_id, milestone_id): 421 if achievement_id == self.controller.achievement_entry.identifier: 422 self.update() 423 424 425 class DotMilestoneMarker(Container): 426 default_height = DOT_MARKER_HEIGHT 427 default_width = DOT_MARKER_WIDTH 428 429 def __init__(self, is_completed = False, is_selected = False, is_historic = False, *args, **kwargs): 430 super(DotMilestoneMarker, self).__init__(*args, **kwargs) 431 self.is_completed = is_completed 432 self.is_selected = is_selected 433 self.is_historic = is_historic 434 self.construct_layout() 435 436 def construct_layout(self): 437 self.dot = Sprite(name='dot', parent=self, align=Align.CENTER, state=uiconst.UI_DISABLED, texturePath='res://UI/Texture/classes/Achievements/card/milestone_dot.png', color=self.fill_color, outputMode=uiconst.OUTPUT_COLOR_AND_GLOW, glowBrightness=self.glow_brightness, pos=(0, 438 0, 439 DOT_MARKER_WIDTH, 440 DOT_MARKER_HEIGHT)) 441 442 @property 443 def fill_height(self): 444 if self.is_selected: 445 return BAR_MARKER_HEIGHT_SELECTED 446 return BAR_MARKER_HEIGHT 447 448 @property 449 def fill_color(self): 450 if self.is_completed: 451 if not self.is_historic: 452 return eveColor.SUCCESS_GREEN 453 return HISTORIC_COMPLETE_COLOR 454 elif self.is_selected: 455 if not self.is_historic: 456 return eveColor.FOCUS_BLUE 457 return HISTORIC_INCOMPLETE_COLOR 458 elif not self.is_historic: 459 return eveColor.SMOKE_BLUE 460 else: 461 return HISTORIC_INCOMPLETE_COLOR 462 463 @property 464 def glow_brightness(self): 465 if self.is_selected: 466 return 0.3 467 return 0.0