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

bloodLineStep.py (28251B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\login\charcreation\steps\bloodLineStep.py
      2 from carbonui import const as uiconst
      3 from carbonui.primitives.container import Container
      4 from carbonui.primitives.fill import Fill
      5 from carbonui.uicore import uicore
      6 from carbon.common.lib.const import genderFemale, genderMale
      7 from characterdata.bloodlines import get_bloodline_ids_by_race_id
      8 from charactercreator import const as ccConst
      9 import charactercreator.client.scalingUtils as ccScalingUtils
     10 from carbonui.fontconst import STYLE_HEADER
     11 from eve.client.script.ui.login.charcreation.charCreation import BaseCharacterCreationStep
     12 from eve.client.script.ui.login.charcreation.charCreationButtons import GenderButton
     13 from eve.client.script.ui.login.charcreation.empireui.backButton import BackButton
     14 from eve.client.script.ui.login.charcreation.empireui.bloodlineBox import BloodlineBox
     15 from eve.client.script.ui.login.charcreation.empireui.bloodlineInfo import BloodlineInfoContainer, GetBloodlineInfoContainerWidth, GetBloodlineInfoContainerHeight
     16 from eve.client.script.ui.login.charcreation.empireui.empireThemedButtons import GetSealHeight, EmpireThemedButton, EmpireThemedDecoration, EmpireThemedButtonState, GetEmpireThemedDecorationSize, BUTTON_TEXT_FONTSIZE_MIN_RES
     17 from eve.client.script.ui.login.charcreation.label import CCLabel
     18 from eve.client.script.ui.login.charcreation.technologyViewUtils import LineDecoration, TECH_NAV_ARROW_SIZE
     19 from eve.client.script.ui.util.uix import GetTextWidth, GetTextHeight
     20 from eve.common.lib import appConst
     21 import localization
     22 import uthread
     23 BACK_BUTTON_WIDTH = 107
     24 BACK_BUTTON_HEIGHT = 36
     25 NEXT_STEP_BUTTON_TOP = 10
     26 NEXT_STEP_BUTTON_TEXT = 'UI/CharacterCreation/CustomizeAppearance'
     27 NEXT_STEP_BUTTON_MIN_TEXT_PADDING = 10
     28 CUSTOMIZE_MOUSEOVER_SOUND = 'ui_es_mouse_over_customize_appearance_play'
     29 CUSTOMIZE_MOUSEEXIT_SOUND = 'ui_es_mouse_over_customize_appearance_stop'
     30 CUSTOMIZE_FLARE_SOUND_INTRO = 'ui_es_customize_appearance_flare_play'
     31 CUSTOMIZE_FLARE_SOUND_OUTRO = 'ui_es_customize_appearance_flare_stop'
     32 BUTTON_SELECT_SOUND = 'ui_icc_button_select_play'
     33 BLOODLINES_HEADER_LABEL = 'UI/CharacterCreation/BloodlineSelection'
     34 BLOODLINE_NOTE_LABEL = 'UI/Login/CharacterCreation/BloodlineSelection/BloodlinesArePurelyAesthetic'
     35 BLOODLINES_INFO_TOP = 11
     36 GENDER_BUTTON_MARGIN = 4
     37 GENDER_BUTTON_SIZE = 23
     38 GENDER_LINE_WIDTH = 1
     39 GENDER_LINE_HEIGHT = 14
     40 BOUNDING_BOX_WIDTH = 105
     41 BOUNDING_BOX_HEIGHT = 325
     42 BOUNDING_BOX_SEPARATION = 50
     43 DISCLAIMER_CONTAINER_TOP = -25
     44 BLOODLINES_NOTE_TOP = 18
     45 BLOODLINES_TEXT_WIDTH = 400
     46 BLOODLINES_NOTE_TEXT_HEIGHT = 28
     47 BLOODLINES_NOTE_BOTTOM = 78
     48 BLOODLINES_NOTE_WIDTH = 580
     49 BLOODLINES_NOTE_FONTSIZE = 11
     50 BLOODLINES_NOTE_BUTTON_TO_TEXT_MARGIN = 14
     51 BLOODLINES_NOTE_LINE_HEIGHT = 4
     52 BLOODLINES_NOTE_LINE_DECO_WIDTH = 41
     53 HOVER_SOUND_EVENTS = {appConst.bloodlineAmarr: 'ui_es_bloodline_mouse_over_amarr_play',
     54  appConst.bloodlineKhanid: 'ui_es_bloodline_mouse_over_khanid_play',
     55  appConst.bloodlineNiKunni: 'ui_es_bloodline_mouse_over_nikunni_play',
     56  appConst.bloodlineGallente: 'ui_es_bloodline_mouse_over_gallente_play',
     57  appConst.bloodlineIntaki: 'ui_es_bloodline_mouse_over_intaki_play',
     58  appConst.bloodlineJinMei: 'ui_es_bloodline_mouse_over_jinmei_play',
     59  appConst.bloodlineDeteis: 'ui_es_bloodline_mouse_over_deteis_play',
     60  appConst.bloodlineAchura: 'ui_es_bloodline_mouse_over_achura_play',
     61  appConst.bloodlineCivire: 'ui_es_bloodline_mouse_over_civire_play',
     62  appConst.bloodlineSebiestor: 'ui_es_bloodline_mouse_over_sebiestor_play',
     63  appConst.bloodlineVherokior: 'ui_es_bloodline_mouse_over_vherokior_play',
     64  appConst.bloodlineBrutor: 'ui_es_bloodline_mouse_over_brutor_play'}
     65 
     66 class BloodlineStep(BaseCharacterCreationStep):
     67     __guid__ = 'uicls.BloodlineStep'
     68     stepID = ccConst.BLOODLINESTEP
     69     __notifyevents__ = ['OnSetDevice']
     70 
     71     def ApplyAttributes(self, attributes):
     72         self.isReady = False
     73         self.audioSvc = sm.GetService('audio')
     74         self.useVideos = attributes.Get('useVideos', True)
     75         BaseCharacterCreationStep.ApplyAttributes(self, attributes)
     76         self.buttonContainer = attributes.buttonContainer
     77         self.bloodlineIDs = []
     78         self.bloodlineBtns = []
     79         info = self.GetInfo()
     80         self.raceID = info.raceID
     81         self.bloodlineID = info.bloodlineID
     82         self.genderID = info.genderID
     83         self.hoveredBloodlineID = None
     84         self.hoveredGenderID = None
     85         self.lastBloodlineID = None
     86         self.lastGenderID = None
     87         self.lastHoveredBloodlineID = None
     88         self.lastHoveredGenderID = None
     89         self.backButtonContainer = None
     90         self.nextStepButton = None
     91         self.nextStepButtonDecoration = None
     92         self.containersByBloodline = {}
     93         self.genderContainerParentsByBloodline = {}
     94         self.genderContainerParentsCenteredByBloodline = {}
     95         self.genderContainersByBloodline = {}
     96         self.bloodlineButtonsByBloodline = {}
     97         self.genderLinesByBloodline = {}
     98         self.buttonsByBloodlineAndGender = {}
     99         self.boundingBoxesByBloodline = {}
    100         self.boundingBoxesWrappersByBloodline = {}
    101         self.tooltipsByBloodline = {}
    102         self.tooltipLock = uthread.Semaphore()
    103         for bloodlineID in get_bloodline_ids_by_race_id(self.raceID, shuffle=True):
    104             self.buttonsByBloodlineAndGender[bloodlineID] = {}
    105             self.bloodlineIDs.append(bloodlineID)
    106 
    107         self.bloodCont = Container(name='bloodCont', parent=self, align=uiconst.CENTER, width=uicore.desktop.width, height=ccScalingUtils.GetMainPanelHeight(), state=uiconst.UI_PICKCHILDREN)
    108         self.ConstructBloodlineBanner()
    109         self.ConstructBloodlineInfo()
    110         self.ConstructBoundingBoxes()
    111         self.ConstructGenderButtons()
    112         self.ConstructBloodlineNote()
    113         self.UpdateNextButton()
    114         sm.RegisterNotify(self)
    115         self.isReady = True
    116 
    117     def ConstructBloodlineBanner(self):
    118         top = ccScalingUtils.GetBannerHeaderHeight()
    119         width = ccScalingUtils.GetMainPanelWidth()
    120         height = ccScalingUtils.GetMainPanelHeight() - top
    121         self.bloodlineBanner = Container(name='bloodlineBanner', parent=self.bloodCont, align=uiconst.CENTERTOP, width=width, height=height, top=top, state=uiconst.UI_PICKCHILDREN)
    122         self.parent.SetTitle(localization.GetByLabel(BLOODLINES_HEADER_LABEL))
    123 
    124     def ConstructBloodlineInfo(self):
    125         bloodlineTextHeight = GetBloodlineInfoContainerHeight()
    126         bloodlineTextTop = BLOODLINES_INFO_TOP * ccScalingUtils.GetScaleFactor()
    127         self.bloodlineInfoCont = BloodlineInfoContainer(name='bloodlineInfoCont', parent=self.bloodlineBanner, align=uiconst.TOTOP, height=bloodlineTextHeight, raceID=self.raceID, bloodlineIDs=self.bloodlineIDs, selectedBloodlineID=self.bloodlineID, top=bloodlineTextTop, state=uiconst.UI_HIDDEN)
    128 
    129     def ConstructGenderButtons(self):
    130         scaleFactor = ccScalingUtils.GetScaleFactor()
    131         bloodlineContainerWidth = GetBloodlineInfoContainerWidth()
    132         genderButtonSize = GENDER_BUTTON_SIZE * scaleFactor
    133         genderMargin = GENDER_BUTTON_MARGIN * scaleFactor
    134         genderLineHeight = GENDER_LINE_HEIGHT * scaleFactor
    135         containerSizeDifference = ccScalingUtils.GetMainPanelWidth() - bloodlineContainerWidth
    136         for bloodlineID in self.bloodlineIDs:
    137             firstBloodlineBox = self.boundingBoxesByBloodline[bloodlineID][genderFemale]
    138             left = firstBloodlineBox.left + firstBloodlineBox.width
    139             self.bloodlineInfoCont.AlignButtonIcons(bloodlineID, left)
    140             genderBtnContainerLeft = left - genderButtonSize - genderMargin - containerSizeDifference / 2
    141             genderContainerParent = Container(name='genderContainerParent', parent=self.bloodlineBanner, align=uiconst.TOTOP_NOPUSH, width=bloodlineContainerWidth, height=genderButtonSize, state=uiconst.UI_HIDDEN)
    142             self.genderContainerParentsByBloodline[bloodlineID] = genderContainerParent
    143             genderContainerParentCentered = Container(name='genderContainerParentCentered', parent=genderContainerParent, align=uiconst.CENTER, width=bloodlineContainerWidth, height=genderButtonSize)
    144             self.genderContainerParentsCenteredByBloodline[bloodlineID] = genderContainerParentCentered
    145             contGender = Container(name='genderContainer_%d' % bloodlineID, parent=genderContainerParentCentered, align=uiconst.TOLEFT, width=genderButtonSize * 2 + 2 * genderMargin, height=genderButtonSize, left=genderBtnContainerLeft)
    146             self.genderContainersByBloodline[bloodlineID] = contGender
    147             genderBtnFemale = GenderButton(name='GenderButton_F', parent=contGender, align=uiconst.BOTTOMLEFT, width=genderButtonSize, height=genderButtonSize, spriteWidth=genderButtonSize, spriteHeight=genderButtonSize, genderID=genderFemale, raceID=self.raceID, state=uiconst.UI_HIDDEN)
    148             self.buttonsByBloodlineAndGender[bloodlineID][genderFemale] = genderBtnFemale
    149             genderLine = Fill(name='genderLine_Bloodline%d' % bloodlineID, parent=contGender, color=(1.0, 1.0, 1.0, 0.25), align=uiconst.CENTERLEFT, width=GENDER_LINE_WIDTH, height=genderLineHeight, left=genderButtonSize + genderMargin, state=uiconst.UI_HIDDEN)
    150             self.genderLinesByBloodline[bloodlineID] = genderLine
    151             genderBtnMale = GenderButton(name='GenderButton_M', parent=contGender, align=uiconst.BOTTOMRIGHT, width=genderButtonSize, height=genderButtonSize, spriteWidth=genderButtonSize, spriteHeight=genderButtonSize, genderID=genderMale, raceID=self.raceID, state=uiconst.UI_HIDDEN)
    152             self.buttonsByBloodlineAndGender[bloodlineID][genderMale] = genderBtnMale
    153             if self.bloodlineID and self.bloodlineID == bloodlineID:
    154                 canChangeGender = uicore.layer.charactercreation.controller.CanChangeGender()
    155                 selectedGenderID = self.genderID
    156                 if selectedGenderID is not None and canChangeGender:
    157                     self.buttonsByBloodlineAndGender[bloodlineID][selectedGenderID].Show()
    158                     self.buttonsByBloodlineAndGender[bloodlineID][selectedGenderID].Select()
    159                     deselectedGenderID = not selectedGenderID
    160                     self.buttonsByBloodlineAndGender[bloodlineID][deselectedGenderID].Hide()
    161 
    162     def ConstructBoundingBoxes(self):
    163         scaleFactor = ccScalingUtils.GetScaleFactor()
    164         genderContainerHeight = GENDER_BUTTON_SIZE * scaleFactor
    165         boundingBoxWidth = BOUNDING_BOX_WIDTH * scaleFactor
    166         boundingBoxHeight = BOUNDING_BOX_HEIGHT * scaleFactor
    167         boundingBoxSeparation = BOUNDING_BOX_SEPARATION * scaleFactor
    168         left = (self.bloodlineBanner.width - 6 * boundingBoxWidth - 3 * boundingBoxSeparation) / 2
    169         isAnySelected = self.bloodlineID is not None and self.genderID is not None
    170         for bloodlineID in self.bloodlineIDs:
    171             boundingBoxWrapper = Container(name='boundingBoxWrapper_Bloodline%s' % bloodlineID, parent=self.bloodlineBanner, align=uiconst.TOTOP_NOPUSH, width=2 * boundingBoxWidth, height=boundingBoxHeight, top=genderContainerHeight, state=uiconst.UI_PICKCHILDREN, opacity=False)
    172             self.boundingBoxesWrappersByBloodline[bloodlineID] = boundingBoxWrapper
    173             self.boundingBoxesByBloodline[bloodlineID] = {}
    174             for gender in [genderFemale, genderMale]:
    175                 isThisBoxSelected = bloodlineID == self.bloodlineID and gender == self.genderID
    176                 showSelectedOnLoad = isThisBoxSelected or not isAnySelected
    177                 boundingBox = BloodlineBox(name='boundingBox_Bloodline%s_Gender%s' % (bloodlineID, gender), parent=boundingBoxWrapper, align=uiconst.TOLEFT, state=uiconst.UI_NORMAL, width=boundingBoxWidth + boundingBoxSeparation / 2, height=boundingBoxHeight, left=left if gender == genderFemale else 0, race=self.raceID, bloodlineID=bloodlineID, gender=gender, isSelected=isThisBoxSelected, onSelection=self.OnBoundingBoxSelection, onHover=self.OnBoundingBoxHover, onDehover=self.OnBoundingBoxDehover, useVideos=self.useVideos, showSelectedOnLoad=showSelectedOnLoad, resAlign=uiconst.TORIGHT_NOPUSH if gender == genderFemale else uiconst.TOLEFT_NOPUSH)
    178                 self.boundingBoxesByBloodline[bloodlineID][gender] = boundingBox
    179 
    180             left = left + 2 * boundingBoxWidth + boundingBoxSeparation
    181 
    182     def ConstructBloodlineNote(self):
    183         noteSizeParameters = self._CalculateNoteSizeParameters()
    184         self.noteContainer = Container(name='noteContainer', parent=self.bloodlineBanner, align=uiconst.CENTERBOTTOM, width=noteSizeParameters['noteWidth'], height=noteSizeParameters['noteHeight'], state=uiconst.UI_HIDDEN, top=DISCLAIMER_CONTAINER_TOP)
    185         self.noteContentContainer = Container(name='noteContentContainer', parent=self.noteContainer, align=uiconst.CENTERTOP, width=noteSizeParameters['noteContentWidth'], height=noteSizeParameters['noteHeight'] - noteSizeParameters['topMargin'], state=uiconst.UI_NORMAL, top=noteSizeParameters['topMargin'])
    186         if not uicore.layer.charactercreation.controller._IsUserInSkipTechnologyStepCohort():
    187             self.ConstructBackButton()
    188         self.disclaimerContainer = Container(name='disclaimerContainer', parent=self.noteContentContainer, align=uiconst.TORIGHT, width=noteSizeParameters['textWidth'], state=uiconst.UI_NORMAL)
    189         self.disclaimerText = CCLabel(name='disclaimerText', parent=self.disclaimerContainer, fontsize=noteSizeParameters['noteTextFontsize'], align=uiconst.TOALL, text=localization.GetByLabel(BLOODLINE_NOTE_LABEL), letterspace=0, top=0, bold=0, fontStyle=STYLE_HEADER)
    190         self.line = LineDecoration(name='noteLine', parent=self.noteContainer, align=uiconst.TOTOP_NOPUSH, width=noteSizeParameters['noteWidth'], height=BLOODLINES_NOTE_LINE_HEIGHT, lineWidth=noteSizeParameters['noteWidth'], lineDecorationWidth=noteSizeParameters['lineDecoWidth'], invert=False)
    191 
    192     def ConstructBackButton(self):
    193         if self.backButtonContainer and not self.backButtonContainer.destroyed:
    194             self.backButtonContainer.Close()
    195         backButtonWidth = BACK_BUTTON_WIDTH * ccScalingUtils.GetScaleFactor()
    196         backButtonHeight = BACK_BUTTON_HEIGHT * ccScalingUtils.GetScaleFactor()
    197         self.backButtonContainer = Container(name='backButtonContainer', parent=self.noteContentContainer, align=uiconst.TOLEFT, width=backButtonWidth, state=uiconst.UI_NORMAL)
    198         backButtonWrapper = Container(name='backButtonWrapper', parent=self.backButtonContainer, align=uiconst.TOTOP, width=backButtonWidth, height=backButtonHeight)
    199         BackButton(name='backButton', parent=backButtonWrapper, align=uiconst.CENTER, width=backButtonWidth, height=backButtonHeight, raceID=self.raceID, iconSize=TECH_NAV_ARROW_SIZE * ccScalingUtils.GetScaleFactor())
    200 
    201     def ShouldReactToMouseEvents(self):
    202         return self.isReady
    203 
    204     def OnBoundingBoxSelection(self, selectedBloodlineID, selectedGender):
    205         if not self.ShouldReactToMouseEvents():
    206             return
    207         for bloodlineID in self.bloodlineIDs:
    208             for gender in [genderFemale, genderMale]:
    209                 boundingBox = self.boundingBoxesByBloodline[bloodlineID][gender]
    210                 if bloodlineID == selectedBloodlineID and gender == selectedGender:
    211                     boundingBox.Select()
    212                 else:
    213                     boundingBox.Deselect()
    214 
    215         uthread.new(self.SelectBloodlineAndGender, selectedBloodlineID, selectedGender)
    216 
    217     def OnBoundingBoxHover(self, hoveredBloodlineID, hoveredGender):
    218         if not self.ShouldReactToMouseEvents():
    219             return
    220         for bloodlineID in self.bloodlineIDs:
    221             for gender in [genderFemale, genderMale]:
    222                 boundingBox = self.boundingBoxesByBloodline[bloodlineID][gender]
    223                 isThisSelected = self.bloodlineID == bloodlineID and self.genderID == gender
    224                 if not isThisSelected:
    225                     isThisHovered = bloodlineID == hoveredBloodlineID and gender == hoveredGender
    226                     if isThisHovered:
    227                         boundingBox.ShowHover()
    228                     else:
    229                         boundingBox.ShowDehover()
    230 
    231         self.hoveredBloodlineID = hoveredBloodlineID
    232         self.bloodlineInfoCont.HoverBloodline(hoveredBloodlineID)
    233         if self.hoveredGenderID != hoveredGender:
    234             sound_event = HOVER_SOUND_EVENTS.get(self.hoveredBloodlineID, 'ui_es_bloodline_mouse_over_stop')
    235             self.audioSvc.SendUIEvent(sound_event)
    236         self.hoveredGenderID = hoveredGender
    237         self._UpdateGenderButtons()
    238 
    239     def OnBoundingBoxDehover(self, dehoveredBloodlineID, dehoveredGender):
    240         if not self.ShouldReactToMouseEvents():
    241             return
    242         isAnySelected = self.bloodlineID is not None and self.genderID is not None
    243         for bloodlineID in self.bloodlineIDs:
    244             for gender in [genderFemale, genderMale]:
    245                 boundingBox = self.boundingBoxesByBloodline[bloodlineID][gender]
    246                 if not isAnySelected:
    247                     boundingBox.ShowSelected()
    248                 else:
    249                     isThisSelected = self.bloodlineID == bloodlineID and self.genderID == gender
    250                     isThisDehovered = bloodlineID == dehoveredBloodlineID and gender == dehoveredGender
    251                     if not isThisSelected and isThisDehovered:
    252                         boundingBox.ShowDehover()
    253 
    254         if self.hoveredBloodlineID != None:
    255             self.audioSvc.SendUIEvent('ui_es_bloodline_mouse_over_stop')
    256         self.hoveredBloodlineID = None
    257         self.hoveredGenderID = None
    258         self.ResetBloodlineInfo()
    259         self._UpdateGenderButtons()
    260 
    261     def ResetBloodlineInfo(self):
    262         self.bloodlineInfoCont.ResetInfo()
    263         for bloodlineID in self.bloodlineIDs:
    264             firstBloodlineBox = self.boundingBoxesByBloodline[bloodlineID][genderFemale]
    265             left = firstBloodlineBox.left + firstBloodlineBox.width
    266             self.bloodlineInfoCont.AlignButtonIcons(bloodlineID, left)
    267 
    268     def SelectBloodlineAndGender(self, selectedBloodlineID, selectedGender):
    269         if selectedBloodlineID is None or selectedGender is None:
    270             return
    271         self.audioSvc.SendUIEvent('ui_es_bloodline_mouse_over_stop')
    272         shouldUpdateNextStepButton = self.bloodlineID is None
    273         uthread.new(uicore.layer.charactercreation.controller.SelectBloodlineAndGender, selectedBloodlineID, selectedGender)
    274         self.bloodlineID = selectedBloodlineID
    275         self.bloodlineInfoCont.SelectBloodline(selectedBloodlineID)
    276         self.audioSvc.SendUIEvent(BUTTON_SELECT_SOUND)
    277         self.genderID = selectedGender
    278         self._UpdateGenderButtons()
    279         if shouldUpdateNextStepButton:
    280             self.SetNextStepButtonDecoration()
    281             self.SetNextStepButton()
    282 
    283     def UpdateLayout(self):
    284         bloodContWidth = uicore.desktop.width
    285         bloodContHeight = ccScalingUtils.GetMainPanelHeight()
    286         hasWidthChanged = self.bloodCont.width != bloodContWidth
    287         hasHeightChanged = self.bloodCont.height != bloodContHeight
    288         if self.isReady and (hasWidthChanged or hasHeightChanged):
    289             self.Reload()
    290 
    291     def UpdateNextButton(self):
    292         self.buttonContainer.Flush()
    293         self.SetNextStepButtonDecoration()
    294         self.SetNextStepButton()
    295 
    296     def _CalculateNoteSizeParameters(self):
    297         backButtonWidth = BACK_BUTTON_WIDTH * ccScalingUtils.GetScaleFactor()
    298         noteText = localization.GetByLabel(BLOODLINE_NOTE_LABEL)
    299         noteTextFontsize = BLOODLINES_NOTE_FONTSIZE * ccScalingUtils.GetScaleFactor()
    300         textWidth = BLOODLINES_TEXT_WIDTH * ccScalingUtils.GetScaleFactor()
    301         textHeight = GetTextHeight(strng=noteText, width=textWidth, fontsize=noteTextFontsize, hspace=0, uppercase=0)
    302         minTextHeight = BLOODLINES_NOTE_TEXT_HEIGHT * ccScalingUtils.GetScaleFactor()
    303         textHeight = max(minTextHeight, textHeight)
    304         topMargin = BLOODLINES_NOTE_TOP * ccScalingUtils.GetScaleFactor()
    305         bottomMargin = BLOODLINES_NOTE_BOTTOM * ccScalingUtils.GetScaleFactor()
    306         noteWidth = BLOODLINES_NOTE_WIDTH * ccScalingUtils.GetScaleFactor()
    307         noteHeight = topMargin + textHeight + bottomMargin
    308         noteButtonToTextMargin = BLOODLINES_NOTE_BUTTON_TO_TEXT_MARGIN * ccScalingUtils.GetScaleFactor()
    309         noteContentWidth = backButtonWidth + noteButtonToTextMargin + textWidth
    310         lineDecoWidth = BLOODLINES_NOTE_LINE_DECO_WIDTH * ccScalingUtils.GetScaleFactor()
    311         noteSizeParameters = {'noteWidth': noteWidth,
    312          'noteHeight': noteHeight,
    313          'noteContentWidth': noteContentWidth,
    314          'topMargin': topMargin,
    315          'backButtonWidth': backButtonWidth,
    316          'textWidth': textWidth,
    317          'noteButtonToTextMargin': noteButtonToTextMargin,
    318          'noteTextFontsize': noteTextFontsize,
    319          'lineDecoWidth': lineDecoWidth}
    320         return noteSizeParameters
    321 
    322     def GetBloodlinePos(self, bloodlineID):
    323         scaleFactor = ccScalingUtils.GetScaleFactor()
    324         firstBloodlineBox = self.boundingBoxesByBloodline[bloodlineID][genderFemale]
    325         left = firstBloodlineBox.left + firstBloodlineBox.width
    326         self.bloodlineInfoCont.AlignButtonIcons(bloodlineID, left)
    327         containerSizeDifference = ccScalingUtils.GetMainPanelWidth() - GetBloodlineInfoContainerWidth()
    328         genderIconSize = GENDER_BUTTON_SIZE * scaleFactor
    329         genderMargin = GENDER_BUTTON_MARGIN * scaleFactor
    330         genderBtnContainer = self.genderContainersByBloodline[bloodlineID]
    331         genderBtnContainer.left = left - genderIconSize - genderMargin - containerSizeDifference / 2
    332 
    333     def _ShouldUpdateGenderButtons(self):
    334         return self.isReady and self.buttonsByBloodlineAndGender and (self.lastBloodlineID != self.bloodlineID or self.lastGenderID != self.genderID or self.lastHoveredBloodlineID != self.hoveredBloodlineID or self.lastHoveredGenderID != self.hoveredGenderID)
    335 
    336     def _UpdateGenderButtons(self):
    337         if not self._ShouldUpdateGenderButtons():
    338             return
    339         for bloodlineID in self.bloodlineIDs:
    340             if bloodlineID not in (self.bloodlineID, self.hoveredBloodlineID):
    341                 self.buttonsByBloodlineAndGender[bloodlineID][genderFemale].Hide()
    342                 self.buttonsByBloodlineAndGender[bloodlineID][genderMale].Hide()
    343                 self.genderLinesByBloodline[bloodlineID].Hide()
    344 
    345         if self.bloodlineID is not None and self.genderID is not None:
    346             genderBtnFemale = self.buttonsByBloodlineAndGender[self.bloodlineID][genderFemale]
    347             genderBtnMale = self.buttonsByBloodlineAndGender[self.bloodlineID][genderMale]
    348             genderLine = self.genderLinesByBloodline[self.bloodlineID]
    349             if self.genderID == genderFemale:
    350                 genderBtnFemale.Select()
    351                 genderBtnMale.Hide()
    352             else:
    353                 genderBtnFemale.Hide()
    354                 genderBtnMale.Select()
    355             genderLine.Hide()
    356         if self.hoveredBloodlineID is not None and self.hoveredGenderID is not None:
    357             genderLine = self.genderLinesByBloodline[self.hoveredBloodlineID]
    358             if self.hoveredBloodlineID == self.bloodlineID:
    359                 deselectedGenderID = not self.genderID
    360                 deselectedGenderButton = self.buttonsByBloodlineAndGender[self.hoveredBloodlineID][deselectedGenderID]
    361                 if self.hoveredGenderID == self.genderID:
    362                     deselectedGenderButton.Hide()
    363                     genderLine.Hide()
    364                 else:
    365                     deselectedGenderButton.HoverInHighlighted()
    366                     genderLine.Show()
    367             else:
    368                 hoveredGenderID = self.hoveredGenderID
    369                 dehoveredGenderID = not self.hoveredGenderID
    370                 hoveredGenderButton = self.buttonsByBloodlineAndGender[self.hoveredBloodlineID][hoveredGenderID]
    371                 dehoveredGenderButton = self.buttonsByBloodlineAndGender[self.hoveredBloodlineID][dehoveredGenderID]
    372                 hoveredGenderButton.HoverInHighlighted()
    373                 dehoveredGenderButton.Show()
    374                 dehoveredGenderButton.Deselect()
    375                 genderLine.Show()
    376         self.lastBloodlineID = self.bloodlineID
    377         self.lastGenderID = self.genderID
    378         self.lastHoveredBloodlineID = self.hoveredBloodlineID
    379         self.lastHoveredGenderID = self.hoveredGenderID
    380 
    381     def OnRaceSelected(self, raceID, *args):
    382         if self.raceID != raceID:
    383             self.raceID = raceID
    384             self.Reload(updateRace=True)
    385 
    386     def OnSetDevice(self):
    387         self.UpdateLayout()
    388 
    389     def CreateCharacter(self):
    390         self.audioSvc.SendUIEvent('ui_es_button_mouse_down_create_character_play')
    391         uicore.layer.charactercreation.controller.Approve()
    392 
    393     def CalculateNextStepButtonState(self):
    394         if self.bloodlineID is not None:
    395             return EmpireThemedButtonState.NORMAL
    396         return EmpireThemedButtonState.DISABLED
    397 
    398     def SetNextStepButton(self):
    399         if self.nextStepButton and not self.nextStepButton.destroyed:
    400             self.nextStepButton.Close()
    401         nextStepButtonLabel = localization.GetByLabel(NEXT_STEP_BUTTON_TEXT)
    402         nextStepButtonLabelFontsize = BUTTON_TEXT_FONTSIZE_MIN_RES * ccScalingUtils.GetScaleFactor()
    403         nextStepButtonLabelWidth = GetTextWidth(strng=nextStepButtonLabel, fontsize=nextStepButtonLabelFontsize, hspace=0, uppercase=1)
    404         minWidth = nextStepButtonLabelWidth + 2 * NEXT_STEP_BUTTON_MIN_TEXT_PADDING
    405         nextStepButtonWidth = max(minWidth, ccScalingUtils.GetCustomizeCharacterButtonWidth())
    406         nextStepButtonHeight = ccScalingUtils.GetCustomizeCharacterButtonHeight()
    407         nextStepButtonTop = ccScalingUtils.GetBottomNavHeight() - nextStepButtonHeight - NEXT_STEP_BUTTON_TOP
    408         self.nextStepButton = EmpireThemedButton(name='NextStepButton', parent=self.buttonContainer, align=uiconst.CENTERBOTTOM, label=nextStepButtonLabel.upper(), raceID=self.raceID, width=nextStepButtonWidth, height=nextStepButtonHeight, top=nextStepButtonTop, buttonState=self.CalculateNextStepButtonState(), mouseOverSound=CUSTOMIZE_MOUSEOVER_SOUND, mouseExitSound=CUSTOMIZE_MOUSEEXIT_SOUND)
    409         self.nextStepButton.OnClick = self.CreateCharacter
    410 
    411     def SetNextStepButtonDecoration(self):
    412         if not self.nextStepButtonDecoration:
    413             width, height = GetEmpireThemedDecorationSize()
    414             nextStepButtonDecorationContainer = Container(name='NextStepButtonDecoration_Container', parent=self.buttonContainer, align=uiconst.TOTOP_NOPUSH, width=width, height=height, top=-GetSealHeight(), state=uiconst.UI_DISABLED)
    415             self.nextStepButtonDecoration = EmpireThemedDecoration(name='NextStepButtonDecoration', parent=nextStepButtonDecorationContainer, align=uiconst.CENTERTOP, width=width, height=height, flareSoundIntro=CUSTOMIZE_FLARE_SOUND_INTRO, flareSoundOutro=CUSTOMIZE_FLARE_SOUND_OUTRO)
    416         nextStepButtonState = self.CalculateNextStepButtonState()
    417         self.nextStepButtonDecoration.UpdateDecoration(self.raceID, nextStepButtonState)
    418 
    419     def ShowBloodlineInfo(self):
    420         self.bloodlineInfoCont.Show()
    421 
    422     def HideBloodlineInfo(self):
    423         self.bloodlineInfoCont.Hide()
    424 
    425     def ShowBoundingBoxes(self):
    426         for container in self.boundingBoxesWrappersByBloodline.values():
    427             container.opacity = 1.0
    428 
    429     def HideBoundingBoxes(self):
    430         for container in self.boundingBoxesWrappersByBloodline.values():
    431             container.opacity = 0.0
    432 
    433     def ShowGenders(self):
    434         for genderContainer in self.genderContainerParentsByBloodline.values():
    435             genderContainer.Show()
    436 
    437     def HideGenders(self):
    438         for genderContainer in self.genderContainerParentsByBloodline.values():
    439             genderContainer.Hide()
    440 
    441     def ShowNote(self):
    442         self.noteContainer.Show()
    443 
    444     def HideNote(self):
    445         self.noteContainer.Hide()
    446 
    447     def HideContent(self):
    448         self.HideBloodlineInfo()
    449         self.HideBoundingBoxes()
    450         self.HideGenders()
    451         self.HideNote()
    452 
    453     def Reload(self, updateRace = False):
    454         if not self.isReady:
    455             return
    456         self.isReady = False
    457         self.HideContent()
    458         uicore.layer.charactercreation.controller.ReloadBloodlineStep(updateRace=updateRace)