colonyEntry.py (21277B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\planet\planetsWindow\colonyEntry.py 2 import eveicon 3 import trinity 4 from carbon.common.script.sys import service 5 from carbon.common.script.util.format import IntToRoman 6 from carbonui import uiconst, ButtonVariant, Density 7 from carbonui.control.button import Button 8 from carbonui.primitives.container import Container 9 from carbonui.primitives.containerAutoSize import ContainerAutoSize 10 from carbonui.primitives.line import Line 11 from carbonui.primitives.sprite import Sprite 12 from carbonui.uianimations import animations 13 from carbonui.util.color import Color 14 from eve.client.script.ui import eveColor 15 from eve.client.script.ui.control import eveIcon 16 from eve.client.script.ui.control.eveLabel import EveLabelLarge, EveLabelMedium 17 from eve.client.script.ui.control.eveWindowUnderlay import ListEntryUnderlay 18 from player_messaging.client.ui_message import message_player 19 from eve.client.script.ui.control.themeColored import FillThemeColored, SpriteThemeColored 20 from eve.client.script.ui.shared.cloneGrade import cloneStateUtil 21 from eve.client.script.ui.shared.cloneGrade.omegaRestrictedEntry import OmegaRestrictedEntry 22 from eve.client.script.ui.shared.planet import planetConst 23 from eve.client.script.ui.shared.planet.pinContainers.storageIcon import StorageIcon 24 from eve.common.lib import appConst 25 from eve.common.script.util.eveFormat import FmtSystemSecStatus, FmtISKAndRound 26 from menu import MenuLabel 27 from inventorycommon import typeHelpers 28 from localization import GetByLabel 29 HEIGHT = 120 30 HEIGHT_COMPACT = 56 31 ICONSIZE = 32 32 ICONSIZE_COMPACT = 26 33 GENERIC_PADDING = 8 34 35 class BaseColonyEntry(Container): 36 default_height = HEIGHT 37 default_state = uiconst.UI_NORMAL 38 39 def ApplyAttributes(self, attributes): 40 Container.ApplyAttributes(self, attributes) 41 self.isSelected = False 42 self.iconCont = Container(name='iconCont', parent=self, align=uiconst.TOLEFT, state=uiconst.UI_DISABLED, width=self.height, padding=(2, 2, 2, 3)) 43 self.ConstructCaptionCont() 44 self.mainCont = Container(name='mainCont', parent=self, padLeft=GENERIC_PADDING, clipChildren=True) 45 FillThemeColored(bgParent=self, colorType=uiconst.COLORTYPE_UIBASE, opacity=0.05) 46 self.underlay = ListEntryUnderlay(bgParent=self) 47 48 def Update(self): 49 pass 50 51 def ConstructCaptionCont(self): 52 self.captionCont = ContainerAutoSize(name='captionCont', parent=self, align=uiconst.TOTOP, padding=(0, 2, 0, 2), clipChildren=True) 53 self.ConstructCaption() 54 FillThemeColored(bgParent=self.captionCont, colorType=uiconst.COLORTYPE_UIHILIGHT) 55 56 def ConstructCaption(self): 57 self.caption = EveLabelLarge(parent=self.captionCont, align=uiconst.TOTOP, text=self.GetCaptionText(), padding=(GENERIC_PADDING, 58 4, 59 0, 60 4), maxLines=1) 61 62 def GetIconSize(self): 63 return ICONSIZE 64 65 def GetCaptionText(self): 66 return '' 67 68 def OnMouseEnter(self, *args): 69 self.underlay.hovered = True 70 71 def OnMouseExit(self, *args): 72 self.underlay.hovered = False 73 74 def SetSelected(self): 75 self.isSelected = True 76 self.underlay.Select() 77 78 def SetDeselected(self): 79 self.isSelected = False 80 self.underlay.Deselect() 81 82 def GetPlanetID(self): 83 return None 84 85 86 class ColonyEntry(BaseColonyEntry): 87 __notifyevents__ = ['OnPlanetSubmittingChanges'] 88 89 def ApplyAttributes(self, attributes): 90 self.planetData = attributes.planetData 91 self.onClickCallback = attributes.onClickCallback 92 BaseColonyEntry.ApplyAttributes(self, attributes) 93 self.ConstructRowContainers() 94 self.ConstructNoActivityLabel(GetByLabel('UI/PI/Common/NoIndustrialActivity')) 95 self.ReconstructItemConts() 96 self.ConstructIcon() 97 sm.RegisterNotify(self) 98 99 def GetPlanetID(self): 100 return self.planetData.planetID 101 102 def ConstructRowContainers(self): 103 self.topRowCont = ContainerAutoSize(name='topRowCont', parent=self.mainCont, align=uiconst.TOTOP, height=self.GetIconSize(), padTop=6, state=uiconst.UI_HIDDEN) 104 self.buttonCont = ContainerAutoSize(name='buttonCont', parent=self.mainCont, align=uiconst.BOTTOMRIGHT) 105 self.bottomRowCont = ContainerAutoSize(name='bottomRowCont', parent=self.mainCont, align=uiconst.TOTOP, height=self.GetIconSize(), padTop=6, state=uiconst.UI_HIDDEN, clipChildren=True) 106 107 def ConstructNoActivityLabel(self, text): 108 self.noActivityLabel = EveLabelMedium(parent=self.mainCont, align=uiconst.TOTOP, text=text, state=uiconst.UI_DISABLED, padTop=6, idx=0, showEllipsis=True) 109 110 def ReconstructItemConts(self): 111 self.topRowCont.Flush() 112 self.buttonCont.Flush() 113 self.CheckConstructExtractionCont() 114 self.CheckConstructProductsCont() 115 self.bottomRowCont.Flush() 116 self.CheckConstructStorageCont() 117 self.AddExtractionButton() 118 if not self.topRowCont.children and not self.bottomRowCont.children: 119 self.noActivityLabel.Show() 120 else: 121 self.noActivityLabel.Hide() 122 123 def CheckConstructProductsCont(self): 124 itemAmount = self.planetData.colony.colonyData.GetAllProcessorProducts() 125 errorsTypeIDs = self.planetData.colony.colonyData.GetErrorsForProcessors() 126 self._CheckConstructItemsCont(self.topRowCont, itemAmount, GetByLabel('UI/PI/Common/Production'), 'res:/UI/Texture/Planet/Icons/processor.png', errorTypeIDs=errorsTypeIDs) 127 128 def CheckConstructExtractionCont(self): 129 itemAmount = self.planetData.colony.colonyData.GetAllECUProducts() 130 errorsTypeIDs = self.planetData.colony.colonyData.GetErrorsForECUPins() 131 self._CheckConstructItemsCont(self.topRowCont, itemAmount, GetByLabel('UI/PI/Common/Extraction'), 'res:/UI/Texture/Planet/Icons/ecu.png', errorTypeIDs=errorsTypeIDs) 132 133 def CheckConstructStorageCont(self): 134 itemAmount = self.planetData.colony.colonyData.GetAllStoredProducts() 135 errorsTypeIDs = self.planetData.colony.colonyData.GetErrorsForStorage() 136 self._CheckConstructItemsCont(self.GetStorageContParent(), itemAmount, GetByLabel('UI/PI/Common/Storage'), 'res:/UI/Texture/Planet/Icons/storage.png', showAmount=True, errorTypeIDs=errorsTypeIDs) 137 138 def GetStorageContParent(self): 139 return self.bottomRowCont 140 141 def _CheckConstructItemsCont(self, parent, itemAmount, hint, texturePath, showAmount = False, errorTypeIDs = None): 142 if itemAmount: 143 errorTypeIDs = errorTypeIDs or set() 144 parent.state = uiconst.UI_PICKCHILDREN 145 PlanetItemCont(parent=parent, align=uiconst.TOLEFT, itemAmount=itemAmount, height=self.GetIconSize(), texturePath=texturePath, hint=hint, padRight=38, onIconDblClickCallback=self.OnDblClick, onMouseEnterCallback=self.OnMouseEnter, showAmount=showAmount, errorTypeIDs=errorTypeIDs) 146 147 def ConstructIcon(self): 148 self.ConstructNeedsAttentionIcon() 149 if self.planetData: 150 self.icon = eveIcon.Icon(parent=self.iconCont, align=uiconst.TOALL, typeID=self.planetData.planetTypeID, itemID=self.planetData.planetID, effectOpacity=0.0) 151 self.CheckUpdateNeedsAttentionIndication() 152 153 def AddExtractionButton(self): 154 planetSvc = sm.GetService('planetSvc') 155 colonyData = self.planetData.colony.colonyData 156 if planetSvc.IsSubmittingInProgressForPlanet(self.GetPlanetID()) and colonyData.GetECUPins(): 157 self._AddExtractionButton(disabledReasonPath='UI/PI/Common/PlanetBusyUpdating') 158 return 159 if self.planetData.IsEditingPlanet(): 160 return 161 if not colonyData.CanEcuPinsBeRestarted(): 162 return 163 disabledReasonPath = None 164 if planetSvc.IsSubmittingInProgressOrThrottled(): 165 disabledReasonPath = 'UI/PI/Common/PlanetBusyUpdating' 166 self._AddExtractionButton(disabledReasonPath) 167 168 def _AddExtractionButton(self, disabledReasonPath = None): 169 if self.topRowCont.children and self.bottomRowCont.children: 170 self.buttonCont.SetAlign(uiconst.TORIGHT) 171 else: 172 self.buttonCont.SetAlign(uiconst.BOTTOMRIGHT) 173 enabled = disabledReasonPath is None 174 hint = GetByLabel(disabledReasonPath) if disabledReasonPath else '' 175 Button(name='restartExtraction', parent=self.buttonCont, label=GetByLabel('UI/PI/Common/RestartExtaction'), func=self.RestartExtractors, align=uiconst.BOTTOMRIGHT, texturePath=eveicon.refresh, pos=(GENERIC_PADDING, 176 2, 177 0, 178 0), variant=ButtonVariant.GHOST, enabled=enabled, hint=hint) 179 180 def CheckUpdateNeedsAttentionIndication(self): 181 if self.IsAttentionNeeded(): 182 self.icon.spriteEffect = trinity.TR2_SFX_COLOROVERLAY 183 self.icon.saturation = 0.25 184 self.needsAttentionCont.Show() 185 else: 186 self.icon.spriteEffect = trinity.TR2_SFX_COPY 187 self.icon.saturation = 1.0 188 self.needsAttentionCont.Hide() 189 190 def ConstructNeedsAttentionIcon(self): 191 self.needsAttentionCont = Container(name='needsAttentionCont', parent=self.iconCont) 192 Sprite(name='needsAttentionCircle', parent=self.needsAttentionCont, texturePath='res:/UI/Texture/Planet/planetsWnd/circleBg.png', align=uiconst.CENTER, pos=(0, 0, 98, 98)) 193 self.needsAttentionCircle = Sprite(name='needsAttentionCircle', parent=self.needsAttentionCont, texturePath='res:/UI/Texture/Planet/planetsWnd/needsAttentionIcon.png', align=uiconst.CENTER, pos=(0, 0, 31, 31), color=Color.RED) 194 animations.FadeTo(self.needsAttentionCircle, 0.2, 1.0, duration=2.0, curveType=uiconst.ANIM_WAVE, loops=uiconst.ANIM_REPEAT) 195 196 def IsAttentionNeeded(self): 197 return self.planetData.colony.colonyData.IsSomePinNeedingAttention() 198 199 def GetCaptionText(self): 200 securityText = self.GetSecurityStatusTxt(self.planetData.solarSystemID) 201 planetName = cfg.evelocations.Get(self.planetData.planetID).locationName 202 planetTypeName = GetByLabel(planetConst.PLANETTYPE_NAMES[self.planetData.planetTypeID]) 203 numInstallations = len(self.planetData.colony.colonyData.pins) 204 numInstallationsTxt = GetByLabel('UI/PI/Common/NumInstallations', numInstallations=numInstallations) 205 captionText = '%s %s - %s - %s' % (securityText, 206 planetName, 207 planetTypeName, 208 numInstallationsTxt) 209 return captionText 210 211 def GetSecurityStatusTxt(self, solarSystemID): 212 securityStatus = sm.GetService('map').GetSecurityStatus(solarSystemID) 213 sec, col = FmtSystemSecStatus(securityStatus, 1) 214 color = Color.RGBtoHex(*col) 215 text = '<color=%s>%s</color>' % (color, sec) 216 return text 217 218 def GetMenu(self, *args): 219 if not self.planetData: 220 return 221 menu = [] 222 menuSvc = sm.GetService('menu') 223 solarSystemID = self.planetData.solarSystemID 224 planetID = self.planetData.planetID 225 if solarSystemID != session.solarsystemid: 226 mapItem = sm.StartService('map').GetItem(solarSystemID) 227 if session.role & (service.ROLE_GML | service.ROLE_WORLDMOD): 228 gmExtrasLabel = MenuLabel('UI/ScienceAndIndustry/ScienceAndIndustryWindow/GMWMExtrasCommand') 229 menu += [(gmExtrasLabel, ('isDynamic', menuSvc.GetGMMenu, (planetID, 230 None, 231 None, 232 None, 233 mapItem)))] 234 menu += menuSvc.MapMenu(solarSystemID) 235 isOpen = sm.GetService('viewState').IsViewActive('planet') and sm.GetService('planetUI').planetID == planetID 236 if isOpen: 237 menu += [[MenuLabel('UI/PI/Common/ExitPlanetMode'), sm.GetService('viewState').CloseSecondaryView, ()]] 238 else: 239 menu += [(MenuLabel('UI/PI/Common/ViewInPlanetMode'), sm.GetService('planetUI').Open, (planetID,))] 240 typeID = self.planetData.planetTypeID 241 menu += [(MenuLabel('UI/Commands/ShowInfo'), menuSvc.ShowInfo, (typeID, 242 planetID, 243 0, 244 None, 245 None))] 246 else: 247 menu += menuSvc.CelestialMenu(planetID) 248 return menu 249 250 def OnClick(self, *args): 251 self.onClickCallback(self) 252 253 def OnDblClick(self, *args): 254 sm.GetService('planetUI').Open(self.planetData.planetID) 255 256 def LoadTooltipPanel(self, tooltipPanel, *args): 257 if self.IsAttentionNeeded(): 258 tooltipPanel.LoadGeneric1ColumnTemplate() 259 text = '<color=red>%s</color>' % GetByLabel('UI/PI/Common/ColonyRequiresAttention') 260 tooltipPanel.AddLabelMedium(text=text) 261 262 def GetTooltipPointer(self): 263 return uiconst.POINT_RIGHT_2 264 265 def RestartExtractors(self, btn, *args): 266 btn.Disable() 267 restarted = self.planetData.RestartExtractors() 268 if restarted: 269 message_player(GetByLabel('UI/PI/Common/RestartExtractionSuccess')) 270 else: 271 message_player(GetByLabel('UI/PI/Common/RestartExtractionFailure')) 272 273 def OnPlanetSubmittingChanges(self): 274 self.Update() 275 276 def Update(self): 277 self.CheckUpdateNeedsAttentionIndication() 278 self.ReconstructItemConts() 279 280 281 class ColonyEntryCompact(ColonyEntry): 282 default_height = HEIGHT_COMPACT 283 284 def ConstructNeedsAttentionIcon(self): 285 self.needsAttentionCont = Container(name='needsAttentionCont', parent=self.iconCont) 286 self.needsAttentionCircle = Sprite(name='needsAttentionCircle', parent=self.needsAttentionCont, texturePath='res:/UI/Texture/Planet/planetsWnd/needsAttentionIcon.png', align=uiconst.CENTER, pos=(0, 0, 31, 31), color=Color.RED) 287 animations.FadeTo(self.needsAttentionCircle, 0.2, 1.0, duration=2.0, curveType=uiconst.ANIM_WAVE, loops=uiconst.ANIM_REPEAT) 288 289 def ConstructRowContainers(self): 290 self.buttonCont = ContainerAutoSize(name='buttonCont', parent=self.mainCont, align=uiconst.TORIGHT) 291 self.topRowCont = ContainerAutoSize(name='topRowCont', parent=self.mainCont, align=uiconst.TOTOP, height=self.GetIconSize(), padTop=0, state=uiconst.UI_HIDDEN, clipChildren=True) 292 self.bottomRowCont = ContainerAutoSize(name='bottomRowCont', parent=self.mainCont, align=uiconst.TOTOP, height=self.GetIconSize(), padTop=6, state=uiconst.UI_HIDDEN) 293 294 def GetStorageContParent(self): 295 return self.topRowCont 296 297 def GetIconSize(self): 298 return ICONSIZE_COMPACT 299 300 def ConstructCaption(self): 301 self.caption = EveLabelMedium(parent=self.captionCont, align=uiconst.CENTERLEFT, text=self.GetCaptionText(), padding=(GENERIC_PADDING, 302 1, 303 0, 304 3)) 305 306 def _AddExtractionButton(self, disabledReasonPath = True): 307 enabled = disabledReasonPath is None 308 hint = GetByLabel(disabledReasonPath) if disabledReasonPath else GetByLabel('UI/PI/Common/RestartExtaction') 309 Button(name='restartExtraction', parent=self.buttonCont, func=self.RestartExtractors, align=uiconst.CENTERRIGHT, texturePath=eveicon.refresh, density=Density.COMPACT, hint=hint, pos=(GENERIC_PADDING, 310 2, 311 0, 312 0), variant=ButtonVariant.GHOST, enabled=enabled) 313 314 315 class ColonyEntryEmpty(BaseColonyEntry): 316 317 def ApplyAttributes(self, attributes): 318 BaseColonyEntry.ApplyAttributes(self, attributes) 319 self.slotIndex = attributes.slotIndex 320 self.slotsTotal = attributes.slotsTotal 321 if self.IsLocked() or not cloneStateUtil.IsOmega(): 322 self.ConstructIconLocked() 323 else: 324 self.ConstructIconAvailable() 325 if not self.IsLocked() and not cloneStateUtil.IsOmega(): 326 self.ConstructIconOmegaNeeded() 327 else: 328 self.ConstructLabel() 329 330 def ConstructLabel(self): 331 EveLabelMedium(parent=self.mainCont, align=uiconst.TOTOP, text=self.GetMainText(), state=uiconst.UI_NORMAL, padTop=6, idx=0, maxLines=5) 332 333 def ConstructIconOmegaNeeded(self): 334 OmegaRestrictedEntry(parent=self.mainCont, align=uiconst.TOTOP, height=30, padTop=8, text=GetByLabel('UI/CloneState/PlanetaryProductionDisabled'), hint=GetByLabel('UI/CloneState/PlanetExportingDisabledHint')) 335 336 def ConstructIconAvailable(self): 337 iconSize = self.GetAvailableIconSize() 338 Sprite(parent=self.iconCont, align=uiconst.CENTER, pos=(0, 339 0, 340 iconSize, 341 iconSize), texturePath='res:/UI/Texture/Planet/PlanetsWnd/slotUnlocked.png') 342 343 def GetAvailableIconSize(self): 344 return 98 345 346 def ConstructIconLocked(self): 347 iconSize = self.GetLockedIconSize() 348 Sprite(parent=self.iconCont, align=uiconst.CENTER, pos=(0, 349 0, 350 iconSize, 351 iconSize), texturePath='res:/UI/Texture/Planet/PlanetsWnd/slotLocked.png') 352 SpriteThemeColored(name='hatchesBg', bgParent=self.iconCont, texturePath='res:/UI/Texture/Classes/Industry/Output/hatchPattern.png', tileX=True, tileY=True, colorType=uiconst.COLORTYPE_UIHILIGHT, opacity=0.3) 353 354 def GetLockedIconSize(self): 355 return 68 356 357 def GetMainText(self): 358 if self.IsLocked(): 359 return self._GetLockedText() 360 else: 361 typeID = appConst.typeBarrenCommandCenter 362 marketGroup, _ = sm.GetService('marketutils').FindMarketGroup(typeID) 363 return GetByLabel('UI/PI/Common/RequiresCommandCenter', marketGroupID=marketGroup.marketGroupID) 364 365 def _GetLockedText(self): 366 return GetByLabel('UI/PI/Common/RequiresSkillLevelX', typeID=appConst.typeInterplanetaryConsolidation, skillLevel=IntToRoman(self.slotIndex)) 367 368 def IsLocked(self): 369 return self.slotIndex >= self.slotsTotal 370 371 def GetCaptionText(self): 372 return GetByLabel('UI/PI/Common/UnestablishedColony') 373 374 375 class ColonyEntryEmptyCompact(ColonyEntryEmpty): 376 default_height = HEIGHT_COMPACT 377 378 def GetAvailableIconSize(self): 379 return 49 380 381 def GetLockedIconSize(self): 382 return 34 383 384 def GetIconSize(self): 385 return ICONSIZE_COMPACT 386 387 def ConstructLabel(self): 388 EveLabelMedium(parent=self.mainCont, align=uiconst.TOTOP, text=self.GetMainText(), state=uiconst.UI_NORMAL, idx=0, maxLines=2) 389 390 def ConstructCaption(self): 391 self.caption = EveLabelMedium(parent=self.captionCont, align=uiconst.CENTERLEFT, text=self.GetCaptionText(), padding=(GENERIC_PADDING, 392 1, 393 0, 394 3)) 395 396 397 class PlanetItemCont(ContainerAutoSize): 398 399 def ApplyAttributes(self, attributes): 400 ContainerAutoSize.ApplyAttributes(self, attributes) 401 self.hint = attributes.hint 402 self.itemAmount = attributes.itemAmount 403 texturePath = attributes.texturePath 404 self.showAmount = attributes.Get('showAmount', False) 405 self.errorTypeIDs = attributes.Get('errorTypeIDs', set()) 406 self.onIconDblClickCallback = attributes.onIconDblClickCallback 407 self.onMouseEnterCallback = attributes.onMouseEnterCallback 408 groupIconCont = Container(name='groupIconCont', parent=self, align=uiconst.TOLEFT, width=self.height) 409 iconSize = self.height - 8 410 icon = SpriteThemeColored(name='groupIcon', parent=groupIconCont, texturePath=texturePath, colorType=uiconst.COLORTYPE_UIHILIGHTGLOW, align=uiconst.CENTERLEFT, pos=(0, 411 0, 412 iconSize, 413 iconSize), opacity=0.9) 414 icon.OnDblClick = self.onIconDblClickCallback 415 icon.OnMouseEnter = self.onMouseEnterCallback 416 icon.LoadTooltipPanel = self.LoadIconTooltipPanel 417 if None in self.errorTypeIDs: 418 self.AddWarningLine(groupIconCont, padRight=8) 419 for typeID, amount in self.itemAmount.iteritems(): 420 if not self.showAmount: 421 amount = None 422 storageIconCont = Container(parent=self, align=uiconst.TOLEFT, width=self.height, padRight=4) 423 if typeID in self.errorTypeIDs: 424 self.AddWarningLine(storageIconCont) 425 icon = StorageIcon(parent=storageIconCont, align=uiconst.CENTER, pos=(0, 426 0, 427 self.height, 428 self.height), typeID=typeID, amount=amount) 429 icon.OnDblClick = self.onIconDblClickCallback 430 icon.OnMouseEnter = self.onMouseEnterCallback 431 432 self.SetSizeAutomatically() 433 434 def AddWarningLine(self, parent, padRight = 0): 435 cont = Container(parent=parent, align=uiconst.TOBOTTOM_NOPUSH, height=10, padRight=padRight, state=uiconst.UI_NORMAL) 436 Line(parent=cont, align=uiconst.TOBOTTOM_NOPUSH, outputMode=trinity.Tr2SpriteTarget.COLOR_AND_GLOW, color=eveColor.CHERRY_RED) 437 cont.hint = GetByLabel('UI/PI/Common/ColonyRequiresAttention') 438 439 def LoadIconTooltipPanel(self, tooltipPanel, *args): 440 tooltipPanel.LoadGeneric1ColumnTemplate() 441 tooltipPanel.AddLabelMedium(text=self.hint) 442 if self.showAmount: 443 totalPriceText = self.GetTotalPriceText() 444 tooltipPanel.AddLabelMedium(text=totalPriceText) 445 446 def GetTotalPriceText(self): 447 total = 0 448 for typeID, amount in self.itemAmount.iteritems(): 449 price = typeHelpers.GetAveragePrice(typeID) 450 if price: 451 total += price * amount 452 453 return GetByLabel('UI/Inventory/EstIskPrice', iskString=FmtISKAndRound(total, False))