reprocessingWnd.py (40292B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\reprocessing\ui\reprocessingWnd.py 2 from math import pi 3 import carbonui.const as uiconst 4 import evetypes 5 from carbonui.control.combo import Combo 6 from carbonui.primitives.flowcontainer import FlowContainer 7 import uthread 8 from menu import MenuLabel, MenuList 9 from carbon.common.script.util.format import FmtAmt 10 from carbonui.const import CENTER 11 from carbonui.control.scrollContainer import ScrollContainer 12 from carbonui.primitives.container import Container 13 from carbonui.primitives.containerAutoSize import ContainerAutoSize 14 from carbonui.primitives.fill import Fill 15 from carbonui.primitives.frame import Frame 16 from carbonui.primitives.gradientSprite import GradientSprite 17 from carbonui.primitives.layoutGrid import LayoutGrid 18 from carbonui.primitives.sprite import Sprite 19 from carbonui.uicore import uicore 20 from carbonui.util.color import Color 21 from dogma.const import attributeRefiningYieldMutator 22 from carbonui.control.button import Button 23 from eve.client.script.ui.control.eveIcon import Icon 24 from eve.client.script.ui.control.eveLabel import EveCaptionMedium, EveLabelMedium, EveLabelMediumBold, EveLabelSmallBold 25 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel 26 from carbonui.control.window import Window 27 from eve.client.script.ui.control.themeColored import GradientThemeColored 28 import eve.client.script.ui.shared.pointerTool.pointerToolConst as pConst 29 from eve.common.script.sys.eveCfg import GetActiveShip 30 from eve.common.script.util.eveFormat import FmtISKAndRound, FmtISK 31 from eveservices.menu import GetMenuService 32 from inventorycommon.const import flagCorpSAGsExcludingProjects, flagHangar, corpDivisionsByFlag 33 from localization import GetByLabel 34 from player_messaging.client.ui_message import prompt_player_fsd_dialog 35 from reprocessing.ui.const import STATE_REPROCESS, STATE_RESTRICTED, STATE_SUSPICIOUS, STATE_RANDOMIZED, TILE_SIZE, COL_YELLOW, COL_RED, COL_GREEN, COL_BLUE, COL_LIGHTBLUE 36 from reprocessing.ui.containerCreator import ContainerCreator, Containers 37 from reprocessing.ui.controller import Controller, NodesToItems 38 from reprocessing.ui.grouper import GetCategoryGrouper, GetGroupGrouper 39 from reprocessing.ui.inputGroups import InputGroups 40 from reprocessing.ui.inputItemAdder import InputItemAdder 41 from reprocessing.ui.itemContainers import InputItemContainerInterface, ItemContainerInterface 42 from reprocessing.ui.itemReprocessor import ItemReprocessor 43 from reprocessing.ui.outputItemAdder import OutputItemAdder, MaterialFetcher 44 from reprocessing.ui.quotes import Quotes 45 from reprocessing.ui.randomizedOutputContainer import RandomisedOutputContainer 46 from reprocessing.ui.reprocessingItemContainer import ReprocessingItemContainer 47 from reprocessing.ui.resultsContainer import ReprocessResultsContainer 48 from reprocessing.ui.states import States 49 from reprocessing.ui.tileplacer import TilePlacer 50 from reprocessing.ui.util import GetTypeSkillBonuses, GetAttributeSkillBonusFromTypeID, GetSpecialReprocessingSkillBonuses, GetScrapMetalReprocessingSkillBonuses 51 from reprocessing.ui.animation import FadeElementsInSequence 52 from reprocessing.util import TypeHasSpecialReprocessingSkillBonuses, CategoryHasSpecialReprocessingSkillBonuses 53 from uthread2 import start_tasklet 54 from utillib import KeyVal 55 56 class ReprocessingWnd(Window): 57 __guid__ = 'form.ReprocessingWnd' 58 default_width = 600 59 default_height = 400 60 default_minSize = (default_width, default_height) 61 default_windowID = 'reprocessingWindow' 62 default_descriptionLabelPath = 'Tooltips/StationServices/ReprocessingPlant_description' 63 default_captionLabelPath = 'UI/Station/ReprocessingPlant' 64 default_iconNum = 'res:/UI/Texture/WindowIcons/Reprocess.png' 65 66 def ApplyAttributes(self, attributes): 67 Window.ApplyAttributes(self, attributes) 68 self.preSelectedItems = attributes.selectedItems 69 self.outputPrice = 0 70 self.outputItemsCount = 0 71 mainCont = Container(name='mainCont', parent=self.sr.main, padding=uiconst.defaultPadding) 72 self.bottomContainer = bottomCont = Container(name='bottomCont', parent=mainCont, align=uiconst.TOBOTTOM, height=36) 73 reprocessingCont = Container(name='reprocessingCont', parent=mainCont, align=uiconst.TOALL) 74 inputCont = Container(name='inputCont', parent=reprocessingCont, align=uiconst.TOLEFT_PROP, width=0.48) 75 outputCont = Container(name='outputCont', parent=reprocessingCont, align=uiconst.TORIGHT_PROP, width=0.48) 76 self.inputInfoCont = ReprocessInputContainer(name='inputInfo', parent=inputCont, dropFunc=self.AddItemByDrag, removeFunc=self.RemoveItem) 77 self.outputInfoCont = ReprocessOutputContainer(name='outputInfo', parent=outputCont) 78 self.resultsInfoCont = ReprocessResultsContainer(name='resultsInfo', parent=outputCont) 79 self.loadingOverlay = Container(parent=self.inputInfoCont, idx=0) 80 Fill(bgParent=self.loadingOverlay, color=(0.0, 0.0, 0.0, 0.3)) 81 LoadingWheel(name='loadingWheel', parent=self.loadingOverlay, align=uiconst.CENTER, width=80, height=80, state=uiconst.UI_DISABLED) 82 self.loadingOverlay.opacity = 0.0 83 self.controller = CreateReprocessingWindowController(self, self.inputInfoCont, self.outputInfoCont, sm.GetService('invCache'), sm.GetService('reprocessing'), GetActiveShip) 84 self.inputInfoCont.captionLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/InputMaterials') 85 self.outputInfoCont.captionLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/PredictedOutputResults') 86 self.resultsInfoCont.captionLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/ActualOutputResults') 87 btnCont = Container(name='buttonCont', parent=bottomCont, align=uiconst.TOBOTTOM, height=36, idx=0, padding=(-4, 3, -4, -2)) 88 GradientThemeColored(bgParent=btnCont) 89 self.reprocessButton = Button(parent=btnCont, name='reprocessButton', uniqueUiName=pConst.UNIQUE_NAME_REPROCESS_BUTTON, label=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessButton'), func=self.ReprocessItems, align=uiconst.CENTERRIGHT, fixedheight=28, left=8) 90 left = self.reprocessButton.left + self.reprocessButton.width 91 self.totalIskCostLabel = EveLabelMedium(parent=btnCont, text='', align=uiconst.CENTERRIGHT, left=left + 8, color=COL_RED) 92 self.cancelButton = Button(parent=btnCont, label=GetByLabel('UI/Common/Buttons/Cancel'), func=self.Cancel, align=uiconst.CENTERLEFT, fixedheight=28, left=8) 93 self.DisableReprocessButton(disable=True) 94 self.ShowPredictedOutputsPanel() 95 if self.preSelectedItems: 96 start_tasklet(self.AddPreselectedItems, self.preSelectedItems) 97 98 def ShowInputLoading(self): 99 self.inputInfoCont.overlayCont.display = False 100 uicore.animations.FadeIn(self.loadingOverlay, endVal=1.0, duration=0.2) 101 102 def HideInputLoading(self): 103 uicore.animations.FadeOut(self.loadingOverlay, duration=0.2) 104 105 def DisableReprocessButton(self, disable): 106 if disable: 107 self.reprocessButton.Disable() 108 self.reprocessButton.hint = GetByLabel('UI/Reprocessing/ReprocessingWindow/NoReprocessableItems') 109 else: 110 self.reprocessButton.Enable() 111 self.reprocessButton.hint = '' 112 113 def AddPreselectedItems(self, items): 114 self.controller.AddItems(items) 115 if self.reprocessButton.disabled and self.controller.HasReprocessableOutput(): 116 self.DisableReprocessButton(disable=False) 117 118 def RemoveItem(self, itemID): 119 self.controller.RemoveItem(itemID) 120 if not self.controller.HasReprocessableOutput(): 121 self.DisableReprocessButton(True) 122 123 def AddItemByDrag(self, dragObj, nodes): 124 self.controller.AddItems(NodesToItems(nodes)) 125 if self.reprocessButton.disabled and self.controller.HasReprocessableOutput(): 126 self.DisableReprocessButton(disable=False) 127 self.cancelButton.SetLabel(GetByLabel('UI/Common/Buttons/Cancel')) 128 self.ShowPredictedOutputsPanel() 129 130 def Cancel(self, *args): 131 self.CloseByUser() 132 133 def GetOutputItems(self): 134 return [] 135 136 def ReprocessItems(self, *args): 137 reprocessed, remaining, outputByTypeID = self.controller.Reprocess(*self.outputInfoCont.outputCombo.GetValue()) 138 self.DisableReprocessButton(disable=True) 139 self.cancelButton.SetLabel(GetByLabel('UI/Common/Buttons/Cancel')) 140 for item in remaining: 141 self.RemoveItem(item.itemID) 142 143 self.inputInfoCont.FadeOutGroups() 144 self.outputInfoCont.FadeOutGroups() 145 self.controller.RemoveAllInputItems() 146 self.outputInfoCont.RemoveRandomizedOutputs() 147 if reprocessed: 148 self.outputInfoCont.overlayCont.display = True 149 self.ShowActualResultsPanel(outputByTypeID) 150 self.inputInfoCont.ShowDropHereHint() 151 152 def UpdateTotalIskCost(self, iskCost): 153 self.totalIskCostLabel.SetText(FmtISK(-iskCost)) 154 155 def Close(self, *args, **kwargs): 156 super(ReprocessingWnd, self).Close(*args, **kwargs) 157 if self.controller: 158 self.controller.Close() 159 160 def ShowPredictedOutputsPanel(self): 161 self.outputInfoCont.display = True 162 self.resultsInfoCont.display = False 163 164 def ShowActualResultsPanel(self, outputByTypeID): 165 self.outputInfoCont.display = False 166 self.resultsInfoCont.display = True 167 self.resultsInfoCont.SetResults(outputByTypeID) 168 169 170 class ReprocessingContainer(Container): 171 172 def ApplyAttributes(self, attributes): 173 Container.ApplyAttributes(self, attributes) 174 nameCont = Container(name='nameCont', parent=self, align=uiconst.TOTOP, height=18) 175 self.infoCont = Container(name='infoCont', parent=self, align=uiconst.TOBOTTOM, height=54, clipChildren=True) 176 self.groupContainers = {} 177 self.overlayCont = Container(name='overlayCont', parent=self, align=uiconst.TOALL) 178 self.CreateScrollContainer() 179 self.captionLabel = EveLabelMediumBold(parent=nameCont, left=6) 180 self.volumeLabel = EveLabelMedium(name='volumeLabel', parent=self.infoCont, align=uiconst.BOTTOMRIGHT, left=5, top=4) 181 self.totalPriceLabel = EveLabelMedium(name='totalPriceLabel', parent=self.infoCont, align=uiconst.BOTTOMRIGHT, left=5, top=20) 182 self.numItemsLabel = EveLabelMedium(name='numItemsLabel', parent=self.infoCont, align=uiconst.BOTTOMRIGHT, left=5, top=36) 183 184 def CreateScrollContainer(self): 185 self.scrollCont = ScrollContainer(parent=self, align=uiconst.TOALL, showUnderlay=True) 186 187 def UpdateSummaryLabels(self, outputPrice, numberOfItems, volume = None): 188 self.totalPriceLabel.text = GetByLabel('UI/Inventory/EstIskPrice', iskString=FmtISKAndRound(outputPrice, False)) 189 self.numItemsLabel.text = GetByLabel('UI/Inventory/NumItems', numItems=numberOfItems, numFilteredTxt='') 190 if volume is not None: 191 self.volumeLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/TotalVolume', volume=FmtAmt(volume, showFraction=2)) 192 self.totalPriceLabel.display = True 193 self.numItemsLabel.display = True 194 self.volumeLabel.display = True 195 196 def HideSummaryLabels(self): 197 self.totalPriceLabel.display = False 198 self.numItemsLabel.display = False 199 self.volumeLabel.display = False 200 201 def RemoveGroup(self, groupID): 202 group = self.groupContainers.pop(groupID) 203 group.Close() 204 205 def AddItem(self, groupID, ctrlID_item): 206 ctrlID, item = ctrlID_item 207 self.groupContainers[groupID].tilePlacer.AddItem(ctrlID, item) 208 self.overlayCont.display = False 209 210 211 class ReprocessInputContainer(ReprocessingContainer): 212 213 def ApplyAttributes(self, attributes): 214 ReprocessingContainer.ApplyAttributes(self, attributes) 215 self.removeFunc = attributes.removeFunc 216 self.scrollCont.name = 'inputScroll' 217 self.scrollCont.Copy = self.CopyInput 218 self.scrollCont.OnDropData = self.OnDroppingItems 219 self.parentDropFunc = attributes.dropFunc 220 self.volumeLabel.display = False 221 self.UpdateSummaryLabels(0, 0) 222 self.overlayCont.GetAbsoluteSize() 223 self.ShowDropHereHint() 224 225 def AddGroup(self, groupID, groupName): 226 self.groupContainers[groupID] = ReprocessingInputGroupContainer(parent=self.scrollCont, align=uiconst.TOTOP, percentage=0.5, groupID=groupID, groupName=groupName) 227 228 def AddItem(self, groupID, ctrlID_item): 229 ctrlID, item = ctrlID_item 230 self.scrollCont.HideNoContentHint() 231 ReprocessingContainer.AddItem(self, groupID, (ctrlID, item)) 232 item.OnDropData = self.OnDroppingItems 233 item.GetMenu = lambda *args: self.GetItemMenu(ctrlID, item.typeID) 234 self.groupContainers[groupID].tilePlacer.mainContainer.OnDropData = self.OnDroppingItems 235 236 def OnDroppingItems(self, dragObj, nodes): 237 if self.parentDropFunc: 238 self.parentDropFunc(dragObj, nodes) 239 240 def GetItemMenu(self, itemID, typeID): 241 menu = MenuList() 242 menu += GetMenuService().GetMenuFromItemIDTypeID(itemID, typeID, includeMarketDetails=True) 243 menu.append((GetByLabel('UI/Generic/RemoveItem'), self.removeFunc, (itemID,))) 244 return menu 245 246 def AnimateItems(self): 247 for group in self.groupContainers.itervalues(): 248 inputItems = group.tilePlacer.GetItems() 249 timeOffset = 0.2 / len(inputItems) 250 funcs = [ (self.GrayOutItem, (item,)) for item in inputItems ] 251 uthread.parallel(funcs) 252 for item in inputItems: 253 uicore.animations.FadeOut(item, duration=timeOffset, sleep=True) 254 255 for groupID, group in self.groupContainers.items(): 256 group.Close() 257 258 self.groupContainers = {} 259 260 def GrayOutItem(self, item): 261 animateCall = lambda cont: uicore.animations.MorphScalar(cont, attrName='saturation', startVal=1.0, endVal=0.0, duration=0.3, sleep=True) 262 uthread.parallel([(animateCall, (item.icon,)), (animateCall, (item.techIcon,))]) 263 264 def SetEfficiency(self, group, efficiency, typeIDs): 265 self.groupContainers[group].SetEfficiency(efficiency, typeIDs) 266 267 def SetTaxAndStationEfficiency(self, group, efficiency, tax): 268 self.groupContainers[group].SetTaxAndStationEfficiency(efficiency, tax) 269 270 def CopyInput(self): 271 allItems = [] 272 groupConts = self.groupContainers.values() 273 groupConts.sort(key=lambda x: x.GetOrder()) 274 for group in groupConts: 275 inputItems = group.tilePlacer.GetItems() 276 allItems += inputItems 277 278 CopyItemsToClipboard(allItems) 279 280 def FadeOutGroups(self): 281 FadeElementsInSequence(self.groupContainers.values(), 0.5, 1.0, 0.0, True) 282 283 def ShowDropHereHint(self): 284 self.scrollCont.ShowNoContentHint(GetByLabel('UI/Reprocessing/ReprocessingWindow/DropHereToReprocess')) 285 286 287 class ReprocessOutputContainer(ReprocessingContainer): 288 289 def ApplyAttributes(self, attributes): 290 ReprocessingContainer.ApplyAttributes(self, attributes) 291 self.scrollCont.name = 'outputScroll' 292 self.scrollCont.Copy = self.CopyOutput 293 self.volumeLabel.display = True 294 self.UpdateSummaryLabels(0, 0, 0) 295 self.overlayCont.display = False 296 w, h = self.overlayCont.GetAbsoluteSize() 297 overlayLabel = EveCaptionMedium(name='overlayLabel', parent=self.overlayCont, align=uiconst.CENTER) 298 overlayLabel.text = GetByLabel('UI/Reprocessing/ReprocessingWindow/OutputTransferredTo') 299 self.overlayLabel2 = EveLabelMediumBold(name='overlayLabel2', parent=self.overlayCont, align=uiconst.CENTER, top=20, state=uiconst.UI_NORMAL) 300 self.overlayLabel2.text = GetByLabel('UI/Inventory/ItemHangar') 301 self.overlayLabel2.OnClick = uicore.cmd.OpenInventory 302 self._CreateOutputCombo() 303 self.randomizedOutputContainers = {} 304 305 def _CreateOutputCombo(self): 306 hangarValue = (session.stationid or session.structureid, flagHangar) 307 sameLocationValue = (None, None) 308 comboOptions = [(GetByLabel('UI/Reprocessing/ReprocessingWindow/InputLocationComboBoxLabel'), 309 sameLocationValue, 310 None, 311 None, 312 0), (GetByLabel('UI/Inventory/ItemHangar'), 313 hangarValue, 314 None, 315 'res:/ui/Texture/WindowIcons/itemHangar.png', 316 0)] 317 office = sm.GetService('officeManager').GetCorpOfficeAtLocation() 318 if office: 319 officeLabel = GetByLabel('UI/Inventory/CorporationHangars') 320 officeIcon = 'res:/UI/Texture/WindowIcons/corporation.png' 321 comboOptions.append((officeLabel, 322 None, 323 None, 324 officeIcon, 325 0)) 326 divisions = sm.GetService('corp').GetDivisionNames() 327 for flagID in flagCorpSAGsExcludingProjects: 328 divID = corpDivisionsByFlag[flagID] 329 comboOptions.append((divisions[divID + 1], 330 (office.officeID, flagID), 331 None, 332 officeIcon, 333 1)) 334 335 outputLabel = EveLabelSmallBold(name='overlayLabel', parent=self.infoCont, align=uiconst.CENTERLEFT, top=-5) 336 outputLabel.text = GetByLabel('UI/Industry/OutputLocation') 337 self.outputCombo = Combo(parent=self.infoCont, align=uiconst.BOTTOMLEFT, callback=self.OnCombo, height=22, width=120) 338 self.outputCombo.LoadOptions(comboOptions, hangarValue) 339 self.outputCombo.last_selected = hangarValue 340 341 def OnCombo(self, comboBox, key, value): 342 if value is None: 343 comboBox.SelectItemByValue(comboBox.last_selected) 344 return 345 comboBox.last_selected = value 346 flag = value[1] 347 if not self.overlayCont.display: 348 if flag in corpDivisionsByFlag: 349 division = corpDivisionsByFlag[flag] + 1 350 self.overlayLabel2.text = '%s - %s' % (GetByLabel('UI/Inventory/CorporationHangars'), sm.GetService('corp').GetDivisionNames()[division]) 351 else: 352 self.overlayLabel2.text = key 353 354 def AddGroup(self, groupID, groupName): 355 self.groupContainers[groupID] = ReprocessingOutputGroupContainer(parent=self.scrollCont, align=uiconst.TOTOP, percentage=0.5, groupID=groupID, groupName=groupName) 356 357 def AddRandomizedOutput(self, quote): 358 if quote.typeID in self.randomizedOutputContainers: 359 c = self.randomizedOutputContainers[quote.typeID] 360 else: 361 c = RandomisedOutputContainer(parent=self.scrollCont, align=uiconst.TOTOP, percentage=0.5, inputTypeID=quote.typeID) 362 self.randomizedOutputContainers[quote.typeID] = c 363 c.AddOutputsFromQuote(quote) 364 365 def RemoveRandomizedOutputs(self): 366 for c in self.randomizedOutputContainers.itervalues(): 367 c.Close() 368 369 self.randomizedOutputContainers.clear() 370 371 def AddItem(self, groupID, ctrlID_item): 372 ctrlID, item = ctrlID_item 373 ReprocessingContainer.AddItem(self, groupID, (ctrlID, item)) 374 item.GetMenu = (self.GetItemMenu, ctrlID) 375 376 @staticmethod 377 def GetItemMenu(typeID): 378 m = [(MenuLabel('UI/Commands/ShowInfo'), sm.GetService('info').ShowInfo, (typeID,))] 379 if evetypes.GetMarketGroupID(typeID) is not None: 380 sm.GetService('marketutils').AddMarketDetailsMenuOption(m, typeID) 381 m.append((MenuLabel('UI/Inventory/ItemActions/AddTypeToMarketQuickbar'), sm.GetService('marketutils').AddTypeToQuickBar, (typeID,))) 382 return m 383 384 def GetItems(self): 385 items = [] 386 for group in self.groupContainers.itervalues(): 387 items.extend(group.tilePlacer.GetItems()) 388 389 return items 390 391 def FadeOutGroups(self): 392 allGroups = [] 393 allGroups.extend(self.groupContainers.itervalues()) 394 allGroups.extend(self.randomizedOutputContainers.itervalues()) 395 FadeElementsInSequence(allGroups, 0.5, 1.0, 0.0, True) 396 397 def ShowItems(self): 398 self.overlayCont.display = False 399 400 def CopyOutput(self): 401 CopyItemsToClipboard(self.GetItems()) 402 403 404 class ReprocessingInputItemContainer(ReprocessingItemContainer): 405 isDragObject = True 406 407 def ApplyAttributes(self, attributes): 408 ReprocessingItemContainer.ApplyAttributes(self, attributes) 409 self.getTypeAttribute = sm.GetService('clientDogmaStaticSvc').GetTypeAttribute 410 self.getSkillLevel = sm.GetService('skills').MySkillLevel 411 self.itemID = attributes.itemID 412 self.quantity = attributes.quantity 413 self.outputMaterials = attributes.outputMaterials 414 self.hintInfo = attributes.hintInfo 415 self.onMouseEnter = None 416 self.onMouseExit = None 417 bgSprite = Sprite(bgParent=self.spriteCont, name='background', texturePath='res:/UI/Texture/classes/InvItem/bgNormal.png') 418 419 def AddItem(self): 420 pass 421 422 def OnMouseEnter(self, *args): 423 if uicore.uilib.leftbtn: 424 return 425 if self.onMouseEnter is not None: 426 self.onMouseEnter() 427 428 def OnMouseExit(self, *args): 429 if self.onMouseExit is not None: 430 self.onMouseExit() 431 432 def RegisterForHoverEvents(self, itemID, onMouseEnter, onMouseExit): 433 self.onMouseEnter = lambda : onMouseEnter(itemID) 434 self.onMouseExit = lambda : onMouseExit(itemID) 435 436 def GetDragData(self): 437 return [KeyVal(itemID=self.itemID, __guid__='xtriui.TypeIcon', typeID=self.typeID, isReprocessingItem=True)] 438 439 def LoadTooltipPanel(self, tooltipPanel, *args): 440 typeID, reprocessingYield, stationTaxHint, itemYieldHint, stationEfficiency = self.hintInfo 441 tooltipPanel.LoadGeneric1ColumnTemplate() 442 rowSpan = 1 443 if self.itemState: 444 rowSpan = 2 445 subGrid1 = LayoutGrid() 446 icon = Icon(width=64, height=64, align=CENTER) 447 icon.LoadIconByTypeID(typeID=self.typeID, ignoreSize=True) 448 subGrid1.AddCell(icon, rowSpan=rowSpan) 449 yieldText = '<color=%s>%s%%</color>' % (Color.RGBtoHex(*COL_LIGHTBLUE), FmtAmt(reprocessingYield * 100.0, showFraction=1)) 450 topLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ItemYieldHint', itemName=evetypes.GetName(self.typeID), itemYield=yieldText), width=170, autoFitToText=True, left=6, top=4, bold=True) 451 subGrid1.AddCell(topLabel) 452 if self.itemState: 453 hintText = '' 454 hintColor = None 455 if self.itemState == STATE_REPROCESS: 456 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessedFurtherHint') 457 hintColor = COL_GREEN 458 elif self.itemState == STATE_RESTRICTED: 459 portionSize = evetypes.GetPortionSize(typeID) 460 if portionSize > self.quantity: 461 noOfItems = FmtAmt(portionSize, showFraction=0) 462 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/CannotReprocessHint', noOfItems=noOfItems) 463 else: 464 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/CannotReprocessNoValueHint') 465 hintColor = COL_RED 466 elif self.itemState == STATE_SUSPICIOUS: 467 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessingWarningHint') 468 hintColor = COL_YELLOW 469 elif self.itemState == STATE_RANDOMIZED: 470 hintText = GetByLabel('UI/Reprocessing/ReprocessingWindow/RandomizedOutputHint') 471 hintColor = COL_BLUE 472 stateHint = EveLabelMedium(text=hintText, width=170, autoFitToText=True, left=6, top=4, color=hintColor) 473 subGrid1.AddCell(stateHint) 474 tooltipPanel.AddCell(subGrid1) 475 subGrid = LayoutGrid() 476 subGrid.AddCell(cellPadding=6, colSpan=2) 477 subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/DetailedYieldHint'), color=COL_BLUE, bold=True), colSpan=2) 478 for label in GetTypeReprocessingModifiersAsLabels(typeID, stationEfficiency, self.getTypeAttribute, self.getSkillLevel): 479 subGrid.AddCell(label) 480 481 if itemYieldHint: 482 subGrid.AddCell(cellPadding=6, colSpan=2) 483 subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YouWillReceiveHint'), color=COL_BLUE, bold=True), colSpan=2) 484 for typeID, qty in itemYieldHint: 485 subGrid.AddCell(EveLabelMedium(text=FmtAmt(qty, showFraction=False), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_LIGHTBLUE, bold=True)) 486 subGrid.AddCell(EveLabelMedium(text='%s' % evetypes.GetName(typeID), colSpan=1, padLeft=3)) 487 488 tooltipPanel.AddCell(subGrid) 489 490 491 class ReprocessingOutputItemContainer(ReprocessingItemContainer): 492 493 def ApplyAttributes(self, attributes): 494 ReprocessingItemContainer.ApplyAttributes(self, attributes) 495 self.outputFrame = Frame(name='outputFrame', bgParent=self.spriteCont, texturePath='res:/UI/Texture/Reprocessing/Dash_Frame_48.png') 496 self.outputFrame.SetRGB(*COL_YELLOW) 497 qtyInfo = attributes.qtyInfo 498 typeInfo = attributes.fromTypeInfo 499 self._SetInfo(qtyInfo, typeInfo) 500 501 def LoadTooltipPanel(self, tooltipPanel, *args): 502 tooltipPanel.LoadGeneric1ColumnTemplate() 503 subGrid1 = LayoutGrid() 504 icon = Icon(width=64, height=64, align=CENTER) 505 icon.LoadIconByTypeID(typeID=self.typeID, ignoreSize=True) 506 subGrid1.AddCell(cellObject=icon) 507 subGrid1.AddCell(EveLabelMedium(text=evetypes.GetName(self.typeID), width=170, autoFitToText=True, left=6, top=4, bold=True)) 508 tooltipPanel.AddCell(subGrid1) 509 subGrid = LayoutGrid() 510 subGrid.columns = 2 511 l1 = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessedFrom'), color=COL_BLUE, bold=True) 512 subGrid.AddCell(l1, colSpan=2) 513 for typeID, quantity in self.typeInfo.iteritems(): 514 subGrid.AddCell(EveLabelMedium(text=FmtAmt(quantity, showFraction=0), align=uiconst.TORIGHT, padRight=3, color=COL_LIGHTBLUE, bold=True)) 515 subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessedFromType', typeName=evetypes.GetName(typeID)), padLeft=3)) 516 517 subGrid.AddCell(EveLabelMedium(text=FmtAmt(self.unrecoverableQty, showFraction=0), colSpan=1, align=uiconst.TORIGHT, padRight=2, color=COL_RED, bold=True)) 518 subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/NotRecoverableHint'), colSpan=1, padLeft=2)) 519 subGrid.AddCell(EveLabelMedium(text=FmtAmt(self.quantity, showFraction=0), colSpan=1, align=uiconst.TORIGHT, padRight=2, color=COL_GREEN, bold=True)) 520 subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/TotalOutputHint'), colSpan=1, padLeft=2)) 521 if self.iskCost: 522 subGrid.AddCell(EveLabelMedium(text=FmtAmt(self.iskCost, showFraction=0), colSpan=1, align=uiconst.TORIGHT, padRight=2, bold=True)) 523 subGrid.AddCell(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/IskPaidPerItem'), colSpan=1, padLeft=2)) 524 tooltipPanel.AddCell(subGrid) 525 526 def Update(self, qtyInfo, fromItemIDs, fromTypeInfo): 527 self._SetInfo(qtyInfo, fromTypeInfo) 528 529 def _SetInfo(self, qtyInfo, typeInfo): 530 self.quantity, self.iskCost, self.unrecoverableQty = qtyInfo 531 self.typeInfo = typeInfo 532 self._SetQtyText() 533 534 535 def AskToContinue(error): 536 buttons = uiconst.YESNO 537 default = uiconst.ID_YES 538 msg = cfg.GetMessage(error.msg, error.dict, onNotFound='return') 539 if msg.type not in ('warning', 'question'): 540 buttons = None 541 default = None 542 ret = prompt_player_fsd_dialog(error.msg, error.dict, buttons=buttons, default=default) 543 return ret == uiconst.ID_YES 544 545 546 def CreateOutputItemContainer(typeID, fromItemIDs, fromTypeInfo, qtyInfo, canBeReprocessed): 547 if canBeReprocessed: 548 itemState = STATE_REPROCESS 549 else: 550 itemState = None 551 return ReprocessingOutputItemContainer(align=uiconst.TOPLEFT, width=TILE_SIZE, height=TILE_SIZE, typeID=typeID, qtyInfo=qtyInfo, itemID=0, fromTypeInfo=fromTypeInfo, itemState=itemState) 552 553 554 def CreateInputItemContainer(item, hintInfo, itemState): 555 return ReprocessingInputItemContainer(align=uiconst.TOPLEFT, width=TILE_SIZE, height=TILE_SIZE, typeID=item.typeID, quantity=item.quantity, itemID=item.itemID, categoryID=item.categoryID, hintInfo=hintInfo, itemState=itemState, singleton=item.singleton, stacksize=item.stacksize) 556 557 558 class ReprocessingInputGroupContainer(ContainerAutoSize): 559 560 def ApplyAttributes(self, attributes): 561 Container.ApplyAttributes(self, attributes) 562 self.header = ReprocessingInputHeaderContainer(parent=self, align=uiconst.TOTOP, height=24, percentage=0.0, groupID=attributes.groupID, groupName=attributes.groupName) 563 tileContainer = FlowContainer(parent=self, align=uiconst.TOTOP, state=uiconst.UI_NORMAL, contentSpacing=(8, 8), padding=8) 564 self.tilePlacer = TilePlacer(tileContainer) 565 566 def SetEfficiency(self, efficiency, typeIDs): 567 self.header.UpdateGauge(efficiency) 568 self.header.UpdateSkills(typeIDs) 569 570 def SetTaxAndStationEfficiency(self, efficiency, tax): 571 self.header.stationEfficiency = efficiency 572 self.header.stationTax = tax 573 574 575 class ReprocessingOutputGroupContainer(ContainerAutoSize): 576 577 def ApplyAttributes(self, attributes): 578 Container.ApplyAttributes(self, attributes) 579 self.header = ReprocessingHeaderContainer(parent=self, align=uiconst.TOTOP, height=24, percentage=0.0, groupID=attributes.groupID, groupName=attributes.groupName) 580 tileContainer = FlowContainer(parent=self, align=uiconst.TOTOP, contentSpacing=(8, 8), padding=8) 581 self.tilePlacer = TilePlacer(tileContainer) 582 583 def UpdateInfo(self, typeID, qtyInfo, fromItemIDs, fromTypeInfo): 584 tile = self.tilePlacer.GetItem(typeID) 585 tile.Update(qtyInfo, fromItemIDs, fromTypeInfo) 586 587 588 class ReprocessingHeaderContainer(Container): 589 default_align = uiconst.TOTOP 590 default_height = 24 591 592 def ApplyAttributes(self, attributes): 593 Container.ApplyAttributes(self, attributes) 594 self.groupID = attributes.groupID 595 self.groupName = attributes.groupName 596 Fill(bgParent=self, color=(0.0, 0.0, 0.0, 0.5)) 597 leftCont = Container(parent=self, align=uiconst.TOALL) 598 self.headerText = EveLabelMedium(text=self.groupName, parent=leftCont, left=2, maxLines=1, align=uiconst.CENTERLEFT, padLeft=4) 599 600 601 class ReprocessingInputHeaderContainer(ReprocessingHeaderContainer): 602 603 def ApplyAttributes(self, attributes): 604 ReprocessingHeaderContainer.ApplyAttributes(self, attributes) 605 self.percentage = attributes.percentage 606 self.avgBonus = 0 607 self.state = uiconst.UI_NORMAL 608 self.groupHilite = Fill(bgParent=self, color=(0.4, 0.4, 0.4, 0.1), opacity=0.0) 609 self.getTypeAttribute = sm.GetService('clientDogmaStaticSvc').GetTypeAttribute 610 self.getSkillLevel = sm.GetService('skills').MySkillLevel 611 self.stationTax = attributes.tax 612 self.stationEfficiency = attributes.efficiency 613 if self._ShouldShowEfficiencyGauge(): 614 rightCont = Container(parent=self, align=uiconst.TORIGHT, width=100) 615 Sprite(parent=rightCont, width=24, height=24, ignoreSize=True, align=uiconst.TOLEFT, texturePath='res:/UI/Texture/Reprocessing/Reprocess.png') 616 self.gaugeParent = Container(name='gaugeParent', parent=rightCont, align=uiconst.TOALL, padding=(0, 5, 2, 4), state=uiconst.UI_NORMAL) 617 self.gaugeParent.LoadTooltipPanel = self.LoadGaugeTooltipPanel 618 self.gaugeLabel = EveLabelSmallBold(parent=self.gaugeParent, align=uiconst.CENTER) 619 Frame(parent=self.gaugeParent, color=(0.5, 0.5, 0.5, 0.05)) 620 Fill(bgParent=self.gaugeParent, color=(0.0, 0.0, 0.0, 0.8)) 621 self.reprocessingGauge = GradientSprite(parent=self.gaugeParent, align=uiconst.TOLEFT_PROP, rotation=-pi / 2, rgbData=[(0, COL_YELLOW)], alphaData=[(0, 0.6), (0.5, 0.4), (1.0, 0.6)], state=uiconst.UI_DISABLED) 622 self.UpdateGauge(self.percentage) 623 624 def _ShouldShowEfficiencyGauge(self): 625 return CategoryHasSpecialReprocessingSkillBonuses(self.groupID) 626 627 def UpdateGauge(self, percentage): 628 if not self._ShouldShowEfficiencyGauge(): 629 return 630 self.reprocessingGauge.width = percentage 631 self.percentage = percentage 632 self.gaugeLabel.text = GetByLabel('UI/Common/Formatting/PercentageDecimal', percentage=percentage * 100.0) 633 634 def UpdateSkills(self, typeIDs): 635 skillBonuses = [] 636 for groupID, typeIDs in typeIDs.iteritems(): 637 for typeID in typeIDs: 638 _, bonus = GetAttributeSkillBonusFromTypeID(typeID, self.getTypeAttribute, self.getSkillLevel) 639 skillBonuses.append(bonus) 640 641 bonusAmt = sum(skillBonuses) 642 self.avgBonus = bonusAmt / len(typeIDs) 643 644 def LoadGaugeTooltipPanel(self, tooltipPanel, *args): 645 tooltipPanel.LoadGeneric1ColumnTemplate() 646 subGrid1 = LayoutGrid() 647 icon = Sprite(width=64, height=64, ignoreSize=True, align=CENTER, texturePath='res:/UI/Texture/Reprocessing/Reprocess.png') 648 subGrid1.AddCell(icon) 649 itemName = self.groupName 650 yieldText = '<color=%s>%s%%</color>' % (Color.RGBtoHex(*COL_LIGHTBLUE), FmtAmt(self.percentage * 100.0, showFraction=1)) 651 topLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ItemYieldHint', itemName=itemName, itemYield=yieldText), width=170, autoFitToText=True, left=6, top=4, bold=True) 652 subGrid1.AddCell(topLabel) 653 tooltipPanel.AddCell(subGrid1) 654 subGrid = LayoutGrid() 655 l1 = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/ReprocessingCalculations'), color=COL_BLUE, bold=True) 656 subGrid.AddCell(l1, colSpan=2) 657 for label in GetCategoryReprocessingModifiersAsLabels(self.groupID, self.stationEfficiency, self.getTypeAttribute, self.getSkillLevel, self.avgBonus): 658 subGrid.AddCell(label) 659 660 tooltipPanel.AddCell(subGrid) 661 662 def OnMouseEnter(self, *args): 663 uicore.animations.FadeIn(self.groupHilite, duration=0.4, endVal=0.25) 664 665 def OnMouseExit(self, *args): 666 uicore.animations.FadeOut(self.groupHilite, duration=0.4) 667 668 669 def CreateReprocessingWindowController(wnd, inputInfoCont, outputInfoCont, invCache, reprocessing, GetActiveShip): 670 quotes = Quotes(reprocessing) 671 materialFetcher = MaterialFetcher(quotes) 672 inputItemContainer = inputInfoCont 673 inputItemContainer = InputItemContainerInterface(inputItemContainer) 674 outputItemContainer = outputInfoCont 675 outputItemContainer = ItemContainerInterface(outputItemContainer) 676 inputGrouper = GetCategoryGrouper() 677 inputGroups = InputGroups(inputItemContainer, inputGrouper) 678 containerCreator = ContainerCreator(Containers(CreateInputItemContainer), Containers(CreateOutputItemContainer), quotes) 679 inputItemAdder = InputItemAdder(inputItemContainer, containerCreator, quotes, States(quotes), inputGrouper, GetActiveShip) 680 outputItemAdder = OutputItemAdder(materialFetcher, outputItemContainer, containerCreator, GetGroupGrouper(), quotes) 681 reprocessor = ItemReprocessor(reprocessing, invCache, AskToContinue) 682 controller = Controller(wnd, inputItemAdder, inputGroups, quotes, outputItemAdder, reprocessor, GetActiveShip) 683 sm.RegisterNotify(controller) 684 return controller 685 686 687 def GetTypeReprocessingModifiersAsLabels(typeID, stationEfficiency, getTypeAttribute, getSkillLevel): 688 labelList = [] 689 labelList.extend(GetStationEfficiencyAsLabel(stationEfficiency)) 690 labelList.extend(GetTypeSkillBonusesAsLabels(typeID, getTypeAttribute, getSkillLevel)) 691 if TypeHasSpecialReprocessingSkillBonuses(typeID): 692 labelList.extend(GetImplantModifiersAsLabels(getTypeAttribute)) 693 return labelList 694 695 696 def GetCategoryReprocessingModifiersAsLabels(categoryID, stationEfficiency, getTypeAttribute, getSkillLevel, avgBonus): 697 labelList = [] 698 labelList.extend(GetStationEfficiencyAsLabel(stationEfficiency)) 699 if CategoryHasSpecialReprocessingSkillBonuses(categoryID): 700 labelList.extend(GetOreAvgBonusAsLabel(avgBonus)) 701 skillBonuses = GetSpecialReprocessingSkillBonuses(getTypeAttribute, getSkillLevel) 702 labelList.extend(_CreateSkillBonusLabelsFromSkillBonuses(skillBonuses)) 703 labelList.extend(GetImplantModifiersAsLabels(getTypeAttribute)) 704 else: 705 skillBonuses = GetScrapMetalReprocessingSkillBonuses(getTypeAttribute, getSkillLevel) 706 labelList.extend(_CreateSkillBonusLabelsFromSkillBonuses(skillBonuses)) 707 return labelList 708 709 710 def GetStationEfficiencyAsLabel(stationEfficiency): 711 stationBonusLabel = EveLabelMedium(text=GetByLabel('UI/Common/Formatting/Percentage', percentage=stationEfficiency * 100), colSpan=1, align=uiconst.TORIGHT, padRight=2, color=COL_LIGHTBLUE, bold=True) 712 stationTextLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/BaseYield'), colSpan=1, padLeft=2) 713 return (stationBonusLabel, stationTextLabel) 714 715 716 def GetOreAvgBonusAsLabel(avgBonus): 717 labelOpacity = 0.35 718 if avgBonus > 0: 719 labelOpacity = 1.0 720 oreAvgBonusLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 + avgBonus / 100), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_GREEN, bold=True, opacity=labelOpacity) 721 oreAvgTextLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/OreProcessingHint'), colSpan=1, padLeft=3, opacity=labelOpacity) 722 return (oreAvgBonusLabel, oreAvgTextLabel) 723 724 725 def GetTypeSkillBonusesAsLabels(typeID, getTypeAttribute, getSkillLevel): 726 skillBonuses = GetTypeSkillBonuses(typeID, getTypeAttribute, getSkillLevel) 727 skillLabels = _CreateSkillBonusLabelsFromSkillBonuses(skillBonuses) 728 return skillLabels 729 730 731 def _CreateSkillBonusLabelsFromSkillBonuses(skillBonuses): 732 skillLabels = [] 733 for skillType, bonus in skillBonuses: 734 skillName = evetypes.GetName(skillType) 735 labelOpacity = 0.35 736 if bonus > 0: 737 labelOpacity = 1.0 738 skillLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 + bonus / 100), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_GREEN, bold=True, opacity=labelOpacity)) 739 skillLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/BonusFromSkill', skillName=skillName), colSpan=1, padLeft=3, opacity=labelOpacity)) 740 741 return skillLabels 742 743 744 def GetImplantModifiersAsLabels(getTypeAttribute): 745 implantLabels = [] 746 implants = sm.GetService('godma').GetItem(session.charid).implants 747 for implant in implants: 748 implantBonus = getTypeAttribute(implant.typeID, attributeRefiningYieldMutator) 749 if implantBonus > 0.0: 750 implantLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 + implantBonus / 100), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_GREEN, bold=True)) 751 implantLabels.append(EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/BonusFromSkill', skillName=evetypes.GetName(implant.typeID)), colSpan=1, padLeft=3)) 752 753 return implantLabels 754 755 756 def GetStationTaxAsLabel(stationTax): 757 taxBonusLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/YieldFormatting', bonusYield=1.0 - stationTax), colSpan=1, align=uiconst.TORIGHT, padRight=3, color=COL_RED, bold=True) 758 taxTextLabel = EveLabelMedium(text=GetByLabel('UI/Reprocessing/ReprocessingWindow/StationTaxHint'), colSpan=1, padLeft=3) 759 return (taxBonusLabel, taxTextLabel) 760 761 762 def CopyItemsToClipboard(items): 763 textLine = [] 764 for item in items: 765 t = '%s\t%s' % (evetypes.GetName(item.typeID), abs(item.quantity)) 766 textLine.append(t) 767 768 text = '\n'.join(textLine) 769 from carbon.common.script.util.commonutils import StripTags 770 strippedText = StripTags(text) 771 if strippedText: 772 import blue 773 blue.pyos.SetClipboardData(strippedText)