blueprintCenter.py (21073B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\industry\views\blueprintCenter.py 2 from math import pi 3 from carbon.client.script.environment.AudioUtil import PlaySound 4 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger 5 from carbonui.primitives.frame import Frame 6 from carbonui.primitives.transform import Transform 7 from eve.client.script.ui.control.themeColored import FrameThemeColored 8 from eve.client.script.ui.shared.industry import industryUIConst 9 from eve.client.script.ui.shared.industry.views.errorFrame import ErrorFrame 10 import industry 11 import localization 12 import uthread 13 import blue 14 import carbonui.const as uiconst 15 from carbonui.primitives.container import Container 16 from carbonui.primitives.containerAutoSize import ContainerAutoSize 17 from carbonui.primitives.sprite import Sprite 18 from carbonui.util.color import Color 19 from localization import GetByLabel 20 from carbon.common.script.sys.service import ROLE_PROGRAMMER 21 from eve.client.script.ui.control.itemIcon import ItemIcon 22 from eve.client.script.ui.control.eveLabel import EveLabelMedium 23 from eve.client.script.ui.control.gaugeCircular import GaugeCircular 24 from eve.client.script.ui.shared.industry.industryUIConst import GetJobColor, COLOR_FRAME 25 from eve.client.script.ui.shared.industry.views.containersMETE import ContainerME, ContainerTE 26 from eve.client.script.ui.shared.industry.views.industryCaptionLabel import IndustryCaptionLabel 27 from eve.client.script.ui.shared.industry.views.skillIcon import SkillIcon 28 from carbonui.uicore import uicore 29 from eveservices.menu import GetMenuService 30 WEDGE_TRAVEL = 15 31 32 class BlueprintCenter(Container): 33 __notifyevents__ = ('OnIndustryWndMouseWheel', 'OnIndustryWndClick', 'OnBlueprintBrowserNumericInput') 34 35 def ApplyAttributes(self, attributes): 36 Container.ApplyAttributes(self, attributes) 37 sm.RegisterNotify(self) 38 self.jobData = attributes.jobData 39 self.newNumRuns = None 40 self.setJobRunsThread = None 41 self.oldJobData = None 42 self.numericInputTimer = None 43 self.iconCont = BlueprintItemIcon(parent=self, align=uiconst.CENTER, state=uiconst.UI_NORMAL, pos=(0, 0, 64, 64), opacity=0.0, jobData=self.jobData) 44 self.errorFrame = ErrorFrame(parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, width=80, height=80) 45 self.ConstructBackground() 46 self.ConstructRunsCont() 47 self.gauge = None 48 self.skillSprite = SkillIcon(parent=self, align=uiconst.CENTERBOTTOM, top=5, jobData=self.jobData) 49 self.containerME = ContainerME(parent=self, align=uiconst.CENTER, pos=(113, -25, 79, 30), jobData=self.jobData, opacity=0.0) 50 self.containerTE = ContainerTE(parent=self, align=uiconst.CENTER, pos=(113, 25, 79, 30), jobData=self.jobData, opacity=0.0) 51 self.runsRemainingCont = ContainerAutoSize(name='bpCopyCont', parent=self, align=uiconst.CENTERTOP, state=uiconst.UI_NORMAL, top=90) 52 self.runsRemainingCont.OnClick = self.OnRunsRemainingContClicked 53 self.runsRemainingCaption = IndustryCaptionLabel(parent=self.runsRemainingCont, align=uiconst.CENTERTOP) 54 self.runsRemainingLabel = EveLabelMedium(name='runsRemainingLabel', parent=self.runsRemainingCont, align=uiconst.CENTERTOP, top=14) 55 self.UpdateState() 56 self.AnimEntry() 57 58 def ConstructRunsCont(self): 59 self.runsCont = ContainerAutoSize(parent=self, align=uiconst.CENTER, top=100, width=76) 60 labelCont = ContainerAutoSize(parent=self.runsCont, align=uiconst.TOTOP) 61 self.runsCaption = IndustryCaptionLabel(name='runsCaption', parent=labelCont, align=uiconst.CENTER, text=GetByLabel('UI/Industry/JobRuns')) 62 self.runsEdit = BlueprintSingleLineEdit(parent=self.runsCont, align=uiconst.TOTOP, OnChange=self.OnRunsEdit, autoselect=True) 63 self.runsPerCopyCont = ContainerAutoSize(name='runsPerCopyCont', parent=self.runsCont, align=uiconst.TOTOP, padTop=8, state=uiconst.UI_HIDDEN) 64 labelCont = ContainerAutoSize(parent=self.runsPerCopyCont, align=uiconst.TOTOP) 65 IndustryCaptionLabel(name='runsPerCopyCaption', parent=labelCont, align=uiconst.CENTER, text=GetByLabel('UI/Industry/RunsPerCopy')) 66 self.runsPerCopyEdit = BlueprintSingleLineEdit(parent=self.runsPerCopyCont, align=uiconst.TOTOP, OnChange=self.OnRunsPerCopyEdit, autoselect=True) 67 68 def OnRunsRemainingContClicked(self, *args): 69 if self.runsEdit.state == uiconst.UI_NORMAL: 70 self.runsEdit.SetValue(self.jobData.maxRuns) 71 72 def OnBlueprintBrowserNumericInput(self, key, flag): 73 if not self.numericInputTimer: 74 self.runsEdit.SelectAll() 75 else: 76 self.numericInputTimer.kill() 77 self.numericInputTimer = uthread.new(self.NumericInputTimer) 78 self.runsEdit.OnChar(key, flag) 79 80 def NumericInputTimer(self): 81 blue.synchro.SleepWallclock(1000) 82 self.numericInputTimer = None 83 84 def OnJobUpdated(self, job): 85 if self.jobData and self.jobData == job: 86 self.UpdateStateJob() 87 88 def UpdateStateJob(self): 89 self.iconCont.Show() 90 typeID = self.jobData.blueprint.blueprintTypeID 91 self.iconCont.SetTypeID(typeID=typeID, bpData=self.jobData.blueprint) 92 self.UpdateGaugeValue() 93 self.UpdateStateRunsEdit() 94 self.UpdateStateRunsPerCopyEdit() 95 self.skillSprite.Show() 96 self.UpdateRunsRemainingLabel() 97 self.containerME.SetValue(self.jobData.blueprint.materialEfficiency) 98 self.containerTE.SetValue(self.jobData.blueprint.timeEfficiency) 99 self.jobData.on_updated.connect(self.OnJobUpdated) 100 activity = self.jobData.GetCurrentActivity() 101 if activity and activity.IsOmegaActivity(): 102 self.iconCont.ShowOmegaOverlay() 103 else: 104 self.iconCont.HideOmegaOverlay() 105 sm.ScatterEvent('OnSelectedIndustryJobChanged', jobData=self.jobData) 106 107 def UpdateRunsRemainingLabel(self): 108 if not self.jobData: 109 return 110 if self.jobData.IsInstalled(): 111 self.runsRemainingCont.Hide() 112 else: 113 runsText = self.jobData.GetRunsRemainingLabel() 114 if runsText: 115 self.runsRemainingCont.Show() 116 self.runsRemainingLabel.text = runsText 117 self.runsRemainingCaption.text = self.jobData.GetRunsRemainingCaption() 118 else: 119 self.runsRemainingCont.Hide() 120 121 def SetNumRuns(self, numRuns): 122 if not self.jobData.IsInstalled(): 123 self.runsEdit.SetValue(numRuns) 124 125 def UpdateStateRunsEdit(self): 126 if self.jobData.IsInstalled(): 127 self.runsEdit.SetMinValue(self.jobData.runs) 128 self.runsEdit.SetMaxValue(self.jobData.runs) 129 self.runsEdit.Show() 130 self.runsCaption.Show() 131 self.runsEdit.Disable() 132 else: 133 self.runsEdit.SetMinValue(1) 134 self.runsEdit.SetMaxValue(self.jobData.maxRuns) 135 self.runsEdit.Enable() 136 self.runsEdit.Show() 137 self.runsCaption.Show() 138 self.runsEdit.SetValue(self.jobData.runs) 139 140 def UpdateStateRunsPerCopyEdit(self): 141 if self.jobData.activityID == industry.COPYING: 142 if self.jobData.IsInstalled(): 143 self.runsPerCopyEdit.SetMinValue(self.jobData.licensedRuns) 144 self.runsPerCopyEdit.SetMaxValue(self.jobData.licensedRuns) 145 self.runsPerCopyEdit.Disable() 146 else: 147 self.runsPerCopyEdit.SetMinValue(1) 148 self.runsPerCopyEdit.SetMaxValue(self.jobData.maxLicensedRuns) 149 self.runsPerCopyEdit.Enable() 150 self.runsPerCopyEdit.SetValue(self.jobData.licensedRuns) 151 self.runsPerCopyCont.Show() 152 else: 153 self.runsPerCopyCont.Hide() 154 155 def UpdateState(self): 156 if self.jobData: 157 self.UpdateStateJob() 158 else: 159 self.iconCont.Hide() 160 self.runsEdit.Hide() 161 self.runsPerCopyCont.Hide() 162 self.runsCaption.Hide() 163 self.skillSprite.Hide() 164 self.runsRemainingCont.Hide() 165 self.containerME.SetValue(0.0) 166 self.containerTE.SetValue(0.0) 167 168 def ReconstructGauge(self): 169 if self.gauge: 170 self.gauge.Close() 171 self.gauge = None 172 if not self.jobData: 173 return 174 color = GetJobColor(self.jobData) 175 h, s, b = Color(*color).GetHSB() 176 colorEnd = Color(*color).SetBrightness(b * 0.5).GetRGBA() 177 self.gauge = BlueprintGaugeCircular(name='gauge', parent=self, align=uiconst.CENTER, radius=64, lineWidth=4, colorStart=color, colorEnd=colorEnd, jobData=self.jobData) 178 179 def AnimWedges(self, startVal, endVal, duration, curveType = None): 180 uicore.animations.MorphScalar(self.topWedge, 'top', startVal, endVal, duration=duration, curveType=curveType) 181 uicore.animations.MorphScalar(self.bottomWedge, 'top', startVal, endVal, duration=duration, curveType=curveType) 182 uicore.animations.MorphScalar(self.leftWedge, 'left', startVal, endVal, duration=duration, curveType=curveType) 183 uicore.animations.MorphScalar(self.rightWedge, 'left', startVal, endVal, duration=duration, curveType=curveType) 184 185 def AnimEntry(self): 186 duration = 0.7 187 if self.jobData: 188 self.HideDashes() 189 if self.topWedge.top < WEDGE_TRAVEL: 190 self.AnimWedges(0, WEDGE_TRAVEL, duration) 191 else: 192 self.AnimWedges(WEDGE_TRAVEL, 18, 0.5, curveType=uiconst.ANIM_WAVE) 193 if not self.IsSameBlueprint(): 194 uicore.animations.FadeTo(self.iconCont, 0.0, 1.0, duration=0.5) 195 for obj in (self.containerME, self.containerTE): 196 obj.Enable() 197 uicore.animations.FadeIn(obj, duration=duration) 198 199 else: 200 self.AnimWedges(self.topWedge.top, 0.0, duration) 201 for obj in (self.containerME, self.containerTE): 202 obj.Disable() 203 uicore.animations.FadeOut(obj, duration=duration) 204 205 self.ShowDashes() 206 if self.jobData and self.jobData.IsPreview(): 207 uicore.animations.FadeTo(self.iconCont, 0.0, 0.65, duration=0.5) 208 self.errorFrame.Show() 209 wedgeColor = industryUIConst.COLOR_NOTREADY 210 else: 211 self.errorFrame.Hide() 212 wedgeColor = Color.WHITE 213 for dots in self.wedgeDots: 214 dots.SetRGBA(*wedgeColor) 215 216 if self.gauge: 217 uicore.animations.BlinkIn(self.gauge, 0.0, 1.0, timeOffset=0.98) 218 for dots in self.wedgeDots: 219 uicore.animations.BlinkIn(dots, 0.0, 0.85, timeOffset=0.78) 220 221 for pattern in self.wedgeBg: 222 if self.jobData and self.jobData.IsPreview(): 223 color = industryUIConst.COLOR_NOTREADY 224 else: 225 color = GetJobColor(self.jobData) 226 uicore.animations.SpColorMorphTo(pattern, pattern.GetRGBA(), color, duration=0.3) 227 228 def IsSameBlueprint(self): 229 if not self.oldJobData or not self.jobData: 230 return False 231 if self.jobData: 232 return self.jobData.blueprint.IsSameBlueprint(self.oldJobData.blueprint) 233 return False 234 235 def UpdateGaugeValue(self): 236 if not self.gauge or not self.jobData: 237 return 238 self.gauge.SetValue(self.jobData.GetGaugeValue()) 239 240 def SetJobRuns(self, value): 241 if not self.jobData: 242 return 243 if self.jobData.runs == value: 244 if self.newNumRuns is None or self.newNumRuns == value: 245 return 246 self.newNumRuns = value 247 if self.setJobRunsThread is None: 248 self.setJobRunsThread = uthread.new(self._SetJobRuns) 249 250 def _SetJobRuns(self): 251 while self.jobData and self.newNumRuns is not None and not self.destroyed: 252 if self.newNumRuns != self.jobData.runs: 253 newNumRuns = self.newNumRuns 254 self.newNumRuns = None 255 self.jobData.runs = newNumRuns 256 blue.synchro.SleepWallclock(100) 257 258 if self.jobData: 259 self.jobData.on_facility(self.jobData) 260 self.setJobRunsThread = None 261 262 def OnRunsEdit(self, value): 263 try: 264 value = int(value) 265 except ValueError: 266 return 267 268 if self.jobData and not self.jobData.IsInstalled(): 269 self.SetJobRuns(value) 270 271 def OnRunsChanged(self): 272 self.UpdateGaugeValue() 273 self.UpdateRunsRemainingLabel() 274 275 def OnRunsPerCopyEdit(self, value): 276 try: 277 value = int(value) 278 except ValueError: 279 return 280 281 self.jobData.licensedRuns = value 282 283 def ConstructBackground(self): 284 Frame(name='bgFrame', parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, width=75, height=75, opacity=0.1) 285 blueprintBg = FrameThemeColored(name='blueprintBgFill', parent=self, align=uiconst.CENTER, state=uiconst.UI_DISABLED, texturePath='res:/UI/Texture/classes/Industry/Center/bgFrame.png', width=90, height=90) 286 self.dashesCont = Container(name='dashesCont', parent=self, state=uiconst.UI_DISABLED, pos=(75, 0, 150, 150), align=uiconst.CENTER) 287 self.bgCont = Container(name='bgCont', parent=self, state=uiconst.UI_DISABLED, width=150, height=150, align=uiconst.CENTER) 288 self.topWedge = Container(name='topWedge', parent=self.bgCont, align=uiconst.CENTERTOP, pos=(0, 0, 84, 60)) 289 topLines = Sprite(bgParent=self.topWedge, texturePath='res:/UI/Texture/classes/Industry/Center/wedgeTopBottom.png') 290 topDots = Sprite(bgParent=self.topWedge, texturePath='res:/UI/Texture/classes/Industry/Center/dotsTopBottom.png') 291 topBg = Sprite(bgParent=self.topWedge, texturePath='res:/UI/Texture/classes/Industry/Center/bgTop.png', color=COLOR_FRAME) 292 self.bottomWedge = Container(name='bottomWedge', parent=self.bgCont, align=uiconst.CENTERBOTTOM, pos=(0, 0, 84, 60)) 293 bottomLines = Sprite(bgParent=self.bottomWedge, texturePath='res:/UI/Texture/classes/Industry/Center/wedgeTopBottom.png', rotation=pi) 294 bottomDots = Sprite(bgParent=self.bottomWedge, texturePath='res:/UI/Texture/classes/Industry/Center/dotsTopBottom.png', rotation=pi) 295 bottomBg = Sprite(bgParent=self.bottomWedge, texturePath='res:/UI/Texture/classes/Industry/Center/bgBottom.png', color=COLOR_FRAME) 296 self.leftWedge = Container(name='leftWedge', parent=self.bgCont, align=uiconst.CENTERLEFT, pos=(0, 0, 60, 84)) 297 leftLines = Sprite(bgParent=self.leftWedge, texturePath='res:/UI/Texture/classes/Industry/Center/wedgeLeftRight.png') 298 leftDots = Sprite(bgParent=self.leftWedge, texturePath='res:/UI/Texture/classes/Industry/Center/dotsLeftRight.png') 299 leftBg = Sprite(bgParent=self.leftWedge, texturePath='res:/UI/Texture/classes/Industry/Center/bgLeft.png', color=COLOR_FRAME) 300 self.rightWedge = Container(name='rightWedge', parent=self.bgCont, align=uiconst.CENTERRIGHT, pos=(0, 0, 60, 84)) 301 rightLines = Sprite(bgParent=self.rightWedge, texturePath='res:/UI/Texture/classes/Industry/Center/wedgeLeftRight.png', rotation=pi) 302 rightDots = Sprite(bgParent=self.rightWedge, texturePath='res:/UI/Texture/classes/Industry/Center/dotsLeftRight.png', rotation=pi) 303 rightBg = Sprite(bgParent=self.rightWedge, texturePath='res:/UI/Texture/classes/Industry/Center/bgRight.png', color=COLOR_FRAME) 304 self.wedgeLines = [topLines, 305 bottomLines, 306 leftLines, 307 rightLines] 308 self.wedgeDots = [topDots, 309 bottomDots, 310 leftDots, 311 rightDots] 312 self.wedgeBg = [topBg, 313 bottomBg, 314 leftBg, 315 rightBg] 316 317 def ShowDashes(self): 318 for rotation in (0, 319 pi / 2, 320 pi, 321 3 * pi / 2): 322 BlueDash(parent=self.dashesCont, align=uiconst.CENTERLEFT, rotation=pi / 4 + rotation, rotationCenter=(0.0, 0.5)) 323 324 def HideDashes(self): 325 self.dashesCont.Flush() 326 327 def OnNewJobData(self, jobData): 328 self.oldJobData = self.jobData 329 self.jobData = jobData 330 self.skillSprite.OnNewJobData(jobData) 331 self.containerME.OnNewJobData(jobData) 332 self.containerTE.OnNewJobData(jobData) 333 self.iconCont.OnNewJobData(jobData) 334 self.ReconstructGauge() 335 if self.gauge: 336 self.gauge.OnNewJobData(jobData) 337 self.UpdateState() 338 self.AnimEntry() 339 self.numericInputTimer = None 340 341 def OnIndustryWndMouseWheel(self, *args): 342 if not self.jobData: 343 return 344 self.runsEdit.OnMouseWheel() 345 if uicore.registry.GetFocus() != self.runsEdit: 346 uicore.registry.SetFocus(self.runsEdit) 347 348 def OnIndustryWndClick(self): 349 if not self.jobData: 350 return 351 uicore.registry.SetFocus(self.runsEdit) 352 353 354 class BlueprintGaugeCircular(GaugeCircular): 355 default_opacity = 0.0 356 357 def ApplyAttributes(self, attributes): 358 GaugeCircular.ApplyAttributes(self, attributes) 359 self.jobData = attributes.jobData 360 361 def OnNewJobData(self, jobData): 362 self.jobData = jobData 363 364 def OnMouseEnter(self, *args): 365 GaugeCircular.OnMouseEnter(self, *args) 366 sm.GetService('audio').SendUIEvent('ind_circleMouseEnter') 367 368 def SetValue(self, value, *args): 369 GaugeCircular.SetValue(self, value, *args) 370 sm.GetService('audio').SetGlobalRTPC('ind_circleValue', 100 * value) 371 372 def OnMouseExit(self, *args): 373 GaugeCircular.OnMouseExit(self, *args) 374 sm.GetService('audio').SendUIEvent('ind_circleMouseExit') 375 376 def OnDropData(self, dragSource, dragData): 377 sm.ScatterEvent('OnIndustryDropData', dragSource, dragData) 378 379 def GetTooltipPosition(self, *args): 380 l, t, w, h = self.GetAbsolute() 381 offset = 43 382 return (l, 383 t - offset, 384 w, 385 h + 2 * offset) 386 387 def GetTooltipPointer(self): 388 return uiconst.POINT_BOTTOM_2 389 390 391 class BlueDash(Transform): 392 default_width = 100 393 default_height = 6 394 395 def ApplyAttributes(self, attributes): 396 Transform.ApplyAttributes(self, attributes) 397 self.sprite1 = Sprite(parent=self, align=uiconst.CENTERLEFT, pos=(0, 0, 49, 6), texturePath='res:/UI/Texture/classes/Industry/Center/blueDash.png') 398 self.sprite2 = Sprite(parent=self, align=uiconst.CENTERLEFT, pos=(0, 0, 49, 6), texturePath='res:/UI/Texture/classes/Industry/Center/blueDash.png') 399 self.sprite3 = Sprite(parent=self, align=uiconst.CENTERLEFT, pos=(0, 0, 49, 6), texturePath='res:/UI/Texture/classes/Industry/Center/blueDash.png') 400 uthread.new(self.Animate) 401 402 def Animate(self): 403 x0 = self.default_width 404 x1 = 0 405 k = 0.22 406 while not self.destroyed: 407 for i in xrange(2): 408 for j, obj in enumerate((self.sprite1, self.sprite2, self.sprite3)): 409 uicore.animations.MorphScalar(obj, 'left', x0, x1, duration=k * (j + 1)) 410 uicore.animations.FadeTo(obj, 0.0, 1.5, duration=2 * k, curveType=uiconst.ANIM_WAVE) 411 412 blue.synchro.SleepWallclock(4 * k * 1000) 413 414 blue.synchro.SleepWallclock(1000) 415 416 417 class BlueprintSingleLineEdit(SingleLineEditInteger): 418 419 def Disable(self): 420 super(BlueprintSingleLineEdit, self).Disable() 421 self.textLabel.left = 0 422 self.textLabel.align = uiconst.CENTER 423 self.SetReadOnly(True) 424 425 def Enable(self): 426 super(BlueprintSingleLineEdit, self).Enable() 427 self.textLabel.left = self.textLeftMargin 428 self.textLabel.align = uiconst.CENTERLEFT 429 self.SetReadOnly(False) 430 431 432 class BlueprintItemIcon(ItemIcon): 433 434 def ApplyAttributes(self, attributes): 435 ItemIcon.ApplyAttributes(self, attributes) 436 self.jobData = attributes.jobData 437 438 def GetMenu(self): 439 bpData = self.jobData.blueprint 440 m = GetMenuService().GetMenuFromItemIDTypeID(self.jobData.blueprintID, bpData.blueprintTypeID, includeMarketDetails=True).filter(['UI/Industry/ViewInIndustry']) 441 m.append((localization.GetByLabel('UI/Industry/RemoveBlueprint'), self.RemoveBlueprint)) 442 if session.role & ROLE_PROGRAMMER: 443 m.insert(0, ('GM: Give me these materials', self._GiveMeMaterials)) 444 return m 445 446 def _GiveMeMaterials(self): 447 materials = [ (material.typeID, material.quantity) for material in self.jobData.materials ] 448 sm.GetService('info').DoCreateMaterials(materials) 449 450 def RemoveBlueprint(self): 451 sm.ScatterEvent('OnIndustryRemoveBlueprint') 452 453 def OnNewJobData(self, jobData): 454 self.jobData = jobData 455 456 def OnMouseEnter(self, *args): 457 ItemIcon.OnMouseEnter(self, *args) 458 PlaySound(uiconst.SOUND_BUTTON_HOVER) 459 460 def OnDropData(self, dragSource, dragData): 461 sm.ScatterEvent('OnIndustryDropData', dragSource, dragData) 462 463 def GetHint(self): 464 hint = ItemIcon.GetHint(self) 465 if hint: 466 return hint.strip()