hexes.py (19690B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\charcreation\hexes.py 2 import math 3 import operator 4 import blue 5 import carbonui.const as uiconst 6 import charactercreator.const as ccConst 7 import localization 8 import uthread 9 import utillib 10 from carbon.client.script.environment.AudioUtil import PlaySound 11 from carbonui.primitives.container import Container 12 from carbonui.primitives.sprite import Sprite 13 from carbonui.uianimations import animations 14 from carbonui.uicore import uicore 15 from eve.client.script.ui import eveColor 16 from eve.client.script.ui.login.charcreation.label import CCLabel 17 from player_messaging.client.ui_message import prompt_player_fsd_dialog 18 FILL_MOUSEOVER = 0.1 19 FILL_SELECTION = 0.2 20 TEXT_MOUSEOVER = 0.6 21 TEXT_SELECTION = 1.0 22 TEXT_NORMAL = 0.8 23 24 class CCGenderPicker(Container): 25 default_name = 'CCRacePicker' 26 default_width = 145 27 default_height = 90 28 hexHeight = 64 29 hexWidth = 64 30 31 def ApplyAttributes(self, attributes): 32 Container.ApplyAttributes(self, attributes) 33 self.isActive = 0 34 self.cookie = uicore.event.RegisterForTriuiEvents(uiconst.UI_MOUSEUP, self._OnGlobalMouseUp) 35 self.showText = attributes.showText 36 self.genderID = attributes.genderID 37 self.clickable = attributes.get('clickable', 1) 38 self.disabledHex = attributes.get('disabledHex', []) 39 self.padValue = -16 40 self.padding2 = -int(math.sqrt(math.pow(self.padValue, 2) + math.pow(0.5 * self.padValue, 2))) - 2 41 self.PrepareInfo() 42 self.Setup() 43 44 def Setup(self, *args): 45 self.genderCont = Container(name='genderCont', parent=self, pos=(0, 46 0, 47 200, 48 int(1.5 * self.hexHeight)), align=uiconst.TOPLEFT) 49 self.CreateGenderHex() 50 if self.showText: 51 if self.genderID is not None: 52 if self.genderID: 53 genderText = localization.GetByLabel('UI/Common/Gender/Male') 54 else: 55 genderText = localization.GetByLabel('UI/Common/Gender/Female') 56 text = localization.GetByLabel('UI/CharacterCreation/GenderAndGenderName', genderName=genderText) 57 genderTextCont = Container(name='genderTextCont', parent=self.genderCont, text=text, pos=(0, 58 int(0.5 * (16 + self.hexHeight)), 59 0, 60 self.hexHeight), align=uiconst.TOTOP) 61 CCLabel(parent=genderTextCont, fontsize=12, align=uiconst.CENTERLEFT, text=text, letterspace=1, left=self.hexWidth + 20, bold=0, color=ccConst.COLOR50) 62 63 def CreateGenderHex(self, *args): 64 offsetMap = {0: (0, int(0.5 * (self.hexHeight + self.padValue))), 65 1: (self.hexWidth + self.padding2, 0)} 66 self.AddGenderHex(offsetMap, self.hexWidth, self.hexHeight, self.currentGenderInfo) 67 self.ChangeStateOfAlmostAllConts(self.genderConts, uiconst.UI_HIDDEN, [self.genderID]) 68 self.SelectHex(self.genderConts.get(self.genderID), []) 69 70 def AddGenderHex(self, offsetMap, width, height, genderInfo, state = uiconst.UI_NORMAL, *args): 71 self.genderConts = {} 72 isClickable = self.clickable and 'gender' not in self.disabledHex 73 for i, info in enumerate(genderInfo): 74 id = info.get('genderID', 0) 75 gender = info.get('text', 0) 76 left, top = offsetMap.get(i, (0, 0)) 77 hex = CCHexButtonGender2(name='genderHex', parent=self.genderCont, align=uiconst.TOPLEFT, state=state, pos=(left, 78 top, 79 width, 80 height), pickRadius=int(height / 2.0), info=info, id=id, hexName=gender, func=self.OnGenderClicked, iconNum=id, clickable=isClickable) 81 self.genderConts[id] = hex 82 83 def OnHexMouseOver(self, cont, *args): 84 sm.StartService('audio').SendUIEvent(unicode('ui_icc_button_mouse_over_play')) 85 if getattr(cont, 'frame', None) is not None: 86 cont.frame.state = uiconst.UI_DISABLED 87 88 def OnHexMouseExit(self, cont, *args): 89 if getattr(cont, 'frame', None) is not None: 90 cont.frame.state = uiconst.UI_HIDDEN 91 92 def _AnimateHexList(self, containerList, time = 100.0, attribute = 'left'): 93 containerList.sort(key=operator.attrgetter(attribute)) 94 for cont in containerList: 95 cont.state = uiconst.UI_NORMAL 96 blue.pyos.synchro.SleepWallclock(time) 97 98 def SelectHex(self, cont, allConts): 99 sm.StartService('audio').SendUIEvent(unicode('ui_icc_button_mouse_down_play')) 100 for c in allConts: 101 c.normalCont.state = uiconst.UI_DISABLED 102 c.selection.state = uiconst.UI_HIDDEN 103 104 self.SetSelectionState(cont, on=0) 105 106 def PrepareInfo(self, *args): 107 self.currentGenderInfo = [utillib.KeyVal(genderID=0, text=localization.GetByLabel('UI/Common/Gender/Female')), utillib.KeyVal(genderID=1, text=localization.GetByLabel('UI/Common/Gender/Male'))] 108 self.RearrangeInfo(self.genderID, 'genderID', self.currentGenderInfo) 109 110 def RearrangeInfo(self, id, what, info, *args): 111 selectedIdx = None 112 for i, each in enumerate(info): 113 if getattr(each, what, '') == id: 114 selectedIdx = i 115 break 116 117 if selectedIdx is not None: 118 currentPick = info[selectedIdx] 119 oldPick = info[0] 120 info[selectedIdx] = oldPick 121 info[0] = currentPick 122 123 def OnGenderClicked(self, cont, *args): 124 info = uicore.layer.charactercreation.controller.GetInfo() 125 if not self.clickable: 126 return 127 newGenderID = cont.info.get('genderID', 0) 128 if newGenderID == self.genderID: 129 self.ClickingOnCurrent(self.genderID, cont, self.genderConts, what=['gender']) 130 else: 131 dnaLog = uicore.layer.charactercreation.controller.GetDollDNAHistory() 132 if dnaLog and len(dnaLog) > 1: 133 if prompt_player_fsd_dialog('CharCreationLoseChangeGender', {}, uiconst.YESNO) != uiconst.ID_YES: 134 return 135 self.isActive = 1 136 self.Disable() 137 self.SwitchGender(newGenderID) 138 self.Enable() 139 140 def SwitchGender(self, newGenderID, *args): 141 uicore.layer.charactercreation.controller.FadeToBlack(why=localization.GetByLabel('UI/Common/Loading')) 142 sm.GetService('character').StopEditing() 143 self.genderID = newGenderID 144 self.genderCont.Flush() 145 self.RearrangeInfo(self.genderID, 'genderID', self.currentGenderInfo) 146 self.CreateGenderHex() 147 self.SelectHex(self.genderConts.get(self.genderID), []) 148 info = uicore.layer.charactercreation.controller.GetInfo() 149 sm.GetService('character').RemoveCharacter(info.charID) 150 uicore.layer.charactercreation.controller.AddCharacter(info.charID, info.bloodlineID, info.raceID, newGenderID) 151 uicore.layer.charactercreation.controller.SelectGender(self.genderID, check=0) 152 uicore.layer.charactercreation.controller.ClearPortraitInfo() 153 uicore.layer.charactercreation.controller.characterSvc.characterMetadata[info.charID]['genderID'] = self.genderID 154 uicore.layer.charactercreation.controller.gender_changed = True 155 uicore.layer.charactercreation.controller.StartEditMode(mode='sculpt', resetAll=True) 156 if hasattr(uicore.layer.charactercreation.controller.step, 'LoadFaceMode'): 157 uthread.new(uicore.layer.charactercreation.controller.step.LoadFaceMode) 158 uicore.layer.charactercreation.controller.FadeFromBlack() 159 160 def ClickingOnCurrent(self, id, cont, allConts, animate = False, what = [], *args): 161 self.isActive = 1 162 expanded = getattr(cont, 'expanded', 0) 163 if expanded: 164 opacity = 1.0 165 selectionOn = 0 166 else: 167 opacity = 0.3 168 selectionOn = 1 169 cont.opacity = 1.0 170 self.SetSelectionState(cont, on=selectionOn) 171 self.ChangeHexOpacity(self.GetMainHexes(exceptWhat=what).values(), opacity=opacity) 172 newState = [uiconst.UI_NORMAL, uiconst.UI_HIDDEN][expanded] 173 self.ChangeStateOfAlmostAllConts(allConts, newState, [id], animate=True) 174 cont.expanded = not expanded 175 176 def GetMainHexes(self, exceptWhat = [], *args): 177 mainHexes = {text:cont for text, cont in [('gender', self.genderConts.get(self.genderID, None))] if text not in exceptWhat} 178 return mainHexes 179 180 def ChangeStateOfAlmostAllConts(self, allConts, newState, exceptIDs = [], animate = False): 181 changed = [] 182 doAnimation = animate and newState == uiconst.UI_NORMAL 183 for id, cont in allConts.iteritems(): 184 if id in exceptIDs: 185 if newState == uiconst.UI_HIDDEN: 186 cont.expanded = False 187 continue 188 if not doAnimation: 189 cont.state = newState 190 changed.append(cont) 191 192 if doAnimation: 193 self.AnimateHexes(changed) 194 return changed 195 196 def AnimateHexes(self, changedConts, *args): 197 for cont in changedConts: 198 cont.state = uiconst.UI_HIDDEN 199 200 uthread.new(self._AnimateHexesThread, changedConts, attribute='top') 201 202 def _AnimateHexesThread(self, changedConts, attribute, time = 100.0, *args): 203 self._AnimateHexList(changedConts, time=time, attribute=attribute) 204 205 def SetSelectionState(self, cont, on = 1): 206 if not cont: 207 return 208 if on: 209 cont.normalCont.state = uiconst.UI_HIDDEN 210 cont.selection.state = uiconst.UI_DISABLED 211 else: 212 cont.normalCont.state = uiconst.UI_DISABLED 213 cont.selection.state = uiconst.UI_HIDDEN 214 215 def CloseAllExtraHexes(self, *args): 216 self.ChangeStateOfAlmostAllConts(self.genderConts, uiconst.UI_HIDDEN, [self.genderID], animate=False) 217 self.ChangeHexOpacity(self.GetMainHexes().values(), opacity=1.0) 218 219 def Disable(self, *args): 220 self.state = uiconst.UI_DISABLED 221 self.opacity = 0.3 222 223 def Enable(self, *args): 224 self.state = uiconst.UI_PICKCHILDREN 225 self.opacity = 1.0 226 self.ChangeHexOpacity(self.GetMainHexes().values(), opacity=1.0) 227 228 def ChangeHexOpacity(self, hexes, opacity = 1.0): 229 for h in hexes: 230 h.opacity = opacity 231 self.SetSelectionState(h, 0) 232 233 def _OnGlobalMouseUp(self, obj, *args): 234 if self.isActive and not isinstance(obj, CCHexButtonMedium): 235 self.CloseAllExtraHexes() 236 self.isActive = False 237 return 1 238 239 def _OnClose(self, *args): 240 uicore.event.UnregisterForTriuiEvents(self.cookie) 241 242 243 class CCHexButtonMedium(Container): 244 texture_0 = 'res:/UI/Texture/CharacterCreation/hexes/bloodlines.dds' 245 textureInv_0 = 'res:/UI/Texture/CharacterCreation/hexes/bloodlinesInverted.dds' 246 frameTexture = 'res:/UI/Texture/CharacterCreation/hexes/mediumHexFrame.dds' 247 bgTexture = 'res:/UI/Texture/CharacterCreation/hexes/mediumHexBg.dds' 248 bevelTexture = 'res:/UI/Texture/CharacterCreation/hexes/mediumHexBevel.dds' 249 shawdowTexture = 'res:/UI/Texture/CharacterCreation/hexes/mediumHexShadow.dds' 250 numColumns = 4 251 hexPadWidth = 0 252 hexPadHeight = 0 253 wInterval = 64 254 hInterval = 64 255 rectW = 64 256 rectH = 64 257 shadowOffset = 1 258 259 def ApplyAttributes(self, attributes): 260 Container.ApplyAttributes(self, attributes) 261 self.hint = self.hexName = attributes.hexName or '' 262 self.info = attributes.info 263 self.func = attributes.func 264 self.id = attributes.id 265 self.iconNum = attributes.iconNum 266 self.showIcon = attributes.get('showIcon', 1) 267 self.clickable = attributes.get('clickable', 1) 268 self.showBg = self.clickable 269 self.SetupHex() 270 271 def SetupHex(self, *args): 272 textureNum, logoLocation = self.GetLogoLocation() 273 normalCont = Container(name='normal', parent=self, align=uiconst.TOALL, state=uiconst.UI_DISABLED) 274 if self.showBg: 275 sprite = Sprite(name='normalBg', parent=normalCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=self.bgTexture, padding=(-self.hexPadWidth, 276 -self.hexPadHeight, 277 -self.hexPadWidth, 278 -self.hexPadHeight)) 279 sprite.SetRGBA(0.35, 0.35, 0.35, 0.3) 280 sprite = Sprite(name='normalBevel', parent=normalCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=self.bevelTexture, padding=(-self.hexPadWidth, 281 -self.hexPadHeight, 282 -self.hexPadWidth, 283 -self.hexPadHeight)) 284 sprite.SetAlpha(0.2) 285 self.bevel = sprite 286 if self.showIcon: 287 sprite = Sprite(name='normalIcon', parent=normalCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=getattr(self, 'texture_%s' % textureNum, '')) 288 sprite.rectLeft, sprite.rectTop, sprite.rectWidth, sprite.rectHeight = logoLocation 289 sprite.SetAlpha(1.0) 290 self.logo = sprite 291 shadowOffset = getattr(self, 'shadowOffset', 3) 292 sprite = Sprite(name='normalShadow', parent=normalCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=getattr(self, 'texture_%s' % textureNum, ''), padding=(shadowOffset, 293 shadowOffset, 294 -shadowOffset, 295 -shadowOffset)) 296 sprite.rectLeft, sprite.rectTop, sprite.rectWidth, sprite.rectHeight = logoLocation 297 sprite.SetRGBA(0.0, 0.0, 0.0, 0.3) 298 self.normalCont = normalCont 299 name = '%sFrame' % self.hexName 300 sprite = Sprite(name=name, parent=self, align=uiconst.TOALL, state=uiconst.UI_HIDDEN, texturePath=self.frameTexture, padding=(-self.hexPadWidth, 301 -self.hexPadHeight, 302 -self.hexPadWidth, 303 -self.hexPadHeight)) 304 sprite.SetAlpha(0.2) 305 self.frame = sprite 306 name = '%sSelection' % self.hexName 307 selectionCont = Container(name='selectionCont', parent=self, align=uiconst.TOALL, state=uiconst.UI_HIDDEN) 308 sprite = Sprite(name=name, parent=selectionCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=getattr(self, 'textureInv_%s' % textureNum, '')) 309 sprite.rectLeft, sprite.rectTop, sprite.rectWidth, sprite.rectHeight = logoLocation 310 sprite = Sprite(name=name, parent=selectionCont, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=getattr(self, 'textureInv_%s' % textureNum, ''), padding=(2, 2, -2, -2)) 311 sprite.rectLeft, sprite.rectTop, sprite.rectWidth, sprite.rectHeight = logoLocation 312 sprite.SetRGBA(0.0, 0.0, 0.0, 0.3) 313 self.selection = selectionCont 314 if self.showBg: 315 sprite = Sprite(name='shadow', parent=self, align=uiconst.TOALL, state=uiconst.UI_DISABLED, texturePath=self.shawdowTexture, padding=(-self.hexPadWidth, 316 -self.hexPadHeight, 317 -self.hexPadWidth, 318 -self.hexPadHeight)) 319 sprite.SetAlpha(0.5) 320 321 def OnClick(self, *args): 322 if not self.clickable: 323 return 324 if self.func: 325 self.func(self) 326 327 def OnMouseEnter(self, *args): 328 if not self.clickable: 329 return 330 PlaySound('ui_icc_button_mouse_over_play') 331 if getattr(self, 'frame', None) is not None: 332 self.frame.state = uiconst.UI_DISABLED 333 if getattr(self, 'bevel', None) is not None: 334 self.bevel.SetAlpha(0.5) 335 336 def OnMouseExit(self, *args): 337 if not self.clickable: 338 return 339 if getattr(self, 'frame', None) is not None: 340 self.frame.state = uiconst.UI_HIDDEN 341 if getattr(self, 'bevel', None) is not None: 342 self.bevel.SetAlpha(0.2) 343 344 def SelectHex(self, allConts = []): 345 PlaySound('ui_icc_button_mouse_down_play') 346 for c in allConts: 347 c.normalCont.state = uiconst.UI_DISABLED 348 c.frame.state = uiconst.UI_HIDDEN 349 c.selection.state = uiconst.UI_HIDDEN 350 351 self.normalCont.state = uiconst.UI_HIDDEN 352 self.selection.state = uiconst.UI_DISABLED 353 354 def GetLogoLocation(self, *args): 355 iconNum = self.iconNum 356 numInFile = pow(self.numColumns, 2) 357 textureNum = iconNum / numInFile 358 newIconNum = iconNum - numInFile * textureNum 359 j = newIconNum / self.numColumns 360 i = newIconNum % self.numColumns 361 leftOffset = getattr(self, 'leftOffset', 0) 362 topOffset = getattr(self, 'topOffset', 0) 363 top = topOffset + j * self.hInterval 364 left = leftOffset + i * self.wInterval 365 return (textureNum, (left, 366 top, 367 self.rectW, 368 self.rectH)) 369 370 371 class CCHexButtonRace2(CCHexButtonMedium): 372 texture_0 = 'res:/UI/Texture/CharacterCreation/hexes/smallRaceGenderHexes.dds' 373 textureInv_0 = 'res:/UI/Texture/CharacterCreation/hexes/smallRaceGenderHexesInverted.dds' 374 frameTexture = 'res:/UI/Texture/CharacterCreation/hexes/mediumHexFrame.dds' 375 bgTexture = 'res:/UI/Texture/CharacterCreation/hexes/mediumHexBg.dds' 376 topOffset = 64 377 378 379 class CCHexButtonGender2(CCHexButtonMedium): 380 texture_0 = 'res:/UI/Texture/CharacterCreation/hexes/smallRaceGenderHexes.dds' 381 textureInv_0 = 'res:/UI/Texture/CharacterCreation/hexes/smallRaceGenderHexesInverted.dds' 382 383 384 class CCHexButtonAncestry(CCHexButtonMedium): 385 texture_0 = 'res:/UI/Texture/CharacterCreation/hexes/ancestries1.dds' 386 textureInv_0 = 'res:/UI/Texture/CharacterCreation/hexes/ancestriesInverted1.dds' 387 texture_1 = 'res:/UI/Texture/CharacterCreation/hexes/ancestries2.dds' 388 textureInv_1 = 'res:/UI/Texture/CharacterCreation/hexes/ancestriesInverted2.dds' 389 texture_2 = 'res:/UI/Texture/CharacterCreation/hexes/ancestries3.dds' 390 textureInv_2 = 'res:/UI/Texture/CharacterCreation/hexes/ancestriesInverted3.dds' 391 392 393 class CCHexButtonSchool(CCHexButtonMedium): 394 texture_0 = 'res:/UI/Texture/CharacterCreation/hexes/ancestries3.dds' 395 textureInv_0 = 'res:/UI/Texture/CharacterCreation/hexes/ancestriesInverted3.dds' 396 topOffset = 192 397 leftOffset = 64 398 399 400 class CCHexButtonHead(CCHexButtonMedium): 401 texture_0 = '' 402 textureInv_0 = 'res:/UI/Texture/CharacterCreation/headPickerBG.dds' 403 frameTexture = 'res:/UI/Texture/CharacterCreation/headPickerFrame.dds' 404 bgTexture = 'res:/UI/Texture/CharacterCreation/headPickerBG.dds' 405 bevelTexture = 'res:/UI/Texture/CharacterCreation/headPickerBevel.dds' 406 shawdowTexture = 'res:/UI/Texture/CharacterCreation/headPickerShadow.dds' 407 numColumns = 1 408 shadowOffset = 0 409 410 411 class CCHexButtonBody(CCHexButtonMedium): 412 texture_0 = '' 413 textureInv_0 = 'res:/UI/Texture/CharacterCreation/bodyPickerBG.dds' 414 frameTexture = 'res:/UI/Texture/CharacterCreation/bodyPickerFrame.dds' 415 bgTexture = 'res:/UI/Texture/CharacterCreation/bodyPickerBG.dds' 416 bevelTexture = 'res:/UI/Texture/CharacterCreation/bodyPickerBevel.dds' 417 shawdowTexture = 'res:/UI/Texture/CharacterCreation/bodyPickerShadow.dds' 418 numColumns = 1 419 shadowOffset = 0 420 wInterval = 128 421 hInterval = 128 422 rectW = 128 423 rectH = 128 424 425 426 class CCHexButtonRandomize(CCHexButtonMedium): 427 __guid__ = 'uicls.CCHexButtonRandomize' 428 texture_0 = 'res:/UI/Texture/CharacterCreation/randomize_arrows.png' 429 numColumns = 1 430 431 def ApplyAttributes(self, attributes): 432 super(CCHexButtonRandomize, self).ApplyAttributes(attributes) 433 self.logo.padding = 5 434 self.logo.SetRGBA(*eveColor.PRIMARY_BLUE) 435 436 def StartBlinking(self): 437 animations.BlinkIn(self.logo, startVal=0.5, endVal=1.2, duration=1.2, loops=-1, curveType=uiconst.ANIM_WAVE) 438 439 def StopBlinking(self): 440 self.logo.StopAnimations() 441 self.logo.opacity = 1.0