characterCreationContainer.py (117540B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\characterCreationContainer.py 2 import copy 3 import math 4 import random 5 import time 6 import types 7 import blue 8 import geo2 9 import mathext 10 import telemetry 11 import carbonui.const as uiconst 12 import charactercreator.client.animparams as animparams 13 import charactercreator.client.characterCreationMetrics as ccm 14 import charactercreator.client.scalingUtils as ccScalingUtils 15 import charactercreator.const as ccConst 16 import eve.client.script.ui.login.charcreation.ccUtil as ccUtil 17 import eve.common.lib.appConst as const 18 import evegraphics.settings as gfxsettings 19 import everesourceprefetch 20 import gatekeeper 21 import localization 22 import log 23 import paperdoll 24 import utillib 25 from carbonui import Density 26 from carbonui.control.button import Button 27 from carbonui.primitives.fill import Fill 28 from carbonui.util.bunch import Bunch 29 from eve.client.script.ui.control.eveLoadingWheel import LoadingWheel 30 from eve.common.script.paperDoll.paperDollDefinitions import BODY_CATEGORIES, DEFAULT_NUDE_PARTS, DESIRED_ORDER, LOD_SKIN 31 from eve.common.script.util import paperDollUtil 32 import trinity 33 import uthread 34 from carbon.client.script.environment.AudioUtil import PlaySound 35 from carbonui.primitives.container import Container 36 from carbonui.primitives.gradientSprite import GradientSprite 37 from carbonui.primitives.sprite import Sprite 38 from carbonui.uianimations import animations 39 from carbonui.uicore import uicore 40 from charactercreator.client.characterCreationSteps import ModeStorage, GetStepOrder, GetStepsUpToAndIncluding, STEP_ORDER_LIST 41 from charactercreator.client.logging.stepLogger import StepLogger 42 from eve.client.script.ui.camera.charCreationCamera import CharCreationCamera 43 from carbonui.control.buttonIcon import ButtonIcon 44 from eve.client.script.ui.login.charcreation.charCreationButtons import EXIT_BUTTON_SIZE 45 from eve.client.script.ui.login.charcreation.empireStepContainer import EmpireStepContainer 46 from eve.client.script.ui.login.charcreation.portraitMaker import PortraitMaker 47 from eve.client.script.ui.login.charcreation.charCreationNavigation import CharCreationNavigation 48 from eve.client.script.ui.login.charcreation.steps.bloodLineStep import BloodlineStep 49 from eve.client.script.ui.login.charcreation.steps.characterCustomization import CharacterCustomization 50 from eve.client.script.ui.login.charcreation.steps.characterNaming import CharacterNaming 51 from eve.client.script.ui.login.charcreation.steps.characterPortrait import CharacterPortrait 52 from eve.client.script.ui.login.charcreation.steps.empireStep import EmpireStep 53 from eve.client.script.ui.login.charcreation.steps.technologyStep import TechnologyStep, GetEmpireNavigationWidth, GetEmpireNavigationHeight 54 from eve.client.script.ui.login.charcreation.technologyViewUtils import EmpireNavigation 55 from eve.client.script.ui.login.charcreation.technologyViewsTracker import TechnologyViewsTracker 56 from eve.client.script.ui.login.charcreation.assetMenu import femaleModifierDisplayNames, maleModifierDisplayNames 57 from eve.client.script.ui.shared.colorThemes import DEFAULT_COLORTHEMEID, COLOR_THEME_ID_BY_RACE 58 from eve.client.script.ui.util.disconnectNotice import DisconnectNotice 59 from eveprefs import prefs 60 from fsdBuiltData.common.graphicIDs import GetGraphicFile 61 from locks import TempLock 62 from eveexceptions import UserError 63 from player_messaging.client.ui_message import prompt_player_fsd_dialog 64 from storylines.client.airnpe import is_air_npe_enabled 65 NETWORKMODE_BASIC = 1 66 NETWORKMODE_PORTRAIT = 2 67 LEFT_SIDE_WITH = 180 68 LEFT_SIDE_HEIGHT = 400 69 RIGHT_SIDE_WIDTH = 350 70 RIGHT_SIDE_HEIGHT = ccConst.BUTTON_AREA_HEIGHT 71 BOTTOM_LEFT_SIDE_WIDTH = 220 72 BOTTOM_LEFT_SIDE_HEIGHT = ccConst.BUTTON_AREA_HEIGHT 73 BUTTON_WIDTH = 145 74 BUTTON_HEIGHT = 36 75 BUTTON_FONT_SIZE = 18 76 BACKGROUND_TRANSITION_SECONDS = 2.5 77 RESOURCE_WHEEL_SEPARATION = 8 78 DOLLSTATES_TO_RETURN_TO_CC = [paperdoll.State.no_existing_customization, paperdoll.State.force_recustomize] 79 CLOTHING_ITEMS = (ccConst.topouter, 80 ccConst.topmiddle, 81 ccConst.bottomouter, 82 ccConst.outer, 83 ccConst.feet, 84 ccConst.glasses, 85 ccConst.bottommiddle, 86 ccConst.mask) 87 RACE_TO_RESOURCE_NAME = {const.raceCaldari: 'caldari', 88 const.raceAmarr: 'amarr', 89 const.raceMinmatar: 'minmatar', 90 const.raceGallente: 'gallente'} 91 TOP_NAVIGATION_LINE_HEIGHT = 1 92 BOTTOM_NAVIGATION_LINE_HEIGHT = 1 93 TOP_NAVIGATION_LINE_OPACITY = 0.25 94 BOTTOM_NAVIGATION_LINE_OPACITY = 0.25 95 EXIT_BUTTON_MARGIN = 10 96 BG_OPACITY = 1.0 97 BG_WIDTH = 2117 98 BG_HEIGHT = 1200 99 VIGNETTE_RGB_DATA = ((0.0, (0.0, 0.0, 0.0)), (0.5, (0.0, 0.0, 0.0)), (1.0, (0.0, 0.0, 0.0))) 100 VIGNETTE_ALPHA_DATA = ((0.0, 0.0), (0.8, 0.5), (1.0, 1.0)) 101 VIGNETTE_OPACITY = 0.7 102 STEPS_WITH_VIGNETTE_EFFECT = [ccConst.BLOODLINESTEP] 103 104 class CharacterCreationContainer(Container): 105 __notifyevents__ = ['OnSetDevice', 106 'OnGraphicSettingsChanged', 107 'OnHideUI', 108 'OnShowUI', 109 'OnDollUpdated', 110 'OnMapShortcut', 111 'OnUIRefresh', 112 'OnDisconnect', 113 'OnUIScalingChange'] 114 __update_on_reload__ = 1 115 116 def ApplyAttributes(self, attributes): 117 super(CharacterCreationContainer, self).ApplyAttributes(attributes) 118 sm.RegisterNotify(self) 119 self.needSculptingTutorial = True 120 self.needNavigationTutorial = True 121 self.step = None 122 self.mainNav = None 123 self.vignette = None 124 self.backgroundGradient = None 125 self.backgroundSprite = None 126 self.topNavigationWhiteLineContainer = None 127 self.bottomNavigationWhiteLineContainer = None 128 self.exitButton = None 129 self.empireNavigationContainer = None 130 self.gender_changed = False 131 132 def SetNameCallback(self, name): 133 self.charName = name 134 135 @telemetry.ZONE_METHOD 136 def OnSetDevice(self, *args): 137 self.UpdateLayout() 138 self.UpdateBackdrop() 139 140 def OnDisconnect(self, reason = 0, msg = ''): 141 disconnectNotice = DisconnectNotice(logProvider=self) 142 disconnectNotice.OnDisconnect(reason, msg) 143 144 @telemetry.ZONE_METHOD 145 def UpdateLayout(self): 146 try: 147 self.LockEverything() 148 with TempLock('CharacterCreationLayerUpdate'): 149 for each in self.mainCont.children: 150 if hasattr(each, 'UpdateLayout'): 151 each.UpdateLayout() 152 153 desktopWidth = uicore.desktop.width 154 self.empireStepContainer.UpdateLayout() 155 self.topNavigationContainer.width = desktopWidth 156 self.bottomNavigationContainer.width = desktopWidth 157 self.topNavigationContainer.height = ccScalingUtils.GetTopNavHeight() 158 self.bottomNavigationContainer.height = ccScalingUtils.GetBottomNavHeight() 159 self.empireNavigationButtonContainer.width = ccScalingUtils.GetMainPanelWidth() 160 self.empireNavigationButtonContainer.height = self.bottomNavigationContainer.height 161 if self.empireNavigationContainer: 162 self.empireNavigationContainer.Close() 163 self._AddEmpireNavigation(self.stepID) 164 self.AddWhiteLines() 165 self.AddBackgroundGradient() 166 self.AddVignetteEffect() 167 self.UpdateVisualArtifacts(self.stepID) 168 finally: 169 self.UnlockEverything() 170 171 def UpdateVisualArtifacts(self, stepID): 172 if stepID in [ccConst.EMPIRESTEP, ccConst.TECHNOLOGYSTEP]: 173 self.ShowWhiteLines() 174 self.ShowBackgroundGradient() 175 elif stepID == ccConst.BLOODLINESTEP: 176 self.ShowWhiteLines() 177 self.HideBackgroundGradient() 178 else: 179 self.HideWhiteLines() 180 self.HideBackgroundGradient() 181 if stepID in STEPS_WITH_VIGNETTE_EFFECT: 182 self.ShowVignetteEffect() 183 else: 184 self.HideVignetteEffect() 185 186 def ShowVignetteEffect(self): 187 if self.vignette and not self.vignette.destroyed: 188 self.vignette.opacity = VIGNETTE_OPACITY 189 190 def HideVignetteEffect(self): 191 if self.vignette and not self.vignette.destroyed: 192 self.vignette.opacity = 0.0 193 194 def AddVignetteEffect(self): 195 width, height = self._GetBackdropSpriteSizes() 196 if self.vignette and not self.vignette.destroyed: 197 self.vignette.width = width 198 self.vignette.height = height 199 return 200 self.vignette = GradientSprite(name='vignetteGradientSprite', align=uiconst.CENTER, parent=self, width=width, height=height, rgbData=VIGNETTE_RGB_DATA, alphaData=VIGNETTE_ALPHA_DATA, radial=True, opacity=0.0) 201 202 def ShowBackgroundGradient(self): 203 if self.backgroundGradient and not self.backgroundGradient.destroyed: 204 self.backgroundGradient.opacity = 1.0 205 206 def HideBackgroundGradient(self): 207 if self.backgroundGradient and not self.backgroundGradient.destroyed: 208 self.backgroundGradient.opacity = 0.0 209 210 def AddBackgroundGradient(self): 211 if self.backgroundGradient and not self.backgroundGradient.destroyed: 212 self.backgroundGradient.Close() 213 start = min(0.4, (uicore.desktop.width - ccScalingUtils.GetMainPanelWidth()) / (2 * uicore.desktop.width)) 214 self.backgroundGradient = GradientSprite(name='backgroundGradient', parent=self, align=uiconst.TOALL, rgbData=[(0, (0.0, 0.0, 0.0))], alphaData=[(0, 0.0), 215 (start, 0.0), 216 (0.4, 0.5), 217 (0.6, 0.5), 218 (1.0 - start, 0.0), 219 (1.0, 0.0)], padTop=self.topNavigationContainer.height, padBottom=self.bottomNavigationContainer.height) 220 221 def ShowWhiteLines(self): 222 if self.topNavigationWhiteLineContainer and not self.topNavigationWhiteLineContainer.destroyed: 223 self.topNavigationWhiteLineContainer.opacity = TOP_NAVIGATION_LINE_OPACITY 224 if self.bottomNavigationWhiteLineContainer and not self.bottomNavigationWhiteLineContainer.destroyed: 225 self.bottomNavigationWhiteLineContainer.opacity = BOTTOM_NAVIGATION_LINE_OPACITY 226 227 def HideWhiteLines(self): 228 if self.topNavigationWhiteLineContainer and not self.topNavigationWhiteLineContainer.destroyed: 229 self.topNavigationWhiteLineContainer.opacity = 0.0 230 if self.bottomNavigationWhiteLineContainer and not self.bottomNavigationWhiteLineContainer.destroyed: 231 self.bottomNavigationWhiteLineContainer.opacity = 0.0 232 233 def AddWhiteLines(self): 234 if self.topNavigationWhiteLineContainer and not self.topNavigationWhiteLineContainer.destroyed: 235 self.topNavigationWhiteLineContainer.Close() 236 self.topNavigationWhiteLineContainer = Container(name='topNavigationWhiteLineContainer', parent=self.topNavigationContainer, align=uiconst.TOTOP_NOPUSH, width=self.uiContainer.width, height=self.topNavigationContainer.height, opacity=0.0) 237 GradientSprite(name='topNavigationWhiteLine', parent=self.topNavigationWhiteLineContainer, align=uiconst.TOBOTTOM, width=self.uiContainer.width, height=TOP_NAVIGATION_LINE_HEIGHT, rgbData=[(0, (1.0, 1.0, 1.0))], alphaData=[(0, 0.0), 238 (0.4, 1.0), 239 (0.6, 1.0), 240 (1.0, 0.0)]) 241 if self.bottomNavigationWhiteLineContainer and not self.bottomNavigationWhiteLineContainer.destroyed: 242 self.bottomNavigationWhiteLineContainer.Close() 243 self.bottomNavigationWhiteLineContainer = Container(name='bottomNavigationWhiteLineContainer', parent=self.bottomNavigationContainer, align=uiconst.TOBOTTOM_NOPUSH, width=self.uiContainer.width, height=self.bottomNavigationContainer.height, opacity=0.0) 244 GradientSprite(name='bottomNavigationWhiteLine', parent=self.bottomNavigationWhiteLineContainer, align=uiconst.TOTOP, width=self.uiContainer.width, height=BOTTOM_NAVIGATION_LINE_HEIGHT, rgbData=[(0, (1.0, 1.0, 1.0))], alphaData=[(0, 0.0), 245 (0.4, 1.0), 246 (0.6, 1.0), 247 (1.0, 0.0)]) 248 249 @telemetry.ZONE_METHOD 250 def OnOpenView(self, **kwargs): 251 self.startTime = blue.os.GetWallclockTime() 252 self.backgroundGradient = None 253 self.topNavigationWhiteLineContainer = None 254 self.bottomNavigationWhiteLineContainer = None 255 self.vignette = None 256 uicore.cmd.commandMap.UnloadAllAccelerators() 257 uicore.cmd.commandMap.LoadAcceleratorsByCategory('general') 258 uicore.cmd.commandMap.LoadAcceleratorsByCategory('charactercreator') 259 self.freezingAnimation = False 260 from eve.client.script.ui.shared.preview import PreviewCharacterWnd, PreviewWnd 261 previewCharWnd = PreviewCharacterWnd.GetIfOpen() 262 if previewCharWnd: 263 self.previewCharWindowWasOpenOn = (previewCharWnd.charID, previewCharWnd.dna) 264 previewCharWnd.CloseByUser() 265 else: 266 self.previewCharWindowWasOpenOn = None 267 previewWnd = PreviewWnd.GetIfOpen() 268 if previewWnd: 269 self.previewWindowWasOpenOn = previewWnd.typeID 270 previewWnd.CloseByUser() 271 else: 272 self.previewWindowWasOpenOn = None 273 self._setColorsByCategory = {} 274 self._setSpecularityByCategory = {} 275 self._setIntensityByCategory = {} 276 self.characterSvc = sm.GetService('character') 277 self.sceneManager = sm.GetService('sceneManager') 278 self.alreadyLoadedOldPortraitData = False 279 self.backdropPath = None 280 self.colorCodedBackDrop = None 281 self.posePath = None 282 self.lightingID = ccConst.LIGHT_SETTINGS_ID[0] 283 self.lightColorID = ccConst.LIGHT_COLOR_SETTINGS_ID[0] 284 self.lightIntensity = 0.5 285 self.camera = None 286 self.cameraUpdateJob = None 287 self.fastCharacterCreation = gfxsettings.Get(gfxsettings.GFX_CHAR_FAST_CHARACTER_CREATION) 288 self.bloodlineSelector = None 289 self.raceMusicStarted = False 290 self.jukeboxWasPlaying = False 291 self.mode = ccConst.MODE_FULLINITIAL_CUSTOMIZATION 292 self.modeStorage = ModeStorage() 293 self.modeObject = self.modeStorage.GetModeFor(self.mode) 294 self.charID = None 295 self.raceID = None 296 self.bloodlineID = None 297 self.genderID = None 298 self.schoolID = None 299 self.charName = '' 300 self.clothesOff = 0 301 self.clothesStorage = {} 302 self.clothesMetaStorage = {} 303 self.dnaList = None 304 self.dna = None 305 self.lastLitHistoryBit = None 306 sm.GetService('cc').ClearMyAvailabelTypeIDs() 307 self.backgroundSprite = None 308 self.stepID = None 309 self.floor = None 310 self.showingHelp = 0 311 self.empireStepContainer = None 312 self.topNavigationContainer = None 313 self.bottomNavigationContainer = None 314 self.empireNavigationContainer = None 315 self.CreateUI() 316 self.avatarScene = None 317 self.animatingToPortraitID = None 318 self.animateToStoredPortraitThread = None 319 self.technologyViewsTracker = None 320 self.audioService = sm.GetService('audio') 321 self.worldLevel = self.audioService.GetWorldVolume() 322 self.audioService.SetWorldVolume(0.0) 323 self.stepLogger = StepLogger(blue.os.GetWallclockTime) 324 self.finalStepLogger = None 325 self.metrics = None 326 self.approve_in_progress = False 327 self.save_in_progress = False 328 329 def Finalize(self): 330 self.Save() 331 332 def CreateLoadingWheel(self): 333 self.loadingWheel = LoadingWheel(name='loadingWheel', parent=self, align=uiconst.CENTER, state=uiconst.UI_NORMAL) 334 self.loadingWheel.forcedOn = 0 335 336 def CreateUI(self): 337 self.uiContainer = Container(name='uiContainer', parent=self, align=uiconst.TOALL) 338 self.CreateLoadingWheel() 339 self.leftSide = Container(name='leftSide', parent=self.uiContainer, align=uiconst.TOPLEFT, pos=(0, 340 0, 341 LEFT_SIDE_WITH, 342 LEFT_SIDE_HEIGHT)) 343 self.rightSide = Container(name='rightSide', parent=self.uiContainer, align=uiconst.BOTTOMRIGHT, pos=(0, 344 0, 345 RIGHT_SIDE_WIDTH, 346 RIGHT_SIDE_HEIGHT)) 347 self.bottomLeftSide = Container(name='bottomLeftSide', parent=self.uiContainer, align=uiconst.BOTTOMLEFT, pos=(0, 348 0, 349 BOTTOM_LEFT_SIDE_WIDTH, 350 BOTTOM_LEFT_SIDE_HEIGHT)) 351 self.buttonNavLeft = Container(name='buttonNavLeft', parent=self.bottomLeftSide, align=uiconst.TOTOP, height=BUTTON_HEIGHT, padLeft=10) 352 self.buttonNavRight = Container(name='buttonNavRight', parent=self.rightSide, align=uiconst.TOTOP, height=BUTTON_HEIGHT, padRight=10) 353 self.finalizeBtn = Button(name='finalizeButtonCC', parent=self.buttonNavRight, align=uiconst.TORIGHT, label=localization.GetByLabel('UI/CharacterCreation/EnterGame'), func=self.Finalize, left=10, args=(), state=uiconst.UI_HIDDEN, density=Density.EXPANDED) 354 self.saveBtn = Button(name='saveButtonCC', parent=self.buttonNavRight, align=uiconst.TORIGHT, label=localization.GetByLabel('UI/CharacterCreation/Finalize'), func=self.Save, left=10, args=(), state=uiconst.UI_HIDDEN, density=Density.EXPANDED) 355 self.approveBtn = Button(name='nextButtonCC', parent=self.buttonNavRight, align=uiconst.TORIGHT, label=localization.GetByLabel('UI/Generic/Next'), func=self.Approve, left=10, args=(), density=Density.EXPANDED) 356 self.backBtn = Button(name='backButtonCC', parent=self.buttonNavLeft, align=uiconst.TOLEFT, label=localization.GetByLabel('UI/Commands/Back'), func=self.Back, args=(), left=10, density=Density.EXPANDED) 357 self.blackOut = Fill(name='blackOutFill', parent=self, color=(0.0, 0.0, 0.0, 0.0)) 358 self.mainCont = Container(name='mainCont', parent=self, align=uiconst.TOALL) 359 desktopHeight = uicore.desktop.height 360 topNavHeight = ccScalingUtils.GetTopNavHeight() 361 bottomNavHeight = ccScalingUtils.GetBottomNavHeight() 362 width = ccScalingUtils.GetMainPanelWidth() 363 height = desktopHeight - topNavHeight - bottomNavHeight 364 self.empireStepContainer = EmpireStepContainer(name='empireStepContainer', parent=self.uiContainer, align=uiconst.CENTER, width=width, height=height, state=uiconst.UI_NORMAL, step=self) 365 self.empireStepContainer.SetOrder(0) 366 self.topNavigationContainer = Container(name='topNavigationContainer', parent=self.uiContainer, align=uiconst.TOTOP_NOPUSH, width=self.uiContainer.width, height=topNavHeight, bgColor=(0.0, 0.0, 0.0, 1.0)) 367 self.topNavigationContainer.SetOrder(1) 368 self.bottomNavigationContainer = Container(name='bottomNavigationContainer', parent=self.uiContainer, align=uiconst.TOBOTTOM_NOPUSH, width=self.uiContainer.width, height=bottomNavHeight, bgColor=(0.0, 0.0, 0.0, 1.0)) 369 self.bottomNavigationContainer.SetOrder(2) 370 self.empireNavigationButtonContainer = Container(parent=self.bottomNavigationContainer, align=uiconst.CENTER, width=width, height=self.bottomNavigationContainer.height) 371 self.UpdateLayout() 372 373 def OnAvailabilityCheck(self, name): 374 if self.finalStepLogger: 375 self.finalStepLogger.AddTriedName(name) 376 377 def OnUIRefresh(self): 378 while getattr(self, 'doll', None) and self.doll.IsBusyUpdating(): 379 blue.synchro.Yield() 380 381 self.Flush() 382 self.CreateUI() 383 self.SwitchStep(self.stepID) 384 385 def OnUIScalingChange(self, *args): 386 if not self.destroyed and self.stepID in ccConst.EMPIRE_SELECTION_STEPS: 387 self.UpdateLayout() 388 self.UpdateBackdrop() 389 390 def OnHelpMouseEnter(self, btn, *args): 391 PlaySound('ui_icc_button_mouse_over_play') 392 btn.sr.icon.SetAlpha(1.0) 393 394 def OnHelpMouseExit(self, btn, *args): 395 if not self.showingHelp: 396 btn.sr.icon.SetAlpha(0.5) 397 398 def SetHintText(self, modifier, hintText = ''): 399 if self.stepID in (ccConst.CUSTOMIZATIONSTEP, ccConst.PORTRAITSTEP): 400 self.step.SetHintText(modifier, hintText) 401 402 def SetMode(self, modeID): 403 self.mode = modeID 404 self.modeObject = self.modeStorage.GetModeFor(modeID) 405 406 def GetModeIDForDollState(self, dollState): 407 mode = ccConst.MODE_LIMITED_RECUSTOMIZATION 408 if dollState == paperdoll.State.full_recustomizing: 409 mode = ccConst.MODE_FULL_BLOODLINECHANGE 410 elif dollState in (paperdoll.State.resculpting, paperdoll.State.no_existing_customization, paperdoll.State.force_recustomize): 411 mode = ccConst.MODE_FULL_RECUSTOMIZATION 412 return mode 413 414 @telemetry.ZONE_METHOD 415 def SetCharDetails(self, charID = None, gender = None, raceID = None, bloodlineID = None, dollState = None): 416 self.ClearFacePortrait() 417 self.dollState = dollState 418 self.dna = None 419 self.charID = 0 420 self.raceID = raceID 421 if charID: 422 self.bloodlineID = bloodlineID 423 self.genderID = int(gender) 424 self.charID = charID 425 if dollState not in (paperdoll.State.force_recustomize, paperdoll.State.no_existing_customization): 426 self.dna = sm.GetService('paperdoll').GetMyPaperDollData(self.charID) 427 mode = self.GetModeIDForDollState(dollState) 428 else: 429 mode = ccConst.MODE_FULLINITIAL_CUSTOMIZATION 430 if self._IsUserInSkipTechnologyStepCohort(): 431 self._DeleteTechStep() 432 self.SetMode(mode) 433 self.availableSteps = self.modeObject.GetSteps() 434 stepID = self.availableSteps[0] 435 self.stepsUsed = {stepID} 436 self.mainCont.Flush() 437 self.stepLogger.Start() 438 if dollState in (paperdoll.State.force_recustomize, paperdoll.State.no_existing_customization) or mode == ccConst.MODE_FULLINITIAL_CUSTOMIZATION: 439 self.metrics = ccm.CharacterCreationMetrics(mode, ccConst.LOGIN) 440 else: 441 self.metrics = ccm.CharacterCreationMetrics(mode, ccConst.HANGAR) 442 self.needSculptingTutorial = self.CanChangeBaseAppearance() 443 self.SwitchStep(stepID) 444 445 @telemetry.ZONE_METHOD 446 def _IsUserInSkipTechnologyStepCohort(self): 447 if gatekeeper.user.IsInCohort(gatekeeper.cohortSkipTechScreen): 448 return True 449 else: 450 return False 451 452 def _DeleteTechStep(self): 453 steps = self.modeStorage.GetModeFor(ccConst.MODE_FULLINITIAL_CUSTOMIZATION) 454 if ccConst.TECHNOLOGYSTEP in steps.GetSteps(): 455 steps.GetSteps().remove(ccConst.TECHNOLOGYSTEP) 456 STEP_ORDER_LIST.remove(ccConst.TECHNOLOGYSTEP) 457 458 @telemetry.ZONE_METHOD 459 def GetInfo(self): 460 return Bunch(charID=self.charID, raceID=self.raceID, bloodlineID=self.bloodlineID, genderID=self.genderID, dna=self.dna, schoolID=self.schoolID, stepID=self.stepID, charName=self.charName) 461 462 def CanChangeBaseAppearance(self, *args): 463 return self.modeObject.CanChangeBaseAppearance() 464 465 def GetMode(self, *args): 466 return self.mode 467 468 def CanChangeBloodline(self, *args): 469 return self.modeObject.CanChangeBloodLine() 470 471 def CanChangeGender(self, *args): 472 return self.modeObject.CanChangeGender() 473 474 def CanChangeName(self, *args): 475 return self.modeObject.CanChangeName() 476 477 def _AddExitButton(self, toStep): 478 if self.exitButton and not self.exitButton.destroyed: 479 self.exitButton.Close() 480 self.exitButton = ButtonIcon(name='exitButton', parent=self.topNavigationContainer, func=self.CancelCharacterCreation, texturePath='res:/UI/Texture/Icons/73_16_45.png', align=uiconst.TOPRIGHT, left=EXIT_BUTTON_MARGIN, top=EXIT_BUTTON_MARGIN, width=EXIT_BUTTON_SIZE, height=EXIT_BUTTON_SIZE, idx=0) 481 482 def ConstructNavigationIfNeeded(self, toStep): 483 self._AddExitButton(toStep) 484 self._AddEmpireNavigation(toStep) 485 if toStep == ccConst.EMPIRESTEP: 486 return 487 if not self.mainNav or self.mainNav.destroyed: 488 navSteps = copy.copy(self.availableSteps) 489 if ccConst.EMPIRESTEP in navSteps: 490 navSteps.remove(ccConst.EMPIRESTEP) 491 self.mainNav = CharCreationNavigation(name='navigation', align=uiconst.CENTERTOP, parent=self.leftSide, pos=(12, 12, 0, 60), stepID=toStep, func=self.SwitchStepIfDifferent, stepsUsed=self.stepsUsed, availableSteps=navSteps) 492 if toStep == ccConst.EMPIRESTEP: 493 self.mainNav.Hide() 494 else: 495 self.mainNav.Show() 496 if toStep in ccConst.EMPIRE_SELECTION_STEPS: 497 self.mainNav.SetParent(self.topNavigationContainer) 498 self.mainNav.align = uiconst.TOLEFT 499 self.topNavigationContainer.Show() 500 self.bottomNavigationContainer.Show() 501 sm.GetService('gameui').MoveResourceLoadingIndicator(newAlignment=uiconst.BOTTOMLEFT, newLeft=10, newTop=10) 502 else: 503 self.mainNav.SetParent(self.leftSide, 0) 504 self.mainNav.align = uiconst.TOLEFT 505 self.topNavigationContainer.Hide() 506 self.bottomNavigationContainer.Hide() 507 sm.GetService('gameui').MoveResourceLoadingIndicator(newAlignment=uiconst.BOTTOMLEFT, newLeft=20, newTop=RESOURCE_WHEEL_SEPARATION + ccConst.BUTTON_AREA_HEIGHT) 508 509 def _ShowOrHideCharacterScene(self, toStep): 510 if toStep == ccConst.BLOODLINESTEP: 511 self.sceneManager.characterRenderJob.DisableStep('RENDER_SCENE') 512 elif self.stepID == ccConst.BLOODLINESTEP or self.stepID is None: 513 self.sceneManager.characterRenderJob.EnableStep('RENDER_SCENE') 514 515 @telemetry.ZONE_METHOD 516 def SwitchStepIfDifferent(self, toStep, *args): 517 if self.stepID == toStep: 518 return 519 if self.stepID == ccConst.TECHNOLOGYSTEP and toStep == ccConst.BLOODLINESTEP: 520 self.step.techView.Enlist() 521 return 522 self.SwitchStep(toStep, args) 523 524 @telemetry.ZONE_METHOD 525 def SwitchStep(self, toStep, *args): 526 if GetStepOrder(toStep) > GetStepOrder(self.stepID): 527 if not self.PassedStepCheck(toStep): 528 return 529 try: 530 self.LockEverything() 531 isStepOutOfEmpireSelection = self.stepID is not None and self.stepID not in ccConst.EMPIRE_SELECTION_STEPS 532 isToStepOutOfEmpireSelection = toStep not in ccConst.EMPIRE_SELECTION_STEPS 533 isBlackScreenTransition = isStepOutOfEmpireSelection or isToStepOutOfEmpireSelection 534 if isBlackScreenTransition: 535 self.FadeToBlack(why=localization.GetByLabel('UI/Generic/Loading')) 536 with TempLock('CharacterCreationLayerUpdate'): 537 self.UnfreezeAnimationIfNeeded() 538 self.BlockOnUpdate() 539 self.ConstructNavigationIfNeeded(toStep) 540 self.empireNavigationButtonContainer.Flush() 541 if self.stepID == ccConst.CUSTOMIZATIONSTEP: 542 sm.StartService('audio').SendUIEvent(unicode('ui_icc_sculpting_mouse_over_loop_stop')) 543 self.step.StoreHistorySliderPosition() 544 elif self.stepID == ccConst.PORTRAITSTEP: 545 sm.StartService('audio').SendUIEvent(unicode('ui_icc_sculpting_mouse_over_loop_stop')) 546 self.StorePortraitCameraSettings() 547 self.step = None 548 raceTheme = COLOR_THEME_ID_BY_RACE.get(self.raceID, DEFAULT_COLORTHEMEID) 549 sm.GetService('uiColor').SetNoCharTheme(raceTheme) 550 if self.mainNav: 551 stepsUsed = self.stepsUsed.copy() 552 uthread.new(self.mainNav.PerformStepChange, toStep, stepsUsed) 553 self._ShowOrHideCharacterScene(toStep) 554 self.BlockOnUpdate() 555 self._UpdateNavigationButtons(toStep) 556 if isBlackScreenTransition: 557 self.mainCont.Flush() 558 if toStep in ccConst.EMPIRE_SELECTION_STEPS: 559 self.empireStepContainer.Show() 560 else: 561 self.empireStepContainer.Hide() 562 self.UpdateVisualArtifacts(toStep) 563 if toStep != ccConst.EMPIRESTEP: 564 self.empireStepContainer.ShowBackgroundBanner(self.raceID) 565 if toStep == ccConst.EMPIRESTEP: 566 self.empireStepContainer.ShowViewCaps() 567 self.empireStepContainer.HideBannerCaps() 568 elif toStep == ccConst.TECHNOLOGYSTEP: 569 self.empireStepContainer.HideViewCaps() 570 self.empireStepContainer.SetBannerCapsForMenu() 571 elif toStep == ccConst.BLOODLINESTEP: 572 self.empireStepContainer.HideViewCaps() 573 self.empireStepContainer.SetBannerCapsForView() 574 self.Cleanup() 575 self.BlockOnUpdate() 576 self.metrics.new_page(toStep) 577 self.StartStep(toStep) 578 self.stepID = toStep 579 self.stepsUsed.add(toStep) 580 self.UpdateBackdrop() 581 finally: 582 self.UnlockEverything() 583 self.setupDone = 1 584 self.FadeFromBlack() 585 self.UnfreezeAnimationIfNeeded() 586 sm.ScatterEvent('OnCharacterCreationStep', self.stepID, toStep) 587 588 def BlockOnUpdate(self): 589 info = self.GetInfo() 590 characters = self.characterSvc.characters 591 if info.charID in characters and self.characterSvc.GetSingleCharactersDoll(info.charID).busyUpdating: 592 start_time = time.clock() 593 while self.characterSvc.GetSingleCharactersDoll(info.charID).busyUpdating and time.clock() - start_time < 60: 594 blue.synchro.Yield() 595 596 if self.characterSvc.GetSingleCharactersDoll(info.charID).busyUpdating: 597 raise UserError('uiwarning01') 598 599 def _UpdateNavigationButtons(self, toStep): 600 if toStep in ccConst.EMPIRE_SELECTION_STEPS: 601 self.backBtn.Hide() 602 self.approveBtn.Hide() 603 self.finalizeBtn.Hide() 604 self.saveBtn.Hide() 605 return 606 self.approveBtn.Show() 607 self.backBtn.Show() 608 isGoingToFinalStep = toStep == self.availableSteps[-1] 609 if isGoingToFinalStep: 610 self.approveBtn.state = uiconst.UI_HIDDEN 611 isNewChar = not self.charID 612 if isNewChar: 613 self.finalizeBtn.state = uiconst.UI_NORMAL 614 self.saveBtn.state = uiconst.UI_HIDDEN 615 else: 616 self.finalizeBtn.state = uiconst.UI_HIDDEN 617 self.saveBtn.state = uiconst.UI_NORMAL 618 else: 619 self.approveBtn.state = uiconst.UI_NORMAL 620 self.finalizeBtn.state = uiconst.UI_HIDDEN 621 self.saveBtn.state = uiconst.UI_HIDDEN 622 623 def _SetUpSceneAndCamera(self, scene): 624 self.sceneManager.Show2DBackdropScene() 625 self.SetupScene(scene) 626 self.camera = CharCreationCamera(None) 627 self.camera.fieldOfView = 0.5 628 self.camera.distance = 7.0 629 self.camera.SetPointOfInterest((0.0, 1.3, 0.0)) 630 self.camera.frontClip = 3.5 631 self.camera.backclip = 100.0 632 self.SetupCameraUpdateJob() 633 634 def _HideBackButtonIfNoCharacters(self): 635 if not sm.GetService('cc').GetCharactersToSelect(): 636 self.backBtn.Hide() 637 638 def StartEmpireStep(self): 639 self.step = EmpireStep(parent=self.empireStepContainer, stepContainer=self.empireStepContainer) 640 self._SetUpSceneAndCamera(ccConst.SCENE_PATH_RACE_SELECTION) 641 self.camera.ToggleMode(ccConst.CAMERA_MODE_DEFAULT, avatar=None) 642 643 def _AddEmpireNavigation(self, stepID): 644 if stepID not in (ccConst.TECHNOLOGYSTEP, ccConst.BLOODLINESTEP): 645 if self.empireNavigationContainer is not None and not self.empireNavigationContainer.destroyed: 646 self.empireNavigationContainer.Close() 647 return 648 if self.empireNavigationContainer is not None and not self.empireNavigationContainer.destroyed: 649 return 650 width = GetEmpireNavigationWidth() 651 height = GetEmpireNavigationHeight() 652 self.empireNavigationContainer = Container(name='empireNavigationContainer', align=uiconst.CENTER, parent=self.topNavigationContainer, width=width, height=self.topNavigationContainer.height, idx=1) 653 rightAlignedContainer = Container(name='rightAlignedContainer', align=uiconst.TORIGHT, parent=self.empireNavigationContainer, width=width, height=self.empireNavigationContainer.height) 654 empireNavigationWrapper = Container(name='empireNavigationWrapper', align=uiconst.CENTERBOTTOM, parent=rightAlignedContainer, width=width, height=height) 655 EmpireNavigation(name='empireNavigationContainer', align=uiconst.TOLEFT, parent=empireNavigationWrapper, width=width, height=height, raceSetter=self.SelectRaceIfDifferent, activeRace=self.raceID) 656 657 def StartTechnologyStep(self): 658 if self.technologyViewsTracker is None: 659 self.technologyViewsTracker = TechnologyViewsTracker() 660 self._SetUpSceneAndCamera(ccConst.SCENE_PATH_RACE_SELECTION) 661 self.camera.ToggleMode(ccConst.CAMERA_MODE_DEFAULT, avatar=None) 662 isStepChange = self.stepID != ccConst.TECHNOLOGYSTEP 663 self.step = TechnologyStep(parent=self.empireStepContainer, shouldGoBackToStart=isStepChange, technologyViewsTracker=self.technologyViewsTracker) 664 self.step.SetOrder(0) 665 666 def StartNewBloodlineStep(self): 667 try: 668 self.ShowLoading() 669 self.LoadBloodlineStep() 670 finally: 671 self.HideLoading() 672 673 def _ShouldUseVideosInBloodlines(self): 674 return not self.IsSlowMachine() 675 676 def LoadBloodlineStep(self): 677 self.step = BloodlineStep(parent=self.empireStepContainer, buttonContainer=uicore.layer.charactercreation.controller.empireNavigationButtonContainer, useVideos=self._ShouldUseVideosInBloodlines()) 678 self.step.SetOrder(0) 679 self.step.ShowBloodlineInfo() 680 self.step.ShowBoundingBoxes() 681 self.step.ShowGenders() 682 self.step.ShowNote() 683 684 def ReloadBloodlineStep(self, updateRace = False): 685 try: 686 self.LockEverything() 687 self.HideContent(updateRace) 688 self.ShowLoading() 689 if self.step and not self.step.destroyed: 690 self.step.Close() 691 self.LoadBloodlineStep() 692 if updateRace: 693 raceTheme = COLOR_THEME_ID_BY_RACE.get(self.raceID, DEFAULT_COLORTHEMEID) 694 sm.GetService('uiColor').SetNoCharTheme(raceTheme) 695 self.UpdateBackdrop() 696 self.ShowContent(updateRace) 697 finally: 698 self.HideLoading() 699 self.UnlockEverything() 700 701 def ShowContent(self, updateRace): 702 if self.empireStepContainer and not self.empireStepContainer.destroyed: 703 self.empireStepContainer.Show() 704 if updateRace: 705 self.empireStepContainer.ExpandRace(self.raceID) 706 if not updateRace and self.backgroundSprite and not self.backgroundSprite.destroyed: 707 self.backgroundSprite.Show() 708 709 def HideContent(self, updateRace): 710 if self.empireStepContainer and not self.empireStepContainer.destroyed: 711 self.empireStepContainer.Hide() 712 if not updateRace and self.backgroundSprite and not self.backgroundSprite.destroyed: 713 self.backgroundSprite.Hide() 714 715 def StartStep(self, toStep): 716 self.stepLogger.SetStep(toStep) 717 start_method = {ccConst.CUSTOMIZATIONSTEP: self.StartCustomizationStep, 718 ccConst.PORTRAITSTEP: self.StartPortraitStep, 719 ccConst.NAMINGSTEP: self.StartNamingStep, 720 ccConst.EMPIRESTEP: self.StartEmpireStep, 721 ccConst.TECHNOLOGYSTEP: self.StartTechnologyStep, 722 ccConst.BLOODLINESTEP: self.StartNewBloodlineStep}.get(toStep, None) 723 if start_method is None: 724 raise NotImplementedError 725 start_method() 726 727 def IsNamingStep(self, step): 728 return step == ccConst.NAMINGSTEP 729 730 @telemetry.ZONE_METHOD 731 def StorePortraitCameraSettings(self): 732 if self.camera is not None: 733 self.storedPortraitCameraSettings = {'poi': self.camera.poi, 734 'pitch': self.camera.pitch, 735 'yaw': self.camera.yaw, 736 'distance': self.camera.distance, 737 'xFactor': self.camera.xFactor, 738 'yFactor': self.camera.yFactor, 739 'fieldOfView': self.camera.fieldOfView} 740 741 @telemetry.ZONE_METHOD 742 def FadeToBlack(self, why = ''): 743 self.ShowLoading(why=why, forceOn=True) 744 animations.FadeIn(self.blackOut, duration=0.5, sleep=True) 745 746 @telemetry.ZONE_METHOD 747 def FadeFromBlack(self): 748 animations.FadeOut(self.blackOut, duration=0.5) 749 self.HideLoading(forceOff=1) 750 751 @telemetry.ZONE_METHOD 752 def PassedStepCheck(self, toStep, *args): 753 if toStep not in self.availableSteps: 754 raise UserError('CCStepUnavailable') 755 if toStep == ccConst.BLOODLINESTEP and self.raceID is None: 756 raise UserError('CCMustSelectRace') 757 if toStep == ccConst.CUSTOMIZATIONSTEP and (self.raceID is None or self.bloodlineID is None or self.genderID is None): 758 raise UserError('CCMustSelectRaceAndBloodline') 759 isNamingStep = self.IsNamingStep(toStep) 760 if (toStep == ccConst.PORTRAITSTEP or isNamingStep) and not prefs.GetValue('ignoreCCValidation', False): 761 info = self.GetInfo() 762 self.ToggleClothes(forcedValue=0) 763 self.characterSvc.ValidateDollCustomizationComplete(info.charID) 764 currentStepID = None 765 if self.step: 766 currentStepID = self.step.stepID 767 if self.step: 768 self.step.ValidateStepComplete() 769 return True 770 771 @telemetry.ZONE_METHOD 772 def Approve(self, *args): 773 if not self.approve_in_progress: 774 try: 775 self.approve_in_progress = True 776 self.stepLogger.IncrementNextTryCount() 777 idx = self.availableSteps.index(self.stepID) 778 if len(self.availableSteps) > idx + 1: 779 nextStep = self.availableSteps[idx + 1] 780 self.SwitchStep(nextStep) 781 uicore.registry.SetFocus(self) 782 finally: 783 self.approve_in_progress = False 784 785 def CheckAndGetName(self): 786 isAvailable = self.step.CheckAvailability() 787 if isAvailable.charName is None: 788 prompt_player_fsd_dialog('CustomInfo', {'info': isAvailable.reason}) 789 return isAvailable.charName 790 791 @telemetry.ZONE_METHOD 792 def Save(self, *args): 793 if not self.save_in_progress: 794 self.save_in_progress = True 795 self.BlockOnUpdate() 796 if self.finalStepLogger: 797 self.finalStepLogger.Finalize() 798 self.stepLogger.IncrementNextTryCount() 799 try: 800 selectedPortraitInfo = self.portraitInfo[self.activePortraitIndex] 801 if selectedPortraitInfo and selectedPortraitInfo.backgroundID < const.NCC_MIN_NORMAL_BACKGROUND_ID: 802 prompt_player_fsd_dialog('CustomInfo', {'info': localization.GetByLabel('UI/CharacterCreation/CannotSaveWithThisBackground')}) 803 return 804 self.LockEverything() 805 if self.step: 806 self.step.ValidateStepComplete() 807 if self.stepID != self.availableSteps[-1]: 808 raise UserError('CCCannotSave') 809 if self.charID and self.modeObject.AskForPortraitConfirmation(): 810 self.UpdateExistingCharacter() 811 return 812 if self.bloodlineID is None or self.genderID is None: 813 raise UserError('CCCannotSave2') 814 else: 815 characterName = self.CheckAndGetName() 816 if characterName is None: 817 return 818 self.SaveAndEnterCurrentCharacter(characterName) 819 finally: 820 if self and not self.destroyed: 821 self.UnlockEverything() 822 self.save_in_progress = False 823 824 def SaveAndEnterCurrentCharacter(self, characterName): 825 self.audioService.SendUIEvent('ui_es_button_mouse_down_finalize_play') 826 charID = self.SaveCurrentCharacter(characterName, self.bloodlineID, self.genderID, self.activePortraitIndex) 827 self.metrics.complete_cc(charid=charID) 828 if charID: 829 self.characterSvc.CachePortraitInfo(charID, self.portraitInfo[self.activePortraitIndex]) 830 self.tryLoginElseCharacterSelection(charID) 831 832 def tryLoginElseCharacterSelection(self, charID): 833 try: 834 if gatekeeper.user.IsInCohort(gatekeeper.cohortToCharacterSelectionTest): 835 sm.GetService('cc').GetCharactersToSelect(force=True) 836 uthread.pool('GameUI::ActivateView::charsel', sm.GetService('viewState').ActivateView, 'charsel') 837 else: 838 skipTutorial = self.CheckSkipTutorial() if is_air_npe_enabled() else True 839 sm.GetService('cc').FinishCharacterCreation(charID, skipTutorial) 840 except: 841 cc = sm.GetService('cc') 842 cc.StopIntro() 843 cc.GetCharactersToSelect(force=True) 844 sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CharacterCreation/CharacterSelection'), localization.GetByLabel('UI/CharacterCreation/FailedToEnterGame'), 2, 2) 845 uthread.pool('GameUI::ActivateView::charsel', sm.GetService('viewState').ActivateView, 'charsel') 846 raise 847 848 def CheckSkipTutorial(self): 849 if sm.RemoteSvc('charUnboundMgr').GetNumCharacters() > 1: 850 if prompt_player_fsd_dialog('AskStartWithTutorial', {}, uiconst.YESNO, default=uiconst.ID_NO) == uiconst.ID_NO: 851 return True 852 return False 853 854 def OnEsc(self): 855 self.Back() 856 857 def CancelCharacterCreation(self): 858 if self.modeObject.ExitToStation(): 859 msg = 'AskCancelCharCustomization' 860 else: 861 msg = 'AskCancelCharCreation' 862 self.audioService.SendUIEvent('ui_es_pop_up_play') 863 popUp = prompt_player_fsd_dialog(msg, {}, uiconst.YESNO) 864 self.audioService.SendUIEvent('ui_es_pop_up_stop') 865 if popUp != uiconst.ID_YES: 866 return 867 self.needNavigationTutorial = True 868 self.needSculptingTutorial = True 869 self.audioService.SendUIEvent('ui_es_stop') 870 self.metrics.cancel_cc() 871 if self.modeObject.ExitToStation(): 872 self.ExitToStation(updateDoll=False) 873 else: 874 sm.StartService('cc').GoBack() 875 self.stepID = None 876 877 @telemetry.ZONE_METHOD 878 def Back(self, *args): 879 idx = self.availableSteps.index(self.stepID) 880 if idx == 0: 881 self.CancelCharacterCreation() 882 else: 883 nextStep = self.availableSteps[idx - 1] 884 self.SwitchStep(nextStep) 885 uicore.registry.SetFocus(self) 886 887 @telemetry.ZONE_METHOD 888 def LockEverything(self, *args): 889 if not getattr(self, 'setupDone', 0): 890 return 891 containers = [self, 892 self.topNavigationContainer, 893 self.bottomNavigationContainer, 894 self.empireStepContainer] 895 for container in containers: 896 container.pickState = uiconst.TR2_SPS_OFF 897 898 self.LockNavigation() 899 900 @telemetry.ZONE_METHOD 901 def LockNavigation(self, *args): 902 if not getattr(self, 'setupDone', 0): 903 return 904 self.buttonNavRight.state = uiconst.UI_DISABLED 905 self.buttonNavLeft.state = uiconst.UI_DISABLED 906 if self.mainNav: 907 self.mainNav.state = uiconst.UI_DISABLED 908 909 @telemetry.ZONE_METHOD 910 def UnlockEverything(self, *args): 911 containers = [self, 912 self.topNavigationContainer, 913 self.bottomNavigationContainer, 914 self.empireStepContainer] 915 for container in containers: 916 container.pickState = uiconst.TR2_SPS_CHILDREN 917 918 self.UnlockNavigation() 919 920 @telemetry.ZONE_METHOD 921 def UnlockNavigation(self, *args): 922 if not self.parent.isopen: 923 return 924 self.buttonNavRight.state = uiconst.UI_PICKCHILDREN 925 self.buttonNavLeft.state = uiconst.UI_PICKCHILDREN 926 if self.mainNav: 927 self.mainNav.state = uiconst.UI_PICKCHILDREN 928 929 @telemetry.ZONE_METHOD 930 def SetActivePortrait(self, portraitNo, *args): 931 self.activePortraitIndex = portraitNo 932 self.activePortrait = self.facePortraits[portraitNo] 933 934 @telemetry.ZONE_METHOD 935 def GetActivePortrait(self): 936 return self.activePortrait 937 938 @telemetry.ZONE_METHOD 939 def SetFacePortrait(self, photo, portraitNo, *args): 940 self.facePortraits[portraitNo] = photo 941 self.SetActivePortrait(portraitNo) 942 943 @telemetry.ZONE_METHOD 944 def ClearFacePortrait(self, *args): 945 self.facePortraits = [None] * ccConst.NUM_PORTRAITS 946 self.ClearPortraitInfo() 947 self.activePortraitIndex = 0 948 self.activePortrait = None 949 950 @telemetry.ZONE_METHOD 951 def SelectRaceIfDifferent(self, raceID, check = 1): 952 if self.raceID != raceID: 953 self._ChangeRace(raceID, check) 954 self._UpdateResourcePriority(raceID) 955 956 @telemetry.ZONE_METHOD 957 def SelectRace(self, raceID, check = 1): 958 self._ChangeRace(raceID, check) 959 self._UpdateResourcePriority(raceID) 960 961 def _ChangeRace(self, raceID, check = 1): 962 oldRaceID = self.raceID 963 bloodLineStepIsUsed = ccConst.BLOODLINESTEP in self.stepsUsed 964 if check and oldRaceID is not None and bloodLineStepIsUsed: 965 if self.stepID == ccConst.CUSTOMIZATIONSTEP: 966 dnaLog = self.GetDollDNAHistory() 967 if dnaLog and len(dnaLog) > 1: 968 if prompt_player_fsd_dialog('CharCreationLoseChangesRace', {}, uiconst.YESNO) != uiconst.ID_YES: 969 return 970 self.ClearSteps(what='race') 971 self.ResetClothesStorage() 972 self.raceID = raceID 973 if self.stepID == ccConst.BLOODLINESTEP: 974 self.SelectBloodlineAndGender(None, None, check) 975 else: 976 self.SelectBloodline(None, check=check) 977 if hasattr(self.step, 'OnRaceSelected'): 978 self.step.OnRaceSelected(raceID) 979 self.UpdateBackdrop() 980 981 def _UpdateResourcePriority(self, raceID): 982 raceAsString = RACE_TO_RESOURCE_NAME.get(raceID, None) 983 if raceAsString: 984 everesourceprefetch.ScheduleFront('interior_' + raceAsString) 985 everesourceprefetch.ScheduleFront('bloodline_select_' + raceAsString) 986 987 @telemetry.ZONE_METHOD 988 def SelectBloodline(self, bloodlineID, check = 1): 989 if self.bloodlineID != bloodlineID: 990 oldBloodlineID = self.bloodlineID 991 if check and oldBloodlineID is not None and ccConst.CUSTOMIZATIONSTEP in self.stepsUsed: 992 if self.stepID == ccConst.CUSTOMIZATIONSTEP: 993 dnaLog = self.GetDollDNAHistory() 994 if dnaLog and len(dnaLog) > 1: 995 if prompt_player_fsd_dialog('CharCreationLoseChangeBloodline', {}, uiconst.YESNO) != uiconst.ID_YES: 996 return 997 self.ClearSteps(what='bloodline') 998 self.ResetClothesStorage() 999 self.bloodlineID = bloodlineID 1000 if hasattr(self.step, 'OnBloodlineSelected'): 1001 self.step.OnBloodlineSelected(bloodlineID, oldBloodlineID) 1002 if self.bloodlineSelector is not None: 1003 self.bloodlineSelector.SelectBloodline(bloodlineID) 1004 1005 @telemetry.ZONE_METHOD 1006 def SelectGender(self, genderID, check = 1): 1007 if not self.CanChangeGender(): 1008 return 1009 if check and self.genderID not in [None, genderID] and ccConst.CUSTOMIZATIONSTEP in self.stepsUsed: 1010 if self.stepID == ccConst.CUSTOMIZATIONSTEP: 1011 dnaLog = self.GetDollDNAHistory() 1012 if dnaLog and len(dnaLog) > 1: 1013 if prompt_player_fsd_dialog('CharCreationLoseChangeGender', {}, uiconst.YESNO) != uiconst.ID_YES: 1014 return 1015 self.genderID = genderID 1016 self.ClearSteps(what='gender') 1017 self.ResetClothesStorage() 1018 if hasattr(self.step, 'OnGenderSelected'): 1019 self.step.OnGenderSelected(genderID) 1020 if getattr(self.step.sr, 'historySlider'): 1021 self.step.sr.historySlider.LoadHistory(0) 1022 1023 @telemetry.ZONE_METHOD 1024 def SelectBloodlineAndGender(self, bloodlineID, genderID, check = 1): 1025 isBloodlineChanged = self.bloodlineID != bloodlineID 1026 isGenderChanged = self.genderID != genderID 1027 self.WarnOfUnsavedChanges(check, isBloodlineChanged, isGenderChanged) 1028 if isBloodlineChanged or isGenderChanged: 1029 self.ClearSteps(what='bloodline') 1030 self.bloodlineID = bloodlineID 1031 self.genderID = genderID 1032 self.ResetClothesStorage() 1033 if getattr(self.step, 'sr') and getattr(self.step.sr, 'historySlider'): 1034 self.step.sr.historySlider.LoadHistory(0) 1035 1036 def WarnOfUnsavedChanges(self, check, isBloodlineChanged, isGenderChanged): 1037 isBloodlineUnsaved = isBloodlineChanged and self.bloodlineID is not None 1038 isGenderUnsaved = isGenderChanged and self.genderID is not None 1039 areThereUnsavedChanges = isBloodlineUnsaved or isGenderUnsaved 1040 isCustomized = self.stepID == ccConst.CUSTOMIZATIONSTEP and ccConst.CUSTOMIZATIONSTEP in self.stepsUsed 1041 shouldWarn = check and areThereUnsavedChanges and isCustomized 1042 if shouldWarn: 1043 dnaLog = self.GetDollDNAHistory() 1044 if dnaLog and len(dnaLog) > 1: 1045 message = 'CharCreationLoseChangeBloodline' if isBloodlineUnsaved else 'CharCreationLoseChangeGender' 1046 if prompt_player_fsd_dialog(message, {}, uiconst.YESNO) != uiconst.ID_YES: 1047 return 1048 1049 @telemetry.ZONE_METHOD 1050 def SelectSchool(self, schoolID): 1051 if self.finalStepLogger: 1052 self.finalStepLogger.SetSchool(schoolID) 1053 self.schoolID = schoolID 1054 if hasattr(self.step, 'OnSchoolSelected'): 1055 self.step.OnSchoolSelected(schoolID) 1056 1057 @telemetry.ZONE_METHOD 1058 def OnDollUpdated(self, charID, redundantUpdate, fromWhere, *args): 1059 if fromWhere in ('AddCharacter', 'OnSetDevice'): 1060 return 1061 self.ClearSteps(what='dollUpdated') 1062 1063 @telemetry.ZONE_METHOD 1064 def IsSlowMachine(self): 1065 if gfxsettings.Get(gfxsettings.GFX_CHAR_FAST_CHARACTER_CREATION): 1066 return True 1067 if gfxsettings.Get(gfxsettings.GFX_SHADER_QUALITY) < 2: 1068 return True 1069 return False 1070 1071 @telemetry.ZONE_METHOD 1072 def OnGraphicSettingsChanged(self, changes): 1073 shouldGoBack = False 1074 if getattr(uicore.layer.charactercreation, 'isopen', 0): 1075 if gfxsettings.GFX_CHAR_FAST_CHARACTER_CREATION in changes: 1076 header = localization.GetByLabel('UI/CharacterCreation/LoseChangesHeader') 1077 text = localization.GetByLabel('UI/CharacterCreation/LoseChanges') 1078 if prompt_player_fsd_dialog('CustomQuestion', {'header': header, 1079 'question': text}, uiconst.YESNO) == uiconst.ID_YES: 1080 self.avatarScene = None 1081 shouldGoBack = True 1082 else: 1083 gfxsettings.Set(gfxsettings.GFX_CHAR_FAST_CHARACTER_CREATION, 0, pending=False) 1084 if shouldGoBack: 1085 if self.charID: 1086 trinity.WaitForResourceLoads() 1087 self.ExitToStation() 1088 else: 1089 sm.GetService('cc').GoBack() 1090 else: 1091 self.bloodlineSelector = None 1092 if self.stepID in ccConst.EMPIRE_SELECTION_STEPS: 1093 self.ReloadStep() 1094 if gfxsettings.UI_NCC_GREEN_SCREEN in changes: 1095 self.UpdateBackdrop() 1096 if self.floor: 1097 self.floor.display = not gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN) 1098 1099 def ReloadStep(self): 1100 self.ShowLoading() 1101 try: 1102 self.SwitchStep(self.stepID) 1103 finally: 1104 self.HideLoading() 1105 1106 @telemetry.ZONE_METHOD 1107 def TearDown(self): 1108 self.Cleanup() 1109 self.characterSvc.TearDown() 1110 self.floor = None 1111 self.doll = None 1112 self.scene = None 1113 self.avatarScene = None 1114 self.ClearCamera() 1115 self.cameraUpdateJob = None 1116 if self.bloodlineSelector is not None: 1117 self.bloodlineSelector.TearDown() 1118 self.bloodlineSelector = None 1119 self.animateToStoredPortraitThread = None 1120 self.animatingToPortraitID = None 1121 self.freezingAnimation = False 1122 self.colorCodedBackDrop = None 1123 1124 @telemetry.ZONE_METHOD 1125 def SetAvatarScene(self, skipAddCharacter = False): 1126 info = self.GetInfo() 1127 if self.avatarScene is None: 1128 self.SetupScene(ccConst.SCENE_PATH_CUSTOMIZATION) 1129 self.avatarScene = self.scene 1130 if not skipAddCharacter: 1131 self.AddCharacter(info.charID, info.bloodlineID, info.raceID, info.genderID, dna=info.dna) 1132 self.floor = trinity.Load(ccConst.CUSTOMIZATION_FLOOR) 1133 self.scene.dynamics.append(self.floor) 1134 else: 1135 self.scene = self.avatarScene 1136 self.sceneManager.SetActiveScene(self.scene, sceneKey='characterCreation') 1137 self.BlockOnUpdate() 1138 1139 @telemetry.ZONE_METHOD 1140 def StartCustomizationStep(self, *args): 1141 info = self.GetInfo() 1142 self.sceneManager.Show2DBackdropScene() 1143 self.SetAvatarScene() 1144 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 1145 if avatar is not None: 1146 network = animparams.GetParamsPerAvatar(avatar, info.charID) 1147 network.SetControlParameter('ControlParameters|NetworkMode', NETWORKMODE_BASIC) 1148 self.camera = CharCreationCamera(avatar, ccConst.CAMERA_MODE_FACE) 1149 self.camera.frontClip = 0.1 1150 self.camera.backclip = 100.0 1151 self.SetupCameraUpdateJob() 1152 self.camera.SetMoveCallback(self.CameraMoveCB) 1153 self.SetDefaultLighting() 1154 self.step = CharacterCustomization(parent=self.mainCont) 1155 if self.CanChangeBaseAppearance(): 1156 self.StartEditMode(showPreview=True, callback=self.step.ChangeSculptingCursor) 1157 self.camera.ToggleMode(ccConst.CAMERA_MODE_FACE, avatar=avatar, transformTime=500.0) 1158 self.scene.SetupShadowMaps() 1159 1160 def CameraMoveCB(self, viewMatrix): 1161 info = self.GetInfo() 1162 if info.charID not in self.characterSvc.characters: 1163 return 1164 if not len(self.characterSvc.characters): 1165 return 1166 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 1167 matrix = geo2.MatrixInverse(viewMatrix.transform) 1168 view = matrix[3][:3] 1169 if info.genderID: 1170 height = 1.7 1171 else: 1172 height = 1.6 1173 head = (0, height, 0) 1174 rot = avatar.rotation 1175 vec = (view[0] - head[0], view[1] - head[1], view[2] - head[2]) 1176 vecLength = geo2.Vec3Distance((0, 0, 0), vec) 1177 vec = geo2.QuaternionTransformVector(geo2.QuaternionInverse(rot), vec) 1178 norm = 1.0 / math.sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]) 1179 vec = (vec[0] * norm, vec[1] * norm, vec[2] * norm) 1180 leftright = math.atan2(vec[2], vec[0]) 1181 updown = math.asin(vec[1]) 1182 leftright = 1 - abs(leftright) / 3.1415927 * 2 1183 updown = 2 * updown / 3.1415927 1184 dist = (vecLength - 1.0) / 7.0 1185 network = animparams.GetParamsPerAvatar(avatar, info.charID) 1186 network.SetControlParameter('ControlParameters|HeadLookLeftRight', leftright) 1187 network.SetControlParameter('ControlParameters|HeadLookUpDown', updown) 1188 network.SetControlParameter('ControlParameters|CameraDistance', dist) 1189 1190 @telemetry.ZONE_METHOD 1191 def FetchOldPortraitData(self, charID): 1192 PREFIX = 'ControlParameters|' 1193 cache = self.characterSvc.GetCachedPortraitInfo(charID) 1194 if cache is not None: 1195 self.lightingID = cache.lightID 1196 self.lightColorID = cache.lightColorID 1197 self.lightIntensity = cache.lightIntensity 1198 path = self.GetBackgroundPathFromID(cache.backgroundID) 1199 if path in self.GetAvailableBackgroundsPaths(): 1200 self.backdropPath = path 1201 self.poseID = cache.poseData['PortraitPoseNumber'] 1202 self.cameraPos = cache.cameraPosition 1203 self.cameraPoi = cache.cameraPoi 1204 self.cameraFov = cache.cameraFieldOfView 1205 params = [] 1206 for key in cache.poseData: 1207 params.append((PREFIX + key, cache.poseData[key])) 1208 1209 if len(params): 1210 self.characterSvc.SetControlParametersFromList(params, charID) 1211 else: 1212 portraitData = sm.GetService('cc').GetPortraitData(charID) 1213 if portraitData is not None: 1214 self.lightingID = portraitData.lightID 1215 self.lightColorID = portraitData.lightColorID 1216 self.lightIntensity = portraitData.lightIntensity 1217 path = self.GetBackgroundPathFromID(portraitData.backgroundID) 1218 if path in self.GetAvailableBackgroundsPaths(): 1219 self.backdropPath = path 1220 self.poseID = portraitData.portraitPoseNumber 1221 self.cameraPos = (portraitData.cameraX, portraitData.cameraY, portraitData.cameraZ) 1222 self.cameraPoi = (portraitData.cameraPoiX, portraitData.cameraPoiY, portraitData.cameraPoiZ) 1223 self.cameraFov = portraitData.cameraFieldOfView 1224 params = self.GetControlParametersFromPoseData(portraitData, fromDB=True).values() 1225 self.characterSvc.SetControlParametersFromList(params, charID) 1226 self.alreadyLoadedOldPortraitData = True 1227 1228 @telemetry.ZONE_METHOD 1229 def StartPortraitStep(self): 1230 info = self.GetInfo() 1231 if not getattr(self, 'alreadyLoadedOldPortraitData', False): 1232 if self.modeObject.GetOldPortraitData(): 1233 self.FetchOldPortraitData(info.charID) 1234 self.step = CharacterPortrait(parent=self.mainCont) 1235 self.SetAvatarScene() 1236 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 1237 if avatar is not None and avatar.animationUpdater is not None: 1238 network = animparams.GetParamsPerAvatar(avatar, info.charID) 1239 network.SetControlParameter('ControlParameters|NetworkMode', NETWORKMODE_PORTRAIT) 1240 if self.camera is None: 1241 self.camera = CharCreationCamera(avatar, ccConst.CAMERA_MODE_PORTRAIT) 1242 self.SetupCameraUpdateJob() 1243 else: 1244 self.camera.ToggleMode(ccConst.CAMERA_MODE_PORTRAIT, avatar=avatar, transformTime=500.0) 1245 if hasattr(self, 'cameraPos'): 1246 if self.gender_changed: 1247 if info.genderID: 1248 camDelta = 0.1 1249 else: 1250 camDelta = -0.1 1251 self.cameraPos = (self.cameraPos[0], self.cameraPos[1] + camDelta, self.cameraPos[2]) 1252 self.cameraPoi = (self.cameraPoi[0], self.cameraPoi[1] + camDelta, self.cameraPoi[2]) 1253 self.camera.PlacePortraitCamera(self.cameraPos, self.cameraPoi) 1254 xFactor, yFactor = self.camera.GetCorrectCameraXandYFactors(self.cameraPos, self.cameraPoi) 1255 self.camera.xFactor = self.camera.xTarget = xFactor 1256 self.camera.yFactor = self.camera.yTarget = yFactor 1257 if hasattr(self, 'storedPortraitCameraSettings'): 1258 self.camera.SetPointOfInterest(self.storedPortraitCameraSettings['poi']) 1259 self.camera.pitch = self.storedPortraitCameraSettings['pitch'] 1260 self.camera.yaw = self.storedPortraitCameraSettings['yaw'] 1261 self.camera.distance = self.storedPortraitCameraSettings['distance'] 1262 self.camera.xFactor = self.storedPortraitCameraSettings['xFactor'] 1263 self.camera.yFactor = self.storedPortraitCameraSettings['yFactor'] 1264 self.camera.fieldOfView = self.storedPortraitCameraSettings['fieldOfView'] 1265 self.UpdateLights() 1266 self.characterSvc.StartPosing(charID=info.charID, callback=self.step.ChangeSculptingCursor) 1267 1268 @telemetry.ZONE_METHOD 1269 def StartNamingStep(self, *args): 1270 self.SetAvatarScene() 1271 self.SetDefaultLighting() 1272 self.CaptureAndSetActivePortrait() 1273 self.step = CharacterNaming(parent=self.mainCont) 1274 self.SetUpNamingStepCamera() 1275 self.SetAvatarAnimationNetworkMode(NETWORKMODE_BASIC) 1276 1277 def CaptureAndSetActivePortrait(self): 1278 self.SetAvatarAnimationNetworkMode(NETWORKMODE_PORTRAIT) 1279 while not self.characterSvc.sculpting: 1280 blue.synchro.Yield() 1281 1282 info = self.GetInfo() 1283 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 1284 self.camera = CharCreationCamera(avatar, ccConst.CAMERA_MODE_PORTRAIT) 1285 self.camera.SetMoveCallback(self.CameraMoveCB) 1286 self.camera.Update() 1287 self.backdropPath = random.choice(ccConst.defaultBackgroundOptions) 1288 self.activePortrait = self.CapturePortrait(0) 1289 1290 def SetUpNamingStepCamera(self): 1291 info = self.GetInfo() 1292 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 1293 self.camera = CharCreationCamera(avatar=avatar) 1294 self.camera.fieldOfView = 0.3 1295 self.camera.distance = 8.0 1296 self.camera.frontClip = 3.5 1297 self.camera.backclip = 100.0 1298 self.SetupCameraUpdateJob() 1299 self.camera.SetPointOfInterest((0.0, self.camera.avatarEyeHeight / 2.0, 0.0)) 1300 1301 def SetAvatarAnimationNetworkMode(self, networkMode): 1302 info = self.GetInfo() 1303 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 1304 if avatar is not None: 1305 if info.charID in self.characterSvc.characters: 1306 network = animparams.GetParamsPerAvatar(avatar, info.charID) 1307 network.SetControlParameter('ControlParameters|NetworkMode', networkMode) 1308 while network.rebuilding: 1309 blue.synchro.Yield() 1310 1311 @telemetry.ZONE_METHOD 1312 def ClearSteps(self, what = None, force = 0, *args): 1313 stepAlreadyCleared = getattr(self.step, 'stepAlreadyCleared', 0) 1314 if not force and stepAlreadyCleared or not getattr(self.mainNav, 'ResetToStep', None): 1315 return 1316 currentStepID = self.stepID 1317 currentStepOrder = GetStepOrder(currentStepID) 1318 if currentStepOrder <= GetStepOrder(ccConst.CUSTOMIZATIONSTEP): 1319 self.ClearFacePortrait() 1320 self.ClearPortraitInfo() 1321 self.schoolID = None 1322 if what in ('bloodline', 'race'): 1323 self.schoolID = None 1324 if currentStepOrder <= GetStepOrder(ccConst.BLOODLINESTEP): 1325 self.avatarScene = None 1326 self.characterSvc.TearDown() 1327 self.schoolID = None 1328 if currentStepOrder <= GetStepOrder(ccConst.EMPIRESTEP): 1329 self.TearDown() 1330 firstStep = self.availableSteps[0] 1331 self.stepsUsed = GetStepsUpToAndIncluding(currentStepID) or {firstStep} 1332 self.mainNav.ResetToStep(currentStepID, stepsUsed=self.stepsUsed) 1333 if self.step: 1334 self.step.stepAlreadyCleared = 1 1335 1336 @telemetry.ZONE_METHOD 1337 def Cleanup(self): 1338 self.characterSvc.StopEditing() 1339 info = self.GetInfo() 1340 charID = info.charID 1341 if charID in self.characterSvc.characters: 1342 self.characterSvc.StopPosing(charID) 1343 self.scene = None 1344 self.ClearCamera() 1345 self.sceneManager.UnregisterScene('characterCreation') 1346 1347 @telemetry.ZONE_METHOD 1348 def SetupScene(self, path): 1349 scene = trinity.Load(path) 1350 blue.resMan.Wait() 1351 if self.IsSlowMachine(): 1352 if hasattr(scene, 'shadowCubeMap'): 1353 scene.shadowCubeMap.enabled = False 1354 if hasattr(scene, 'ssao') and hasattr(scene.ssao, 'enable'): 1355 scene.ssao.enable = False 1356 if hasattr(scene, 'ambientColor'): 1357 scene.ambientColor = (0.25, 0.25, 0.25) 1358 elif scene: 1359 if hasattr(scene, 'shadowCubeMap'): 1360 scene.shadowCubeMap.enabled = False 1361 self.scene = scene 1362 self.sceneManager.RegisterScene(scene, 'characterCreation') 1363 self.sceneManager.SetRegisteredScenes('characterCreation') 1364 1365 @telemetry.ZONE_METHOD 1366 def ReduceLights(self): 1367 scene = self.scene 1368 if hasattr(scene, 'lights'): 1369 lightsToRemove = [] 1370 for each in scene.lights: 1371 if each.name != 'FrontMain': 1372 lightsToRemove.append(each) 1373 1374 for each in lightsToRemove: 1375 scene.lights.remove(each) 1376 1377 def ApplyGraphicsSettingsToDoll(self, doll): 1378 doll.overrideLod = LOD_SKIN 1379 textureQuality = gfxsettings.Get(gfxsettings.GFX_CHAR_TEXTURE_QUALITY) 1380 doll.textureResolution = ccConst.TEXTURE_RESOLUTIONS[textureQuality] 1381 if self.IsSlowMachine(): 1382 doll.useFastShader = True 1383 else: 1384 doll.useFastShader = False 1385 1386 @telemetry.ZONE_METHOD 1387 def AddCharacter(self, charID, bloodlineID, raceID, genderID, scene = None, dna = None, validateColors = True, noRandomize = False): 1388 self.ResetDna() 1389 self.characterSvc.AddCharacterToScene(charID, scene or self.scene, ccUtil.GenderIDToPaperDollGender(genderID), dna=dna, bloodlineID=bloodlineID, raceID=raceID, updateDoll=False, noRandomize=noRandomize) 1390 self.doll = self.characterSvc.GetSingleCharactersDoll(charID) 1391 while self.doll.IsBusyUpdating(): 1392 blue.synchro.Yield() 1393 1394 self.ApplyGraphicsSettingsToDoll(self.doll) 1395 self.bloodlineID = bloodlineID 1396 self.characterSvc.SetDollBloodline(charID, bloodlineID) 1397 if validateColors: 1398 for categoryName in ccConst.COLORMAPPING.keys(): 1399 self.UpdateColorSelectionFromDoll(categoryName) 1400 self.ValidateColors(categoryName) 1401 1402 self.StartDnaLogging() 1403 self.characterSvc.UpdateDoll(charID, fromWhere='AddCharacter') 1404 1405 def GetAvailableBackgroundsPaths(self): 1406 bgOptions = [] 1407 if gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN): 1408 bgOptions += ccConst.greenscreenBackgroundOptions 1409 authoredBackgrounds = self.characterSvc.GetAvailableBackgrounds() 1410 for eachResource in authoredBackgrounds: 1411 path = eachResource.resPath 1412 bgOptions.append(path) 1413 1414 return bgOptions 1415 1416 @telemetry.ZONE_METHOD 1417 def GetAvailableStyles(self, modifier): 1418 info = self.GetInfo() 1419 gender = info.genderID 1420 bloodline = info.bloodlineID 1421 currentModifier = self.characterSvc.GetModifierByCategory(info.charID, modifier) 1422 itemTypes = self.characterSvc.GetAvailableTypesByCategory(modifier, gender, info.raceID) 1423 activeIndex = None 1424 if currentModifier: 1425 currentType = currentModifier.GetTypeData() 1426 for i, each in enumerate(itemTypes): 1427 if each[1][0] == currentType[0] and each[1][1] == currentType[1] and each[1][2] == currentType[2]: 1428 activeIndex = i 1429 1430 return (itemTypes, activeIndex) 1431 1432 def GetModifierIntensity(self, modifierPath): 1433 info = self.GetInfo() 1434 modifier = self.characterSvc.GetModifiersByCategory(info.charID, modifierPath) 1435 if modifier: 1436 return modifier[0].weight 1437 return 0.0 1438 1439 @telemetry.ZONE_METHOD 1440 def GetAvailableColors(self, modifier): 1441 info = self.GetInfo() 1442 colors, activeColorIndex = self.characterSvc.GetCharacterColorVariations(info.charID, modifier) 1443 colors = tuple(colors) 1444 retColors = [] 1445 for name, color in colors: 1446 if color and type(color[0]) == types.TupleType: 1447 r = g = b = 0 1448 for _r, _g, _b, _a in color: 1449 r += _r 1450 g += _g 1451 b += _b 1452 1453 r = r / float(len(color)) 1454 g = g / float(len(color)) 1455 b = b / float(len(color)) 1456 retColors.append((name, (r, 1457 g, 1458 b, 1459 1.0), color)) 1460 else: 1461 retColors.append((name, color, color)) 1462 1463 return (retColors, activeColorIndex) 1464 1465 @telemetry.ZONE_METHOD 1466 def SetColorValue(self, modifier, primaryColor, secondaryColor = None, doUpdate = True, ignoreValidate = False): 1467 self._setColorsByCategory[modifier] = (primaryColor, secondaryColor) 1468 info = self.GetInfo() 1469 self.characterSvc.SetColorValueByCategory(info.charID, modifier, primaryColor, secondaryColor, doUpdate=False) 1470 if ccUtil.HasUserDefinedSpecularity(modifier): 1471 specValue = self._setSpecularityByCategory.setdefault(modifier, 0.5) 1472 self.SetColorSpecularity(modifier, specValue, doUpdate=False) 1473 if ccUtil.HasUserDefinedWeight(modifier): 1474 defaultIntensity = ccConst.defaultIntensity.get(modifier, 0.5) 1475 intensityValue = self._setIntensityByCategory.setdefault(modifier, defaultIntensity) 1476 self.SetIntensity(modifier, intensityValue, doUpdate=False) 1477 if not ignoreValidate: 1478 self.ValidateColors(modifier) 1479 if doUpdate: 1480 self.characterSvc.UpdateDoll(info.charID, fromWhere='SetColorValue') 1481 1482 def GetSpecularityByCategory(self, category): 1483 return self._setSpecularityByCategory.get(category, 0.5) 1484 1485 def GetIntensityByCategory(self, category): 1486 return self._setIntensityByCategory.get(category, 0.5) 1487 1488 @telemetry.ZONE_METHOD 1489 def SetRandomColorSpecularity(self, modifier, doUpdate = True): 1490 self.SetColorSpecularity(modifier, random.random(), doUpdate=doUpdate) 1491 1492 @telemetry.ZONE_METHOD 1493 def SetColorSpecularity(self, modifier, specularity, doUpdate = True): 1494 self._setSpecularityByCategory[modifier] = specularity 1495 info = self.GetInfo() 1496 self.characterSvc.SetColorSpecularityByCategory(info.charID, modifier, specularity, doUpdate=doUpdate) 1497 1498 @telemetry.ZONE_METHOD 1499 def SetRandomHairDarkness(self, doUpdate = True): 1500 self.SetHairDarkness(random.random(), doUpdate=doUpdate) 1501 1502 @telemetry.ZONE_METHOD 1503 def SetHairDarkness(self, darkness, doUpdate = True): 1504 info = self.GetInfo() 1505 self.characterSvc.SetHairDarkness(info.charID, darkness) 1506 if doUpdate: 1507 sm.GetService('character').UpdateDoll(info.charID, fromWhere='SetHairDarkness') 1508 1509 @telemetry.ZONE_METHOD 1510 def SetRandomIntensity(self, modifier, doUpdate = True): 1511 self.SetIntensity(modifier, random.random(), doUpdate=doUpdate) 1512 1513 @telemetry.ZONE_METHOD 1514 def SetIntensity(self, modifier, value, doUpdate = True): 1515 info = self.GetInfo() 1516 if modifier == ccConst.muscle: 1517 self.characterSvc.SetCharacterMuscularity(info.charID, value, doUpdate=doUpdate) 1518 elif modifier == ccConst.weight: 1519 self.characterSvc.SetCharacterWeight(info.charID, value, doUpdate=doUpdate) 1520 else: 1521 self._setIntensityByCategory[modifier] = value 1522 self.characterSvc.SetWeightByCategory(info.charID, modifier, value, doUpdate=doUpdate) 1523 1524 @telemetry.ZONE_METHOD 1525 def SetItemType(self, itemType, weight = 1.0, doUpdate = True): 1526 info = self.GetInfo() 1527 category = self.characterSvc.GetCategoryFromResPath(itemType[1][0]) 1528 if category in CLOTHING_ITEMS: 1529 if category in self.clothesStorage: 1530 self.clothesStorage.pop(category) 1531 self.clothesMetaStorage.pop(category) 1532 self.ToggleClothes(forcedValue=0, doUpdate=False) 1533 self.characterSvc.ApplyTypeToDoll(info.charID, itemType, weight=weight, doUpdate=False) 1534 if category in self._setColorsByCategory: 1535 var1, var2 = self._setColorsByCategory[category] 1536 self.SetColorValue(category, var1, var2, doUpdate=False) 1537 self.ValidateColors(category) 1538 if doUpdate: 1539 self.characterSvc.UpdateDoll(info.charID, fromWhere='SetItemType') 1540 1541 @telemetry.ZONE_METHOD 1542 def SetStyle(self, category, style, variation = None, doUpdate = True): 1543 info = self.GetInfo() 1544 if style or variation or category in CLOTHING_ITEMS: 1545 self.ToggleClothes(forcedValue=0, doUpdate=False) 1546 self.characterSvc.ApplyItemToDoll(info.charID, category, style, removeFirst=True, variation=variation, doUpdate=False) 1547 if style: 1548 if category in self._setColorsByCategory: 1549 var1, var2 = self._setColorsByCategory[category] 1550 self.SetColorValue(category, var1, var2, doUpdate=False) 1551 self.ValidateColors(category) 1552 if doUpdate: 1553 self.characterSvc.UpdateDoll(info.charID, fromWhere='SetStyle') 1554 1555 @telemetry.ZONE_METHOD 1556 def ValidateColors(self, category): 1557 if category not in ccConst.COLORMAPPING: 1558 return 1559 info = self.GetInfo() 1560 categoryColors = self.characterSvc.GetAvailableColorsForCategory(category, info.genderID, info.raceID) 1561 if not categoryColors: 1562 return 1563 primary, secondary = categoryColors 1564 hasValidColor = False 1565 modifier = self.characterSvc.GetModifiersByCategory(info.charID, category) 1566 if modifier: 1567 currentColor = modifier[0].GetColorizeData() 1568 if secondary: 1569 if modifier[0].metaData.numColorAreas > 1: 1570 for primaryColorTuple in primary: 1571 primaryColorName, primaryDisplayColor, primaryColorValue = primaryColorTuple 1572 pA, pB, pC = primaryColorValue['colors'] 1573 for secondaryColorTuple in secondary: 1574 secondaryColorName, secondaryDisplayColor, secondaryColorValue = secondaryColorTuple 1575 srA, srB, srC = secondaryColorValue['colors'] 1576 if pA == currentColor[0] and srB == currentColor[1] and srC == currentColor[2]: 1577 hasValidColor = True 1578 if category not in self._setColorsByCategory or self._setColorsByCategory[category][1] == None: 1579 self.SetColorValue(category, primaryColorTuple, secondaryColorTuple, doUpdate=False, ignoreValidate=True) 1580 break 1581 1582 if hasValidColor: 1583 break 1584 1585 if not hasValidColor: 1586 for primaryColorTuple in primary: 1587 primaryColorName, primaryDisplayColor, primaryColorValue = primaryColorTuple 1588 if primaryColorValue['colors'] == currentColor: 1589 hasValidColor = True 1590 self.SetColorValue(category, primaryColorTuple, secondary[0], doUpdate=False, ignoreValidate=True) 1591 break 1592 1593 else: 1594 for primaryColorTuple in primary: 1595 primaryColorName, primaryDisplayColor, primaryColorValue = primaryColorTuple 1596 if primaryColorValue['colors'] == currentColor: 1597 hasValidColor = True 1598 if category not in self._setColorsByCategory: 1599 self.SetColorValue(category, primaryColorTuple, None, doUpdate=False, ignoreValidate=True) 1600 break 1601 else: 1602 if category in self._setColorsByCategory: 1603 hasValidColor = True 1604 else: 1605 for primaryColorTuple in primary: 1606 primaryColorName, primaryDisplayColor, primaryColorValue = primaryColorTuple 1607 if primaryColorValue['colors'] == currentColor: 1608 hasValidColor = True 1609 if category not in self._setColorsByCategory: 1610 self.SetColorValue(category, primaryColorTuple, None, doUpdate=False, ignoreValidate=True) 1611 break 1612 1613 if not hasValidColor and primary: 1614 if secondary: 1615 var2 = secondary[0] 1616 else: 1617 var2 = None 1618 self.SetColorValue(category, primary[0], var2, doUpdate=False, ignoreValidate=True) 1619 1620 def UpdateColorSelectionFromDoll(self, category): 1621 if category not in ccConst.COLORMAPPING: 1622 return 1623 info = self.GetInfo() 1624 categoryColors = self.characterSvc.GetAvailableColorsForCategory(category, info.genderID, info.raceID) 1625 if not categoryColors: 1626 return 1627 primary, secondary = categoryColors 1628 modifier = self.characterSvc.GetModifiersByCategory(info.charID, category) 1629 if modifier: 1630 corPrimary = None 1631 corSecondary = None 1632 try: 1633 chosenPrimary, chosenSecondary = self.characterSvc.GetSingleCharactersMetadata(info.charID).typeColors[category] 1634 for primaryColorTuple in primary: 1635 if primaryColorTuple[0] == chosenPrimary: 1636 corPrimary = primaryColorTuple 1637 break 1638 1639 if secondary and chosenSecondary: 1640 for secondaryColorTuple in secondary: 1641 if secondaryColorTuple[0] == chosenSecondary: 1642 corSecondary = secondaryColorTuple 1643 break 1644 1645 except KeyError: 1646 log.LogWarn('KeyError when getting Metadata for a single character in characterCreationContainer.UpdateColorSelectionFromDoll', info.charID, category) 1647 1648 if corPrimary is not None: 1649 self._setColorsByCategory[category] = (corPrimary, corSecondary) 1650 if category in self.characterSvc.characterMetadata[info.charID].typeWeights: 1651 self._setIntensityByCategory[category] = self.characterSvc.characterMetadata[info.charID].typeWeights[category] 1652 if category in self.characterSvc.characterMetadata[info.charID].typeSpecularity: 1653 self._setSpecularityByCategory[category] = self.characterSvc.characterMetadata[info.charID].typeSpecularity[category] 1654 1655 @telemetry.ZONE_METHOD 1656 def ClearCategory(self, category, doUpdate = True): 1657 self.SetStyle(category, style=None, doUpdate=doUpdate) 1658 1659 @telemetry.ZONE_METHOD 1660 def CheckDnaLog(self, trigger = None): 1661 if self.step and self.step.sr.historySlider: 1662 currentIndex, maxIndex = self.step.sr.historySlider.GetCurrentIndexAndMaxIndex() 1663 if currentIndex != maxIndex: 1664 self.ClearDnaLogFromIndex(currentIndex) 1665 1666 @telemetry.ZONE_METHOD 1667 def ClearCamera(self): 1668 if self.camera is not None: 1669 for priority, behavior in self.camera.cameraBehaviors: 1670 behavior.camera = None 1671 1672 del self.camera.cameraBehaviors[:] 1673 self.camera.avatar = None 1674 self.camera = None 1675 1676 @telemetry.ZONE_METHOD 1677 def SetDefaultLighting(self): 1678 self.SetLightScene('res:/Graphics/Character/Global/PaperdollSettings/LightSettings/Normal.red') 1679 if self.IsSlowMachine(): 1680 self.ReduceLights() 1681 1682 @telemetry.ZONE_METHOD 1683 def SetupCameraUpdateJob(self): 1684 self.sceneManager.RefreshJob(self.camera) 1685 if self.cameraUpdateJob is None: 1686 self.cameraUpdateJob = trinity.renderJob.CreateRenderJob('cameraUpdate') 1687 r = trinity.TriStepPythonCB() 1688 r.SetCallback(self.UpdateCamera) 1689 self.cameraUpdateJob.steps.append(r) 1690 self.sceneManager.characterRenderJob.SetCameraUpdate(self.cameraUpdateJob) 1691 1692 @telemetry.ZONE_METHOD 1693 def UpdateCamera(self): 1694 if self.camera is not None: 1695 self.camera.Update() 1696 1697 @telemetry.ZONE_METHOD 1698 def PickObjectUV(self, pos): 1699 return self.scene.PickObjectUV(pos[0], pos[1], self.camera.projectionMatrix, self.camera.viewMatrix, trinity.device.viewport) 1700 1701 @telemetry.ZONE_METHOD 1702 def PickObjectAndArea(self, pos): 1703 return self.scene.PickObjectAndArea(pos[0], pos[1], self.camera.projectionMatrix, self.camera.viewMatrix, trinity.device.viewport) 1704 1705 @telemetry.ZONE_METHOD 1706 def PickObject(self, pos): 1707 if not self.step: 1708 return 1709 if self.scene is not None: 1710 return self.scene.PickObject(pos[0], pos[1], self.camera.projectionMatrix, self.camera.viewMatrix, self.step.GetViewportForPicking()) 1711 1712 @telemetry.ZONE_METHOD 1713 def SaveCurrentCharacter(self, charactername, bloodlineID, genderID, portraitID): 1714 total = 3 1715 sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CharacterCreation/Registering'), localization.GetByLabel('UI/CharacterCreation/CompilePrefs'), 1, total) 1716 try: 1717 if self.portraitInfo[portraitID] is None: 1718 raise UserError('CharCreationNoPortrait') 1719 info = self.GetInfo() 1720 charInfo = self.characterSvc.GetCharacterAppearanceInfo(info.charID) 1721 charID = sm.GetService('cc').CreateCharacterWithDoll(charactername, bloodlineID, genderID, const.ancestryUndefined, charInfo, self.portraitInfo[portraitID], info.schoolID, info.raceID) 1722 except UserError as what: 1723 if not what.msg.startswith('CharNameInvalid'): 1724 prompt_player_fsd_dialog(*what.args) 1725 return 1726 sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CharacterCreation/Registering'), localization.GetByLabel('UI/CharacterCreation/FailedForSomeReason'), 3, total) 1727 else: 1728 sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CharacterCreation/Registering'), localization.GetByLabel('UI/CharacterCreation/InsertingRecord'), 2, total) 1729 sm.GetService('photo').AddPortrait(self.GetPortraitSnapshotPath(portraitID), charID) 1730 sm.GetService('loading').ProgressWnd(localization.GetByLabel('UI/CharacterCreation/Registering'), localization.GetByLabel('UI/Generic/Done'), 3, total) 1731 return charID 1732 finally: 1733 self.sessionSounds = [] 1734 1735 @telemetry.ZONE_METHOD 1736 def UpdateExistingCharacter(self, *args): 1737 portraitID = self.activePortraitIndex 1738 charID = self.charID 1739 activePortraitInfo = self.portraitInfo[portraitID] 1740 if activePortraitInfo is None: 1741 raise UserError('CharCreationNoPortrait') 1742 dollExists = self.dna is not None 1743 dollInfo = self.characterSvc.GetCharacterAppearanceInfo(charID) 1744 availableTypeIDs = sm.GetService('cc').GetMyApparel() 1745 metadata = self.characterSvc.characterMetadata[charID] 1746 typesInUse = metadata.types 1747 for resourceID in typesInUse.itervalues(): 1748 if resourceID: 1749 info = cfg.paperdollResources.Get(resourceID) 1750 if info.typeID is not None and info.typeID not in availableTypeIDs: 1751 raise UserError('ItemNotAtStation', {'item': info.typeID}) 1752 1753 bgInfo = cfg.paperdollPortraitResources.Get(activePortraitInfo.backgroundID) 1754 if bgInfo and bgInfo.typeID is not None and bgInfo.typeID not in availableTypeIDs: 1755 raise UserError('ItemNotAtStation', {'item': bgInfo.typeID}) 1756 try: 1757 if self.mode == ccConst.MODE_FULL_RECUSTOMIZATION: 1758 sm.GetService('cc').UpdateExistingCharacterFull(charID, dollInfo, activePortraitInfo, dollExists, metadata['genderID'], flush=True) 1759 elif self.mode == ccConst.MODE_LIMITED_RECUSTOMIZATION: 1760 sm.GetService('cc').UpdateExistingCharacterLimited(charID, dollInfo, activePortraitInfo, dollExists) 1761 elif self.mode == ccConst.MODE_FULL_BLOODLINECHANGE: 1762 info = self.GetInfo() 1763 sm.GetService('cc').UpdateExistingCharacterBloodline(charID, info.bloodlineID, True) 1764 except UserError as e: 1765 if e.msg == 'CCInvalidClothing': 1766 if e.dict['genderID'] == 0: 1767 modifierNames = femaleModifierDisplayNames 1768 else: 1769 modifierNames = maleModifierDisplayNames 1770 modifierName = modifierNames.get(e.dict['modifierKey'], '') 1771 prompt_player_fsd_dialog('CustomInfo', {'info': localization.GetByLabel('UI/Login/CharacterCreation/InvalidApparelAssets', modifierName=localization.GetByLabel(modifierName))}) 1772 return 1773 1774 sm.GetService('photo').AddPortrait(self.GetPortraitSnapshotPath(portraitID), charID) 1775 self.characterSvc.CachePortraitInfo(self.charID, self.portraitInfo[self.activePortraitIndex]) 1776 self.metrics.complete_cc(charid=charID) 1777 if self.dollState != paperdoll.State.force_recustomize: 1778 self.ExitToStation() 1779 else: 1780 uthread.pool('GameUI::ActivateView::charsel', sm.GetService('viewState').ActivateView, 'charsel') 1781 1782 @telemetry.ZONE_METHOD 1783 def SetBackdrop(self, backdropPath): 1784 self.backdropPath = backdropPath 1785 1786 @telemetry.ZONE_METHOD 1787 def SetPoseID(self, poseID): 1788 self.poseID = poseID 1789 1790 @telemetry.ZONE_METHOD 1791 def SetLightScene(self, lightPath, scene = None): 1792 scene = scene or self.scene 1793 lightScene = trinity.Load(lightPath) 1794 if scene: 1795 lightList = [] 1796 for l in scene.lights: 1797 lightList.append(l) 1798 1799 for l in lightList: 1800 scene.RemoveLightSource(l) 1801 1802 for l in lightScene.lights: 1803 scene.AddLightSource(l) 1804 1805 @telemetry.ZONE_METHOD 1806 def SetLights(self, lightID): 1807 self.lightingID = lightID 1808 self.UpdateLights() 1809 1810 @telemetry.ZONE_METHOD 1811 def GetLight(self): 1812 return self.lightingID 1813 1814 @telemetry.ZONE_METHOD 1815 def SetLightColor(self, lightID): 1816 self.lightColorID = lightID 1817 self.UpdateLights() 1818 1819 @telemetry.ZONE_METHOD 1820 def GetLightColor(self): 1821 return self.lightColorID 1822 1823 @telemetry.ZONE_METHOD 1824 def SetLightsAndColor(self, lightID, colorID): 1825 self.lightingID = lightID 1826 self.lightColorID = colorID 1827 self.UpdateLights() 1828 1829 @telemetry.ZONE_METHOD 1830 def SetLightIntensity(self, intensity): 1831 self.lightIntensity = intensity 1832 self.UpdateLights() 1833 1834 @telemetry.ZONE_METHOD 1835 def GetLightIntensity(self): 1836 return self.lightIntensity 1837 1838 @telemetry.ZONE_METHOD 1839 def UpdateLights(self): 1840 lightsPath = GetGraphicFile(self.lightingID) 1841 lightColorPath = GetGraphicFile(self.lightColorID) 1842 lightScene = trinity.Load(lightsPath) 1843 lightColorScene = trinity.Load(lightColorPath) 1844 ccUtil.SetupLighting(self.scene, lightScene, lightColorScene, self.lightIntensity) 1845 if self.IsSlowMachine(): 1846 self.ReduceLights() 1847 1848 @telemetry.ZONE_METHOD 1849 def GetBackdrop(self): 1850 return self.backdropPath 1851 1852 @telemetry.ZONE_METHOD 1853 def GetPoseId(self): 1854 return getattr(self, 'poseID', 0) 1855 1856 @telemetry.ZONE_METHOD 1857 def StartEditMode(self, callback = None, **kwds): 1858 if callback is None and kwds.get('mode', None) == 'sculpt': 1859 callback = getattr(self.step, 'ChangeSculptingCursor', None) 1860 info = self.GetInfo() 1861 self.characterSvc.StartEditMode(info.charID, self.scene, self.camera, callback=callback, **kwds) 1862 1863 @telemetry.ZONE_METHOD 1864 def UpdateBackdropLite(self, raceID, mouseEnter = False, *args): 1865 bdScene = self.sceneManager.Get2DBackdropScene() 1866 if not bdScene: 1867 return 1868 blue.resMan.SetUrgentResourceLoads(True) 1869 for each in bdScene.children: 1870 each.display = False 1871 if mouseEnter: 1872 if raceID: 1873 if each.name == 'mouseoverSprite_%d' % raceID: 1874 each.display = True 1875 else: 1876 each.display = True 1877 elif each.name == 'backdropSprite': 1878 each.texturePrimary.resPath = 'res:/UI/Texture/CharacterCreation/bg/RACE_Background_%d.dds' % raceID 1879 each.display = True 1880 1881 blue.resMan.SetUrgentResourceLoads(False) 1882 1883 def _GetDpiScaledWidthAndHeight(self): 1884 desktopWidth = int(uicore.desktop.width * uicore.desktop.dpiScaling) 1885 desktopHeight = int(uicore.desktop.height * uicore.desktop.dpiScaling) 1886 return (desktopWidth, desktopHeight) 1887 1888 def _AssembleBackDropSprite(self, name, res_path, bgSize = None): 1889 desktopWidth, desktopHeight = self._GetDpiScaledWidthAndHeight() 1890 if bgSize is None: 1891 bgSize = max(desktopWidth, desktopHeight) 1892 sprite = trinity.Tr2Sprite2d() 1893 sprite.name = name 1894 sprite.displayWidth = bgSize 1895 sprite.displayHeight = bgSize 1896 sprite.displayY = (desktopHeight - bgSize) / 2 1897 sprite.displayX = (desktopWidth - bgSize) / 2 1898 sprite.texturePrimary = trinity.Tr2Sprite2dTexture() 1899 sprite.texturePrimary.resPath = res_path 1900 sprite.display = True 1901 return sprite 1902 1903 def _GetCurrentSpritePath(self): 1904 if self.stepID == ccConst.EMPIRESTEP: 1905 return ccConst.EMPIRE_PANELS_BACKGROUND 1906 if self.stepID in ccConst.EMPIRE_SELECTION_STEPS: 1907 return ccConst.EMPIRE_BACKGROUND_BY_RACE.get(self.raceID, None) 1908 1909 def _GetBackdropSpriteSizes(self): 1910 clientHeight = uicore.desktop.height 1911 percentOfClientHeight = float(clientHeight) / BG_HEIGHT 1912 height = clientHeight 1913 width = int(percentOfClientHeight * BG_WIDTH) 1914 return (width, height) 1915 1916 def _CreateNewBackdropSprite(self, path): 1917 spriteID = const.races[self.raceID] if self.raceID else 'Global' 1918 width, height = self._GetBackdropSpriteSizes() 1919 return Sprite(name='charCreationBackground_%s' % spriteID, parent=self, texturePath=path, align=uiconst.CENTER, width=width, height=height, opacity=BG_OPACITY) 1920 1921 def UpdateBackdropSprite(self): 1922 spritePath = self._GetCurrentSpritePath() 1923 if spritePath is None: 1924 if self.backgroundSprite and not self.backgroundSprite.destroyed: 1925 self.backgroundSprite.Close() 1926 return 1927 if self.backgroundSprite and not self.backgroundSprite.destroyed: 1928 if spritePath == self.backgroundSprite.texturePath: 1929 width, height = self._GetBackdropSpriteSizes() 1930 self.backgroundSprite.width = width 1931 self.backgroundSprite.height = height 1932 return 1933 oldSprite = self.backgroundSprite 1934 oldSpriteOrder = oldSprite.GetOrder() 1935 self.backgroundSprite = self._CreateNewBackdropSprite(spritePath) 1936 self.backgroundSprite.SetOrder(oldSpriteOrder) 1937 uicore.animations.SpMaskIn(self.backgroundSprite, duration=BACKGROUND_TRANSITION_SECONDS, callback=oldSprite.Close) 1938 elif self.stepID in ccConst.EMPIRE_SELECTION_STEPS: 1939 self.backgroundSprite = self._CreateNewBackdropSprite(spritePath) 1940 1941 @telemetry.ZONE_METHOD 1942 def UpdateBackdrop(self, *args): 1943 self.UpdateBackdropSprite() 1944 bdScene = self.sceneManager.Get2DBackdropScene() 1945 if not bdScene: 1946 return 1947 bdScene.clearBackground = True 1948 for each in bdScene.children[:]: 1949 bdScene.children.remove(each) 1950 1951 for each in bdScene.curveSets[:]: 1952 bdScene.curveSets.remove(each) 1953 1954 self.colorCodedBackDrop = None 1955 desktopWidth, desktopHeight = self._GetDpiScaledWidthAndHeight() 1956 size = min(desktopHeight, desktopWidth) 1957 margin = -200 1958 info = self.GetInfo() 1959 if gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN): 1960 backdropSprite = self._AssembleBackDropSprite(u'greenscreen', 'res:/UI/Texture/CharacterCreation/backdrops/Background_1001_thumb.dds') 1961 bdScene.children.append(backdropSprite) 1962 else: 1963 if self.stepID in ccConst.EMPIRE_SELECTION_STEPS: 1964 return 1965 if info.raceID == const.raceCaldari: 1966 rn = 'caldari' 1967 bgcolor = (74 / 255.0, 87 / 255.0, 97 / 255.0) 1968 elif info.raceID == const.raceAmarr: 1969 rn = 'amarr' 1970 bgcolor = (93 / 255.0, 89 / 255.0, 74 / 255.0) 1971 elif info.raceID == const.raceMinmatar: 1972 rn = 'minmatar' 1973 bgcolor = (92 / 255.0, 81 / 255.0, 80 / 255.0) 1974 elif info.raceID == const.raceGallente: 1975 rn = 'gallente' 1976 bgcolor = (77 / 255.0, 94 / 255.0, 93 / 255.0) 1977 else: 1978 rn = 'caldari' 1979 bgcolor = (74 / 255.0, 87 / 255.0, 97 / 255.0) 1980 log.LogWarn('Unknown raceID in characterCreationContainer.UpdateBackground', info.raceID) 1981 mainHalo = trinity.Tr2Sprite2d() 1982 mainHalo.name = u'mainHalo' 1983 mainHalo.texturePrimary = trinity.Tr2Sprite2dTexture() 1984 mainHalo.blendMode = trinity.TR2_SBM_ADD 1985 r, g, b = bgcolor 1986 mainHalo.color = (r * 0.75, 1987 g * 0.75, 1988 b * 0.75, 1989 1.0) 1990 mainHalo.displayWidth = mainHalo.displayHeight = max(desktopWidth, desktopHeight) * 1.5 1991 mainHalo.displayX = (desktopWidth - mainHalo.displayWidth) / 2 1992 mainHalo.displayY = (desktopHeight - mainHalo.displayHeight) / 2 1993 mainHalo.display = True 1994 mainHalo.texturePrimary.resPath = 'res:/UI/Texture/CharacterCreation/mainCenterHalo.dds' 1995 bdScene.children.append(mainHalo) 1996 if self.stepID == ccConst.PORTRAITSTEP: 1997 activeBackdrop = self.GetBackdrop() 1998 if activeBackdrop: 1999 portraitBackground = trinity.Tr2Sprite2d() 2000 portraitBackground.name = u'portraitBackground' 2001 bdScene.children.insert(0, portraitBackground) 2002 portraitBackground.displayX = (desktopWidth - size) * 0.5 2003 portraitBackground.displayY = (desktopHeight - size) * 0.5 2004 portraitBackground.displayWidth = size 2005 portraitBackground.displayHeight = size 2006 if not portraitBackground.texturePrimary: 2007 portraitBackground.texturePrimary = trinity.Tr2Sprite2dTexture() 2008 portraitBackground.texturePrimary.resPath = activeBackdrop 2009 portraitBackground.color = (1, 1, 1, 1) 2010 portraitBackground.display = True 2011 portraitBackground.blendMode = trinity.TR2_SBM_BLEND 2012 else: 2013 if gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN): 2014 return 2015 mainSize = size - margin 2016 cs = trinity.TriCurveSet() 2017 cs.name = 'RotationCurveSet' 2018 bdScene.curveSets.append(cs) 2019 for textureNo, textureSize in ((1, 468 / 1024.0), 2020 (2, 580 / 1024.0), 2021 (3, 1.0), 2022 (4, 1.0)): 2023 tf = trinity.Tr2Sprite2dTransform() 2024 tf.name = u'tf' 2025 tf.displayX = desktopWidth * 0.5 2026 tf.displayY = desktopHeight * 0.5 2027 bdScene.children.append(tf) 2028 circleBG = trinity.Tr2Sprite2d() 2029 circleBG.name = u'circleBG' 2030 circleBG.texturePrimary = trinity.Tr2Sprite2dTexture() 2031 circleBG.texturePrimary.resPath = 'res:/UI/Texture/CharacterCreation/circularRaceBgs/%s_%s.dds' % (rn, textureNo) 2032 circleBG.color = (0.025, 0.025, 0.025, 1.0) 2033 circleBG.blendMode = trinity.TR2_SBM_BLEND 2034 circleBG.displayWidth = mainSize * textureSize 2035 circleBG.displayHeight = mainSize * textureSize 2036 circleBG.displayX = -circleBG.displayWidth * 0.5 2037 circleBG.displayY = -circleBG.displayHeight * 0.5 2038 circleBG.display = True 2039 tf.children.append(circleBG) 2040 rotationCurve = self.CreatePerlinCurve(cs, scale=16.0, offset=10.0, speed=0.001, alpha=0.9, beta=1.0 + random.random()) 2041 self.CreateBinding(cs, rotationCurve, tf, 'rotation', 'value') 2042 2043 cs.Play() 2044 2045 @telemetry.ZONE_METHOD 2046 def CreateBinding(self, curveSet, curve, destinationObject, attribute, sourceAttribute = 'currentValue'): 2047 binding = trinity.TriValueBinding() 2048 curveSet.bindings.append(binding) 2049 binding.destinationObject = destinationObject 2050 binding.destinationAttribute = attribute 2051 binding.sourceObject = curve 2052 binding.sourceAttribute = sourceAttribute 2053 return binding 2054 2055 @telemetry.ZONE_METHOD 2056 def CreatePerlinCurve(self, curveSet, scale = 1.0, offset = 6.0, speed = 1.1, alpha = 1.0, beta = 1.1): 2057 curve = trinity.TriPerlinCurve() 2058 curve.scale = scale 2059 curve.offset = offset 2060 curve.speed = speed 2061 curve.alpha = alpha 2062 curve.beta = beta 2063 curveSet.curves.append(curve) 2064 return curve 2065 2066 @telemetry.ZONE_METHOD 2067 def GetLightID(self): 2068 path = self.lightingID 2069 files = ccConst.LIGHT_SETTINGS_ID 2070 for i, light in enumerate(files): 2071 if path == light: 2072 return i 2073 2074 return 1 2075 2076 @telemetry.ZONE_METHOD 2077 def GetLightColorID(self): 2078 path = self.lightColorID 2079 files = ccConst.LIGHT_COLOR_SETTINGS_ID 2080 for i, light in enumerate(files): 2081 if path == light: 2082 return i 2083 2084 return 1 2085 2086 @telemetry.ZONE_METHOD 2087 def GetCurrentBackgroundID(self): 2088 path = self.backdropPath 2089 return self.GetBackgroundID(path) 2090 2091 def GetBackgroundID(self, path): 2092 authoredBackground = self.characterSvc.GetPortraitResourceByPath(path) 2093 if authoredBackground: 2094 return authoredBackground.portraitResourceID 2095 ID = path.split('_')[-1].split('.')[0] 2096 try: 2097 ID = int(ID) 2098 except ValueError: 2099 return None 2100 2101 return ID 2102 2103 @telemetry.ZONE_METHOD 2104 def GetBackgroundPathFromID(self, bgID): 2105 if bgID < const.NCC_MIN_NORMAL_BACKGROUND_ID: 2106 return 'res:/UI/Texture/CharacterCreation/backdrops/Background_' + str(bgID) + '.dds' 2107 resourceRow = cfg.paperdollPortraitResources.Get(bgID) 2108 if resourceRow: 2109 return resourceRow.resPath 2110 2111 @telemetry.ZONE_METHOD 2112 def CapturePortrait(self, portraitID, *args): 2113 if self.camera is None: 2114 return 2115 poseData = self.characterSvc.GetPoseData() 2116 if poseData is None: 2117 return 2118 self.portraitInfo[portraitID] = utillib.KeyVal(cameraPosition=self.camera.GetPosition(), cameraFieldOfView=self.camera.fieldOfView, cameraPoi=self.camera.GetPointOfInterest(), backgroundID=self.GetCurrentBackgroundID(), lightID=self.lightingID, lightColorID=self.lightColorID, lightIntensity=self.GetLightIntensity(), poseData=poseData) 2119 maker = PortraitMaker(self.camera, self.backdropPath) 2120 return maker.GetPortraitTexture(portraitID) 2121 2122 @telemetry.ZONE_METHOD 2123 def GetPortraitSnapshotPath(self, portraitID): 2124 return blue.paths.ResolvePathForWriting(u'cache:/Pictures/Portraits/PortraitSnapshot_%s_%s.jpg' % (portraitID, session.userid)) 2125 2126 @telemetry.ZONE_METHOD 2127 def ClearPortraitInfo(self): 2128 self.portraitInfo = [None] * ccConst.NUM_PORTRAITS 2129 2130 @telemetry.ZONE_METHOD 2131 def GetPortraitInfo(self, portraitID): 2132 return self.portraitInfo[portraitID] 2133 2134 @telemetry.ZONE_METHOD 2135 def GetDNA(self, getHiddenModifiers = False, getWeightless = False): 2136 return self.doll.GetDNA(getHiddenModifiers=getHiddenModifiers, getWeightless=getWeightless) 2137 2138 @telemetry.ZONE_METHOD 2139 def OnHideUI(self, *args): 2140 self.uiContainer.state = uiconst.UI_HIDDEN 2141 2142 @telemetry.ZONE_METHOD 2143 def OnShowUI(self, *args): 2144 self.uiContainer.state = uiconst.UI_PICKCHILDREN 2145 2146 def OnMapShortcut(self, *args): 2147 uicore.cmd.commandMap.UnloadAllAccelerators() 2148 uicore.cmd.commandMap.LoadAcceleratorsByCategory('general') 2149 2150 @telemetry.ZONE_METHOD 2151 def ShowLoading(self, why = '', top = 200, forceOn = 0, *args): 2152 wheel = self.loadingWheel 2153 wheel.top = top 2154 wheel.hint = why 2155 wheel.forcedOn = forceOn 2156 wheel.Show() 2157 2158 @telemetry.ZONE_METHOD 2159 def HideLoading(self, why = '', forceOff = 0, *args): 2160 wheel = self.loadingWheel 2161 if not wheel.forcedOn or forceOff: 2162 self.loadingWheel.Hide() 2163 wheel.forcedOn = 0 2164 2165 @telemetry.ZONE_METHOD 2166 def OnCloseView(self): 2167 uicore.cmd.LoadAllAccelerators() 2168 self.TearDown() 2169 self.audioService.SendUIEvent('ui_icc_sculpting_mouse_over_loop_stop') 2170 if self.audioService.GetWorldVolume() == 0.0: 2171 self.audioService.SetWorldVolume(self.worldLevel) 2172 sm.GetService('cc').ClearMyAvailabelTypeIDs() 2173 self.Flush() 2174 self.step = None 2175 if self.previewCharWindowWasOpenOn is not None: 2176 charID = self.previewCharWindowWasOpenOn[0] 2177 self.previewCharWindowWasOpenOn = None 2178 sm.GetService('preview').PreviewCharacter(charID) 2179 if self.previewWindowWasOpenOn is not None: 2180 typeID = self.previewWindowWasOpenOn 2181 sm.GetService('preview').PreviewType(typeID) 2182 2183 @telemetry.ZONE_METHOD 2184 def ExitToStation(self, updateDoll = True): 2185 self.OnCloseView() 2186 if session.structureid: 2187 change = {'structureid': (None, session.structureid)} 2188 else: 2189 change = {'stationid': (None, session.stationid)} 2190 sm.GetService('gameui').OnSessionChanged(isRemote=False, session=session, change=change) 2191 2192 def ToggleClothes(self, forcedValue = None, doUpdate = True, *args): 2193 valueBefore = self.clothesOff 2194 if forcedValue is None: 2195 self.clothesOff = not self.clothesOff 2196 else: 2197 self.clothesOff = forcedValue 2198 if valueBefore == self.clothesOff: 2199 return 2200 info = self.GetInfo() 2201 if info.charID in self.characterSvc.characters: 2202 character = self.characterSvc.GetSingleCharacter(info.charID) 2203 if self.clothesOff: 2204 self.RemoveClothes(character, doUpdate=doUpdate) 2205 else: 2206 self.ReApplyClothes(character, doUpdate=doUpdate) 2207 2208 @telemetry.ZONE_METHOD 2209 def ReApplyClothes(self, character, doUpdate = True): 2210 if not self.clothesStorage or character is None: 2211 return 2212 doll = character.doll 2213 bdm = doll.buildDataManager 2214 for category in self.clothesMetaStorage: 2215 self.characterSvc.SetCharacterMetadataByCategory(self.charID, category, self.clothesMetaStorage[category]) 2216 2217 modifiers = doll.SortModifiersForBatchAdding(self.clothesStorage.values()) 2218 for modifier in modifiers: 2219 bdm.AddModifier(modifier) 2220 2221 self.ResetClothesStorage() 2222 if doUpdate: 2223 sm.GetService('character').UpdateDollsAvatar(character) 2224 2225 @telemetry.ZONE_METHOD 2226 def RemoveClothes(self, character, doUpdate = True): 2227 if self.clothesStorage or character is None: 2228 return 2229 categoriesToRemove = BODY_CATEGORIES - (BODY_CATEGORIES.SKIN, 2230 BODY_CATEGORIES.TATTOO, 2231 BODY_CATEGORIES.TOPUNDERWEAR, 2232 BODY_CATEGORIES.BOTTOMUNDERWEAR, 2233 BODY_CATEGORIES.SKINTONE, 2234 BODY_CATEGORIES.SKINTYPE, 2235 BODY_CATEGORIES.SCARS) 2236 categoriesToRemove = list(categoriesToRemove) 2237 categoriesToRemove.sort(key=lambda x: -DESIRED_ORDER.index(x)) 2238 self.ResetClothesStorage() 2239 bdm = character.doll.buildDataManager 2240 for category in categoriesToRemove: 2241 categoryModifiers = bdm.GetModifiersByCategory(category) 2242 self.StoreCharacterMetadata(category) 2243 self.characterSvc.RemoveFromCharacterMetadata(self.charID, category) 2244 for modifier in categoryModifiers: 2245 if modifier.respath not in DEFAULT_NUDE_PARTS: 2246 self.clothesStorage[category] = modifier 2247 bdm.RemoveModifier(modifier) 2248 2249 modifier = self.characterSvc.GetModifierByCategory(self.charID, ccConst.glasses) 2250 if modifier: 2251 self.StoreCharacterMetadata(ccConst.glasses) 2252 self.characterSvc.RemoveFromCharacterMetadata(self.charID, ccConst.glasses) 2253 self.clothesStorage[ccConst.glasses] = modifier 2254 bdm.RemoveModifier(modifier) 2255 modifier = self.characterSvc.GetModifierByCategory(self.charID, ccConst.mask) 2256 if modifier: 2257 self.StoreCharacterMetadata(ccConst.mask) 2258 self.characterSvc.RemoveFromCharacterMetadata(self.charID, ccConst.mask) 2259 self.clothesStorage[ccConst.mask] = modifier 2260 bdm.RemoveModifier(modifier) 2261 if doUpdate: 2262 sm.GetService('character').UpdateDollsAvatar(character) 2263 2264 def StoreCharacterMetadata(self, category): 2265 self.clothesMetaStorage[category] = self.characterSvc.GetCharacterMetadataByCategory(self.charID, category) 2266 2267 def ResetClothesStorage(self, *args): 2268 self.clothesStorage.clear() 2269 self.clothesMetaStorage.clear() 2270 2271 def RemoveBodyModifications(self, *args): 2272 try: 2273 if getattr(self, 'bodyModRemoved', 0): 2274 return 2275 modifiersToRemove = [ccConst.p_earslow, 2276 ccConst.p_earshigh, 2277 ccConst.p_nose, 2278 ccConst.p_nostril, 2279 ccConst.p_brow, 2280 ccConst.p_lips, 2281 ccConst.p_chin, 2282 ccConst.t_head, 2283 ccConst.s_head] 2284 character = self.characterSvc.GetSingleCharacter(self.charID) 2285 for mod in modifiersToRemove: 2286 modifiers = self.characterSvc.GetModifiersByCategory(self.charID, mod) 2287 for m in modifiers: 2288 character.doll.buildDataManager.RemoveModifier(m) 2289 self.characterSvc.RemoveFromCharacterMetadata(self.charID, mod) 2290 2291 self.bodyModRemoved = 1 2292 sm.GetService('character').UpdateDollsAvatar(character) 2293 except Exception: 2294 pass 2295 2296 @telemetry.ZONE_METHOD 2297 def StartDnaLogging(self): 2298 self.dnaList = [] 2299 self.lastLitHistoryBit = None 2300 2301 def ResetDna(self, *args): 2302 self.dnaList = None 2303 self.lastLitHistoryBit = None 2304 2305 @telemetry.ZONE_METHOD 2306 def ClearDnaLogFromIndex(self, fromIndex): 2307 if self.dnaList: 2308 to = fromIndex + 1 2309 if to > len(self.dnaList): 2310 to = len(self.dnaList) 2311 self.dnaList = self.dnaList[:to] 2312 2313 @telemetry.ZONE_METHOD 2314 def GetDollDNAHistory(self): 2315 return self.dnaList 2316 2317 def TryStoreDna(self, lastUpdateRedundant, fromWhere, sculpting = 0, force = 0, allowReduntant = 0, *args): 2318 if not lastUpdateRedundant or fromWhere in ('RandomizeCharacterGroups', 'RandomizeCharacter', 'AddCharacter'): 2319 if not self.parent.isopen: 2320 return 2321 if self.stepID == ccConst.CUSTOMIZATIONSTEP: 2322 if self.step is None: 2323 return 2324 if not force and self.step.menuMode == self.step.TATTOOMENU: 2325 self.step.tattooChangeMade = 1 2326 return 2327 if self.dnaList is not None: 2328 self.CheckDnaLog('UpdateDoll') 2329 dna = self.GetDNA(getHiddenModifiers=False, getWeightless=True) 2330 if not allowReduntant: 2331 try: 2332 currentIndex, maxIndex = self.step.sr.historySlider.GetCurrentIndexAndMaxIndex() 2333 if dna == self.dnaList[currentIndex][0]: 2334 return 2335 except Exception: 2336 pass 2337 2338 currMetadata = copy.deepcopy(self.characterSvc.characterMetadata[self.charID]) 2339 self.dnaList.append((dna, currMetadata)) 2340 if lastUpdateRedundant or force: 2341 sm.ScatterEvent('OnHistoryUpdated') 2342 2343 @telemetry.ZONE_METHOD 2344 def LoadDnaFromHistory(self, historyIndex): 2345 if len(self.characterSvc.characters) > 0: 2346 character = self.characterSvc.GetSingleCharacter(self.charID) 2347 if character: 2348 historyIndex = max(0, min(len(self.dnaList) - 1, historyIndex)) 2349 dna, metadata = self.dnaList[historyIndex] 2350 metadata = copy.deepcopy(metadata) 2351 self.ToggleClothes(forcedValue=0, doUpdate=False) 2352 self.characterSvc.MatchDNA(character, dna) 2353 self.characterSvc.characterMetadata[self.charID] = metadata 2354 if self.characterSvc.GetSculptingActive(): 2355 sculpting = self.characterSvc.GetSculpting() 2356 sculpting.UpdateFieldsBasedOnExistingValues(character.doll) 2357 self.characterSvc.UpdateDoll(self.charID, fromWhere='LoadDnaFromHistory', registerDna=False) 2358 self.characterSvc.SynchronizeHairColors(self.charID) 2359 2360 @telemetry.ZONE_METHOD 2361 def PassMouseEventToSculpt(self, type, x, y): 2362 if not hasattr(self, 'characterSvc'): 2363 return 2364 if getattr(self, 'doll', None) is None: 2365 return 2366 if self.doll.IsBusyUpdating(): 2367 return 2368 sculpting = self.characterSvc.GetSculpting() 2369 if not uicore.uilib.leftbtn and sculpting and sculpting.startXY is not None and self.characterSvc.GetSculptingActive(): 2370 type = 'LeftUp' 2371 pickValue = None 2372 if sculpting and self.characterSvc.GetSculptingActive(): 2373 if type == 'LeftDown': 2374 pickValue = sculpting.PickWrapper(x, y) 2375 elif type == 'LeftUp': 2376 pickValue = sculpting.EndMotion(x, y) 2377 elif type == 'Motion': 2378 pickValue = sculpting.MotionWrapper(x, y) 2379 return pickValue 2380 2381 def PickPortrait(self, newPortraitID): 2382 if self.stepID != ccConst.PORTRAITSTEP: 2383 return 2384 self.step.PickPortrait(newPortraitID) 2385 2386 def AnimateToStoredPortrait(self, newPortraitID): 2387 if self.stepID != ccConst.PORTRAITSTEP: 2388 return 2389 if self.portraitInfo[newPortraitID] is None: 2390 return 2391 if self.animateToStoredPortraitThread and self.animateToStoredPortraitThread.alive: 2392 if self.animatingToPortraitID == newPortraitID: 2393 return 2394 self.animateToStoredPortraitThread.kill() 2395 self.animateToStoredPortraitThread = uthread.new(self.AnimateToStoredPortrait_thread, newPortraitID) 2396 2397 def AnimateToStoredPortrait_thread(self, newPortraitID): 2398 portraitInfo = self.portraitInfo[newPortraitID] 2399 if portraitInfo is None: 2400 return 2401 newParams = self.GetControlParametersFromPortraitID(newPortraitID) 2402 if newParams is None: 2403 return 2404 oldParams = self.GetControlParametersFromPortraitID(None) 2405 if len(oldParams) < 1 or len(newParams) < 1: 2406 return 2407 self.animatingToPortraitID = newPortraitID 2408 thereIsCamera = self.camera is not None 2409 if thereIsCamera: 2410 oldCameraPos = self.camera.cameraPosition 2411 oldCameraPoi = self.camera.poi 2412 oldCameraFov = self.camera.fieldOfView 2413 info = self.GetInfo() 2414 start, ndt = blue.os.GetWallclockTime(), 0.0 2415 moveCamera = self.ShouldMoveCamera(portraitInfo.cameraPosition, portraitInfo.cameraPoi) 2416 while ndt != 1.0: 2417 timeValue = min(blue.os.TimeDiffInMs(start, blue.os.GetWallclockTime()) / 250.0, 1.0) 2418 ndt = math.sin(timeValue * math.pi - math.pi / 2.0) / 2.0 + 0.5 2419 params = [] 2420 for shortKey, keyAndValue in oldParams.iteritems(): 2421 longKey, value = keyAndValue 2422 if shortKey == 'HeadLookTarget': 2423 lerpedValue = geo2.Lerp(value, newParams[shortKey][1], ndt) 2424 elif shortKey == 'PortraitPoseNumber': 2425 continue 2426 else: 2427 lerpedValue = mathext.lerp(value, newParams[shortKey][1], ndt) 2428 params.append([longKey, lerpedValue]) 2429 2430 sm.GetService('character').SetControlParametersFromList(params, info.charID) 2431 if thereIsCamera and moveCamera: 2432 posValue = geo2.Lerp(oldCameraPos, portraitInfo.cameraPosition, ndt) 2433 poiValue = geo2.Lerp(oldCameraPoi, portraitInfo.cameraPoi, ndt) 2434 self.cameraPos = posValue 2435 self.cameraPoi = poiValue 2436 self.camera.PlacePortraitCamera(self.cameraPos, self.cameraPoi) 2437 blue.pyos.synchro.Yield() 2438 2439 xFactor, yFactor = self.camera.GetCorrectCameraXandYFactors(portraitInfo.cameraPosition, portraitInfo.cameraPoi) 2440 self.camera.xFactor = self.camera.xTarget = xFactor 2441 self.camera.yFactor = self.camera.yTarget = yFactor 2442 self.lightingID = portraitInfo.lightID 2443 self.lightIntensity = portraitInfo.lightIntensity 2444 self.lightColorID = portraitInfo.lightColorID 2445 shouldSnapPortrait = False 2446 path = self.GetBackgroundPathFromID(portraitInfo.backgroundID) 2447 if path in self.GetAvailableBackgroundsPaths(): 2448 self.backdropPath = path 2449 elif not gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN): 2450 shouldSnapPortrait = True 2451 self.poseID = int(portraitInfo.poseData['PortraitPoseNumber']) 2452 sm.GetService('character').SetControlParametersFromList([['ControlParameters|PortraitPoseNumber', float(self.poseID)]], info.charID) 2453 uicore.layer.charactercreation.controller.UpdateBackdrop() 2454 self.UpdateLights() 2455 sm.ScatterEvent('OnPortraitPicked') 2456 if shouldSnapPortrait and self.step: 2457 self.step.CapturePortrait(newPortraitID) 2458 2459 def ShouldMoveCamera(self, newPos, newPoi): 2460 newDirection = geo2.Subtract(newPos, newPoi) 2461 distanceDiff = abs(self.camera.distance - geo2.Vec3Length(newDirection)) 2462 direction2 = geo2.Vec3Normalize(newDirection) 2463 yaw = math.acos(direction2[0]) 2464 yawDiff = abs(self.camera.yaw - yaw) 2465 pitch = math.asin(direction2[1]) + math.pi / 2.0 2466 pitchDiff = math.sqrt(math.pow(self.camera.pitch - pitch, 2)) 2467 diffPos = geo2.Vec3Distance(self.camera.GetPosition(), newPos) 2468 if distanceDiff < 5e-07 and yawDiff < 5e-05 and pitchDiff < 5e-05 and diffPos < 0.05: 2469 return False 2470 return True 2471 2472 def GetControlParametersFromPortraitID(self, portraitID, *args): 2473 PREFIX = 'ControlParameters|' 2474 params = {} 2475 if portraitID is not None: 2476 portraitInfo = uicore.layer.charactercreation.controller.portraitInfo[portraitID] 2477 if portraitInfo is None: 2478 return {} 2479 return self.GetControlParametersFromPoseData(portraitInfo.poseData) 2480 info = self.GetInfo() 2481 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 2482 if avatar is None: 2483 return {} 2484 for controlParameter in paperDollUtil.FACIAL_POSE_PARAMETERS.__dict__.iterkeys(): 2485 if controlParameter.startswith('_'): 2486 continue 2487 longKey = PREFIX + controlParameter 2488 network = animparams.GetParamsPerAvatar(avatar, info.charID) 2489 value = network.GetControlParameterValue(longKey) 2490 params[controlParameter] = (longKey, value) 2491 2492 return params 2493 2494 def GetControlParametersFromPoseData(self, poseData, fromDB = False): 2495 if poseData is None: 2496 return {} 2497 if fromDB: 2498 allParameterKeys = poseData.__keys__ 2499 else: 2500 allParameterKeys = poseData.keys() 2501 params = {} 2502 PREFIX = 'ControlParameters|' 2503 for key in allParameterKeys: 2504 if key in ('headLookTargetX', 'headLookTargetY', 'headLookTargetZ', 'cameraX', 'cameraY', 'cameraZ'): 2505 continue 2506 value = poseData[key] 2507 if fromDB: 2508 key = key.replace(key[0], key[0].upper(), 1) 2509 params[key] = (PREFIX + key, value) 2510 2511 if fromDB: 2512 params['HeadLookTarget'] = (PREFIX + 'HeadLookTarget', (poseData['headLookTargetX'], poseData['headLookTargetY'], poseData['headLookTargetZ'])) 2513 return params 2514 2515 def TryFreezeAnimation(self, *args): 2516 if sm.GetService('machoNet').GetGlobalConfig().get('disableFreezeAnimationInNCC'): 2517 return 2518 if self.stepID != ccConst.CUSTOMIZATIONSTEP: 2519 return 2520 info = self.GetInfo() 2521 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 2522 if avatar is not None: 2523 network = animparams.GetParamsPerAvatar(avatar, info.charID) 2524 network.update = False 2525 self.freezingAnimation = True 2526 2527 def UnfreezeAnimationIfNeeded(self, *args): 2528 if self.freezingAnimation: 2529 info = self.GetInfo() 2530 avatar = self.characterSvc.GetSingleCharactersAvatar(info.charID) 2531 if avatar is not None: 2532 network = animparams.GetParamsPerAvatar(avatar, info.charID) 2533 network.update = True 2534 self.freezingAnimation = False