Add A26 to A27 scripts
This commit is contained in:
parent
675591324c
commit
418b077ea6
38
A26ToA27.py
Normal file
38
A26ToA27.py
Normal file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: python-mode; python-indent-offset: 4; -*-
|
||||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: © 2023 Wildfire Games
|
||||
# SPDX-FileCopyrightText: © 2023 Stanislas Daniel Claude Dolcini
|
||||
|
||||
from A26_A27.ActorsWithMaterialsWithNoSpecMapFixer import ActorsWithMaterialsWithNoSpecMapFixer
|
||||
from A26_A27.P265 import TemplateFixer as RequirementsFixer
|
||||
from A26_A27.P292 import remove_terrain_materials_recursively, remove_actor_materials_recursively
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = ArgumentParser(description='A26 to A27 converter.')
|
||||
parser.add_argument('-r', '--root', action='store', dest='root', default=os.path.dirname(os.path.realpath(__file__)))
|
||||
parser.add_argument('-m', '--mod', action='store', dest='mod', default='public')
|
||||
parser.add_argument('-v', '--verbose', action='store_true', default=False, help="Be verbose.")
|
||||
args = parser.parse_args()
|
||||
script_dir = args.root
|
||||
mod_name = args.mod
|
||||
path = Path(script_dir) / mod_name
|
||||
|
||||
print(f"Running in {path}")
|
||||
print("Fixing rP27245...")
|
||||
template_fixer = RequirementsFixer(path)
|
||||
template_fixer.run()
|
||||
print("Fixing Actors using no specmap (rP27308)...")
|
||||
template_fixer = ActorsWithMaterialsWithNoSpecMapFixer(path)
|
||||
template_fixer.run()
|
||||
print("Fixing actors using old deprecated materials (rP27368)")
|
||||
if os.path.exists(path / 'art' / 'terrains') and os.path.isdir(path / 'art' / 'terrains'):
|
||||
remove_terrain_materials_recursively(path / 'art' / 'terrains')
|
||||
if os.path.exists(path / 'art' / 'actors') and os.path.isdir(path / 'art' / 'actors'):
|
||||
remove_actor_materials_recursively(path / 'art' / 'actors')
|
||||
|
74
A26_A27/ActorsWithMaterialsWithNoSpecMapFixer.py
Normal file
74
A26_A27/ActorsWithMaterialsWithNoSpecMapFixer.py
Normal file
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: python-mode; python-indent-offset: 4; -*-
|
||||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: © 2023 Wildfire Games
|
||||
# SPDX-FileCopyrightText: © 2023 Stanislas Daniel Claude Dolcini
|
||||
|
||||
from utils.fixers.BaseFixer import BaseFixer
|
||||
|
||||
import os
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
class ActorsWithMaterialsWithNoSpecMapFixer(BaseFixer):
|
||||
def __init__(self, vfs_root, verbose=False):
|
||||
BaseFixer.__init__(self, vfs_root, verbose)
|
||||
self.add_files(os.path.join('art', 'actors'), tuple(".xml"))
|
||||
self.changes = [
|
||||
['basic_spec', 'no_trans_spec'],
|
||||
["blend_spec", 'basic_trans_spec'],
|
||||
["objectcolor_spec", 'objectcolor_specmap'],
|
||||
["playercolor_spec", 'player_trans_spec'],
|
||||
]
|
||||
|
||||
def process_actor(self, actorNode):
|
||||
materialCmp = actorNode.find('material')
|
||||
if materialCmp is not None:
|
||||
changed = False
|
||||
|
||||
if (materialCmp.text == 'basic_spec.xml' or
|
||||
materialCmp.text == 'blend_spec.xml' or
|
||||
materialCmp.text == 'objectcolor_spec.xml' or
|
||||
materialCmp.text == 'playercolor_spec.xml'):
|
||||
for group in actorNode:
|
||||
for variant in group:
|
||||
cmpTextures = variant.find('textures')
|
||||
if cmpTextures is not None:
|
||||
|
||||
found = False
|
||||
for texture in cmpTextures:
|
||||
if texture.attrib['name']== 'specTex':
|
||||
found = True
|
||||
break
|
||||
|
||||
if found:
|
||||
continue
|
||||
|
||||
tag = ET.SubElement(cmpTextures, 'texture')
|
||||
tag.attrib['name'] = 'specTex'
|
||||
tag.attrib['file'] = 'null_white.dds'
|
||||
changed = True
|
||||
|
||||
|
||||
for change in self.changes:
|
||||
materialCmp.text = materialCmp.text.replace(change[0], change[1])
|
||||
|
||||
return changed
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
count = 0
|
||||
for file in self.files:
|
||||
tree = ET.parse(file)
|
||||
root = tree.getroot()
|
||||
changed = False
|
||||
if root.tag == 'actor':
|
||||
changed = self.process_actor(root)
|
||||
elif root.tag == 'qualitylevels':
|
||||
for actor in root:
|
||||
changed |= self.process_actor(actor)
|
||||
if changed:
|
||||
self.save_xml_file(tree, root, file, False)
|
||||
count = count + 1
|
||||
|
||||
self.logger.info(f"Fixed {count} file(s).")
|
70
A26_A27/P265.py
Normal file
70
A26_A27/P265.py
Normal file
@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: python-mode; python-indent-offset: 4; -*-
|
||||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: © 2023 Wildfire Games
|
||||
# SPDX-FileCopyrightText: © 2023 Freagarach
|
||||
|
||||
import fileinput
|
||||
import glob
|
||||
import os
|
||||
from lxml import etree as ET
|
||||
|
||||
class StyleFixer:
|
||||
def fix_template_style(template_path):
|
||||
changes = [
|
||||
["version='1.0'", 'version="1.0"'],
|
||||
["'UTF-8'", '"utf-8"']
|
||||
]
|
||||
StyleFixer.sed(template_path, changes)
|
||||
|
||||
def sed(path, changes):
|
||||
for line in fileinput.input(path, inplace=True):
|
||||
for change in changes:
|
||||
line = line.replace(change[0], change[1])
|
||||
print(line, end="")
|
||||
|
||||
class TemplateFixer:
|
||||
def __init__(self, vfs_root):
|
||||
self.template_folder = os.path.join(vfs_root, 'simulation', 'templates')
|
||||
|
||||
def fix_template(self, template_path):
|
||||
tree = ET.parse(template_path)
|
||||
root = tree.getroot()
|
||||
|
||||
changed = False
|
||||
cmp_identity = root.find('Identity')
|
||||
if cmp_identity != None:
|
||||
if self.fix_requirements(cmp_identity):
|
||||
changed = True
|
||||
|
||||
cmp_upgrade = root.find('Upgrade')
|
||||
if cmp_upgrade != None:
|
||||
for upgrade in cmp_upgrade.iterfind("./"):
|
||||
if self.fix_requirements(upgrade):
|
||||
changed = True
|
||||
|
||||
if not changed:
|
||||
return False
|
||||
|
||||
root[:] = sorted(root, key=lambda x: x.tag)
|
||||
ET.indent(tree)
|
||||
|
||||
tree.write(template_path, xml_declaration=True, pretty_print=True, encoding='utf-8')
|
||||
return True
|
||||
|
||||
def fix_requirements(self, cmp):
|
||||
req_tech = cmp.find('RequiredTechnology')
|
||||
if req_tech == None:
|
||||
return False
|
||||
|
||||
ET.SubElement(ET.SubElement(cmp, 'Requirements'), 'Techs').text = req_tech.text
|
||||
|
||||
cmp.remove(req_tech)
|
||||
|
||||
return True
|
||||
|
||||
def run(self):
|
||||
for template in glob.iglob(self.template_folder + '/**/*.xml', recursive=True):
|
||||
if self.fix_template(template):
|
||||
StyleFixer.fix_template_style(template)
|
283
A26_A27/P292.py
Normal file
283
A26_A27/P292.py
Normal file
@ -0,0 +1,283 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: python-mode; python-indent-offset: 4; -*-
|
||||
# SPDX-License-Identifier: MIT
|
||||
# SPDX-FileCopyrightText: © 2023 Wildfire Games
|
||||
# SPDX-FileCopyrightText: © 2023 Vladislav Belov
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
def output_xml_tree(tree, path):
|
||||
with open(path, 'wt') as handle:
|
||||
handle.write('<?xml version="1.0" encoding="utf-8"?>\n')
|
||||
def output_xml_node(node, handle, depth):
|
||||
indent = ' ' * depth
|
||||
attributes = ''
|
||||
for attribute_name in node.attrib.keys():
|
||||
attributes += ' {}="{}"'.format(attribute_name, node.attrib[attribute_name])
|
||||
if len(node) != 0:
|
||||
assert (node.text is None) or (not node.text.strip())
|
||||
handle.write('{}<{}{}>\n'.format(indent, node.tag, attributes))
|
||||
for child in node:
|
||||
output_xml_node(child, handle, depth + 1)
|
||||
handle.write('{}</{}>\n'.format(indent, node.tag))
|
||||
else:
|
||||
if node.text is None:
|
||||
handle.write('{}<{}{}/>\n'.format(indent, node.tag, attributes))
|
||||
else:
|
||||
handle.write('{}<{}{}>{}</{}>\n'.format(indent, node.tag, attributes, node.text, node.tag))
|
||||
output_xml_node(tree.getroot(), handle, 0)
|
||||
|
||||
def remove_terrain_materials(path):
|
||||
with open(path, 'rt') as handle:
|
||||
xml = handle.read()
|
||||
|
||||
terrain_base = 'terrain_base.xml' in xml
|
||||
terrain_norm = 'terrain_norm.xml' in xml
|
||||
terrain_spec = 'terrain_spec.xml' in xml
|
||||
terrain_triplanar = 'terrain_triplanar.xml' in xml
|
||||
|
||||
should_save = terrain_base or terrain_norm or terrain_spec or terrain_triplanar
|
||||
|
||||
assert xml.count('<material>') == 1
|
||||
|
||||
tree = ET.parse(path)
|
||||
root = tree.getroot()
|
||||
for element in root:
|
||||
if len(element) != 0:
|
||||
assert element.tag == 'textures'
|
||||
for child in element:
|
||||
assert child.tag == 'texture'
|
||||
if terrain_base or terrain_spec or terrain_triplanar:
|
||||
texture_element = ET.SubElement(element, 'texture')
|
||||
texture_element.set('name', 'normTex')
|
||||
texture_element.set('file', 'types/default_norm.png')
|
||||
if terrain_base or terrain_norm or terrain_triplanar:
|
||||
texture_element = ET.SubElement(element, 'texture')
|
||||
texture_element.set('name', 'specTex')
|
||||
texture_element.set('file', 'types/blackness.dds')
|
||||
elif element.tag == 'material':
|
||||
if terrain_base or terrain_norm or terrain_spec:
|
||||
element.text = 'terrain_norm_spec.xml'
|
||||
elif terrain_triplanar:
|
||||
element.text = 'terrain_triplanar_norm_spec.xml'
|
||||
|
||||
if should_save:
|
||||
output_xml_tree(tree, path)
|
||||
|
||||
def get_materials():
|
||||
return {
|
||||
'aura.xml': {'norm': False, 'spec': True, 'replacement': 'aura_norm_spec.xml'},
|
||||
'aura_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'aura_norm_spec.xml'},
|
||||
'basic_glow.xml': {'norm': False, 'spec': True, 'replacement': 'basic_glow_norm_spec.xml'},
|
||||
'basic_glow_norm.xml': {'norm': True, 'spec': True, 'replacement': 'basic_glow_norm_spec.xml'},
|
||||
'basic_glow_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_glow_norm_spec.xml'},
|
||||
'basic_glow_wind.xml': {'norm': False, 'spec': True, 'replacement': 'basic_glow_wind_norm_spec.xml'},
|
||||
'basic_glow_wind_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_glow_wind_norm_spec.xml'},
|
||||
'basic_specmap.xml': {'norm': False, 'spec': True, 'replacement': 'no_trans_norm_spec.xml'},
|
||||
'basic_trans.xml': {'norm': False, 'spec': False, 'replacement': 'basic_trans_norm_spec.xml'},
|
||||
'basic_trans_ao.xml': {'norm': False, 'spec': False, 'replacement': 'basic_trans_ao_norm_spec.xml'},
|
||||
'basic_trans_ao_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_trans_ao_norm_spec.xml'},
|
||||
'basic_trans_ao_parallax_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_trans_ao_parallax_spec.xml'},
|
||||
'basic_trans_ao_spec.xml': {'norm': False, 'spec': True, 'replacement': 'basic_trans_ao_norm_spec.xml'},
|
||||
'basic_trans_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_trans_norm_spec.xml'},
|
||||
'basic_trans_parallax_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_trans_parallax_spec.xml'},
|
||||
'basic_trans_spec.xml': {'norm': False, 'spec': True, 'replacement': 'basic_trans_norm_spec.xml'},
|
||||
'basic_trans_wind.xml': {'norm': False, 'spec': False, 'replacement': 'basic_trans_wind_norm_spec.xml'},
|
||||
'basic_trans_wind_grain.xml': {'norm': False, 'spec': False, 'replacement': 'basic_trans_wind_grain_norm_spec.xml'},
|
||||
'basic_trans_wind_grain_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_trans_wind_grain_norm_spec.xml'},
|
||||
'basic_trans_wind_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'basic_trans_wind_norm_spec.xml'},
|
||||
'default.xml': {'norm': False, 'spec': False, 'replacement': 'no_trans_norm_spec.xml'},
|
||||
'no_trans_ao.xml': {'norm': False, 'spec': False, 'replacement': 'no_trans_ao_norm_spec.xml'},
|
||||
'no_trans_ao_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'no_trans_ao_norm_spec.xml'},
|
||||
'no_trans_ao_parallax_spec.xml': {'norm': True, 'spec': True, 'replacement': 'no_trans_ao_parallax_spec.xml'},
|
||||
'no_trans_ao_spec.xml': {'norm': False, 'spec': True, 'replacement': 'no_trans_ao_norm_spec.xml'},
|
||||
'no_trans_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'no_trans_norm_spec.xml'},
|
||||
'no_trans_parallax_ao.xml': {'norm': True, 'spec': False, 'replacement': 'no_trans_ao_parallax_spec.xml'},
|
||||
'no_trans_parallax_spec.xml': {'norm': True, 'spec': True, 'replacement': 'no_trans_parallax_spec.xml'},
|
||||
'no_trans_spec.xml': {'norm': False, 'spec': True, 'replacement': 'no_trans_norm_spec.xml'},
|
||||
'objectcolor.xml': {'norm': False, 'spec': False, 'replacement': 'objectcolor_norm_spec.xml'},
|
||||
'objectcolor_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'objectcolor_norm_spec.xml'},
|
||||
'objectcolor_specmap.xml': {'norm': False, 'spec': True, 'replacement': 'objectcolor_norm_spec.xml'},
|
||||
'player_trans.xml': {'norm': False, 'spec': False, 'replacement': 'player_trans_norm_spec.xml'},
|
||||
'player_trans_ao.xml': {'norm': False, 'spec': False, 'replacement': 'player_trans_ao_norm_spec.xml'},
|
||||
'player_trans_ao_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_ao_norm_spec.xml'},
|
||||
'player_trans_ao_parallax.xml': {'norm': True, 'spec': False, 'replacement': 'player_trans_ao_parallax_spec.xml'},
|
||||
'player_trans_ao_parallax_spec.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_ao_parallax_spec.xml'},
|
||||
'player_trans_ao_spec.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_ao_spec.xml'},
|
||||
'player_trans_norm.xml': {'norm': True, 'spec': False, 'replacement': 'player_trans_norm_spec.xml'},
|
||||
'player_trans_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_norm_spec.xml'},
|
||||
'player_trans_norm_spec_helmet.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_norm_spec_helmet.xml'},
|
||||
'player_trans_parallax.xml': {'norm': True, 'spec': False, 'replacement': 'player_trans_parallax_spec.xml'},
|
||||
'player_trans_parallax_spec.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_parallax_spec.xml'},
|
||||
'player_trans_parallax_spec_helmet.xml': {'norm': True, 'spec': True, 'replacement': 'player_trans_parallax_spec_helmet.xml'},
|
||||
'player_trans_spec.xml': {'norm': False, 'spec': True, 'replacement': 'player_trans_norm_spec.xml'},
|
||||
'player_trans_spec_helmet.xml': {'norm': False, 'spec': True, 'replacement': 'player_trans_norm_spec_helmet.xml'},
|
||||
'player_water.xml': {'norm': False, 'spec': False, 'replacement': 'player_water.xml'},
|
||||
'rock_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'rock_norm_spec.xml'},
|
||||
'rock_norm_spec_ao.xml': {'norm': True, 'spec': True, 'replacement': 'rock_norm_spec_ao.xml'},
|
||||
'rock_normstrong_spec.xml': {'norm': True, 'spec': True, 'replacement': 'rock_normstrong_spec.xml'},
|
||||
'rock_normstrong_spec_ao.xml': {'norm': True, 'spec': True, 'replacement': 'rock_normstrong_spec_ao.xml'},
|
||||
'terrain_base.xml': {'norm': False, 'spec': False, 'replacement': 'terrain_norm_spec.xml'},
|
||||
'terrain_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'terrain_norm_spec.xml'},
|
||||
'terrain_normstrong_spec.xml': {'norm': True, 'spec': True, 'replacement': 'terrain_normstrong_spec.xml'},
|
||||
'terrain_normweak_spec.xml': {'norm': True, 'spec': True, 'replacement': 'terrain_normweak_spec.xml'},
|
||||
'terrain_triplanar.xml': {'norm': False, 'spec': False, 'replacement': 'terrain_triplanar_norm_spec.xml'},
|
||||
'terrain_triplanar_norm_spec.xml': {'norm': True, 'spec': True, 'replacement': 'terrain_triplanar_norm_spec.xml'},
|
||||
'trans_wind.xml': {'norm': False, 'spec': False, 'replacement': 'basic_trans_wind_norm_spec.xml'},
|
||||
'waterfall.xml': {'norm': False, 'spec': False, 'replacement': 'waterfall.xml'},
|
||||
}
|
||||
|
||||
def get_material(material):
|
||||
return get_materials()[material]
|
||||
|
||||
def remove_actor_materials(path):
|
||||
with open(path, 'rt') as handle:
|
||||
xml = handle.read()
|
||||
|
||||
should_save = False
|
||||
|
||||
tree = ET.parse(path)
|
||||
root = tree.getroot()
|
||||
|
||||
material_name = None
|
||||
|
||||
if '<material>' in xml:
|
||||
assert xml.count('<material>') == 1
|
||||
|
||||
if root.tag == 'actor':
|
||||
for child in root:
|
||||
if child.tag == 'material':
|
||||
material_name = child.text.strip()
|
||||
child.text = get_material(material_name)['replacement']
|
||||
else:
|
||||
assert root.tag == 'qualitylevels'
|
||||
for root_child in root:
|
||||
assert root_child.tag == 'inline' or root_child.tag == 'actor'
|
||||
for child in root_child:
|
||||
if child.tag == 'material':
|
||||
material_name = child.text.strip()
|
||||
child.text = get_material(material_name)['replacement']
|
||||
else:
|
||||
assert root.tag == 'actor'
|
||||
material_name = 'default.xml'
|
||||
material_element = ET.SubElement(root, 'material')
|
||||
material_element.text = get_material(material_name)['replacement']
|
||||
|
||||
assert material_name is not None
|
||||
|
||||
material = get_material(material_name)
|
||||
if material_name == material['replacement']:
|
||||
return
|
||||
replacement_material = get_material(material['replacement'])
|
||||
assert (not material['norm']) or (not material['spec'])
|
||||
assert replacement_material['norm'] and replacement_material['spec']
|
||||
|
||||
if material['norm'] != ('normTex' in xml) or material['spec'] != ('specTex' in xml) or '<!--' in xml:
|
||||
sys.stdout.write(
|
||||
'Actor "{}" should be handled manually. It should use "{}" instead of "{}".\n'.format(
|
||||
path, material['replacement'], material_name))
|
||||
return
|
||||
should_save = True
|
||||
|
||||
# If there are no textures it means the material isn't really useful. We'll with them later.
|
||||
if xml.count('<textures>') > 0:
|
||||
def add_default_norm_element(textures_element, index=None):
|
||||
if not index:
|
||||
norm_element = ET.SubElement(textures_element, 'texture')
|
||||
else:
|
||||
norm_element = ET.Element('texture')
|
||||
norm_element.set('file', 'default_norm.png')
|
||||
norm_element.set('name', 'normTex')
|
||||
if index:
|
||||
textures_element.insert(index, norm_element)
|
||||
def add_default_spec_element(textures_element, index=None):
|
||||
if not index:
|
||||
spec_element = ET.SubElement(textures_element, 'texture')
|
||||
else:
|
||||
spec_element = ET.Element('texture')
|
||||
spec_element.set('file', 'null_black.dds')
|
||||
spec_element.set('name', 'specTex')
|
||||
if index:
|
||||
textures_element.insert(index, spec_element)
|
||||
def add_missing_textures(element, needs_norm, needs_spec):
|
||||
for child in element:
|
||||
if child.tag == 'textures':
|
||||
expected_len = 1
|
||||
if not needs_norm:
|
||||
expected_len += 1
|
||||
if not needs_spec:
|
||||
expected_len += 1
|
||||
if expected_len > 1:
|
||||
only_base = True
|
||||
for texture_child in child:
|
||||
if texture_child.get('name') == 'normTex' or texture_child.get('name') == 'specTex':
|
||||
only_base = False
|
||||
if only_base:
|
||||
continue
|
||||
if needs_norm and needs_spec:
|
||||
add_default_norm_element(child)
|
||||
add_default_spec_element(child)
|
||||
elif needs_norm:
|
||||
add_default_norm_element(child)
|
||||
elif needs_spec:
|
||||
add_default_spec_element(child)
|
||||
else:
|
||||
add_missing_textures(child, needs_norm, needs_spec)
|
||||
if not material['norm'] and not material['spec']:
|
||||
if xml.count('<textures>') > 1:
|
||||
group_element = ET.Element('group')
|
||||
variant_element = ET.SubElement(group_element, 'variant')
|
||||
textures_element = ET.SubElement(variant_element, 'textures')
|
||||
add_default_norm_element(textures_element)
|
||||
add_default_spec_element(textures_element)
|
||||
if root.tag == 'actor':
|
||||
last_index = len(root) - 1
|
||||
assert root[last_index].tag == 'material'
|
||||
root.insert(last_index, group_element)
|
||||
else:
|
||||
assert root.tag == 'qualitylevels'
|
||||
for root_child in root:
|
||||
assert root_child.tag == 'inline' or root_child.tag == 'actor'
|
||||
last_index = len(root_child) - 1
|
||||
assert root_child[last_index].tag == 'material'
|
||||
root_child.insert(last_index, group_element)
|
||||
else:
|
||||
add_missing_textures(root, True, True)
|
||||
else:
|
||||
add_missing_textures(root, not material['norm'], not material['spec'])
|
||||
|
||||
if should_save:
|
||||
sys.stdout.write('Actor "{}" is fixed.\n'.format(path))
|
||||
output_xml_tree(tree, path)
|
||||
|
||||
def remove_terrain_materials_recursively(path):
|
||||
for file_name in os.listdir(path):
|
||||
file_path = os.path.join(path, file_name)
|
||||
if os.path.isfile(file_path):
|
||||
name, ext = os.path.splitext(file_name)
|
||||
if ext.lower() == '.xml' and name.lower() != 'terrains':
|
||||
remove_terrain_materials(file_path)
|
||||
elif os.path.isdir(file_path):
|
||||
remove_terrain_materials_recursively(file_path)
|
||||
|
||||
def remove_actor_materials_recursively(path):
|
||||
for file_name in os.listdir(path):
|
||||
file_path = os.path.join(path, file_name)
|
||||
if os.path.isfile(file_path):
|
||||
name, ext = os.path.splitext(file_name)
|
||||
if ext.lower() == '.xml':
|
||||
remove_actor_materials(file_path)
|
||||
elif os.path.isdir(file_path):
|
||||
remove_actor_materials_recursively(file_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# paths should be a list of paths to mods folders
|
||||
paths = sys.argv[1:]
|
||||
for path in paths:
|
||||
remove_terrain_materials_recursively(os.path.join(path, 'art', 'terrains'))
|
||||
remove_actor_materials_recursively(os.path.join(path, 'art', 'actors'))
|
Loading…
Reference in New Issue
Block a user