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

assetMenu.py (80714B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\charcreation\assetMenu.py
      2 import random
      3 import types
      4 import blue
      5 import charactercreator.const as ccConst
      6 import evegraphics.settings as gfxsettings
      7 import localization
      8 import uthread
      9 from carbon.client.script.environment.AudioUtil import PlaySound
     10 from carbon.common.script.sys import serviceConst
     11 from carbon.common.script.util import timerstuff
     12 from carbonui import uiconst
     13 from carbonui.primitives.container import Container
     14 from carbonui.primitives.containerAutoSize import ContainerAutoSize
     15 from carbonui.primitives.fill import Fill
     16 from carbonui.primitives.frame import Frame
     17 from carbonui.primitives.line import Line
     18 from carbonui.primitives.sprite import Sprite
     19 from carbonui.uianimations import animations
     20 from carbonui.uicore import uicore
     21 from carbonui.util.various_unsorted import SortListOfTuples
     22 from eve.client.script.ui import eveColor
     23 from eve.client.script.ui.control import eveIcon, eveImagePicker
     24 from carbonui.control.buttonIcon import ButtonIcon
     25 from eve.client.script.ui.login.charcreation import ccUtil, charCreation, charCreationColorPicker
     26 from eve.common.lib import appConst as appconst
     27 from eve.client.script.ui.login.charcreation.label import CCLabel
     28 from eveexceptions import UserError
     29 from eveprefs import prefs
     30 HAIRDARKNESS = 'hari_darkness'
     31 HAIRSATURATION = 'hari_saturation'
     32 GROUPNAMES = {ccConst.SKINGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Complexion',
     33  ccConst.HAIRGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Hair',
     34  ccConst.EYESGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Eyes',
     35  ccConst.MAKEUPGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Makeup',
     36  ccConst.SKINDETAILSGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/SkinDetails',
     37  ccConst.CLOTHESGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Clothes',
     38  ccConst.BODYGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Shape',
     39  ccConst.BACKGROUNDGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Backgrounds',
     40  ccConst.POSESGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Poses',
     41  ccConst.LIGHTSGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Lights',
     42  ccConst.PIERCINGGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Piercings',
     43  ccConst.TATTOOGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Tattoos',
     44  ccConst.SCARSGROUP: 'UI/Login/CharacterCreation/AssetMenu/Groups/Scars',
     45  ccConst.PROSTHETICS: 'UI/Login/CharacterCreation/AssetMenu/Groups/Prosthetics',
     46  ccConst.AUGMENTATIONS: 'UI/Login/CharacterCreation/AssetMenu/Groups/Augmentations'}
     47 commonModifiersDisplayNames = {ccConst.eyes: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Eyes',
     48  ccConst.hair: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/HairStyle',
     49  ccConst.eyebrows: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Eyebrows',
     50  ccConst.skintone: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/SkinTone',
     51  ccConst.skinaging: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Aging',
     52  ccConst.scarring: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Scarring',
     53  ccConst.freckles: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Freckles',
     54  ccConst.glasses: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/Glasses',
     55  ccConst.muscle: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Muscularity',
     56  ccConst.weight: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Weight',
     57  ccConst.topmiddle: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/TopMiddleLayer',
     58  ccConst.topouter: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/TopOuterLayer',
     59  ccConst.bottomouter: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/BottomOuterLayer',
     60  ccConst.outer: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/OuterLayer',
     61  ccConst.bottommiddle: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/BottomMiddleLayer',
     62  ccConst.feet: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/FeetLayer',
     63  ccConst.p_earslow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/EarsLow',
     64  ccConst.p_earshigh: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/EarsHigh',
     65  ccConst.p_nose: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Nose',
     66  ccConst.p_nostril: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Nostril',
     67  ccConst.p_brow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Eyebrows',
     68  ccConst.p_lips: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Lips',
     69  ccConst.p_chin: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Piercings/Chin',
     70  ccConst.t_head: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Tattoos/Head',
     71  ccConst.t_armleft: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Tattoos/ArmLeft',
     72  ccConst.t_armright: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Tattoos/ArmRight',
     73  ccConst.s_head: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Scars/Head',
     74  ccConst.skintype: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Skintype',
     75  ccConst.pr_armleft: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Prosthetics/ArmLeft',
     76  ccConst.pr_armright: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Prosthetics/ArmRight',
     77  ccConst.augm_face: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Augmentations/Face',
     78  ccConst.augm_body: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Augmentations/Body',
     79  ccConst.mask: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Clothing/Masks'}
     80 maleModifierDisplayNames = {ccConst.eyeshadow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/EyeDetails',
     81  ccConst.eyeliner: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/LashThickness',
     82  ccConst.lipstick: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/LipTone',
     83  ccConst.blush: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/CheekColor',
     84  ccConst.beard: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/FacialHair'}
     85 maleModifierDisplayNames.update(commonModifiersDisplayNames)
     86 femaleModifierDisplayNames = {ccConst.eyeshadow: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/EyeShadow',
     87  ccConst.eyeliner: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Eyeliner',
     88  ccConst.lipstick: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Lipstick',
     89  ccConst.blush: 'UI/Login/CharacterCreation/AssetMenu/ModifierNames/Blush'}
     90 femaleModifierDisplayNames.update(commonModifiersDisplayNames)
     91 
     92 class CharCreationAssetMenu(Container):
     93 
     94     def ApplyAttributes(self, attributes):
     95         Container.ApplyAttributes(self, attributes)
     96         self.name = attributes.menuType or 'CharCreationAssetMenu'
     97         sm.GetService('cc').LogInfo('CharCreationAssetMenu::ApplyAttributes:: name = ', self.name)
     98         if attributes.genderID == 0:
     99             modifierNames = femaleModifierDisplayNames
    100         else:
    101             modifierNames = maleModifierDisplayNames
    102         self.mainContainter = Container(parent=self, name='mainAssetMenuCont', align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN)
    103         self.mainContainter.clipChildren = 1
    104         self.togglerIdx = None
    105         self.toggleFunc = attributes.toggleFunc
    106         self.bloodlineID = attributes.bloodlineID
    107         empireID = attributes.raceID
    108         if empireID == appconst.raceMinmatar:
    109             if self.bloodlineID not in [appconst.bloodlineBrutor, appconst.bloodlineVherokior, appconst.bloodlineSebiestor]:
    110                 self.bloodlineID = appconst.bloodlineSebiestor
    111         elif empireID == appconst.raceAmarr:
    112             if self.bloodlineID not in [appconst.bloodlineAmarr, appconst.bloodlineKhanid, appconst.bloodlineNiKunni]:
    113                 self.bloodlineID = appconst.bloodlineKhanid
    114         elif empireID == appconst.raceGallente:
    115             if self.bloodlineID not in [appconst.bloodlineGallente, appconst.bloodlineJinMei, appconst.bloodlineIntaki]:
    116                 self.bloodlineID = appconst.bloodlineGallente
    117         elif empireID == appconst.raceCaldari:
    118             if self.bloodlineID not in [appconst.bloodlineAchura, appconst.bloodlineCivire, appconst.bloodlineDeteis]:
    119                 self.bloodlineID = appconst.bloodlineCivire
    120         if self.toggleFunc:
    121             self.togglerIdx = idx = attributes.get('togglerIdx', -1)
    122             if idx == -1:
    123                 padTop = 16
    124                 padBottom = 4
    125             else:
    126                 padTop = 4
    127                 padBottom = 16
    128             self.menuToggler = CharCreationMenuToggler(parent=self.mainContainter, caption=localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/BodyModifications'), padTop=padTop, padBottom=padBottom, menuType=attributes.menuType, func=self.ToggleMenu, idx=idx)
    129         for groupID, modifiers in attributes.groups:
    130             if self._AreAllModifiersEmpty(modifiers):
    131                 continue
    132             if type(groupID) == types.IntType:
    133                 caption = localization.GetByLabel(GROUPNAMES.get(groupID, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption'))
    134             else:
    135                 caption = localization.GetByLabel(modifierNames.get(groupID, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption'))
    136             CharCreationAssetPicker(parent=self.mainContainter, modifier=groupID, caption=caption, padTop=4, padBottom=4, genderID=attributes.genderID, bloodlineID=self.bloodlineID, charID=attributes.charID, isSubmenu=False, groupID=groupID)
    137             for modifier in modifiers:
    138                 if self._IsModifierEmpty(modifier):
    139                     continue
    140                 caption = localization.GetByLabel(modifierNames.get(modifier, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption'))
    141                 CharCreationAssetPicker(parent=self.mainContainter, modifier=modifier, caption=caption, padTop=-2, padBottom=4, genderID=attributes.genderID, bloodlineID=self.bloodlineID, isSubmenu=True, groupID=groupID)
    142 
    143         menuState = settings.user.ui.Get('assetMenuState', {ccConst.BODYGROUP: True})
    144         for pickerContainer in self.mainContainter.children:
    145             if isinstance(pickerContainer, CharCreationMenuToggler):
    146                 continue
    147             key = pickerContainer.modifier or 'group_%s' % getattr(pickerContainer, 'groupID', '')
    148             if not pickerContainer.isSubmenu and menuState.get(key, 0):
    149                 pickerContainer.Expand(initing=True)
    150 
    151         if self.togglerIdx and self.menuToggler:
    152             self.menuToggler.SetOrder(self.togglerIdx)
    153 
    154     def _AreAllModifiersEmpty(self, modifiers):
    155         return modifiers and not any([ not self._IsModifierEmpty(modifier) for modifier in modifiers ])
    156 
    157     def _IsModifierEmpty(self, modifier):
    158         if type(modifier) is types.IntType:
    159             return False
    160         itemTypes, _ = uicore.layer.charactercreation.controller.GetAvailableStyles(modifier)
    161         if itemTypes:
    162             return False
    163         return True
    164 
    165     def ToggleMenu(self, *args):
    166         if self.toggleFunc:
    167             self.toggleFunc()
    168 
    169     def CheckIfOversize(self, currentPicker = None):
    170         canCollapse = []
    171         totalExpandedHeight = 0
    172         for each in self.mainContainter.children:
    173             if not isinstance(each, CharCreationAssetPicker):
    174                 continue
    175             if each.state == uiconst.UI_HIDDEN:
    176                 continue
    177             if each.IsExpanded():
    178                 if not each.isSubmenu:
    179                     subs = each.GetMySubmenus()
    180                     totalExpandedHeight += each.padTop + each.GetExpandedHeight() + each.padBottom
    181                     if each is not currentPicker and currentPicker not in each.GetMySubmenus():
    182                         canCollapse.append((each._expandTime, each))
    183                 else:
    184                     totalExpandedHeight += each.padTop + each.GetExpandedHeight() + each.padBottom
    185                 if each is not currentPicker and each.isSubmenu:
    186                     canCollapse.append((each._expandTime, each))
    187             else:
    188                 totalExpandedHeight += each.padTop + each.GetCollapsedHeight() + each.padBottom
    189 
    190         canCollapse.sort()
    191         availableSpace = uicore.desktop.height - 150 - ccConst.BUTTON_AREA_HEIGHT
    192         if totalExpandedHeight > availableSpace:
    193             diff = totalExpandedHeight - availableSpace
    194             for expandTime, each in canCollapse:
    195                 if each.IsExpanded():
    196                     uthread.new(each.Collapse)
    197                     diff -= each.GetExpandedHeight() - each.GetCollapsedHeight()
    198                 if diff <= 0:
    199                     break
    200 
    201 
    202 class CCColorPalette(ContainerAutoSize):
    203     default_state = uiconst.UI_NORMAL
    204     default_opacity = 0.0
    205     default_left = 6
    206     default_top = 22
    207     SIDEMARGIN = 6
    208     TOPMARGIN = 6
    209     COLORSIZE = 14
    210     MINCOLORSIZE = 10
    211     COLORGAP = 0
    212     COLORMARGIN = 1
    213     COLORPALETTEWIDTH = 124
    214 
    215     def ApplyAttributes(self, attributes):
    216         super(CCColorPalette, self).ApplyAttributes(attributes)
    217         self.modifier = attributes.modifier
    218         self.primaryColors = None
    219         self.secondaryColors = None
    220         self.OnSetValue = attributes.OnSetValue
    221         self.maxPaletteHeight = attributes.maxPaletteHeight or 200
    222         self.maxPaletteWidth = attributes.maxPaletteWidth
    223         self.startingWidth = self.width
    224         self.currentNumColorAreas = None
    225         self.browseFunction = attributes.browseFunction
    226         self.browseText = attributes.browseText
    227         self.isLights = attributes.isLights
    228         self._expanded = False
    229         self.fadeInThread = None
    230         self.fadeOutThread = None
    231         self.PrepareControls()
    232 
    233     def Close(self):
    234         if self.mouseOverTimer:
    235             self.mouseOverTimer.KillTimer()
    236         super(CCColorPalette, self).Close()
    237 
    238     def PrepareControls(self, reloading = None, *args):
    239         info = uicore.layer.charactercreation.controller.GetInfo()
    240         charSvc = sm.GetService('character')
    241         sliders = []
    242         if info.genderID == ccConst.GENDERID_FEMALE:
    243             facialHairText = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/EyebrowsColor')
    244         else:
    245             facialHairText = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/FacialHairColor')
    246         if ccUtil.HasUserDefinedWeight(self.modifier):
    247             sliders += [('intensity', localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/MakeupOpacity'), charSvc.GetWeightByCategory(info.charID, self.modifier))]
    248         if info.genderID == ccConst.GENDERID_FEMALE and ccUtil.HasUserDefinedSpecularity(self.modifier):
    249             sliders += [('specularity', localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/LipGloss'), charSvc.GetColorSpecularityByCategory(info.charID, self.modifier))]
    250         if self.modifier == ccConst.hair:
    251             sliders += [(HAIRDARKNESS, facialHairText, charSvc.GetHairDarkness(info.charID))]
    252         elif self.isLights:
    253             if not uicore.layer.charactercreation.controller.IsSlowMachine():
    254                 sliders += [('lights', localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/Intensity'), uicore.layer.charactercreation.controller.GetLightIntensity())]
    255         self.Flush()
    256         self.height = 0
    257         self.width = self.startingWidth
    258         self.currentColorSize = self.COLORSIZE
    259         self.PrepareTuckControls()
    260         for referenceName, label, currentValue in sliders:
    261             extraParameters = {}
    262             if referenceName == 'intensity':
    263                 sliderClass = charCreation.GradientSlider
    264                 extraParameters = {'alphaValues': (0, 0)}
    265             elif referenceName == HAIRDARKNESS:
    266                 sliderClass = charCreation.GradientSlider
    267             else:
    268                 sliderClass = charCreation.BitSlider
    269             modifier = self.modifier or 'NotReallyModifier'
    270             slider = sliderClass(parent=self, name=(modifier + '_slider'), padTop=20, padLeft=0, align=uiconst.TOTOP, setvalue=currentValue, OnSetValue=self.SetSliderValue, sliderWidth=(self.COLORPALETTEWIDTH - self.SIDEMARGIN * 2 + 1), bitHeight=6, idx=0, left=self.SIDEMARGIN, **extraParameters)
    271             slider.modifier = modifier
    272             slider.sliderType = referenceName
    273             setattr(self, referenceName, slider)
    274             label = CCLabel(parent=slider, uppercase=1, shadowOffset=(0, 0), fontsize=9, letterspace=2, text=label, width=slider.width, color=ccConst.COLOR50)
    275             label.top = -label.textheight - 1
    276 
    277         self.previousWidth = self.width
    278         self.activePrimary = None
    279         self.activeSecondary = None
    280         if self.modifier in ccConst.COLORMAPPING:
    281             if reloading == 'oldColors':
    282                 self.LoadColors(self.primaryColors, self.secondaryColors)
    283             else:
    284                 self.PrepareCategoryColorOptions()
    285         self.SetGradientsColor()
    286         self.SetSizeAutomatically()
    287         self.mouseOverTimer = timerstuff.AutoTimer(50, self.CheckMouseOver)
    288 
    289     def SetSizeAutomatically(self):
    290         ContainerAutoSize.SetSizeAutomatically(self)
    291         if self.height > 0:
    292             self.padBottom = -8
    293         else:
    294             self.padBottom = 0
    295 
    296     def PrepareTuckControls(self, *args):
    297         self.tuckParent = Container(parent=self, name='tuckParent', align=uiconst.TOTOP, top=8, height=56, state=uiconst.UI_HIDDEN, padLeft=self.SIDEMARGIN, padRight=self.SIDEMARGIN)
    298         if self.isLights:
    299             browseText = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/BrowseLightColors')
    300         else:
    301             browseText = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/Tucking')
    302         CCLabel(parent=self.tuckParent, uppercase=1, shadowOffset=(0, 0), fontsize=9, letterspace=2, text=browseText, top=0, left=0, color=ccConst.COLOR50, idx=0)
    303         self.tuckParent.countLabel = CCLabel(parent=self.tuckParent, uppercase=1, shadowOffset=(0, 0), fontsize=9, letterspace=2, text='', top=16, left=0, color=ccConst.COLOR50, idx=0)
    304         self.tuckLeftBtn = ButtonIcon(parent=self.tuckParent, name='leftBtn', align=uiconst.TOPLEFT, pos=(0, 32, 20, 20), iconSize=32, func=self.OnTuckLeftButtonClicked, texturePath=ccConst.ICON_BACK)
    305         self.tuckRightBtn = ButtonIcon(parent=self.tuckParent, name='rightBtn', align=uiconst.TOPRIGHT, pos=(0, 32, 20, 20), iconSize=32, func=self.OnTuckRightButtonClicked, texturePath=ccConst.ICON_NEXT)
    306 
    307     def OnTuckRightButtonClicked(self):
    308         self.OnTuckButtonClicked(self.tuckRightBtn)
    309 
    310     def OnTuckLeftButtonClicked(self):
    311         self.OnTuckButtonClicked(self.tuckLeftBtn)
    312 
    313     def OnTuckButtonClicked(self, btn):
    314         if self.browseFunction is not None:
    315             self.browseFunction(btn)
    316 
    317     def SetTuckingCounter(self, current = 0, total = 0):
    318         self.tuckParent.countLabel.text = '%s/%s' % (current, total)
    319 
    320     def SetGradientsColor(self, displayColor = None):
    321         slidersToColor = []
    322         if self.activePrimary is None:
    323             return
    324         for slider in [getattr(self, HAIRDARKNESS, None), getattr(self.sr, 'intensity', None)]:
    325             if slider is None:
    326                 continue
    327             if displayColor is None:
    328                 displayColor = self.activePrimary.displayColor
    329             slidersToColor.append(slider)
    330 
    331         if displayColor is None:
    332             return
    333         gradientColor = (1.0, displayColor[:3])
    334         for slider in slidersToColor:
    335             slider.ChangeGradientColor(secondColor=gradientColor)
    336 
    337     def CheckMouseOver(self, *args):
    338         if uicore.uilib.leftbtn or uicore.uilib.rightbtn:
    339             return
    340         if self.parent is None:
    341             return
    342         grandParent = self.parent.parent
    343         if uicore.uilib.mouseOver is self or uicore.uilib.mouseOver is grandParent or uicore.uilib.mouseOver.IsUnder(grandParent):
    344             if grandParent.browser and grandParent.IsExpanded():
    345                 activeData = grandParent.browser.GetActiveData()
    346                 if not activeData:
    347                     return
    348                 self.ExpandPalette()
    349                 return
    350         if self._expanded:
    351             self.CollapsePalette()
    352 
    353     def ExpandPalette(self, *args):
    354         if self.fadeOutThread:
    355             self.fadeOutThread.kill()
    356             self.fadeOutThread = None
    357         if self.fadeInThread:
    358             return
    359         self._expanded = True
    360         self.left = 0
    361         self.fadeInThread = uthread.new(self.ShowPalette_thread)
    362 
    363     def ShowPalette_thread(self, *args):
    364         if self and not self.destroyed:
    365             self.state = uiconst.UI_NORMAL
    366         animations.FadeIn(self, duration=0.5, sleep=True)
    367 
    368     def CollapsePalette(self, push = False, *args):
    369         if self.fadeInThread:
    370             self.fadeInThread.kill()
    371             self.fadeInThread = None
    372         if self.fadeOutThread:
    373             return
    374         self._expanded = False
    375         if push:
    376             animations.MorphScalar(self, 'left', endVal=-self.COLORPALETTEWIDTH, duration=0.15)
    377             animations.FadeOut(self, duration=0.15)
    378         else:
    379             self.fadeOutThread = uthread.new(self.HidePalette_thread)
    380 
    381     def HidePalette_thread(self, *args):
    382         animations.FadeOut(self, duration=0.75, sleep=True)
    383         if self and not self.destroyed:
    384             self.state = uiconst.UI_HIDDEN
    385 
    386     def PrepareCategoryColorOptions(self):
    387         info = uicore.layer.charactercreation.controller.GetInfo()
    388         categoryColors = sm.GetService('character').GetAvailableColorsForCategory(self.modifier, info.genderID, info.raceID)
    389         if not categoryColors:
    390             return
    391         primary, secondary = categoryColors
    392         self.hasSecondary = bool(secondary)
    393         uicore.layer.charactercreation.controller.ValidateColors(self.modifier)
    394         self.LoadColors(primary, secondary)
    395         self.primaryColors = primary
    396         self.secondaryColors = secondary
    397 
    398     def UpdatePalette(self):
    399         self.HiliteActive()
    400 
    401     def HiliteActive(self):
    402         info = uicore.layer.charactercreation.controller.GetInfo()
    403         charSvc = sm.GetService('character')
    404         currentPrimaryName, currentSecondaryName = charSvc.GetTypeColors(info.charID, self.modifier)
    405         if not currentPrimaryName:
    406             return
    407         if getattr(self, 'colorControlsCont', None) is None:
    408             return
    409         for each in self.colorControlsCont.children:
    410             if not getattr(each, 'colorValue', None):
    411                 continue
    412             each.activeFrame.state = uiconst.UI_HIDDEN
    413             if not self.hasSecondary:
    414                 if each.colorName == currentPrimaryName:
    415                     each.activeFrame.state = uiconst.UI_DISABLED
    416                     self.activePrimary = each
    417                 continue
    418             if each.colorName == currentPrimaryName:
    419                 each.activeFrame.state = uiconst.UI_DISABLED
    420                 self.activePrimary = each
    421             elif each.colorName == currentSecondaryName:
    422                 each.activeFrame.state = uiconst.UI_DISABLED
    423                 self.activeSecondary = each
    424 
    425     def GetNumColorAreas(self, *args):
    426         info = uicore.layer.charactercreation.controller.GetInfo()
    427         activeMod = sm.GetService('character').GetModifierByCategory(info.charID, self.modifier)
    428         if activeMod:
    429             return activeMod.metaData.numColorAreas
    430 
    431     def TryReloadColors(self, *args):
    432         numColorAreas = self.GetNumColorAreas()
    433         if numColorAreas is not None and self.currentNumColorAreas != numColorAreas:
    434             self.PrepareControls(reloading='oldColors')
    435 
    436     def LoadColors(self, primary, secondary):
    437         for each in self.children[:]:
    438             if each.name == 'colorPar':
    439                 each.Close()
    440 
    441         if self.modifier == ccConst.hair:
    442             firstColourCaption = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/HairRootColor')
    443             secondColourCaption = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/HairColor')
    444         else:
    445             firstColourCaption = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/NonHairColor')
    446             secondColourCaption = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/NonHairSecondaryColor')
    447         numColorAreas = self.GetNumColorAreas()
    448         self.currentNumColorAreas = numColorAreas
    449         if numColorAreas is not None:
    450             if numColorAreas < 2:
    451                 secondary = []
    452                 if self.modifier == ccConst.hair:
    453                     firstColourCaption = localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/HairColor')
    454             if numColorAreas < 1:
    455                 primary = []
    456         if not (primary or secondary):
    457             return
    458         top = 0
    459         left = self.SIDEMARGIN
    460         gapAndSize = self.currentColorSize + self.COLORGAP
    461         self.colorControlsCont = Container(parent=self, align=uiconst.TOTOP, idx=0)
    462         for colors in [primary, secondary]:
    463             if colors:
    464                 top += 20
    465                 inRow = self.width / gapAndSize
    466                 rows = len(colors) / inRow + bool(len(colors) % inRow)
    467                 colorHeight = top + rows * gapAndSize
    468                 top = colorHeight
    469                 self.SetSizeAutomatically()
    470                 if self.height + colorHeight > self.maxPaletteHeight:
    471                     if self.width > self.maxPaletteWidth:
    472                         if self.currentColorSize > self.MINCOLORSIZE:
    473                             self.currentColorSize = self.currentColorSize - 1
    474                             self.width = self.startingWidth
    475                             return self.LoadColors(primary, secondary)
    476                     else:
    477                         self.width += gapAndSize
    478                         return self.LoadColors(primary, secondary)
    479                 top += self.currentColorSize
    480 
    481         top = 0
    482         colorHeight = 0
    483         for colors, caption in ((primary, firstColourCaption), (secondary, secondColourCaption)):
    484             if not colors:
    485                 continue
    486             left = self.SIDEMARGIN
    487             top += 4
    488             label = CCLabel(parent=self.colorControlsCont, uppercase=1, shadowOffset=(0, 0), fontsize=9, letterspace=2, text=caption, top=top, left=left, color=ccConst.COLOR50, idx=0)
    489             top += label.textheight + 3
    490             for data in colors:
    491                 colorName, displayColor, colorValue = data
    492                 colorPar = Container(parent=self.colorControlsCont, pos=(left,
    493                  top,
    494                  self.currentColorSize,
    495                  self.currentColorSize), align=uiconst.TOPLEFT, state=uiconst.UI_NORMAL, name='colorPar', idx=0)
    496                 colorPar.OnClick = (self.OnColorPicked, colorPar)
    497                 colorPar.OnMouseEnter = (self.OnMouseEnterColor, colorPar)
    498                 colorPar.OnMouseExit = (self.OnMouseExitColor, colorPar)
    499                 colorPar.colorName = colorName
    500                 colorPar.displayColor = displayColor
    501                 colorPar.colorValue = colorValue
    502                 colorPar.modifier = self.modifier
    503                 colorPar.activeFrame = Frame(parent=colorPar, name='activeFrame', state=uiconst.UI_HIDDEN, frameConst=(ccConst.ICON_FOCUSFRAME, 15, -11), color=(1.0, 1.0, 1.0, 1.0))
    504                 colorPar.hiliteFrame = Frame(parent=colorPar, name='hiliteFrame', state=uiconst.UI_HIDDEN, frameConst=(ccConst.ICON_FOCUSFRAME, 15, -11), color=(1.0, 1.0, 1.0, 0.25))
    505                 f = Frame(parent=colorPar, color=(1.0, 1.0, 1.0, 0.05), padding=self.COLORMARGIN - 2)
    506                 Fill(parent=colorPar, color=displayColor, padding=self.COLORMARGIN)
    507                 colorHeight = top + self.currentColorSize
    508                 left += self.currentColorSize + self.COLORGAP
    509                 if left + self.currentColorSize > self.width:
    510                     top += self.currentColorSize + self.COLORGAP
    511                     left = self.SIDEMARGIN
    512 
    513             top += self.currentColorSize
    514 
    515         self.colorControlsCont.height = colorHeight
    516         self.HiliteActive()
    517         if self.width > self.previousWidth:
    518             sm.ScatterEvent('OnColorPaletteChanged', self.width)
    519         self.previousWidth = self.width
    520 
    521     def OnColorPicked(self, colorObj, *args):
    522         var1 = None
    523         var2 = None
    524         if self.hasSecondary:
    525             charID = uicore.layer.charactercreation.controller.GetInfo().charID
    526             currentPrimaryName, currentSecondaryName = sm.GetService('character').GetTypeColors(charID, self.modifier)
    527             if colorObj.colorName.lower().endswith('_bc'):
    528                 var2 = (colorObj.colorName, colorObj.colorValue)
    529                 for each in self.colorControlsCont.children:
    530                     if not getattr(each, 'colorValue', None):
    531                         continue
    532                     if each.colorName == currentPrimaryName:
    533                         var1 = (each.colorName, each.colorValue)
    534 
    535                 if var1 is None:
    536                     return
    537             else:
    538                 var1 = (colorObj.colorName, colorObj.colorValue)
    539                 if currentSecondaryName:
    540                     for each in self.colorControlsCont.children:
    541                         if not getattr(each, 'colorValue', None):
    542                             continue
    543                         if each.colorName == currentSecondaryName:
    544                             var2 = (each.colorName, each.colorValue)
    545 
    546         else:
    547             var1 = (colorObj.colorName, colorObj.colorValue)
    548         if not colorObj.colorName.lower().endswith('_bc'):
    549             displayColor = colorObj.displayColor
    550             gradientColor = (1.0, displayColor[:3])
    551             self.SetGradientsColor(displayColor=displayColor)
    552         uicore.layer.charactercreation.controller.SetColorValue(self.modifier, var1, var2)
    553 
    554     def SetSliderValue(self, slider):
    555         value = slider.GetValue()
    556         if slider.sliderType == 'lights':
    557             intensity = slider.GetValue()
    558             uicore.layer.charactercreation.controller.SetLightIntensity(intensity)
    559         elif slider.sliderType == 'intensity':
    560             info = uicore.layer.charactercreation.controller.GetInfo()
    561             value = sm.GetService('character').GetTrueWeight(info.charID, slider.modifier, value)
    562             uicore.layer.charactercreation.controller.SetIntensity(slider.modifier, value)
    563         elif slider.sliderType == 'specularity':
    564             uicore.layer.charactercreation.controller.SetColorSpecularity(slider.modifier, value)
    565         elif slider.sliderType == HAIRDARKNESS:
    566             uicore.layer.charactercreation.controller.SetHairDarkness(value)
    567 
    568     def OnMouseWheel(self, *args):
    569         pass
    570 
    571     def OnMouseEnterColor(self, colorPar, *args):
    572         colorPar.hiliteFrame.state = uiconst.UI_DISABLED
    573 
    574     def OnMouseExitColor(self, colorPar, *args):
    575         colorPar.hiliteFrame.state = uiconst.UI_HIDDEN
    576 
    577 
    578 class CharCreationAssetPicker(Container):
    579     __notifyevents__ = ['OnDollUpdated', 'OnColorPaletteChanged', 'OnPortraitPicked']
    580     FULLHEIGHT = 190
    581     COLLAPSEHEIGHT = 22
    582     default_align = uiconst.TOTOP
    583     default_left = 0
    584     default_top = 0
    585     default_width = 0
    586     default_height = COLLAPSEHEIGHT
    587     default_name = 'CharCreationAssetPicker'
    588     default_state = uiconst.UI_PICKCHILDREN
    589 
    590     def ApplyAttributes(self, attributes):
    591         sm.GetService('cc').LogInfo('CharCreationAssetPicker::ApplyAttributes:: modifier = ', attributes.modifier)
    592         for each in uicore.layer.main.children:
    593             if each.name == self.default_name:
    594                 each.Close()
    595 
    596         self.bloodlineID = attributes.bloodlineID
    597         if attributes.isSubmenu:
    598             self.COLLAPSEHEIGHT = 18
    599             attributes.heght = 18
    600         Container.ApplyAttributes(self, attributes)
    601         if attributes.parent is None:
    602             uicore.layer.main.children.append(self)
    603         self._expandTime = None
    604         self._expanded = False
    605         self._didRandomize = None
    606         self.randomButton = None
    607         self.colorPalette = None
    608         self.browser = None
    609         self.colorIntensitySlider = None
    610         self._sliders = []
    611         self._colorPickers = []
    612         self.colorPaletteParent = Container(parent=self, align=uiconst.TOLEFT, width=CCColorPalette.COLORPALETTEWIDTH, name='colorPaletteParent', state=uiconst.UI_PICKCHILDREN)
    613         self.captionParent = Container(parent=self, align=uiconst.TOTOP, height=self.COLLAPSEHEIGHT, name='captionParent', state=uiconst.UI_NORMAL)
    614         self.captionParent.OnClick = self.Toggle
    615         self.captionParent.OnMouseEnter = self.OnCaptionEnter
    616         self.captionParent.OnMouseExit = self.OnCaptionExit
    617         self.captionParent.modifier = attributes.modifier
    618         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)
    619         self.caption.SetAlpha(0.5)
    620         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)
    621         if attributes.isSubmenu:
    622             Fill(parent=self.captionParent, color=(0.2, 0.2, 0.2, 0.4))
    623             self.caption.fontsize = 12
    624             bevelAlpha = 0.1
    625         else:
    626             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)
    627             Frame(parent=self.captionParent, frameConst=ccConst.MAINFRAME_INV, color=(1.0, 1.0, 1.0, 0.5))
    628             Fill(parent=self.captionParent, color=(0.0, 0.0, 0.0, 0.5))
    629             bevelAlpha = 0.2
    630         self.bevel = Frame(parent=self.captionParent, color=(1.0,
    631          1.0,
    632          1.0,
    633          bevelAlpha), frameConst=ccConst.FILL_BEVEL, state=uiconst.UI_HIDDEN)
    634         frame = Frame(parent=self.captionParent, frameConst=ccConst.FRAME_SOFTSHADE, color=(1.0, 1.0, 1.0, 0.5))
    635         frame.padding = (-12, -5, -12, -15)
    636         self.mainParent = Container(parent=self, align=uiconst.TOALL, name='mainParent')
    637         if attributes.modifier in ccConst.REMOVEABLE:
    638             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)
    639             self.removeParent.OnClick = (self.RemoveAsset, self.removeParent)
    640             self.removeParent.OnMouseEnter = (self.OnGenericMouseEnter, self.removeParent)
    641             self.removeParent.OnMouseExit = (self.OnGenericMouseExit, self.removeParent)
    642             self.removeParent.modifier = attributes.modifier
    643             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)
    644         modifier = attributes.modifier
    645         if modifier == ccConst.EYESGROUP:
    646             modifier = ccConst.eyes
    647         elif modifier == ccConst.HAIRGROUP:
    648             modifier = ccConst.hair
    649         Frame(parent=self.mainParent, frameConst=ccConst.MAINFRAME, color=(1.0, 1.0, 1.0, 0.5))
    650         self.assetParent = Container(parent=self.mainParent, align=uiconst.TOALL, name='assetParent', clipChildren=True, padding=(1, 1, 1, 1))
    651         self.modifier = modifier
    652         self.isSubmenu = attributes.isSubmenu
    653         self.groupID = attributes.groupID
    654         genderID = attributes.genderID
    655         if modifier is not None:
    656             if modifier == ccConst.BACKGROUNDGROUP:
    657                 self.FULLHEIGHT = 170
    658                 self.PrepareBackgrounds()
    659             elif modifier == ccConst.POSESGROUP:
    660                 self.FULLHEIGHT = 170
    661                 self.PreparePoses()
    662             elif modifier == ccConst.LIGHTSGROUP:
    663                 self.PrepareLights()
    664             elif modifier == ccConst.SKINGROUP:
    665                 self.FULLHEIGHT = 150
    666                 self.PrepareSkinTone()
    667             elif modifier == ccConst.BODYGROUP:
    668                 self.FULLHEIGHT = 70
    669                 self.PrepareBodyShape()
    670             elif modifier == ccConst.hair:
    671                 self.PrepareHair()
    672             elif type(modifier) is not types.IntType:
    673                 self.FULLHEIGHT = 150
    674                 if modifier == ccConst.eyeshadow:
    675                     self.FULLHEIGHT = 180
    676                 itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(modifier)
    677                 categoryName = modifier.replace('/', '_')
    678                 assetData = []
    679                 numSpecialItems = 0
    680                 for itemType in itemTypes:
    681                     if itemType[2] is not None:
    682                         numSpecialItems += 1
    683                     path = self.GetAssetThumbnailPath(itemType, genderID, categoryName, self.bloodlineID)
    684                     assetData.append((path, itemType, ''))
    685 
    686                 self.browser = eveImagePicker.ImagePicker(parent=self.assetParent, align=uiconst.CENTER, imageWidth=96, imageHeight=96, zoomFactor=3.0, radius=150.0, images=assetData, numSpecialItems=numSpecialItems, OnSetValue=self.OnStylePicked)
    687                 self.browser.assetCategory = modifier
    688             else:
    689                 self.FULLHEIGHT = self.COLLAPSEHEIGHT
    690         Fill(parent=self.mainParent, color=(0.25, 0.25, 0.25, 0.25))
    691         self.mainParent.SetOpacity(0.0)
    692         self.height = self.captionParent.height
    693         self.expanderIcon.LoadIcon([ccConst.ICON_COLLAPSED, ccConst.ICON_COLLAPSEDSINGLE][self.isSubmenu])
    694         if not attributes.isSubmenu:
    695             self.state = uiconst.UI_PICKCHILDREN
    696         else:
    697             self.state = uiconst.UI_HIDDEN
    698         sm.RegisterNotify(self)
    699 
    700     def OnMouseEnter(self, *args):
    701         if self.randomButton:
    702             self.randomButton.Show()
    703         self.caption.SetRGBA(*eveColor.PRIMARY_BLUE)
    704         super(CharCreationAssetPicker, self).OnMouseEnter(*args)
    705 
    706     def OnMouseExit(self, *args):
    707         if self.randomButton:
    708             self.randomButton.Hide()
    709         self.caption.SetRGBA(*ccConst.COLOR)
    710         super(CharCreationAssetPicker, self).OnMouseExit(*args)
    711 
    712     def GetAssetThumbnailPath(self, itemType, genderID, categoryName, bloodlineID):
    713         path = ''
    714         if itemType[2] is not None:
    715             if genderID == 0:
    716                 genderText = 'Female'
    717             else:
    718                 genderText = 'Male'
    719             assetResPath = cfg.paperdollResources.Get(itemType[0]).resPath
    720             assetResPath = assetResPath.replace('/', '_').replace('.type', '')
    721             tempPath = 'res:/UI/Asset/mannequin/%s/%s_%s_%s.png' % (categoryName,
    722              itemType[2],
    723              genderText,
    724              assetResPath)
    725             if blue.paths.exists(tempPath):
    726                 path = tempPath
    727         if not path:
    728             path = 'res:/UI/Asset/%s_g%s_b%s.png' % ('_'.join(list(itemType[1])).replace('/', '_'), genderID, bloodlineID)
    729         return path
    730 
    731     def RandomizeGroup(self, groupID, *args):
    732         PlaySound('ui_icc_button_mouse_down_play')
    733         if uicore.layer.charactercreation.controller.doll.busyUpdating:
    734             raise UserError('uiwarning01')
    735         uicore.layer.charactercreation.controller.LockNavigation()
    736         svc = sm.GetService('character')
    737         info = uicore.layer.charactercreation.controller.GetInfo()
    738         if info.genderID == ccConst.GENDERID_FEMALE:
    739             itemDict = ccConst.femaleRandomizeItems
    740         else:
    741             itemDict = ccConst.maleRandomizeItems
    742         if groupID in (ccConst.BACKGROUNDGROUP, ccConst.POSESGROUP, ccConst.LIGHTSGROUP):
    743             randomPick = random.choice(self.browser.images)
    744             self.browser.SetActiveData(randomPick)
    745         elif groupID == ccConst.BODYGROUP:
    746             svc.RandomizeCharacterSculpting(info.charID, info.raceID, doUpdate=False)
    747             self.UpdateControls('OnDollUpdated', setFocusOnActive=True)
    748             svc.UpdateTattoos(info.charID, doUpdate=True)
    749             uicore.layer.charactercreation.controller.TryStoreDna(False, 'Sculpting', force=True)
    750         else:
    751             groupList = []
    752             for key, value in itemDict.iteritems():
    753                 if value == groupID:
    754                     groupList.append(key)
    755 
    756             if len(groupList) > 0:
    757                 svc.RandomizeCharacterGroups(info.charID, info.raceID, groupList, doUpdate=True)
    758             for cat in groupList:
    759                 if cat in ccConst.COLORMAPPING:
    760                     uicore.layer.charactercreation.controller.UpdateColorSelectionFromDoll(cat)
    761 
    762         if groupID == ccConst.CLOTHESGROUP:
    763             uicore.layer.charactercreation.controller.ToggleClothes(forcedValue=0)
    764         self._didRandomize = [groupID]
    765         uicore.layer.charactercreation.controller.UnlockNavigation()
    766 
    767     def GetAssetBloodlineID(self, fromBloodlineID):
    768         if fromBloodlineID in (1, 8, 7, 3, 2, 5, 6):
    769             assetBloodlineID = 1
    770         elif fromBloodlineID in (4,):
    771             assetBloodlineID = 4
    772         elif fromBloodlineID in (14, 12, 11, 13):
    773             assetBloodlineID = 14
    774         else:
    775             assetBloodlineID = 1
    776         return assetBloodlineID
    777 
    778     def OnDollUpdated(self, charID, redundantUpdate, *args):
    779         info = uicore.layer.charactercreation.controller.GetInfo()
    780         if charID == info.charID and self and not self.destroyed:
    781             self.UpdateControls('OnDollUpdated', setFocusOnActive=True)
    782 
    783     def OnPortraitPicked(self, *args):
    784         pickerType = getattr(self, 'pickerType', None)
    785         if pickerType is None:
    786             return
    787         if pickerType == 'backgrounds':
    788             activeBackdrop = uicore.layer.charactercreation.controller.GetBackdrop()
    789             if activeBackdrop:
    790                 self.browser.SetActiveDataFromValue(activeBackdrop, focusOnSlot=True, doCallbacks=False, doYield=False)
    791         elif pickerType == 'poses':
    792             poseID = uicore.layer.charactercreation.controller.GetPoseId()
    793             self.browser.SetActiveDataFromValue(poseID, focusOnSlot=True, doCallbacks=False, doYield=False)
    794         elif pickerType == 'lights':
    795             currentLight = uicore.layer.charactercreation.controller.GetLight()
    796             self.browser.SetActiveDataFromValue(currentLight, focusOnSlot=True, doCallbacks=False, doYield=False)
    797             if uicore.layer.charactercreation.controller.IsSlowMachine():
    798                 return
    799             self.BrowseLightColors(None)
    800             if self.colorPalette:
    801                 intensitySlider = self.colorPalette.lights
    802                 intensitySlider.SetValue(uicore.layer.charactercreation.controller.GetLightIntensity())
    803 
    804     def OnGenericMouseEnter(self, btn, *args):
    805         PlaySound('ui_icc_button_mouse_over_play')
    806         btn.icon.SetAlpha(1.0)
    807         if btn.sr.label:
    808             btn.label.SetAlpha(1.0)
    809 
    810     def OnGenericMouseExit(self, btn, *args):
    811         btn.icon.SetAlpha(0.5)
    812         if btn.sr.label:
    813             btn.label.SetAlpha(0.5)
    814 
    815     def OnGenericMouseDown(self, btn, *args):
    816         btn.icon.top += 1
    817 
    818     def OnGenericMouseUp(self, btn, *args):
    819         btn.icon.top -= 1
    820 
    821     def OnTuckBrowse(self, btn, *args):
    822         if getattr(self.colorPalette.tuckParent, 'tuckOptions', None) is None:
    823             return
    824         tuckOptions = self.colorPalette.tuckParent.tuckOptions
    825         currentIndex = self.colorPalette.tuckParent.tuckIndex
    826         if btn.name == 'leftBtn':
    827             if currentIndex == 0:
    828                 currentIndex = len(tuckOptions) - 1
    829             else:
    830                 currentIndex = currentIndex - 1
    831         elif currentIndex == len(tuckOptions) - 1:
    832             currentIndex = 0
    833         else:
    834             currentIndex = currentIndex + 1
    835         uicore.layer.charactercreation.controller.SetStyle(self.colorPalette.tuckParent.tuckPath, self.colorPalette.tuckParent.tuckStyle, tuckOptions[currentIndex])
    836 
    837     def PrepareHair(self):
    838         self.FULLHEIGHT = 170
    839         svc = sm.GetService('character')
    840         info = uicore.layer.charactercreation.controller.GetInfo()
    841         itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.hair)
    842         assetData = []
    843         for itemType in itemTypes:
    844             path = self.GetAssetThumbnailPath(itemType, info.genderID, ccConst.hair, self.bloodlineID)
    845             assetData.append((path, itemType, ''))
    846 
    847         subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=130)
    848         self.browser = eveImagePicker.ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=96, imageHeight=96, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnStylePicked)
    849         self.browser.assetCategory = ccConst.hair
    850         Line(parent=self.assetParent, align=uiconst.TOTOP, padding=(6, 0, 6, 0), color=(1.0, 1.0, 1.0, 0.1))
    851         itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.eyebrows)
    852         assetData = []
    853         for itemType in itemTypes:
    854             assetData.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('_'.join(list(itemType[1])).replace('/', '_'), info.genderID, self.bloodlineID), itemType, ''))
    855 
    856         subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=92)
    857         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)
    858         removeParent.OnMouseEnter = (self.OnGenericMouseEnter, removeParent)
    859         removeParent.OnMouseExit = (self.OnGenericMouseExit, removeParent)
    860         removeParent.modifier = ccConst.eyebrows
    861         removeParent.icon = eveIcon.Icon(name='removeIcon', icon=ccConst.ICON_CLOSE, parent=removeParent, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, color=ccConst.COLOR50, left=-9)
    862         self.altbrowser = eveImagePicker.ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=64, imageHeight=64, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnStylePicked)
    863         self.altbrowser.removeParent = removeParent
    864         removeParent.OnClick = (self.RemoveHairAsset, removeParent, self.altbrowser)
    865         self.altbrowser.assetCategory = ccConst.eyebrows
    866         self.FULLHEIGHT += 80
    867         self.beardbrowser = None
    868         if info.genderID == 1:
    869             Line(parent=self.assetParent, align=uiconst.TOTOP, padding=(6, 0, 6, 0), color=(1.0, 1.0, 1.0, 0.1))
    870             itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.beard)
    871             assetData = []
    872             for itemType in itemTypes:
    873                 assetData.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('_'.join(list(itemType[1])).replace('/', '_'), info.genderID, self.bloodlineID), itemType, ''))
    874 
    875             subPar = Container(parent=self.assetParent, align=uiconst.TOTOP, height=92)
    876             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)
    877             removeParent.OnMouseEnter = (self.OnGenericMouseEnter, removeParent)
    878             removeParent.OnMouseExit = (self.OnGenericMouseExit, removeParent)
    879             removeParent.modifier = ccConst.beard
    880             removeParent.icon = eveIcon.Icon(name='removeIcon', icon=ccConst.ICON_CLOSE, parent=removeParent, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT, color=ccConst.COLOR50, left=-9)
    881             self.beardbrowser = eveImagePicker.ImagePicker(parent=subPar, align=uiconst.CENTER, imageWidth=64, imageHeight=64, zoomFactor=3.0, radius=150.0, images=assetData, OnSetValue=self.OnStylePicked)
    882             self.beardbrowser.removeParent = removeParent
    883             removeParent.OnClick = (self.RemoveHairAsset, removeParent, self.beardbrowser)
    884             self.beardbrowser.assetCategory = ccConst.beard
    885             self.FULLHEIGHT += 90
    886 
    887     def PrepareBodyShape(self):
    888         l, t, w, h = self.assetParent.GetAbsolute()
    889         sliderWidth = (w - 30) / 2
    890         left = 10
    891         for sModifier in (ccConst.muscle, ccConst.weight):
    892             slider = charCreation.BitSlider(parent=self.assetParent, name=sModifier + '_slider', align=uiconst.CENTERLEFT, OnSetValue=self.OnSetSliderValue, sliderWidth=sliderWidth, left=left, top=7)
    893             left += sliderWidth + 10
    894             label = CCLabel(parent=slider, text=localization.GetByLabel(maleModifierDisplayNames.get(sModifier, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption')), top=-18, color=ccConst.COLOR50)
    895             slider.modifier = sModifier
    896             self._sliders.append(slider)
    897 
    898     def PrepareBackgrounds(self):
    899         self.modifier = None
    900         self.pickerType = 'backgrounds'
    901         images = []
    902         charSvc = sm.GetService('character')
    903         ccLayer = uicore.layer.charactercreation.controller
    904         activeBackdrop = ccLayer.GetBackdrop()
    905         if not gfxsettings.Get(gfxsettings.UI_NCC_GREEN_SCREEN):
    906             if activeBackdrop is not None and ccLayer.GetCurrentBackgroundID() < appconst.NCC_MIN_NORMAL_BACKGROUND_ID:
    907                 activeBackdrop = None
    908         backgroundOptions = ccLayer.GetAvailableBackgroundsPaths()
    909         if activeBackdrop not in backgroundOptions:
    910             activeBackdrop = None
    911         numSpecialItems = 0
    912         for background in backgroundOptions:
    913             resource = charSvc.GetPortraitResourceByPath(background)
    914             typeID = resource.typeID if resource else None
    915             bgID = resource.portraitResourceID if resource else -1
    916             if typeID:
    917                 numSpecialItems += 1
    918                 bgID = -bgID
    919             images.append((bgID, (background.replace('.dds', '_thumb.dds'), ('background', background, typeID), None)))
    920 
    921         images = SortListOfTuples(images)
    922         if activeBackdrop is None:
    923             activeBackdrop = random.choice(images)
    924             self.OnSetBackground(activeBackdrop[1][1])
    925             activeBackdrop = activeBackdrop[0]
    926         self.browser = eveImagePicker.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)
    927         if activeBackdrop:
    928             self.browser.SetActiveDataFromValue(activeBackdrop, focusOnSlot=True, doCallbacks=False, doYield=False)
    929 
    930     def PreparePoses(self):
    931         info = uicore.layer.charactercreation.controller.GetInfo()
    932         self.modifier = None
    933         self.pickerType = 'poses'
    934         posesData = []
    935         assetBloodlineID = self.GetAssetBloodlineID(info.bloodlineID)
    936         for i in range(ccConst.POSERANGE):
    937             posesData.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('pose_%s' % i, info.genderID, assetBloodlineID), ('pose', i), None))
    938 
    939         self.browser = eveImagePicker.ImagePicker(parent=self.assetParent, align=uiconst.CENTERTOP, top=-10, imageWidth=110, imageHeight=110, zoomFactor=3.0, radius=150.0, images=posesData, OnSetValue=self.OnAltSetAsset)
    940         activePose = int(uicore.layer.charactercreation.controller.GetPoseId())
    941         if activePose:
    942             pose = posesData[activePose]
    943         else:
    944             pose = random.choice(posesData)
    945         self.OnAltSetAsset(pose)
    946         self.browser.SetActiveDataFromValue(pose[1][1], focusOnSlot=True, doCallbacks=False, doYield=False)
    947 
    948     def PrepareLights(self):
    949         info = uicore.layer.charactercreation.controller.GetInfo()
    950         self.modifier = None
    951         self.pickerType = 'lights'
    952         currentLight = uicore.layer.charactercreation.controller.GetLight()
    953         currentLightColor = uicore.layer.charactercreation.controller.GetLightColor()
    954         lightingList = ccConst.LIGHT_SETTINGS_ID
    955         lightingColorList = ccConst.LIGHT_COLOR_SETTINGS_ID
    956         currentIndex = lightingColorList.index(currentLightColor)
    957         defaultThumbnailColor = lightingColorList[0]
    958         lightStyles = []
    959         assetBloodlineID = self.GetAssetBloodlineID(info.bloodlineID)
    960         for each in lightingList:
    961             lightStyles.append(('res:/UI/Asset/%s_g%s_b%s.png' % ('light_%s_%s' % (each, defaultThumbnailColor), info.genderID, assetBloodlineID), ('light', each), None))
    962 
    963         self.browser = eveImagePicker.ImagePicker(parent=self.assetParent, align=uiconst.CENTERTOP, top=-10, imageWidth=110, imageHeight=110, zoomFactor=3.0, radius=150.0, images=lightStyles, OnSetValue=self.OnAltSetAsset)
    964         if self.colorPalette is None:
    965             self.CreateColorPallette(isLights=True)
    966         self.colorPalette.tuckParent.display = True
    967         self.browser.SetActiveDataFromValue(currentLight, focusOnSlot=True, doCallbacks=False, doYield=False)
    968         self.colorPalette.SetTuckingCounter(currentIndex + 1, len(lightingColorList))
    969 
    970     def BrowseLightColors(self, btn, *args):
    971         currentLightColor = uicore.layer.charactercreation.controller.GetLightColor()
    972         lightingColorList = ccConst.LIGHT_COLOR_SETTINGS_ID
    973         currentIndex = lightingColorList.index(currentLightColor)
    974         if btn:
    975             if btn.name == 'leftBtn':
    976                 currentIndex -= 1
    977                 if currentIndex == -1:
    978                     currentIndex = len(lightingColorList) - 1
    979             else:
    980                 currentIndex += 1
    981                 if currentIndex == len(lightingColorList):
    982                     currentIndex = 0
    983         uicore.layer.charactercreation.controller.SetLightColor(lightingColorList[currentIndex])
    984         self.colorPalette.SetTuckingCounter(currentIndex + 1, len(lightingColorList))
    985 
    986     def OnAltSetAsset(self, assetData, *args):
    987         if assetData:
    988             thumb, assetData, hiliteResPath = assetData
    989             k = assetData[0]
    990             v = assetData[1]
    991             if k == 'background':
    992                 uicore.layer.charactercreation.controller.SetBackdrop(v)
    993                 uicore.layer.charactercreation.controller.UpdateBackdrop()
    994             elif k == 'light':
    995                 uicore.layer.charactercreation.controller.SetLights(v)
    996             elif k == 'pose':
    997                 uicore.layer.charactercreation.controller.SetPoseID(assetData[1])
    998                 info = uicore.layer.charactercreation.controller.GetInfo()
    999                 sm.GetService('character').ChangePose(v, info.charID)
   1000                 if uicore.layer.charactercreation.controller.camera is not None:
   1001                     uicore.layer.charactercreation.controller.camera.UpdatePortraitInfo()
   1002             self.UpdateControls('OnAltSetAsset')
   1003 
   1004     def OnSetBackground(self, bgPath, *args):
   1005         uicore.layer.charactercreation.controller.SetBackdrop(bgPath)
   1006         uicore.layer.charactercreation.controller.UpdateBackdrop()
   1007 
   1008     def OnColorPaletteChanged(self, width):
   1009         self.colorPaletteParent.width = width
   1010 
   1011     def PrepareSkinTone(self):
   1012         itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(ccConst.skintype)
   1013         itemsWithDisplayColor = []
   1014         for i, each in enumerate(itemTypes):
   1015             itemsWithDisplayColor.append(('colorName', ccConst.SKINTYPECOLORS.get(str(each[1][2]), (1, 1, 1, 1)), each))
   1016 
   1017         colorPicker = charCreationColorPicker.CharCreationColorPicker(parent=self.assetParent, align=uiconst.CENTERLEFT, colors=itemsWithDisplayColor, OnSetValue=self.OnSkinTypePicked, activeColorIndex=activeIndex)
   1018         colorPicker.modifier = ccConst.skintype
   1019         self._colorPickers.append(colorPicker)
   1020         l, t, w, h = self.assetParent.GetAbsolute()
   1021         sliderWidth = w - 130 - 10
   1022         left = 10
   1023         top = -32
   1024         for sModifier in (ccConst.skinaging, ccConst.freckles, ccConst.scarring):
   1025             itemTypes, activeIdx = uicore.layer.charactercreation.controller.GetAvailableStyles(sModifier)
   1026             bitAmount = len(itemTypes)
   1027             slider = charCreation.BitSlider(parent=self.assetParent, name=sModifier + '_slider', align=uiconst.CENTERLEFT, OnSetValue=self.OnSetSliderValue, bitAmount=bitAmount, sliderWidth=sliderWidth, left=130, top=top)
   1028             top += 32
   1029             label = CCLabel(parent=slider, text=localization.GetByLabel(maleModifierDisplayNames.get(sModifier, 'UI/Login/CharacterCreation/AssetMenu/MissingCaption')), top=-18, color=ccConst.COLOR50)
   1030             slider.modifier = sModifier
   1031             self._sliders.append(slider)
   1032 
   1033     def OnSetSliderValue(self, slider):
   1034         value = slider.GetValue()
   1035         if slider.modifier in (ccConst.skinaging, ccConst.freckles, ccConst.scarring):
   1036             itemTypes, activeIdx = uicore.layer.charactercreation.controller.GetAvailableStyles(slider.modifier)
   1037             styleRange = 1.0 / len(itemTypes)
   1038             portionalIndex = int(len(itemTypes) * (value + styleRange / 2))
   1039             if portionalIndex == 0:
   1040                 uicore.layer.charactercreation.controller.ClearCategory(slider.modifier)
   1041             else:
   1042                 uicore.layer.charactercreation.controller.SetItemType(itemTypes[portionalIndex - 1])
   1043         else:
   1044             uicore.layer.charactercreation.controller.SetIntensity(slider.modifier, value)
   1045 
   1046     def ShowActiveItem(self, *args):
   1047         if self.browser:
   1048             active = self.browser.GetActiveData()
   1049             if active:
   1050                 self.browser.SetActiveData(active)
   1051 
   1052     def RemoveAsset(self, button, *args):
   1053         uicore.layer.charactercreation.controller.ClearCategory(button.modifier)
   1054         if self.browser:
   1055             self.browser.SetActiveData(None, focusOnSlot=False)
   1056             self.CollapseColorPalette()
   1057 
   1058     def RemoveHairAsset(self, button, browser, *args):
   1059         info = uicore.layer.charactercreation.controller.GetInfo()
   1060         modifiers = sm.GetService('character').GetModifierByCategory(info.charID, button.modifier, getAll=True)
   1061         for each in modifiers:
   1062             uicore.layer.charactercreation.controller.ClearCategory(button.modifier)
   1063 
   1064     def OnCaptionEnter(self, *args):
   1065         uicore.layer.charactercreation.controller.SetHintText(self.captionParent.modifier)
   1066         sm.StartService('audio').SendUIEvent(unicode('ui_icc_menu_mouse_over_play'))
   1067         self.caption.SetAlpha(1.0)
   1068         self.expanderIcon.SetAlpha(1.0)
   1069         if self.bevel:
   1070             self.bevel.state = uiconst.UI_DISABLED
   1071 
   1072     def OnCaptionExit(self, *args):
   1073         uicore.layer.charactercreation.controller.SetHintText(None)
   1074         if not self.IsExpanded():
   1075             self.caption.SetAlpha(0.5)
   1076             self.expanderIcon.SetAlpha(0.5)
   1077         if self.bevel:
   1078             self.bevel.state = uiconst.UI_HIDDEN
   1079 
   1080     def Toggle(self, *args):
   1081         sm.StartService('audio').SendUIEvent(unicode('ui_icc_button_mouse_down_play'))
   1082         if self._expanded:
   1083             self.Collapse()
   1084         else:
   1085             self.Expand()
   1086 
   1087     def IsExpanded(self):
   1088         return self._expanded
   1089 
   1090     def UpdateControls(self, trigger = None, setFocusOnActive = False):
   1091         subMenus = self.GetMySubmenus()
   1092         if not self.IsExpanded() or subMenus:
   1093             if subMenus and self._didRandomize and self.groupID in self._didRandomize:
   1094                 self._didRandomize = None
   1095                 for each in subMenus:
   1096                     each.UpdateControls('UpdateControls', setFocusOnActive=True)
   1097 
   1098             return
   1099         try:
   1100             if self.colorPalette:
   1101                 uicore.layer.charactercreation.controller.ValidateColors(self.modifier)
   1102                 self.colorPalette.UpdatePalette()
   1103         except Exception:
   1104             if not self or self.destroyed:
   1105                 return
   1106             raise
   1107 
   1108         info = uicore.layer.charactercreation.controller.GetInfo()
   1109         charSvc = sm.GetService('character')
   1110         browsersAndModifiers = [(self.browser, self.modifier)]
   1111         if self.modifier == ccConst.hair:
   1112             browsersAndModifiers.append((self.altbrowser, ccConst.eyebrows))
   1113             if hasattr(self, 'beardbrowser'):
   1114                 browsersAndModifiers.append((self.beardbrowser, ccConst.beard))
   1115         for browser, modifier in browsersAndModifiers:
   1116             if browser and modifier is not None:
   1117                 if modifier == ccConst.beard:
   1118                     activeMod = None
   1119                     activeMods = charSvc.GetModifierByCategory(info.charID, modifier, getAll=True)
   1120                     if activeMods:
   1121                         if len(activeMods) == 1:
   1122                             activeMod = activeMods[0]
   1123                         else:
   1124                             for a in activeMods:
   1125                                 if a.respath == ccConst.BASEBEARD:
   1126                                     continue
   1127                                 activeMod = a
   1128                                 break
   1129                             else:
   1130                                 activeMod = activeMods[0]
   1131 
   1132                 else:
   1133                     activeMod = charSvc.GetModifierByCategory(info.charID, modifier)
   1134                     if activeMod and activeMod.name in ccConst.invisibleModifiers:
   1135                         activeMod = None
   1136                     if not activeMod and modifier in uicore.layer.charactercreation.controller.clothesStorage:
   1137                         activeMod = uicore.layer.charactercreation.controller.clothesStorage.get(modifier, None)
   1138                 if activeMod:
   1139                     uthread.new(self.SetActiveData_thread, browser, activeMod, setFocusOnActive)
   1140                 else:
   1141                     browser.SetActiveData(None, focusOnSlot=False, doCallbacks=False)
   1142 
   1143         self.LoadTuckOptions()
   1144         self.LoadRemoveOptions()
   1145         for colorPicker in self._colorPickers:
   1146             if not getattr(colorPicker, 'modifier', None):
   1147                 continue
   1148             itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(colorPicker.modifier)
   1149             if activeIndex is None:
   1150                 colorPicker.SetActiveColor(None, initing=True)
   1151             else:
   1152                 activeColor = itemTypes[activeIndex]
   1153                 colorPicker.SetActiveColor(activeColor, initing=True)
   1154 
   1155         for slider in self._sliders:
   1156             if not getattr(slider, 'modifier', None):
   1157                 continue
   1158             if slider.modifier in (ccConst.skinaging, ccConst.freckles, ccConst.scarring):
   1159                 itemTypes, activeIndex = uicore.layer.charactercreation.controller.GetAvailableStyles(slider.modifier)
   1160                 if not itemTypes:
   1161                     continue
   1162                 if activeIndex is None:
   1163                     activeIndex = 0
   1164                 else:
   1165                     activeIndex = activeIndex + 1
   1166                 value = 1.0 / float(len(itemTypes)) * activeIndex
   1167                 slider.SetValue(value, doCallback=False)
   1168             elif slider.modifier in ccConst.weight:
   1169                 weight = charSvc.GetCharacterWeight(info.charID)
   1170                 slider.SetValue(weight, doCallback=False)
   1171             elif slider.modifier == ccConst.muscle:
   1172                 muscularity = charSvc.GetCharacterMuscularity(info.charID)
   1173                 slider.SetValue(muscularity, doCallback=False)
   1174             elif slider.modifier == ccConst.hair:
   1175                 slider.SetValue(charSvc.GetHairDarkness(info.charID), doCallback=False)
   1176                 slider.parent.SetGradientsColor()
   1177             else:
   1178                 activeMod = charSvc.GetModifierByCategory(info.charID, slider.modifier)
   1179                 if activeMod:
   1180                     if slider.sliderType == 'intensity':
   1181                         slider.SetValue(charSvc.GetWeightByCategory(info.charID, slider.modifier))
   1182                         slider.parent.SetGradientsColor()
   1183                     elif slider.sliderType == 'specularity':
   1184                         slider.SetValue(charSvc.GetColorSpecularityByCategory(info.charID, slider.modifier))
   1185 
   1186     def SetActiveData_thread(self, browser, activeMod, setFocusOnActive):
   1187         typeData = activeMod.GetTypeData()
   1188         if typeData[0].startswith(('makeup', 'beard')) and typeData[2] in ('default', 'none'):
   1189             typeData = (typeData[0], typeData[1], '')
   1190         if browser and hasattr(browser, 'SetActiveDataFromValue'):
   1191             browser.SetActiveDataFromValue(typeData, doCallbacks=False, focusOnSlot=setFocusOnActive, doYield=False)
   1192             if self.colorPalette:
   1193                 self.colorPalette.TryReloadColors()
   1194             self.LoadTuckOptions()
   1195             self.LoadRemoveOptions()
   1196 
   1197     def DebugRoleCheck(self):
   1198         mask = serviceConst.ROLE_CONTENT | serviceConst.ROLE_QA | serviceConst.ROLE_PROGRAMMER | serviceConst.ROLE_GML
   1199         if session.role & mask and not prefs.GetValue('CCHideAssetDebugText', False):
   1200             return True
   1201         else:
   1202             return False
   1203 
   1204     def UpdatePrefs(self, state):
   1205         currentMenuState = settings.user.ui.Get('assetMenuState', {ccConst.BODYGROUP: 1})
   1206         key = self.modifier or 'group_%s' % getattr(self, 'groupID', '')
   1207         currentMenuState[key] = state
   1208         settings.user.ui.Set('assetMenuState', currentMenuState)
   1209 
   1210     def Expand(self, initing = False):
   1211         if self._expanded:
   1212             return
   1213         self._expanded = True
   1214         self._expandTime = blue.os.GetWallclockTime()
   1215         self.caption.SetAlpha(1.0)
   1216         self.expanderIcon.SetAlpha(1.0)
   1217         self.CheckIfOversize()
   1218         if self.isSubmenu or not self.GetMySubmenus():
   1219             self.height = self.GetCollapsedHeight()
   1220             animations.FadeIn(self.mainParent, duration=0.05)
   1221             uicore.effect.MorphUIMassSpringDamper(self, 'height', self.GetExpandedHeight(), newthread=True, float=False, frequency=15.0, dampRatio=0.75)
   1222             self.Show()
   1223         else:
   1224             mySubs = self.GetMySubmenus()
   1225             menuState = settings.user.ui.Get('assetMenuState', {ccConst.BODYGROUP: True})
   1226             for subMenu in mySubs:
   1227                 key = subMenu.modifier or 'group_%s' % getattr(subMenu, 'groupID', '')
   1228                 if menuState.get(key, False):
   1229                     subMenu.Expand(True)
   1230                 else:
   1231                     subMenu.height = 0
   1232                     subMenu.Show()
   1233                     uicore.effect.MorphUIMassSpringDamper(subMenu, 'height', subMenu.GetCollapsedHeight(), newthread=True, float=False, frequency=15.0, dampRatio=0.75)
   1234 
   1235         self.CheckIfOversize()
   1236         if self.modifier in ccConst.COLORMAPPING or self.modifier in ccConst.TUCKMAPPING:
   1237             uthread.new(self.ExpandColorPalette)
   1238         self.UpdateControls('Expand', setFocusOnActive=True)
   1239         self.UpdatePrefs(True)
   1240         self.expanderIcon.LoadIcon([ccConst.ICON_EXPANDED, ccConst.ICON_EXPANDEDSINGLE][self.isSubmenu])
   1241 
   1242     def ExpandColorPalette(self, initing = False, *args):
   1243         blue.pyos.synchro.SleepWallclock(500)
   1244         if hasattr(self, 'sr'):
   1245             self.CreateColorPallette()
   1246         if self.browser and self.IsExpanded():
   1247             info = uicore.layer.charactercreation.controller.GetInfo()
   1248             activeMod = sm.GetService('character').GetModifierByCategory(info.charID, self.modifier)
   1249             if activeMod and (uicore.uilib.mouseOver is self or uicore.uilib.mouseOver.IsUnder(self)):
   1250                 self.colorPalette.ExpandPalette()
   1251 
   1252     def CreateColorPallette(self, isLights = False, *args):
   1253         if self.colorPalette is None:
   1254             maxPaletteWidth = int(uicore.desktop.width / 8)
   1255             if isLights:
   1256                 browseFunction = self.BrowseLightColors
   1257             else:
   1258                 browseFunction = self.OnTuckBrowse
   1259             self.colorPalette = CCColorPalette(name='CCColorPalette', parent=self.colorPaletteParent, align=uiconst.TOPRIGHT, pos=(0,
   1260              self.GetCollapsedHeight(),
   1261              CCColorPalette.COLORPALETTEWIDTH,
   1262              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)
   1263 
   1264     def CheckIfOversize(self, *args):
   1265         self.parent.parent.CheckIfOversize(currentPicker=self)
   1266 
   1267     def GetCollapsedHeight(self):
   1268         return self.captionParent.height
   1269 
   1270     def GetExpandedHeight(self):
   1271         return self.FULLHEIGHT
   1272 
   1273     def Collapse(self):
   1274         self._expanded = False
   1275         self.CollapseColorPalette()
   1276         if self._expanded:
   1277             return
   1278         animations.FadeOut(self.mainParent, duration=0.15)
   1279         if self.isSubmenu or not self.GetMySubmenus():
   1280             uicore.effect.MorphUIMassSpringDamper(self, 'height', self.captionParent.height, newthread=1, float=False, frequency=15.0, dampRatio=1.0)
   1281         else:
   1282             mySubs = self.GetMySubmenus()
   1283             hideHeight = 0
   1284             for subMenu in mySubs:
   1285                 if subMenu.IsExpanded():
   1286                     subMenu.Collapse()
   1287 
   1288             for subMenu in mySubs:
   1289                 subMenu.Hide()
   1290 
   1291         self.expanderIcon.LoadIcon([ccConst.ICON_COLLAPSED, ccConst.ICON_COLLAPSEDSINGLE][self.isSubmenu])
   1292         if uicore.uilib.mouseOver is not self.captionParent:
   1293             self.OnCaptionExit()
   1294         self.UpdatePrefs(False)
   1295 
   1296     def CollapseColorPalette(self, *args):
   1297         if self.colorPalette:
   1298             self.colorPalette.CollapsePalette(push=True)
   1299 
   1300     def GetMySubmenus(self):
   1301         ret = []
   1302         if self.isSubmenu:
   1303             return []
   1304         for each in self.parent.children:
   1305             if not hasattr(each, 'groupID'):
   1306                 continue
   1307             if each is not self and each.groupID == self.groupID and getattr(each, 'isSubmenu', False):
   1308                 ret.append(each)
   1309 
   1310         return ret
   1311 
   1312     def GetCurrentModifierValue(self, modifierPath):
   1313         info = uicore.layer.charactercreation.controller.GetInfo()
   1314         modifier = sm.GetService('character').GetModifiersByCategory(info.charID, modifierPath)
   1315         if modifier:
   1316             return modifier[0].weight
   1317         return 0.0
   1318 
   1319     def OnStylePicked(self, assetData, *args):
   1320         if assetData:
   1321             info = uicore.layer.charactercreation.controller.GetInfo()
   1322             thumb, itemType, hiliteResPath = assetData
   1323             weight = 1.0
   1324             if self.colorIntensitySlider:
   1325                 weight = self.colorIntensitySlider.GetValue()
   1326             uicore.layer.charactercreation.controller.SetItemType(itemType, weight=weight)
   1327             uthread.new(self.UpdateControls, 'OnStylePicked')
   1328 
   1329     def OnSkinTypePicked(self, itemType, *args):
   1330         if itemType:
   1331             info = uicore.layer.charactercreation.controller.GetInfo()
   1332             uicore.layer.charactercreation.controller.ClearCategory(ccConst.skintone, doUpdate=False)
   1333             sm.GetService('character').characterMetadata[info.charID].typeColors.pop(ccConst.skintone, None)
   1334             uicore.layer.charactercreation.controller.SetItemType(itemType)
   1335             uthread.new(self.UpdateControls, 'OnSkinTypePicked')
   1336 
   1337     def LoadRemoveOptions(self, *args):
   1338         if self.modifier == ccConst.hair:
   1339             return self.LoadRemoveHairOptions()
   1340         if not self.browser or not self.IsExpanded() or self.state == uiconst.UI_HIDDEN or self.modifier not in ccConst.REMOVEABLE:
   1341             return
   1342         self.SetRemoveIcon(self.modifier, self.removeParent)
   1343 
   1344     def SetRemoveIcon(self, modifier, icon):
   1345         info = uicore.layer.charactercreation.controller.GetInfo()
   1346         currentModifier = sm.GetService('character').GetModifierByCategory(info.charID, modifier)
   1347         if not currentModifier or getattr(currentModifier, 'name', None) in ccConst.invisibleModifiers:
   1348             if icon:
   1349                 icon.Hide()
   1350         elif icon:
   1351             icon.Show()
   1352 
   1353     def LoadRemoveHairOptions(self, *args):
   1354         if not self.IsExpanded() or self.state == uiconst.UI_HIDDEN:
   1355             return
   1356         if self.altbrowser:
   1357             self.SetRemoveIcon(ccConst.eyebrows, self.altbrowser.removeParent)
   1358         if self.beardbrowser:
   1359             self.SetRemoveIcon(ccConst.beard, self.beardbrowser.removeParent)
   1360 
   1361     def LoadTuckOptions(self, *args):
   1362         if not self.browser or not self.IsExpanded() or self.state == uiconst.UI_HIDDEN or self.modifier not in ccConst.TUCKMAPPING:
   1363             if getattr(self, 'pickerType', None) == 'lights' and uicore.layer.charactercreation.controller.IsSlowMachine():
   1364                 self.colorPalette.tuckParent.display = False
   1365             return
   1366         if self.colorPalette is None:
   1367             self.CreateColorPallette()
   1368         if self.colorPalette is None:
   1369             return
   1370         info = uicore.layer.charactercreation.controller.GetInfo()
   1371         currentModifier = sm.GetService('character').GetModifierByCategory(info.charID, self.modifier)
   1372         activeData = None
   1373         if self.browser and self.IsExpanded():
   1374             activeData = self.browser.GetActiveData()
   1375         hideTuck = True
   1376         if activeData and currentModifier:
   1377             tuckPath, requiredModifiers, subKey = ccConst.TUCKMAPPING[self.modifier]
   1378             if requiredModifiers:
   1379                 haveRequired = False
   1380                 for each in requiredModifiers:
   1381                     haveRequired = bool(sm.GetService('character').GetModifierByCategory(info.charID, each))
   1382                     if haveRequired:
   1383                         break
   1384 
   1385             else:
   1386                 haveRequired = True
   1387             resPath, itemType, hiliteResPath = activeData
   1388             if haveRequired:
   1389                 tuckModifier = sm.GetService('character').GetModifierByCategory(info.charID, tuckPath)
   1390                 if tuckModifier:
   1391                     tuckVariations = tuckModifier.GetVariations()
   1392                     if tuckVariations:
   1393                         currentTuckVariation = tuckModifier.currentVariation
   1394                         tuckStyle = tuckModifier.GetResPath().split('/')[-1]
   1395                         if currentTuckVariation in tuckVariations:
   1396                             tuckIndex = tuckVariations.index(currentTuckVariation)
   1397                         else:
   1398                             tuckIndex = 0
   1399                         tuckParent = self.colorPalette.tuckParent
   1400                         tuckParent.tuckOptions = tuckVariations
   1401                         tuckParent.tuckIndex = tuckIndex
   1402                         tuckParent.tuckPath = tuckPath
   1403                         tuckParent.tuckStyle = tuckStyle
   1404                         tuckParent.tuckResPath = tuckModifier.GetResPath()
   1405                         self.colorPalette.SetTuckingCounter(tuckIndex + 1, len(tuckVariations))
   1406                         hideTuck = False
   1407         if hideTuck:
   1408             if self.colorPalette.tuckParent.display == True:
   1409                 self.colorPalette.tuckParent.display = False
   1410                 animations.FadeOut(self.colorPalette.tuckParent, duration=0.125)
   1411         else:
   1412             self.colorPalette.tuckParent.display = True
   1413             animations.FadeIn(self.colorPalette.tuckParent, duration=0.125)
   1414 
   1415     def OnColorPickedFromWheel(self, colorPicker, color, name):
   1416         uicore.layer.charactercreation.controller.SetColorValue(colorPicker.modifier, (name, tuple(color)))
   1417 
   1418 
   1419 class CharCreationMenuToggler(Container):
   1420     __notifyevents__ = ['OnColorPaletteChanged']
   1421     FULLHEIGHT = 22
   1422     COLLAPSEHEIGHT = 22
   1423     default_align = uiconst.TOTOP
   1424     default_left = 0
   1425     default_top = 0
   1426     default_width = 0
   1427     default_height = COLLAPSEHEIGHT
   1428     default_pos = None
   1429     default_name = 'CharCreationMenuToggler'
   1430     default_state = uiconst.UI_PICKCHILDREN
   1431 
   1432     def ApplyAttributes(self, attributes):
   1433         for each in uicore.layer.main.children:
   1434             if each.name == self.default_name:
   1435                 each.Close()
   1436 
   1437         info = uicore.layer.charactercreation.controller.GetInfo()
   1438         Container.ApplyAttributes(self, attributes)
   1439         if attributes.parent is None:
   1440             uicore.layer.main.children.append(self)
   1441         self.colorPaletteParent = Container(parent=self, align=uiconst.TOLEFT, width=CCColorPalette.COLORPALETTEWIDTH, name='colorPaletteParent', state=uiconst.UI_DISABLED)
   1442         self.captionParent = Container(parent=self, align=uiconst.TOTOP, height=self.COLLAPSEHEIGHT, name='captionParent', state=uiconst.UI_NORMAL)
   1443         self.func = attributes.func
   1444         self.captionParent.OnClick = self.Toggle
   1445         self.captionParent.OnMouseEnter = self.OnCaptionEnter
   1446         self.captionParent.OnMouseExit = self.OnCaptionExit
   1447         self.menuType = attributes.menuType
   1448         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)
   1449         if self.menuType != 'tattooMenu':
   1450             self.caption.SetAlpha(0.5)
   1451         self.keepColor = 0
   1452         self.AddRadioButton()
   1453         Fill(parent=self.captionParent, color=(0.4, 0.4, 0.4, 0.5))
   1454         self.bevel = bevel = Frame(parent=self.captionParent, color=(1.0, 1.0, 1.0, 0.2), frameConst=ccConst.FILL_BEVEL, state=uiconst.UI_HIDDEN)
   1455         frame = Frame(parent=self.captionParent, frameConst=ccConst.FRAME_SOFTSHADE, color=(1.0, 1.0, 1.0, 0.5))
   1456         frame.padding = (-12, -5, -12, -15)
   1457         self.height = self.captionParent.height
   1458         sm.RegisterNotify(self)
   1459 
   1460     def AddRadioButton(self, *args):
   1461         self.shadowIcon = Sprite(parent=self.captionParent, name='shadowIcon', align=uiconst.CENTERRIGHT, state=uiconst.UI_DISABLED, pos=(0, 0, 32, 32), texturePath='res:/UI/Texture/CharacterCreation/radiobuttonShadow.dds', color=(0.4, 0.4, 0.4, 0.6))
   1462         self.backIcon = Sprite(parent=self.captionParent, name='backIcon', align=uiconst.CENTERRIGHT, state=uiconst.UI_DISABLED, pos=(0, 0, 32, 32), texturePath='res:/UI/Texture/CharacterCreation/radiobuttonBack.dds')
   1463         self.radioBtnFill = Container(parent=self.captionParent, state=uiconst.UI_HIDDEN, align=uiconst.CENTERRIGHT, pos=(0, 0, 32, 32), idx=0)
   1464         self.radioBtnHilite = Sprite(parent=self.radioBtnFill, name='radioBtnHilite', align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, pos=(0, 0, 32, 32), texturePath='res:/UI/Texture/CharacterCreation/radiobuttonWhite.dds')
   1465         self.radioBtnColor = Sprite(parent=self.radioBtnFill, name='radioBtnColor', align=uiconst.TOPLEFT, state=uiconst.UI_DISABLED, pos=(0, 0, 32, 32), texturePath='res:/UI/Texture/CharacterCreation/radiobuttonColor.dds')
   1466         if self.menuType == 'tattooMenu':
   1467             self.SetRadioBtnColor(color='green')
   1468 
   1469     def OnCaptionEnter(self, *args):
   1470         uicore.layer.charactercreation.controller.SetHintText(None, localization.GetByLabel('UI/Login/CharacterCreation/AssetMenu/BodyModHelp'))
   1471         sm.StartService('audio').SendUIEvent(unicode('ui_icc_menu_mouse_over_play'))
   1472         if not self.keepColor:
   1473             self.caption.SetAlpha(1.0)
   1474             if self.menuType == 'tattooMenu':
   1475                 self.SetRadioBtnColor(color='red')
   1476             elif self.menuType == 'assetMenu':
   1477                 self.SetRadioBtnColor(color='green')
   1478         if self.bevel:
   1479             self.bevel.state = uiconst.UI_DISABLED
   1480 
   1481     def OnCaptionExit(self, *args):
   1482         uicore.layer.charactercreation.controller.SetHintText(None)
   1483         if self.menuType != 'tattooMenu':
   1484             self.caption.SetAlpha(0.5)
   1485         if not self.keepColor:
   1486             if self.menuType == 'tattooMenu':
   1487                 self.SetRadioBtnColor(color='green')
   1488             else:
   1489                 self.radioBtnFill.state = uiconst.UI_HIDDEN
   1490             if self.bevel:
   1491                 self.bevel.state = uiconst.UI_HIDDEN
   1492 
   1493     def Toggle(self, *args):
   1494         sm.StartService('audio').SendUIEvent(unicode('ui_icc_button_mouse_down_play'))
   1495         self.keepColor = 1
   1496         if self.func:
   1497             self.func()
   1498             self.ResetRadioButton()
   1499 
   1500     def ResetRadioButton(self, *args):
   1501         self.keepColor = 0
   1502         if self.menuType != 'tattooMenu':
   1503             self.caption.SetAlpha(0.5)
   1504         if self.menuType == 'tattooMenu':
   1505             self.SetRadioBtnColor(color='green')
   1506         else:
   1507             self.radioBtnFill.state = uiconst.UI_HIDDEN
   1508 
   1509     def OnColorPaletteChanged(self, width):
   1510         self.colorPaletteParent.width = width
   1511 
   1512     def SetRadioBtnColor(self, color = 'green', *args):
   1513         if color == 'green':
   1514             self.radioBtnFill.state = uiconst.UI_DISABLED
   1515             self.radioBtnColor.SetRGB(0, 1, 0)
   1516             self.radioBtnHilite.SetAlpha(0.7)
   1517         elif color == 'red':
   1518             self.radioBtnFill.state = uiconst.UI_DISABLED
   1519             self.radioBtnColor.SetRGB(1, 0, 0)
   1520             self.radioBtnHilite.SetAlpha(0.3)