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

fittingCenter.py (14805B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fittingScreen\fittingCenter.py
      2 import blue
      3 import math
      4 import uthread
      5 from carbonui import const as uiconst
      6 from carbonui.primitives.container import Container
      7 from carbonui.uicore import uicore
      8 from eve.client.script.ui.control.scenecontainer import SceneContainerBaseNavigation, STENCIL_MAP_DEFAULT
      9 from eve.client.script.ui.inflight.shipHud.groupAllIcon import GroupAllButton
     10 from eve.client.script.ui.shared.fitting.fittingUtil import GetScaleFactor, EatSignalChangingErrors
     11 from eve.client.script.ui.shared.fitting.shipSceneContainer import ShipSceneContainer
     12 from eve.client.script.ui.shared.fitting.slotAdder import SlotAdder
     13 from eve.client.script.ui.shared.fittingScreen.feedbackLabelCont import FeedbackLabelCont
     14 from eve.client.script.ui.shared.fittingScreen.fittingLayout import FittingLayout
     15 from eve.client.script.ui.shared.fittingScreen.fittingRadialMenu import RadialMenuIcon
     16 from eve.client.script.ui.shared.fittingScreen.slot import FittingSlot
     17 from eve.client.script.ui.station.fitting.stanceSlot import StanceSlots
     18 from eve.common.script.sys.eveCfg import IsControllingStructure
     19 from eveservices.menu import GetMenuService
     20 from eveui.decorators import lock_and_set_pending
     21 from inventorycommon import const as invconst
     22 from localization import GetByLabel
     23 from menu import MenuLabel, MenuList
     24 from signals.signalUtil import ChangeSignalConnect
     25 
     26 class FittingCenter(FittingLayout):
     27     default_align = uiconst.CENTER
     28     default_state = uiconst.UI_PICKCHILDREN
     29 
     30     def ApplyAttributes(self, attributes):
     31         FittingLayout.ApplyAttributes(self, attributes)
     32         self.controller = attributes.controller
     33         self.ChangeSignalConnection(connect=True)
     34         self.slots = {}
     35         self.slotList = []
     36         self.menuSlots = {}
     37         self.AddSlots()
     38         self.AddFeedbackLabel()
     39         self.AddSceneContainer()
     40         uthread.new(self.AnimateSlots)
     41         self.UpdateGauges()
     42         self.SetShipStance()
     43         self.UpdateRadialMenuAndGroupAllDisplay()
     44 
     45     def ChangeSignalConnection(self, connect = True):
     46         signalAndCallback = [(self.controller.on_stats_changed, self.UpdateGaugesOnSignal),
     47          (self.controller.on_gauge_preview_changed, self.UpdatePreviewGauges),
     48          (self.controller.on_new_itemID, self.OnNewItem),
     49          (self.controller.on_slots_with_menu_changed, self.OnSlotsWithMenuChanged),
     50          (self.controller.on_simulation_state_changed, self.OnSimulationStateChanged),
     51          (self.controller.on_slots_updated, self.CheckGroupAllButton)]
     52         ChangeSignalConnect(signalAndCallback, connect)
     53 
     54     def OnNewItem(self, *args):
     55         self.UpdateGauges()
     56         self.SetShipStance()
     57 
     58     def GetSlots(self):
     59         return self.slots
     60 
     61     def AddToSlotsWithMenu(self, slot):
     62         self.menuSlots[slot] = 1
     63 
     64     def ClearSlotsWithMenu(self):
     65         for slot in self.menuSlots.iterkeys():
     66             slot.HideUtilButtons()
     67 
     68         self.menuSlots = {}
     69 
     70     def AddSceneContainer(self):
     71         size = 550 * GetScaleFactor()
     72         self.sceneContainerParent = ShipSceneParent(parent=self, align=uiconst.CENTER, width=size, height=size, controller=self.controller)
     73         self.sceneContainer = self.sceneContainerParent.sceneContainer
     74         self.sceneNavigation = self.sceneContainerParent.sceneNavigation
     75 
     76     def AddFeedbackLabel(self):
     77         FeedbackLabelCont(parent=self, idx=0, align=uiconst.CENTERBOTTOM, top=150)
     78 
     79     def AddSlots(self):
     80         self.slotCont = Container(parent=self, name='slotCont', align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN, idx=0)
     81         self.slotList = []
     82         slotAdder = SlotAdder(self.controller, FittingSlot)
     83         for groupIdx, group in self.controller.GetSlotsByGroups().iteritems():
     84             if groupIdx < 0:
     85                 continue
     86             arcStart, arcLength = self.controller.SLOTGROUP_LAYOUT_ARCS[groupIdx]
     87             slotAdder.StartGroup(arcStart, arcLength, len(group))
     88             for slotIdx, slotController in enumerate(group):
     89                 slot = slotAdder.AddSlot(self.slotCont, slotController.flagID)
     90                 self.slotList.append(slot)
     91                 self.slots[slotController.flagID] = slot
     92 
     93         self.stances = StanceSlots(parent=self.slotCont, shipID=self.controller.GetItemID(), angleToPos=lambda angle: slotAdder.GetPositionNumbers(angle), typeID=self.controller.GetTypeID(), controller=self.controller)
     94         self.slotList.extend(self.stances.GetStanceContainers())
     95         self.AddRadialMenuIcons()
     96 
     97     def AddRadialMenuIcons(self):
     98         rad = int(243 * self.scaleFactor)
     99         cX = cY = self.baseShapeSize / 2
    100         size = int(22 * GetScaleFactor())
    101 
    102         def GetLocation(angle, size):
    103             cos = math.cos(angle * math.pi / 180.0)
    104             sin = math.sin(angle * math.pi / 180.0)
    105             left = int(round(rad * cos + cX - size / 2))
    106             top = int(round(rad * sin + cY - size / 2))
    107             return (left, top)
    108 
    109         left, top = GetLocation(227, size)
    110         self.allHiSlotsIcon = RadialMenuIcon(name='hiSlotRadial', parent=self.slotCont, texturePath='res:/ui/Texture/classes/RadialMenu/fitting/high.png', pos=(left,
    111          top,
    112          size,
    113          size), mouseDownFunc=self.TryOpenRadialMenu, flags=invconst.hiSlotFlags, iconSize=size, hint=GetByLabel('UI/Fitting/FittingWindow/RadialMenu/RadialMenuHighSlots'))
    114         left, top = GetLocation(315, size)
    115         self.allMedSlotsIcon = RadialMenuIcon(name='medSlotRadial', parent=self.slotCont, texturePath='res:/ui/Texture/classes/RadialMenu/fitting/med.png', pos=(left,
    116          top,
    117          size,
    118          size), mouseDownFunc=self.TryOpenRadialMenu, flags=invconst.medSlotFlags, iconSize=size, hint=GetByLabel('UI/Fitting/FittingWindow/RadialMenu/RadialMenuMedSlots'))
    119         left, top = GetLocation(45, size)
    120         texturePath = 'res:/ui/Texture/classes/RadialMenu/fitting/low.png'
    121         self.allLoSlotsIcon = RadialMenuIcon(name='loSlotRadial', parent=self.slotCont, texturePath=texturePath, pos=(left,
    122          top,
    123          size,
    124          size), mouseDownFunc=self.TryOpenRadialMenu, flags=invconst.loSlotFlags, iconSize=size, hint=GetByLabel('UI/Fitting/FittingWindow/RadialMenu/RadialMenuLowSlots'))
    125         left, top = GetLocation(227, size)
    126         self.groupAllButton = GroupAllButton(parent=self, idx=0, pos=(left,
    127          top,
    128          size,
    129          size))
    130 
    131     def CheckGroupAllButton(self):
    132         if self.groupAllButton is not None and not self.groupAllButton.destroyed:
    133             self.groupAllButton.CheckGroupAllButton()
    134 
    135     def TryOpenRadialMenu(self, icon, slotList, mouseButton, *args):
    136         if mouseButton != uiconst.MOUSELEFT:
    137             return
    138         uthread.new(self.ExpandRadialMenu, icon, slotList)
    139 
    140     def ExpandRadialMenu(self, anchorObject, slotList, *args):
    141         from eve.client.script.ui.shared.fittingScreen.fittingRadialMenu import RadialMenuFitting
    142         radialMenu = RadialMenuFitting(name='radialMenuFitting', parent=uicore.layer.menu, state=uiconst.UI_NORMAL, align=uiconst.TOPLEFT, anchorObject=anchorObject, slotList=slotList, isStructure=self.controller.ControllerForCategory() == const.categoryStructure)
    143         uicore.layer.menu.radialMenu = radialMenu
    144         uicore.uilib.SetMouseCapture(radialMenu)
    145 
    146     def ChangeRadialMenuIconDisplay(self, displayState):
    147         for element in [self.allHiSlotsIcon, self.allMedSlotsIcon, self.allLoSlotsIcon]:
    148             element.display = displayState
    149 
    150     def AnimateSlots(self):
    151         uthread.new(self.EntryAnimation, self.slotList)
    152 
    153     def EntryAnimation(self, toAnimate):
    154         for obj in toAnimate:
    155             obj.opacity = 0.0
    156 
    157         for i, obj in enumerate(toAnimate):
    158             if obj.state == uiconst.UI_DISABLED:
    159                 endOpacity = 0.05
    160             else:
    161                 endOpacity = 1.0
    162                 sm.GetService('audio').SendUIEvent('msg_fittingSlotHi_play')
    163             uicore.animations.FadeTo(obj, 0.0, endOpacity, duration=0.3)
    164             blue.synchro.SleepWallclock(5)
    165 
    166     def UpdatePreviewGauges(self, cpuLoad, powerLoad, calibrationLoad, *args):
    167         if self.controller is None or not self.controller.CurrentShipIsLoaded():
    168             return
    169         if self.controller.IsGodmaPrimingInterfering():
    170             return
    171         cpuOutput = self.controller.GetCPUOutput()
    172         portion = self.GetPortion(cpuLoad, cpuOutput.value)
    173         self.cpuGaugePreview.SetValue(portion, animate=False)
    174         powerOutput = self.controller.GetPowerOutput()
    175         portion = self.GetPortion(powerLoad, powerOutput.value)
    176         self.powerGaugePreview.SetValue(portion, animate=False)
    177         calibrationOutput = self.controller.GetCalibrationOutput()
    178         if calibrationLoad and calibrationOutput.value > 0:
    179             portion = calibrationLoad / calibrationOutput.value
    180         else:
    181             portion = 0.0
    182         self.calibrationGaugePreview.SetValue(portion, animate=False)
    183 
    184     def UpdateGaugesOnSignal(self):
    185         uthread.new(self.UpdateGauges)
    186 
    187     @lock_and_set_pending()
    188     def UpdateGauges(self):
    189         if self.controller is None or not self.controller.CurrentShipIsLoaded():
    190             return
    191         self.UpdatePowerGauge()
    192         self.UpdateCPUGauge()
    193         self.UpdateCalibrationGauge()
    194 
    195     def UpdatePowerGauge(self):
    196         powerLoad = self.controller.GetPowerLoad()
    197         powerOutput = self.controller.GetPowerOutput()
    198         portion = self.GetPortion(powerLoad.value, powerOutput.value)
    199         self.powerGauge.SetValue(portion)
    200 
    201     def UpdateCPUGauge(self):
    202         cpuLoad = self.controller.GetCPULoad()
    203         cpuOutput = self.controller.GetCPUOutput()
    204         portion = self.GetPortion(cpuLoad.value, cpuOutput.value)
    205         self.cpuGauge.SetValue(portion)
    206 
    207     def GetPortion(self, loadValue, outputValue):
    208         portion = 0.0
    209         if loadValue:
    210             if outputValue == 0.0:
    211                 portion = 1.0
    212             else:
    213                 portion = loadValue / outputValue
    214         return portion
    215 
    216     def UpdateCalibrationGauge(self):
    217         calibrationLoad = self.controller.GetCalibrationLoad()
    218         calibrationOutput = self.controller.GetCalibrationOutput()
    219         if calibrationLoad.value and calibrationOutput.value > 0:
    220             portion = calibrationLoad.value / calibrationOutput.value
    221         else:
    222             portion = 0.0
    223         self.calibrationGauge.SetValue(portion)
    224         self.calibrationGauge.SetCalibrationNumbers(calibrationLoad.value, calibrationOutput.value)
    225 
    226     def SetShipStance(self):
    227         if self.controller.HasStance():
    228             self.ShowStanceButtons()
    229         else:
    230             self.HideStanceButtons()
    231 
    232     def ShowStanceButtons(self):
    233         self.stances.display = True
    234         self.stances.ShowStances(self.controller.GetItemID(), self.controller.GetTypeID())
    235 
    236     def HideStanceButtons(self):
    237         self.stances.display = False
    238 
    239     def GetTooltipPosition(self):
    240         return (uicore.uilib.x - 5,
    241          uicore.uilib.y - 5,
    242          10,
    243          10)
    244 
    245     def OnSlotsWithMenuChanged(self, oldFlagID, newFlagID):
    246         slot = self.slots.get(oldFlagID, None)
    247         if slot is not None:
    248             slot.HideUtilButtons()
    249 
    250     def OnSimulationStateChanged(self):
    251         self.UpdateRadialMenuAndGroupAllDisplay()
    252 
    253     def UpdateRadialMenuAndGroupAllDisplay(self):
    254         isSimulated = self.controller.IsSimulated()
    255         if isSimulated:
    256             displayState = True
    257         else:
    258             displayState = False
    259         self.ChangeRadialMenuIconDisplay(displayState=displayState)
    260         self.groupAllButton.display = not isSimulated
    261 
    262     def Close(self):
    263         with EatSignalChangingErrors(errorMsg='fitting center'):
    264             self.ChangeSignalConnection(connect=False)
    265         FittingLayout.Close(self)
    266 
    267 
    268 class ShipSceneParent(Container):
    269 
    270     def ApplyAttributes(self, attributes):
    271         Container.ApplyAttributes(self, attributes)
    272         self.controller = attributes.controller
    273         self.stencilMask = attributes.Get('stencilMask', STENCIL_MAP_DEFAULT)
    274         self.ChangeSignalConnection(connect=True)
    275         self.sceneContainer = ShipSceneContainer(align=uiconst.TOALL, parent=self, state=uiconst.UI_DISABLED, controller=self.controller)
    276         self.SetScene()
    277         self.sceneContainer.LoadShipModel()
    278         scaleFactor = GetScaleFactor()
    279         self.sceneNavigation = SceneContainerBaseNavigation(parent=self, align=uiconst.TOALL, pos=(0, 0, 0, 0), idx=0, state=uiconst.UI_NORMAL, pickRadius=225 * scaleFactor)
    280         self.sceneNavigation.Startup(self.sceneContainer)
    281         self.sceneNavigation.OnDropData = self.OnDropData
    282         self.sceneNavigation.GetMenu = self.GetShipMenu
    283 
    284     def ChangeSignalConnection(self, connect = True):
    285         signalAndCallback = [(self.controller.on_new_itemID, self.OnNewShipLoaded)]
    286         ChangeSignalConnect(signalAndCallback, connect)
    287 
    288     def SetScene(self):
    289         scenePath = self.controller.scenePath
    290         self.sceneContainer.PrepareSpaceScene(scenePath=scenePath)
    291         self.sceneContainer.SetStencilMap(self.stencilMask)
    292 
    293     def OnNewShipLoaded(self, *_args):
    294         self.ReloadShipModel()
    295 
    296     def OnDropData(self, dragObj, nodes):
    297         if hasattr(self.controller, 'OnDropData'):
    298             self.controller.OnDropData(dragObj, nodes)
    299 
    300     def ReloadShipModel(self):
    301         self.SetScene()
    302         self.sceneContainer.ReloadShipModel(animate=False)
    303 
    304     def GetShipMenu(self, *args):
    305         itemID = self.controller.itemID
    306         if itemID is None:
    307             return MenuList()
    308         m = MenuList()
    309         if self.controller.IsSimulated():
    310             typeID = self.controller.GetTypeID()
    311             m += GetMenuService().GetMenuFromItemIDTypeID(None, typeID=typeID, includeMarketDetails=True)
    312             m += [[MenuLabel('UI/Inventory/ItemActions/StripFitting'), self.controller.StripFitting, []]]
    313             return m.filter(['UI/Fitting/FittingWindow/SimulateShip'])
    314         if IsControllingStructure():
    315             m += GetMenuService().CelestialMenu(session.structureid)
    316         elif session.stationid or session.structureid:
    317             hangarInv = sm.GetService('invCache').GetInventory(const.containerHangar)
    318             hangarItems = [hangarInv.GetItem()] + hangarInv.List(const.flagHangar)
    319             for each in hangarItems:
    320                 if each and each.itemID == self.controller.itemID:
    321                     m += GetMenuService().InvItemMenu(each)
    322 
    323         elif session.solarsystemid:
    324             m += GetMenuService().CelestialMenu(session.shipid)
    325         return m
    326 
    327     def Close(self):
    328         with EatSignalChangingErrors(errorMsg='ShipSceneParent'):
    329             self.ChangeSignalConnection(connect=False)
    330             Container.Close(self)