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

controller.py (22233B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\skins\controller.py
      2 import gametime
      3 import uthread2
      4 from cosmetics.client.shipSkinApplicationSvc import get_ship_skin_application_svc
      5 from cosmetics.client.ships.ship_skin_signals import on_skin_state_set, on_skin_license_activated, on_skin_state_reapplied
      6 from cosmetics.client.ships.skins.live_data.ship_skin_state import ShipSkinState
      7 from cosmetics.client.shipSkinLicensesSvc import get_ship_skin_license_svc
      8 from cosmetics.common.ships.skins.static_data.skin_type import ShipSkinType
      9 from cosmetics.common.ships.skins.static_data.slot_configuration import is_skinnable_ship
     10 from player_messaging.client.ui_message import message_player
     11 from eve.client.script.ui.shared.skins.skinUISignals import on_skin_selected
     12 from eve.client.script.environment.spaceObject.cosmeticsManager import CosmeticsManager
     13 from eve.client.script.environment.sofService import GetSofService
     14 from eve.common.script.sys.idCheckers import IsShipType
     15 from eveexceptions import UserError
     16 from eveexceptions.exceptionEater import ExceptionEater
     17 from itertoolsext import first
     18 import locks
     19 import uthread
     20 import signals
     21 import evetypes
     22 from localization import GetByLabel
     23 from structures import STATE_SHIELD_VULNERABLE
     24 from evegraphics.utils import BuildSOFDNAFromTypeID
     25 from inventorycommon.util import IsModularShip, GetSubSystemTypeIDsForDogmaLocation
     26 import inventorycommon.const as invConst
     27 from carbon.common.script.util.logUtil import LogException, LogInfo
     28 from publicGateway.grpc.exceptions import GenericException
     29 from stackless_response_router.exceptions import TimeoutException
     30 SKIN_DELAY_STRUCTURES = 8
     31 
     32 class ThirdPartySkinWrapper(object):
     33 
     34     def __init__(self, third_party_skin_license):
     35         self.skin = third_party_skin_license
     36         self.skin_data = self.skin.skin_design
     37         self.ship_type_id = self.skin.skin_design.ship_type_id
     38 
     39     @property
     40     def skin_type(self):
     41         return ShipSkinType.THIRD_PARTY_SKIN
     42 
     43     @property
     44     def skinID(self):
     45         return self.skin.skin_hex
     46 
     47     @property
     48     def name(self):
     49         return self.skin.skin_design.name
     50 
     51     @property
     52     def licensed(self):
     53         return True
     54 
     55     @property
     56     def expires(self):
     57         return None
     58 
     59     @property
     60     def iconTexturePath(self):
     61         return 'res:/UI/Texture/WindowIcons/paint_tool.png'
     62 
     63     def __eq__(self, other):
     64         if not isinstance(other, ThirdPartySkinWrapper):
     65             return False
     66         return self.skinID == other.skinID
     67 
     68 
     69 class SkinPanelAdapter(object):
     70 
     71     def ApplySkin(self, controller, itemID, hullTypeID, skin):
     72         uthread.new(self._ApplySkinThread, controller, itemID, hullTypeID, skin)
     73 
     74     def _ApplySkinThread(self, controller, itemID, hullTypeID, skin):
     75         try:
     76             if skin and skin.skin_type == ShipSkinType.THIRD_PARTY_SKIN:
     77                 self._ApplyThirdPartySkin(skin.skinID, itemID)
     78             else:
     79                 self._ApplyFirstPartySkin(itemID, hullTypeID, skin)
     80         except Exception:
     81             controller.OnApplySkinFailed(itemID, skin, hullTypeID)
     82             raise
     83 
     84     def _ApplyFirstPartySkin(self, itemID, hullTypeID, skin):
     85         try:
     86             get_ship_skin_application_svc().apply_first_party_skin(itemID, hullTypeID, skin)
     87         except UserError as e:
     88             if e.msg != 'SkinAlreadyApplied':
     89                 raise
     90         except Exception:
     91             raise
     92 
     93     def _ApplyThirdPartySkin(self, licenseID, itemID):
     94         get_ship_skin_application_svc().apply_third_party_skin(itemID, licenseID, apply_license=True, activate_license=False)
     95 
     96     def GetAppliedSkin(self, itemID, hullTypeID, licenseeID = None):
     97         cosmeticsSvc = sm.GetService('cosmeticsSvc')
     98         if licenseeID is None:
     99             skin_state = cosmeticsSvc.GetAppliedSkinStateForCurrentSession(itemID)
    100         else:
    101             skin_state = cosmeticsSvc.GetAppliedSkinState(licenseeID, itemID)
    102         if skin_state is None or skin_state.skin_type == ShipSkinType.NO_SKIN:
    103             return
    104         if skin_state.skin_type == ShipSkinType.FIRST_PARTY_SKIN:
    105             if licenseeID is None:
    106                 return cosmeticsSvc.GetFirstPartySkinObjectForCurrentSession(skin_state.skin_data.skin_id)
    107             else:
    108                 return cosmeticsSvc.GetFirstPartySkinObject(licenseeID, skin_state.skin_data.skin_id)
    109         if skin_state.skin_type == ShipSkinType.THIRD_PARTY_SKIN:
    110             if skin_state.character_id != session.charid:
    111                 return
    112             else:
    113                 try:
    114                     skin_license = get_ship_skin_license_svc().get_license(skin_state.skin_data.skin_id, skin_state.character_id)
    115                 except (GenericException, TimeoutException):
    116                     message_player(GetByLabel('UI/Common/CannotConnectToServer'))
    117                     skin_license = None
    118 
    119                 if skin_license:
    120                     return ThirdPartySkinWrapper(skin_license)
    121                 return
    122 
    123     def GetSkins(self, hullTypeID):
    124         if not IsShipType(hullTypeID):
    125             return []
    126         skins = sm.GetService('cosmeticsSvc').GetSkins(hullTypeID)
    127         if is_skinnable_ship(hullTypeID):
    128             try:
    129                 thirdPartySkins = [ ThirdPartySkinWrapper(skin_license) for skin_license in get_ship_skin_license_svc().get_my_activated_licenses(hullTypeID) ]
    130                 skins.extend(thirdPartySkins)
    131             except:
    132                 pass
    133 
    134         return sorted(skins, key=lambda s: s.name)
    135 
    136     def GetTypesForSkin(self, skinID):
    137         skin = sm.GetService('cosmeticsSvc').static.GetSkinByID(skinID)
    138         return skin.types
    139 
    140     def RegisterNotify(self, controller):
    141         sm.RegisterNotify(controller)
    142 
    143     def UnregisterNotify(self, controller):
    144         sm.UnregisterNotify(controller)
    145 
    146 
    147 class SkinPanelController(object):
    148     __notifyevents__ = ['OnSkinLicenseActivated']
    149 
    150     def __init__(self, hullTypeID, adapter = None):
    151         self._adapter = adapter or SkinPanelAdapter()
    152         self._lock = locks.Lock()
    153         self.Reset(hullTypeID)
    154         self.onChange = signals.Signal(signalName='onChange')
    155         self.onSkinsChange = signals.Signal(signalName='onSkinsChange')
    156         self.on_position_changed = signals.Signal(signalName='on_position_changed')
    157         self.onSkinsChange.connect(self.onChange)
    158         on_skin_license_activated.connect(self._OnThirdPartySkinLicenseActivated)
    159         self._adapter.RegisterNotify(self)
    160 
    161     def Close(self):
    162         on_skin_license_activated.disconnect(self._OnThirdPartySkinLicenseActivated)
    163         self._adapter.UnregisterNotify(self)
    164         self.onSkinsChange.clear()
    165         self.onChange.clear()
    166 
    167     def Reset(self, hullTypeID):
    168         self._typeID = hullTypeID
    169         self._applied = None
    170         self._previewed = None
    171         self._pending = None
    172         self._skins = None
    173         self._lastSkinChange = sm.GetService('cosmeticsSvc').lastSkinChange
    174         self._forcedDelayInSec = 0
    175 
    176     @property
    177     def typeID(self):
    178         return self._typeID
    179 
    180     @typeID.setter
    181     def typeID(self, newTypeID):
    182         with self._lock:
    183             self.Reset(newTypeID)
    184             self.onSkinsChange()
    185 
    186     @property
    187     def applied(self):
    188         return self._applied
    189 
    190     @property
    191     def previewed(self):
    192         return self._previewed
    193 
    194     @property
    195     def pending(self):
    196         return self._pending
    197 
    198     @property
    199     def skins(self):
    200         if self._skins is None:
    201             self._skins = self._adapter.GetSkins(self._typeID)
    202         return self._skins
    203 
    204     def PickSkinAndMoveToIt(self, skin, deselectIfSame = True):
    205         self.PickSkin(skin, deselectIfSame)
    206         uthread2.call_after_wallclocktime_delay(self.on_position_changed, 1)
    207 
    208     def PickSkin(self, skin, deselectIfSame = True):
    209         with self._lock:
    210             if self._previewed and skin:
    211                 if hasattr(self._previewed, 'materialID') and hasattr(skin, 'materialID') and self._previewed.materialID == skin.materialID and deselectIfSame:
    212                     skin = None
    213                 elif self._previewed.skinID and skin.skinID and self._previewed.skinID == skin.skinID:
    214                     skin = None
    215             self._previewed = skin
    216             self.onChange()
    217 
    218     def OnSkinLicenseActivated(self, skinID, licenseeID):
    219         with self._lock:
    220             types = self._adapter.GetTypesForSkin(skinID)
    221             if self._typeID not in types:
    222                 return
    223             self._skins = None
    224             self._UpdateActivatedSkin(skinID)
    225             self.onSkinsChange()
    226 
    227     def _OnThirdPartySkinLicenseActivated(self, licenseID):
    228         with self._lock:
    229             self._skins = None
    230             self._UpdateActivatedSkin(licenseID)
    231             self.onSkinsChange()
    232 
    233     def _UpdateActivatedSkin(self, skinID):
    234         if self._previewed is None:
    235             return
    236         try:
    237             skin = self._GetSkinByID(skinID)
    238             if skin and skin == self._previewed:
    239                 self._previewed = skin
    240         except StopIteration:
    241             pass
    242 
    243     def _GetSkinByID(self, skinID):
    244         try:
    245             return first(self.skins, lambda s: s.skinID == skinID)
    246         except StopIteration:
    247             return None
    248 
    249     def IsSkinAccessRestricted(self):
    250         return False
    251 
    252     def IsDisabledDueToDamage(self):
    253         return False
    254 
    255     def GetAppliedSkin(self, itemID, hullTypeID):
    256         return self._adapter.GetAppliedSkin(itemID, hullTypeID)
    257 
    258     def GetTimeUntilNextAllowedSkinChange(self):
    259         if self._lastSkinChange is None or self._forcedDelayInSec <= 0:
    260             return 0
    261         timeUntil = self._lastSkinChange + self._forcedDelayInSec * const.SEC - gametime.GetWallclockTime()
    262         return max(0, float(timeUntil) / const.SEC)
    263 
    264 
    265 class ShipInfoSkinPanelController(SkinPanelController):
    266 
    267     def __init__(self, itemID, ownerID, hullTypeID, adapter = None):
    268         self.itemID = itemID
    269         self.ownerID = ownerID
    270         super(ShipInfoSkinPanelController, self).__init__(hullTypeID, adapter)
    271         on_skin_state_set.connect(self._OnSkinStateSet)
    272         on_skin_state_reapplied.connect(self._OnSkinStateReapplied)
    273 
    274     def Close(self):
    275         super(ShipInfoSkinPanelController, self).Close()
    276         on_skin_state_set.disconnect(self._OnSkinStateSet)
    277         on_skin_state_reapplied.disconnect(self._OnSkinStateReapplied)
    278 
    279     def Reset(self, hullTypeID):
    280         super(ShipInfoSkinPanelController, self).Reset(hullTypeID)
    281         self._applied = self.GetAppliedSkin(self.itemID, hullTypeID)
    282 
    283     def GetAppliedSkin(self, itemID, hullTypeID):
    284         return self._adapter.GetAppliedSkin(itemID, hullTypeID, self.ownerID)
    285 
    286     def PickSkin(self, skin, deselectIfSame = True):
    287         itemID = self.itemID
    288         typeID = self.typeID
    289         if not itemID or self.ownerID != session.charid:
    290             super(ShipInfoSkinPanelController, self).PickSkin(skin, deselectIfSame)
    291             return
    292         with self._lock:
    293             if skin is not None and skin not in self.skins:
    294                 raise SkinNotAvailableForType('%s not found in %s' % (skin, self.skins))
    295             if skin is None:
    296                 self._ResetPick(itemID, typeID)
    297             elif skin.licensed and not self.IsSkinAccessRestricted() and not self.IsDisabledDueToDamage():
    298                 if self.GetTimeUntilNextAllowedSkinChange():
    299                     raise UserError('CustomNotify', {'notify': GetByLabel('UI/Skins/SkinChangeUnderway')})
    300                 self._PickLicensedSkin(skin, itemID, typeID)
    301             else:
    302                 self._PickUnlicensedSkin(skin)
    303 
    304     def SetPreviewed(self, skin):
    305         self._previewed = skin
    306 
    307     def _ResetPick(self, itemID, hullTypeID):
    308         if all((s is None for s in (self._applied, self._pending, self._previewed))):
    309             return
    310         self._applied = None
    311         self._pending = None
    312         self._previewed = None
    313         self._adapter.ApplySkin(self, itemID, hullTypeID, None)
    314         self.onChange()
    315 
    316     def _PickUnlicensedSkin(self, skin):
    317         if self._previewed == skin:
    318             self._previewed = None
    319         else:
    320             self._previewed = skin
    321         self.onChange()
    322 
    323     def _PickLicensedSkin(self, skin, itemID, typeID):
    324         if self._applied == skin or self._pending == skin:
    325             skin = None
    326         self._pending = skin
    327         self._applied = None
    328         if skin is not None:
    329             self._previewed = None
    330         self._adapter.ApplySkin(self, itemID, typeID, skin)
    331         self.onChange()
    332         on_skin_selected(skin)
    333 
    334     def _OnSkinStateSet(self, itemID, skinState):
    335         if itemID != self.itemID:
    336             return
    337         with self._lock:
    338             if skinState is None and self._applied is None:
    339                 return
    340             if skinState is None or skinState.skin_type == ShipSkinType.NO_SKIN:
    341                 skin = None
    342             else:
    343                 skin = self._GetSkinByID(skinState.skin_data.skin_id)
    344             if self._applied == skin:
    345                 return
    346             if self._pending and self._pending == skin:
    347                 self._pending = None
    348             self._applied = skin
    349             self._lastSkinChange = gametime.GetWallclockTime()
    350             sm.GetService('cosmeticsSvc').lastSkinChange = self._lastSkinChange
    351             self.onChange()
    352 
    353     def _OnSkinStateReapplied(self, itemID):
    354         skin_state = sm.GetService('cosmeticsSvc').GetCachedAppliedSkinState(session.charid, itemID)
    355         if skin_state:
    356             self._OnSkinStateSet(itemID, skin_state)
    357 
    358 
    359 class SkinNotAvailableForType(Exception):
    360     pass
    361 
    362 
    363 class FittingSkinPanelController(SkinPanelController):
    364     __notifyevents__ = SkinPanelController.__notifyevents__ + ['OnSkinLicenseRemoved']
    365 
    366     def __init__(self, fitting, adapter = None):
    367         self._fitting = fitting
    368         super(FittingSkinPanelController, self).__init__(hullTypeID=fitting.typeID, adapter=adapter)
    369         self._UpdateFittingMaterial()
    370         self.onChange.connect(self._UpdateFittingMaterial)
    371         on_skin_state_set.connect(self._OnSkinStateSet)
    372         on_skin_state_reapplied.connect(self._OnSkinStateReapplied)
    373         self._fitting.on_new_itemID.connect(self.OnNewItemID)
    374 
    375     @property
    376     def itemID(self):
    377         return self._itemID
    378 
    379     @property
    380     def isStructureSkin(self):
    381         return self._isStructureSkin
    382 
    383     def Reset(self, hullTypeID):
    384         super(FittingSkinPanelController, self).Reset(hullTypeID)
    385         self._itemID = self._fitting.itemID
    386         self._applied = self.GetAppliedSkin(self._itemID, hullTypeID)
    387         self._isStructureSkin = evetypes.GetCategoryID(hullTypeID) == const.categoryStructure
    388         if self.isStructureSkin:
    389             self._forcedDelayInSec = SKIN_DELAY_STRUCTURES
    390 
    391     def GetAppliedSkin(self, itemID, hullTypeID):
    392         ownerID = self.GetOwnerID()
    393         return self._adapter.GetAppliedSkin(itemID, hullTypeID, ownerID)
    394 
    395     def PickSkin(self, skin):
    396         itemID = self.itemID
    397         typeID = self.typeID
    398         with self._lock:
    399             if skin is not None and skin not in self.skins:
    400                 raise SkinNotAvailableForType('%s not found in %s' % (skin, self.skins))
    401             if skin is None:
    402                 self._ResetPick(itemID, typeID)
    403             elif skin.licensed and not self.IsSkinAccessRestricted() and not self.IsDisabledDueToDamage():
    404                 if self.GetTimeUntilNextAllowedSkinChange():
    405                     raise UserError('CustomNotify', {'notify': GetByLabel('UI/Skins/SkinChangeUnderway')})
    406                 self._PickLicensedSkin(skin, itemID, typeID)
    407             else:
    408                 self._PickUnlicensedSkin(skin)
    409 
    410     def _ResetPick(self, itemID, hullTypeID):
    411         if all((s is None for s in (self._applied, self._pending, self._previewed))):
    412             return
    413         self._applied = None
    414         self._pending = None
    415         self._previewed = None
    416         self._adapter.ApplySkin(self, itemID, hullTypeID, None)
    417         self.onChange()
    418 
    419     def _PickLicensedSkin(self, skin, itemID, typeID):
    420         if self._applied == skin or self._pending == skin:
    421             skin = None
    422         self._pending = skin
    423         self._applied = None
    424         if skin is not None:
    425             self._previewed = None
    426         self._adapter.ApplySkin(self, itemID, typeID, skin)
    427         self.onChange()
    428         on_skin_selected(skin)
    429 
    430     def _PickUnlicensedSkin(self, skin):
    431         if self._previewed == skin:
    432             self._previewed = None
    433         else:
    434             self._previewed = skin
    435         self.onChange()
    436 
    437     def _OnSkinStateSet(self, itemID, skinState):
    438         if itemID != self.itemID:
    439             return
    440         with self._lock:
    441             if skinState is None and self._applied is None:
    442                 return
    443             if skinState is None or skinState.skin_type == ShipSkinType.NO_SKIN:
    444                 skin = None
    445             else:
    446                 skin = self._GetSkinByID(skinState.skin_data.skin_id)
    447             if self._applied == skin:
    448                 return
    449             if self._pending and self._pending == skin:
    450                 self._pending = None
    451             self._applied = skin
    452             self._lastSkinChange = gametime.GetWallclockTime()
    453             sm.GetService('cosmeticsSvc').lastSkinChange = self._lastSkinChange
    454             self.onChange()
    455 
    456     def _OnSkinStateReapplied(self, itemID):
    457         skin_state = sm.GetService('cosmeticsSvc').GetCachedAppliedSkinState(session.charid, itemID)
    458         if skin_state:
    459             self._OnSkinStateSet(itemID, skin_state)
    460 
    461     def OnNewItemID(self, *args):
    462         self.typeID = self._fitting.typeID
    463 
    464     def OnApplySkinFailed(self, itemID, skin, hullTypeID):
    465         if itemID != self.itemID:
    466             return
    467         with self._lock:
    468             if self._pending == skin:
    469                 self._pending = None
    470                 self._applied = self.GetAppliedSkin(itemID, hullTypeID)
    471                 self.onChange()
    472 
    473     def _UpdateActivatedSkin(self, skinID):
    474         if self._applied is not None and self._applied.skinID == skinID:
    475             self._applied = None
    476         if self._pending is not None and self._pending.skinID == skinID:
    477             self._pending = None
    478         if self._previewed is not None:
    479             try:
    480                 skin = self._GetSkinByID(skinID)
    481                 if self._previewed == skin:
    482                     self._previewed = None
    483             except StopIteration:
    484                 pass
    485 
    486     def _UpdateFittingMaterial(self):
    487         if self._previewed:
    488             skin = self._previewed
    489         elif self._pending:
    490             skin = self._pending
    491         elif self._applied:
    492             skin = self._applied
    493         else:
    494             skin = None
    495         self._fitting.SetDisplayedSkin(skin)
    496 
    497     def OnSkinLicenseRemoved(self, skinID, itemID, typeID):
    498         with self._lock:
    499             if self.itemID != itemID:
    500                 return
    501             types = self._adapter.GetTypesForSkin(skinID)
    502             if self._typeID not in types:
    503                 return
    504             self._skins = None
    505             self.onSkinsChange()
    506             self._ResetPick(self.itemID, typeID)
    507 
    508     def IsSkinAccessRestricted(self):
    509         ownerID = self.GetOwnerID()
    510         if ownerID not in (session.charid, session.corpid):
    511             return True
    512         return False
    513 
    514     def GetOwnerID(self):
    515         if self.itemID:
    516             dogmaItem = self._fitting.dogmaItem
    517             if dogmaItem:
    518                 return dogmaItem.ownerID
    519 
    520     def IsDisabledDueToDamage(self):
    521         return self._IsDamagedStructure()
    522 
    523     def _IsDamagedStructure(self):
    524         if not self.isStructureSkin:
    525             return False
    526         if not self.itemID or self.itemID != session.shipid:
    527             return False
    528         ballpark = sm.GetService('michelle').GetBallpark()
    529         if not ballpark:
    530             return False
    531         slimItem = ballpark.GetInvItem(self.itemID)
    532         if slimItem and slimItem.state != STATE_SHIELD_VULNERABLE:
    533             return True
    534         return False
    535 
    536     def Close(self):
    537         with ExceptionEater('FittingSkinPanelController:Closing '):
    538             self._fitting.on_new_itemID.disconnect(self.OnNewItemID)
    539             self._fitting = None
    540         on_skin_state_set.disconnect(self._OnSkinStateSet)
    541         on_skin_state_reapplied.disconnect(self._OnSkinStateReapplied)
    542         SkinPanelController.Close(self)
    543 
    544 
    545 def GetSkinnedShipModel(skin, typeID, multiHullTypeIDList = None):
    546     try:
    547         if skin and skin.skin_type == ShipSkinType.THIRD_PARTY_SKIN:
    548             return GetSkinnedThirdPartyModel(skin, typeID)
    549         return GetSkinnedFirstPartyModel(skin, typeID, multiHullTypeIDList)
    550     except Exception as e:
    551         LogException(str(e))
    552         return None
    553 
    554 
    555 def GetSkinnedFirstPartyModel(skin, typeID, multiHullTypeIDList = None):
    556     skinMaterialSetID = None
    557     if skin and skin.skin_type == ShipSkinType.FIRST_PARTY_SKIN:
    558         skinMaterialSetID = getattr(skin, 'materialSetID', None)
    559         if not skinMaterialSetID:
    560             skin_data = getattr(skin, 'skin_data', None)
    561             if skin_data:
    562                 skinMaterialSetID = sm.GetService('cosmeticsSvc').GetFirstPartySkinMaterialSetID(skin_data.skin_id)
    563     dna = BuildSOFDNAFromTypeID(typeID, materialSetID=skinMaterialSetID, multiHullTypeIDList=multiHullTypeIDList)
    564     return GetSofService().spaceObjectFactory.BuildFromDNA(dna)
    565 
    566 
    567 def GetSkinnedThirdPartyModel(skin, typeID):
    568     sofDNA = CosmeticsManager.CreateSOFDNAfromSkinState(skin, typeID)
    569     model = GetSofService().spaceObjectFactory.BuildFromDNA(sofDNA)
    570     CosmeticsManager.UpdatePatternProjectionParametersFromSkinState(skin, model, typeID)
    571     blend_mode = skin.skin_data.slot_layout.pattern_blend_mode
    572     if blend_mode is not None:
    573         CosmeticsManager.SetBlendMode(model, blendMode=blend_mode)
    574     return model
    575 
    576 
    577 def GetMultiHullTypeIDList(typeID, itemID, dogmaLocation):
    578     if IsModularShip(typeID) and itemID and dogmaLocation:
    579         multiHullTypeIDList = GetSubSystemTypeIDsForDogmaLocation(itemID, typeID, dogmaLocation)
    580         if len(multiHullTypeIDList or []) < len(invConst.subsystemSlotFlags):
    581             return
    582     else:
    583         multiHullTypeIDList = None
    584     return multiHullTypeIDList