radialMenu.py (36380B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\radialMenu\radialMenu.py 2 from __future__ import print_function 3 import math 4 from carbon.common.script.util import timerstuff 5 from carbon.common.script.util.format import FmtDist 6 from carbonui.primitives.container import Container 7 from carbonui.primitives.sprite import Sprite 8 from carbonui.primitives.transform import Transform 9 from eve.client.script.ui.control import eveLabel 10 from eve.client.script.ui.shared.radialMenu.radialMenuActions import RadialMenuActioSecondLevel, RadialMenuRangeAction 11 from eve.client.script.ui.shared.radialMenu.radialMenuLayer import RadialMenuLayer, RadialMenuShadow 12 from eve.client.script.ui.shared.radialMenu.radialMenuUtils import RadialMenuOptionsInfo, RangeRadialMenuAction, SimpleRadialMenuAction, RadialMenuSizeInfo 13 from eve.client.script.ui.shared.radialMenu import spaceRadialMenuFunctions, inventoryRadialMenuFunctions, NORMAL_RADIAL_MENU, BROADCAST_RADIAL_MENU 14 from eve.client.script.ui.shared.radialMenu.rangeCircle import RangeCircle 15 import evetypes 16 import uthread 17 import carbonui.const as uiconst 18 import geo2 19 import blue 20 import telemetry 21 import localization 22 from eve.client.script.ui.util import uix 23 from carbonui.control.contextMenu.contextMenu import ShowMenu 24 from carbonui.uicore import uicore 25 from eve.client.script.ui.shared.radialMenu.spaceRadialMenuFunctions import GetSingleMouseBtnBroadcastRadialMenu 26 from eve.client.script.util.bubble import SlimItemFromCharID 27 RMO_SizeInfo = RadialMenuSizeInfo(width=220, height=220, shadowSize=256, rangeSize=128, sliceCount=8, buttonWidth=100, buttonHeight=70, buttonPaddingTop=12, buttonPaddingBottom=6, actionDistance=110) 28 29 class RadialMenu(Transform): 30 __notifyevents__ = ['OnSettingsOpened'] 31 default_left = 0 32 default_top = 0 33 default_align = uiconst.TOPLEFT 34 default_state = uiconst.UI_NORMAL 35 default_width = RMO_SizeInfo.width 36 default_height = RMO_SizeInfo.height 37 sizeInfo = RMO_SizeInfo 38 default_showActionText = True 39 default_usePreciseRanges = True 40 shadowTexture = 'res:/UI/Texture/classes/RadialMenu/menuShadow2.png' 41 buttonBackgroundOpacity = 0.7 42 menuType = NORMAL_RADIAL_MENU 43 44 def ApplyAttributes(self, attributes): 45 self.creationTime = blue.os.GetWallclockTime() 46 self.clickedObject = attributes.get('clickedObject', None) 47 self.radialMenuSvc = sm.GetService('radialmenu') 48 self.cursor = uiconst.UICURSOR_SELECT 49 uicore.UpdateCursor(self, force=True) 50 self.lastMoveTime = 0 51 Transform.ApplyAttributes(self, attributes) 52 self.InitializeVariables(attributes) 53 self.itemID = None 54 self.SetSpecificValues(attributes) 55 self.actionDistance = int(self.height / 2.0) 56 self.selectedBtn = None 57 self.AddMenuLayers() 58 self.blocker = Container(name='blocker', parent=uicore.layer.menu, state=uiconst.UI_NORMAL, align=uiconst.TOALL, pos=(0, 0, 0, 0)) 59 self.blocker.OnMouseUp = self.OnMouseUpBlocker 60 self.AddRangeCircle() 61 doShowActionText = attributes.get('showActionText', self.default_showActionText) 62 if doShowActionText: 63 self.AddOptionText() 64 shadowSize = self.sizeInfo.shadowSize 65 self.shadow = RadialMenuShadow(parent=self, pos=(0, 66 0, 67 shadowSize, 68 shadowSize), shadowSize=shadowSize, texturePath=self.shadowTexture, idx=-1) 69 self.LoadMyActions(animate=True) 70 self.InitializeCenterPoint(attributes) 71 if self.displayName or self.updateDisplayName: 72 self.AddDisplayLabel() 73 self.SetPosition() 74 self.mouseMoveCookie = uicore.event.RegisterForTriuiEvents(uiconst.UI_MOUSEMOVE, self.OnGlobalMove) 75 self.updateOptionsTimer = timerstuff.AutoTimer(250, self.UpdateOptions) 76 self.UpdateIndicator() 77 sm.GetService('audio').SendUIEvent('ui_radial_open_play') 78 sm.RegisterNotify(self) 79 80 def AddMenuLayers(self): 81 self.secondLayerCont = RadialMenuLayer(parent=self, name='secondLayerCont', pos=(0, 82 0, 83 self.width, 84 self.height), display=False, sizeInfo=self.sizeInfo, buttonBackgroundOpacity=self.buttonBackgroundOpacity, usePreciseRanges=self.usePreciseRanges, menuType=self.menuType) 85 self.firstLayerCont = RadialMenuLayer(parent=self, name='firstLayerCont', pos=(0, 86 0, 87 self.width, 88 self.height), sizeInfo=self.sizeInfo, buttonBackgroundOpacity=self.buttonBackgroundOpacity, usePreciseRanges=self.usePreciseRanges, menuType=self.menuType) 89 90 def InitializeVariables(self, attributes): 91 self.sliceCount = self.sizeInfo.sliceCount 92 self.stepSize = 360 / self.sliceCount 93 self.buttonHeight = self.sizeInfo.buttonHeight 94 self.buttonPaddingBottom = self.sizeInfo.buttonPaddingBottom 95 self.usePreciseRanges = attributes.get('usePreciseRanges', self.default_usePreciseRanges) 96 self.displayName = attributes.get('displayName', '') 97 self.updateDisplayName = attributes.get('updateDisplayName', False) 98 99 def InitializeCenterPoint(self, attributes): 100 self.originalX = attributes.get('x', uicore.uilib.x) 101 self.originalY = attributes.get('y', uicore.uilib.y) 102 self.currentCenterX = self.originalX 103 self.currentCenterY = self.originalY 104 self.halfScreenX = uicore.desktop.width / 2 105 self.halfScreenY = uicore.desktop.height / 2 106 uicore.uilib.ClipCursor(0, 0, uicore.desktop.width, uicore.desktop.height) 107 self.cursorClipped = True 108 self.offsetX = 0 109 self.offsetY = 0 110 111 def SetSpecificValues(self, attributes): 112 pass 113 114 def AddDisplayLabel(self): 115 displayTop = -18 116 self.displayLabelCont = ThreePartContainer(parent=self, name='labelShadow', pos=(0, 117 displayTop, 118 200, 119 30), align=uiconst.CENTERTOP, state=uiconst.UI_DISABLED, idx=0, leftTexturePath='res:/UI/Texture/classes/RadialMenu/textShadowLeft.png', rightTexturePath='res:/UI/Texture/classes/RadialMenu/textShadowRight.png', centerTexturePath='res:/UI/Texture/classes/RadialMenu/textShadowCenter.png', sideSize=24) 120 self.displayLabel = eveLabel.EveLabelLarge(text=self.displayName, parent=self.displayLabelCont, state=uiconst.UI_DISABLED, align=uiconst.CENTERTOP, top=0, idx=0) 121 height = self.displayLabel.textheight + 2 122 centerWidth = self.displayLabel.textwidth 123 self.displayLabelCont.SetCenterSizeAndTop(centerWidth, height) 124 if self.updateDisplayName: 125 self.UpdateDisplayName() 126 self.displayNameTimer = timerstuff.AutoTimer(250, self.UpdateDisplayName) 127 128 def AddRangeCircle(self): 129 rangeSize = self.sizeInfo.rangeSize 130 self.rangeCont = RangeCircle(parent=self, rangeSize=rangeSize, idx=0) 131 132 def AddOptionText(self): 133 self.labelShadow = ThreePartContainer(parent=self, name='labelShadow', pos=(0, -10, 200, 30), align=uiconst.CENTER, state=uiconst.UI_DISABLED, idx=0, leftTexturePath='res:/UI/Texture/classes/RadialMenu/textShadowLeft.png', rightTexturePath='res:/UI/Texture/classes/RadialMenu/textShadowRight.png', centerTexturePath='res:/UI/Texture/classes/RadialMenu/textShadowCenter.png', sideSize=24) 134 self.labelShadow.display = False 135 self.optionLabel = eveLabel.EveLabelLarge(text='', parent=self, state=uiconst.UI_DISABLED, align=uiconst.CENTER, top=-10, idx=0, bold=True) 136 self.optionLabel.display = False 137 self.optionRangeLabel = eveLabel.EveLabelLarge(text='', parent=self, state=uiconst.UI_DISABLED, align=uiconst.CENTER, top=6, idx=0) 138 self.optionRangeLabel.display = False 139 self.AdjustTextShadow() 140 141 def SetOptionText(self, text): 142 if not getattr(self, 'optionLabel', None): 143 return 144 self.optionLabel.display = True 145 if text != self.optionLabel.text: 146 self.optionLabel.text = text 147 self.AdjustTextShadow() 148 149 def ClearOptionText(self, *args): 150 if not getattr(self, 'optionLabel', None): 151 return 152 self.optionLabel.display = False 153 if self.optionLabel.text: 154 self.optionLabel.text = '' 155 if getattr(self, 'labelShadow', None): 156 self.labelShadow.display = False 157 158 def SetOptionRangeText(self, text = None, display = True): 159 if not getattr(self, 'optionRangeLabel', None): 160 return 161 if text: 162 self.optionRangeLabel.text = text 163 self.optionRangeLabel.display = display 164 self.AdjustTextShadow() 165 166 def ClearOptionRangeText(self, *args): 167 if not getattr(self, 'optionRangeLabel', None): 168 return 169 self.optionRangeLabel.display = False 170 if self.optionRangeLabel.text: 171 self.optionRangeLabel.text = '' 172 self.AdjustTextShadow() 173 174 def UpdateOptions(self): 175 self.LoadMyActions(doReset=False) 176 if self.secondLayerCont.isExpanded and self.secondLayerCont.expandedButton: 177 self.UpdateSecondLevel(self.secondLayerCont.expandedButton, animate=False) 178 179 def LoadMyActions(self, doReset = False, animate = False): 180 pass 181 182 def AnimateMenuFromCenter(self, sizeRatio = 0.5, opacityRatio = 0.5, duration = 0.25, grow = True, sleep = False, skipBnts = ()): 183 curveSet = None 184 curveSet = self.firstLayerCont.AnimateFromCenter(curveSet, duration, sizeRatio, opacityRatio, grow, skipBnts) 185 curveSet = self.secondLayerCont.AnimateFromCenter(curveSet, duration, sizeRatio, opacityRatio, grow, skipBnts) 186 curveSet = self.shadow.AnimateFromCenter(duration, sizeRatio, opacityRatio, grow) 187 curveSet = self.rangeCont.AnimateFromCenter(curveSet, duration, opacityRatio, grow, sleep) 188 189 def ClickButton(self, btn): 190 self.CleanUp() 191 self.state = uiconst.UI_DISABLED 192 btnClickThread = uthread.new(btn.actionButton.OnButtonClick) 193 btnClickThread.context = 'RadialMenu::ClickButton:OnButtonClick' 194 duration = 0.5 195 sm.GetService('audio').SendUIEvent('ui_radial_select_play') 196 btnClickThread = uthread.new(self.RunClosingAnimation_thread, btn, duration) 197 btnClickThread.context = 'RadialMenu::ClickButton:RunClosingAnimation_thread' 198 199 def RunClosingAnimation_thread(self, btn, duration = 0.5): 200 self.isClosing = True 201 self.CleanUp() 202 self.AnimateMenuFromCenter(opacityRatio=0.0, duration=duration * 0.5, grow=False, sleep=False, skipBnts=(btn,)) 203 btn.actionButton.SelectButtonSlice(duration=duration) 204 self.Close() 205 206 @telemetry.ZONE_METHOD 207 def GetLengthFromCenter(self): 208 aX, bY = self.GetDistancesFromMenuCenter() 209 length = geo2.Vec2Length((aX, bY)) 210 return length 211 212 @telemetry.ZONE_METHOD 213 def GetCurrentDegree(self): 214 aX, bY = self.GetDistancesFromMenuCenter() 215 currentDegree = math.degrees(math.atan2(-aX, bY)) 216 if currentDegree < 0: 217 currentDegree += 360 218 return currentDegree 219 220 def GetDistancesFromMenuCenter(self, *args): 221 xDistance = self.currentCenterX - self.offsetX - uicore.uilib.x 222 yDistance = self.currentCenterY - self.offsetY - uicore.uilib.y 223 return (xDistance, yDistance) 224 225 @telemetry.ZONE_METHOD 226 def FindMyButton(self, degree, buttonLayer, stepSize): 227 return buttonLayer.FindMyButton(degree, stepSize) 228 229 @telemetry.ZONE_METHOD 230 def OnGlobalMove(self, *args): 231 try: 232 self._OnGlobalMove() 233 finally: 234 return 1 235 236 def _OnGlobalMove(self): 237 self.TryRepositionMouse() 238 now = blue.os.GetWallclockTime() 239 if now - self.lastMoveTime < 250000: 240 return 241 self.lastMoveTime = now 242 if getattr(self, 'isClosing', False): 243 return 244 length = self.GetLengthFromCenter() 245 if length < self.actionDistance - self.buttonHeight + self.buttonPaddingBottom: 246 self.ResetFromCenter() 247 return 248 if not self.IsRadialMenuButtonActive() and length > self.actionDistance - self.sizeInfo.buttonPaddingTop: 249 self.ResetFromCenter() 250 return 251 currentDegree = self.GetCurrentDegree() 252 if self.secondLayerCont.isExpanded: 253 buttonLayer = self.secondLayerCont 254 else: 255 buttonLayer = self.firstLayerCont 256 if self.selectedBtn and isinstance(self.selectedBtn.actionButton, RadialMenuRangeAction) and length > self.selectedBtn.actionButton.minRangeDistance: 257 buttonFound = self.selectedBtn 258 else: 259 self.rangeCont.display = False 260 buttonFound = self.FindMyButton(currentDegree, buttonLayer, self.stepSize) 261 self.HiliteOneButton(buttonFound, buttonLayer) 262 self.SelectButton(btn=None) 263 if buttonFound: 264 if isinstance(buttonFound.actionButton, RadialMenuRangeAction): 265 moveMouseResults = self.MoveMouseRangeAction(buttonFound, buttonFound.actionButton, length, currentDegree) 266 elif isinstance(buttonFound.actionButton, RadialMenuActioSecondLevel): 267 uthread.new(self.MoveMouseSecondLevel, buttonFound, buttonFound.actionButton, length, currentDegree) 268 self.MoveMouseRangeCallback(usingRangeOption=False) 269 else: 270 self.SelectButton(buttonFound) 271 self.ClearOptionRangeText() 272 self.MoveMouseRangeCallback(usingRangeOption=False) 273 else: 274 self.ClearOptionRangeText() 275 276 def MoveMouseRangeAction(self, buttonCont, actionButton, length, currentDegree): 277 moveMouseResults = actionButton.MoveMouse(length, currentDegree) 278 if moveMouseResults: 279 currentRange, percOfAllRange = moveMouseResults 280 self.MoveMouseRangeCallback(usingRangeOption=True, currentRange=currentRange, percOfAllRange=percOfAllRange) 281 self.SetOptionRangeText(FmtDist(currentRange)) 282 self.SetRangeCircle(buttonCont.degree, percOfAllRange) 283 self.SelectButton(buttonCont) 284 return moveMouseResults 285 286 def MoveMouseRangeCallback(self, usingRangeOption, currentRange = None, percOfAllRange = None): 287 pass 288 289 def MoveMouseSecondLevel(self, buttonParent, actionButton, length, currentDegree): 290 self.ClearOptionRangeText() 291 shouldExpand = actionButton.MoveMouse(length, currentDegree) 292 if shouldExpand and not self.secondLayerCont.isExpanded: 293 wasLoaded = self.UpdateSecondLevel(buttonParent, animate=True) 294 if wasLoaded: 295 sm.GetService('audio').SendUIEvent('ui_radial_expand_play') 296 297 def AdjustTextShadow(self): 298 if not getattr(self, 'optionLabel', None) or not self.optionLabel.display: 299 if getattr(self, 'labelShadow', None): 300 self.labelShadow.display = False 301 return 302 if self.optionRangeLabel.display: 303 centerWidth = max(self.optionLabel.textwidth, self.optionRangeLabel.textwidth) 304 height = self.optionLabel.textheight + self.optionRangeLabel.textheight + 4 305 top = 0 306 else: 307 centerWidth = self.optionLabel.textwidth 308 height = self.optionLabel.textheight + 4 309 top = -10 310 self.labelShadow.display = True 311 self.labelShadow.SetCenterSizeAndTop(centerWidth, height, top=top) 312 313 def UpdateSecondLevel(self, buttonParent, animate = False): 314 optionsInfo = self.GetSecondLevelOptions(buttonParent) 315 if not optionsInfo or len(optionsInfo.allWantedMenuOptions) < 1: 316 return 317 self.firstLayerCont.SetOpacity(0.3) 318 wasLoaded = self.LoadSecondLevelActions(buttonParent, optionsInfo=optionsInfo, animate=animate) 319 if wasLoaded: 320 self.secondLayerCont.isExpanded = True 321 self.secondLayerCont.expandedButton = buttonParent 322 return True 323 return False 324 325 def GetSecondLevelOptions(self, buttonParent): 326 return None 327 328 def LoadSecondLevelActions(self, buttonParent, optionsInfo = None, animate = False): 329 return False 330 331 def OnMouseUp(self, button, *args): 332 uicore.uilib.UnclipCursor() 333 self.cursorClipped = False 334 radialMenuBtn = self.GetRadialMenuButton() 335 if radialMenuBtn == button and self.selectedBtn: 336 self.ClickButton(self.selectedBtn) 337 else: 338 self.KillRadialMenu(button) 339 340 def KillRadialMenu(self, button): 341 self.CloseWithoutActionCallback(button) 342 self.Close() 343 344 def OnMouseUpBlocker(self, button): 345 self.OnMouseUp(button) 346 347 def CloseWithoutActionCallback(self, button): 348 pass 349 350 @telemetry.ZONE_METHOD 351 def HiliteOneButton(self, btnCont, buttonLayer): 352 newLabel = buttonLayer.HiliteOneButtonAndGetLabel(btnCont) 353 if newLabel: 354 self.SetOptionText(newLabel) 355 if btnCont is None: 356 self.ClearOptionText() 357 self.ClearOptionRangeText() 358 359 def SelectButton(self, btn = None): 360 self.selectedBtn = btn 361 362 def HideCursor(self): 363 self.cursor = uiconst.UICURSOR_NONE 364 uicore.UpdateCursor(self, force=True) 365 366 def TryRepositionMouse(self, *args): 367 if not self.cursorClipped: 368 return 369 repositionToCenter = False 370 resetToRealPointer = False 371 currentMouseX = uicore.uilib.x 372 currentMouseY = uicore.uilib.y 373 newX = currentMouseX 374 newY = currentMouseY 375 newOffsetX = self.offsetX 376 newOffsetY = self.offsetY 377 if (currentMouseX <= 1 or currentMouseX >= uicore.desktop.width - 1) and self.offsetX == 0: 378 repositionToCenter = True 379 newX = self.halfScreenX 380 newOffsetX = uicore.uilib.x - newX 381 if (currentMouseY <= 1 or currentMouseY >= uicore.desktop.height - 1) and self.offsetY == 0: 382 repositionToCenter = True 383 newY = self.halfScreenY 384 newOffsetY = uicore.uilib.y - newY 385 if not repositionToCenter and self.offsetX == 0 and self.offsetY == 0: 386 return 387 if self.offsetX < 0 and currentMouseX > abs(self.offsetX) or self.offsetX > 0 and currentMouseX < self.offsetX: 388 newX = max(2, min(uicore.uilib.x + self.offsetX, uicore.desktop.width - 2)) 389 newOffsetX = 0 390 resetToRealPointer = True 391 if self.offsetY < 0 and currentMouseY > abs(self.offsetY) or self.offsetY > 0 and currentMouseY < self.offsetY: 392 newY = max(2, min(uicore.uilib.y + self.offsetY, uicore.desktop.height - 2)) 393 newOffsetY = 0 394 resetToRealPointer = True 395 if repositionToCenter or resetToRealPointer: 396 self.offsetX = newOffsetX 397 self.offsetY = newOffsetY 398 if resetToRealPointer and self.offsetX == 0 and self.offsetY == 0: 399 self.cursor = uiconst.UICURSOR_SELECT 400 else: 401 self.cursor = uiconst.UICURSOR_NONE 402 uicore.uilib.SetCursorPos(newX, newY) 403 uicore.UpdateCursor(self, force=True) 404 405 def ResetFromCenter(self): 406 self.rangeCont.display = False 407 self.HiliteOneButton(None, self.firstLayerCont) 408 self.SelectButton(btn=None) 409 self.ResetSecondLevel() 410 self.firstLayerCont.SetOpacity(1.0) 411 if getattr(self, 'moduleOpacityChanged', False): 412 uicore.layer.shipui.ResetModuleButtonOpacity() 413 self.moduleOpacityChanged = False 414 415 def SetPosition(self): 416 normalX = self.currentCenterX - self.width / 2 417 rightMost = uicore.desktop.width - self.width 418 if normalX > rightMost: 419 left = rightMost 420 self.currentCenterX = rightMost + self.width / 2 421 else: 422 left = normalX 423 left = max(0, left) 424 normalY = self.currentCenterY - self.height / 2 425 bottomMost = uicore.desktop.height - self.height 426 if normalY > bottomMost: 427 top = bottomMost 428 self.currentCenterY = bottomMost + self.height / 2 429 else: 430 top = normalY 431 if getattr(self, 'displayLabelCont', None): 432 minTop = self.displayLabelCont.height + 4 433 else: 434 minTop = 4 435 top = max(minTop, top) 436 self.currentCenterX = max(left + self.width / 2, self.currentCenterX) 437 self.currentCenterY = max(top + self.height / 2, self.currentCenterY) 438 uicore.uilib.SetCursorPos(self.currentCenterX, self.currentCenterY) 439 self.offsetX = 0 440 self.offsetY = 0 441 self.left = left 442 self.top = top 443 444 def CleanUp(self): 445 self.cleanupStarted = True 446 self.state = uiconst.UI_DISABLED 447 self.ResetCursor() 448 if getattr(self, 'blocker', None): 449 self.blocker.Close() 450 self.updateOptionsTimer = None 451 self.displayNameTimer = None 452 self.cleanUpDone = True 453 if getattr(self, 'mouseMoveCookie', None): 454 uicore.event.UnregisterForTriuiEvents(self.mouseMoveCookie) 455 456 def ResetCursor(self): 457 try: 458 self.ResetCursorPosition() 459 uicore.UpdateCursor(uicore.uilib.mouseOver) 460 uicore.uilib.UpdateMouseOver() 461 except Exception as e: 462 self.radialMenuSvc.LogError('Error when resetting the cursor, error = ', e) 463 uicore.uilib.SetCursorPos(uicore.desktop.width / 2, uicore.desktop.height / 2) 464 465 def ResetCursorPosition(self, *args): 466 try: 467 leftPos = max(0, min(uicore.uilib.x + self.offsetX, uicore.desktop.width)) 468 topPos = max(0, min(uicore.uilib.y + self.offsetY, uicore.desktop.height)) 469 uicore.uilib.SetCursorPos(leftPos, topPos) 470 except: 471 uicore.uilib.SetCursorPos(uicore.desktop.width / 2, uicore.desktop.height / 2) 472 473 def _OnClose(self, *args): 474 if not getattr(self, 'cleanUpDone', False): 475 self.CleanUp() 476 sm.GetService('audio').SendUIEvent('ui_radial_close') 477 super(RadialMenu, self)._OnClose(*args) 478 self.clickedObject = None 479 480 def SetRangeCircle(self, degree, percOfAllRange): 481 self.rangeCont.SetRangeCircle(degree, percOfAllRange) 482 if percOfAllRange is None: 483 self.AdjustTextShadow() 484 485 def ResetSecondLevel(self): 486 self.secondLayerCont.display = False 487 self.secondLayerCont.isExpanded = False 488 self.secondLayerCont.expandedButton = None 489 490 def LoadButtons(self, parentLayer, optionsInfo, alternate = False, startingDegree = 0, animate = False, doReset = False): 491 if getattr(self, 'busyReloading', False): 492 return 493 self.busyReloading = True 494 parentLayer.LoadButtons(self.itemID, self.stepSize, alternate, animate, doReset, optionsInfo, startingDegree, self.GetIconTexturePath) 495 self.OnGlobalMove() 496 self.busyReloading = False 497 498 def GetIconTexturePath(self, activeOption, menuOptions = None): 499 return None 500 501 def GetMyActions(self): 502 return None 503 504 def UpdateDisplayName(self): 505 pass 506 507 def UpdateIndicator(self): 508 pass 509 510 def OnSettingsOpened(self): 511 self.KillRadialMenu(None) 512 513 514 class ThreePartContainer(Container): 515 516 def ApplyAttributes(self, attributes): 517 Container.ApplyAttributes(self, attributes) 518 leftTexturePath = attributes.leftTexturePath 519 rightTexturePath = attributes.rightTexturePath 520 centerTexturePath = attributes.centerTexturePath 521 orientation = attributes.get('orientation', 'horizontal') 522 self.sideSize = attributes.sideSize 523 color = attributes.get('color', (0, 0, 0, 0.5)) 524 if orientation == 'vertical': 525 leftSide = Container(parent=self, name='leftSide', height=self.sideSize, align=uiconst.TOTOP, state=uiconst.UI_DISABLED) 526 rightSide = Container(parent=self, name='rightSide', height=self.sideSize, align=uiconst.TOBOTTOM, state=uiconst.UI_DISABLED) 527 else: 528 leftSide = Container(parent=self, name='leftSide', width=self.sideSize, align=uiconst.TOLEFT, state=uiconst.UI_DISABLED) 529 rightSide = Container(parent=self, name='rightSide', width=self.sideSize, align=uiconst.TORIGHT, state=uiconst.UI_DISABLED) 530 leftTexture = Sprite(parent=leftSide, name='leftTexture', pos=(0, 0, 0, 0), texturePath=leftTexturePath, align=uiconst.TOALL, color=color, idx=0) 531 rightTexture = Sprite(parent=rightSide, name='rightTexture', pos=(0, 0, 0, 0), texturePath=rightTexturePath, align=uiconst.TOALL, color=color, idx=0) 532 centerTexture = Sprite(parent=self, name='centerTexture', pos=(0, 0, 0, 0), texturePath=centerTexturePath, align=uiconst.TOALL, color=color) 533 534 def SetCenterSizeAndTop(self, centerWidth, height, top = None): 535 self.width = centerWidth + 2 * self.sideSize 536 self.height = height 537 if top is not None: 538 self.top = top 539 540 541 class RadialMenuSpace(RadialMenu): 542 default_usePreciseRanges = False 543 CLICKCOUNTRESETTIME = 250 544 545 def SetSpecificValues(self, attributes): 546 slimItem = attributes.slimItem 547 self.slimItem = slimItem 548 self.itemID = attributes.itemID 549 self.manyItemsData = attributes.get('manyItemsData', None) 550 self.bookmarkInfo = attributes.get('bookmarkInfo', None) 551 self.typeID = attributes.get('typeID', None) 552 self.siteData = attributes.get('siteData', None) 553 self.SetFallbackDisplayName() 554 555 def SetFallbackDisplayName(self, *args): 556 try: 557 if self.manyItemsData: 558 self.fallBackDisplayName = self.manyItemsData.displayName 559 elif self.siteData: 560 self.fallBackDisplayName = self.siteData.GetName() 561 else: 562 self.fallBackDisplayName = cfg.evelocations.Get(self.itemID).name 563 except: 564 self.fallBackDisplayName = '' 565 566 def LoadMyActions(self, doReset = False, animate = False): 567 self.SetSlimItemAndItemIDIfNeeded() 568 optionsInfo = spaceRadialMenuFunctions.FindRadialMenuOptions(slimItem=self.slimItem, itemID=self.itemID, typeID=self.typeID, bookmarkInfo=self.bookmarkInfo, manyItemsData=self.manyItemsData, siteData=self.siteData, menuType=self.menuType) 569 if optionsInfo is None: 570 return 571 if self.itemID is None and self.slimItem is not None: 572 self.itemID = self.slimItem.itemID 573 self.LoadButtons(self.firstLayerCont, optionsInfo, doReset=doReset) 574 if animate: 575 self.AnimateMenuFromCenter(duration=0.1) 576 577 def LoadSecondLevelActions(self, buttonParent, optionsInfo = None, animate = False): 578 self.SetSlimItemAndItemIDIfNeeded() 579 if not optionsInfo: 580 optionsInfo = self.GetSecondLevelOptions(buttonParent) 581 if optionsInfo is None: 582 return False 583 if self.itemID is None and self.slimItem is not None: 584 self.itemID = self.slimItem.itemID 585 self.secondLayerCont.display = True 586 self.LoadButtons(self.secondLayerCont, optionsInfo, alternate=True, startingDegree=buttonParent.degree, doReset=animate, animate=animate) 587 return True 588 589 def GetSecondLevelOptions(self, buttonParent): 590 if self.itemID is None and self.slimItem is not None: 591 self.itemID = self.slimItem.itemID 592 return spaceRadialMenuFunctions.FindRadialMenuOptions(slimItem=self.slimItem, itemID=self.itemID, typeID=self.typeID, primaryActions=False, bookmarkInfo=self.bookmarkInfo, manyItemsData=self.manyItemsData, siteData=self.siteData, menuType=self.menuType) 593 594 def GetIconTexturePath(self, activeOption, menuOptions = None): 595 texturePath = spaceRadialMenuFunctions.GetIconPath(activeOption) 596 return texturePath 597 598 def MoveMouseRangeCallback(self, usingRangeOption, currentRange = None, percOfAllRange = None): 599 if usingRangeOption: 600 uicore.layer.shipui.ChangeOpacityForRange(currentRange=currentRange) 601 self.moduleOpacityChanged = True 602 elif getattr(self, 'moduleOpacityChanged', False): 603 uicore.layer.shipui.ResetModuleButtonOpacity() 604 self.moduleOpacityChanged = False 605 606 def IsRadialMenuButtonActive(self, *args): 607 return spaceRadialMenuFunctions.IsRadialMenuButtonActive() 608 609 def GetRadialMenuButton(self, *args): 610 actionmenuBtn = settings.user.ui.Get('actionmenuBtn', uiconst.MOUSELEFT) 611 if self.menuType == BROADCAST_RADIAL_MENU: 612 btn = GetSingleMouseBtnBroadcastRadialMenu() 613 if btn: 614 return btn 615 return actionmenuBtn 616 617 def _OnClose(self, *args): 618 if self.clickedObject and hasattr(self.clickedObject, 'HideRadialMenuIndicator'): 619 self.clickedObject.HideRadialMenuIndicator(self.slimItem) 620 RadialMenu._OnClose(self, *args) 621 uicore.layer.shipui.ResetModuleButtonOpacity() 622 uicore.layer.menu.radialMenu = None 623 624 def UpdateDisplayName(self): 625 displayName = '' 626 if self.itemID == session.shipid and self.slimItem: 627 shipCategory = evetypes.GetGroupNameByGroup(self.slimItem.groupID) 628 displayName = localization.GetByLabel('UI/Inflight/ActionButtonsYourShipWithCategory', categoryOfYourShip=shipCategory) 629 elif self.manyItemsData and self.fallBackDisplayName: 630 displayName = self.fallBackDisplayName 631 elif self.slimItem: 632 displayName = uix.GetSlimItemName(self.slimItem) 633 bp = sm.StartService('michelle').GetBallpark() 634 if bp: 635 ball = bp.GetBall(self.itemID) 636 if ball: 637 displayName += ' ' + FmtDist(ball.surfaceDist) 638 elif self.bookmarkInfo: 639 displayName = self.bookmarkInfo.memo 640 displayName = displayName.strip('\t') 641 elif self.fallBackDisplayName: 642 displayName = self.fallBackDisplayName 643 displayName = '<b>%s</b>' % displayName 644 self.SetDisplayName(displayName) 645 646 def SetDisplayName(self, displayName, *args): 647 if displayName != self.displayName: 648 self.displayLabel.text = displayName 649 height = self.displayLabel.textheight + 2 650 centerWidth = self.displayLabel.textwidth 651 self.displayLabelCont.SetCenterSizeAndTop(centerWidth, height) 652 self.displayLabelCont.display = True 653 self.displayName = displayName 654 elif not displayName: 655 self.displayLabelCont.display = False 656 657 def SetSlimItemAndItemIDIfNeeded(self, *args): 658 pass 659 660 def UpdateIndicator(self, *args): 661 if self.clickedObject and hasattr(self.clickedObject, 'ShowRadialMenuIndicator'): 662 self.clickedObject.ShowRadialMenuIndicator(self.slimItem) 663 664 def CloseWithoutActionCallback(self, button): 665 if self.clickedObject is None: 666 return 667 now = blue.os.GetWallclockTime() 668 diff = now - self.creationTime 669 if diff > self.CLICKCOUNTRESETTIME * const.MSEC: 670 return 671 xDistance = self.currentCenterX - self.offsetX - uicore.uilib.x 672 yDistance = self.currentCenterY - self.offsetY - uicore.uilib.y 673 menuButton = self.GetRadialMenuButton() 674 if xDistance != 0 or yDistance != 0: 675 return 676 if menuButton not in (uiconst.MOUSELEFT, uiconst.MOUSERIGHT): 677 return 678 self.blocker.display = False 679 if menuButton == uiconst.MOUSELEFT: 680 uthread.new(self.clickedObject.OnMouseUp, button) 681 uthread.new(self.clickedObject.OnClick) 682 elif menuButton == uiconst.MOUSERIGHT: 683 if uicore.uilib.leftbtn: 684 return 685 if getattr(self.clickedObject, 'GetMenu', None): 686 uthread.new(ShowMenu, self.clickedObject, uicore.uilib.GetAuxMouseOver()) 687 688 689 class RadialMenuSpaceCharacter(RadialMenuSpace): 690 __guid__ = 'uicls.RadialMenuSpaceCharacter' 691 692 def SetSpecificValues(self, attributes): 693 RadialMenuSpace.SetSpecificValues(self, attributes) 694 self.charID = attributes.charID 695 696 def SetSlimItemAndItemIDIfNeeded(self, *args): 697 if self.slimItem is None and self.charID is not None: 698 self.slimItem = SlimItemFromCharID(self.charID) 699 if self.slimItem is not None: 700 self.itemID = self.slimItem.itemID 701 702 def UpdateDisplayName(self): 703 if self.itemID == session.shipid or self.slimItem: 704 return RadialMenuSpace.UpdateDisplayName(self) 705 if self.charID: 706 displayName = '<b>%s' % cfg.eveowners.Get(self.charID).name 707 self.SetDisplayName(displayName) 708 709 710 class RadialMenuInventory(RadialMenuSpace): 711 712 def SetSpecificValues(self, attributes): 713 RadialMenuSpace.SetSpecificValues(self, attributes) 714 self.rec = attributes.rec 715 716 def LoadMyActions(self, doReset = False, animate = False): 717 optionsInfo = inventoryRadialMenuFunctions.FindRadialMenuOptions(itemID=self.itemID, typeID=self.typeID, manyItemsData=self.manyItemsData, rec=self.rec) 718 if optionsInfo is None: 719 return 720 self.LoadButtons(self.firstLayerCont, optionsInfo, doReset=doReset) 721 if animate: 722 self.AnimateMenuFromCenter(duration=0.1) 723 724 def LoadSecondLevelActions(self, buttonParent, optionsInfo = None, animate = False): 725 if not optionsInfo: 726 optionsInfo = self.GetSecondLevelOptions(buttonParent) 727 if optionsInfo is None: 728 return False 729 self.secondLayerCont.display = True 730 self.LoadButtons(self.secondLayerCont, optionsInfo, alternate=True, startingDegree=buttonParent.degree, doReset=animate, animate=animate) 731 return True 732 733 def GetSecondLevelOptions(self, buttonParent): 734 levelType = buttonParent.levelType 735 return inventoryRadialMenuFunctions.FindRadialMenuOptions(itemID=self.itemID, typeID=self.typeID, primaryActions=False, manyItemsData=self.manyItemsData, rec=self.rec, levelType=levelType) 736 737 def GetIconTexturePath(self, activeOption, menuOptions = None): 738 texturePath = inventoryRadialMenuFunctions.GetIconPath(activeOption) 739 return texturePath 740 741 742 RMTEST_SizeInfo = RadialMenuSizeInfo(width=118, height=118, shadowSize=130, rangeSize=50, sliceCount=4, buttonWidth=84, buttonHeight=49, buttonPaddingTop=5, buttonPaddingBottom=5, actionDistance=59) 743 744 class RadialMenuTest(RadialMenu): 745 default_left = 0 746 default_top = 0 747 default_align = uiconst.TOPLEFT 748 default_width = RMTEST_SizeInfo.width 749 default_height = RMTEST_SizeInfo.height 750 sizeInfo = RMTEST_SizeInfo 751 default_showActionText = False 752 753 def LoadMyActions(self, doReset = False, animate = False): 754 optionsInfo = self.GetMyActions() 755 if optionsInfo is None: 756 return 757 self.LoadButtons(self.firstLayerCont, optionsInfo, doReset=doReset) 758 if animate: 759 self.AnimateMenuFromCenter(duration=0.1) 760 761 def GetMyActions(self, *args): 762 inactiveRangeOptions = set() 763 allWantedMenuOptions = [RangeRadialMenuAction(optionPath='UI/Inflight/OrbitObject', rangeList=[1, 2, 3], defaultRange=2, callback=self.Orbit, iconPath='res:/UI/Texture/Icons/44_32_27.png'), 764 SimpleRadialMenuAction(option1='a', func=self.TestA, iconPath='res:/UI/Texture/Icons/44_32_24.png'), 765 SimpleRadialMenuAction(option1='b', func=self.TestB, iconPath='res:/UI/Texture/Icons/44_32_25.png'), 766 SimpleRadialMenuAction(option1='c', func=self.TestC, iconPath='res:/UI/Texture/Icons/44_32_26.png')] 767 activeSingleOptions = {'b': allWantedMenuOptions[1], 768 'c': allWantedMenuOptions[2]} 769 activeRangeOptions = {'UI/Inflight/OrbitObject': allWantedMenuOptions[0]} 770 inactiveSingleOptions = set(('a', 'd')) 771 optionsInfo = RadialMenuOptionsInfo(allWantedMenuOptions=allWantedMenuOptions, activeSingleOptions=activeSingleOptions, inactiveSingleOptions=inactiveSingleOptions, activeRangeOptions=activeRangeOptions, inactiveRangeOptions=inactiveRangeOptions) 772 return optionsInfo 773 774 def TestA(self, *args): 775 print('TestAx') 776 777 def TestB(self, *args): 778 print('~~~~ TestB') 779 780 def TestC(self, *args): 781 print('TestC') 782 783 def TestD(self, *args): 784 print('TestD') 785 786 def GetIconTexturePath(self, activeOption, menuOptions = None, *args): 787 return menuOptions.iconPath 788 789 def Orbit(self, itemID, value, *args): 790 print('value = ', value)