sequenceBinderPanel.py (13035B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\cosmetics\ship\pages\sequence\sequenceBinderPanel.py 2 import logging 3 from carbonui import Align, PickState, uiconst 4 from carbonui.primitives.container import Container 5 from carbonui.primitives.containerAutoSize import ContainerAutoSize 6 from carbonui.primitives.sprite import Sprite 7 from carbonui.uianimations import animations 8 from carbonui.uiconst import OutputMode 9 from cosmetics.client.shipSkinComponentSvc import get_ship_skin_component_svc 10 from cosmetics.client.shipSkinSequencingSvc import get_ship_skin_sequencing_svc 11 from cosmetics.client.ships import ship_skin_signals 12 from cosmetics.client.ships.skins.live_data import current_skin_design, current_skin_design_signals 13 from cosmetics.common.cosmeticsConst import SEQUENCE_BINDER_TYPES 14 from cosmetics.common.ships.skins.static_data.slot import SlotsDataLoader 15 from cosmetics.common.ships.skins.static_data.slot_configuration import SlotConfigurationsDataLoader 16 from cosmetics.common.ships.skins.static_data.slot_name import SlotID, PATTERN_RELATED_SLOT_IDS 17 from eve.client.script.ui import eveThemeColor 18 from player_messaging.client.ui_message import message_player 19 from eve.client.script.ui.cosmetics.ship.pages.sequence import sequence_ui_signals 20 from eve.client.script.ui.cosmetics.ship.pages.sequence.sequenceBinderEntries import SequenceBinderCostEntryCompact 21 from eve.client.script.ui.cosmetics.ship.pages.studio.cosmeticSlot import CosmeticSlot 22 from eve.client.script.ui.cosmetics.ship.pages.studio.licenseSelector import LicenseSelector 23 from eve.common.lib import appConst 24 from localization import GetByLabel 25 from publicGateway.grpc.exceptions import GenericException 26 from stackless_response_router.exceptions import TimeoutException 27 log = logging.getLogger(__name__) 28 LINE_TEXTURES_BY_SLOT_ID_TYPE_ID = {SlotID.PRIMARY_NANOCOATING: {appConst.typeFermionic: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_1_ferm.png', (-20, 63, 45, 72)), 29 appConst.typeKerr: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_1_kerr.png', (-20, 60, 45, 170))}, 30 SlotID.SECONDARY_NANOCOATING: {appConst.typeFermionic: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_2_ferm.png', (-20, 21, 45, 44)), 31 appConst.typeKerr: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_2_kerr.png', (-20, 60, 45, 58))}, 32 SlotID.TERTIARY_NANOCOATING: {appConst.typeFermionic: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_3_ferm.png', (-20, -91, 45, 156)), 33 appConst.typeKerr: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_3_kerr.png', (-20, 4, 45, 58))}, 34 SlotID.TECH_AREA: {appConst.typeFermionic: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_4_ferm.png', (-20, -203, 45, 268)), 35 appConst.typeKerr: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/left_4_kerr.png', (-20, -108, 45, 170))}, 36 SlotID.PATTERN_MATERIAL: {appConst.typeFermionic: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/right_1_ferm.png', (-20, 90, 57, 17)), 37 appConst.typeKerr: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/right_1_kerr.png', (-20, 65, 45, 140))}, 38 SlotID.SECONDARY_PATTERN_MATERIAL: {appConst.typeFermionic: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/right_2_ferm.png', (-20, 19, 53, 28)), 39 appConst.typeKerr: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/right_2_kerr.png', (-20, 90, 57, 31))}, 40 SlotID.PATTERN: {appConst.typeAlignment: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/right_3_align.png', (-20, 87, 56, 26))}, 41 SlotID.SECONDARY_PATTERN: {appConst.typeAlignment: ('res:/UI/Texture/classes/Cosmetics/Ship/sequencing/lines/right_4_align.png', (-20, 24, 55, 20))}} 42 43 class SequenceBinderPanel(ContainerAutoSize): 44 is_loaded = False 45 46 def __init__(self, **kw): 47 super(SequenceBinderPanel, self).__init__(**kw) 48 self.cost_entries = [] 49 50 def load_panel(self): 51 if not self.is_loaded: 52 self.is_loaded = True 53 self.construct_layout() 54 self.connect_signals() 55 self.reconstruct_slots() 56 self.update_values() 57 self.anim_entry() 58 59 def anim_entry(self): 60 self.opacity = 0.0 61 animations.MorphScalar(self, 'left', -200, 0, duration=0.6) 62 animations.FadeTo(self, 0.0, 1.0, duration=0.3, timeOffset=0.6) 63 64 def connect_signals(self): 65 sequence_ui_signals.on_num_skins_changed.connect(self.on_num_skins_changed) 66 current_skin_design_signals.on_component_instance_license_to_use_changed.connect(self.on_component_instance_license_to_use_changed) 67 current_skin_design_signals.on_slot_fitting_changed.connect(self.on_slot_fitting_changed) 68 ship_skin_signals.on_component_license_granted.connect(self.on_component_license_granted) 69 70 def disconnect_signals(self): 71 sequence_ui_signals.on_num_skins_changed.disconnect(self.on_num_skins_changed) 72 current_skin_design_signals.on_component_instance_license_to_use_changed.disconnect(self.on_component_instance_license_to_use_changed) 73 current_skin_design_signals.on_slot_fitting_changed.disconnect(self.on_slot_fitting_changed) 74 ship_skin_signals.on_component_license_granted.disconnect(self.on_component_license_granted) 75 76 def on_slot_fitting_changed(self, *args): 77 self.reconstruct_slots() 78 self.update_values() 79 80 def on_component_instance_license_to_use_changed(self, component_id, license): 81 self.update_values() 82 83 def on_component_license_granted(self, *args): 84 self.reconstruct_slots() 85 self.update_values() 86 87 def Close(self): 88 try: 89 self.disconnect_signals() 90 finally: 91 super(SequenceBinderPanel, self).Close() 92 93 def on_num_skins_changed(self, num_skins): 94 self.update_values() 95 96 def update_values(self): 97 num_runs = get_ship_skin_sequencing_svc().get_num_runs() 98 amount_by_type = current_skin_design.get().get_sequence_binder_amounts_required(num_runs) 99 for entry in self.cost_entries: 100 entry.update(amount_by_type[entry.type_id]) 101 102 def construct_layout(self): 103 self.content = ContainerAutoSize(name='content', parent=self, align=Align.CENTERLEFT, height=512, top=64) 104 self.left_cont = ContainerAutoSize(name='left_cont', parent=self.content, align=Align.TOLEFT) 105 self.center_cont = Container(name='center_cont', parent=self.content, align=Align.TOLEFT, pickState=PickState.ON, width=100, top=64) 106 self.right_cont = ContainerAutoSize(name='right_cont', parent=self.content, align=Align.TOLEFT) 107 self.construct_center_cont() 108 109 def reconstruct_slots(self): 110 self.left_cont.Flush() 111 self.right_cont.Flush() 112 slot_config = SlotConfigurationsDataLoader.get_for_ship(current_skin_design.get().ship_type_id) 113 y_offset_left = 118 114 k_offset_right = 34 115 y_offset_right = 94 116 for slot_id in slot_config.slots: 117 if slot_id == SlotID.PRIMARY_NANOCOATING: 118 SlotCostEntry(parent=self.left_cont, slot_id=slot_id, top=0, align=Align.TOPRIGHT, alignMode=Align.CENTERRIGHT) 119 elif slot_id == SlotID.SECONDARY_NANOCOATING: 120 SlotCostEntry(parent=self.left_cont, slot_id=slot_id, top=y_offset_left, align=Align.TOPRIGHT, alignMode=Align.CENTERRIGHT) 121 elif slot_id == SlotID.TERTIARY_NANOCOATING: 122 SlotCostEntry(parent=self.left_cont, slot_id=slot_id, align=Align.TOPRIGHT, top=2 * y_offset_left, alignMode=Align.CENTERRIGHT) 123 elif slot_id == SlotID.TECH_AREA: 124 SlotCostEntry(parent=self.left_cont, slot_id=slot_id, align=Align.TOPRIGHT, top=3 * y_offset_left, alignMode=Align.CENTERRIGHT) 125 elif slot_id == SlotID.PATTERN_MATERIAL: 126 SlotCostEntry(parent=self.right_cont, slot_id=slot_id, align=Align.TOPLEFT, top=k_offset_right, alignMode=Align.CENTERLEFT) 127 elif slot_id == SlotID.SECONDARY_PATTERN_MATERIAL: 128 SlotCostEntry(parent=self.right_cont, slot_id=slot_id, align=Align.TOPLEFT, top=k_offset_right + y_offset_right, alignMode=Align.CENTERLEFT) 129 elif slot_id == SlotID.PATTERN: 130 SlotCostEntry(parent=self.right_cont, slot_id=slot_id, align=Align.TOPLEFT, top=k_offset_right + 2 * y_offset_right, alignMode=Align.CENTERLEFT) 131 elif slot_id == SlotID.SECONDARY_PATTERN: 132 SlotCostEntry(parent=self.right_cont, slot_id=slot_id, align=Align.TOPLEFT, top=k_offset_right + 3 * y_offset_right, alignMode=Align.CENTERLEFT) 133 134 def construct_center_cont(self): 135 for i, type_id in enumerate(SEQUENCE_BINDER_TYPES): 136 cost_entry = SequenceBinderCostEntryCompact(parent=self.center_cont, type_id=type_id, align=Align.CENTERTOP, pickState=PickState.ON, top=45 + i * 97) 137 self.cost_entries.append(cost_entry) 138 139 140 class SlotCostEntry(ContainerAutoSize): 141 default_state = uiconst.UI_PICKCHILDREN 142 143 def __init__(self, slot_id, **kw): 144 super(SlotCostEntry, self).__init__(**kw) 145 self.slot_id = slot_id 146 self.line = None 147 self.component = current_skin_design.get().slot_layout.get_component(self.slot_id) 148 if self.component: 149 svc = get_ship_skin_component_svc() 150 component_data = self.component.get_component_data() 151 try: 152 self.bound_license = svc.get_bound_license(self.component.component_id, component_data.category) 153 self.unbound_license = svc.get_unbound_license(self.component.component_id, component_data.category) 154 except (GenericException, TimeoutException): 155 message_player(GetByLabel('UI/Common/CannotConnectToServer')) 156 self.bound_license = self.unbound_license = None 157 158 else: 159 self.opacity = 0.35 160 self.bound_license = self.unbound_license = None 161 self.construct_layout() 162 self.connect_signals() 163 164 def Close(self): 165 try: 166 self.disconnect_signals() 167 finally: 168 super(SlotCostEntry, self).Close() 169 170 def connect_signals(self): 171 current_skin_design_signals.on_component_instance_license_to_use_changed.connect(self.on_component_instance_license_to_use_changed) 172 sequence_ui_signals.on_component_license_selection_changed.connect(self.on_component_license_selection_changed) 173 174 def disconnect_signals(self): 175 current_skin_design_signals.on_component_instance_license_to_use_changed.disconnect(self.on_component_instance_license_to_use_changed) 176 sequence_ui_signals.on_component_license_selection_changed.disconnect(self.on_component_license_selection_changed) 177 178 def on_component_license_selection_changed(self): 179 self.reconstruct_line() 180 181 def on_component_instance_license_to_use_changed(self, component_id, license): 182 if self.component and self.component.component_id == component_id: 183 self.reconstruct_line() 184 185 def construct_layout(self): 186 slot_data = SlotsDataLoader.get_slot_data(self.slot_id) 187 self.slot = SequenceStepCosmeticSlot(name='slot_{name}'.format(name=slot_data.internal_name), parent=self, slot_data=slot_data, component=self.component, align=self.alignMode, selectable=False) 188 LicenseSelector(name='license_selector', parent=self, align=self.alignMode, component_instance=self.component, left=108) 189 if self.component: 190 self.reconstruct_line() 191 192 def reconstruct_line(self): 193 if self.line: 194 self.line.Close() 195 if not self.component or not self.component.sequence_binder_amount_required: 196 return 197 pos, texturePath = self._get_line_texture_path_and_position() 198 align = Align.TOPLEFT if self.slot_id in PATTERN_RELATED_SLOT_IDS else Align.TOPRIGHT 199 self.line = Sprite(name='line', parent=self, align=align, pos=pos, texturePath=texturePath, outputMode=OutputMode.COLOR_AND_GLOW, glowBrightness=0.75, color=eveThemeColor.THEME_ACCENT, pickState=PickState.ON) 200 201 def _get_line_texture_path_and_position(self): 202 try: 203 texturePath, pos = LINE_TEXTURES_BY_SLOT_ID_TYPE_ID[self.slot_id][self.component.sequence_binder_type_id] 204 except KeyError: 205 log.exception('Line texture not found: slot_id: {}, component_id: {}, sequence_binder_type_id: {}'.format(self.slot_id, self.component.component_id, self.component.sequence_binder_type_id)) 206 texturePath = None 207 pos = (0, 0, 0, 0) 208 209 return (pos, texturePath) 210 211 212 class SequenceStepCosmeticSlot(CosmeticSlot): 213 default_height = 128 214 default_width = 128 215 216 def _update_state_side_frame(self, animate): 217 self.side_frame.display = False 218 219 def construct_license_selector(self): 220 self.license_selector = None