radialMenuActions.py (14409B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\radialMenu\radialMenuActions.py 2 import math 3 import types 4 from carbonui.primitives.sprite import Sprite 5 from eve.client.script.ui.control.glowSprite import GlowSprite 6 from eve.client.script.ui.control.themeColored import SpriteThemeColored 7 import carbonui.const as uiconst 8 import localization 9 from carbonui.primitives.transform import Transform 10 import telemetry 11 from carbonui.uicore import uicore 12 from eve.client.script.ui.shared.radialMenu import BROADCAST_RADIAL_MENU 13 from eve.client.script.ui.shared.radialMenu.broadcastRadialMenuFunctions import GetBroadcastMenuColor 14 15 class RadialMenuActionBase(Transform): 16 default_left = 0 17 default_top = 0 18 default_align = uiconst.CENTERTOP 19 default_state = uiconst.UI_NORMAL 20 moveOverSliceBasePath = 'res:/UI/Texture/classes/RadialMenu/mouseOver_%s.png' 21 selelectedBasePath = 'res:/UI/Texture/classes/RadialMenu/selected_%s.png' 22 emptySliceBasePath = 'res:/UI/Texture/classes/RadialMenu/emptySlice_%s.png' 23 sliceBasePath = 'res:/UI/Texture/classes/RadialMenu/slice_%s.png' 24 default_width = 100 25 default_height = 70 26 default_fullWidth = default_width 27 default_fullHeight = default_height 28 29 def ApplyAttributes(self, attributes): 30 Transform.ApplyAttributes(self, attributes) 31 self.degree = attributes.get('degree', 0) 32 self.func = None 33 self.funcArgs = None 34 self.itemID = attributes.itemID 35 self.isDisabled = False 36 self.degreeWidth = attributes.degreeWidth 37 self.labelPath = '' 38 self.labelText = '' 39 self.isEmpty = attributes.get('isEmpty', False) 40 self.commandName = None 41 self.isHilighted = False 42 self.fullWidth = attributes.sizeInfo.buttonWidth 43 self.fullHeight = attributes.sizeInfo.buttonHeight 44 iconPar = Transform(parent=self, name='iconPar', pos=(0, 3, 32, 32), state=uiconst.UI_DISABLED, align=uiconst.CENTER) 45 iconPar.rotation = math.radians(self.degree) 46 self.icon = GlowSprite(parent=iconPar, name='icon', pos=(0, 0, 32, 32), state=uiconst.UI_DISABLED, align=uiconst.CENTER) 47 if attributes.menuType == BROADCAST_RADIAL_MENU: 48 color = GetBroadcastMenuColor() 49 else: 50 color = SpriteThemeColored.default_fixedColor 51 selectionSlice = SpriteThemeColored(parent=self, name='selectionSlice', state=uiconst.UI_DISABLED, texturePath=self.selelectedBasePath % self.degreeWidth, align=uiconst.TOALL, opacity=0.9, color=color) 52 selectionSlice.display = False 53 self.selectionSlice = selectionSlice 54 if self.isEmpty: 55 sliceTexturePath = self.emptySliceBasePath % self.degreeWidth 56 else: 57 sliceTexturePath = self.sliceBasePath % self.degreeWidth 58 self.hilite = SpriteThemeColored(parent=self, name='hilite', state=uiconst.UI_DISABLED, texturePath=self.selelectedBasePath % self.degreeWidth, align=uiconst.TOALL, colorType=uiconst.COLORTYPE_UIHILIGHTGLOW, opacity=0.0) 59 self.availableSlice = SpriteThemeColored(parent=self, name='availableSlice', state=uiconst.UI_DISABLED, texturePath=sliceTexturePath, align=uiconst.TOALL, opacity=attributes.get('buttonBackgroundOpacity', 0.8), color=color) 60 self.unavailableSlice = SpriteThemeColored(parent=self, name='unavailableSlice', state=uiconst.UI_DISABLED, texturePath=sliceTexturePath, align=uiconst.TOALL, colorType=uiconst.COLORTYPE_UIBASE, opacity=0.85) 61 self.unavailableSlice.display = False 62 self.sliceInUse = self.availableSlice 63 64 def SetButtonInfo(self, labelPath, labelArgs, buttonInfo = None, isEnabled = True, iconTexturePath = None): 65 self.labelPath = labelPath 66 if isEnabled: 67 self.labelText = localization.GetByLabel(labelPath, **labelArgs) 68 else: 69 self.labelText = '' 70 self.name = 'actionButton_%s' % labelPath.split('/')[-1] 71 if isEnabled: 72 self.SetEnabled() 73 else: 74 self.SetDisabled() 75 if iconTexturePath is not None: 76 self.SetIcon(iconTexturePath) 77 if buttonInfo is None: 78 return 79 buttonFunc = buttonInfo.func 80 buttonFuncArgs = buttonInfo.funcArgs 81 if not isinstance(buttonFunc, (types.MethodType, types.LambdaType)): 82 return 83 self.func = buttonFunc 84 self.funcArgs = buttonFuncArgs 85 self.commandName = getattr(buttonInfo, 'commandName', None) 86 87 @telemetry.ZONE_METHOD 88 def ShowButtonHilite(self): 89 if self.isHilighted: 90 return 91 uicore.animations.FadeTo(self.hilite, self.hilite.opacity, 0.15, duration=uiconst.TIME_ENTRY) 92 self.isHilighted = True 93 sm.GetService('audio').SendUIEvent('ui_radial_mouseover_play') 94 self.icon.OnMouseEnter() 95 96 @telemetry.ZONE_METHOD 97 def HideButtonHilite(self): 98 if not self.isHilighted: 99 return 100 uicore.animations.FadeTo(self.hilite, self.hilite.opacity, 0.0, duration=uiconst.TIME_EXIT) 101 self.isHilighted = False 102 self.sliceInUse.Show() 103 if self.isDisabled: 104 self.icon.opacity = 0.4 105 else: 106 self.icon.opacity = 1.0 107 self.icon.OnMouseExit() 108 109 def ShowSelectionSlice(self): 110 self.availableSlice.display = False 111 self.unavailableSlice.display = False 112 self.selectionSlice.display = True 113 114 def SetIcon(self, texturePath): 115 self.icon.SetTexturePath(texturePath) 116 117 def SetDisabled(self): 118 if self.sliceInUse != self.unavailableSlice: 119 self.sliceInUse = self.unavailableSlice 120 self.availableSlice.display = False 121 self.unavailableSlice.display = True 122 self.isDisabled = True 123 self.icon.opacity = 0.4 124 125 def SetEnabled(self): 126 if self.sliceInUse != self.availableSlice: 127 self.sliceInUse = self.availableSlice 128 self.unavailableSlice.display = False 129 self.availableSlice.display = True 130 self.isDisabled = False 131 self.icon.opacity = 1.0 132 133 def AnimateSize(self, sizeRatio = 0.5, duration = 0.5, grow = True): 134 if grow: 135 startHeight = sizeRatio * self.fullHeight 136 startWidth = sizeRatio * self.fullWidth 137 endHeight = self.fullHeight 138 endWidth = self.fullWidth 139 else: 140 startHeight = self.height 141 startWidth = self.width 142 endHeight = sizeRatio * self.fullHeight 143 endWidth = sizeRatio * self.fullWidth 144 uicore.animations.MorphScalar(self, 'height', startVal=startHeight, endVal=endHeight, duration=duration) 145 uicore.animations.MorphScalar(self, 'width', startVal=startWidth, endVal=endWidth, duration=duration) 146 147 def SelectButtonSlice(self, duration = 0.5): 148 self.ShowSelectionSlice() 149 curvePoints = ([0.0, 0], [0.5, -10], [1, -10]) 150 uicore.animations.MorphScalar(self, 'top', duration=duration, curveType=curvePoints, sleep=False) 151 curvePoints = ([0.0, self.selectionSlice.opacity], 152 [0.5, self.selectionSlice.opacity], 153 [0.6, 1.5], 154 [0.7, 0.5], 155 [0.8, 1.5], 156 [1, 0]) 157 uicore.animations.MorphScalar(self, 'opacity', duration=duration, curveType=curvePoints, sleep=True) 158 159 160 class RadialMenuAction(RadialMenuActionBase): 161 162 def OnButtonClick(self): 163 if self.func: 164 if self.funcArgs and isinstance(self.funcArgs[0], tuple) and isinstance(self.funcArgs[0][0], (types.MethodType, types.LambdaType)): 165 self.func(*self.funcArgs[0]) 166 else: 167 self.func(*(self.funcArgs or [])) 168 return True 169 return False 170 171 172 class RadialMenuRangeAction(RadialMenuActionBase): 173 174 def ApplyAttributes(self, attributes): 175 RadialMenuActionBase.ApplyAttributes(self, attributes) 176 self.rangeList = attributes.rangeList 177 self.defaultRange = attributes.defaultRange 178 self.percOfAllRange = None 179 self.currentRange = self.defaultRange 180 self.minRangeDistance = attributes.sizeInfo.actionDistance 181 self.actionButtonTopPadding = attributes.get('actionButtonTopPadding', 0) 182 self.usePreciseRanges = attributes.get('usePreciseRanges', True) 183 self.maxRangeDistance = 300 184 self.lastLength = None 185 self.rangeArrow = Sprite(parent=self, name='rangeArrow', pos=(0, 186 self.actionButtonTopPadding + 1, 187 18, 188 12), state=uiconst.UI_DISABLED, align=uiconst.CENTERTOP, texturePath='res:/UI/Texture/classes/RadialMenu/rangeArrow.png', idx=0) 189 190 def SetEnabled(self): 191 RadialMenuActionBase.SetEnabled(self) 192 self.rangeArrow.opacity = 1.0 193 194 def SetDisabled(self): 195 RadialMenuActionBase.SetDisabled(self) 196 self.rangeArrow.opacity = 0.4 197 198 def MoveMouse(self, length, currentDegree): 199 if self.isDisabled: 200 self.currentRange = None 201 self.percOfAllRange = None 202 return (self.currentRange, self.percOfAllRange) 203 if length < self.minRangeDistance - self.actionButtonTopPadding: 204 self.currentRange = self.defaultRange 205 self.percOfAllRange = None 206 return (self.currentRange, self.percOfAllRange) 207 numRangeOptions = len(self.rangeList) 208 lengthInEachStep = float((self.maxRangeDistance - self.minRangeDistance) / numRangeOptions) 209 lengthInRangeMeasurer = length - self.minRangeDistance 210 lengthInRangeMeasurer = self.FindLengthToUse(lengthInRangeMeasurer, currentDegree) 211 for i, eachRange in enumerate(self.rangeList): 212 lengthForThisStep = i * lengthInEachStep 213 if lengthInRangeMeasurer > lengthForThisStep: 214 continue 215 if i == 0: 216 self.currentRange = eachRange 217 self.percOfAllRange = 0 218 return (self.currentRange, self.percOfAllRange) 219 lengthForPreviousStep = lengthInEachStep * (i - 1) 220 previousStepDistance = self.rangeList[i - 1] 221 lengthInThisStep = lengthInRangeMeasurer - lengthForPreviousStep 222 percOfStep = float(lengthInThisStep) / lengthInEachStep 223 if self.usePreciseRanges: 224 currentRange = percOfStep * (eachRange - previousStepDistance) + previousStepDistance 225 else: 226 currentRange = previousStepDistance 227 percOfEachStep = 1.0 / (numRangeOptions - 1) 228 percOfAllRange = (i - 1 + percOfStep) * percOfEachStep 229 self.currentRange = currentRange 230 self.percOfAllRange = percOfAllRange 231 return (currentRange, self.percOfAllRange) 232 else: 233 self.currentRange = self.rangeList[-1] 234 return (self.currentRange, 1) 235 236 def FindLengthToUse(self, length, currentDegree): 237 if self.lastLength is None: 238 self.lastLength = length 239 halfDegreeWidth = self.degreeWidth / 2.0 240 if not self.degree - halfDegreeWidth < currentDegree < self.degree + halfDegreeWidth: 241 dx, dy = uicore.uilib.dx, uicore.uilib.dy 242 if 90 < self.degree < 270: 243 length = self.lastLength + dy 244 else: 245 length = self.lastLength - dy 246 length = max(0, length) 247 self.lastLength = length 248 return length 249 250 def OnButtonClick(self): 251 if self.func and self.currentRange is not None: 252 self.func(self.funcArgs, self.currentRange, self.percOfAllRange) 253 254 255 class RadialMenuActioSecondLevel(RadialMenuActionBase): 256 257 def ApplyAttributes(self, attributes): 258 RadialMenuActionBase.ApplyAttributes(self, attributes) 259 self.icon.SetTexturePath(attributes.texturePath) 260 self.hasExtraOptions = attributes.hasExtraOptions 261 self.levelType = attributes.levelType 262 263 def MoveMouse(self, length, currentDegree): 264 return True 265 266 267 class ActionParent(Transform): 268 default_align = uiconst.CENTER 269 default_name = 'radialmenuActionParent' 270 271 def ApplyAttributes(self, attributes): 272 Transform.ApplyAttributes(self, attributes) 273 degree = attributes.degree 274 radians = math.radians(degree) 275 self.rotation = -radians 276 self.actionDistance = attributes.sizeInfo.actionDistance 277 self.degree = degree 278 279 def SetButtonInfo(self, menuOptions, buttonInfo, isEnabled, iconTexturePath): 280 activeOption = menuOptions.activeOption 281 labelArgs = getattr(menuOptions, 'labelArgs', {}) 282 self.actionButton.SetButtonInfo(activeOption, labelArgs, buttonInfo, isEnabled=isEnabled, iconTexturePath=iconTexturePath) 283 284 def SetDisabledIcon(self, texturePath): 285 self.actionButton.SetIcon(texturePath=texturePath) 286 self.actionButton.SetDisabled() 287 288 def SetIconOffset(self, iconOffset): 289 self.actionButton.icon.parent.top = iconOffset 290 291 292 class ActionButtonParent(ActionParent): 293 294 def ApplyAttributes(self, attributes): 295 ActionParent.ApplyAttributes(self, attributes) 296 actionButton = RadialMenuAction(parent=self, name='actionButton', sizeInfo=attributes.sizeInfo, degree=attributes.degree, isEmpty=attributes.isEmpty, buttonBackgroundOpacity=attributes.buttonBackgroundOpacity, menuType=attributes.menuType, **attributes.actionKeywords) 297 self.actionButton = actionButton 298 299 300 class RangeActionButtonParent(ActionParent): 301 302 def ApplyAttributes(self, attributes): 303 ActionParent.ApplyAttributes(self, attributes) 304 actionButton = RadialMenuRangeAction(parent=self, name='rangeButton', sizeInfo=attributes.sizeInfo, degree=attributes.degree, actionButtonTopPadding=attributes.sizeInfo.buttonPaddingTop, usePreciseRanges=attributes.usePreciseRanges, buttonBackgroundOpacity=attributes.buttonBackgroundOpacity, **attributes.actionKeywords) 305 self.actionButton = actionButton 306 307 308 class SecondLevelButtonParent(ActionParent): 309 default_name = 'secondLevelButtonParent' 310 311 def ApplyAttributes(self, attributes): 312 ActionParent.ApplyAttributes(self, attributes) 313 self.levelType = attributes.actionKeywords['levelType'] 314 actionButton = RadialMenuActioSecondLevel(parent=self, name='secondLevelButton', sizeInfo=attributes.sizeInfo, degree=attributes.degree, buttonBackgroundOpacity=attributes.buttonBackgroundOpacity, **attributes.actionKeywords) 315 self.actionButton = actionButton