minihangar.py (14778B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fittingScreen\fittingPanels\minihangar.py 2 from collections import defaultdict 3 import evetypes 4 from carbon.client.script.environment.AudioUtil import PlaySound 5 from carbon.common.script.util.format import FmtAmt 6 from carbonui.primitives.container import Container 7 from carbonui.primitives.fill import Fill 8 from carbonui.primitives.frame import Frame 9 from eve.client.script.environment import invControllers as invCtrl 10 from eve.client.script.ui.control import eveIcon, eveLabel 11 from eve.client.script.ui.control.utilMenu import UtilMenu 12 from eve.client.script.ui.shared.fitting.fittingUtil import EatSignalChangingErrors 13 from eve.client.script.ui.shared.fittingScreen.fittingUtil import GetColoredText 14 from eve.common.lib import appConst as const 15 from eve.common.script.sys import eveCfg 16 from shipfitting.fittingWarnings import GetColorForLevel 17 from signals.signalUtil import ChangeSignalConnect 18 from inventorycommon.util import IsShipFittingFlag, IsShipFittable 19 import uthread 20 import carbonui.const as uiconst 21 import localization 22 from carbonui.uicore import uicore 23 24 class CargoSlots(Container): 25 default_state = uiconst.UI_NORMAL 26 27 def ApplyAttributes(self, attributes): 28 Container.ApplyAttributes(self, attributes) 29 self.warningFrame = None 30 self.controller = attributes.controller 31 self.ChangeSignalConnection(connect=True) 32 invController = self.GetInvController() 33 getMenuFunc = attributes.getMenuFunc 34 if getMenuFunc: 35 self.itemUtilMenu = self.AddUtilMenu(getMenuFunc) 36 self.itemUtilMenu.OnDropData = self.OnDropData 37 else: 38 self.itemUtilMenu = None 39 self.sr.icon = eveIcon.Icon(parent=self, size=32, state=uiconst.UI_DISABLED, ignoreSize=True, icon=invController.GetIconName()) 40 self.sr.hilite = Fill(parent=self, name='hilite', align=uiconst.RELATIVE, state=uiconst.UI_HIDDEN, idx=-1, width=32, height=self.height) 41 self.sr.icon.opacity = 0.8 42 Container(name='push', parent=self, align=uiconst.TOLEFT, width=32) 43 self.sr.statusCont = Container(name='statusCont', parent=self, align=uiconst.TOLEFT, width=50) 44 self.sr.statustext1 = eveLabel.EveLabelMedium(text='status', parent=self.sr.statusCont, name='cargo_statustext', left=0, top=2, idx=0, state=uiconst.UI_DISABLED, align=uiconst.TOPRIGHT) 45 self.sr.statustext2 = eveLabel.EveLabelMedium(text='status', parent=self.sr.statusCont, name='cargo_statustext', left=0, top=14, idx=0, state=uiconst.UI_DISABLED, align=uiconst.TOPRIGHT) 46 m3TextCont = Container(name='m3Cont', parent=self, align=uiconst.TOLEFT, width=12) 47 self.sr.m3Text = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Fitting/FittingWindow/CubicMeters'), parent=m3TextCont, name='m3', left=4, top=14, idx=0) 48 sm.GetService('inv').Register(self) 49 self.invReady = 1 50 self.Update() 51 52 def ChangeSignalConnection(self, connect = True): 53 signalAndCallback = [(self.controller.on_stats_changed, self.Update), (self.controller.on_new_itemID, self.Update), (self.controller.on_warning_display_changed, self.ChangeWarningDisplay)] 54 ChangeSignalConnect(signalAndCallback, connect) 55 56 def ConstructWarningFrame(self): 57 if self.warningFrame and not self.warningFrame.destroyed: 58 return 59 self.warningFrame = Frame(bgParent=self, frameConst=uiconst.FRAME_BORDER1_CORNER9, padding=(-2, -2, -4, 0)) 60 61 def AddUtilMenu(self, expandMenuFunc): 62 invController = self.GetInvController() 63 if invController: 64 iconName = invController.GetIconName() 65 else: 66 iconName = '' 67 utilMenu = UtilMenu(menuAlign=uiconst.TOPLEFT, parent=self, align=uiconst.TOPLEFT, GetUtilMenu=expandMenuFunc, texturePath=iconName, idx=0, iconSize=32, pos=(0, 0, 32, 32)) 68 return utilMenu 69 70 def IsItemHere(self, item): 71 return True 72 73 def AddItem(self, item): 74 self.Update() 75 76 def UpdateItem(self, item, *etc): 77 self.Update() 78 79 def RemoveItem(self, item): 80 self.Update() 81 82 def OnClick(self, *args): 83 if self.controller.IsSimulated(): 84 if self.itemUtilMenu: 85 self.itemUtilMenu.OnClick() 86 else: 87 self.OnHoldClicked() 88 PlaySound(uiconst.SOUND_BUTTON_CLICK) 89 90 def OnHoldClicked(self): 91 pass 92 93 def OnMouseEnter(self, *args): 94 self.DoMouseEntering() 95 PlaySound(uiconst.SOUND_BUTTON_HOVER) 96 97 def OnMouseEnterDrone(self, *args): 98 if session.stationid: 99 self.DoMouseEntering() 100 101 def DoMouseEntering(self): 102 self.Hilite(1) 103 self.sr.statustext1.OnMouseEnter() 104 self.sr.statustext2.OnMouseEnter() 105 self.sr.m3Text.OnMouseEnter() 106 107 def OnMouseExit(self, *args): 108 self.Hilite(0) 109 self.sr.statustext1.OnMouseExit() 110 self.sr.statustext2.OnMouseExit() 111 self.sr.m3Text.OnMouseExit() 112 uthread.new(self.Update) 113 114 def Hilite(self, state): 115 self.sr.icon.opacity = [0.8, 1.0][state] 116 117 def SetStatusText(self, text1, text2, color): 118 self.sr.statustext1.text = text1 119 self.sr.statustext2.text = localization.GetByLabel('UI/Fitting/FittingWindow/CargoUsage', color=color, text=text2) 120 self.sr.statusCont.width = max(0, self.sr.statustext1.textwidth, self.sr.statustext2.textwidth) 121 122 def OnDropData(self, dragObj, nodes): 123 self.Hilite(0) 124 125 def Update(self, *args): 126 uthread.new(self._Update) 127 128 def _Update(self): 129 if not self.controller.CurrentShipIsLoaded(): 130 return 131 if not self.controller.IsValidItemAndSimulationState(): 132 return 133 try: 134 cap = self.GetCapacity() 135 except (RuntimeError, AttributeError) as e: 136 sm.GetService('fittingSvc').LogWarn('Failed to get cap for ship: ', e) 137 return 138 139 if not cap or not self or self.destroyed: 140 return 141 try: 142 capacityInfo = self.GetCapacityInfo() 143 except KeyError: 144 self.SetStatusText('-', '-', '') 145 return 146 147 cap2 = capacityInfo.value 148 used = FmtAmt(cap.used, showFraction=1) 149 cap2 = FmtAmt(cap2, showFraction=1) 150 coloredText = GetColoredText(isBetter=capacityInfo.isBetterThanBefore, text=cap2) 151 self.SetStatusText(used, coloredText, '') 152 self.SetMenuState() 153 154 def GetCapacity(self, flag = None): 155 if self.controller.IsSimulated(): 156 return self.GetSimulatedCapacity() 157 else: 158 return self.GetInvController().GetCapacity() 159 160 def GetSimulatedCapacity(self): 161 pass 162 163 def GetCapacityInfo(self): 164 pass 165 166 def GetInvController(self): 167 pass 168 169 def SetMenuState(self): 170 if self.itemUtilMenu is None: 171 return 172 if self.controller.IsSimulated(): 173 self.itemUtilMenu.display = True 174 else: 175 self.itemUtilMenu.display = False 176 177 def ChangeWarningDisplay(self, warningModuleSlotDict, *args): 178 pass 179 180 def Close(self): 181 with EatSignalChangingErrors(errorMsg='Container'): 182 self.ChangeSignalConnection(connect=False) 183 Container.Close(self) 184 185 186 class CargoDroneSlots(CargoSlots): 187 188 def ChangeSignalConnection(self, connect = True): 189 CargoSlots.ChangeSignalConnection(self, connect=connect) 190 signalAndCallback = [(self.controller.on_drone_bay_open, self.OnClick)] 191 ChangeSignalConnect(signalAndCallback, connect) 192 193 def GetInvController(self): 194 if self.controller.IsSimulated(): 195 itemID = None 196 else: 197 itemID = self.controller.GetItemID() 198 return invCtrl.ShipDroneBay(itemID) 199 200 def OnDropData(self, dragObj, nodes): 201 if self.controller.IsSimulated(): 202 self.AddSimulatedDrones(nodes) 203 else: 204 shipID = eveCfg.GetActiveShip() 205 invCtrl.ShipDroneBay(shipID).OnDropData(nodes) 206 CargoSlots.OnDropData(self, dragObj, nodes) 207 208 def OnHoldClicked(self, *args): 209 uicore.cmd.OpenDroneBayOfActiveShip() 210 211 def GetCapacityInfo(self, flag = None): 212 return self.controller.GetDroneCapacity() 213 214 def GetSimulatedCapacity(self): 215 shipID = self.controller.GetItemID() 216 return self.controller.dogmaLocation.GetCapacity(shipID, None, const.flagDroneBay) 217 218 def AddSimulatedDrones(self, nodes): 219 qtyByTypeIDs = GetQtyByTypeAndItemIDs(nodes) 220 for typeID, itemID in qtyByTypeIDs.keys(): 221 if evetypes.GetCategoryID(typeID) != const.categoryDrone: 222 qtyByTypeIDs.pop(typeID, None) 223 224 sm.GetService('ghostFittingSvc').TryFitDronesToDroneBay(qtyByTypeIDs) 225 226 227 class CargoCargoSlots(CargoSlots): 228 229 def GetInvController(self): 230 if self.controller.IsSimulated(): 231 itemID = None 232 else: 233 itemID = self.controller.GetItemID() 234 return invCtrl.ShipCargo(itemID) 235 236 def OnDropData(self, dragObj, nodes): 237 if self.controller.IsSimulated(): 238 return self.AddSimulatedCargo(nodes) 239 self.Hilite(0) 240 if len(nodes) == 1: 241 item = nodes[0].item 242 if item and IsShipFittingFlag(item.flagID): 243 dogmaLocation = sm.GetService('clientDogmaIM').GetDogmaLocation() 244 shipID = eveCfg.GetActiveShip() 245 if IsShipFittable(item.categoryID): 246 return dogmaLocation.UnloadModuleToContainer(shipID, item.itemID, (shipID,), flag=const.flagCargo) 247 if item.categoryID == const.categoryCharge: 248 return dogmaLocation.UnloadAmmoToContainer(shipID, item, (shipID, session.charid, const.flagCargo)) 249 invCtrl.ShipCargo(eveCfg.GetActiveShip()).OnDropData(nodes) 250 CargoSlots.OnDropData(self, dragObj, nodes) 251 252 def AddSimulatedCargo(self, nodes): 253 qtyByTypeIDs = GetQtyByTypeIDs(nodes) 254 sm.GetService('ghostFittingSvc').TryFitItemsToCargo(qtyByTypeIDs) 255 256 def OnHoldClicked(self, *args): 257 uicore.cmd.OpenCargoHoldOfActiveShip() 258 259 def GetCapacityInfo(self, flag = None): 260 return self.controller.GetCargoCapacity() 261 262 def GetSimulatedCapacity(self): 263 shipID = self.controller.GetItemID() 264 return self.controller.dogmaLocation.GetCapacity(shipID, None, const.flagCargo) 265 266 def ChangeWarningDisplay(self, warningModuleSlotDict, *args): 267 invCtrl = self.GetInvController() 268 warningLevel = warningModuleSlotDict.get(invCtrl.locationFlag, None) 269 if warningLevel: 270 color = GetColorForLevel(warningLevel) 271 self.ConstructWarningFrame() 272 self.warningFrame.display = True 273 self.warningFrame.SetRGBA(*color) 274 elif self.warningFrame: 275 self.warningFrame.display = False 276 277 278 class CargoFighterSlots(CargoSlots): 279 280 def ChangeSignalConnection(self, connect = True): 281 CargoSlots.ChangeSignalConnection(self, connect=connect) 282 signalAndCallback = [(self.controller.on_drone_bay_open, self.OnClick)] 283 ChangeSignalConnect(signalAndCallback, connect) 284 285 def GetInvController(self): 286 if self.controller.IsSimulated(): 287 itemID = None 288 else: 289 itemID = self.controller.GetItemID() 290 return invCtrl.ShipFighterBay(itemID) 291 292 def OnDropData(self, dragObj, nodes): 293 if self.controller.IsSimulated(): 294 self.AddSimulatedFighters(nodes) 295 else: 296 self.GetInvController().OnDropData(nodes) 297 CargoSlots.OnDropData(self, dragObj, nodes) 298 299 def OnHoldClicked(self, *args): 300 uicore.cmd.OpenFighterBayOfActiveShip() 301 302 def GetCapacityInfo(self, flag = None): 303 return self.controller.GetFighterCapacity() 304 305 def GetSimulatedCapacity(self): 306 shipID = self.controller.GetItemID() 307 return self.controller.dogmaLocation.GetCapacity(shipID, None, const.flagFighterBay) 308 309 def AddSimulatedFighters(self, nodes): 310 qtyByTypeIDs = GetQtyByTypeIDs(nodes) 311 for typeID in qtyByTypeIDs.keys(): 312 if evetypes.GetCategoryID(typeID) != const.categoryFighter: 313 qtyByTypeIDs.pop(typeID, None) 314 315 if qtyByTypeIDs: 316 sm.GetService('ghostFittingSvc').TryFitFightersToTubeOrBay(qtyByTypeIDs) 317 318 def ChangeWarningDisplay(self, warningModuleSlotDict, *args): 319 invCtrl = self.GetInvController() 320 warningLevel = None 321 for eachFlag in [invCtrl.locationFlag] + const.fighterTubeFlags: 322 warningLevel = max(warningLevel, warningModuleSlotDict.get(eachFlag, None)) 323 324 if warningLevel: 325 color = GetColorForLevel(warningLevel) 326 self.ConstructWarningFrame() 327 self.warningFrame.display = True 328 self.warningFrame.SetRGBA(*color) 329 elif self.warningFrame: 330 self.warningFrame.display = False 331 332 333 class CargoStructureAmmoBay(CargoSlots): 334 335 def GetInvController(self): 336 return invCtrl.StructureAmmoBay(self.controller.GetItemID()) 337 338 def OnDropData(self, dragObj, nodes): 339 if self.controller.IsSimulated(): 340 return self.AddSimulatedCargo(nodes) 341 self.GetInvController().OnDropData(nodes) 342 CargoSlots.OnDropData(self, dragObj, nodes) 343 344 def OnHoldClicked(self, *args): 345 itemID = self.controller.GetItemID() 346 invID = ('StructureAmmoBay', itemID) 347 from eve.client.script.ui.shared.inventory.invWindow import Inventory 348 Inventory.OpenOrShow(invID, usePrimary=False, toggle=True) 349 350 def GetCapacityInfo(self, flag = None): 351 return self.controller.GetCargoCapacity() 352 353 def GetSimulatedCapacity(self): 354 shipID = self.controller.GetItemID() 355 return self.controller.dogmaLocation.GetCapacity(shipID, None, const.flagCargo) 356 357 def AddSimulatedCargo(self, nodes): 358 qtyByTypeIDs = GetQtyByTypeIDs(nodes) 359 sm.GetService('ghostFittingSvc').TryFitItemsToCargo(qtyByTypeIDs) 360 361 362 def GetQtyByTypeIDs(nodes): 363 qtyByTypeIDs = defaultdict(int) 364 for eachNode in nodes: 365 typeID = getattr(eachNode, 'typeID', None) 366 if typeID is None and getattr(eachNode, 'rec', None): 367 typeID = eachNode.rec.typeID 368 if typeID: 369 qtyByTypeIDs[typeID] += 1 370 371 return qtyByTypeIDs 372 373 374 def GetQtyByTypeAndItemIDs(nodes): 375 qtyByTypeIDs = defaultdict(int) 376 for eachNode in nodes: 377 typeID = getattr(eachNode, 'typeID', None) 378 itemID = getattr(eachNode, 'itemID', None) 379 if typeID is None and getattr(eachNode, 'rec', None): 380 typeID = eachNode.rec.typeID 381 if typeID: 382 qtyByTypeIDs[typeID, itemID] += 1 383 384 return qtyByTypeIDs