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

sofpreviewer.py (37790B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\eveclientqatools\sofpreviewer.py
      2 from __future__ import print_function
      3 import re
      4 import blue
      5 import carbonui.fontconst
      6 import carbonui.const as uiconst
      7 import evegraphics.utils as gfxutils
      8 import eveSpaceObject.spaceobjanimation as soanimation
      9 from carbonui.control.combo import Combo
     10 from carbonui.control.singlelineedits.singleLineEditFloat import SingleLineEditFloat
     11 from carbonui.control.singlelineedits.singleLineEditInteger import SingleLineEditInteger
     12 from carbonui.button.group import ButtonGroup
     13 from carbonui.control.checkbox import Checkbox
     14 from carbonui.control.singlelineedits.singleLineEditText import SingleLineEditText
     15 from carbonui.control.window import Window
     16 from carbonui.decorative.panelUnderlay import PanelUnderlay
     17 from eve.client.script.ui.shared.preview import PreviewContainer
     18 from carbonui.primitives.container import Container
     19 from carbonui.primitives.gridcontainer import GridContainer
     20 from carbonui.primitives.sprite import Sprite
     21 from carbonui.primitives.line import Line
     22 from eve.client.script.ui.control.eveLabel import EveLabelSmall
     23 from carbonui.control.scrollContainer import ScrollContainer
     24 from carbonui.control.slider import Slider
     25 import fsdBuiltData.common.graphicMaterialSets as graphicMaterialSets
     26 from shipskins.static import SkinMaterialStorage
     27 from sofDnaLibrary.query import GetDnaStringsMatchingQuery
     28 MAX_MULTI_HULLS = 4
     29 MULTI_HULL_REGEX = re.compile('_s\\dv\\d')
     30 MULTI_HULL_VARIATION_REGEX = re.compile('v\\d')
     31 MULTI_HULL_SPECIFICATION_REGEX = re.compile('_s\\d')
     32 DEFAULT_FACTION_FOR_T2HULLS = {'ardishapur': ['ac2_t2b',
     33                 'ai2_t2',
     34                 'af5_t2',
     35                 'ab2_t2',
     36                 'af2_t2',
     37                 'ac4_t2'],
     38  'brutor': ['mf1_t2a',
     39             'mcb1_t2c',
     40             'mf5_t2a',
     41             'mc3_t2a',
     42             'mf7_t2c',
     43             'mc2_t2a',
     44             'mbc2_t2',
     45             'mb2_t2',
     46             'mf4_t2a',
     47             'mdh1_t2',
     48             'mdl1_t2',
     49             'mdm1_t2',
     50             'msd1_t2'],
     51  'creodron': ['gfr1_t2',
     52               'gbc2_t2',
     53               'gf5_t2',
     54               'gf4_t2a',
     55               'gc3_t2',
     56               'gb1_t2',
     57               'gdh1_t2',
     58               'gdl1_t2',
     59               'gdm1_t2',
     60               'gsd1_t2'],
     61  'development': ['oref1_t2b'],
     62  'duvolle': ['gc1_t2a',
     63              'gbc1_t2a',
     64              'gc4_t2a',
     65              'gf7_t2',
     66              'gb2_t2',
     67              'gf3_t2',
     68              'gf6_t2b',
     69              'gi4_t2'],
     70  'ishukone': ['cf3_t2',
     71               'cc2_t2b',
     72               'cc4_t2a',
     73               'cf7_t2b',
     74               'cfr1_t2',
     75               'cbc1_t2b'],
     76  'kaalakiota': ['ci2_t2',
     77                 'cf2_t2a',
     78                 'cde1_t2',
     79                 'cbc2_t2',
     80                 'cc2_t2a',
     81                 'cc4_t2b',
     82                 'cb2_t2'],
     83  'khanid': ['af7_t2',
     84             'ac1_t2a',
     85             'abc1_t2a',
     86             'ade1_t2',
     87             'ai1_t2',
     88             'af4_t2a',
     89             'ac2_t2a',
     90             'af3_t2a'],
     91  'laidai': ['cc1_t2',
     92             'ci3_t2',
     93             'cc3_t2',
     94             'cb1_t2',
     95             'cf7_t2a',
     96             'cf4_t2',
     97             'cf6_t2',
     98             'cf2_t2b',
     99             'cdh1_t2',
    100             'cdl1_t2',
    101             'cdm1_t2',
    102             'csd1_t2'],
    103  'orebase': ['oredh1_t2'],
    104  'prospecting': ['oreba3_t2', 'oreba2_t2', 'oreba1_t2'],
    105  'roden': ['gf6_t2a',
    106            'gf4_t2b',
    107            'gde1_t2',
    108            'gc1_t2b',
    109            'gi2_t2',
    110            'gc2_t2',
    111            'gc4_t2b'],
    112  'sarum': ['abc_t2',
    113            'afr1_t2',
    114            'af4_t2b',
    115            'ac3_t2',
    116            'ab1_t2',
    117            'ac1_t2b',
    118            'af3_t2b',
    119            'adh1_t2',
    120            'adl1_t2',
    121            'adm1_t2',
    122            'asd1_t2'],
    123  'sebiestor': ['mc2_t2c',
    124                'mi3_t2c',
    125                'mc3_t2c',
    126                'mde1_t2c',
    127                'mc4_t2c',
    128                'mf1_t2c'],
    129  'thukker': ['mf2_t2b',
    130              'mf4_t2b',
    131              'mi2_t2b',
    132              'mfr1_t2',
    133              'mb1_t2b',
    134              'mc1_t2b']}
    135 
    136 def GetGenericName(label):
    137     return label.replace(' ', '_').replace(':', '').strip().lower()
    138 
    139 
    140 def _CreateCheckbox(name, checkboxLabel, checkboxCallback, parent, align = uiconst.TOLEFT):
    141     return Checkbox(name=name + '_constraint', align=align, width=75, height=18, padLeft=10, parent=parent, text=checkboxLabel, callback=checkboxCallback)
    142 
    143 
    144 def _CreateCombo(name, values, callback, select, label, parent, align = uiconst.TOLEFT, width = 150):
    145     return Combo(name=name + '_combo', align=align, width=width, height=18, parent=parent, label=label, options=[ (name, i) for i, name in enumerate(values) ], callback=callback, select=select)
    146 
    147 
    148 def _CreateInput(name, value, callback, label, parent, align = uiconst.TOLEFT):
    149     return SingleLineEditText(name=name + '_input', align=align, label=label, parent=parent, width=150, height=18, setvalue=value, OnFocusLost=callback, OnReturn=callback)
    150 
    151 
    152 def _CreateSlider(name, label, minValue, maxValue, startVal, valueChangeFunc, parent, align = uiconst.TOLEFT):
    153     return Slider(name=name, align=align, label=label, parent=parent, width=150, height=18, minValue=minValue, maxValue=maxValue, value=startVal, on_dragging=valueChangeFunc, callback=valueChangeFunc)
    154 
    155 
    156 def _CreateContainer(name, parent, padTop = 16, padBottom = 0):
    157     return Container(name=name + '_container', parent=parent, align=uiconst.TOTOP, height=18, padTop=padTop, padBottom=padBottom, padLeft=5, padRight=5)
    158 
    159 
    160 def CreateDropdownWithCheckbox(label, values, select, dropdownCallback, checkboxLabel, checkboxCallback, parent):
    161     name = GetGenericName(label)
    162     container = _CreateContainer(name, parent)
    163     dropdown = _CreateCombo(name, values, dropdownCallback, select, label, container)
    164     checkbox = _CreateCheckbox(name, checkboxLabel, checkboxCallback, container)
    165     return (dropdown, checkbox)
    166 
    167 
    168 def CreateDropdown(label, values, callback, select, parent, align = uiconst.TOLEFT):
    169     name = GetGenericName(label)
    170     container = _CreateContainer(name, parent)
    171     combo = _CreateCombo(name, values, callback, select, label, container, align)
    172     return combo
    173 
    174 
    175 def CreateInput(label, value, callback, parent, align = uiconst.TOLEFT):
    176     name = GetGenericName(label)
    177     container = _CreateContainer(name, parent)
    178     inputField = _CreateInput(name, value, callback, label, container, align)
    179     return inputField
    180 
    181 
    182 def CreateSlider(label, minValue, maxValue, startValue, valueChangedFunc, parent):
    183     name = GetGenericName(label)
    184     container = _CreateContainer(name, parent, padTop=0, padBottom=16)
    185     slider = _CreateSlider(name, label, minValue, maxValue, startValue, valueChangedFunc, container)
    186     return slider
    187 
    188 
    189 def GetMultiHullInfo(hull):
    190     results = MULTI_HULL_REGEX.findall(hull)
    191     if len(results) > 0:
    192         return (hull.replace(results[0], ''), GetMultiHullSpecification(hull), GetMultiHullVariation(hull))
    193     return (None, None, None)
    194 
    195 
    196 def GetMultiHullVariation(hull):
    197     return int(MULTI_HULL_VARIATION_REGEX.findall(hull)[0].replace('v', ''))
    198 
    199 
    200 def GetMultiHullSpecification(hull):
    201     return int(MULTI_HULL_SPECIFICATION_REGEX.findall(hull)[0].replace('_s', ''))
    202 
    203 
    204 def GetMultiHullBaseName(hull):
    205     results = MULTI_HULL_REGEX.findall(hull)
    206     if len(results) > 0:
    207         result = results[0]
    208         return hull.replace(result, '')
    209     return ''
    210 
    211 
    212 def IsMultiHull(hull):
    213     return len(MULTI_HULL_REGEX.findall(hull)) > 0
    214 
    215 
    216 class StateMachineController:
    217 
    218     def __init__(self):
    219         self._states = {}
    220         self._currentStates = {}
    221         self._model = None
    222         self._variables = {}
    223         self._variableTypes = {}
    224         self._variableEnumValues = {}
    225 
    226     def _ClearAll(self):
    227         self._states = {}
    228         self._currentStates = {}
    229         self._model = None
    230 
    231     def SetupForHullAndModel(self, hull, model):
    232         self._ClearAll()
    233         self._model = model
    234         soanimation.TriggerDefaultStates(model)
    235         self._variables = {}
    236         for each in self._model.controllers:
    237             for var in getattr(each, 'variables', []):
    238                 self._variables[var.name] = var.value
    239                 self._variableTypes[var.name] = var.variableType
    240                 self._variableEnumValues[var.name] = var.enumValues
    241 
    242     def GetVariables(self):
    243         return self._variables
    244 
    245     def GetVariableType(self, name):
    246         return self._variableTypes.get(name, 0)
    247 
    248     def GetEnumValues(self, name):
    249         if self._variableTypes.get(name, 0) != 3:
    250             return []
    251         result = []
    252         for each in self._variableEnumValues.get(name, '').split(','):
    253             try:
    254                 k, v = each.strip().rsplit('=', 1)
    255                 v = float(v)
    256             except ValueError:
    257                 continue
    258 
    259             result.append((k, v))
    260 
    261         return result
    262 
    263     def SetVariable(self, name, value):
    264         self._variables[name] = float(value)
    265         self._model.SetControllerVariable(name, float(value))
    266 
    267     def ApplyTo(self, model):
    268         for name, value in self._variables.items():
    269             model.SetControllerVariable(name, value)
    270 
    271 
    272 class SOFPreviewWindow:
    273 
    274     def __init__(self):
    275         self.name = 'SOF Preview Window'
    276         self.windowID = 'SOFPreviewWindow_ ' + self.name
    277         self.previewCont = None
    278         dna = self.GetDnaFromPlayerShip()
    279         multiHulls = dna.split(':')[0].split(';')
    280         self.currentHulls = [ (None if i >= len(multiHulls) else multiHulls[i]) for i in xrange(0, MAX_MULTI_HULLS) ]
    281         self.currentFaction = dna.split(':')[1]
    282         self.currentRace = dna.split(':')[2]
    283         self.currentMat = ['None',
    284          'None',
    285          'None',
    286          'None']
    287         self.currentPatternMat = ['None', 'None']
    288         self.currentVariant = 'None'
    289         self.currentPattern = 'None'
    290         self.currentDirtLevel = None
    291         self.currentResPathInsert = None
    292         self.constrainToFaction = False
    293         self.constrainToHull = False
    294         self.constrainToRace = False
    295         self.constrainToPattern = False
    296         self.updateShip = True
    297         self.stateMachineController = StateMachineController()
    298 
    299     def _OnApplyButton(self, *args):
    300         self._UpdatePlayerShip()
    301 
    302     def _OnCopyDnaButton(self, *args):
    303         blue.pyos.SetClipboardData(self.GetPreviewDna())
    304 
    305     def ShowUI(self):
    306         Window.CloseIfOpen(windowID=self.windowID)
    307         wnd = Window.Open(windowID=self.windowID)
    308         wnd.SetMinSize([800, 500])
    309         wnd.SetCaption(self.name)
    310         main = wnd.GetMainArea()
    311         sofDB = blue.resMan.LoadObject('res:/dx9/model/spaceobjectfactory/data.red')
    312         self.sofFactions = []
    313         for faction in sofDB.faction:
    314             self.sofFactions.append(faction.name)
    315 
    316         self.sofFactions.sort()
    317         self.sofHulls = []
    318         self.multihulls = {}
    319         for hull in sofDB.hull:
    320             hull = hull.name
    321             if IsMultiHull(hull):
    322                 baseHullName, subpart, variation = GetMultiHullInfo(hull)
    323                 if baseHullName not in self.multihulls:
    324                     self.multihulls[baseHullName] = []
    325                 self.multihulls[baseHullName].append((hull, subpart, variation))
    326                 if subpart == 1:
    327                     self.sofHulls.append(hull)
    328             else:
    329                 self.sofHulls.append(hull)
    330 
    331         self.sofHulls.sort()
    332         self.sofRaces = []
    333         for race in sofDB.race:
    334             self.sofRaces.append(race.name)
    335 
    336         self.sofRaces.sort()
    337         self.sofMaterials = []
    338         for material in sofDB.material:
    339             self.sofMaterials.append(material.name)
    340 
    341         self.sofMaterials.sort()
    342         self.sofMaterials.insert(0, 'None')
    343         self.sofVariants = []
    344         for i in xrange(len(sofDB.generic.variants)):
    345             self.sofVariants.append(sofDB.generic.variants[i].name)
    346 
    347         self.sofVariants.sort()
    348         self.sofVariants.insert(0, 'None')
    349         self.sofPatterns = []
    350         self.patternToHulls = {}
    351         for pattern in sofDB.pattern:
    352             self.sofPatterns.append(pattern.name)
    353             self.patternToHulls[pattern.name] = [ hull.name for hull in pattern.projections ]
    354 
    355         self.sofPatterns.sort()
    356         self.sofPatterns.insert(0, 'None')
    357         headerCont = Container(name='headerCont', parent=main, align=uiconst.TOTOP, height=30)
    358         self.dnaLabel = EveLabelSmall(name='dnaLabel', align=uiconst.CENTER, parent=headerCont, text='')
    359         self.SetupButtonContainer(main)
    360         self.SetupInputContainers(main)
    361         self.previewCont = PreviewContainer(parent=main, align=uiconst.TOALL)
    362         self.previewCont.PreviewSofDna(self.GetPreviewDna())
    363         self._ReloadStateMachineOptions()
    364 
    365     def SetupButtonContainer(self, parent):
    366         buttonContainer = Container(name='_buttonCont', parent=parent, align=uiconst.TOBOTTOM, height=20, padBottom=10)
    367         buttonGroup = ButtonGroup(name='buttonGroup', parent=buttonContainer, align=uiconst.CENTER, fontsize=carbonui.fontconst.EVE_MEDIUM_FONTSIZE)
    368         buttonGroup.AddButton('Copy DNA', self._OnCopyDnaButton)
    369         buttonGroup.AddButton('Apply', self._OnApplyButton)
    370 
    371     def SetupInputContainers(self, parent):
    372         inputContainer = GridContainer(name='inputCont', parent=parent, align=uiconst.TOBOTTOM, height=250, lines=1, columns=3)
    373         self.SetupLeftContainer(inputContainer)
    374         self.SetupCenterContainer(inputContainer)
    375         self.SetupRightContainer(inputContainer)
    376 
    377     def SetupLeftContainer(self, inputContainer):
    378         _leftContainer = Container(name='_leftContainer', parent=inputContainer)
    379         leftContainer = Container(name='leftContainer', parent=_leftContainer, align=uiconst.TORIGHT, height=250, width=250)
    380         selectedRace = self.GetComboListIndex(self.sofRaces, self.currentRace)
    381         self.raceCombo, self.raceConstraint = CreateDropdownWithCheckbox('Race:', self.sofRaces, selectedRace, self.OnRaceComboChange, 'Constrained', self.OnRaceConstraintChanged, leftContainer)
    382         selectedHull = self.GetComboListIndex(self.sofHulls, self.currentHulls[0])
    383         self.hullCombos = []
    384         firstHullCombo, self.hullConstraint = CreateDropdownWithCheckbox('Hull:', self.sofHulls, selectedHull, self.OnHullComboChange, 'Constrained', self.OnHullConstraintChanged, leftContainer)
    385         self.hullCombos.append(firstHullCombo)
    386         self.multiHullContainer = Container(name='multiHulls', parent=leftContainer, align=uiconst.TOTOP, height=35 * (MAX_MULTI_HULLS - 1))
    387         for i in xrange(1, MAX_MULTI_HULLS):
    388             self.hullCombos.append(CreateDropdown('Hull %d:' % (i + 1), [], self.OnSpecificationChanges, self.currentHulls[i], self.multiHullContainer, align=uiconst.TOALL))
    389 
    390         self.multiHullContainer.display = False
    391         selectedFaction = self.GetComboListIndex(self.sofFactions, self.currentFaction)
    392         self.factionCombo, self.factionConstraint = CreateDropdownWithCheckbox('Faction:', self.sofFactions, selectedFaction, self.OnFactionComboChange, 'Constrained', self.OnFactionConstraintChanged, leftContainer)
    393         selectedPattern = self.GetComboListIndex(self.sofPatterns, self.currentPattern)
    394         self.patternCombo, self.patternConstraint = CreateDropdownWithCheckbox('Pattern:', self.sofPatterns, selectedPattern, self.OnPatternComboChange, 'Constrained', self.OnPatternConstraintChanged, leftContainer)
    395         previewContainer = Container(parent=leftContainer, align=uiconst.TOALL, padTop=16)
    396         self.previewImage = Sprite(parent=previewContainer, align=uiconst.CENTER, width=64, height=64)
    397         self.skinUnavailableLabel = EveLabelSmall(name='skinUnavailableLabel', align=uiconst.CENTERBOTTOM, parent=leftContainer, text='No skin license available', display=False)
    398         self.UpdateIcon()
    399 
    400     def SetupCenterContainer(self, inputContainer):
    401         _centerContainer = Container(name='_centerContainer', parent=inputContainer)
    402         centerContainer = Container(name='centerContainer', parent=_centerContainer, align=uiconst.CENTERTOP, height=250, width=250)
    403         self.matCombo1 = CreateDropdown('Material 1:', self.sofMaterials, self.OnMat1ComboChange, self.GetComboListIndex(self.sofMaterials, self.currentMat[0]), centerContainer, align=uiconst.CENTER)
    404         self.matCombo2 = CreateDropdown('Material 2:', self.sofMaterials, self.OnMat2ComboChange, self.GetComboListIndex(self.sofMaterials, self.currentMat[1]), centerContainer, align=uiconst.CENTER)
    405         self.matCombo3 = CreateDropdown('Material 3:', self.sofMaterials, self.OnMat3ComboChange, self.GetComboListIndex(self.sofMaterials, self.currentMat[2]), centerContainer, align=uiconst.CENTER)
    406         self.matCombo4 = CreateDropdown('Material 4:', self.sofMaterials, self.OnMat4ComboChange, self.GetComboListIndex(self.sofMaterials, self.currentMat[3]), centerContainer, align=uiconst.CENTER)
    407         self.matCombo5 = CreateDropdown('Pattern Material 1:', self.sofMaterials, self.OnPatternMat1ComboChange, self.GetComboListIndex(self.sofMaterials, self.currentPatternMat[0]), centerContainer, align=uiconst.CENTER)
    408         self.matCombo6 = CreateDropdown('Pattern Material 2:', self.sofMaterials, self.OnPatternMat2ComboChange, self.GetComboListIndex(self.sofMaterials, self.currentPatternMat[1]), centerContainer, align=uiconst.CENTER)
    409 
    410     def SetupRightContainer(self, inputContainer):
    411         _rightContainer = Container(name='_rightContainer', parent=inputContainer)
    412         rightContainer = Container(name='rightContainer', parent=_rightContainer, align=uiconst.TOLEFT, height=250, width=250)
    413         self.dirtSlider = CreateSlider('Dirt', 0.0, 100.0, 50.0, self.OnDirtSliderChange, rightContainer)
    414         self.UpdateDirtSliderLabel()
    415         self.materialSetIDCombo, self.materialSetFilteredByRace = CreateDropdownWithCheckbox('materialSetID', [], 0, self.OnMaterialSetIDChange, 'Filter By Race', self.OnMaterialSetFiltered, rightContainer)
    416         self._FilterMaterialSet(False)
    417         self.resPathInsertEdit = CreateInput('resPathInsert', '', self.OnResPathInsertChange, rightContainer)
    418         self.variantCombo = CreateDropdown('Variants:', self.sofVariants, self.OnVariantComboChange, self.GetComboListIndex(self.sofVariants, self.currentVariant), rightContainer)
    419         self.controllerParent = Container(parent=rightContainer, align=uiconst.TOTOP, height=68, padTop=16, padLeft=5, padRight=5)
    420         self.controllers = None
    421 
    422     @staticmethod
    423     def GetComboListIndex(comboContentList, name):
    424         for index, each in enumerate(comboContentList):
    425             if each.lower() == name.lower():
    426                 return index
    427 
    428     def GetCurrentHull(self):
    429         currentHull = self.currentHulls[0]
    430         if IsMultiHull(currentHull):
    431             currentHull += ';' + ';'.join((hull for hull in self.currentHulls[1:] if hull is not None))
    432         return currentHull
    433 
    434     def GetPreviewDna(self):
    435         dna = self.GetCurrentHull() + ':' + self.currentFaction + ':' + self.currentRace
    436         if any((x != 'None' for x in self.currentMat)):
    437             dna += ':material?' + str(self.currentMat[0]) + ';' + str(self.currentMat[1]) + ';' + str(self.currentMat[2]) + ';' + str(self.currentMat[3])
    438         if self.currentResPathInsert is not None:
    439             dna += ':respathinsert?' + str(self.currentResPathInsert)
    440         if self.currentVariant != 'None':
    441             dna += ':variant?' + str(self.currentVariant)
    442         if self.currentPattern != 'None':
    443             dna += ':pattern?' + str(self.currentPattern) + ';' + str(self.currentPatternMat[0]) + ';' + str(self.currentPatternMat[1])
    444         self.dnaLabel.text = dna
    445         return dna
    446 
    447     @staticmethod
    448     def GetDnaFromPlayerShip():
    449         michelle = sm.GetService('michelle')
    450         ship = michelle.GetBall(session.shipid)
    451         if ship is None:
    452             return 'ab1_t1:amarrbase:amarr'
    453         dna = ship.GetDNA()
    454         if dna is None:
    455             return 'ab1_t1:amarrbase:amarr'
    456         return dna
    457 
    458     def UpdateDirtSliderLabel(self):
    459         dirtLevel = gfxutils.RemapDirtLevel(self.dirtSlider.GetValue())
    460         self.dirtSlider.SetLabel('Dirt level: ' + str(dirtLevel))
    461 
    462     def OnDirtSliderChange(self, slider):
    463         self.currentDirtLevel = gfxutils.RemapDirtLevel(slider.GetValue())
    464         self.UpdateDirtSliderLabel()
    465         self._UpdatePreviewShip()
    466 
    467     def OnFactionConstraintChanged(self, checkbox):
    468         self.constrainToFaction = checkbox.GetValue()
    469         self.ConstrainDnaSelection()
    470 
    471     def OnRaceConstraintChanged(self, checkbox):
    472         self.constrainToRace = checkbox.GetValue()
    473         self.ConstrainDnaSelection()
    474 
    475     def OnHullConstraintChanged(self, checkbox):
    476         self.constrainToHull = checkbox.GetValue()
    477         self.ConstrainDnaSelection()
    478 
    479     def OnPatternConstraintChanged(self, checkbox):
    480         self.constrainToPattern = checkbox.GetValue()
    481         self.ConstrainDnaSelection()
    482 
    483     def OnMaterialSetFiltered(self, checkbox):
    484         materialSetFiltered = checkbox.GetValue()
    485         self._FilterMaterialSet(materialSetFiltered)
    486 
    487     def _FilterMaterialSet(self, filterByRace):
    488         materialSets = graphicMaterialSets.GetGraphicMaterialSets()
    489         availableMaterialSets = []
    490         for materialSetID, materialSet in materialSets.iteritems():
    491             if filterByRace:
    492                 raceHint = graphicMaterialSets.GetSofRaceHint(materialSet)
    493                 if raceHint and raceHint == self.raceCombo.GetKey():
    494                     availableMaterialSets.append((materialSetID, materialSet.description))
    495             else:
    496                 availableMaterialSets.append((materialSetID, materialSet.description))
    497 
    498         availableMaterialSets = sorted(availableMaterialSets, key=lambda x: x[0])
    499         options = [('None', -1)] + [ ('%s: %s' % keyAndDesc, keyAndDesc[0]) for keyAndDesc in availableMaterialSets ]
    500         self.materialSetIDCombo.LoadOptions(options)
    501         self.TrySettingComboValue(self.materialSetIDCombo, 0)
    502 
    503     def ConstrainDnaSelection(self):
    504         raceQuery = '.*'
    505         factionQuery = '.*'
    506         hullQuery = '.*'
    507         if self.constrainToFaction:
    508             factionQuery = self.factionCombo.GetKey()
    509         if self.constrainToHull:
    510             hullQuery = self.hullCombos[0].GetKey()
    511         if self.constrainToRace:
    512             raceQuery = self.raceCombo.GetKey()
    513         if self.constrainToPattern and self.currentPattern != 'None':
    514             self.currentHulls[0] = self.TrySettingComboOptions(self.hullCombos[0], self.patternToHulls[self.currentPattern], self.currentHulls[0])
    515         if not self.constrainToFaction and not self.constrainToHull and not self.constrainToRace and not self.constrainToPattern:
    516             self.currentFaction = self.TrySettingComboOptions(self.factionCombo, self.sofFactions, self.GetDefaultFactionForHull())
    517             self.currentRace = self.TrySettingComboOptions(self.raceCombo, self.sofRaces, self.currentRace)
    518             self.currentHulls[0] = self.TrySettingComboOptions(self.hullCombos[0], self.sofHulls, self.currentHulls[0])
    519             self.currentPattern = self.TrySettingComboOptions(self.patternCombo, self.sofPatterns, self.currentPattern)
    520         else:
    521             dnaList = GetDnaStringsMatchingQuery(hullQuery, factionQuery, raceQuery)
    522             selectableRaces = []
    523             selectableFactions = []
    524             selectableHulls = []
    525             for dna in dnaList:
    526                 dnaElements = dna.split(':')
    527                 hull = dnaElements[0]
    528                 faction = dnaElements[1]
    529                 race = dnaElements[2]
    530                 if faction not in selectableFactions:
    531                     selectableFactions.append(faction)
    532                 if race not in selectableRaces:
    533                     selectableRaces.append(race)
    534                 if hull not in selectableHulls:
    535                     selectableHulls.append(hull)
    536 
    537             if not self.constrainToPattern:
    538                 selectablePatterns = [ patternName for patternName, hulls in self.patternToHulls.iteritems() for hullName in selectableHulls if hullName in hulls ]
    539                 selectablePatterns = list(set(selectablePatterns))
    540                 selectablePatterns.insert(0, 'None')
    541                 self.currentPattern = self.TrySettingComboOptions(self.patternCombo, selectablePatterns, self.currentPattern)
    542             elif self.currentPattern != 'None':
    543                 selectableHullsBasedOfPattern = set(self.patternToHulls[self.currentPattern])
    544                 selectableHulls = list(set(selectableHulls).intersection(selectableHullsBasedOfPattern))
    545             if not self.constrainToHull:
    546                 self.currentHulls[0] = self.TrySettingComboOptions(self.hullCombos[0], selectableHulls, self.currentHulls[0])
    547                 self.ShowMultiHullComboBoxes(self.currentHulls[0])
    548             if not self.constrainToFaction:
    549                 self.currentFaction = self.TrySettingComboOptions(self.factionCombo, selectableFactions, self.GetDefaultFactionForHull())
    550             if not self.constrainToRace:
    551                 self.currentRace = self.TrySettingComboOptions(self.raceCombo, selectableRaces, self.currentRace)
    552             if not self.constrainToPattern and self.constrainToHull:
    553                 availablePatterns = [ pattern for pattern, hulls in self.patternToHulls.iteritems() if self.currentHulls[0] in hulls ]
    554                 availablePatterns.insert(0, 'None')
    555                 self.currentPattern = self.TrySettingComboOptions(self.patternCombo, availablePatterns, self.currentPattern)
    556         self._UpdatePreviewShip()
    557 
    558     def GetDefaultFactionForHull(self):
    559         if self.currentHulls[0].endswith('t2'):
    560             return self._GetDefaultFactionForT2Hull(self.currentHulls[0])
    561         else:
    562             return self._GetDefaultFactionForT1Hull(self.currentHulls[0])
    563 
    564     def UpdateIcon(self):
    565         path = None
    566         id = self.GetCurrentMaterialSetID()
    567         for mid, m in SkinMaterialStorage().iteritems():
    568             if m.materialSetID == id:
    569                 path = 'res:/UI/Texture/classes/skins/icons/%s.png' % mid
    570                 break
    571 
    572         self.skinUnavailableLabel.display = path is None
    573         if path is None:
    574             path = 'res:/UI/Texture/notavailable.dds'
    575         self.previewImage.texture.resPath = path
    576 
    577     @staticmethod
    578     def _GetDefaultFactionForT1Hull(hullName):
    579         dnaList = GetDnaStringsMatchingQuery(hullName)
    580         if len(dnaList) == 0:
    581             return ''
    582         race = dnaList[0].split(':')[2]
    583         return race + 'base'
    584 
    585     @staticmethod
    586     def _GetDefaultFactionForT2Hull(hullName):
    587         for factionName, hullList in DEFAULT_FACTION_FOR_T2HULLS.iteritems():
    588             if hullName in hullList:
    589                 return factionName
    590 
    591         return ''
    592 
    593     def GetCurrentMaterialSetID(self):
    594         if not hasattr(self, 'materialSetIDCombo'):
    595             return -1
    596         return self.materialSetIDCombo.GetValue()
    597 
    598     def GetCurrentMaterialSet(self):
    599         materialSetID = self.GetCurrentMaterialSetID()
    600         print('trying to find materialset for ' + str(materialSetID))
    601         materialSet = graphicMaterialSets.GetGraphicMaterialSet(materialSetID)
    602         return materialSet
    603 
    604     def ShowMultiHullComboBoxes(self, hull):
    605         isMultiHull = IsMultiHull(hull)
    606         self.multiHullContainer.display = isMultiHull
    607         if isMultiHull:
    608             baseHullName = GetMultiHullBaseName(hull)
    609             for i in xrange(1, MAX_MULTI_HULLS):
    610                 availableHulls = [ hull for hull, specification, variation in sorted(self.multihulls[baseHullName], key=lambda x: x[2]) if specification == i + 1 ]
    611                 self.TrySettingComboOptions(self.hullCombos[i], availableHulls, self.currentPattern)
    612                 self.currentHulls[i] = availableHulls[0]
    613 
    614         else:
    615             for i in xrange(1, MAX_MULTI_HULLS):
    616                 self.currentHulls[i] = None
    617 
    618     def TrySettingComboOptions(self, comboBox, options, selectedValue):
    619         options = sorted(options)
    620         if 'None' in options:
    621             o = options.pop(options.index('None'))
    622             options.insert(0, o)
    623         optionTuple = [ (name, i) for i, name in enumerate(options) ]
    624         comboBox.LoadOptions(optionTuple)
    625         return self.TrySettingComboValue(comboBox, selectedValue)
    626 
    627     def TrySettingComboValue(self, comboBox, selectedValue):
    628         try:
    629             comboBox.SelectItemByLabel(selectedValue)
    630         except RuntimeError:
    631             comboBox.SelectItemByIndex(0)
    632             print("Could not select '%s', defaulting to '%s'" % (selectedValue, comboBox.GetKey()))
    633 
    634         return comboBox.GetKey()
    635 
    636     def IsMaterialSetSelected(self):
    637         return self.materialSetIDCombo.GetKey() != 'None'
    638 
    639     def OnPatternComboChange(self, comboBox, pattern, value):
    640         self.currentPattern = pattern
    641         if self.constrainToPattern:
    642             self.ConstrainDnaSelection()
    643         self._UpdatePreviewShip()
    644 
    645     def OnFactionComboChange(self, comboBox, faction, value):
    646         self.currentFaction = faction
    647         if self.constrainToFaction:
    648             self.ConstrainDnaSelection()
    649         self._UpdatePreviewShip()
    650 
    651     def OnHullComboChange(self, comboBox, hull, value):
    652         self.currentHulls[0] = hull
    653         self.ShowMultiHullComboBoxes(hull)
    654         if self.constrainToHull:
    655             self.ConstrainDnaSelection()
    656         self._UpdatePreviewShip()
    657 
    658     def OnSpecificationChanges(self, comboBox, hull, value):
    659         specification = GetMultiHullSpecification(hull)
    660         self.currentHulls[specification - 1] = hull
    661         self._UpdatePreviewShip()
    662 
    663     def OnRaceComboChange(self, comboBox, race, value):
    664         self.currentRace = race
    665         if self.constrainToRace:
    666             self.ConstrainDnaSelection()
    667         if self.materialSetFilteredByRace.GetValue():
    668             self._FilterMaterialSet(self.currentRace)
    669         self._UpdatePreviewShip()
    670 
    671     def OnMat1ComboChange(self, comboBox, material, value):
    672         self.currentMat[0] = material
    673         self._UpdatePreviewShip()
    674 
    675     def OnMat2ComboChange(self, comboBox, material, value):
    676         self.currentMat[1] = material
    677         self._UpdatePreviewShip()
    678 
    679     def OnMat3ComboChange(self, comboBox, material, value):
    680         self.currentMat[2] = material
    681         self._UpdatePreviewShip()
    682 
    683     def OnMat4ComboChange(self, comboBox, material, value):
    684         self.currentMat[3] = material
    685         self._UpdatePreviewShip()
    686 
    687     def OnPatternMat1ComboChange(self, comboBox, material, value):
    688         self.currentPatternMat[0] = material
    689         self._UpdatePreviewShip()
    690 
    691     def OnPatternMat2ComboChange(self, comboBox, material, value):
    692         self.currentPatternMat[1] = material
    693         self._UpdatePreviewShip()
    694 
    695     def OnVariantComboChange(self, comboBox, variant, value):
    696         self.currentVariant = variant
    697         self._UpdatePreviewShip()
    698 
    699     def OnMaterialSetIDChange(self, *args):
    700         self.updateShip = False
    701         materialSet = self.GetCurrentMaterialSet()
    702         faction = graphicMaterialSets.GetSofFactionName(materialSet)
    703         if not faction:
    704             dna = self.GetDnaFromPlayerShip()
    705             if dna.split(':')[0] == self.GetCurrentHull():
    706                 faction = dna.split(':')[1]
    707         if faction:
    708             try:
    709                 self.factionCombo.SelectItemByLabel(faction)
    710             except RuntimeError:
    711                 if materialSet is not None:
    712                     print("Removing constraints because '%s' is not in the constrained faction list" % materialSet.sofFactionName)
    713                 self.constrainToFaction = False
    714                 self.constrainToRace = False
    715                 self.constrainToHull = False
    716                 self.constrainToPattern = False
    717                 self.factionConstraint.SetValue(False)
    718                 self.raceConstraint.SetValue(False)
    719                 self.hullConstraint.SetValue(False)
    720                 self.patternConstraint.SetValue(False)
    721                 self.ConstrainDnaSelection()
    722 
    723             self.factionCombo.SelectItemByLabel(faction)
    724             self.OnFactionComboChange(self.factionCombo, faction, None)
    725         material1 = graphicMaterialSets.GetMaterial1(materialSet, 'None')
    726         idx = self.GetComboListIndex(self.sofMaterials, material1)
    727         self.matCombo1.SelectItemByValue(idx)
    728         self.OnMat1ComboChange(self.matCombo1, material1, idx)
    729         material2 = graphicMaterialSets.GetMaterial2(materialSet, 'None')
    730         idx = self.GetComboListIndex(self.sofMaterials, material2)
    731         self.matCombo2.SelectItemByValue(idx)
    732         self.OnMat2ComboChange(self.matCombo2, material2, idx)
    733         material3 = graphicMaterialSets.GetMaterial3(materialSet, 'None')
    734         idx = self.GetComboListIndex(self.sofMaterials, material3)
    735         self.matCombo3.SelectItemByValue(idx)
    736         self.OnMat3ComboChange(self.matCombo3, material3, idx)
    737         material4 = graphicMaterialSets.GetMaterial4(materialSet, 'None')
    738         idx = self.GetComboListIndex(self.sofMaterials, material4)
    739         self.matCombo4.SelectItemByValue(idx)
    740         self.OnMat4ComboChange(self.matCombo4, material4, idx)
    741         patternmaterial1 = graphicMaterialSets.GetCustomMaterial1(materialSet, 'None')
    742         idx = self.GetComboListIndex(self.sofMaterials, patternmaterial1)
    743         self.matCombo5.SelectItemByValue(idx)
    744         self.OnPatternMat1ComboChange(self.matCombo5, patternmaterial1, idx)
    745         patternmaterial2 = graphicMaterialSets.GetCustomMaterial2(materialSet, 'None')
    746         idx = self.GetComboListIndex(self.sofMaterials, patternmaterial2)
    747         self.matCombo6.SelectItemByValue(idx)
    748         self.OnPatternMat2ComboChange(self.matCombo6, patternmaterial2, idx)
    749         self.resPathInsertEdit.SetValue(graphicMaterialSets.GetResPathInsert(materialSet, ''))
    750         self.OnResPathInsertChange()
    751         sofPatternName = graphicMaterialSets.GetSofPatternName(materialSet, 'None')
    752         idx = self.GetComboListIndex(self.sofPatterns, sofPatternName)
    753         self.patternCombo.SelectItemByValue(idx)
    754         self.OnPatternComboChange(self.patternCombo, sofPatternName, idx)
    755         self.updateShip = True
    756         self._UpdatePreviewShip()
    757         self.UpdateIcon()
    758 
    759     def OnResPathInsertChange(self, *args):
    760         resPathInsert = self.resPathInsertEdit.GetValue()
    761         print('new respathinsert: ' + resPathInsert)
    762         if len(resPathInsert) == 0:
    763             self.currentResPathInsert = None
    764         else:
    765             self.currentResPathInsert = resPathInsert
    766         self._UpdatePreviewShip()
    767 
    768     def _UpdatePreviewShip(self):
    769         if self.previewCont is not None and self.updateShip:
    770             self.previewCont.PreviewSofDna(self.GetPreviewDna(), dirt=self.currentDirtLevel)
    771             self._ReloadStateMachineOptions()
    772 
    773     def _ReloadStateMachineOptions(self):
    774         model = self.previewCont.context.GetModel()
    775         hull = self.GetCurrentHull()
    776         self.stateMachineController.SetupForHullAndModel(hull, model)
    777         self._RefreshControllerVariables()
    778 
    779     def _OnControllerVariable(self, edit):
    780         edit.SetText(edit.text, 1)
    781         name = edit.name
    782         value = float(edit.text)
    783         self.stateMachineController.SetVariable(name, value)
    784 
    785     def _OnControllerBoolVariable(self, cb):
    786         name = cb.name
    787         value = cb.GetValue()
    788         self.stateMachineController.SetVariable(name, 1.0 if value else 0.0)
    789 
    790     def _OnControllerEnumVariable(self, cb, *args):
    791         name = cb.name
    792         value = cb.GetValue()
    793         self.stateMachineController.SetVariable(name, value)
    794 
    795     def _RefreshControllerVariables(self):
    796         if self.controllers:
    797             self.controllers.Close()
    798         self.controllers = ScrollContainer(parent=self.controllerParent, align=uiconst.TOTOP, height=68)
    799         PanelUnderlay(bgParent=self.controllers)
    800         for name, value in self.stateMachineController.GetVariables().items():
    801             line = Container(parent=self.controllers, align=uiconst.TOTOP, height=20, state=uiconst.UI_NORMAL)
    802             EveLabelSmall(parent=line, align=uiconst.CENTERLEFT, text=name, left=4)
    803             varType = self.stateMachineController.GetVariableType(name)
    804             if varType == 1:
    805                 SingleLineEditInteger(align=uiconst.CENTERRIGHT, name=name, parent=line, width=150, height=18, setvalue=str(int(value)), OnFocusLost=self._OnControllerVariable, OnReturn=self._OnControllerVariable, sendSelfAsArgument=True)
    806             elif varType == 2:
    807                 Checkbox(align=uiconst.CENTERRIGHT, name=name, parent=line, width=150, height=18, setvalue=str(value), floats=(None, None), callback=self._OnControllerBoolVariable)
    808             elif varType == 3:
    809                 Combo(align=uiconst.CENTERRIGHT, name=name, parent=line, width=150, height=18, options=self.stateMachineController.GetEnumValues(name), callback=self._OnControllerEnumVariable, select=value)
    810             else:
    811                 SingleLineEditFloat(align=uiconst.CENTERRIGHT, name=name, parent=line, width=150, height=18, setvalue=str(value), OnFocusLost=self._OnControllerVariable, OnReturn=self._OnControllerVariable, sendSelfAsArgument=True)
    812             Line(parent=line, align=uiconst.TOBOTTOM, opacity=0.05)
    813 
    814     def _UpdatePlayerShip(self):
    815         michelle = sm.GetService('michelle')
    816         ship = michelle.GetBall(session.shipid)
    817         if ship is None:
    818             return
    819         ship.UnfitHardpoints()
    820         ship.Release()
    821         while ship.model is not None:
    822             blue.synchro.Yield()
    823 
    824         ship.released = False
    825         ship.GetDNA = self.GetPreviewDna
    826         ship.LoadModel()
    827         ship.Assemble()
    828         if self.currentDirtLevel is not None:
    829             ship.model.dirtLevel = self.currentDirtLevel
    830         self.stateMachineController.ApplyTo(ship.model)
    831         ship.model.StartControllers()