mapMarkerBase.py (21795B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\mapView\markers\mapMarkerBase.py 2 import types 3 import weakref 4 import geo2 5 import telemetry 6 import carbonui.const as uiconst 7 import eve.client.script.ui.shared.mapView.mapViewConst as mapViewConst 8 import trinity 9 import uthread 10 from carbon.client.script.environment.AudioUtil import PlaySound 11 from carbon.common.script.util.commonutils import StripTags 12 from carbonui.primitives.base import ScaleDpiF 13 from carbonui.primitives.container import Container 14 from carbonui.primitives.sprite import Sprite 15 from carbonui.uianimations import animations 16 from carbonui.util.bunch import Bunch 17 from carbonui.control.link import Link 18 from carbonui.util.dpi import ReverseScaleDpi 19 from eve.client.script.ui.control.glowSprite import GlowSprite 20 from eve.client.script.ui.inflight.scannerFiles.scannerUtil import COLOR_DSCAN 21 from eve.client.script.ui.shared.mapView.mapViewConst import SOLARSYSTEM_SCALE 22 from eve.client.script.ui.shared.mapView.mapViewUtil import MapPosToSolarSystemPos 23 from eve.client.script.ui.shared.maps.maputils import GetMyPos 24 from eve.client.script.ui.tooltips.tooltipHandler import TOOLTIP_SETTINGS_BRACKET, TOOLTIP_DELAY_BRACKET 25 from carbonui.uicore import uicore 26 from logmodule import LogException 27 28 class MarkerContainerBase(Container): 29 default_align = uiconst.NOALIGN 30 default_opacity = 1.0 31 default_state = uiconst.UI_NORMAL 32 markerObject = None 33 isDragObject = True 34 35 def ApplyAttributes(self, attributes): 36 Container.ApplyAttributes(self, attributes) 37 self.markerObject = attributes.markerObject 38 self.renderObject.displayY = -1000 39 40 def Close(self, *args): 41 Container.Close(self, *args) 42 self.markerObject = None 43 44 def OnClick(self, *args): 45 return self.markerObject.OnClick(*args) 46 47 def OnDblClick(self, *args): 48 return self.markerObject.OnDblClick(*args) 49 50 def OnMouseDown(self, *args): 51 sm.ScatterEvent('OnMarkerMouseDown', *args) 52 return self.markerObject.OnMouseDown(*args) 53 54 def OnMouseUp(self, *args): 55 sm.ScatterEvent('OnMarkerMouseUp', *args) 56 return self.markerObject.OnMouseUp(*args) 57 58 def OnMouseEnter(self, *args): 59 return self.markerObject.OnMouseEnter(*args) 60 61 def OnMouseExit(self, *args): 62 return self.markerObject.OnMouseExit(*args) 63 64 def GetMenu(self): 65 return self.markerObject.GetMenu() 66 67 def GetTooltipDelay(self): 68 return settings.user.ui.Get(TOOLTIP_SETTINGS_BRACKET, TOOLTIP_DELAY_BRACKET) 69 70 @apply 71 def opacity(): 72 73 def fget(self): 74 return self._opacity 75 76 def fset(self, value): 77 self._opacity = value 78 self.renderObject.opacity = value 79 80 return property(**locals()) 81 82 def UpdateBackgrounds(self): 83 for each in self.background: 84 pl, pt, pr, pb = each.padding 85 each.displayRect = (ScaleDpiF(pl), 86 ScaleDpiF(pt), 87 self._displayWidth - ScaleDpiF(pl + pr), 88 self._displayHeight - ScaleDpiF(pt + pb)) 89 90 def GetDragData(self, *args): 91 return self.markerObject.GetDragData(self, *args) 92 93 @classmethod 94 def PrepareDrag(cls, *args): 95 return Link.PrepareDrag(*args) 96 97 98 class MarkerBase(object): 99 __metaclass__ = telemetry.ZONE_PER_METHOD 100 isLoaded = False 101 isGrouped = False 102 markerID = None 103 position = (0, 0, 0) 104 destroyed = False 105 distanceFadeAlphaNearFar = (0.0, mapViewConst.MAX_MARKER_DISTANCE) 106 displayStateOverride = None 107 ignoreOverlaps = False 108 markerContainer = None 109 parentContainer = None 110 extraContainer = None 111 curveSet = None 112 eventHandler = None 113 solarSystemID = None 114 positionPickable = False 115 hilightState = False 116 activeState = False 117 updated = False 118 tooltipRowClass = None 119 itemID = None 120 typeID = None 121 122 def __init__(self, markerID, markerHandler, parentContainer, position, curveSet, eventHandler = None, **kwds): 123 self.isDscanHiliteShown = False 124 self.dScanHilite = None 125 self.markerID = markerID 126 self.curveSet = None 127 self.currentGroupID = None 128 self.projectBracket = trinity.EveProjectBracket() 129 if 'distanceFadeAlphaNearFar' in kwds: 130 self._distanceFadeAlphaNearFar = kwds['distanceFadeAlphaNearFar'] 131 else: 132 self._distanceFadeAlphaNearFar = self.distanceFadeAlphaNearFar 133 self.SetBracketMaxDispRange() 134 self.parentContainer = weakref.ref(parentContainer) 135 self.markerHandler = markerHandler 136 self.eventHandler = eventHandler 137 self.SetPosition(position) 138 self.projectBracket.bracketUpdateCallback = self.OnMapMarkerUpdated 139 if curveSet: 140 self.curveSet = weakref.ref(curveSet) 141 curveSet.curves.append(self.projectBracket) 142 143 def SetBracketMaxDispRange(self): 144 if self._distanceFadeAlphaNearFar: 145 self.projectBracket.maxDispRange = self._distanceFadeAlphaNearFar[1] 146 147 def Close(self): 148 self.DestroyRenderObject() 149 if self.curveSet: 150 curveSet = self.curveSet() 151 if curveSet: 152 curveSet.curves.fremove(self.projectBracket) 153 self.markerHandler = None 154 self.eventHandler = None 155 self.curveSet = None 156 if self.projectBracket: 157 self.projectBracket.bracketUpdateCallback = None 158 self.projectBracket = None 159 self.parentContainer = None 160 self.markerContainer = None 161 162 def SetOverlappedState(self, overlapState): 163 pass 164 165 def RegisterOverlapMarkers(self, overlapMarkers): 166 pass 167 168 def FadeOutAndClose(self): 169 if self.markerContainer and not self.markerContainer.destroyed and self.markerContainer.opacity: 170 uicore.animations.FadeTo(self.markerContainer, startVal=self.markerContainer.opacity, endVal=0.0, callback=self.Close) 171 else: 172 self.Close() 173 174 def GetGroupingId(self, zoomLevel): 175 return None 176 177 def GetGroupingValue(self): 178 return 1 179 180 def SetGroupingID(self, groupID): 181 if groupID != self.currentGroupID: 182 self.currentGroupID = groupID 183 self.lastUpdateCameraValues = None 184 self.UpdateActiveAndHilightState() 185 self._UpdateRenderObjectVisibility(0) 186 187 def GetCurrentGroupID(self): 188 return self.currentGroupID 189 190 def GetExtraMouseOverInfo(self): 191 if self.markerHandler: 192 return self.markerHandler.GetExtraMouseOverInfoForMarker(self.markerID) 193 194 def SetHilightState(self, hilightState): 195 if hilightState != self.hilightState: 196 self.hilightState = hilightState 197 self.lastUpdateCameraValues = None 198 self.UpdateActiveAndHilightState() 199 200 def SetActiveState(self, activeState): 201 if activeState != self.activeState: 202 self.activeState = activeState 203 self.lastUpdateCameraValues = None 204 self.UpdateActiveAndHilightState() 205 206 def UpdateActiveAndHilightState(self): 207 pass 208 209 def MoveToFront(self): 210 if self.parentContainer: 211 parentContainer = self.parentContainer() 212 if not parentContainer or parentContainer.destroyed: 213 return 214 if self.markerContainer and not self.markerContainer.destroyed: 215 renderObject = self.markerContainer.renderObject 216 parentContainer.renderObject.children.remove(renderObject) 217 parentContainer.renderObject.children.insert(0, renderObject) 218 219 def GetBoundaries(self): 220 mx, my = self.projectBracket.rawProjectedPosition 221 return (mx - 6 + self.projectBracket.offsetX, 222 my - 6 + self.projectBracket.offsetY, 223 mx + 6 + self.projectBracket.offsetX, 224 my + 6 + self.projectBracket.offsetY) 225 226 def GetDisplayText(self): 227 return None 228 229 def GetLabelText(self): 230 return None 231 232 def GetDragText(self): 233 return self.GetDisplayText() 234 235 def GetMarkerDistance(self): 236 return self.GetCameraDistance() 237 238 def GetCameraDistance(self): 239 return self.projectBracket.cameraDistance 240 241 def SetPosition(self, position): 242 self.position = position 243 self.projectBracket.trackPosition = position 244 245 def GetDisplayPosition(self): 246 if self.projectBracket: 247 return self.projectBracket.trackPosition 248 249 def OnMapMarkerUpdated(self, projectBracket): 250 try: 251 self._OnMapMarkerUpdated(projectBracket) 252 except: 253 LogException() 254 raise 255 256 def _OnMapMarkerUpdated(self, projectBracket): 257 if self.displayStateOverride == False: 258 if self.markerContainer: 259 self.DestroyRenderObject() 260 return 261 cameraTranslationFromParent = self.markerHandler.cameraTranslationFromParent 262 bracketCameraDistance = projectBracket.cameraDistance 263 if (cameraTranslationFromParent, bracketCameraDistance) != getattr(self, 'lastUpdateCameraValues', None): 264 self.lastUpdateCameraValues = (cameraTranslationFromParent, bracketCameraDistance) 265 opacity = self.GetMarkerOpacity(bracketCameraDistance, cameraTranslationFromParent) 266 self._UpdateRenderObjectVisibility(opacity) 267 self.updated = True 268 269 def _UpdateRenderObjectVisibility(self, opacity): 270 if self.currentGroupID: 271 self._HideRenderObject() 272 return 273 if opacity is not None and opacity > 0.05: 274 self._ShowRenderObject(opacity) 275 elif self.markerContainer: 276 self._HideRenderObject() 277 278 def _HideRenderObject(self): 279 if self.markerContainer and not self.markerContainer.destroyed: 280 self.markerContainer.Hide() 281 282 def _ShowRenderObject(self, opacity): 283 self.CreateRenderObject() 284 self.markerContainer.opacity = opacity 285 self.markerContainer.Show() 286 287 def OnClick(self, *args, **kwds): 288 self.ClickMarker() 289 290 def OnDblClick(self, *args, **kwds): 291 self.ClickMarker() 292 293 def ClickMarker(self): 294 if uicore.cmd.IsSomeCombatCommandLoaded(): 295 uicore.cmd.ExecuteCombatCommand(self.itemID, uiconst.UI_CLICK) 296 else: 297 self.markerHandler.OnMarkerSelected(self) 298 299 def OnMouseDown(self, *args): 300 pass 301 302 def OnMouseUp(self, *args): 303 pass 304 305 def OnMouseEnter(self, *args): 306 if uicore.uilib.leftbtn or uicore.uilib.rightbtn: 307 return 308 PlaySound(uiconst.SOUND_ENTRY_HOVER) 309 self.markerHandler.OnMarkerMouseEnter(self) 310 311 def OnMouseExit(self, *args): 312 self.markerHandler.OnMarkerMouseExit(self) 313 314 def CreateRenderObject(self): 315 if self.parentContainer and (not self.markerContainer or self.markerContainer.destroyed): 316 if not self.parentContainer(): 317 return 318 self._CreateRenderObject() 319 320 def _CreateRenderObject(self): 321 self.markerContainer = self.GetMarkerContainerCls()(parent=self.parentContainer(), markerObject=self, name=self.__class__.__name__) 322 self.projectBracket.bracket = self.markerContainer.renderObject 323 self.Load() 324 325 def GetMarkerContainerCls(self): 326 return MarkerContainerBase 327 328 def Reload(self): 329 self.DestroyRenderObject() 330 self.lastUpdateCameraValues = None 331 332 def DestroyRenderObject(self): 333 if self.projectBracket: 334 self.projectBracket.bracket = None 335 if self.markerContainer and not self.markerContainer.destroyed: 336 markerContainer = self.markerContainer 337 self.markerContainer = None 338 markerContainer.Close() 339 if self.extraContainer and not self.extraContainer.destroyed: 340 self.extraContainer.Close() 341 self.extraContainer = None 342 self.isLoaded = False 343 self.lastUpdateCameraValues = None 344 345 def Load(self): 346 pass 347 348 def GetMenu(self): 349 try: 350 objectID = int(self.markerID) 351 return self.eventHandler.GetMenuForObjectID(objectID) 352 except: 353 pass 354 355 def GetHint(self): 356 return None 357 358 def GetDragData(self, *args): 359 displayText = self.GetDragText() 360 if self.itemID and self.typeID and displayText: 361 url = 'showinfo:%d//%d' % (self.typeID, self.itemID) 362 entry = Bunch() 363 entry.__guid__ = 'TextLink' 364 entry.url = url 365 entry.displayText = StripTags(displayText) 366 return [entry] 367 368 def HasEventHandler(self, handlerName): 369 handlerArgs, handler = self.FindEventHandler(handlerName) 370 if not handler: 371 return False 372 baseHandler = getattr(MarkerBase, handlerName, None) 373 if baseHandler and getattr(handler, '__func__', None) is baseHandler.__func__: 374 return False 375 return bool(handler) 376 377 def GetOverlapSortValue(self, reset = False): 378 return None 379 380 def FindEventHandler(self, handlerName): 381 handler = getattr(self, handlerName, None) 382 if not handler: 383 return (None, None) 384 if type(handler) == types.TupleType: 385 handlerArgs = handler[1:] 386 handler = handler[0] 387 else: 388 handlerArgs = () 389 return (handlerArgs, handler) 390 391 def ShowDscanHilite(self): 392 resetOverlap = not self.isDscanHiliteShown 393 self.isDscanHiliteShown = True 394 if resetOverlap: 395 self.GetOverlapSortValue(reset=True) 396 if not self.IsPickable(): 397 return 398 self.ConstructDscanHilite() 399 if self.dScanHilite: 400 self.dScanHilite.Show() 401 402 def IsPartialResult(self): 403 return False 404 405 def IsDscanHiliteShown(self): 406 return self.isDscanHiliteShown 407 408 def ConstructDscanHilite(self): 409 if not self.dScanHilite or self.dScanHilite.destroyed: 410 if not self.markerContainer: 411 return 412 self.dScanHilite = Container(name='dScanHilite', parent=self.markerContainer, align=uiconst.CENTER, state=uiconst.UI_DISABLED, idx=-1, pos=(0, 0, 32, 32)) 413 Sprite(align=uiconst.CENTER, pos=(0, 0, 50, 50), parent=self.dScanHilite, color=COLOR_DSCAN, texturePath='res:/UI/Texture/classes/animations/radialGradient.png', opacity=0.3) 414 GlowSprite(align=uiconst.CENTER, pos=(0, 0, 30, 30), parent=self.dScanHilite, color=COLOR_DSCAN, texturePath='res:/UI/Texture/classes/Bracket/selectionCircle.png') 415 416 def IsPickable(self): 417 if self.markerContainer: 418 return self.markerContainer.pickState == uiconst.TR2_SPS_ON 419 else: 420 return False 421 422 def HideDscanHilite(self): 423 resetOverlap = self.isDscanHiliteShown 424 self.isDscanHiliteShown = False 425 if resetOverlap: 426 self.GetOverlapSortValue(reset=True) 427 if self.dScanHilite: 428 self.dScanHilite.Hide() 429 430 def AnimBlinkDscanHilite(self): 431 if self.dScanHilite and self.dScanHilite.display: 432 animations.FadeTo(self.dScanHilite, 3.0, 1.0, duration=1.0) 433 434 def GetMarkerOpacity(self, bracketCameraDistance, cameraZoomDistance): 435 if self.IsSelected() or self.IsHilighted(): 436 return mapViewConst.OPACITY_MARKER_SELECTED 437 elif self.IsActive() or self._distanceFadeAlphaNearFar is None: 438 return mapViewConst.OPACITY_MARKER_ACTIVE 439 else: 440 nearFadeDist, farFadeDist = self._distanceFadeAlphaNearFar 441 baseOpacity = self.GetMarkerBaseOpacity(bracketCameraDistance, nearFadeDist, farFadeDist) 442 nearFactor = self.GetNearFadeFactor(bracketCameraDistance, cameraZoomDistance) 443 return round(baseOpacity * nearFactor, 2) 444 445 def GetMarkerBaseOpacity(self, bracketCameraDistance, nearFadeDist, farFadeDist): 446 if bracketCameraDistance < nearFadeDist: 447 return bracketCameraDistance / nearFadeDist 448 elif bracketCameraDistance < farFadeDist: 449 return min(1.0, max(0.0, 1.0 - bracketCameraDistance / farFadeDist)) 450 else: 451 return 0.0 452 453 def GetNearFadeFactor(self, bracketCameraDistance, cameraZoomDistance): 454 return min(1.0, cameraZoomDistance / bracketCameraDistance) 455 456 def IsSelected(self): 457 return self.activeState == mapViewConst.MARKER_SELECTED 458 459 def IsHilighted(self): 460 return bool(self.hilightState) 461 462 def IsActive(self): 463 return self.activeState == mapViewConst.MARKER_ACTIVE 464 465 466 class MarkerSolarSystemBased(MarkerBase): 467 inRangeIndicatorState = False 468 itemID = None 469 trackObjectID = None 470 binding = None 471 vectorSequencer = None 472 473 def __init__(self, *args, **kwds): 474 MarkerBase.__init__(self, *args, **kwds) 475 self.mapPositionSolarSystem = kwds['mapPositionSolarSystem'] 476 self.mapPositionLocal = kwds['mapPositionLocal'] 477 self.solarSystemID = kwds['solarSystemID'] 478 self.trackObjectID = kwds.get('trackObjectID', None) 479 self.trackObjectScale = kwds.get('trackObjectScale', 1.0) 480 if self.trackObjectID: 481 self.SetupTracking() 482 483 def Close(self, *args, **kwds): 484 self.TearDownTracking() 485 MarkerBase.Close(self, *args, **kwds) 486 487 def UpdateSolarSystemPosition(self, solarSystemPosition): 488 self.mapPositionSolarSystem = solarSystemPosition 489 self.position = solarSystemPosition 490 self.projectBracket.trackPosition = self.position 491 492 def SetInRangeIndicatorState(self, visibleState): 493 self.inRangeIndicatorState = visibleState 494 495 def GetDistance(self): 496 if session.solarsystemid: 497 if self.itemID: 498 ballPark = sm.GetService('michelle').GetBallpark() 499 if ballPark and self.itemID in ballPark.balls: 500 return ballPark.balls[self.itemID].surfaceDist 501 if self.solarSystemID == session.solarsystemid: 502 solarSystemPosition = self._GetSolarSystemPosition() 503 myPosition = GetMyPos() 504 return geo2.Vec3Length(geo2.Vec3Subtract(solarSystemPosition, (myPosition.x, myPosition.y, myPosition.z))) 505 506 def _GetSolarSystemPosition(self): 507 return MapPosToSolarSystemPos(self.mapPositionLocal) 508 509 def TearDownTracking(self): 510 if self.vectorSequencer: 511 if self.curveSet: 512 curveSet = self.curveSet() 513 if curveSet: 514 curveSet.curves.remove(self.vectorSequencer) 515 curveSet.bindings.remove(self.binding) 516 self.binding = None 517 self.vectorSequencer = None 518 519 def SetupTracking(self): 520 self.TearDownTracking() 521 bp = sm.GetService('michelle').GetBallpark() 522 if not bp: 523 return 524 sunBall = None 525 if self.trackObjectID == session.shipid: 526 for itemID, each in bp.slimItems.iteritems(): 527 if each.groupID == const.groupSun: 528 sunBall = bp.GetBall(itemID) 529 break 530 531 trackBallID = self.trackObjectID 532 ball = bp.GetBall(trackBallID) 533 if ball is None or sunBall is None: 534 return 535 vectorCurve = trinity.Tr2CurveVector3() 536 scale = SOLARSYSTEM_SCALE * self.trackObjectScale 537 vectorCurve.AddKey(0, (-scale, -scale, -scale)) 538 invSunPos = trinity.TriVectorSequencer() 539 invSunPos.operator = trinity.TRIOP_MULTIPLY 540 invSunPos.functions.append(sunBall) 541 invSunPos.functions.append(vectorCurve) 542 vectorCurve = trinity.Tr2CurveVector3() 543 vectorCurve.AddKey(0, (scale, scale, scale)) 544 ballPos = trinity.TriVectorSequencer() 545 ballPos.operator = trinity.TRIOP_MULTIPLY 546 ballPos.functions.append(ball) 547 ballPos.functions.append(vectorCurve) 548 vectorSequencer = trinity.TriVectorSequencer() 549 vectorSequencer.operator = trinity.TRIOP_ADD 550 vectorSequencer.functions.append(invSunPos) 551 vectorSequencer.functions.append(ballPos) 552 bind = trinity.TriValueBinding() 553 bind.copyValueCallable = self.OnBallPositionUpdate 554 bind.sourceObject = vectorSequencer 555 bind.sourceAttribute = 'value' 556 self.binding = bind 557 self.vectorSequencer = vectorSequencer 558 if self.curveSet: 559 curveSet = self.curveSet() 560 if curveSet: 561 curveSet.curves.append(vectorSequencer) 562 curveSet.bindings.append(bind) 563 564 @property 565 def x_offset(self): 566 if self.binding: 567 return ReverseScaleDpi(self.binding[0].offset[0]) 568 569 @x_offset.setter 570 def x_offset(self, value): 571 if self.binding: 572 self.binding[0].offset = (ScaleDpi(value), 573 0, 574 0, 575 0) 576 577 @property 578 def y_offset(self): 579 if self.binding: 580 return ReverseScaleDpi(self.binding[1].offset[0]) 581 582 @y_offset.setter 583 def y_offset(self, value): 584 if self.binding: 585 self.binding[1].offset = (ScaleDpi(value), 586 0, 587 0, 588 0) 589 590 def OnBallPositionUpdate(self, curveSet, *args): 591 try: 592 if curveSet.value == (0, 0, 0): 593 uthread.new(self.TearDownTracking) 594 else: 595 self.UpdateMapPositionLocal(curveSet.value) 596 except: 597 LogException() 598 raise 599 600 def CheckDirectionalScanItem(self): 601 doDScan = uicore.cmd.IsCombatCommandLoaded('CmdRefreshDirectionalScan') 602 if doDScan: 603 markerPosition = self.position 604 uicore.cmd.GetCommandAndExecute('OpenDirectionalScanner', toggle=False) 605 sm.GetService('directionalScanSvc').ScanTowardsItem(self.itemID, mapPosition=markerPosition) 606 return doDScan