uix.py (33310B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\util\uix.py 2 import math 3 import sys 4 import appConst 5 import numbers 6 import types 7 import blue 8 import caching 9 import dogma.data 10 import dogma.units 11 import eveicon 12 import evetypes 13 import localization 14 import log 15 import metaGroups 16 import telemetry 17 import trinity 18 import utillib 19 from carbon.common.script.util.format import FmtAmt 20 from carbonui import fontconst, uiconst 21 from carbonui.control.scroll_const import GetHiddenColumnsKey 22 from carbonui.primitives.containerAutoSize import ContainerAutoSize 23 from carbonui.primitives.sprite import Sprite 24 from carbonui.uicore import uicore 25 from carbonui.util.bunch import Bunch 26 from carbonui.util.various_unsorted import MapIcon 27 from dogma.attributes.format import GetFormatAndValue 28 from dogma.const import attributeNonDestructible 29 from eve.client.script.ui.control import eveLabel 30 from eve.client.script.ui.control.eveIcon import GetLogoIcon, Icon 31 from carbonui.control.window import Window 32 from eve.client.script.ui.control.themeColored import FillThemeColored 33 from eve.common.lib import appConst as const 34 from eve.common.script.sys import idCheckers 35 from eve.common.script.sys.idCheckers import IsSolarSystem, IsKnownSpaceSystem 36 from eve.common.script.util.eveFormat import FmtISK, GetAveragePrice 37 from fsdBuiltData.common.iconIDs import GetIconFile 38 from inventorycommon.const import VIEWMODE_ICONS, VIEWMODE_DETAILS, VIEWMODE_LIST, VIEWMODE_CARDS 39 from inventorycommon.util import GetItemVolume 40 from player_messaging.client.ui_message import prompt_player_fsd_dialog 41 from spacecomponents.common.helper import HasDeployComponent, HasNpcPilotComponent, HasMineableComponent, GetMineableComponentTypeAttributes 42 from inventorycommon.typeHelpers import GetAveragePrice as GetAverageTypePrice 43 isTakeTimeEnabled = True 44 slotTextByEffect = {const.effectRigSlot: 'UI/Inventory/SlotRigs', 45 const.effectHiPower: 'UI/Inventory/SlotHigh', 46 const.effectMedPower: 'UI/Inventory/SlotMedium', 47 const.effectLoPower: 'UI/Inventory/SlotLow'} 48 categoryGroupTypeStringForTypeID = {} 49 50 def TakeTime(label, func, *args, **kw): 51 if isTakeTimeEnabled: 52 t = blue.pyos.taskletTimer.EnterTasklet(label) 53 try: 54 return func(*args, **kw) 55 finally: 56 blue.pyos.taskletTimer.ReturnFromTasklet(t) 57 58 else: 59 return func(*args, **kw) 60 61 62 @telemetry.ZONE_FUNCTION 63 def GetItemData(rec, viewMode, viewOnly = 0, container = None, scrollID = None, *args, **kw): 64 attribs = {} 65 for attribute in sm.GetService('godma').GetType(rec.typeID).displayAttributes: 66 attribs[attribute.attributeID] = attribute.value 67 68 sort_slotsize = 0 69 for effect in dogma.data.get_type_effects(rec.typeID): 70 if effect.effectID in (const.effectHiPower, const.effectMedPower, const.effectLoPower): 71 sort_slotsize = 1 72 break 73 74 data = Bunch() 75 data.__guid__ = 'listentry.InvItem' 76 data.item = rec 77 data.rec = rec 78 data.itemID = rec.itemID 79 data.godmaattribs = attribs 80 data.invtype = rec.typeID 81 data.container = container 82 data.viewMode = viewMode 83 data.viewOnly = viewOnly 84 data.locked = rec.flagID == const.flagLocked 85 data.sublevel = kw.get('sublevel', 0) 86 if not data.locked and rec.flagID != const.flagUnlocked and container and container.invController.isLockable: 87 if hasattr(container, 'invController'): 88 containerItem = container.invController.GetInventoryItem() 89 if containerItem: 90 maybeLocked = containerItem.groupID in (const.groupAuditLogSecureContainer, const.groupStation) 91 maybeLocked = maybeLocked or evetypes.GetCategoryID(data.invtype) == const.categoryBlueprint and containerItem.typeID in (const.typeOffice, const.typeAssetSafetyWrap) 92 if maybeLocked: 93 data.locked = sm.GetService('lockedItems').IsItemLocked(rec) 94 data.factionID = sm.GetService('faction').GetCurrentFactionID() 95 if rec.singleton or rec.typeID in (const.typeBookmark,): 96 data.Set('sort_%s' % localization.GetByLabel('UI/Common/Quantity'), 0) 97 else: 98 data.Set('sort_%s' % localization.GetByLabel('UI/Common/Quantity'), rec.stacksize) 99 ml = evetypes.GetMetaLevel(data.invtype) 100 if not ml: 101 metaLevel = '' 102 else: 103 metaLevel = FmtAmt(ml) 104 data.metaLevel = metaLevel 105 data.groupName = evetypes.GetGroupName(rec.typeID) 106 data.categoryName = evetypes.GetCategoryName(rec.typeID) 107 estPrice = GetAveragePrice(rec) 108 data.estPrice = rec.stacksize * estPrice if estPrice and rec.stacksize else None 109 data.sort_ammosizeconstraints = const.attributeChargeSize in attribs 110 data.sort_slotsize = sort_slotsize 111 data.Set('sort_%s' % localization.GetByLabel('UI/Common/Name'), GetItemName(rec, data).lower()) 112 data.Set('sort_%s' % localization.GetByLabel('UI/Common/Type'), GetCategoryGroupTypeStringForItem(rec).lower()) 113 data.Set('sort_%s' % localization.GetByLabel('UI/Inventory/ItemMetaLevel'), ml or 0.0) 114 data.Set('sort_%s' % localization.GetByLabel('UI/Inventory/ItemGroup'), data.groupName.lower()) 115 data.Set('sort_%s' % localization.GetByLabel('UI/Inventory/ItemCategory'), data.categoryName.lower()) 116 data.Set('sort_%s' % localization.GetByLabel('UI/Contracts/ContractsWindow/EstPrice'), data.estPrice or 0) 117 if data.rec.typeID == const.typePlasticWrap: 118 data.volume = '' 119 data.Set('sort_%s' % localization.GetByLabel('UI/Inventory/ItemVolume'), 0) 120 else: 121 volume = GetItemVolume(rec) 122 unit = dogma.units.get_display_name(const.unitVolume) 123 decimalPlaces = 2 if abs(volume - int(volume)) > const.FLOAT_TOLERANCE else 0 124 data.volume = localization.GetByLabel('UI/InfoWindow/ValueAndUnit', value=FmtAmt(volume, showFraction=decimalPlaces), unit=unit) 125 data.Set('sort_%s' % localization.GetByLabel('UI/Inventory/ItemVolume'), volume) 126 data.scrollID = scrollID 127 return data 128 129 130 @telemetry.ZONE_FUNCTION 131 def GetItemLabel(rec, data, new = 0): 132 if getattr(data, 'label', None) and data.viewMode == VIEWMODE_ICONS and not new: 133 return data.label 134 name = GetItemName(rec, data) 135 if data.viewMode in (VIEWMODE_LIST, VIEWMODE_DETAILS): 136 label = GetItemLabelForListOrDetails(rec, data, name) 137 data.label = label 138 elif data.viewMode == VIEWMODE_CARDS: 139 data.label = name 140 else: 141 data.label = '<center>%s' % name 142 return data.label 143 144 145 class Column(object): 146 NAME = 0 147 QUANTITY = 1 148 GROUP = 2 149 CATEGORY = 3 150 SIZE = 4 151 SLOT = 5 152 VOLUME = 6 153 META_LEVEL = 7 154 TECH_LEVEL = 8 155 ESTIMATED_PRICE = 9 156 _COLUMN_BY_LABEL = {'UI/Common/Name': NAME, 157 'UI/Common/Quantity': QUANTITY, 158 'UI/Inventory/ItemGroup': GROUP, 159 'UI/Inventory/ItemCategory': CATEGORY, 160 'UI/Inventory/ItemSize': SIZE, 161 'UI/Inventory/ItemSlot': SLOT, 162 'UI/Inventory/ItemVolume': VOLUME, 163 'UI/Inventory/ItemMetaLevel': META_LEVEL, 164 'UI/Inventory/ItemTechLevel': TECH_LEVEL, 165 'UI/Contracts/ContractsWindow/EstPrice': ESTIMATED_PRICE} 166 _cached_column_localized_labels_by_language_id = {} 167 168 @classmethod 169 def from_localized_label(cls, text): 170 language_id = session.languageID 171 if language_id not in cls._cached_column_localized_labels_by_language_id: 172 Column._cache_localized_labels_for_language(session.languageID) 173 return cls._cached_column_localized_labels_by_language_id[language_id][text] 174 175 @classmethod 176 def _cache_localized_labels_for_language(cls, language_id): 177 cls._cached_column_localized_labels_by_language_id[language_id] = {localization.GetByLabel(label, languageID=language_id):header for label, header in cls._COLUMN_BY_LABEL.items()} 178 179 180 def _get_item_size(rec, data, name): 181 attribs = getattr(data, 'godmaattribs', {}) 182 if const.attributeChargeSize in attribs: 183 return GetFormatAndValue(attributeType=utillib.KeyVal(unitID=const.unitSizeclass, attributeID=const.attributeChargeSize, dataType=const.attributeDataTypeTypeInteger), value=attribs[const.attributeChargeSize]) 184 else: 185 return '' 186 187 188 def _get_item_slot(rec, data, name): 189 attribs = getattr(data, 'godmaattribs', {}) 190 if const.attributeImplantness in attribs: 191 return GetFormatAndValue(attributeType=utillib.KeyVal(unitID=int, attributeID=const.attributeImplantness, dataType=const.attributeDataTypeTypeInteger), value=attribs[const.attributeImplantness]) 192 elif const.attributeBoosterness in attribs: 193 return GetFormatAndValue(attributeType=utillib.KeyVal(unitID=int, attributeID=const.attributeBoosterness, dataType=const.attributeDataTypeTypeInteger), value=attribs[const.attributeBoosterness]) 194 else: 195 return GetPowerSlotSizeSymbol(rec.typeID) or '' 196 197 198 def _get_item_tech_level(rec, data, name): 199 techLevel = evetypes.GetTechLevel(rec.typeID) 200 if techLevel: 201 techLevel = FmtAmt(techLevel) 202 return '<right>%s' % techLevel 203 204 205 _item_column_value_getter_by_column = {Column.NAME: lambda rec, data, name: name, 206 Column.QUANTITY: lambda rec, data, name: '<right>%s' % GetItemQty(data, 'ln'), 207 Column.GROUP: lambda rec, data, name: data.groupName, 208 Column.CATEGORY: lambda rec, data, name: data.categoryName, 209 Column.SIZE: _get_item_size, 210 Column.SLOT: _get_item_slot, 211 Column.VOLUME: lambda rec, data, name: '<right>%s' % data.volume, 212 Column.META_LEVEL: lambda rec, data, name: '<right>%s' % data.metaLevel, 213 Column.TECH_LEVEL: _get_item_tech_level, 214 Column.ESTIMATED_PRICE: lambda rec, data, name: ('<right>%s' % FmtISK(data.estPrice) if data.estPrice else '')} 215 216 def GetImplantsCostForCharacter(): 217 try: 218 godma = sm.GetService('godma') 219 godmaItem = godma.GetItem(session.charid) 220 if godmaItem: 221 implantCost = 0 222 for implant in godmaItem.implants: 223 if godma.GetTypeAttribute2(implant.typeID, attributeNonDestructible): 224 continue 225 avgPrice = GetAverageTypePrice(implant.typeID) 226 if avgPrice: 227 implantCost += avgPrice 228 229 return implantCost 230 return None 231 except Exception as e: 232 log.LogException('Failing to get implant cost') 233 234 235 def GetItemLabelForListOrDetails(rec, data, name): 236 column_values = [] 237 for header in GetVisibleItemHeaders(data.scrollID): 238 getter = _item_column_value_getter_by_column[Column.from_localized_label(header)] 239 column_values.append(getter(rec, data, name)) 240 241 return u'<t>'.join(column_values) 242 243 244 @telemetry.ZONE_FUNCTION 245 def GetPowerSlotSizeSymbol(recTypeID): 246 fType = None 247 for effect in dogma.data.get_type_effects(recTypeID): 248 labelPath = slotTextByEffect.get(effect.effectID) 249 if labelPath: 250 fType = localization.GetByLabel(labelPath) 251 break 252 253 return fType 254 255 256 @telemetry.ZONE_FUNCTION 257 def GetItemQty(data, fmt = 'ln'): 258 ret = getattr(data, 'qty_%s' % fmt, None) 259 if ret is not None and ret[0] == data.item.stacksize: 260 return ret[1] 261 ret = '' 262 if not (data.item.singleton or data.item.typeID in (const.typeBookmark,)): 263 ret = FmtAmt(data.item.stacksize, fmt) 264 setattr(data, 'qty_%s' % fmt, (data.item.stacksize, ret)) 265 return ret 266 267 268 NAMEABLE_GROUPS = (const.groupWreck, 269 const.groupCargoContainer, 270 const.groupSecureCargoContainer, 271 const.groupAuditLogSecureContainer, 272 const.groupFreightContainer, 273 const.groupBiomass) 274 275 def IsValidNamedItem(invItem): 276 if not invItem.singleton: 277 return False 278 elif invItem.categoryID == const.categoryShip: 279 return True 280 elif invItem.groupID in NAMEABLE_GROUPS: 281 return True 282 elif HasDeployComponent(invItem.typeID): 283 return True 284 else: 285 return False 286 287 288 def PrimeEveLocationsBeforeGetItemName(invItems): 289 itemIDsToPrime = {x.itemID for x in invItems if IsValidNamedItem(x)} 290 if itemIDsToPrime: 291 cfg.evelocations.Prime(itemIDsToPrime) 292 293 294 @telemetry.ZONE_FUNCTION 295 def GetItemName(invItem, data = None): 296 if data and getattr(data, 'name', None): 297 return data.name 298 name = evetypes.GetName(invItem.typeID) 299 if invItem.categoryID == const.categoryStation and invItem.groupID == const.groupStation: 300 try: 301 name = localization.GetByLabel('UI/Station/StationInSolarSystem', station=invItem.itemID, solarsystem=invItem.locationID) 302 except KeyError: 303 sys.exc_clear() 304 305 elif IsValidNamedItem(invItem): 306 locationName = cfg.evelocations.Get(invItem.itemID).name 307 if locationName: 308 name = locationName 309 elif invItem.typeID == const.typeAssetSafetyWrap: 310 name = sm.GetService('assetSafety').GetWrapName(invItem.itemID) 311 elif invItem.categoryID == const.categoryStructure and invItem.singleton and IsSolarSystem(invItem.locationID): 312 try: 313 locationName = cfg.evelocations.Get(invItem.itemID).name 314 if locationName: 315 name = locationName 316 except KeyError: 317 pass 318 319 if data: 320 data.name = name 321 if name is None: 322 name = '%s %s' % (evetypes.GetName(invItem.typeID), invItem.itemID) 323 return name 324 325 326 @telemetry.ZONE_FUNCTION 327 def GetCategoryGroupTypeStringForItem(invItem): 328 try: 329 return categoryGroupTypeStringForTypeID[invItem.typeID] 330 except KeyError: 331 try: 332 retString = '%s %s %s' % (evetypes.GetCategoryNameByCategory(invItem.categoryID), evetypes.GetGroupNameByGroup(invItem.groupID), evetypes.GetName(invItem.typeID)) 333 categoryGroupTypeStringForTypeID[invItem.typeID] = retString 334 return retString 335 except (IndexError, 336 TypeError, 337 evetypes.CategoryNotFoundException, 338 evetypes.GroupNotFoundException, 339 evetypes.TypeNotFoundException): 340 return GetFallbackCategoryGroupTypeStringForItem(invItem) 341 342 343 def GetFallbackCategoryGroupTypeStringForItem(invItem): 344 if invItem is None: 345 log.LogTraceback('None is not an invItem') 346 sys.exc_clear() 347 return 'Unknown Unknown Unknown' 348 log.LogTraceback('InvalidItem Report') 349 sys.exc_clear() 350 log.LogError('--------------------------------------------------') 351 log.LogError('Invalid Item Report') 352 log.LogError('Item: ', invItem) 353 reason = '' 354 typeName = 'Unknown' 355 groupName = 'Unknown' 356 categoryName = 'Unknown' 357 try: 358 typeID = getattr(invItem, 'typeID', None) 359 except IndexError: 360 typeID = None 361 sys.exc_clear() 362 363 try: 364 groupID = getattr(invItem, 'groupID', None) 365 except IndexError: 366 groupID = None 367 sys.exc_clear() 368 369 try: 370 categoryID = getattr(invItem, 'categoryID', None) 371 except IndexError: 372 categoryID = None 373 sys.exc_clear() 374 375 if typeID is None: 376 log.LogError('typeID is missing. Probably caused by a coding mistake.') 377 reason += 'item attribute typeID is missing (Probably a coding mistake). ' 378 else: 379 typeExists = evetypes.Exists(typeID) 380 if not typeExists: 381 log.LogError('THERE IS NO type info FOR typeID:', typeID) 382 log.LogError('THE DATABASE REQUIRES CLEANUP FOR THIS TYPE') 383 reason += 'The type %s no longer exists. Database requires cleanup. ' % typeID 384 if groupID is None: 385 log.LogError('groupID is missing. Probably caused by a coding mistake.') 386 reason += 'item attribute groupID is missing (Probably a coding mistake?). ' 387 typeExists = evetypes.Exists(typeID) 388 if typeExists: 389 log.LogWarn('Extracting groupID from type') 390 groupID = evetypes.GetGroupID(typeID) 391 groupExists = evetypes.GroupExists(groupID) 392 if groupID is not None: 393 if not groupExists: 394 log.LogError('THERE IS NO group info FOR groupID:', groupID) 395 log.LogError('THE DATABASE REQUIRES CLEANUP FOR THIS GROUP') 396 reason += 'The group %s no longer exists. Database requires cleanup. ' % groupID 397 if categoryID is None: 398 log.LogError('categoryID is missing. Probably caused by a coding mistake.') 399 reason += 'item attribute categoryID is missing (Probably a coding mistake?). ' 400 if groupExists: 401 log.LogWarn('Extracting categoryID from group') 402 categoryID = evetypes.GetCategoryIDByGroup(groupID) 403 if categoryID is not None: 404 if not evetypes.CategoryExists(categoryID): 405 log.LogError('THERE IS NO category info FOR categoryID:', categoryID) 406 log.LogError('THE DATABASE REQUIRES CLEANUP FOR THIS CATEGORY') 407 reason += 'The category %s no longer exists. Database requires cleanup. ' % categoryID 408 if typeExists: 409 typeName = evetypes.GetName(typeID) 410 if groupExists: 411 groupName = evetypes.GetGroupNameByGroup(groupID) 412 if evetypes.CategoryExists(categoryID): 413 categoryName = evetypes.GetCategoryNameByCategory(categoryID) 414 log.LogError('--------------------------------------------------') 415 prompt_player_fsd_dialog('CustomInfo', {'info': 'Invalid item detected:<br>Item:%s<br>CGT:%s %s %s<br>Reason: %s' % (invItem, 416 categoryName, 417 groupName, 418 typeName, 419 reason)}) 420 return '%s %s %s' % (categoryName, groupName, typeName) 421 422 423 def GetSlimItemName(slimItem): 424 if slimItem.categoryID == const.categoryShip or HasNpcPilotComponent(slimItem.typeID): 425 if not slimItem.charID or slimItem.charID == session.charid and slimItem.itemID != session.shipid: 426 return evetypes.GetName(slimItem.typeID) 427 if idCheckers.IsCharacter(slimItem.charID): 428 return cfg.eveowners.Get(slimItem.charID).name 429 else: 430 if slimItem.groupID == appConst.groupHarvestableCloud or slimItem.categoryID == appConst.categoryAsteroid: 431 return evetypes.GetName(slimItem.typeID) 432 if HasMineableComponent(slimItem.typeID): 433 attributes = GetMineableComponentTypeAttributes(slimItem.typeID) 434 output_type = attributes.outputType 435 return evetypes.GetName(output_type) 436 if slimItem.categoryID == const.categoryOrbital: 437 return localization.GetByLabel('UI/Inventory/SlimItemNames/SlimOrbital', typeID=slimItem.typeID, planetID=slimItem.planetID, corpName=cfg.eveowners.Get(slimItem.ownerID).name) 438 if slimItem.groupID == const.groupDisruptedGate: 439 return localization.GetByLabel('UI/Inventory/SlimItemNames/SlimDisruptedGate', solarSystemID=slimItem.targetSolarSystemID) 440 locationname = cfg.evelocations.Get(slimItem.itemID).name 441 if locationname and locationname[0] != '@': 442 if slimItem.groupID == const.groupBeacon: 443 dungeonNameID = getattr(slimItem, 'dungeonNameID', None) 444 if dungeonNameID: 445 translatedName = localization.GetByMessageID(dungeonNameID) 446 return translatedName 447 return locationname 448 else: 449 return evetypes.GetName(slimItem.typeID) 450 451 452 def EditStationName(stationname, compact = 0, usename = 0): 453 if compact: 454 longForm = localization.GetByLabel('UI/Locations/LocationMoonLong') + ' ' 455 shortForm = localization.GetByLabel('UI/Locations/LocationMoonShort') 456 stationname = stationname.replace(longForm, shortForm).replace(longForm.lower(), shortForm.lower()) 457 _stationname = stationname.split(' - ') 458 if len(_stationname) >= 2 and usename: 459 stationname = _stationname[-1] 460 return stationname 461 462 463 def GetTextHeight(strng, width = 0, fontsize = fontconst.EVE_MEDIUM_FONTSIZE, linespace = None, hspace = 0, uppercase = 0, specialIndent = 0, getTextObj = 0, tabs = [], maxLines = None, fontStyle = None, bold = False, **kwds): 464 return uicore.font.GetTextHeight(strng, width=width, font=None, fontStyle=fontStyle, fontsize=fontsize, linespace=linespace, letterspace=hspace, uppercase=uppercase, specialIndent=specialIndent, getTextObj=getTextObj, tabs=tabs, maxLines=maxLines, bold=bold) 465 466 467 def GetTextWidth(strng, fontsize = fontconst.EVE_MEDIUM_FONTSIZE, hspace = 0, uppercase = 0, fontStyle = None, bold = False): 468 return uicore.font.GetTextWidth(strng, fontsize=fontsize, letterspace=hspace, uppercase=uppercase, fontStyle=fontStyle, bold=bold) 469 470 471 def GetStanding(standing, type = 0): 472 if standing > 5: 473 return localization.GetByLabel('UI/Standings/Excellent') 474 elif standing > 0: 475 return localization.GetByLabel('UI/Standings/Good') 476 elif standing == 0: 477 return localization.GetByLabel('UI/Standings/Neutral') 478 elif standing < -5: 479 return localization.GetByLabel('UI/Standings/Terrible') 480 elif standing < 0: 481 return localization.GetByLabel('UI/Standings/Bad') 482 else: 483 return localization.GetByLabel('UI/Standings/Unknown') 484 485 486 def GetMappedRankBase(rank, warFactionID, align): 487 logo = Sprite(align=align) 488 if rank < 0: 489 logo.texture = None 490 else: 491 iconNum = '%s_%s' % (rank / 4 + 1, rank % 4 + 1) 492 MapLogo(iconNum, logo, root='res:/UI/Texture/Medals/Ranks/%s_' % warFactionID) 493 if align != uiconst.TOALL: 494 logo.width = logo.height = 128 495 else: 496 logo.width = logo.height = 0 497 return logo 498 499 500 def GetRankSprite(rank, warFactionID, align): 501 texturePath = _GetRankTexturePath(rank, warFactionID) 502 if align != uiconst.TOALL: 503 size = 128 504 else: 505 size = 0 506 logo = Sprite(name='rankSprite', align=align, pos=(0, 507 0, 508 size, 509 size), texturePath=texturePath) 510 return logo 511 512 513 def _GetRankTexturePath(rank, warFactionID): 514 if rank < 0: 515 return None 516 texturePath = 'res:/UI/Texture/Medals/Ranks/%s_%s.png' % (warFactionID, rank) 517 return texturePath 518 519 520 def MapLogo(iconNum, sprite, root = 'res:/UI/Texture/Corps/corps'): 521 texpix, num = iconNum.split('_') 522 while texpix.find('0') == 0: 523 texpix = texpix[1:] 524 525 sprite.texturePath = '%s%s%s.dds' % (root, ['', '0'][int(texpix) < 10], texpix) 526 num = int(num) 527 sprite.rectWidth = sprite.rectHeight = 128 528 sprite.rectLeft = [0, 128][num in (2, 4)] 529 sprite.rectTop = [0, 128][num > 2] 530 531 532 def GetTechLevelIconPathAndHint(typeID = None): 533 icon = None 534 hint = None 535 if typeID is None: 536 return (icon, hint) 537 try: 538 if evetypes.GetCategoryID(typeID) in (const.categoryBlueprint, const.categoryAncientRelic): 539 ptID = cfg.blueprints.Get(typeID).productTypeID 540 if ptID is not None: 541 typeID = ptID 542 except Exception: 543 pass 544 545 metaGroupID = evetypes.GetMetaGroupID(typeID) 546 if metaGroupID: 547 icon = GetIconFile(metaGroups.get_icon_id(metaGroupID)) 548 hint = metaGroups.get_name(metaGroupID) 549 return (icon, hint) 550 551 552 def GetTechLevelColor(typeID = None): 553 if typeID is None: 554 return 555 metaGroupID = evetypes.GetMetaGroupID(typeID) 556 return metaGroups.get_color(metaGroupID) 557 558 559 def GetTechLevelIcon(tlicon = None, offset = 0, typeID = None): 560 icon, hint = GetTechLevelIconPathAndHint(typeID) 561 if icon: 562 if tlicon is None: 563 tlicon = Icon(icon=icon, parent=None, width=16, height=16, align=uiconst.TOPLEFT, idx=0, hint=hint) 564 else: 565 MapIcon(tlicon, icon) 566 tlicon.hint = hint 567 if offset: 568 tlicon.top = offset 569 tlicon.state = uiconst.UI_NORMAL 570 elif tlicon: 571 tlicon.state = uiconst.UI_HIDDEN 572 return tlicon 573 574 575 def GetBallparkRecord(itemID): 576 bp = sm.GetService('michelle').GetBallpark() 577 if bp and hasattr(bp, 'GetInvItem'): 578 return bp.GetInvItem(itemID) 579 else: 580 return None 581 582 583 def Close(owner, wndNames): 584 for each in wndNames: 585 if getattr(owner, each, None): 586 wnd = getattr(owner, each, None) 587 setattr(owner, each, None) 588 if not wnd.destroyed: 589 wnd.Close() 590 591 592 def GetContainerHeader(caption, where, bothlines = 1, padHorizontal = 0, padTop = 0): 593 container = ContainerAutoSize(name='headercontainer', parent=where, align=uiconst.TOTOP, alignMode=uiconst.TOTOP, padding=(padHorizontal, 594 padTop, 595 padHorizontal, 596 2)) 597 FillThemeColored(bgParent=container, colorType=uiconst.COLORTYPE_UIHILIGHT, align=uiconst.TOALL, opacity=0.15) 598 t = eveLabel.EveLabelLarge(text=caption, name='header1', parent=container, padding=(8, 4, 8, 4), align=uiconst.TOTOP) 599 return container 600 601 602 def ListWnd(lst, listtype = None, caption = None, hint = None, ordered = 0, minw = 200, minh = 256, minChoices = 1, maxChoices = 1, initChoices = [], validator = None, isModal = 1, scrollHeaders = [], iconMargin = 0, windowName = 'listwindow', lstDataIsGrouped = 0, unstackable = 0, noContentHint = None): 603 from eve.client.script.ui.control.listwindow import ListWindow 604 return ListWindow.ShowList(lst, listtype, caption, hint, ordered, minw, minh, minChoices, maxChoices, initChoices, validator, isModal, scrollHeaders, iconMargin, windowName, lstDataIsGrouped, unstackable, noContentHint) 605 606 607 def HybridWnd(format, caption, windowID, modal = 1, buttons = None, location = None, minW = 256, minH = 256, blockconfirm = 0, icon = None, unresizeAble = 0, ignoreCurrent = 1): 608 if windowID is None: 609 raise ValueError('Created Hybrid window without a windowID', caption) 610 else: 611 wnd = Window.GetIfOpen(windowID=windowID) 612 if wnd: 613 return 614 if buttons is None: 615 buttons = uiconst.OK 616 from eve.client.script.ui.control.hybridWindow import HybridWindow 617 wnd = HybridWindow.Open(ignoreCurrent=ignoreCurrent, format=format, caption=caption, modal=modal, windowID=windowID, buttons=buttons, location=location, minW=minW, minH=minH, icon=icon, blockconfirm=blockconfirm) 618 wnd.MakeUnstackable() 619 if unresizeAble: 620 wnd.MakeUnResizeable() 621 import uthread 622 uthread.new(wnd.OnScale_) 623 if modal == 1: 624 if wnd.ShowModal() == uiconst.ID_OK: 625 return wnd.result 626 else: 627 return 628 return wnd 629 630 631 def GetDialogIconTexturePath(icon): 632 if isinstance(icon, (types.StringType, eveicon.IconData)): 633 return icon 634 else: 635 mapping = {uiconst.INFO: 'res:/ui/Texture/WindowIcons/info.png', 636 uiconst.WARNING: 'res:/ui/Texture/WindowIcons/warning.png', 637 uiconst.QUESTION: 'res:/ui/Texture/WindowIcons/question.png', 638 uiconst.ERROR: 'res:/ui/Texture/WindowIcons/stop.png', 639 uiconst.FATAL: 'res:/UI/Texture/WindowICons/criminal.png'} 640 return mapping.get(icon, 'res:/ui/Texture/WindowIcons/warning.png') 641 642 643 def TextBox(header, txt, modal = 0, windowID = 'generictextbox2', tabs = [], preformatted = 0, scrolltotop = 1): 644 wnd = Window.GetIfOpen(windowID=windowID) 645 if wnd is None or wnd.destroyed or uicore.uilib.Key(uiconst.VK_SHIFT): 646 format = [{'type': 'textedit', 647 'readonly': 1, 648 'label': '_hide', 649 'key': 'text'}] 650 wnd = HybridWnd(format, header, windowID, modal, buttons=uiconst.CLOSE, location=None, minW=256, minH=128) 651 if wnd: 652 wnd.form.align = uiconst.TOALL 653 wnd.form.left = wnd.form.width = 3 654 wnd.form.top = -2 655 wnd.form.height = 6 656 wnd.form.sr.text.parent.align = uiconst.TOALL 657 wnd.form.sr.text.parent.left = wnd.form.sr.text.parent.top = wnd.form.sr.text.parent.width = wnd.form.sr.text.parent.height = 0 658 wnd.form.sr.text.parent.children[0].height = 0 659 wnd.form.sr.text.autoScrollToBottom = 0 660 if wnd is not None: 661 i = 1 662 for t in tabs: 663 setattr(wnd.form.sr.text.content.control, 'tabstop%s' % i, t) 664 i = i + 1 665 666 wnd.form.sr.text.SetValue(txt, scrolltotop=scrolltotop, preformatted=preformatted) 667 if wnd.state == uiconst.UI_NORMAL: 668 wnd.SetOrder(0) 669 else: 670 wnd.Maximize() 671 672 673 def QtyPopup(maxvalue = None, minvalue = 0, setvalue = '', hint = None, caption = None, label = '', digits = 0): 674 if caption is None: 675 caption = localization.GetByLabel('UI/Common/SetQuantity') 676 if maxvalue is not None and hint is None: 677 hint = localization.GetByLabel('UI/Common/SetQtyBetween', min=FmtAmt(minvalue), max=FmtAmt(maxvalue)) 678 if setvalue == 0: 679 setvalue = maxvalue 680 maxvalue = maxvalue or min(maxvalue, sys.maxint) 681 format = [] 682 if hint is not None: 683 format += [{'type': 'text', 684 'text': hint, 685 'frame': 0}] 686 if label is not None: 687 format += [{'type': 'labeltext', 688 'label': label, 689 'text': '', 690 'frame': 0, 691 'labelwidth': 240}] 692 if digits: 693 format += [{'type': 'edit', 694 'setvalue': setvalue, 695 'floatonly': [minvalue, maxvalue, digits], 696 'key': 'qty', 697 'label': '_hide', 698 'required': 1, 699 'frame': 0, 700 'setfocus': 1, 701 'selectall': 1}] 702 else: 703 format += [{'type': 'edit', 704 'setvalue': setvalue, 705 'intonly': [minvalue, maxvalue], 706 'key': 'qty', 707 'label': '_hide', 708 'required': 1, 709 'frame': 0, 710 'setfocus': 1, 711 'selectall': 1}] 712 return HybridWnd(format, caption, windowID='setQuantityPopup', modal=1, buttons=uiconst.OKCANCEL, location=None, minW=300, minH=120) 713 714 715 @caching.Memoize 716 def GetInvItemDefaultHiddenHeaders(): 717 return [localization.GetByLabel('UI/Inventory/ItemMetaLevel'), localization.GetByLabel('UI/Inventory/ItemTechLevel'), localization.GetByLabel('UI/Inventory/ItemCategory')] 718 719 720 @telemetry.ZONE_FUNCTION 721 @caching.Memoize 722 def GetInvItemDefaultHeaders(): 723 return [localization.GetByLabel('UI/Common/Name'), 724 localization.GetByLabel('UI/Common/Quantity'), 725 localization.GetByLabel('UI/Inventory/ItemGroup'), 726 localization.GetByLabel('UI/Inventory/ItemCategory'), 727 localization.GetByLabel('UI/Inventory/ItemSize'), 728 localization.GetByLabel('UI/Inventory/ItemSlot'), 729 localization.GetByLabel('UI/Inventory/ItemVolume'), 730 localization.GetByLabel('UI/Inventory/ItemMetaLevel'), 731 localization.GetByLabel('UI/Inventory/ItemTechLevel'), 732 localization.GetByLabel('UI/Contracts/ContractsWindow/EstPrice')] 733 734 735 @telemetry.ZONE_FUNCTION 736 def GetVisibleItemHeaders(scrollID): 737 key = GetHiddenColumnsKey(scrollID) 738 defaultHeaders = GetInvItemDefaultHeaders() 739 hiddenColumns = settings.user.ui.Get('filteredColumns_%s' % uiconst.SCROLLVERSION, {}).get(key, []) 740 allHiddenColumns = hiddenColumns + settings.user.ui.Get('filteredColumnsByDefault_%s' % uiconst.SCROLLVERSION, {}).get((key, session.languageID), []) 741 filterColumns = filter(lambda x: x not in allHiddenColumns, defaultHeaders) 742 return filterColumns 743 744 745 def GetLightYearDistance(fromSystem, toSystem, fraction = True): 746 for system in (fromSystem, toSystem): 747 if not isinstance(system, numbers.Integral): 748 return None 749 if not IsKnownSpaceSystem(system): 750 return None 751 752 def GetLoc(system): 753 if isinstance(system, numbers.Integral): 754 return cfg.evelocations.Get(system) 755 if type(system) == types.InstanceType: 756 return system 757 758 fromSystem = GetLoc(fromSystem) 759 toSystem = GetLoc(toSystem) 760 dist = math.sqrt((toSystem.x - fromSystem.x) ** 2 + (toSystem.y - fromSystem.y) ** 2 + (toSystem.z - fromSystem.z) ** 2) / const.LIGHTYEAR 761 if fraction: 762 dist = float(int(dist * 10)) / 10 763 return dist 764 765 766 def HideButtonFromGroup(btns, label, button = None): 767 if label: 768 btn = btns.FindChild('%s_Btn' % label) 769 if btn: 770 btn.state = uiconst.UI_HIDDEN 771 if button: 772 btn.state = uiconst.UI_HIDDEN 773 774 775 def ShowButtonFromGroup(btns, label, button = None): 776 if label: 777 btn = btns.FindChild('%s_Btn' % label) 778 if btn: 779 btn.state = uiconst.UI_NORMAL 780 if button: 781 btn.state = uiconst.UI_NORMAL 782 783 784 def FormatMedalData(data): 785 from eve.client.script.ui.shared.medalribbonranks import Ribbon 786 from eve.client.script.ui.shared.medalribbonranks import Medal 787 fdata = [] 788 for part in (1, 2): 789 dpart = {1: Ribbon, 790 2: Medal}.get(part, None) 791 pdata = [] 792 for row in data.Filter('part').get(part): 793 label, icon = row.graphic.split('.') 794 color = row.color 795 pdata.append((label, icon, color)) 796 797 fdata.append([dpart, pdata]) 798 799 return fdata 800 801 802 def GetFullscreenProjectionViewAndViewport(): 803 viewport = trinity.device.viewport 804 camera = sm.GetService('sceneManager').GetActiveCamera() 805 return (camera.projectionMatrix, camera.viewMatrix, viewport) 806 807 808 def GetOwnerLogo(parent, ownerID, size = 64, noServerCall = False): 809 if idCheckers.IsCharacter(ownerID): 810 logo = Icon(icon=None, parent=parent, pos=(0, 811 0, 812 size, 813 size), ignoreSize=True) 814 if size < 64: 815 fetchSize = 64 816 else: 817 fetchSize = size 818 sm.GetService('photo').GetPortrait(ownerID, fetchSize, logo) 819 elif idCheckers.IsCorporation(ownerID) or idCheckers.IsAlliance(ownerID) or idCheckers.IsFaction(ownerID): 820 GetLogoIcon(itemID=ownerID, parent=parent, pos=(0, 821 0, 822 size, 823 size), ignoreSize=True) 824 else: 825 raise RuntimeError('ownerID %d is not of an owner type!!' % ownerID)