saveSkinButton.py (10965B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\cosmetics\ship\pages\studio\saveSkinButton.py 2 import eveicon 3 import uthread2 4 from carbonui import ButtonStyle, TextColor, uiconst 5 from carbonui.text.styles import TextBody 6 from carbonui.control.button import Button 7 from cosmetics.client.ships import ship_skin_signals 8 from cosmetics.client.shipSkinDesignSvc import get_ship_skin_design_svc 9 from cosmetics.client.ships.qa.settings import should_show_popup_if_skin_name_missing 10 from cosmetics.client.ships.skins.errors import DESIGN_ERROR_TEXT_BY_CODE, SkinDesignManagementError 11 from cosmetics.client.ships.skins.live_data import current_skin_design, current_skin_design_signals 12 from cosmetics.client.ships.skins.live_data.skin_design_editor_config import SkinDesignEditorConfig 13 from cosmetics.common.ships.skins.static_data import saved_designs_const 14 from cosmetics.common.ships.skins.static_data.slot_name import SlotID 15 from eve.client.script.ui import eveColor 16 from player_messaging.client.ui_message import message_player 17 from eve.client.script.ui.control.tooltips import TooltipPanel 18 from eve.client.script.ui.cosmetics.ship.pages.studio.skinNameDialogue import SkinNameDialogue 19 from eve.client.script.ui.shared.shipTree.infoBubble import SkillEntry 20 from localization import GetByLabel 21 from skills.client.util import get_skill_service 22 23 class SaveSkinButton(Button): 24 default_texturePath = eveicon.load 25 __notifyevents__ = ['OnSkillsChanged'] 26 27 def __init__(self, *args, **kwargs): 28 super(SaveSkinButton, self).__init__(*args, **kwargs) 29 self.func = self.on_save_button_click 30 self.design_count = 0 31 self.design_limit = 0 32 self.has_fitted_components = False 33 self.save_requirements_met = False 34 self.button_state_thread = None 35 self.save_design_thread = None 36 self.connect_signals() 37 self.update_button_state() 38 39 def Close(self): 40 try: 41 self.kill_threads() 42 self.disconnect_signals() 43 finally: 44 super(SaveSkinButton, self).Close() 45 46 def kill_threads(self): 47 if self.button_state_thread is not None: 48 self.button_state_thread.kill() 49 self.button_state_thread = None 50 if self.save_design_thread is not None: 51 self.save_design_thread.kill() 52 self.save_design_thread = None 53 54 def connect_signals(self): 55 current_skin_design_signals.on_design_reset.connect(self.on_new_design_initialized) 56 current_skin_design_signals.on_existing_design_loaded.connect(self.on_existing_design_loaded) 57 current_skin_design_signals.on_slot_fitting_changed.connect(self.on_slot_fitting_changed) 58 ship_skin_signals.on_skin_design_saved.connect(self.on_skin_design_saved) 59 sm.RegisterNotify(self) 60 61 def disconnect_signals(self): 62 current_skin_design_signals.on_design_reset.disconnect(self.on_new_design_initialized) 63 current_skin_design_signals.on_existing_design_loaded.disconnect(self.on_existing_design_loaded) 64 current_skin_design_signals.on_slot_fitting_changed.disconnect(self.on_slot_fitting_changed) 65 ship_skin_signals.on_skin_design_saved.disconnect(self.on_skin_design_saved) 66 sm.UnregisterNotify(self) 67 68 def OnSkillsChanged(self, *args): 69 try: 70 self.design_limit = get_ship_skin_design_svc().get_saved_designs_capacity(force_refresh=True) 71 except Exception as e: 72 self.design_limit = 0 73 74 self.update_button_state() 75 76 def update_button_state(self): 77 self.button_state_thread = uthread2.StartTasklet(self.update_button_state_async) 78 79 def update_button_state_async(self): 80 self.busy = True 81 try: 82 self.load_data() 83 self.validate_save_requirements() 84 self.style = ButtonStyle.NORMAL if self.save_requirements_met else ButtonStyle.DANGER 85 self.disabled = not self.has_fitted_components and self.save_requirements_met 86 finally: 87 self.button_state_thread = None 88 self.busy = False 89 90 def load_data(self): 91 try: 92 self.design_count = len(get_ship_skin_design_svc().get_all_owned_designs()) 93 except Exception as e: 94 self.design_count = 0 95 96 try: 97 self.design_limit = get_ship_skin_design_svc().get_saved_designs_capacity() 98 except Exception as e: 99 self.design_limit = 0 100 101 def validate_save_requirements(self): 102 self.has_fitted_components = current_skin_design.get().has_fitted_components() 103 self.save_requirements_met = not self.is_restricted_by_design_limit() 104 105 def is_restricted_by_design_limit(self): 106 skin_design = current_skin_design.get() 107 if skin_design.saved_skin_design_id and skin_design.creator_character_id == session.charid: 108 return False 109 else: 110 return self.design_count >= self.design_limit 111 112 def on_save_button_click(self, *args): 113 if not self.save_requirements_met or not self.has_fitted_components: 114 return 115 if should_show_popup_if_skin_name_missing.is_enabled(): 116 dialogue = SkinNameDialogue(window_name=self.get_dialogue_window_name()) 117 dialogue.on_submit.connect(self.on_submit) 118 dialogue.on_submit_failed.connect(self.on_submit_failed) 119 dialogue.ShowModal() 120 else: 121 self.on_submit() 122 123 def get_dialogue_window_name(self): 124 return GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/SaveDesign') 125 126 def on_submit(self): 127 self.save_design_thread = uthread2.StartTasklet(self._save_design_async) 128 129 def _save_design_async(self): 130 self.busy = True 131 self.disabled = True 132 try: 133 design_id, error = self.call_save_on_service() 134 if error in DESIGN_ERROR_TEXT_BY_CODE: 135 label = DESIGN_ERROR_TEXT_BY_CODE[error] 136 if error == SkinDesignManagementError.MAX_SAVED_DESIGNS_LIMIT_REACHED: 137 text = GetByLabel(label, current=self.design_count, limit=self.design_limit) 138 else: 139 text = GetByLabel(label) 140 message_player(text) 141 else: 142 current_skin_design.get().saved_skin_design_id = design_id 143 current_skin_design.get().creator_character_id = session.charid 144 current_skin_design.take_snapshot() 145 message_player(GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/DesignSaved')) 146 except Exception as e: 147 message_player(e.message) 148 raise 149 finally: 150 self.save_design_thread = None 151 self.disabled = False 152 self.busy = False 153 154 def call_save_on_service(self): 155 return get_ship_skin_design_svc().save_design(design=current_skin_design.get(), editor_configs={SlotID.PATTERN: SkinDesignEditorConfig(0.0, 0.0, 0.0, 0.0, 0.0, 0.0), 156 SlotID.SECONDARY_PATTERN: SkinDesignEditorConfig(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)}, design_id=current_skin_design.get().saved_skin_design_id) 157 158 def on_submit_failed(self, reason): 159 message_player(reason) 160 161 def on_new_design_initialized(self, *args): 162 self.update_button_state() 163 164 def on_existing_design_loaded(self, *args): 165 self.update_button_state() 166 167 def on_slot_fitting_changed(self, *args): 168 self.update_button_state() 169 170 def on_skin_design_saved(self, *args): 171 self.update_button_state() 172 173 def ConstructTooltipPanel(self): 174 if self.save_requirements_met and self.has_fitted_components: 175 return SaveSkinTooltip(has_fitted_components=self.has_fitted_components, design_count=self.design_count, design_limit=self.design_limit) 176 else: 177 return SaveSkinErrorTooltip(has_fitted_components=self.has_fitted_components, design_count=self.design_count, design_limit=self.design_limit) 178 179 180 class SaveAsSkinButton(SaveSkinButton): 181 182 def get_dialogue_window_name(self): 183 return GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/SaveAsNew') 184 185 def call_save_on_service(self): 186 return get_ship_skin_design_svc().save_design(design=current_skin_design.get(), editor_configs={SlotID.PATTERN: SkinDesignEditorConfig(0.0, 0.0, 0.0, 0.0, 0.0, 0.0), 187 SlotID.SECONDARY_PATTERN: SkinDesignEditorConfig(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)}) 188 189 def is_restricted_by_design_limit(self): 190 return self.design_count >= self.design_limit 191 192 193 class SaveSkinTooltip(TooltipPanel): 194 default_state = uiconst.UI_NORMAL 195 196 def __init__(self, has_fitted_components, design_count, design_limit, *args, **kwargs): 197 super(SaveSkinTooltip, self).__init__(*args, **kwargs) 198 self.has_fitted_components = has_fitted_components 199 self.design_count = design_count 200 self.design_limit = design_limit 201 self.LoadStandardSpacing() 202 self.construct_layout() 203 204 def construct_layout(self): 205 self.construct_caption() 206 self.construct_save_limit() 207 self.construct_skills() 208 209 def construct_caption(self): 210 self.AddCaptionSmall(text=GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/SaveDesign')) 211 self.AddDivider() 212 213 def construct_save_limit(self): 214 self.FillRow() 215 self.AddLabelMedium(text=GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/SaveLimit', current=self.design_count, limit=self.design_limit), width=300) 216 217 def construct_skills(self): 218 self.AddSpacer(height=32) 219 self.FillRow() 220 self.AddCell(TextBody(text=GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/MaxSavedDesignsTooltipText'), color=TextColor.SECONDARY, width=300)) 221 for type_id in saved_designs_const.max_saved_designs_skills: 222 self.FillRow() 223 self.AddRow(rowClass=SkillEntry, typeID=type_id, level=get_skill_service().GetMyLevel(type_id), showLevel=False) 224 225 226 class SaveSkinErrorTooltip(SaveSkinTooltip): 227 228 def construct_layout(self): 229 self.construct_caption() 230 if not self.has_fitted_components: 231 self.construct_component_warning() 232 self.construct_save_limit() 233 self.construct_skills() 234 235 def construct_component_warning(self): 236 self.FillRow() 237 self.AddSpriteLabel(texturePath=eveicon.block_ban, iconSize=16, iconColor=eveColor.DANGER_RED, label=GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/NoComponentsSelected'), width=300) 238 239 def construct_save_limit(self): 240 if self.design_count < self.design_limit: 241 super(SaveSkinErrorTooltip, self).construct_save_limit() 242 else: 243 self.FillRow() 244 self.AddSpriteLabel(texturePath=eveicon.block_ban, iconSize=16, iconColor=eveColor.DANGER_RED, label=GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/DesignErrors/SaveLimitReached', current=self.design_count, limit=self.design_limit), width=300)