NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

patternSlots.py (13202B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\cosmetics\ship\pages\studio\patternSlots.py
      2 import eveicon
      3 from carbonui import Align, PickState
      4 from carbonui.control.contextMenu.menuData import MenuData
      5 from carbonui.primitives.container import Container
      6 from clientsettings.setting import SessionSettingEnum
      7 from carbonui.uianimations import animations
      8 from cosmetics.client.ships.skins.live_data import current_skin_design, current_skin_design_signals
      9 from cosmetics.common.ships.skins.static_data.pattern_attribute import PatternAttribute
     10 from cosmetics.common.ships.skins.static_data.pattern_blend_mode import PatternBlendMode, NO_SECONDARY_COLOR_BLEND_MODES
     11 from cosmetics.common.ships.skins.static_data.slot import SlotsDataLoader
     12 from cosmetics.common.ships.skins.static_data.slot_name import SlotID, PATTERN_RELATED_SLOT_IDS
     13 from eve.client.script.ui.cosmetics.ship.pages.studio import studioUtil
     14 from eve.client.script.ui.cosmetics.ship.pages.studio.areaToggleButtonMenuIcon import AreaToggleButtonMenuIcon
     15 from eve.client.script.ui.cosmetics.ship.pages.studio.circularButtonIcon import CircularButtonIcon, CircularMenuButtonIcon
     16 from eve.client.script.ui.cosmetics.ship.pages.studio.cosmeticSlot import PatternCosmeticSlot
     17 from localization import GetByLabel
     18 SLOT_LEFT = 100
     19 SLOT_TOP = 66
     20 MATERIAL_OFFSET = 64
     21 SLOT_LEFT_TOP_BY_ID = {SlotID.SECONDARY_PATTERN: (-SLOT_LEFT, -SLOT_TOP),
     22  SlotID.SECONDARY_PATTERN_MATERIAL: (-SLOT_LEFT + MATERIAL_OFFSET, -SLOT_TOP - MATERIAL_OFFSET),
     23  SlotID.PATTERN: (-SLOT_LEFT, SLOT_TOP),
     24  SlotID.PATTERN_MATERIAL: (-SLOT_LEFT + MATERIAL_OFFSET, SLOT_TOP + MATERIAL_OFFSET)}
     25 
     26 class PatternSlots(Container):
     27     default_width = 360
     28     default_height = 400
     29 
     30     def __init__(self, *args, **kwargs):
     31         super(PatternSlots, self).__init__(*args, **kwargs)
     32         self.slots_by_id = {}
     33         self.construct_layout()
     34         self.update()
     35         self.connect_signals()
     36 
     37     def Close(self):
     38         try:
     39             self.disconnect_signals()
     40         finally:
     41             super(PatternSlots, self).Close()
     42 
     43     def connect_signals(self):
     44         current_skin_design_signals.on_slot_fitting_changed.connect(self.on_slot_fitting_changed)
     45         current_skin_design_signals.on_slot_selected.connect(self.on_slot_selected)
     46         current_skin_design_signals.on_pattern_blend_mode_changed.connect(self.on_pattern_blend_mode_changed)
     47         current_skin_design_signals.on_component_attribute_changed.connect(self.on_component_attribute_changed)
     48 
     49     def disconnect_signals(self):
     50         current_skin_design_signals.on_slot_fitting_changed.disconnect(self.on_slot_fitting_changed)
     51         current_skin_design_signals.on_slot_selected.disconnect(self.on_slot_selected)
     52         current_skin_design_signals.on_pattern_blend_mode_changed.disconnect(self.on_pattern_blend_mode_changed)
     53         current_skin_design_signals.on_component_attribute_changed.disconnect(self.on_component_attribute_changed)
     54 
     55     def on_component_attribute_changed(self, slot_id, attribute_id, value):
     56         if attribute_id == PatternAttribute.MIRROR:
     57             self.update_mirror_toggle_buttons()
     58 
     59     def on_pattern_blend_mode_changed(self, blend_mode):
     60         self.update_slots()
     61 
     62     def construct_layout(self):
     63         self.construct_mirror_toggle_buttons()
     64         self.construct_area_toggle_buttons()
     65         self.reconstruct_slots()
     66         self.construct_switch_pattern_button()
     67         self.construct_blendmode_button()
     68 
     69     def construct_mirror_toggle_buttons(self):
     70         self.primary_mirror_toggle_button = MirrorToggleButtonIcon(parent=self, align=Align.CENTER, left=-161, top=88, display=False, pickState=PickState.ON)
     71         self.secondary_mirror_toggle_button = MirrorSecondaryToggleButtonIcon(parent=self, align=Align.CENTER, left=-161, top=-88, display=False, pickState=PickState.ON)
     72 
     73     def construct_area_toggle_buttons(self):
     74         self.primary_area_toggle_button = AreaToggleButtonMenuIcon(parent=self, align=Align.CENTER, left=-161, top=46, slot_id=SlotID.PATTERN, display=False, pickState=PickState.ON)
     75         self.secondary_area_toggle_button = AreaToggleButtonMenuIcon(parent=self, align=Align.CENTER, left=-161, top=-46, slot_id=SlotID.SECONDARY_PATTERN, display=False, pickState=PickState.ON)
     76 
     77     def reconstruct_slots(self):
     78         for slot in self.slots_by_id.values():
     79             slot.Close()
     80 
     81         self.slots_by_id.clear()
     82         for slot_id in current_skin_design.get().slot_layout.slots:
     83             if slot_id not in PATTERN_RELATED_SLOT_IDS:
     84                 continue
     85             slot_data = SlotsDataLoader.get_slot_data(slot_id)
     86             is_pattern = slot_data.unique_id in (SlotID.PATTERN, SlotID.SECONDARY_PATTERN)
     87             self.slots_by_id[slot_data.unique_id] = PatternCosmeticSlot(name='slot_{name}'.format(name=slot_data.internal_name), parent=self, slot_data=slot_data, opacity=0.0, license_selector_align=Align.CENTERRIGHT if is_pattern else Align.CENTERLEFT)
     88 
     89     def construct_switch_pattern_button(self):
     90         self.switch_pattern_button = SwitchPatternButtonIcon(name='switch_pattern_button', parent=self, pickState=PickState.OFF, align=Align.CENTER, opacity=0.0, func=self.on_switch_pattern_button, left=-100)
     91 
     92     def construct_blendmode_button(self):
     93         self.blendmode_button = BlendModeButton(name='blendmode_button', parent=self, pickState=PickState.OFF, align=Align.CENTER, opacity=0.0, left=-50)
     94 
     95     def update(self):
     96         self.update_slots()
     97         self.update_blend_and_switch_buttons()
     98         self.update_primary_buttons()
     99         self.update_secondary_buttons()
    100 
    101     def update_primary_buttons(self):
    102         show_primary_buttons = self.has_primary_pattern and current_skin_design.get_selected_slot_id() in (SlotID.PATTERN, SlotID.PATTERN_MATERIAL)
    103         self.primary_mirror_toggle_button.display = show_primary_buttons
    104         self.primary_area_toggle_button.display = show_primary_buttons
    105         self.primary_area_toggle_button.update_selected()
    106 
    107     def update_secondary_buttons(self):
    108         show_secondary_buttons = self.has_secondary_pattern and current_skin_design.get_selected_slot_id() in (SlotID.SECONDARY_PATTERN, SlotID.SECONDARY_PATTERN_MATERIAL)
    109         self.secondary_mirror_toggle_button.display = show_secondary_buttons
    110         self.secondary_area_toggle_button.display = show_secondary_buttons
    111         self.secondary_area_toggle_button.update_selected()
    112 
    113     def update_slots(self):
    114         for slot_id, slot in self.slots_by_id.items():
    115             if self.should_display_slot(slot_id):
    116                 slot.show()
    117                 animations.MoveTo(obj=slot, startPos=(slot.left, slot.top), endPos=self.get_slot_left_top(slot_id), duration=0.25)
    118             else:
    119                 slot.hide()
    120 
    121         self.update_mirror_toggle_buttons()
    122 
    123     def update_mirror_toggle_buttons(self):
    124         component_instance = current_skin_design.get().get_fitted_component_instance(SlotID.PATTERN)
    125         if component_instance:
    126             if component_instance.mirrored:
    127                 self.primary_mirror_toggle_button.SetSelected()
    128             else:
    129                 self.primary_mirror_toggle_button.SetDeselected()
    130         component_instance = current_skin_design.get().get_fitted_component_instance(SlotID.SECONDARY_PATTERN)
    131         if component_instance:
    132             if component_instance.mirrored:
    133                 self.secondary_mirror_toggle_button.SetSelected()
    134             else:
    135                 self.secondary_mirror_toggle_button.SetDeselected()
    136 
    137     def update_blend_and_switch_buttons(self):
    138         for button in (self.blendmode_button, self.switch_pattern_button):
    139             if self.has_two_patterns:
    140                 button.pickState = PickState.ON
    141                 button.Enable()
    142             else:
    143                 button.pickState = PickState.OFF
    144                 button.Disable()
    145             target_opacity = 1.0 if self.has_primary_pattern else 0.0
    146             animations.FadeTo(button, button.opacity, target_opacity, duration=0.25)
    147 
    148     def populate_from_design(self):
    149         for slot_id in self.slots_by_id.keys():
    150             component_instance = current_skin_design.get().slot_layout.fitted_slots.get(slot_id, None)
    151             self.slots_by_id[slot_id].on_slot_fitting_changed(slot_id, component_instance)
    152 
    153         self.update()
    154 
    155     def update_radial_position(self, radius):
    156         self.left, self.top = studioUtil.get_radial_position(radius, 0)
    157 
    158     def on_switch_pattern_button(self, *args):
    159         pass
    160 
    161     def on_slot_fitting_changed(self, slot_id, component_instance):
    162         self.update()
    163         self.blendmode_button.update_selected()
    164 
    165     def on_slot_selected(self, slot_id):
    166         self.update_primary_buttons()
    167         self.update_secondary_buttons()
    168 
    169     def get_slot_left_top(self, slot_id):
    170         if not self.has_primary_pattern:
    171             return (-50, 0)
    172         else:
    173             return SLOT_LEFT_TOP_BY_ID[slot_id]
    174 
    175     def should_display_slot(self, slot_id):
    176         if slot_id == SlotID.PATTERN:
    177             return True
    178         if slot_id == SlotID.SECONDARY_PATTERN_MATERIAL:
    179             if current_skin_design.get().slot_layout.pattern_blend_mode in NO_SECONDARY_COLOR_BLEND_MODES:
    180                 return False
    181             else:
    182                 return self.has_secondary_pattern
    183         else:
    184             return self.has_primary_pattern
    185 
    186     def is_slot_fitted(self, slot_id):
    187         return current_skin_design.get().get_fitted_component_instance(slot_id) is not None
    188 
    189     @property
    190     def has_primary_pattern(self):
    191         return self.is_slot_fitted(SlotID.PATTERN)
    192 
    193     @property
    194     def has_secondary_pattern(self):
    195         return self.is_slot_fitted(SlotID.SECONDARY_PATTERN)
    196 
    197     @property
    198     def has_two_patterns(self):
    199         return self.has_primary_pattern and self.has_secondary_pattern
    200 
    201 
    202 class BlendModeButton(CircularMenuButtonIcon):
    203     default_texturePath = eveicon.blend_modes
    204     default_hint = GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/BlendModes')
    205 
    206     def __init__(self, **kwargs):
    207         super(BlendModeButton, self).__init__(**kwargs)
    208         self.update_selected()
    209 
    210     def on_blend_mode_setting_changed(self, value):
    211         current_skin_design.get().slot_layout.pattern_blend_mode = value
    212         self.update_selected()
    213         current_skin_design.add_to_undo_history()
    214 
    215     def update_selected(self):
    216         if not self.enabled or current_skin_design.get().slot_layout.pattern_blend_mode == PatternBlendMode.OVERLAY:
    217             self.SetDeselected()
    218         else:
    219             self.SetSelected()
    220 
    221     def Enable(self):
    222         super(BlendModeButton, self).Enable()
    223         self.update_selected()
    224 
    225     def Disable(self):
    226         super(BlendModeButton, self).Disable()
    227         self.update_selected()
    228 
    229     def GetMenu(self):
    230         pattern_blend_mode_setting = SessionSettingEnum(current_skin_design.get().slot_layout.pattern_blend_mode)
    231         pattern_blend_mode_setting.on_change.connect(self.on_blend_mode_setting_changed)
    232         m = MenuData()
    233         m.AddRadioButton(GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/BlendMode/Normal'), PatternBlendMode.OVERLAY, pattern_blend_mode_setting)
    234         m.AddRadioButton(GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/BlendMode/Subtractive'), PatternBlendMode.SUBTRACT, pattern_blend_mode_setting)
    235         m.AddRadioButton(GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/BlendMode/Exclusion'), PatternBlendMode.EXCLUSION, pattern_blend_mode_setting)
    236         m.AddRadioButton(GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/BlendMode/Nested'), PatternBlendMode.NESTED, pattern_blend_mode_setting)
    237         m.AddRadioButton(GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/BlendMode/NestedInverted'), PatternBlendMode.NESTED_INVERTED, pattern_blend_mode_setting)
    238         return m
    239 
    240 
    241 class MirrorToggleButtonIcon(CircularButtonIcon):
    242     default_texturePath = eveicon.mirror
    243     default_hint = GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/Gizmo/MirrorToggle')
    244 
    245     def _ExecuteFunction(self, *args):
    246         self.ToggleSelected()
    247         component_instance = current_skin_design.get().get_fitted_component_instance(SlotID.PATTERN)
    248         if component_instance:
    249             component_instance.mirrored = self.isSelected
    250             current_skin_design.add_to_undo_history()
    251 
    252 
    253 class MirrorSecondaryToggleButtonIcon(CircularButtonIcon):
    254     default_texturePath = eveicon.mirror
    255     default_hint = GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/Gizmo/MirrorToggle')
    256 
    257     def _ExecuteFunction(self, *args):
    258         self.ToggleSelected()
    259         component_instance = current_skin_design.get().get_fitted_component_instance(SlotID.SECONDARY_PATTERN)
    260         if component_instance:
    261             component_instance.mirrored = self.isSelected
    262             current_skin_design.add_to_undo_history()
    263 
    264 
    265 class SwitchPatternButtonIcon(CircularButtonIcon):
    266     default_texturePath = eveicon.switch
    267     default_hint = GetByLabel('UI/Personalization/ShipSkins/SKINR/Studio/Switch')
    268 
    269     def _ExecuteFunction(self, *args):
    270         current_skin_design.get().swap_slots(SlotID.PATTERN, SlotID.SECONDARY_PATTERN)
    271         current_skin_design.add_to_undo_history()