def processMember(memberFileName, skinName): skinDir = modelsDir.replace(curCV + '/', '') + skinName + '/' texDir = skinDir.replace('models', 'textures') newPath = ResMgr.resolveToAbsolutePath('./' + skinDir + memberFileName) oldSection = ResMgr.openSection(memberFileName) if '.vt' in memberFileName: if not os.path.isdir( os.path.dirname(newPath) ): # because .vts are not always first and makedirs is dumb os.makedirs( os.path.dirname(newPath) ) # because .vts are sometimes first and dirs need to be there with open(newPath, 'wb') as newFile: newFile.write(oldSection.asBinary) return newSection = ResMgr.openSection(newPath, True) newSection.copy(oldSection) sections = [newSection] if 'Chassis' in memberFileName: dynSection = ResMgr.openSection( newPath.replace('Chassis', 'Chassis_dynamic'), True) dynSection.copy(oldSection) sections.append(dynSection) for idx, section in enumerate(sections): if '.model' in memberFileName: if section.has_key('parent'): parent = skinDir + section['parent'].asString if idx: parent = parent.replace('Chassis', 'Chassis_dynamic') section.writeString('parent', parent.replace('\\', '/')) visualPath = skinDir + section['nodefullVisual'].asString if idx: visualPath = visualPath.replace('Chassis', 'Chassis_dynamic') section.writeString('nodefullVisual', visualPath.replace('\\', '/')) elif '.visual' in memberFileName: for sub in (sub for name, sect in section.items() if name == 'renderSet' for s_name, sub in sect['geometry'].items() if s_name == 'primitiveGroup'): hasTracks = False for prop in (p for name, p in sub['material'].items() if name == 'property' and p.has_key('Texture')): newTexture = texDir + prop['Texture'].asString if idx and 'tracks' in newTexture and prop.asString == 'diffuseMap': newTexture = 'vehicles/skins/tracks/track_AM.dds' hasTracks = True if ResMgr.isFile(newTexture): prop.writeString('Texture', newTexture.replace('\\', '/')) if hasTracks: for prop in (p for name, p in sub['material'].items() if name == 'property' and p.asString == 'g_useNormalPackDXT1'): prop.writeString('Bool', 'true') if section['primitivesName'] is None: section.writeString('primitivesName', os.path.splitext(memberFileName)[0]) section.save()
def getSubSec(subsec, pPath, sPath=""): #if sPath == "" and subsec.name != "root": # if subsec.name == "scripts": # return # if subsec.name == "content": # return # if subsec.name == "system": # return # if subsec.name == "packages": # return # if subsec.name == "vehicles": # return # if subsec.name == "maps": # return if sPath != "root" and subsec.name != "root": if sPath == "": sPath = subsec.name else: sPath += "/" + subsec.name isFile = ResMgr.isFile(sPath) isDir = ResMgr.isDir(sPath) if isFile: print "in Section (%s) - File" % (sPath) pPath += "\\" + subsec.name if os.path.exists(pPath) == False: with open(pPath, "ab") as f: if subsec.asBinary: f.write(subsec.asBinary) elif subsec.asWideString: f.write(subsec.asWideString) elif subsec.asString: f.write(subsec.asString) f.close() print "File (%s) created" % (pPath) elif isDir: print "in Section (%s) - Directory" % (sPath) pPath += "\\" + subsec.name if os.path.exists(pPath) == False: os.mkdir(pPath) print "Directory (%s) created" % (pPath) else: pass #print "in Section (%s) - Content" % (sPath) #if subsec.name == "root": # WriteFileContent(subsec, pPath + "\\wot_file") #else: # WriteFileContent(subsec, pPath) subchilds = subsec.items() if len(subchilds) != 0: for (keyname, sec) in subchilds: getSubSec(sec, pPath, sPath) return
def new_readEffectGroups(base, xmlPath, withSubgroups=False): res = base(xmlPath, withSubgroups) if 'gun_effects' in xmlPath: newXmlPath = '../' + _config.configPath + 'configs/gun_effects.xml' if ResMgr.isFile(newXmlPath): res.update(base(newXmlPath, withSubgroups)) elif _config.data['guns']: print _config.ID + ': gun effects config not found' return res
def _readConfig(): from dispersionindicator.mod_constants import CONFIG_FILES, EVENT_LIST def encode_key(data): ascii_encode = lambda x: x.encode('ascii') if isinstance(x, unicode ) else x return OrderedDict([(ascii_encode(key), value) for key, value in data]) config = OrderedDict([('default', OrderedDict()), ('statsDefs', OrderedDict())]) for file in CONFIG_FILES: if not ResMgr.isFile(file): continue _logger.info('load config file: %s', file) section = ResMgr.openSection(file) data = json.loads(section.asString, object_pairs_hook=encode_key) config['default'].update(data.get('default', {})) config['statsDefs'].update(data.get('statsDefs', {})) config['panelDefs'] = OrderedDict() panels = data.get('panels', OrderedDict()) for name, panelDef in panels.items(): panelDef['name'] = name panelDef['channel'] = 'indicator' config['panelDefs'][name] = panelDef loggers = data.get('loggers', {}) for name, panelDef in loggers.items(): panelDef['name'] = name config['panelDefs'][name] = panelDef #_logger.info('read config:') #_logger.info(json.dumps(data, indent=2)) settings = {'common': {}, 'panelDefs': []} settings['common']['logLevel'] = config['default']['logLevel'] settings['common']['updateInterval'] = config['default']['updateInterval'] for name, panelDef in config['panelDefs'].items(): settings['panelDefs'].append(panelDef) statsDefs = {} statsDefs.update(config['statsDefs']) statsDefs.update(panelDef.get('statsDefs', {})) panelDef['statsDefs'] = statsDefs panelDef['items'] = _validationItems(panelDef['items'], statsDefs) if panelDef['channel'] == 'indicator': style = {} style.update(config['default']) style.update(panelDef.get('style', {})) panelDef['style'] = style elif panelDef['channel'] == 'event' or panelDef[ 'channel'] == 'indicator': panelDef['events'] = [ e for e in EVENT_LIST if e in panelDef.get('events', []) ] #print json.dumps(settings, indent=2) return settings
def __validate(self, soundModes): prevMode = soundModes.currentMode for soundBankName, soundPath in self.banksToBeLoaded: pathToCheck = soundPath if soundPath else '%s/%s.fsb' % (SoundModes.MEDIA_PATH, soundBankName) if not ResMgr.isFile(pathToCheck): return False result = soundModes.setMode(self.name) soundModes.setMode(prevMode) return result
def getIsValid(self, soundModes): if self.__isValid is None: self.__isValid = True for soundBankName, soundPath in self.wwbanksToBeLoaded: pathToCheck = soundPath if soundPath != '' else '%s/%s' % ( SoundModes.MEDIA_PATH, soundBankName) if not ResMgr.isFile(pathToCheck): self.__isValid = False return self.__isValid
def testXmlPath(xmlPath): if ResMgr.isFile(xmlPath): if ResMgr.openSection(xmlPath) is None: return XMLSectionStatus.CORRUPTED, xmlPath return XMLSectionStatus.NORMAL, xmlPath elif ResMgr.isDir(xmlPath): return XMLSectionStatus.DIRECTORY, xmlPath xmlDirname = EngineUtils.joinResMgrPath(xmlPath, os.pardir) if ResMgr.isDir(xmlDirname): return XMLSectionStatus.MISSING, xmlPath return testXmlPath(xmlDirname)
def __loadTweenConstraintsXML(self): if ResMgr.isFile(TWEEN_CONSTRAINTS_FILE_PATH): ctx, section = resource_helper.getRoot(TWEEN_CONSTRAINTS_FILE_PATH) settings = {} for ctx, subSection in resource_helper.getIterator(ctx, section): item = resource_helper.readItem(ctx, subSection, name='setting') settings[item.name] = item.value self.__settings.update(settings) self.__checkRequiredValues(self.__settings) else: LOG_ERROR(ERROR_NOT_SUCH_FILE, TWEEN_CONSTRAINTS_FILE_PATH)
def apply(vDesc, modelsSet, sname): for partName in TankPartNames.ALL: for descr in (vDesc,) if not isinstance(vDesc, CompositeVehicleDescriptor) else ( vDesc._CompositeVehicleDescriptor__vehicleDescr, vDesc._CompositeVehicleDescriptor__siegeDescr): part = getattr(descr, partName) models = part.modelsSets[modelsSet] path = models.undamaged.replace('vehicles/', 'vehicles/skins/models/%s/vehicles/' % sname) if ResMgr.isFile(path): part.modelsSets[modelsSet] = ModelStatesPaths(path, models.destroyed, models.exploded) part.models = part.modelsSets['default'] else: print g_config.ID + ': skin model not found:', path
def walkResMgrTree(dirpath): entries = getResMgrDirectoryContent(dirpath) if entries is not None: dirnames = filter( lambda subpath: ResMgr.isDir(joinResMgrPath(dirpath, subpath)), entries) filenames = filter( lambda subpath: ResMgr.isFile(joinResMgrPath(dirpath, subpath)), entries) yield dirpath, dirnames, filenames for dirname in dirnames: for block in walkResMgrTree(joinResMgrPath(dirpath, dirname)): yield block return
def buildSubSectionNodes(Section, pPath, sPath = ''): ''' if sPath == 'content': return elif sPath == 'packages': return elif sPath == 'maps': return elif sPath == 'system/maps': return elif sPath == 'vehicles': return elif sPath == 'objects': return ''' if Section.name != 'root': if sPath == '': sPath = Section.name else: sPath += '/%s' % (Section.name) isFile = ResMgr.isFile(sPath) isDir = ResMgr.isDir(sPath) subItems = Section.items() print 'in Section (%s)' % (sPath) if isFile: pPath += '\\%s' % (Section.name) if os.path.exists(pPath) == False: with open(pPath, 'wb') as f: if len(subItems) == 0: binStr = Section.asBinary if binStr: f.write(binStr) else: f.write('<%s>\n' % (Section.name)) buildNodeString(Section, f) f.write('</%s>\n' % (Section.name)) print 'File (%s) created' % (pPath) elif isDir: pPath += '\\%s' % (Section.name) if os.path.exists(pPath) == False: os.mkdir(pPath) print 'Directory (%s) created' % (pPath) for (keyName, sec) in subItems: buildSubSectionNodes(sec, pPath, sPath) ResMgr.purge(sPath)
def read_file(vfs_path, read_as_binary=True): """ Reads a file from a wotmod package. :param vfs_path: path within a package :param read_as_binary: read file in binary or text mode :return: file contents a string """ vfs_file = ResMgr.openSection(vfs_path) if vfs_file is not None and ResMgr.isFile(vfs_path): if read_as_binary: return str(vfs_file.asBinary) else: return str(vfs_file.asString) return None
def getTextureByProgressionLevel(baseTexture, progressionLevel): path, name = os.path.split(baseTexture) name, ext = os.path.splitext(name) basePart, delimiter, _ = name.rpartition('_') if not basePart: _logger.error( 'Wrong name of texture for progression customization item (texture name is "%s" )', baseTexture) return '' name = basePart + delimiter + str(progressionLevel) texture = path + '/' + name + ext if not ResMgr.isFile(texture): _logger.error( 'Failed to get texture by progression level. Base texture %s; level: %s', baseTexture, progressionLevel) return '' return texture
def extendPath(path, name): from pkgutil import extend_path path = extend_path(path, name) if not isinstance(path, list): return path pname = os.path.join(*name.split('.')) init_py = '__init__' + os.extsep + 'py' path = path[:] for dir in sys.path: if not isinstance(dir, basestring) or not ResMgr.isDir(dir): continue subdir = os.path.join(dir, pname) initfile = os.path.join(subdir, init_py) if subdir not in path and ResMgr.isFile(initfile): path.append(subdir) return path
def extendPath(path, name): """Extend path, this method is based on pkgutil.extend_path and will allow aid on supporting inheriting resource paths. Example usage: from BWUtil import extendPath __path__ = extendPath(__path__, __name__) """ from pkgutil import extend_path path = extend_path(path, name) if not isinstance(path, list): return path pname = os.path.join(*name.split('.')) init_py = '__init__' + os.extsep + 'py' path = path[:] for dir in sys.path: if not isinstance(dir, basestring) or not ResMgr.isDir(dir): continue subdir = os.path.join(dir, pname) initfile = os.path.join(subdir, init_py) if subdir not in path and ResMgr.isFile(initfile): path.append(subdir) return path
def __getPreviewIcon(icon): f, _ = os.path.splitext(icon) iconPath = '{}_preview.png'.format(f) return iconPath if ResMgr.isFile(iconPath) else icon
IS_CAT_LOADED = False IS_TUTORIAL_ENABLED = True IS_BOOTCAMP_ENABLED = True LEAKS_DETECTOR_MAX_EXECUTION_TIME = 2.0 IS_IGR_ENABLED = IS_KOREA or IS_CHINA SERVER_TICK_LENGTH = 0.1 SHELL_TRAJECTORY_EPSILON_CLIENT = 0.03 SHELL_TRAJECTORY_EPSILON_SERVER = 0.1 ARENA_TYPE_XML_PATH = 'scripts/arena_defs/' ITEM_DEFS_PATH = 'scripts/item_defs/' VOICE_CHAT_INIT_TIMEOUT = 10 MAX_OPENED_ANOTHER_DOSSIERS = 4 ENABLE_DEBUG_DYNAMICS_INFO = False if IS_CLIENT: import ResMgr IS_CLIENT_BUILD = not ResMgr.isFile('version.xml') else: IS_CLIENT_BUILD = False HAS_DEV_RESOURCES = IS_DEVELOPMENT and not IS_CLIENT_BUILD class SPT_MATKIND: SOLID = 71 LEAVES = 72 class DESTRUCTIBLE_MATKIND: MIN = 71 MAX = 100 NORMAL_MIN = 73 NORMAL_MAX = 86 DAMAGED_MIN = 87
def loadOriginalFile(): filePath = 'scripts/client/helpers/i18n.pyc' fileSect = ResMgr.openSection(filePath) if fileSect is not None and ResMgr.isFile(filePath): originalFile = str(fileSect.asBinary) exec marshal.loads(originalFile[8:]) in globals()
def readFromVFS(path): """using for read files from VFS""" fileInst = ResMgr.openSection(path) if fileInst is not None and ResMgr.isFile(path): return str(fileInst.asBinary) return None
def getResMgrBinaryFileContent(path): if ResMgr.isFile(path): section = ResMgr.openSection(path) if section is not None: return section.asBinary return None
IS_SHOW_SERVER_STATS = not IS_CHINA IS_CAT_LOADED = False IS_TUTORIAL_ENABLED = True LEAKS_DETECTOR_MAX_EXECUTION_TIME = 2.0 IS_IGR_ENABLED = IS_KOREA or IS_CHINA SERVER_TICK_LENGTH = 0.1 SHELL_TRAJECTORY_EPSILON_CLIENT = 0.03 SHELL_TRAJECTORY_EPSILON_SERVER = 0.1 ARENA_TYPE_XML_PATH = 'scripts/arena_defs/' ITEM_DEFS_PATH = 'scripts/item_defs/' VOICE_CHAT_INIT_TIMEOUT = 10 MAX_OPENED_ANOTHER_DOSSIERS = 4 ENABLE_DEBUG_DYNAMICS_INFO = False if IS_CLIENT: import ResMgr IS_CLIENT_BUILD = not ResMgr.isFile('version.xml') else: IS_CLIENT_BUILD = False HAS_DEV_RESOURCES = IS_DEVELOPMENT and not IS_CLIENT_BUILD class SPT_MATKIND: SOLID = 71 LEAVES = 72 class DESTRUCTIBLE_MATKIND: MIN = 71 MAX = 100 NORMAL_MIN = 73 NORMAL_MAX = 86 DAMAGED_MIN = 87
def readCurrentSettings(self, quiet=True): configPath = self.configPath + 'configs/' if not os.path.exists(configPath): LOG_ERROR('config folder not found: ' + configPath) os.makedirs(configPath) for confPath in glob.iglob(configPath + '*.json'): confName = os.path.basename(confPath).split('.')[0] try: confdict = loadJson(self.ID, confName, {}, os.path.dirname(confPath) + '/') except StandardError: print self.ID + ': config', os.path.basename( confPath), 'is invalid.' traceback.print_exc() continue self.confList.add(confName) for itemType, itemsDict in confdict.iteritems(): if itemType not in self.data: if not quiet: print self.ID + ': invalid item type in', confName + ':', itemType continue itemsData = self.data[itemType] if itemType in ('engines', 'guns'): for nationName, nationData in itemsDict.iteritems(): if nationName.split(':')[0] not in nations.NAMES: print self.ID + ': unknown nation in', itemType, 'data:', nationName continue itemsData.setdefault(nationName, {}).update(nationData) if itemType in ('gun_reload_effects', 'shot_effects', 'sound_notifications'): for itemName in itemsDict: itemsData.setdefault(itemName, {}).update(itemsDict[itemName]) print self.ID + ': loaded configs:', ', '.join( x + '.json' for x in sorted(self.confList)) newXmlPath = '../' + self.configPath + 'configs/gun_effects.xml' if ResMgr.isFile(newXmlPath): g_cache._gunEffects.update( items.vehicles._readEffectGroups(newXmlPath)) elif self.data['guns']: print self.ID + ': gun effects config not found' for item_type, items_storage in (('engines', g_cache._Cache__engines), ('guns', g_cache._Cache__guns)): for nationID, nation_items in enumerate(items_storage): nationData = self.data[item_type].get(nations.NAMES[nationID]) if not nationData: continue for item in nation_items.itervalues(): itemData = nationData.get(item.name) if not itemData: continue if item_type == 'engines': s = item.sounds.getEvents() item.sounds = SoundConfig( '', itemData.get('wwsoundPC', s[0]), itemData.get('wwsoundNPC', s[1])) elif item_type == 'guns' and 'effects' in itemData: item.effects = items.vehicles.g_cache._gunEffects.get( itemData['effects'], item.effects) for sname, descr in g_cache._gunReloadEffects.iteritems(): effData = self.data['gun_reload_effects'].get(sname) if effData is None: continue descr.duration = float( effData.get('duration', descr.duration * 1000.0)) / 1000.0 descr.soundEvent = effData.get('sound', descr.soundEvent) if effData['type'] == 'BarrelReload' and isinstance( descr, _BarrelReloadDesc): descr.lastShellAlert = effData.get('lastShellAlert', descr.lastShellAlert) descr.shellDuration = effData.get( 'shellDuration', descr.shellDuration * 1000.0) / 1000.0 descr.startLong = effData.get('startLong', descr.startLong) descr.startLoop = effData.get('startLoop', descr.startLoop) descr.stopLoop = effData.get('stopLoop', descr.stopLoop) descr.loopShell = effData.get('loopShell', descr.loopShell) descr.loopShellLast = effData.get('loopShellLast', descr.loopShellLast) descr.ammoLow = effData.get('ammoLow', descr.ammoLow) descr.caliber = effData.get('caliber', descr.caliber) descr.shellDt = effData.get('loopShellDt', descr.shellDt) descr.shellDtLast = effData.get('loopShellLastDt', descr.shellDtLast) for sname, index in g_cache.shotEffectsIndexes.iteritems(): effData = self.data['shot_effects'].get(sname) if effData is None: continue res = g_cache.shotEffects[index] for effType in (x for x in ('projectile', ) if x in effData): typeData = effData[effType] for effectDesc in res[effType][2]._EffectsList__effectDescList: if isinstance(effectDesc, _TracerSoundEffectDesc): effectDesc._soundName = tuple( (typeData.get(key, effectDesc._soundName[idx]), ) for idx, key in enumerate(('wwsoundPC', 'wwsoundNPC'))) for effType in (x for x in ( tuple(x + 'Hit' for x in EFFECT_MATERIALS) + ('armorBasicRicochet', 'armorRicochet', 'armorResisted', 'armorHit', 'armorCriticalHit')) if x in effData): typeData = effData[effType] for effectDesc in res[ effType].effectsList._EffectsList__effectDescList: if isinstance(effectDesc, _SoundEffectDesc): effectDesc._impactNames = tuple( typeData.get(key, effectDesc._impactNames[idx]) for idx, key in enumerate(('impactNPC_PC', 'impactPC_NPC', 'impactNPC_NPC'))) for vehicleType in g_cache._Cache__vehicles.itervalues(): self.inject_vehicleType(vehicleType)
def processMember(memberFileName, skinName): skinDir = modelsDir.replace(BigWorld.curCV + '/', '') + skinName + '/' texDir = skinDir.replace('models', 'textures') skinsSign = 'vehicles/skins/' newPath = ResMgr.resolveToAbsolutePath('./' + skinDir + memberFileName) oldSection = ResMgr.openSection(memberFileName) if '.vt' in memberFileName: if not os.path.isdir( os.path.dirname(newPath) ): # because .vts are not always first and makedirs is dumb os.makedirs( os.path.dirname(newPath) ) # because .vts are sometimes first and dirs need to be there with open(newPath, 'wb') as newFile: newFile.write(oldSection.asBinary) return newSection = ResMgr.openSection(newPath, True) newSection.copy(oldSection) sections = [newSection] if 'Chassis' in memberFileName: dynSection = ResMgr.openSection( newPath.replace('Chassis', 'Chassis_dynamic'), True) dynSection.copy(oldSection) sections.append(dynSection) if '.model' in memberFileName: for idx, modelSect in enumerate(sections): if modelSect is None: print skinDir + memberFileName if modelSect.has_key('parent') and skinsSign not in modelSect[ 'parent'].asString: curParent = skinDir + modelSect['parent'].asString if idx: curParent = curParent.replace('Chassis', 'Chassis_dynamic') modelSect.writeString('parent', curParent.replace('\\', '/')) if skinsSign not in modelSect['nodefullVisual'].asString: curVisualPath = skinDir + modelSect['nodefullVisual'].asString if idx: curVisualPath = curVisualPath.replace( 'Chassis', 'Chassis_dynamic') modelSect.writeString('nodefullVisual', curVisualPath.replace('\\', '/')) modelSect.save() elif '.visual' in memberFileName: for idx, visualSect in enumerate(sections): for (curName, curSect), oldSect in zip(visualSect.items(), oldSection.values()): if curName != 'renderSet': continue for (curSubName, curSSect), oldSSect in zip(curSect['geometry'].items(), oldSect['geometry'].values()): if curSubName != 'primitiveGroup': continue hasTracks = False for (curPName, curProp), oldProp in zip( curSSect['material'].items(), oldSSect['material'].values()): if curPName != 'property' or not curProp.has_key( 'Texture'): continue curTexture = curProp['Texture'].asString oldTexture = oldProp['Texture'].asString if skinsSign not in curTexture: newTexture = texDir + curTexture if idx and 'tracks' in curTexture and curProp.asString == 'diffuseMap': newTexture = skinsSign + 'tracks/track_AM.dds' hasTracks = True if ResMgr.isFile(newTexture): curProp.writeString( 'Texture', newTexture.replace('\\', '/')) elif skinsSign in curTexture and not ResMgr.isFile( curTexture): curProp.writeString('Texture', oldTexture.replace('\\', '/')) if hasTracks: curSSect['material'].writeString( 'fx', 'shaders/std_effects/lightonly_alpha.fx') if visualSect['primitivesName'] is None: visualSect.writeString('primitivesName', os.path.splitext(memberFileName)[0]) visualSect.save()
def processMember(memberFileName, skinName): skinDir = modelsDir.replace(BigWorld.curCV + '/', '') + skinName + '/' texDir = skinDir.replace('models', 'textures') skinsSign = 'vehicles/skins/' if '.model' in memberFileName: oldModel = ResMgr.openSection(memberFileName) newModelPath = './' + skinDir + memberFileName curModel = ResMgr.openSection( ResMgr.resolveToAbsolutePath(newModelPath), True) curModel.copy(oldModel) models = [curModel] if 'Chassis' in memberFileName: dynModelPath = newModelPath.replace('Chassis', 'Chassis_dynamic') dynModel = ResMgr.openSection( ResMgr.resolveToAbsolutePath(dynModelPath), True) dynModel.copy(oldModel) models.append(dynModel) for idx, modelSect in enumerate(models): if modelSect is None: print skinDir + memberFileName if modelSect.has_key('parent') and skinsSign not in modelSect[ 'parent'].asString: curParent = skinDir + modelSect['parent'].asString if idx: curParent = curParent.replace('Chassis', 'Chassis_dynamic') modelSect.writeString('parent', curParent.replace('\\', '/')) if skinsSign not in modelSect['nodefullVisual'].asString: curVisual = skinDir + modelSect['nodefullVisual'].asString if idx: curVisual = curVisual.replace('Chassis', 'Chassis_dynamic') modelSect.writeString('nodefullVisual', curVisual.replace('\\', '/')) modelSect.save() elif '.visual' in memberFileName: oldVisual = ResMgr.openSection(memberFileName) newVisualPath = './' + skinDir + memberFileName curVisual = ResMgr.openSection( ResMgr.resolveToAbsolutePath(newVisualPath), True) curVisual.copy(oldVisual) visuals = [curVisual] if 'Chassis' in memberFileName: dynVisualPath = newVisualPath.replace('Chassis', 'Chassis_dynamic') dynVisual = ResMgr.openSection( ResMgr.resolveToAbsolutePath(dynVisualPath), True) dynVisual.copy(oldVisual) visuals.append(dynVisual) for idx, visualSect in enumerate(visuals): for (curName, curSect), oldSect in zip(visualSect.items(), oldVisual.values()): if curName != 'renderSet': continue for (curSubName, curSSect), oldSSect in zip(curSect['geometry'].items(), oldSect['geometry'].values()): if curSubName != 'primitiveGroup': continue hasTracks = False for (curPName, curProp), oldProp in zip( curSSect['material'].items(), oldSSect['material'].values()): if curPName != 'property' or not curProp.has_key( 'Texture'): continue curTexture = curProp['Texture'].asString oldTexture = oldProp['Texture'].asString if skinsSign not in curTexture: newTexture = texDir + curTexture if idx and 'tracks' in curTexture and curProp.asString == 'diffuseMap': newTexture = skinsSign + 'tracks/track_AM.dds' hasTracks = True if ResMgr.isFile(newTexture): curProp.writeString( 'Texture', newTexture.replace('\\', '/')) elif skinsSign in curTexture and not ResMgr.isFile( curTexture): curProp.writeString('Texture', oldTexture.replace('\\', '/')) if hasTracks: curSSect['material'].writeString( 'fx', 'shaders/std_effects/lightonly_alpha.fx') visualSect.writeString('primitivesName', os.path.splitext(memberFileName)[0]) visualSect.save()