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

locatorValidation.py (9591B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\evegraphics\validation\validators\locatorValidation.py
      2 import ctypes
      3 import string
      4 import re
      5 from evegraphics.validation.commonUtilities import Validate, SceneType
      6 from evegraphics.validation.errors import SingleObjectValidationError
      7 from evegraphics.validation.validationFunctions import ListIsNotEmpty, ShouldBeGreaterThanOrEqual
      8 from evegraphics.validation import resources
      9 import geo2
     10 from evegraphics.validation.validators import limits
     11 import trinity
     12 
     13 @Validate('EveSOFDataHull(owner)/.../List[EveSOFDataHullLocator](locators)')
     14 def ValidateTurretLocatorsCount(context, owner, locators):
     15     minTurretLocators = limits.GetValue(owner.category, limits.MIN_TURRET_LOCATOR_COUNT)
     16     if minTurretLocators is None:
     17         return
     18     validTurretSetNames = ['locator_turret_', 'locator_atomic_']
     19     locatorsByName = {locator.name:locator for locator in locators}
     20     turretLocators = set()
     21     for validTurretSetName in validTurretSetNames:
     22         for locatorName, locator in locatorsByName.iteritems():
     23             if locatorName.startswith(validTurretSetName):
     24                 setIdentifier = re.search('%s\\d+' % validTurretSetName, locatorName).group()
     25                 turretLocators.add(setIdentifier)
     26 
     27     if len(turretLocators) < minTurretLocators:
     28         context.Error(locators, 'Too few turret locators, expected to get %d locators, but only found %d: [%s]' % (minTurretLocators, len(turretLocators), ','.join(turretLocators)))
     29 
     30 
     31 @Validate('EveSOFDataHull(owner)/.../List[EveSOFDataHullLocator](locators)')
     32 def ValidateTurretLocatorName(context, owner, locators):
     33     minTurretLocators = limits.GetValue(owner.category, limits.MIN_TURRET_LOCATOR_COUNT)
     34     if minTurretLocators is None:
     35         return
     36     validTurretSetNames = ['locator_turret_', 'locator_atomic_']
     37     locatorsByName = {locator.name:locator for locator in locators}
     38     locatorSetIdentifiers = {setName:[] for setName in validTurretSetNames}
     39     for validTurretSetName in validTurretSetNames:
     40         for locatorName, locator in locatorsByName.iteritems():
     41             if locatorName.startswith(validTurretSetName):
     42                 if not re.match('[a-z]+_[a-z]+_\\d+[a-z]', locatorName):
     43                     context.Error(locator, 'Incorrectly named turret locator')
     44                     continue
     45                 setIndex = int(re.search('\\d+', locatorName.replace(validTurretSetName, '')).group())
     46                 setLetter = re.search('[a-z]+', locatorName.replace(validTurretSetName, '')).group()
     47                 locatorSetIdentifiers[validTurretSetName].append((setIndex, setLetter))
     48 
     49     for turretSetName, identifiers in locatorSetIdentifiers.iteritems():
     50         if len(identifiers) == 1:
     51             context.Error(locators, 'Turret set has only 1 locator. There should be more than 1...')
     52             continue
     53         identifiers.sort()
     54         for index, (turretIndex, turretLetter) in enumerate(identifiers):
     55             currentLocatorName = '%s%d%s' % (turretSetName, turretIndex, turretLetter)
     56             locator = locatorsByName[currentLocatorName]
     57             if index == 0:
     58                 if turretIndex != 1 or turretLetter != 'a':
     59                     context.Error(locator, 'Incorrect name should be %s%d%s' % (turretSetName, 1, 'a'))
     60                 continue
     61             lastIndex, lastLetter = identifiers[index - 1]
     62             lastLocatorName = '%s%d%s' % (turretSetName, lastIndex, lastLetter)
     63             incorrectIndex = turretIndex not in (lastIndex, lastIndex + 1)
     64             incorrectLetter = turretIndex == lastIndex and ord(turretLetter) != ord(lastLetter) + 1
     65             incorrectStartingLetter = turretIndex == lastIndex + 1 and turretLetter != 'a'
     66             if incorrectIndex or incorrectLetter or incorrectStartingLetter:
     67                 context.Error(locator, "Incorrect name when following this locator '%s'" % lastLocatorName)
     68 
     69 
     70 @Validate('EveSOFDataHullLocatorSet')
     71 def ValidateEveSOFDataHullLocatorSet(context, sofLocatorSet):
     72     context.Expect(sofLocatorSet, 'locators', ListIsNotEmpty)
     73 
     74 
     75 def RemoveSofLocatorSets(owner):
     76 
     77     def inner():
     78         owner.locatorSets.removeAt(-1)
     79 
     80     return ('Remove all locator sets from hull', inner, True)
     81 
     82 
     83 @Validate('EveSOFDataHull(owner)/.../List[EveSOFDataHullLocatorSet](sofLocatorSets)')
     84 def StructureSetsShouldNotHaveLocators(context, owner, sofLocatorSets):
     85     if owner.category == 'structure_states' and sofLocatorSets:
     86         context.Error(sofLocatorSets, 'Structure state hulls should not have locators', actions=(RemoveSofLocatorSets(owner),))
     87 
     88 
     89 @Validate('EveSOFDataHull(owner)/.../List[EveSOFDataHullLocatorSet](sofLocatorSets)')
     90 def ValidateListOfEveSOFDataHullLocatorSet(context, owner, sofLocatorSets):
     91     damageLocatorsMin = limits.GetValue(owner.category, limits.DAMAGE_LOCATORS_MIN)
     92     damageLocatorSet = None
     93     for locatorSet in sofLocatorSets:
     94         if locatorSet.name == 'damage':
     95             damageLocatorSet = locatorSet
     96             break
     97 
     98     if damageLocatorSet is None:
     99         if owner.category not in ('structure_states', 'placeholder') and damageLocatorsMin > 0:
    100             context.AddError(SingleObjectValidationError(sofLocatorSets, "has no locatorset called 'damage'"))
    101     elif damageLocatorsMin is not None:
    102         context.ExpectValue(damageLocatorSet, len(damageLocatorSet.locators), ShouldBeGreaterThanOrEqual(damageLocatorsMin), message='number of damage locators should be no less than %s (but is %s)' % (damageLocatorsMin, len(damageLocatorSet.locators)))
    103 
    104 
    105 @Validate('EveSOFDataHull(owner)/.../EveSOFDataHullLocatorSet(sofLocatorSet)')
    106 def ValidateLocatorSetBoneIndices(context, owner, sofLocatorSet):
    107     granny = resources.GetResource(context, owner.geometryResFilePath, resources.ResourceType.GRANNY)
    108     if not granny:
    109         return
    110     count = len(granny.meshes[0].bonebindings)
    111     for locator in sofLocatorSet.locators:
    112         if locator.boneIndex >= count:
    113             context.Error(locator, 'bone index is not valid')
    114 
    115 
    116 @Validate('EveSOFDataHull(owner)/.../EveSOFDataHullLocatorSet(locators)')
    117 def HullLocatorsAreCloseToGeometry(context, owner, locators):
    118     if locators.name not in ('damage', 'explosions'):
    119         return
    120     granny = resources.GetResource(context, owner.geometryResFilePath, resources.ResourceType.GRANNY)
    121     if not granny:
    122         return
    123     fi = ctypes.cast(granny.GetGrannyFileInfo(), ctypes.c_void_p).value
    124     for i, each in enumerate(locators.locators):
    125         direction = geo2.QuaternionTransformVector(each.rotation, (0, 1, 0))
    126         pos = geo2.Vec3Add(each.position, geo2.Vec3Scale(direction, 1))
    127         if not trinity.GrannyRayIntersection(fi, pos, geo2.Vec3Scale(direction, -1), -1, -1):
    128             context.Error(locators, '%s locators not touching geometry' % locators.name)
    129             return
    130 
    131 
    132 _NAME_PATTERNS = (re.compile('locator_turret_(?P<index>\\d+)\\w?'),
    133  re.compile('locator_launcher_(?P<index>\\d+)\\w?'),
    134  re.compile('locator_booster_(?P<index>\\d+)'),
    135  re.compile('locator_audio_booster'),
    136  re.compile('locator_turretm_(?P<index>\\d+)\\w?'),
    137  re.compile('locator_moonharvester_(?P<index>\\d+)\\w?'),
    138  re.compile('locator_xl_(?P<index>\\d+)\\w?'),
    139  re.compile('locator_atomic_(?P<index>\\d+)\\w?'))
    140 _HANGAR_NAME_PATTERNS = (re.compile('Traffic_Start_(?P<index>[123])\\w?'), re.compile('Traffic_End_(?P<index>[123])\\w?'))
    141 _SEQUENCE_PATTERNS = (re.compile('locator_turret_(?P<index>\\d+)\\w?'), re.compile('locator_launcher_(?P<index>\\d+)\\w?'))
    142 
    143 def _GetLocatorName(pattern):
    144     found = pattern.find('(')
    145     if found == -1:
    146         return pattern
    147     return pattern[:found]
    148 
    149 
    150 @Validate('List[EveLocator2]', SceneType)
    151 def ValidateLocatorNamesPrefixes(context, locators):
    152     isHangar = context.GetArgument(SceneType) == SceneType.HANGAR
    153     namePatterns = _NAME_PATTERNS
    154     if isHangar:
    155         namePatterns = _NAME_PATTERNS + _HANGAR_NAME_PATTERNS
    156     for locator in locators:
    157         found = False
    158         for i, pattern in enumerate(namePatterns):
    159             match = pattern.match(locator.name)
    160             if match:
    161                 found = True
    162                 break
    163 
    164         if not found:
    165             context.Error(locator, 'invalid locator name %s' % locator.name)
    166 
    167 
    168 @Validate('List[EveLocator2]')
    169 def ValidateLocatorNamesFormSequence(context, locators):
    170     indices = {}
    171     for locator in locators:
    172         found = False
    173         for i, pattern in enumerate(_SEQUENCE_PATTERNS):
    174             match = pattern.match(locator.name)
    175             if match:
    176                 found = True
    177                 try:
    178                     idx = int(match.group('index'))
    179                 except IndexError:
    180                     break
    181 
    182                 indices.setdefault(i, set()).add(idx)
    183                 break
    184 
    185         if not found:
    186             continue
    187 
    188     for k, v in indices.items():
    189         if min(v) != 1 or max(v) != len(v):
    190             context.Error(locators, 'locator indices %s in names do not form a sequence 1, 2, ...' % _GetLocatorName(_NAME_PATTERNS[k].pattern))
    191 
    192 
    193 @Validate('List[EveLocator2]')
    194 def LocatorsHaveDistinctNames(context, locators):
    195     for each in locators:
    196         occurences = [ x for x in locators if x.name == each.name ]
    197         if len(occurences) != 1:
    198             context.Error(each, 'duplicate locator name %s' % each.name)
    199 
    200 
    201 @Validate('/EveShip2/.../List[EveLocator2]')
    202 def ShipMustHaveAudioBoosterLocator(context, locators):
    203     audio = [ x for x in locators if x.name == 'locator_audio_booster' ]
    204     if not audio:
    205         context.Error(locators, 'ship must have a locator_audio_booster locator')