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

characterCustomization.py (25552B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\charcreation_new\steps\characterCustomization.py
      2 from carbon.client.script.environment.AudioUtil import PlaySound
      3 from carbon.common.script.sys import serviceConst
      4 from carbonui import uiconst
      5 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger
      6 from carbonui.primitives.container import Container
      7 from carbonui.primitives.containerAutoSize import ContainerAutoSize
      8 from carbonui.primitives.frame import Frame
      9 from carbonui.primitives.sprite import Sprite
     10 from carbonui.uianimations import animations
     11 from charactercreator import const as ccConst
     12 from eve.client.script.ui import eveColor
     13 from eve.client.script.ui.control import eveLabel
     14 from carbonui.control.buttonIcon import ButtonIcon
     15 from carbonui.control.button import Button
     16 from eve.client.script.ui.control.eveLabel import EveLabelMedium, Label, EveHeaderLarge
     17 from eve.client.script.ui.login.charcreation_new import ccUtil, soundConst
     18 from eve.client.script.ui.login.charcreation_new.charCreation import BaseCharacterCreationStep, MAXMENUSIZE
     19 from eve.client.script.ui.login.charcreation_new.charCreationBodyPicker import CCHeadBodyPicker
     20 from eve.client.script.ui.login.charcreation_new.hexes import CCHexButtonRandomize
     21 from eve.client.script.ui.login.charcreation_new.assetMenu import CharCreationAssetMenu
     22 from eve.client.script.ui.login.charcreation_new.colorPalette import CCColorPalette
     23 from eve.client.script.ui.login.charcreation_new.historySlider import CharacterCreationHistorySlider
     24 from eve.client.script.ui.login.charcreation_new.sceneManager import GetCharacterCreationSceneManager
     25 from eve.client.script.ui.login.charcreation_new.dollManager import GetCharacterCreationDollManager
     26 from eveexceptions import UserError
     27 from evegraphics import settings as gfxsettings
     28 import localization
     29 import trinity
     30 import uthread
     31 import blue
     32 import geo2
     33 from carbonui.uicore import uicore
     34 from eveprefs import prefs
     35 from itertoolsext.Enum import Enum
     36 TOGGLE_CLOTHES_BUTTON_ANALYTIC_ID = 'ToggleClothesButton'
     37 
     38 class CharacterCustomization(BaseCharacterCreationStep):
     39     __guid__ = 'uicls.CharacterCustomization'
     40     __notifyevents__ = ['OnColorPaletteChanged', 'OnHideUI', 'OnShowUI']
     41     stepID = ccConst.CUSTOMIZATIONSTEP
     42     ASSETMENU = 1
     43     TATTOOMENU = 2
     44 
     45     def ApplyAttributes(self, attributes):
     46         uicore.event.RegisterForTriuiEvents(uiconst.UI_ACTIVE, self.CheckAppFocus)
     47         BaseCharacterCreationStep.ApplyAttributes(self, attributes)
     48         self.menuMode = self.ASSETMENU
     49         self.colorPaletteWidth = CCColorPalette.COLORPALETTEWIDTH
     50         self.tattooChangeMade = 0
     51         self.menusInitialized = 0
     52         self.tattoMenu = None
     53         self.assetMenu = None
     54         self.loadingWheelThread = None
     55         self.historySlider = None
     56         self.debugReloadBtn = None
     57         customizationOptionsContainer = ContainerAutoSize(name='customizationOptionsContainer', parent=self.leftSide, align=uiconst.TOLEFT, top=90, width=200)
     58         self.randomizeButton = CCHexButtonRandomize(name='randomizeButton', parent=Container(parent=customizationOptionsContainer, align=uiconst.TOTOP, height=64), align=uiconst.CENTER, state=uiconst.UI_NORMAL, width=64, height=64, pickRadius=32, iconNum=0, func=self.RandomizeCharacter, hexName=localization.GetByLabel('UI/CharacterCreation/RandomizeDollTooltip'))
     59         EveLabelMedium(name='randomizeLabel', parent=customizationOptionsContainer, align=uiconst.TOTOP, text='<center>%s</center>' % localization.GetByLabel('UI/CharacterCreation/RandomizeAll'), top=-4)
     60         CCHeadBodyPicker(parent=customizationOptionsContainer, align=uiconst.TOTOP, headCallback=self.LoadFaceMode, bodyCallback=self.LoadBodyMode, top=10)
     61         EveLabelMedium(name='toggleClothesLabel', parent=customizationOptionsContainer, align=uiconst.TOTOP, text='<center>%s</center>' % localization.GetByLabel('UI/CharacterCreation/Zoom'))
     62         ButtonIcon(name='toggleClothesButton', parent=Container(parent=customizationOptionsContainer, align=uiconst.TOTOP, height=64, top=5), align=uiconst.CENTER, width=64, height=64, iconSize=64, texturePath='res:/UI/Texture/WindowIcons/charcustomization.png', func=self.ToggleClothes, useThemeColor=False, iconClass=Sprite, iconBlendMode=trinity.TR2_SBM_BLEND, hint=localization.GetByLabel('UI/CharacterCreation/ToggleClothes'), analyticID=TOGGLE_CLOTHES_BUTTON_ANALYTIC_ID)
     63         EveLabelMedium(name='toggleClothesLabel', parent=customizationOptionsContainer, align=uiconst.TOTOP, text='<center>%s</center>' % localization.GetByLabel('UI/CharacterCreation/ToggleClothes'))
     64         self.assetMenuParent = Container(parent=self.rightSide, name='assetMenuParent', pos=(20, 115, 500, 0), state=uiconst.UI_PICKCHILDREN, align=uiconst.TORIGHT)
     65         assetMenuWidth = min(MAXMENUSIZE, self.rightSide.width - 22)
     66         Label(name='assetMenuLabel', parent=Container(parent=self.assetMenuParent, align=uiconst.TOPRIGHT, width=assetMenuWidth, height=25), align=uiconst.CENTERLEFT, text=localization.GetByLabel('UI/CharacterCreation/CustomizeAppearance'), color=eveColor.PRIMARY_BLUE, fontsize=22, uppercase=True)
     67         self.hintBox = Container(name='hintBox', parent=self.assetMenuParent, pos=(-96, 30, 200, 150), align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED)
     68         self.hintText = eveLabel.EveLabelMedium(parent=self.hintBox, align=uiconst.TOTOP)
     69         self.characterCustomizationInfoPanel = CharacterCustomizationInfoPanel(name='characterCustomizationInfoPanel', parent=self.uiContainer, align=uiconst.CENTERTOP, top=80, width=300)
     70         self.UpdateLayout()
     71         if uicore.layer.charactercreation.controller.needSculptingTutorial:
     72             self.ShowSculptingInfoPanel()
     73         elif uicore.layer.charactercreation.controller.needNavigationTutorial:
     74             self.ShowNavigationInfoPanel()
     75         GetCharacterCreationSceneManager().camera.cameraModeChanged.connect(self._OnCameraModeChanged)
     76         self.StartLoadingThread()
     77         PlaySound(soundConst.EDIT_CHARACTER_LOOP)
     78 
     79     def StartLoadingThread(self, *args):
     80         if self.loadingWheelThread:
     81             self.loadingWheelThread.kill()
     82             self.loadingWheelThread = None
     83         self.loadingWheelThread = uthread.new(self.ShowLoadingWheel_thread)
     84 
     85     def SetHintText(self, modifier, hintText = ''):
     86         text = hintText
     87         if modifier in ccConst.HELPTEXTS:
     88             labelPath = ccConst.HELPTEXTS[modifier]
     89             text = localization.GetByLabel(labelPath)
     90         elif modifier == ccConst.eyes:
     91             labelPath = ccConst.HELPTEXTS[ccConst.EYESGROUP]
     92             text = localization.GetByLabel(labelPath)
     93         if text != self.hintText.text:
     94             self.hintText.text = text
     95 
     96     def ToggleClothes(self, *args):
     97         PlaySound(uiconst.SOUND_BUTTON_CLICK)
     98         info = self.GetInfo()
     99         ccDollManager = GetCharacterCreationDollManager()
    100         if ccDollManager.GetDoll(info.charID).busyUpdating:
    101             raise UserError('uiwarning01')
    102         ccDollManager.ToggleClothes()
    103 
    104     def UpdateLayout(self, *args):
    105         self.colorPaletteWidth = CCColorPalette.COLORPALETTEWIDTH
    106         sm.GetService('cc').LogInfo('CharacterCustomization::UpdateLayout')
    107         if not self.menusInitialized:
    108             self.tattoMenu = self.ReloadTattooMenu()
    109             self.assetMenu = self.ReloadAssetMenu()
    110             self.menusInitialized = 1
    111         self.LoadMenu()
    112 
    113     def OnColorPaletteChanged(self, width, *args):
    114         if width > self.colorPaletteWidth:
    115             self.colorPaletteWidth = width
    116 
    117     def RandomizeCharacter(self, *args):
    118         self.randomizeButton.StartBlinking()
    119         PlaySound('ui_icc_button_mouse_down_play')
    120         uicore.layer.charactercreation.controller.RandomizeCharacter()
    121         self.randomizeButton.StopBlinking()
    122 
    123     def InitAvatarPositions(self):
    124         info = self.GetInfo()
    125         avatar = sm.GetService('character').GetSingleCharactersAvatar(info.charID)
    126         avatar.translation = (0.0, 0.0, 0.0)
    127         avatar.rotation = geo2.QuaternionRotationSetYawPitchRoll(0.0, 0.0, 0.0)
    128         sm.GetService('character').UpdateDoll(info.charID, fromWhere='InitAvatarPositions')
    129 
    130     def LoadMenu(self, animate = 0, forcedMode = 0, *arg):
    131         sm.GetService('cc').LogInfo('CharacterCustomization::LoadMenu')
    132         menu = None
    133         if self.menuMode == self.ASSETMENU:
    134             menu = self.GetAssetMenu(forcedMode)
    135         elif self.menuMode == self.TATTOOMENU:
    136             menu = self.GetTattooMenu(forcedMode)
    137         if menu is None:
    138             return
    139         if animate:
    140             mainCont = menu.mainContainter
    141             if self.menuMode == self.TATTOOMENU:
    142                 menu.state = uiconst.UI_PICKCHILDREN
    143             else:
    144                 menu.state = uiconst.UI_DISABLED
    145                 uicore.effect.MorphUIMassSpringDamper(mainCont, 'top', 0, newthread=False, float=False, frequency=15.0, dampRatio=0.85)
    146                 menu.state = uiconst.UI_PICKCHILDREN
    147         else:
    148             menu.state = uiconst.UI_PICKCHILDREN
    149         menu.CheckIfOversize()
    150 
    151     def GetTattooMenu(self, forcedMode = 0, *args):
    152         sm.GetService('cc').LogInfo('CharacterCustomization::GetTattooMenu')
    153         if not forcedMode and self.tattoMenu and not self.tattoMenu.destroyed:
    154             if self.assetMenu:
    155                 self.assetMenu.state = uiconst.UI_HIDDEN
    156             return self.tattoMenu
    157         else:
    158             return self.ReloadTattooMenu()
    159 
    160     def ReloadTattooMenu(self, *args):
    161         sm.GetService('cc').LogInfo('CharacterCustomization::ReloadTattooMenu')
    162         self.StartLoadingThread()
    163         if self.assetMenu:
    164             self.assetMenu.state = uiconst.UI_HIDDEN
    165         if self.tattoMenu:
    166             self.tattoMenu.Close()
    167         info = self.GetInfo()
    168         piercingSub = (ccConst.p_brow,
    169          ccConst.p_nose,
    170          ccConst.p_nostril,
    171          ccConst.p_earshigh,
    172          ccConst.p_earslow,
    173          ccConst.p_lips,
    174          ccConst.p_chin)
    175         scarSub = (ccConst.s_head,)
    176         tattooSub = (ccConst.t_head, ccConst.t_armleft, ccConst.t_armright)
    177         augmentations = (ccConst.pr_armleft,
    178          ccConst.pr_armright,
    179          ccConst.augm_face,
    180          ccConst.augm_body)
    181         groups = []
    182         groups += [(ccConst.PIERCINGGROUP, piercingSub)]
    183         groups += [(ccConst.TATTOOGROUP, tattooSub)]
    184         groups += [(ccConst.SCARSGROUP, scarSub)]
    185         groups += [(ccConst.AUGMENTATIONS, augmentations)]
    186         self.tattoMenu = CharCreationAssetMenu(menuType='tattooMenu', parent=self.assetMenuParent, bloodlineID=info.bloodlineID, state=uiconst.UI_PICKCHILDREN, genderID=info.genderID, charID=info.charID, groups=groups, align=uiconst.TOALL, toggleFunc=self.GoToAssetMode, togglerIdx=0, top=26)
    187         return self.tattoMenu
    188 
    189     def GetAssetMenu(self, forcedMode = 0, *args):
    190         sm.GetService('cc').LogInfo('CharacterCustomization::GetAssetMenu')
    191         if not forcedMode and self.assetMenu and not self.assetMenu.destroyed:
    192             if self.tattoMenu and not self.tattoMenu.destroyed:
    193                 self.tattoMenu.state = uiconst.UI_HIDDEN
    194             return self.assetMenu
    195         else:
    196             return self.ReloadAssetMenu()
    197 
    198     def ReloadAssetMenu(self, *args):
    199         sm.GetService('cc').LogInfo('CharacterCustomization::ReloadAssetMenu')
    200         self.StartLoadingThread()
    201         if self.assetMenu:
    202             self.assetMenu.Close()
    203         if self.tattoMenu:
    204             self.tattoMenu.state = uiconst.UI_HIDDEN
    205         info = self.GetInfo()
    206         makeup = ccConst.MAKEUPGROUP
    207         if info.genderID == 1:
    208             makeup = ccConst.SKINDETAILSGROUP
    209         clothesSub = (ccConst.outer,
    210          ccConst.topouter,
    211          ccConst.topmiddle,
    212          ccConst.bottomouter,
    213          ccConst.bottommiddle,
    214          ccConst.feet,
    215          ccConst.glasses,
    216          ccConst.mask)
    217         groups = []
    218         if uicore.layer.charactercreation.controller.CanChangeBaseAppearance():
    219             groups += [(ccConst.ARCHETYPESGROUP, ())]
    220             groups += [(ccConst.BODYGROUP, ())]
    221             groups += [(ccConst.SKINGROUP, ())]
    222         groups += [(ccConst.EYESGROUP, ())]
    223         groups += [(ccConst.HAIRGROUP, ())]
    224         groups += [(makeup, (ccConst.eyeshadow,
    225            ccConst.eyeliner,
    226            ccConst.blush,
    227            ccConst.lipstick))]
    228         groups += [(ccConst.CLOTHESGROUP, clothesSub)]
    229         assetMenuWidth = min(MAXMENUSIZE + CCColorPalette.COLORPALETTEWIDTH, self.rightSide.width - 20)
    230         self.assetMenuMainWidth = assetMenuWidth - CCColorPalette.COLORPALETTEWIDTH
    231         self.assetMenu = CharCreationAssetMenu(menuType='assetMenu', parent=self.assetMenuParent, bloodlineID=info.bloodlineID, state=uiconst.UI_PICKCHILDREN, genderID=info.genderID, charID=info.charID, groups=groups, align=uiconst.TOALL, toggleFunc=self.GoToTattooMode, clipChildren=True, top=26)
    232         if self.historySlider:
    233             self.historySlider.Close()
    234         self.historySlider = CharacterCreationHistorySlider(parent=self.uiContainer, align=uiconst.CENTERBOTTOM, top=-45, width=400, opacity=0.0, bitChangeCheck=self.IsDollReady, lastLitHistoryBit=GetCharacterCreationDollManager().lastLitHistoryBit)
    235         mask = serviceConst.ROLE_CONTENT | serviceConst.ROLE_QA | serviceConst.ROLE_PROGRAMMER | serviceConst.ROLE_GML
    236         if session.role & mask:
    237             if self.debugReloadBtn:
    238                 self.debugReloadBtn.Close()
    239                 self.tattooModeBtn.Close()
    240                 self.typeAddEdit.Close()
    241                 self.validationToggle.Close()
    242                 self.typeAddBtn.Close()
    243             self.debugReloadBtn = Button(parent=self.uiContainer, func=self.GoToAssetMode, args=(1,), label='Reload Menu (debug)', align=uiconst.TOPRIGHT, left=self.randomizeButton.left + 30, top=16)
    244             self.tattooModeBtn = Button(parent=self.uiContainer, func=self.GoToTattooMode, args=(0, 1), label='Go to Tattoo mode (debug)', align=uiconst.TOPRIGHT, left=250, top=16)
    245             self.typeAddEdit = SingleLineEditInteger(parent=self.uiContainer, name='typeAdd', maxValue=100000, align=uiconst.TOPRIGHT, left=650, top=16, maxLength=10)
    246             self.validationToggle = Button(parent=self.uiContainer, name='validationToggle', func=self.ToggleValidation, label='Validation On', align=uiconst.TOPRIGHT, left=430, top=16)
    247             self.typeAddBtn = Button(parent=self.uiContainer, func=self.AddTypeButton, label='Add Type (debug)', align=uiconst.TOPRIGHT, left=530, top=16)
    248             self.addBlankDoll = Button(parent=self.uiContainer, func=self.AddBlankDrifterDoll, label='Add Blank Drifter Doll (debug)', align=uiconst.TOPRIGHT, left=530, top=35)
    249         animations.MorphScalar(self.historySlider, 'top', endVal=55, duration=0.125)
    250         animations.FadeIn(self.historySlider, duration=0.125)
    251         return self.assetMenu
    252 
    253     def AddBlankDrifterDoll(self, *args):
    254         from eve.common.script.paperDoll.paperDollDefinitions import LOD_SKIN
    255         info = self.GetInfo()
    256         self.charSvc.RemoveCharacter(info.charID)
    257         self.charSvc.AddCharacterToScene(info.charID, uicore.layer.charactercreation.controller.scene, ccUtil.GenderIDToPaperDollGender(info.genderID), bloodlineID=19, raceID=None, noRandomize=True, updateDoll=False)
    258         doll = self.charSvc.GetSingleCharactersDoll(info.charID)
    259         GetCharacterCreationDollManager().SetDoll(info.charID, doll)
    260         while doll.IsBusyUpdating():
    261             blue.synchro.Yield()
    262 
    263         doll.overrideLod = LOD_SKIN
    264         textureQuality = gfxsettings.Get(gfxsettings.GFX_CHAR_TEXTURE_QUALITY)
    265         doll.textureResolution = ccConst.TEXTURE_RESOLUTIONS[textureQuality]
    266         if ccUtil.IsSlowMachine():
    267             doll.useFastShader = True
    268         else:
    269             doll.useFastShader = False
    270         self.charSvc.SetDollBloodline(info.charID, 19)
    271         self.charSvc.UpdateDoll(info.charID, fromWhere='AddCharacter')
    272 
    273     def ToggleValidation(self, *args):
    274         validating = sm.RemoteSvc('charUnboundMgr').ToggleValidation()
    275         if validating:
    276             self.validationToggle.SetLabel('Validation On')
    277         else:
    278             self.validationToggle.SetLabel('Validation Off')
    279 
    280     def AddTypeButton(self, *args):
    281         resourceID = self.typeAddEdit.GetValue()
    282         paperdollResource = cfg.paperdollResources.Get(resourceID)
    283         if paperdollResource:
    284             info = self.GetInfo()
    285             itemRelativeResPath = self.charSvc.GetRelativePath(paperdollResource.resPath).lower()
    286             itemTypeData = self.charSvc.factory.GetItemType(itemRelativeResPath, gender=ccUtil.GenderIDToPaperDollGender(info.genderID))
    287             itemInfo = (resourceID, itemTypeData[:3], paperdollResource.typeID)
    288             GetCharacterCreationDollManager().SetItemType(itemInfo)
    289 
    290     def GoToTattooMode(self, animate = 1, forcedMode = 0, *args):
    291         self.menuMode = self.TATTOOMENU
    292         self.tattooChangeMade = 0
    293         self.charSvc.StopEditing()
    294         if self.historySlider:
    295             self.historySlider.state = uiconst.UI_HIDDEN
    296         if self.assetMenu and not self.assetMenu.destroyed:
    297             mainCont = self.assetMenu.mainContainter
    298             h = mainCont.displayHeight - self.assetMenu.menuToggler.height - 4
    299             uicore.effect.MorphUIMassSpringDamper(mainCont, 'top', -h, newthread=False, float=False, frequency=15.0, dampRatio=0.85)
    300         self.LoadMenu(animate=animate, forcedMode=forcedMode)
    301 
    302     def GoToAssetMode(self, forcedMode = 0, *args):
    303         self.menuMode = self.ASSETMENU
    304         if self.tattoMenu and not self.tattoMenu.destroyed:
    305             if self.tattooChangeMade:
    306                 uicore.layer.charactercreation.controller.TryStoreDna(False, 'GoToAssetMode', sculpting=False, force=1, allowReduntant=0)
    307             mainCont = self.tattoMenu.mainContainter
    308             h = self.tattoMenu.menuToggler.height + self.tattoMenu.menuToggler.padTop + self.tattoMenu.menuToggler.padBottom
    309             animations.MorphScalar(mainCont, 'top', endVal=0, duration=0.01)
    310             animations.MorphScalar(mainCont, 'height', endVal=h, duration=0.25, sleep=True)
    311         self.tattooChangeMade = 0
    312         if uicore.layer.charactercreation.controller.CanChangeBaseAppearance():
    313             uicore.layer.charactercreation.controller.StartEditMode()
    314         if self.historySlider:
    315             self.historySlider.state = uiconst.UI_PICKCHILDREN
    316         self.LoadMenu(animate=1, forcedMode=forcedMode)
    317 
    318     def OnGenericMouseEnter(self, btn, *args):
    319         PlaySound('ui_icc_button_mouse_over_play')
    320         btn.icon.SetAlpha(1.0)
    321 
    322     def OnGenericMouseExit(self, btn, *args):
    323         btn.icon.SetAlpha(0.5)
    324 
    325     def LoadFaceMode(self, *args):
    326         info = self.GetInfo()
    327         avatar = self.charSvc.GetSingleCharactersAvatar(info.charID)
    328         GetCharacterCreationSceneManager().camera.ToggleMode(ccConst.CAMERA_MODE_FACE, avatar=avatar, transformTime=500.0)
    329 
    330     def LoadBodyMode(self, *args):
    331         info = self.GetInfo()
    332         avatar = self.charSvc.GetSingleCharactersAvatar(info.charID)
    333         GetCharacterCreationSceneManager().camera.ToggleMode(ccConst.CAMERA_MODE_BODY, avatar=avatar, transformTime=500.0)
    334 
    335     def ValidateStepComplete(self):
    336         info = self.GetInfo()
    337         if prefs.GetValue('ignoreCCValidation', False):
    338             return True
    339         if self.menuMode == self.TATTOOMENU:
    340             uicore.layer.charactercreation.controller.TryStoreDna(False, 'ValidateStepComplete', force=1, allowReduntant=0)
    341         while not self.IsDollReady():
    342             blue.synchro.Yield()
    343 
    344         return self.charSvc.ValidateDollCustomizationComplete(info.charID)
    345 
    346     def ShowLoadingWheel_thread(self, *args):
    347         layer = uicore.layer.charactercreation.controller
    348         info = self.GetInfo()
    349         doll = GetCharacterCreationDollManager().GetDoll(info.charID)
    350         while doll and not self.destroyed:
    351             if layer.step and getattr(layer.step, '_activeSculptZone', None) is not None:
    352                 layer.HideLoading()
    353             elif doll.busyUpdating:
    354                 layer.ShowLoading(why=localization.GetByLabel('UI/CharacterCreation/UpdatingCharacter'))
    355             else:
    356                 layer.HideLoading()
    357             blue.pyos.synchro.SleepWallclock(100)
    358 
    359     def CheckAppFocus(self, wnd, msgID, vkey):
    360         focused = vkey[0]
    361         if not focused:
    362             uicore.layer.charactercreation.controller.PassMouseEventToSculpt('LeftDown', uicore.uilib.x, uicore.uilib.y)
    363             uicore.layer.charactercreation.controller.PassMouseEventToSculpt('LeftUp', uicore.uilib.x, uicore.uilib.y)
    364             self.ChangeSculptingCursor(-1, 0, 0)
    365             uicore.layer.charactercreation.controller.UnfreezeAnimationIfNeeded()
    366         return 1
    367 
    368     def Close(self):
    369         PlaySound(soundConst.EDIT_CHARACTER_LOOP_STOP)
    370         super(CharacterCustomization, self).Close()
    371 
    372     def StoreHistorySliderPosition(self, *args):
    373         if self.historySlider:
    374             currentIndex, maxIndex = self.historySlider.GetCurrentIndexAndMaxIndex()
    375         else:
    376             currentIndex = None
    377         GetCharacterCreationDollManager().lastLitHistoryBit = currentIndex
    378 
    379     def _SetActiveSculptZone(self, sculptZone):
    380         super(CharacterCustomization, self)._SetActiveSculptZone(sculptZone)
    381         if sculptZone:
    382             self.HideSculptingInfoPanel()
    383 
    384     def _OnCameraModeChanged(self, previousMode, newMode):
    385         if previousMode is not None and newMode in [ccConst.CAMERA_MODE_FACE, ccConst.CAMERA_MODE_BODY]:
    386             uicore.layer.charactercreation.controller.needNavigationTutorial = False
    387             self.HideNavigationInfoPanel()
    388             GetCharacterCreationSceneManager().camera.cameraModeChanged.disconnect(self._OnCameraModeChanged)
    389 
    390     def IsNavigationInfoPanelVisible(self):
    391         return self.characterCustomizationInfoPanel.IsVisible() and self.characterCustomizationInfoPanel.GetMode() == CharacterCustomizationInfoPanel.Modes.NAVIGATION
    392 
    393     def IsSculptingInfoPanelVisible(self):
    394         return self.characterCustomizationInfoPanel.IsVisible() and self.characterCustomizationInfoPanel.GetMode() == CharacterCustomizationInfoPanel.Modes.SCULPTING
    395 
    396     def ShowSculptingInfoPanel(self):
    397         if uicore.layer.charactercreation.controller.needSculptingTutorial:
    398             self.characterCustomizationInfoPanel.SetMode(CharacterCustomizationInfoPanel.Modes.SCULPTING)
    399             self.characterCustomizationInfoPanel.Show()
    400 
    401     def HideSculptingInfoPanel(self):
    402         if self.IsSculptingInfoPanelVisible():
    403             self.characterCustomizationInfoPanel.Hide(callback=lambda : self.ShowNavigationInfoPanel(timeOffset=1.0))
    404             uicore.layer.charactercreation.controller.needSculptingTutorial = False
    405 
    406     def ShowNavigationInfoPanel(self, timeOffset = 0.0):
    407         if uicore.layer.charactercreation.controller.needNavigationTutorial:
    408             self.characterCustomizationInfoPanel.SetMode(CharacterCustomizationInfoPanel.Modes.NAVIGATION)
    409             self.characterCustomizationInfoPanel.Show(timeOffset=timeOffset)
    410 
    411     def HideNavigationInfoPanel(self):
    412         if self.IsNavigationInfoPanelVisible():
    413             self.characterCustomizationInfoPanel.Hide()
    414             uicore.layer.charactercreation.controller.needNavigationTutorial = False
    415 
    416 
    417 class CharacterCustomizationInfoPanel(ContainerAutoSize):
    418 
    419     @Enum
    420 
    421     class Modes(object):
    422         NONE = 'NONE'
    423         NAVIGATION = 'NAVIGATION'
    424         SCULPTING = 'SCULPTING'
    425 
    426     def ApplyAttributes(self, attributes):
    427         super(CharacterCustomizationInfoPanel, self).ApplyAttributes(attributes)
    428         Frame(bgParent=self, color=(0.15, 0.15, 0.15, 1.0))
    429         self.background_color = (0.04, 0.04, 0.04, 1.0)
    430         self._mode = CharacterCustomizationInfoPanel.Modes.NONE
    431         self._title = EveHeaderLarge(name='sculptingInfoTitle', parent=self, align=uiconst.TOTOP, top=10)
    432         self._title.SetTextColor(eveColor.PRIMARY_BLUE)
    433         self._text = EveLabelMedium(name='sculptingInfoText', parent=self, align=uiconst.TOTOP, padding=(10, 10, 10, 10))
    434         self.opacity = 0
    435 
    436     def SetMode(self, mode):
    437         self._mode = mode
    438         if self._mode == CharacterCustomizationInfoPanel.Modes.NONE:
    439             self._SetTitle('')
    440             self._SetText('')
    441             self.opacity = 0
    442             return
    443         if self._mode == CharacterCustomizationInfoPanel.Modes.SCULPTING:
    444             self._SetTitle(localization.GetByLabel('UI/CharacterCreation/SculptingTool'))
    445             self._SetText(localization.GetByLabel('UI/CharacterCreation/SculptingToolHelp'))
    446         elif self._mode == CharacterCustomizationInfoPanel.Modes.NAVIGATION:
    447             self._SetTitle(localization.GetByLabel('UI/CharacterCreation/Navigation'))
    448             self._SetText(localization.GetByLabel('UI/CharacterCreation/NavigationHelp'))
    449 
    450     def GetMode(self):
    451         return self._mode
    452 
    453     def IsVisible(self):
    454         return self.opacity > 0
    455 
    456     def _SetTitle(self, title):
    457         self._title.SetText('<center>%s</center>' % title)
    458 
    459     def _SetText(self, text):
    460         self._text.SetText(text)
    461 
    462     def Show(self, timeOffset = 0.0, callback = None):
    463         uicore.animations.FadeTo(self, startVal=self.opacity, endVal=1.0, duration=0.25 * (1.0 - self.opacity), timeOffset=timeOffset, callback=callback)
    464 
    465     def Hide(self, timeOffset = 0.0, callback = None):
    466         uicore.animations.FadeTo(self, startVal=self.opacity, endVal=0.0, duration=0.25 * self.opacity, timeOffset=timeOffset, callback=callback)