NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

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)