overview_panel.py (21452B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\theatersOfWar\campaigns\panels\overview_panel.py 2 import eve.client.script.ui.shared.theatersOfWar.campaigns.panels.panel_const as panel_const 3 import logging 4 import uthread2 5 from achievement_system.client.api.signal import on_achievement_progressed 6 from campaigns.client.errors import CampaignRequestError 7 from campaigns.client.settings import campaign_animate_background 8 from campaigns.client.v1.signals import on_campaign_completed 9 from carbonui import Align, PickState, TextColor 10 from carbonui.primitives.container import Container 11 from carbonui.primitives.containerAutoSize import ContainerAutoSize 12 from carbonui.primitives.layoutGrid import LayoutGrid 13 from carbonui.primitives.sprite import Sprite, StreamingVideoSprite 14 from carbonui.text.custom import TextCustom 15 from carbonui.text.styles import TextDetail, TextBody, TextHeader 16 from carbonui.uianimations import animations 17 from carbonui.uiconst import OUTPUT_COLOR_AND_GLOW, SpriteEffect 18 from eve.client.script.ui import eveColor 19 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.achievement_banner import AchievementBanner 20 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.base_scrolling_page import BaseScrollingPage 21 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.outcome_panel import OutcomePanel 22 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.overview_job_provider_panel import CampaignJobProviderSectionPanel 23 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.progress_cont import ProgressCont 24 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.segmentedVideo import SegmentedVideoCont 25 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.static_background import StaticBackground 26 from eve.client.script.ui.shared.theatersOfWar.campaigns.panels.stats_cont import StatsContainer 27 from eveexceptions import ExceptionEater 28 from jobboard.client.features.campaigns.recommended_card_section import RecommendedCont 29 from localization.formatters.timeIntervalFormatters import GetByLabel 30 logger = logging.getLogger(__name__) 31 32 class CampaignOverview(BaseScrollingPage): 33 default_name = 'campaignOverview' 34 default_align = Align.TOTOP 35 default_display = True 36 37 def ApplyAttributes(self, attributes): 38 self.achievement_cont = None 39 super(CampaignOverview, self).ApplyAttributes(attributes) 40 self.campaignPanelController = attributes.campaignPanelController 41 self._campaign_id = self.campaignPanelController.selected_campaign_id 42 self._construct_ui() 43 self.connect_signals() 44 45 def _construct_ui(self): 46 self.Flush() 47 self.outcome_cont = Container(name='outcome_cont', parent=self, align=Align.TOALL, display=False) 48 self.overview_cont = Container(name='overview_cont', parent=self, align=Align.TOALL, display=False) 49 self.objective_cont = Container(name='objective_cont', parent=self, align=Align.TOALL, top=700, display=False) 50 self._objective_right_side = Container(parent=self.objective_cont, name='_objective_right_side', align=Align.TORIGHT, width=500) 51 self._objective_left_side = Container(parent=self.objective_cont, name='_objective_left_side', align=Align.TOALL, left=panel_const.PANEL_LEFT_PADDING) 52 self._overview_right_side = Container(parent=self.overview_cont, name='_overview_right_side', align=Align.TORIGHT, width=620) 53 self._overview_left_side = Container(parent=self.overview_cont, name='_overview_left_side', align=Align.TOALL, left=panel_const.PANEL_LEFT_PADDING, minWidth=300) 54 self._construct_outcome_panel() 55 self._construct_campaign_bg() 56 self._construct_campaign_info_section() 57 self._construct_progress_section() 58 self._construct_stats() 59 self._construct_achievement() 60 self._construct_recommended() 61 self._construct_all_objectives() 62 self.change_page(self.campaignPanelController.selected_campaign_page_id, None, False) 63 64 def connect_signals(self): 65 on_campaign_completed.connect(self.on_campaign_competed) 66 campaign_animate_background.on_change.connect(self.on_animation_setting_changed) 67 self.campaignPanelController.on_contribution_completed_objective.connect(self.on_objective_completed_by_contribution) 68 on_achievement_progressed.connect(self.on_achievement_progressed) 69 70 def disconnect_signals(self): 71 on_campaign_completed.disconnect(self.on_campaign_competed) 72 campaign_animate_background.on_change.disconnect(self.on_animation_setting_changed) 73 self.campaignPanelController.on_contribution_completed_objective.disconnect(self.on_objective_completed_by_contribution) 74 on_achievement_progressed.disconnect(self.on_achievement_progressed) 75 76 def _construct_outcome_panel(self): 77 self.outcome_cont.Flush() 78 self.outcome_panel = OutcomePanel(parent=self.outcome_cont) 79 80 def _construct_campaign_bg(self): 81 self.bg_cont = Container(name='bg_cont', parent=self) 82 self.static_background_cont = StaticBackgroundWithParallax(name='static_background_cont', parent=self.bg_cont, display=False) 83 self.video_background_cont = VideoBackground(name='video_background_cont', parent=self.bg_cont, display=False) 84 self.campaign_ambient_bg = Sprite(parent=self, align=Align.TOALL, pickState=PickState.OFF) 85 self._update_bg_states() 86 87 def on_animation_setting_changed(self, newValue): 88 self._update_bg_states() 89 self._load_campaign_bg() 90 91 def _update_bg_states(self): 92 if campaign_animate_background.get(): 93 self.static_background_cont.Hide() 94 self.video_background_cont.Show() 95 else: 96 self.static_background_cont.Show() 97 self.video_background_cont.Hide() 98 self.video_background_cont.pause_videos() 99 100 def on_achievement_progressed(self, achievement_id, achievement_state): 101 if self.achievement_cont: 102 self.achievement_cont.on_achievement_progressed(achievement_id, achievement_state) 103 104 def _construct_campaign_info_section(self): 105 top = 48 106 self.info_cont = ContainerAutoSize(name='info_cont', parent=self._overview_left_side, align=Align.TOTOP, top=top) 107 self.info_cont.orignal_top = self.info_cont.top 108 self.date_label = TextDetail(parent=self.info_cont, align=Align.TOTOP, color=TextColor.SECONDARY) 109 cont = ContainerAutoSize(parent=self.info_cont, align=Align.TOTOP, alignMode=Align.CENTERLEFT, top=8) 110 self.campaign_icon = Sprite(parent=cont, align=Align.CENTERLEFT, pos=(0, 0, 16, 16)) 111 self.issuer_label = TextBody(parent=cont, align=Align.CENTERLEFT, left=self.campaign_icon.width + 8) 112 self.title_label = TextCustom(parent=self.info_cont, align=Align.TOTOP, fontsize=96, lineSpacing=-0.2, color=TextColor.HIGHLIGHT, maxLines=2) 113 self.subtitle_label = TextBody(parent=self.info_cont, align=Align.TOTOP, color=TextColor.SECONDARY, pickState=PickState.ON) 114 115 def _construct_progress_section(self): 116 progress_cont = ContainerAutoSize(name='progress_cont', parent=self._overview_left_side, align=Align.TOTOP, top=32) 117 text_cont = ContainerAutoSize(name='text_cont', parent=progress_cont, align=Align.TOTOP, alignMode=Align.TOTOP) 118 right_text_cont = ContainerAutoSize(parent=text_cont, align=Align.TORIGHT) 119 TextDetail(name='objectives_completed', parent=text_cont, text=GetByLabel('UI/Campaigns/ObjectivesCompleted'), align=Align.TOTOP, color=TextColor.SECONDARY) 120 self.num_objectives = TextDetail(name='num_objectives', parent=right_text_cont, align=Align.TORIGHT, color=TextColor.SECONDARY) 121 completed_label_cont = ContainerAutoSize(parent=right_text_cont, align=Align.TORIGHT) 122 self.completed_label = TextBody(name='completed_label', parent=completed_label_cont, align=Align.BOTTOMRIGHT, color=eveColor.SUCCESS_GREEN, bold=True, upperCase=True, text=GetByLabel('UI/Campaigns/CampaignCompleted'), left=8, outputMode=OUTPUT_COLOR_AND_GLOW, glowBrightness=0.4, display=False) 123 self.progress_grid = ProgressCont(parent=progress_cont, top=8) 124 125 def _construct_stats(self): 126 self.stats_cont = ContainerAutoSize(name='stats_cont', parent=self._overview_left_side, align=Align.TOTOP, top=64) 127 grid = LayoutGrid(parent=self.stats_cont, columns=3, cellSpacing=64) 128 self.stat_completed = StatsContainer(parent=grid, stat_name=GetByLabel('UI/Campaigns/ObjectivesCompleted')) 129 self.stat_days_left = StatsContainer(parent=grid, stat_name=GetByLabel('UI/Campaigns/DaysToComplete')) 130 self.stat_contributors = StatsContainer(parent=grid, stat_name=GetByLabel('UI/Campaigns/NumContributors')) 131 132 def _construct_achievement(self): 133 self.achievement_cont = AchievementBanner(parent=self._objective_right_side, align=Align.TORIGHT, pos=(144, 0, 320, 0), campaignPanelController=self.campaignPanelController) 134 135 def _construct_recommended(self): 136 self.recommended_section = RecommendedCont(parent=self._objective_left_side, padBottom=24, title=GetByLabel('UI/Campaigns/RecommendedObjectives'), campaign_id=self._campaign_id, padTop=24) 137 138 def _construct_all_objectives(self): 139 all_objectives_cont = Container(name='all_objectives_cont', parent=self._objective_left_side, align=Align.TOALL) 140 TextHeader(parent=all_objectives_cont, text=GetByLabel('UI/Campaigns/AllObjectives'), align=Align.TOTOP, top=24) 141 self.job_panel = CampaignJobProviderSectionPanel(parent=all_objectives_cont, campaignPanelController=self.campaignPanelController) 142 143 def load_ui(self): 144 campaign_controller = self.campaignPanelController.selected_campaign_controller 145 self._load_campaign_bg() 146 if campaign_controller.is_expired: 147 self.outcome_cont.Show() 148 self.overview_cont.Hide() 149 self.objective_cont.Hide() 150 self._load_outcome(campaign_controller) 151 else: 152 self.outcome_cont.Hide() 153 self.overview_cont.Show() 154 self.objective_cont.Show() 155 self._load_info_section(campaign_controller) 156 self.job_panel.AutoSelect() 157 uthread2.StartTasklet(self._load_progress_ui) 158 self.animate_in() 159 160 def _load_progress_ui(self): 161 campaign_controller = self.campaignPanelController.selected_campaign_controller 162 self._load_progress_section(campaign_controller) 163 self._load_stats(campaign_controller) 164 self.completed_label.display = campaign_controller.is_completed 165 166 def _load_campaign_bg(self): 167 campaign_controller = self.campaignPanelController.selected_campaign_controller 168 if campaign_animate_background.get(): 169 selected_page_id = self.campaignPanelController.selected_campaign_page_id 170 self.video_background_cont.load_ui(campaign_controller, selected_page_id == panel_const.PANEL_ID_OVERVIEW) 171 else: 172 self.static_background_cont.load_ui(campaign_controller) 173 self.campaign_ambient_bg.texturePath = campaign_controller.textures.ambient_background 174 175 def _load_info_section(self, campaign_controller): 176 self.date_label.text = campaign_controller.get_duration_text() 177 self.campaign_icon.texturePath = campaign_controller.textures.icon_path 178 self.issuer_label.text = campaign_controller.issuer_name 179 fontFamily = campaign_controller.font_family 180 self.title_label.fontFamily = fontFamily 181 self.title_label.text = campaign_controller.title_text.upper() 182 self.subtitle_label.text = campaign_controller.subtitle_text 183 184 def _load_progress_section(self, campaign_controller): 185 current_progress = campaign_controller.current_progress 186 current = min(current_progress, campaign_controller.target_progress) 187 text = '%s/%s' % (current, campaign_controller.target_progress) 188 self.num_objectives.text = text 189 self.progress_grid.load_progress(current_progress, campaign_controller.target_progress, progress_color=campaign_controller.theme_pack.accent) 190 191 def _load_stats(self, campaign_controller): 192 try: 193 progress = campaign_controller.current_progress 194 completed = progress or 0 195 contributors = campaign_controller.total_contributors or 0 196 except CampaignRequestError: 197 logger.exception('Failed to load campaign stats') 198 completed = ' ' 199 contributors = ' ' 200 201 color = campaign_controller.theme_pack.focus 202 self.stat_completed.load_stats(completed, color=color) 203 self.stat_days_left.load_stats(campaign_controller.num_days_left, color=color) 204 self.stat_contributors.load_stats(contributors, color=color) 205 206 def _load_outcome(self, campaign_controller): 207 victory = campaign_controller.is_expired and campaign_controller.is_completed 208 if victory: 209 resolution_state_text = campaign_controller.text.finished_success_resolution_state_text 210 resolution_desc = campaign_controller.text.finished_success_description_text 211 else: 212 resolution_state_text = campaign_controller.text.finished_failure_resolution_state_text 213 resolution_desc = campaign_controller.text.finished_failure_description_text 214 self.outcome_panel.load_ui(campaign_controller.text.finished_campaign_ended_text, campaign_controller.title_text, resolution_state_text, resolution_desc, campaign_controller.theme_pack) 215 216 def animate_in(self): 217 selected_page_id = self.campaignPanelController.selected_campaign_page_id 218 if selected_page_id != panel_const.PANEL_ID_OVERVIEW: 219 return 220 morph_duration = 1.0 221 self.static_background_cont.do_parallax_animation(morph_duration) 222 morph(self._overview_left_side, 'top', 0, morph_duration, 100) 223 224 def change_page(self, new_page_id, old_page_id, animate = True): 225 new_page_id = new_page_id or panel_const.PANEL_ID_OVERVIEW 226 duration = 1.0 227 morph_duration = duration if animate else 0 228 if new_page_id in (panel_const.PANEL_ID_OVERVIEW, panel_const.PANEL_ID_OBJECTIVES): 229 self._change_opacity(new_page_id, duration, animate) 230 if new_page_id == panel_const.PANEL_ID_OBJECTIVES: 231 self.animate_go_to_objectives_panel(morph_duration, old_page_id) 232 elif new_page_id == panel_const.PANEL_ID_OVERVIEW: 233 self.animate_go_to_overview_panel(morph_duration, old_page_id) 234 else: 235 morph(self.objective_cont, 'top', 0, morph_duration) 236 self._update_video_playing(new_page_id, old_page_id) 237 238 def _update_video_playing(self, new_page_id, old_page_id): 239 if not campaign_animate_background.get(): 240 return 241 if new_page_id == old_page_id: 242 return 243 if new_page_id == panel_const.PANEL_ID_OVERVIEW: 244 self.video_background_cont.play_videos() 245 elif new_page_id == panel_const.PANEL_ID_OBJECTIVES: 246 self.video_background_cont.pause_videos() 247 else: 248 self.video_background_cont.pause_videos() 249 self.video_background_cont.hide_videos() 250 251 def animate_go_to_objectives_panel(self, morph_duration, old_page_id): 252 if old_page_id is None: 253 morph_duration = 0 254 info_panel_to_value = min(-200, -self.info_cont.height) 255 morph(self.info_cont, 'top', info_panel_to_value, morph_duration) 256 morph(self.objective_cont, 'top', 75, morph_duration) 257 morph(self._overview_right_side, 'width', 520, morph_duration) 258 if campaign_animate_background.get() and old_page_id == panel_const.PANEL_ID_OVERVIEW: 259 self.video_background_cont.animate_out() 260 261 def animate_go_to_overview_panel(self, morph_duration, old_page_id): 262 morph(self.info_cont, 'top', self.info_cont.orignal_top, morph_duration) 263 morph(self.objective_cont, 'top', self.height - 150, morph_duration) 264 morph(self._overview_right_side, 'width', 620, morph_duration) 265 266 def _change_opacity(self, current_page_id, duration, animate): 267 fade_elements = {panel_const.PANEL_ID_OVERVIEW: [self.info_cont, self.bg_cont, self.stats_cont], 268 panel_const.PANEL_ID_OBJECTIVES: [self.achievement_cont]} 269 for page_id, element_list in fade_elements.iteritems(): 270 for element in element_list: 271 if element is None: 272 return 273 if current_page_id != page_id: 274 if animate: 275 animations.FadeOut(element, duration=duration, callback=element.Hide) 276 else: 277 element.opacity = 0.0 278 element.Hide() 279 else: 280 element.Show() 281 if animate: 282 animations.FadeIn(element, duration=duration) 283 else: 284 element.opacity = 1.0 285 286 def _on_size_changed(self, width, height): 287 current_page_id = self.campaignPanelController.selected_campaign_page_id or 0 288 if current_page_id == panel_const.PANEL_ID_OVERVIEW: 289 self.objective_cont.top = self.height - 150 290 291 def on_campaign_competed(self, campaign_id): 292 self._load_progress_ui() 293 294 def on_objective_completed_by_contribution(self, objective_id, campaign_id): 295 self._load_progress_ui() 296 297 def Close(self): 298 super(CampaignOverview, self).Close() 299 with ExceptionEater('Closing CampaignOverview'): 300 self.disconnect_signals() 301 302 303 class StaticBackgroundWithParallax(StaticBackground): 304 305 def do_parallax_animation(self, morph_duration): 306 morph(self.campaign_bg, 'top', self.campaign_bg.top, morph_duration, self.campaign_bg.top - 120) 307 morph(self.campaign_bg, 'left', self.campaign_bg.left, morph_duration, self.campaign_bg.left + 40) 308 morph(self.campaign_middleground, 'top', self.campaign_middleground.top, morph_duration, self.campaign_middleground.top - 60) 309 morph(self.campaign_middleground, 'left', self.campaign_middleground.left, morph_duration, self.campaign_middleground.left + 60) 310 morph(self.campaign_middleground, 'width', self.campaign_middleground.width, morph_duration, self.campaign_middleground.width + 80) 311 morph(self.campaign_middleground, 'height', self.campaign_middleground.height, morph_duration, self.campaign_middleground.height + 142) 312 morph(self.campaign_foreground, 'top', self.campaign_foreground.top, morph_duration, self.campaign_foreground.top - 80) 313 morph(self.campaign_foreground, 'left', self.campaign_foreground.left, morph_duration, self.campaign_foreground.left - 160) 314 315 316 class VideoBackground(Container): 317 318 def ApplyAttributes(self, attributes): 319 self._videos_loaded = False 320 super(VideoBackground, self).ApplyAttributes(attributes) 321 self.campaign_foreground_video = SegmentedVideoCont(name='campaign_foreground_video', parent=self, align=Align.TOPRIGHT, pos=(-280, 320, 1152, 648), pickState=PickState.OFF) 322 self.campaign_middleground_video = SegmentedVideoCont(name='campaign_middleground_video', parent=self, align=Align.TOPRIGHT, pos=(0, -30, 648, 1152), pickState=PickState.OFF) 323 self.campaign_bg_video = StreamingVideoSprite(name='campaign_bg_video', parent=self, align=Align.TOPRIGHT, pos=(-15, -100, 648, 1152), pickState=PickState.OFF, spriteEffect=SpriteEffect.COPY, videoLoop=True) 324 325 def load_ui(self, campaign_controller, start_videos = False): 326 return uthread2.StartTasklet(self._load_ui, campaign_controller, start_videos) 327 328 def _load_ui(self, campaign_controller, start_videos): 329 self.campaign_foreground_video.load_videos(*campaign_controller.textures.dashboard_foreground_videos) 330 self.campaign_middleground_video.load_videos(*campaign_controller.textures.dashboard_middleground_videos) 331 try: 332 background_path = campaign_controller.textures.dashboard_background_video 333 if self.campaign_bg_video.path == background_path: 334 self.campaign_bg_video.Play() 335 else: 336 self.campaign_bg_video.SetVideoPath(background_path, videoLoop=True) 337 except RuntimeError: 338 logger.exception('failed to play video') 339 340 self._videos_loaded = True 341 if start_videos: 342 self.play_videos() 343 344 def animate_out(self): 345 self.campaign_foreground_video.skip_loop() 346 347 def pause_videos(self): 348 self.campaign_foreground_video.pause_videos() 349 self.campaign_middleground_video.pause_videos() 350 self.campaign_bg_video.Pause() 351 352 def play_videos(self): 353 self.campaign_foreground_video.play() 354 self.campaign_middleground_video.play() 355 self.campaign_bg_video.Play() 356 self.campaign_bg_video.Show() 357 358 def hide_videos(self): 359 self.campaign_foreground_video.hide_videos() 360 self.campaign_middleground_video.hide_videos() 361 self.campaign_bg_video.Hide() 362 363 364 def morph(obj, attributeName, to_value, duration, startValue = None): 365 if duration == 0: 366 setattr(obj, attributeName, to_value) 367 else: 368 if startValue is None: 369 startValue = getattr(obj, attributeName) 370 animations.MorphScalar(obj, attributeName, startValue, to_value, duration=duration)