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

assetPicker.py (51479B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\charcreation_new\assetPicker.py
      2 import os
      3 import random
      4 import types
      5 import uthread
      6 import charactercreator.const as ccConst
      7 import blue
      8 import localization
      9 import evegraphics.settings as gfxsettings
     10 from carbon.client.script.environment.AudioUtil import PlaySound
     11 from carbon.common.script.sys.serviceConst import ROLE_CONTENT, ROLE_GML, ROLE_PROGRAMMER, ROLE_QA
     12 from carbonui import uiconst
     13 from carbonui.primitives.container import Container
     14 from carbonui.primitives.fill import Fill
     15 from carbonui.primitives.frame import Frame
     16 from carbonui.primitives.line import Line
     17 from carbonui.primitives.sprite import Sprite
     18 from carbonui.uicore import uicore
     19 from carbonui.uianimations import animations
     20 from carbonui.util.various_unsorted import SortListOfTuples
     21 from eve.client.script.ui import eveColor
     22 from eve.client.script.ui.control import eveIcon
     23 from eve.client.script.ui.control.eveImagePicker import ImagePicker
     24 from carbonui.control.buttonIcon import ButtonIcon
     25 from eve.client.script.ui.login.charcreation_new.charCreationUtils import GradientSlider, BitSlider, CCLabel
     26 from eve.client.script.ui.login.charcreation_new.charCreationColorPicker import CharCreationColorPicker
     27 from eve.client.script.ui.login.charcreation_new.colorPalette import CCColorPalette
     28 from eve.client.script.ui.login.charcreation_new.sceneManager import GetCharacterCreationSceneManager
     29 from eve.client.script.ui.login.charcreation_new.portraitManager import GetCharacterCreationPortraitManager
     30 from eve.client.script.ui.login.charcreation_new.dollManager import GetCharacterCreationDollManager
     31 import eve.client.script.ui.login.charcreation_new.ccUtil as ccUtil
     32 from eveexceptions import UserError
     33 from eveprefs import prefs
     34 commonModifiersDisplayNames = {ccConst.eyes: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Eyes',
     35  ccConst.hair: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/HairStyle',
     36  ccConst.eyebrows: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Eyebrows',
     37  ccConst.skintone: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/SkinTone',
     38  ccConst.skinaging: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Aging',
     39  ccConst.scarring: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Scarring',
     40  ccConst.freckles: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Freckles',
     41  ccConst.glasses: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/Glasses',
     42  ccConst.muscle: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Muscularity',
     43  ccConst.weight: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Weight',
     44  ccConst.topmiddle: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/TopMiddleLayer',
     45  ccConst.topouter: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/TopOuterLayer',
     46  ccConst.bottomouter: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/BottomOuterLayer',
     47  ccConst.outer: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/OuterLayer',
     48  ccConst.bottommiddle: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/BottomMiddleLayer',
     49  ccConst.feet: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/FeetLayer',
     50  ccConst.p_earslow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/EarsLow',
     51  ccConst.p_earshigh: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/EarsHigh',
     52  ccConst.p_nose: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Nose',
     53  ccConst.p_nostril: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Nostril',
     54  ccConst.p_brow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Eyebrows',
     55  ccConst.p_lips: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Lips',
     56  ccConst.p_chin: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Chin',
     57  ccConst.t_head: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Tattoos/Head',
     58  ccConst.t_armleft: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Tattoos/ArmLeft',
     59  ccConst.t_armright: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Tattoos/ArmRight',
     60  ccConst.s_head: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Scars/Head',
     61  ccConst.skintype: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Skintype',
     62  ccConst.pr_armleft: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Prosthetics/ArmLeft',
     63  ccConst.pr_armright: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Prosthetics/ArmRight',
     64  ccConst.augm_face: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Augmentations/Face',
     65  ccConst.augm_body: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Augmentations/Body',
     66  ccConst.mask: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/Masks'}
     67 maleModifierDisplayNames = {ccConst.eyeshadow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/EyeDetails',
     68  ccConst.eyeliner: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/LashThickness',
     69  ccConst.lipstick: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/LipTone',
     70  ccConst.blush: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/CheekColor',
     71  ccConst.beard: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/FacialHair'}
     72 maleModifierDisplayNames.update(commonModifiersDisplayNames)
     73 femaleModifierDisplayNames = {ccConst.eyeshadow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/EyeShadow',
     74  ccConst.eyeliner: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Eyeliner',
     75  ccConst.lipstick: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Lipstick',
     76  ccConst.blush: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Blush'}
     77 femaleModifierDisplayNames.update(commonModifiersDisplayNames)
     78 
     79 class CharCreationAssetPicker(Container):
     80     __guid__ = 'uicls.CharCreationAssetPicker'
     81     __notifyevents__ = ['OnDollUpdated', 'OnColorPaletteChanged', 'OnPortraitPicked']
     82     FULLHEIGHT = 190
     83     COLLAPSEHEIGHT = 22
     84     default_align = uiconst.TOTOP
     85     default_left = 0
     86     default_top = 0
     87     default_width = 0
     88     default_height = COLLAPSEHEIGHT
     89     default_name = 'CharCreationAssetPicker'
     90     default_state = uiconst.UI_PICKCHILDREN
     91 
     92     def ApplyAttributes(self, attributes):
     93         sm.GetService('cc').LogInfo('CharCreationAssetPicker::ApplyAttributes:: modifier = ', attributes.modifier)
     94         for each in uicore.layer.main.children:
     95             if each.name == self.default_name:
     96                 each.Close()
     97 
     98         info = uicore.layer.charactercreation.controller.GetInfo()
     99         if attributes.isSubmenu:
    100             self.COLLAPSEHEIGHT = 18
    101             attributes.heght = 18
    102         Container.ApplyAttributes(self, attributes)
    103         if attributes.parent is None:
    104             uicore.layer.main.children.append(self)
    105         self._expandTime = None
    106         self._expanded = False
    107         self._didRandomize = None
    108         self.randomButton = None
    109         self.colorPalette = None
    110         self.browser = None
    111         self.colorIntensitySlider = None
    112         self.colorPaletteParent = Container(parent=self, align=uiconst.TOLEFT, width=CCColorPalette.COLORPALETTEWIDTH, name='colorPaletteParent', state=uiconst.UI_PICKCHILDREN)
    113         self.captionParent = Container(parent=self, align=uiconst.TOTOP, height=self.COLLAPSEHEIGHT, name='captionParent', state=uiconst.UI_NORMAL)
    114         self.captionParent.OnClick = self.Toggle
    115         self.captionParent.OnMouseEnter = self.OnCaptionEnter
    116         self.captionParent.OnMouseExit = self.OnCaptionExit
    117         self.captionParent.modifier = attributes.modifier
    118         self.caption = CCLabel(parent=self.captionParent, align=uiconst.CENTERLEFT, left=10, letterspace=3, shadowOffset=(0, 0), text=attributes.caption, uppercase=1, color=ccConst.COLOR, fontsize=13)
    119         self.caption.SetAlpha(0.5)
    120         self.expanderIcon = eveIcon.Icon(name='expanderIcon', icon=[ccConst.ICON_EXPANDED, ccConst.ICON_EXPANDEDSINGLE][attributes.isSubmenu], parent=self.captionParent, state=uiconst.UI_DISABLED, align=uiconst.CENTERRIGHT, color=ccConst.COLOR50)
    121         if attributes.isSubmenu:
    122             Fill(parent=self.captionParent, color=(0.2, 0.2, 0.2, 0.4))
    123             self.caption.fontsize = 12
    124             bevelAlpha = 0.1
    125         else:
    126             self.randomButton = ButtonIcon(parent=self.colorPaletteParent, name='randomizeButton', pos=(0, 0, 22, 22), iconSize=32, align=uiconst.TOPRIGHT, hint=localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/RandomizeGroup'), idx=0, func=lambda : self.RandomizeGroup(attributes.groupID), texturePath='res:/UI/Texture/CharacterCreation/randomize_arrows.png', state=uiconst.UI_HIDDEN, iconClass=Sprite)
    127             Frame(parent=self.captionParent, frameConst=ccConst.MAINFRAME_INV, color=(1.0, 1.0, 1.0, 0.5))
    128             Fill(parent=self.captionParent, color=(0.0, 0.0, 0.0, 0.5))
    129             bevelAlpha = 0.2
    130         self.bevel = Frame(parent=self.captionParent, color=(1.0,
    131          1.0,
    132          1.0,
    133          bevelAlpha), frameConst=ccConst.FILL_BEVEL, state=uiconst.UI_HIDDEN)
    134         frame = Frame(parent=self.captionParent, frameConst=ccConst.FRAME_SOFTSHADE, color=(1.0, 1.0, 1.0, 0.5))
    135         frame.padding = (-12, -5, -12, -15)
    136         self.mainParent = Container(parent=self, align=uiconst.TOALL, name='mainParent')
    137         if attributes.modifier in ccConst.REMOVEABLE:
    138             self.removeParent = Container(parent=self.mainParent, align=uiconst.TOPRIGHT, name='removeParent', pickRadius=-1, state=uiconst.UI_HIDDEN, hint=localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/RemoveCharacterPart'), pos=(2, 2, 20, 20), opacity=0.75, idx=0)
    139             self.removeParent.OnClick = (self.RemoveAsset, self.removeParent)
    140             self.removeParent.OnMouseEnter = (self.OnGenericMouseEnter, self.removeParent)
    141             self.removeParent.OnMouseExit = (self.OnGenericMouseExit, self.removeParent)
    142             self.removeParent.modifier = attributes.modifier
    143             self.removeParent.icon = eveIcon.Icon(name='removeIcon', icon=ccConst.ICON_CLOSE, parent=self.removeParent, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, color=ccConst.COLOR50, left=-10)
    144         modifier = attributes.modifier
    145         if modifier == ccConst.EYESGROUP:
    146             modifier = ccConst.eyes
    147         elif modifier == ccConst.HAIRGROUP:
    148             modifier = ccConst.hair
    149         Frame(parent=self.mainParent, frameConst=ccConst.MAINFRAME, color=(1.0, 1.0, 1.0, 0.5))
    150         self.assetParent = Container(parent=self.mainParent, align=uiconst.TOALL, name='assetParent', clipChildren=True, padding=(1, 1, 1, 1))
    151         self.modifier = modifier
    152         self.isSubmenu = attributes.isSubmenu
    153         self.groupID = attributes.groupID
    154         genderID = attributes.genderID
    155         if modifier is not None:
    156             if modifier == ccConst.BACKGROUNDGROUP:
    157                 self.FULLHEIGHT = 170
    158                 self.PrepareBackgrounds()
    159             elif modifier == ccConst.POSESGROUP:
    160                 self.FULLHEIGHT = 170
    161                 self.PreparePoses()
    162             elif modifier == ccConst.LIGHTSGROUP:
    163                 self.PrepareLights()
    164             elif modifier == ccConst.SKINGROUP:
    165                 self.FULLHEIGHT = 150
    166                 self.PrepareSkinTone()
    167             elif modifier == ccConst.BODYGROUP:
    168                 self.FULLHEIGHT = 70
    169                 self.PrepareBodyShape()
    170             elif modifier == ccConst.hair:
    171                 self.PrepareHair()
    172             elif modifier == ccConst.ARCHETYPESGROUP:
    173                 self.PrepareArchetypes()
    174             elif type(modifier) is not types.IntType:
    175                 self.FULLHEIGHT = 150
    176                 if modifier == ccConst.eyeshadow:
    177                     self.FULLHEIGHT = 180
    178                 itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(modifier)
    179                 categoryName = modifier.replace('/', '_')
    180                 assetData = []
    181                 numSpecialItems = 0
    182                 for itemType in itemTypes:
    183                     if itemType[2] is not None:
    184                         numSpecialItems += 1
    185                     path = self.GetAssetThumbnailPath(itemType, genderID, categoryName, info.bloodlineID)
    186                     assetData.append((path, itemType, ''))
    187 
    188                 self.browser = ImagePicker(parent=self.assetParent, align=uiconst.CENTER, imageWidth=96, imageHeight=96, zoomFactor=3.0, radius=150.0, images=assetData, numSpecialItems=numSpecialItems, OnSetValue=self.OnStylePicked)
    189                 self.browser.assetCategory = modifier
    190             else:
    191                 self.FULLHEIGHT = self.COLLAPSEHEIGHT
    192         Fill(parent=self.mainParent, color=(0.25, 0.25, 0.25, 0.25))
    193         self.mainParent.SetOpacity(0.0)
    194         self.height = self.captionParent.height
    195         self.expanderIcon.LoadIcon([ccConst.ICON_COLLAPSED, ccConst.ICON_COLLAPSEDSINGLE][self.isSubmenu])
    196         if not attributes.isSubmenu:
    197             self.state = uiconst.UI_PICKCHILDREN
    198         else:
    199             self.state = uiconst.UI_HIDDEN
    200         sm.RegisterNotify(self)
    201 
    202     def OnMouseEnter(self, *args):
    203         if self.randomButton:
    204             self.randomButton.Show()
    205         self.caption.SetRGBA(*eveColor.PRIMARY_BLUE)
    206         super(CharCreationAssetPicker, self).OnMouseEnter(*args)
    207 
    208     def OnMouseExit(self, *args):
    209         if self.randomButton:
    210             self.randomButton.Hide()
    211         self.caption.SetRGBA(*ccConst.COLOR)
    212         super(CharCreationAssetPicker, self).OnMouseExit(*args)
    213 
    214     def GetAssetThumbnailPath(self, itemType, genderID, categoryName, bloodlineID):
    215         path = ''
    216         if itemType[2] is not None:
    217             if genderID == 0:
    218                 genderText = 'Female'
    219             else:
    220                 genderText = 'Male'
    221             assetResPath = cfg.paperdollResources.Get(itemType[0]).resPath
    222             assetResPath = assetResPath.replace('/', '_').replace('.type', '')
    223             tempPath = 'res:/UI/Asset/mannequin/%s/%s_%s_%s.png' % (categoryName,
    224              itemType[2],
    225              genderText,
    226              assetResPath)
    227             if blue.paths.exists(tempPath):
    228                 path = tempPath
    229         if not path:
    230             path = 'res:/UI/Asset/%s_g%s_b%s.png' % ('_'.join(list(itemType[1])).replace('/', '_'), genderID, bloodlineID)
    231         return path
    232 
    233     def GetArchetypeThumbnailPath(self, genderID, bloodlineID):
    234         return 'res:/UI/Asset/bloodline_g%s_b%s.png' % (genderID, bloodlineID)
    235 
    236     def RandomizeGroup(self, groupID, *args):
    237         ccDollManager = GetCharacterCreationDollManager()
    238         info = uicore.layer.charactercreation.controller.GetInfo()
    239         PlaySound('ui_icc_button_mouse_down_play')
    240         if ccDollManager.GetDoll(info.charID).busyUpdating:
    241             raise UserError('uiwarning01')
    242         uicore.layer.charactercreation.controller.LockNavigation()
    243         svc = sm.GetService('character')
    244         if info.genderID == ccConst.GENDERID_FEMALE:
    245             itemDict = ccConst.femaleRandomizeItems
    246         else:
    247             itemDict = ccConst.maleRandomizeItems
    248         if groupID in (ccConst.BACKGROUNDGROUP,
    249          ccConst.POSESGROUP,
    250          ccConst.LIGHTSGROUP,
    251          ccConst.ARCHETYPESGROUP):
    252             randomPick = random.choice(self.browser.images)
    253             self.browser.SetActiveData(randomPick)
    254         elif groupID == ccConst.BODYGROUP:
    255             svc.RandomizeCharacterSculpting(info.charID, info.raceID, doUpdate=False)
    256             self.UpdateControls('OnDollUpdated', setFocusOnActive=True)
    257             svc.UpdateTattoos(info.charID, doUpdate=True)
    258             uicore.layer.charactercreation.controller.TryStoreDna(False, 'Sculpting', force=True)
    259         else:
    260             groupList = []
    261             for key, value in itemDict.iteritems():
    262                 if value == groupID:
    263                     groupList.append(key)
    264 
    265             if len(groupList) > 0:
    266                 svc.RandomizeCharacterGroups(info.charID, info.raceID, groupList, doUpdate=True)
    267             for cat in groupList:
    268                 if cat in ccConst.COLORMAPPING:
    269                     ccDollManager.UpdateColorSelectionFromDoll(cat)
    270 
    271         if groupID == ccConst.CLOTHESGROUP:
    272             ccDollManager.ToggleClothes(forcedValue=0)
    273         self._didRandomize = [groupID]
    274         uicore.layer.charactercreation.controller.UnlockNavigation()
    275 
    276     def GetAssetBloodlineID(self, fromBloodlineID):
    277         if fromBloodlineID in (1, 8, 7, 3, 2, 5, 6):
    278             assetBloodlineID = 1
    279         elif fromBloodlineID in (4,):
    280             assetBloodlineID = 4
    281         elif fromBloodlineID in (14, 12, 11, 13):
    282             assetBloodlineID = 14
    283         else:
    284             assetBloodlineID = 1
    285         return assetBloodlineID
    286 
    287     def OnDollUpdated(self, charID, redundantUpdate, *args):
    288         info = uicore.layer.charactercreation.controller.GetInfo()
    289         if charID == info.charID and self and not self.destroyed:
    290             self.UpdateControls('OnDollUpdated', setFocusOnActive=True)
    291 
    292     def OnPortraitPicked(self, *args):
    293         ccPortraitManager = GetCharacterCreationPortraitManager()
    294         pickerType = getattr(self, 'pickerType', None)
    295         if pickerType is None:
    296             return
    297         if pickerType == 'backgrounds':
    298             activeBackdrop = ccPortraitManager.GetBackdrop()
    299             if activeBackdrop:
    300                 self.browser.SetActiveDataFromValue(activeBackdrop, focusOnSlot=True, doCallbacks=False, doYield=False)
    301         elif pickerType == 'poses':
    302             poseID = ccPortraitManager.GetPoseID()
    303             self.browser.SetActiveDataFromValue(poseID, focusOnSlot=True, doCallbacks=False, doYield=False)
    304         elif pickerType == 'lights':
    305             ccSceneManager = GetCharacterCreationSceneManager()
    306             currentLight = ccSceneManager.GetLight()
    307             self.browser.SetActiveDataFromValue(currentLight, focusOnSlot=True, doCallbacks=False, doYield=False)
    308             if ccUtil.IsSlowMachine():
    309                 return
    310             self.BrowseLightColors(None)
    311             if self.colorPalette:
    312                 intensitySlider = self.colorPalette.lights
    313                 intensitySlider.SetValue(ccSceneManager.GetLightIntensity())
    314 
    315     def OnGenericMouseEnter(self, btn, *args):
    316         PlaySound('ui_icc_button_mouse_over_play')
    317         btn.icon.SetAlpha(1.0)
    318         if btn.sr.label:
    319             btn.label.SetAlpha(1.0)
    320 
    321     def OnGenericMouseExit(self, btn, *args):
    322         btn.icon.SetAlpha(0.5)
    323         if btn.sr.label:
    324             btn.label.SetAlpha(0.5)
    325 
    326     def OnGenericMouseDown(self, btn, *args):
    327         btn.icon.top += 1
    328 
    329     def OnGenericMouseUp(self, btn, *args):
    330         btn.icon.top -= 1
    331 
    332     def OnTuckBrowse(self, btn, *args):
    333         if getattr(self.colorPalette.tuckParent, 'tuckOptions', None) is None:
    334             return
    335         tuckOptions = self.colorPalette.tuckParent.tuckOptions
    336         currentIndex = self.colorPalette.tuckParent.tuckIndex
    337         if btn.name == 'leftBtn':
    338             if currentIndex == 0:
    339                 currentIndex = len(tuckOptions) - 1
    340             else:
    341                 currentIndex = currentIndex - 1
    342         elif currentIndex == len(tuckOptions) - 1:
    343             currentIndex = 0
    344         else:
    345             currentIndex = currentIndex + 1
    346         GetCharacterCreationDollManager().SetStyle(self.colorPalette.tuckParent.tuckPath, self.colorPalette.tuckParent.tuckStyle, tuckOptions[currentIndex])
    347 
    348     def PrepareHair(self):
    349         self.FULLHEIGHT = 170
    350         svc = sm.GetService('character')
    351         info = uicore.layer.charactercreation.controller.GetInfo()
    352         itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.hair)
    353         assetData = []
    354         for itemType in itemTypes:
    355             path = self.GetAssetThumbnailPath(itemType, info.genderID, ccConst.hair, info.bloodlineID)
    356             assetData.append((path, itemType, ''))
    357 
    358         subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=130)
    359         self.browser = ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=96, imageHeight=96, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnStylePicked)
    360         self.browser.assetCategory = ccConst.hair
    361         Line(parent=self.assetParent, align=uiconst.TOTOP, padding=(6, 0, 6, 0), color=(1.0, 1.0, 1.0, 0.1))
    362         itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.eyebrows)
    363         assetData = []
    364         for itemType in itemTypes:
    365             assetData.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('_'.join(list(itemType[1])).replace('/', '_'), info.genderID, info.bloodlineID), itemType, ''))
    366 
    367         subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=92)
    368         removeParent = Container(parent=subPar, align=uiconst.TOPRIGHT, name='removeParent', pickRadius=-1, state=uiconst.UI_NORMAL, hint=localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/RemoveCharacterPart'), pos=(2, 2, 20, 20), opacity=0.75, idx=0)
    369         removeParent.OnMouseEnter = (self.OnGenericMouseEnter, removeParent)
    370         removeParent.OnMouseExit = (self.OnGenericMouseExit, removeParent)
    371         removeParent.modifier = ccConst.eyebrows
    372         removeParent.icon = eveIcon.Icon(name='removeIcon', icon=ccConst.ICON_CLOSE, parent=removeParent, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, color=ccConst.COLOR50, left=-9)
    373         self.altbrowser = ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=64, imageHeight=64, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnStylePicked)
    374         self.altbrowser.removeParent = removeParent
    375         removeParent.OnClick = (self.RemoveHairAsset, removeParent, self.altbrowser)
    376         self.altbrowser.assetCategory = ccConst.eyebrows
    377         self.FULLHEIGHT += 80
    378         self.beardbrowser = None
    379         if info.genderID == 1:
    380             Line(parent=self.assetParent, align=uiconst.TOTOP, padding=(6, 0, 6, 0), color=(1.0, 1.0, 1.0, 0.1))
    381             itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.beard)
    382             assetData = []
    383             for itemType in itemTypes:
    384                 assetData.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('_'.join(list(itemType[1])).replace('/', '_'), info.genderID, info.bloodlineID), itemType, ''))
    385 
    386             subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=92)
    387             removeParent = Container(parent=subPar, align=uiconst.TOPRIGHT, name='removeParent', pickRadius=-1, state=uiconst.UI_NORMAL, hint=localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/RemoveCharacterPart'), pos=(2, 2, 20, 20), opacity=0.75, idx=0)
    388             removeParent.OnMouseEnter = (self.OnGenericMouseEnter, removeParent)
    389             removeParent.OnMouseExit = (self.OnGenericMouseExit, removeParent)
    390             removeParent.modifier = ccConst.beard
    391             removeParent.icon = eveIcon.Icon(name='removeIcon', icon=ccConst.ICON_CLOSE, parent=removeParent, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, color=ccConst.COLOR50, left=-9)
    392             self.beardbrowser = ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=64, imageHeight=64, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnStylePicked)
    393             self.beardbrowser.removeParent = removeParent
    394             removeParent.OnClick = (self.RemoveHairAsset, removeParent, self.beardbrowser)
    395             self.beardbrowser.assetCategory = ccConst.beard
    396             self.FULLHEIGHT += 90
    397 
    398     def PrepareArchetypes(self):
    399         self.FULLHEIGHT = 170
    400         self.modifier = None
    401         info = uicore.layer.charactercreation.controller.GetInfo()
    402         activeArchetypePath = None
    403         assetData = []
    404         for archetype in ccConst.AVAILABLE_ARCHETYPES:
    405             path = self.GetArchetypeThumbnailPath(info.genderID, archetype)
    406             assetData.append((path, (archetype, os.path.basename(path), None), ''))
    407             if archetype == info.bloodlineID:
    408                 activeArchetypePath = os.path.basename(path)
    409 
    410         subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=130)
    411         self.browser = ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=96, imageHeight=96, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnArchetypePicked)
    412         self.browser.assetCategory = ccConst.AVAILABLE_ARCHETYPES
    413         self.browser.SetActiveDataFromValue(activeArchetypePath, focusOnSlot=True, doCallbacks=False, doYield=False)
    414 
    415     def PrepareBodyShape(self):
    416         l, t, w, h = self.assetParent.GetAbsolute()
    417         sliderWidth = (w - 30) / 2
    418         left = 10
    419         for sModifier in (ccConst.muscle, ccConst.weight):
    420             slider = BitSlider(parent=self.assetParent, name=sModifier + '_slider', align=uiconst.CENTERLEFT, OnSetValue=self.OnSetSliderValue, sliderWidth=sliderWidth, left=left, top=7)
    421             left += sliderWidth + 10
    422             label = CCLabel(parent=slider, text=localization.GetByLabel(maleModifierDisplayNames.get(sModifier, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption')), top=-18, color=ccConst.COLOR50)
    423             slider.modifier = sModifier
    424 
    425     def PrepareBackgrounds(self):
    426         self.modifier = None
    427         self.pickerType = 'backgrounds'
    428         images = []
    429         charSvc = sm.GetService('character')
    430         ccPortraitManager = GetCharacterCreationPortraitManager()
    431         activeBackdrop = ccPortraitManager.GetBackdrop()
    432         if not gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN):
    433             if activeBackdrop is not None and ccPortraitManager.GetCurrentBackgroundID() < const.NCC_MIN_NORMAL_BACKGROUND_ID:
    434                 activeBackdrop = None
    435         backgroundOptions = ccPortraitManager.GetAvailableBackgroundsPaths()
    436         if activeBackdrop not in backgroundOptions:
    437             activeBackdrop = None
    438         numSpecialItems = 0
    439         for background in backgroundOptions:
    440             resource = charSvc.GetPortraitResourceByPath(background)
    441             typeID = resource.typeID if resource else None
    442             bgID = resource.portraitResourceID if resource else -1
    443             if typeID:
    444                 numSpecialItems += 1
    445                 bgID = -bgID
    446             images.append((bgID, (background.replace('.dds', '_thumb.dds'), ('background', background, typeID), None)))
    447 
    448         images = SortListOfTuples(images)
    449         if activeBackdrop is None:
    450             activeBackdrop = random.choice(images)
    451             self.OnSetBackground(activeBackdrop[1][1])
    452             activeBackdrop = activeBackdrop[0]
    453         self.browser = ImagePicker(parent=self.assetParent, align=uiconst.CENTERTOP, top=-10, imageWidth=110, imageHeight=110, zoomFactor=3.0, radius=150.0, images=images, numSpecialItems=numSpecialItems, OnSetValue=self.OnAltSetAsset)
    454         if activeBackdrop:
    455             self.browser.SetActiveDataFromValue(activeBackdrop, focusOnSlot=True, doCallbacks=False, doYield=False)
    456 
    457     def PreparePoses(self):
    458         info = uicore.layer.charactercreation.controller.GetInfo()
    459         self.modifier = None
    460         self.pickerType = 'poses'
    461         posesData = []
    462         assetBloodlineID = self.GetAssetBloodlineID(info.bloodlineID)
    463         for i in range(ccConst.POSERANGE):
    464             posesData.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('pose_%s' % i, info.genderID, assetBloodlineID), ('pose', i), None))
    465 
    466         self.browser = ImagePicker(parent=self.assetParent, align=uiconst.CENTERTOP, top=-10, imageWidth=110, imageHeight=110, zoomFactor=3.0, radius=150.0, images=posesData, OnSetValue=self.OnAltSetAsset)
    467         activePose = int(GetCharacterCreationPortraitManager().GetPoseID())
    468         if activePose:
    469             pose = posesData[activePose]
    470         else:
    471             pose = random.choice(posesData)
    472         self.OnAltSetAsset(pose)
    473         self.browser.SetActiveDataFromValue(pose[1][1], focusOnSlot=True, doCallbacks=False, doYield=False)
    474 
    475     def PrepareLights(self):
    476         info = uicore.layer.charactercreation.controller.GetInfo()
    477         self.modifier = None
    478         self.pickerType = 'lights'
    479         ccSceneManager = GetCharacterCreationSceneManager()
    480         currentLight = ccSceneManager.GetLight()
    481         currentLightColor = ccSceneManager.GetLightColor()
    482         lightingList = ccConst.LIGHT_SETTINGS_ID
    483         lightingColorList = ccConst.LIGHT_COLOR_SETTINGS_ID
    484         currentIndex = lightingColorList.index(currentLightColor)
    485         defaultThumbnailColor = lightingColorList[0]
    486         lightStyles = []
    487         assetBloodlineID = self.GetAssetBloodlineID(info.bloodlineID)
    488         for each in lightingList:
    489             lightStyles.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('light_%s_%s' % (each, defaultThumbnailColor), info.genderID, assetBloodlineID), ('light', each), None))
    490 
    491         self.browser = ImagePicker(parent=self.assetParent, align=uiconst.CENTERTOP, top=-10, imageWidth=110, imageHeight=110, zoomFactor=3.0, radius=150.0, images=lightStyles, OnSetValue=self.OnAltSetAsset)
    492         if self.colorPalette is None:
    493             self.CreateColorPallette(isLights=True)
    494         self.colorPalette.tuckParent.display = True
    495         self.browser.SetActiveDataFromValue(currentLight, focusOnSlot=True, doCallbacks=False, doYield=False)
    496         self.colorPalette.SetTuckingCounter(currentIndex + 1, len(lightingColorList))
    497 
    498     def BrowseLightColors(self, btn, *args):
    499         ccSceneManager = GetCharacterCreationSceneManager()
    500         currentLightColor = ccSceneManager.GetLightColor()
    501         lightingColorList = ccConst.LIGHT_COLOR_SETTINGS_ID
    502         currentIndex = lightingColorList.index(currentLightColor)
    503         if btn:
    504             if btn.name == 'leftBtn':
    505                 currentIndex -= 1
    506                 if currentIndex == -1:
    507                     currentIndex = len(lightingColorList) - 1
    508             else:
    509                 currentIndex += 1
    510                 if currentIndex == len(lightingColorList):
    511                     currentIndex = 0
    512         ccSceneManager.SetLightColor(lightingColorList[currentIndex])
    513         self.colorPalette.SetTuckingCounter(currentIndex + 1, len(lightingColorList))
    514 
    515     def OnAltSetAsset(self, assetData, *args):
    516         if assetData:
    517             ccSceneManager = GetCharacterCreationSceneManager()
    518             ccPortraitManager = GetCharacterCreationPortraitManager()
    519             thumb, assetData, hiliteResPath = assetData
    520             k = assetData[0]
    521             v = assetData[1]
    522             if k == 'background':
    523                 ccPortraitManager.SetBackdrop(v)
    524                 ccPortraitManager.UpdateBackdrop()
    525             elif k == 'light':
    526                 ccSceneManager.SetLights(v)
    527             elif k == 'pose':
    528                 ccPortraitManager.SetPoseID(assetData[1])
    529                 info = uicore.layer.charactercreation.controller.GetInfo()
    530                 sm.GetService('character').ChangePose(v, info.charID)
    531                 if ccSceneManager.camera is not None:
    532                     ccSceneManager.camera.UpdatePortraitInfo()
    533             self.UpdateControls('OnAltSetAsset')
    534 
    535     def OnSetBackground(self, bgPath, *args):
    536         ccPortraitManager = GetCharacterCreationPortraitManager()
    537         ccPortraitManager.SetBackdrop(bgPath)
    538         ccPortraitManager.UpdateBackdrop()
    539 
    540     def OnColorPaletteChanged(self, width):
    541         self.colorPaletteParent.width = width
    542 
    543     def PrepareSkinTone(self):
    544         itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.skintype)
    545         itemsWithDisplayColor = []
    546         for i, each in enumerate(itemTypes):
    547             itemsWithDisplayColor.append(('colorName', ccConst.SKINTYPECOLORS.get(str(each[1][2]), (1, 1, 1, 1)), each))
    548 
    549         colorPicker = CharCreationColorPicker(parent=self.assetParent, colors=itemsWithDisplayColor, align=uiconst.CENTERLEFT, OnSetValue=self.OnSkinTypePicked, activeColorIndex=activeIndex)
    550         colorPicker.modifier = ccConst.skintype
    551         l, t, w, h = self.assetParent.GetAbsolute()
    552         sliderWidth = w - 130 - 10
    553         left = 10
    554         top = -32
    555         for sModifier in (ccConst.skinaging, ccConst.freckles, ccConst.scarring):
    556             itemTypes, activeIdx = uicore.layer.charactercreation.controller.GetAvailableStyles(sModifier)
    557             bitAmount = len(itemTypes)
    558             slider = BitSlider(parent=self.assetParent, name=sModifier + '_slider', align=uiconst.CENTERLEFT, OnSetValue=self.OnSetSliderValue, bitAmount=bitAmount, sliderWidth=sliderWidth, left=130, top=top)
    559             top += 32
    560             label = CCLabel(parent=slider, text=localization.GetByLabel(maleModifierDisplayNames.get(sModifier, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption')), top=-18, color=ccConst.COLOR50)
    561             slider.modifier = sModifier
    562 
    563     def OnSetSliderValue(self, slider):
    564         value = slider.GetValue()
    565         ccDollManager = GetCharacterCreationDollManager()
    566         if slider.modifier in (ccConst.skinaging, ccConst.freckles, ccConst.scarring):
    567             itemTypes, activeIdx = uicore.layer.charactercreation.controller.GetAvailableStyles(slider.modifier)
    568             styleRange = 1.0 / len(itemTypes)
    569             portionalIndex = int(len(itemTypes) * (value + styleRange / 2))
    570             if portionalIndex == 0:
    571                 ccDollManager.ClearCategory(slider.modifier)
    572             else:
    573                 ccDollManager.SetItemType(itemTypes[portionalIndex - 1])
    574         else:
    575             ccDollManager.SetIntensity(slider.modifier, value)
    576 
    577     def ShowActiveItem(self, *args):
    578         if self.browser:
    579             active = self.browser.GetActiveData()
    580             if active:
    581                 self.browser.SetActiveData(active)
    582 
    583     def RemoveAsset(self, button, *args):
    584         GetCharacterCreationDollManager().ClearCategory(button.modifier)
    585         if self.browser:
    586             self.browser.SetActiveData(None, focusOnSlot=False)
    587             self.CollapseColorPalette()
    588 
    589     def RemoveHairAsset(self, button, browser, *args):
    590         info = uicore.layer.charactercreation.controller.GetInfo()
    591         modifiers = sm.GetService('character').GetModifierByCategory(info.charID, button.modifier, getAll=True)
    592         for each in modifiers:
    593             GetCharacterCreationDollManager().ClearCategory(button.modifier)
    594 
    595     def OnCaptionEnter(self, *args):
    596         uicore.layer.charactercreation.controller.SetHintText(self.captionParent.modifier)
    597         sm.StartService('audio').SendUIEvent(unicode('ui_icc_menu_mouse_over_play'))
    598         self.caption.SetAlpha(1.0)
    599         self.expanderIcon.SetAlpha(1.0)
    600         if self.bevel:
    601             self.bevel.state = uiconst.UI_DISABLED
    602 
    603     def OnCaptionExit(self, *args):
    604         uicore.layer.charactercreation.controller.SetHintText(None)
    605         if not self.IsExpanded():
    606             self.caption.SetAlpha(0.5)
    607             self.expanderIcon.SetAlpha(0.5)
    608         if self.bevel:
    609             self.bevel.state = uiconst.UI_HIDDEN
    610 
    611     def Toggle(self, *args):
    612         sm.StartService('audio').SendUIEvent(unicode('ui_icc_button_mouse_down_play'))
    613         if self._expanded:
    614             self.Collapse()
    615         else:
    616             self.Expand()
    617 
    618     def IsExpanded(self):
    619         return self._expanded
    620 
    621     def UpdateControls(self, trigger = None, setFocusOnActive = False):
    622         ccDollManager = GetCharacterCreationDollManager()
    623         subMenus = self.GetMySubmenus()
    624         if not self.IsExpanded() or subMenus:
    625             if subMenus and self._didRandomize and self.groupID in self._didRandomize:
    626                 self._didRandomize = None
    627                 for each in subMenus:
    628                     each.UpdateControls('UpdateControls', setFocusOnActive=True)
    629 
    630             return
    631         try:
    632             if self.colorPalette:
    633                 ccDollManager.ValidateColors(self.modifier)
    634                 self.colorPalette.UpdatePalette()
    635         except Exception:
    636             if not self or self.destroyed:
    637                 return
    638             raise
    639 
    640         info = uicore.layer.charactercreation.controller.GetInfo()
    641         charSvc = sm.GetService('character')
    642         containers = [ w for w in self.Find('trinity.Tr2Sprite2dContainer') ]
    643         browsersAndModifiers = [(self.browser, self.modifier)]
    644         if self.modifier == ccConst.hair:
    645             browsersAndModifiers.append((self.altbrowser, ccConst.eyebrows))
    646             if hasattr(self, 'beardbrowser'):
    647                 browsersAndModifiers.append((self.beardbrowser, ccConst.beard))
    648         for browser, modifier in browsersAndModifiers:
    649             if browser and modifier is not None:
    650                 if modifier == ccConst.beard:
    651                     activeMod = None
    652                     activeMods = charSvc.GetModifierByCategory(info.charID, modifier, getAll=True)
    653                     if activeMods:
    654                         if len(activeMods) == 1:
    655                             activeMod = activeMods[0]
    656                         else:
    657                             for a in activeMods:
    658                                 if a.respath == ccConst.BASEBEARD:
    659                                     continue
    660                                 activeMod = a
    661                                 break
    662                             else:
    663                                 activeMod = activeMods[0]
    664 
    665                 else:
    666                     activeMod = charSvc.GetModifierByCategory(info.charID, modifier)
    667                     if activeMod and activeMod.name in ccConst.invisibleModifiers:
    668                         activeMod = None
    669                     if not activeMod and modifier in ccDollManager.clothesStorage:
    670                         activeMod = ccDollManager.clothesStorage.get(modifier, None)
    671                 if activeMod:
    672                     uthread.new(self.SetActiveData_thread, browser, activeMod, setFocusOnActive)
    673                 else:
    674                     browser.SetActiveData(None, focusOnSlot=False, doCallbacks=False)
    675 
    676         self.LoadTuckOptions()
    677         self.LoadRemoveOptions()
    678         colorPickers = [ each for each in containers if isinstance(each, CharCreationColorPicker) ]
    679         for colorPicker in colorPickers:
    680             if not getattr(colorPicker, 'modifier', None):
    681                 continue
    682             itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(colorPicker.modifier)
    683             if activeIndex is None:
    684                 colorPicker.SetActiveColor(None, initing=True)
    685             else:
    686                 activeColor = itemTypes[activeIndex]
    687                 colorPicker.SetActiveColor(activeColor, initing=True)
    688 
    689         sliders = [ each for each in containers if isinstance(each, BitSlider) or isinstance(each, GradientSlider) ]
    690         for slider in sliders:
    691             if not getattr(slider, 'modifier', None):
    692                 continue
    693             if slider.modifier in (ccConst.skinaging, ccConst.freckles, ccConst.scarring):
    694                 itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(slider.modifier)
    695                 if not itemTypes:
    696                     continue
    697                 if activeIndex is None:
    698                     activeIndex = 0
    699                 else:
    700                     activeIndex = activeIndex + 1
    701                 value = 1.0 / float(len(itemTypes)) * activeIndex
    702                 slider.SetValue(value, doCallback=False)
    703             elif slider.modifier in ccConst.weight:
    704                 weight = charSvc.GetCharacterWeight(info.charID)
    705                 slider.SetValue(weight, doCallback=False)
    706             elif slider.modifier == ccConst.muscle:
    707                 muscularity = charSvc.GetCharacterMuscularity(info.charID)
    708                 slider.SetValue(muscularity, doCallback=False)
    709             elif slider.modifier == ccConst.hair:
    710                 slider.SetValue(charSvc.GetHairDarkness(info.charID), doCallback=False)
    711                 slider.parent.SetGradientsColor()
    712             else:
    713                 activeMod = charSvc.GetModifierByCategory(info.charID, slider.modifier)
    714                 if activeMod:
    715                     if slider.sliderType == 'intensity':
    716                         slider.SetValue(charSvc.GetWeightByCategory(info.charID, slider.modifier))
    717                         slider.parent.SetGradientsColor()
    718                     elif slider.sliderType == 'specularity':
    719                         slider.SetValue(charSvc.GetColorSpecularityByCategory(info.charID, slider.modifier))
    720 
    721     def SetActiveData_thread(self, browser, activeMod, setFocusOnActive):
    722         typeData = activeMod.GetTypeData()
    723         if typeData[0].startswith(('makeup', 'beard')) and typeData[2] in ('default', 'none'):
    724             typeData = (typeData[0], typeData[1], '')
    725         if browser and hasattr(browser, 'SetActiveDataFromValue'):
    726             browser.SetActiveDataFromValue(typeData, doCallbacks=False, focusOnSlot=setFocusOnActive, doYield=False)
    727             if self.colorPalette:
    728                 self.colorPalette.TryReloadColors()
    729             self.LoadTuckOptions()
    730             self.LoadRemoveOptions()
    731 
    732     def DebugRoleCheck(self):
    733         mask = ROLE_CONTENT | ROLE_QA | ROLE_PROGRAMMER | ROLE_GML
    734         if session.role & mask and not prefs.GetValue('CCHideAssetDebugText', False):
    735             return True
    736         else:
    737             return False
    738 
    739     def UpdatePrefs(self, state):
    740         currentMenuState = settings.user.ui.Get('assetMenuState', {ccConst.BODYGROUP: 1})
    741         key = self.modifier or 'group_%s' % getattr(self, 'groupID', '')
    742         currentMenuState[key] = state
    743         settings.user.ui.Set('assetMenuState', currentMenuState)
    744 
    745     def Expand(self, initing = False):
    746         if self._expanded:
    747             return
    748         self._expanded = True
    749         self._expandTime = blue.os.GetWallclockTime()
    750         self.caption.SetAlpha(1.0)
    751         self.expanderIcon.SetAlpha(1.0)
    752         self.CheckIfOversize()
    753         if self.isSubmenu or not self.GetMySubmenus():
    754             self.height = self.GetCollapsedHeight()
    755             animations.FadeIn(self.mainParent, duration=0.05)
    756             uicore.effect.MorphUIMassSpringDamper(self, 'height', self.GetExpandedHeight(), newthread=True, float=False, frequency=15.0, dampRatio=0.75)
    757             self.Show()
    758         else:
    759             mySubs = self.GetMySubmenus()
    760             menuState = settings.user.ui.Get('assetMenuState', {ccConst.BODYGROUP: True})
    761             for subMenu in mySubs:
    762                 key = subMenu.modifier or 'group_%s' % getattr(subMenu, 'groupID', '')
    763                 if menuState.get(key, False):
    764                     subMenu.Expand(True)
    765                 else:
    766                     subMenu.height = 0
    767                     subMenu.Show()
    768                     uicore.effect.MorphUIMassSpringDamper(subMenu, 'height', subMenu.GetCollapsedHeight(), newthread=True, float=False, frequency=15.0, dampRatio=0.75)
    769 
    770         self.CheckIfOversize()
    771         if self.modifier in ccConst.COLORMAPPING or self.modifier in ccConst.TUCKMAPPING:
    772             uthread.new(self.ExpandColorPalette)
    773         self.UpdateControls('Expand', setFocusOnActive=True)
    774         self.UpdatePrefs(True)
    775         self.expanderIcon.LoadIcon([ccConst.ICON_EXPANDED, ccConst.ICON_EXPANDEDSINGLE][self.isSubmenu])
    776 
    777     def ExpandColorPalette(self, initing = False, *args):
    778         blue.pyos.synchro.SleepWallclock(500)
    779         if hasattr(self, 'sr'):
    780             self.CreateColorPallette()
    781         if self.browser and self.IsExpanded():
    782             info = uicore.layer.charactercreation.controller.GetInfo()
    783             activeMod = sm.GetService('character').GetModifierByCategory(info.charID, self.modifier)
    784             if activeMod and (uicore.uilib.mouseOver is self or uicore.uilib.mouseOver.IsUnder(self)):
    785                 self.colorPalette.ExpandPalette()
    786 
    787     def CreateColorPallette(self, isLights = False, *args):
    788         if self.colorPalette is None:
    789             maxPaletteWidth = int(uicore.desktop.width / 8)
    790             if isLights:
    791                 browseFunction = self.BrowseLightColors
    792             else:
    793                 browseFunction = self.OnTuckBrowse
    794             self.colorPalette = CCColorPalette(name='CCColorPalette', parent=self.colorPaletteParent, align=uiconst.TOPRIGHT, pos=(0,
    795              self.GetCollapsedHeight(),
    796              CCColorPalette.COLORPALETTEWIDTH,
    797              0), modifier=self.modifier, state=uiconst.UI_HIDDEN, maxPaletteHeight=self.GetExpandedHeight(), maxPaletteWidth=maxPaletteWidth, browseFunction=browseFunction, bgColor=(0.0, 0.0, 0.0, 0.25), isLights=isLights)
    798 
    799     def CheckIfOversize(self, *args):
    800         self.parent.parent.CheckIfOversize(currentPicker=self)
    801 
    802     def GetCollapsedHeight(self):
    803         return self.captionParent.height
    804 
    805     def GetExpandedHeight(self):
    806         return self.FULLHEIGHT
    807 
    808     def Collapse(self):
    809         self._expanded = False
    810         self.CollapseColorPalette()
    811         if self._expanded:
    812             return
    813         animations.FadeOut(self.mainParent, duration=0.15)
    814         if self.isSubmenu or not self.GetMySubmenus():
    815             uicore.effect.MorphUIMassSpringDamper(self, 'height', self.captionParent.height, newthread=1, float=False, frequency=15.0, dampRatio=1.0)
    816         else:
    817             mySubs = self.GetMySubmenus()
    818             hideHeight = 0
    819             for subMenu in mySubs:
    820                 if subMenu.IsExpanded():
    821                     subMenu.Collapse()
    822 
    823             for subMenu in mySubs:
    824                 subMenu.Hide()
    825 
    826         self.expanderIcon.LoadIcon([ccConst.ICON_COLLAPSED, ccConst.ICON_COLLAPSEDSINGLE][self.isSubmenu])
    827         if uicore.uilib.mouseOver is not self.captionParent:
    828             self.OnCaptionExit()
    829         self.UpdatePrefs(False)
    830 
    831     def CollapseColorPalette(self, *args):
    832         if self.colorPalette:
    833             self.colorPalette.CollapsePalette(push=True)
    834 
    835     def GetMySubmenus(self):
    836         ret = []
    837         if self.isSubmenu:
    838             return []
    839         for each in self.parent.children:
    840             if not hasattr(each, 'groupID'):
    841                 continue
    842             if each is not self and each.groupID == self.groupID and getattr(each, 'isSubmenu', False):
    843                 ret.append(each)
    844 
    845         return ret
    846 
    847     def GetCurrentModifierValue(self, modifierPath):
    848         info = uicore.layer.charactercreation.controller.GetInfo()
    849         modifier = sm.GetService('character').GetModifiersByCategory(info.charID, modifierPath)
    850         if modifier:
    851             return modifier[0].weight
    852         return 0.0
    853 
    854     def OnStylePicked(self, assetData, *args):
    855         if assetData:
    856             info = uicore.layer.charactercreation.controller.GetInfo()
    857             thumb, itemType, hiliteResPath = assetData
    858             weight = 1.0
    859             if self.colorIntensitySlider:
    860                 weight = self.colorIntensitySlider.GetValue()
    861             GetCharacterCreationDollManager().SetItemType(itemType, weight=weight)
    862             uthread.new(self.UpdateControls, 'OnStylePicked')
    863 
    864     def OnSkinTypePicked(self, itemType, *args):
    865         if itemType:
    866             ccDollManager = GetCharacterCreationDollManager()
    867             info = uicore.layer.charactercreation.controller.GetInfo()
    868             ccDollManager.ClearCategory(ccConst.skintone, doUpdate=False)
    869             sm.GetService('character').characterMetadata[info.charID].typeColors.pop(ccConst.skintone, None)
    870             ccDollManager.SetItemType(itemType)
    871             uthread.new(self.UpdateControls, 'OnSkinTypePicked')
    872 
    873     def OnArchetypePicked(self, assetData, *args):
    874         if assetData:
    875             uicore.layer.charactercreation.controller.SelectBloodline(assetData[1][0])
    876 
    877     def LoadRemoveOptions(self, *args):
    878         if self.modifier == ccConst.hair:
    879             return self.LoadRemoveHairOptions()
    880         if not self.browser or not self.IsExpanded() or self.state == uiconst.UI_HIDDEN or self.modifier not in ccConst.REMOVEABLE:
    881             return
    882         self.SetRemoveIcon(self.modifier, self.removeParent)
    883 
    884     def SetRemoveIcon(self, modifier, icon):
    885         info = uicore.layer.charactercreation.controller.GetInfo()
    886         currentModifier = sm.GetService('character').GetModifierByCategory(info.charID, modifier)
    887         if not currentModifier or getattr(currentModifier, 'name', None) in ccConst.invisibleModifiers:
    888             if icon:
    889                 icon.Hide()
    890         elif icon:
    891             icon.Show()
    892 
    893     def LoadRemoveHairOptions(self, *args):
    894         if not self.IsExpanded() or self.state == uiconst.UI_HIDDEN:
    895             return
    896         if self.altbrowser:
    897             self.SetRemoveIcon(ccConst.eyebrows, self.altbrowser.removeParent)
    898         if self.beardbrowser:
    899             self.SetRemoveIcon(ccConst.beard, self.beardbrowser.removeParent)
    900 
    901     def LoadTuckOptions(self, *args):
    902         if not self.browser or not self.IsExpanded() or self.state == uiconst.UI_HIDDEN or self.modifier not in ccConst.TUCKMAPPING:
    903             if getattr(self, 'pickerType', None) == 'lights' and ccUtil.IsSlowMachine():
    904                 self.colorPalette.tuckParent.display = False
    905             return
    906         if self.colorPalette is None:
    907             self.CreateColorPallette()
    908         if self.colorPalette is None:
    909             return
    910         info = uicore.layer.charactercreation.controller.GetInfo()
    911         currentModifier = sm.GetService('character').GetModifierByCategory(info.charID, self.modifier)
    912         activeData = None
    913         if self.browser and self.IsExpanded():
    914             activeData = self.browser.GetActiveData()
    915         hideTuck = True
    916         if activeData and currentModifier:
    917             tuckPath, requiredModifiers, subKey = ccConst.TUCKMAPPING[self.modifier]
    918             if requiredModifiers:
    919                 haveRequired = False
    920                 for each in requiredModifiers:
    921                     haveRequired = bool(sm.GetService('character').GetModifierByCategory(info.charID, each))
    922                     if haveRequired:
    923                         break
    924 
    925             else:
    926                 haveRequired = True
    927             resPath, itemType, hiliteResPath = activeData
    928             if haveRequired:
    929                 tuckModifier = sm.GetService('character').GetModifierByCategory(info.charID, tuckPath)
    930                 if tuckModifier:
    931                     tuckVariations = tuckModifier.GetVariations()
    932                     if tuckVariations:
    933                         currentTuckVariation = tuckModifier.currentVariation
    934                         tuckStyle = tuckModifier.GetResPath().split('/')[-1]
    935                         if currentTuckVariation in tuckVariations:
    936                             tuckIndex = tuckVariations.index(currentTuckVariation)
    937                         else:
    938                             tuckIndex = 0
    939                         tuckParent = self.colorPalette.tuckParent
    940                         tuckParent.tuckOptions = tuckVariations
    941                         tuckParent.tuckIndex = tuckIndex
    942                         tuckParent.tuckPath = tuckPath
    943                         tuckParent.tuckStyle = tuckStyle
    944                         tuckParent.tuckResPath = tuckModifier.GetResPath()
    945                         self.colorPalette.SetTuckingCounter(tuckIndex + 1, len(tuckVariations))
    946                         hideTuck = False
    947         if hideTuck:
    948             if self.colorPalette.tuckParent.display == True:
    949                 self.colorPalette.tuckParent.display = False
    950                 animations.FadeOut(self.colorPalette.tuckParent, duration=0.125)
    951         else:
    952             self.colorPalette.tuckParent.display = True
    953             animations.FadeIn(self.colorPalette.tuckParent, duration=0.125)
    954 
    955     def OnColorPickedFromWheel(self, colorPicker, color, name):
    956         GetCharacterCreationDollManager().SetColorValue(colorPicker.modifier, (name, tuple(color)))