Export prefabs to JSON
This commit is contained in:
parent
17435b829e
commit
507c516b0b
132
tools/parse-prefabs.py
Executable file
132
tools/parse-prefabs.py
Executable file
@ -0,0 +1,132 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
#
|
||||||
|
# [ TD2 TRACK STRUCTURE PREFAB PARSER ]
|
||||||
|
# by dkgl
|
||||||
|
# v1.0
|
||||||
|
#
|
||||||
|
|
||||||
|
prefab_header_pattern = re.compile(r"^--- !u!(\d+) &(\d+)$")
|
||||||
|
|
||||||
|
|
||||||
|
def parse_prefab(file):
|
||||||
|
component_list = []
|
||||||
|
component_map = {}
|
||||||
|
current_yaml = ""
|
||||||
|
component_type = None
|
||||||
|
component_id = None
|
||||||
|
|
||||||
|
for line in file:
|
||||||
|
match = prefab_header_pattern.match(line)
|
||||||
|
if match:
|
||||||
|
if component_type is not None:
|
||||||
|
component = parse_prefab_component(current_yaml, component_type, component_id)
|
||||||
|
if component is not None:
|
||||||
|
component_list.append(component)
|
||||||
|
component_map[component_id] = component
|
||||||
|
current_yaml = ""
|
||||||
|
component_type = match.group(1)
|
||||||
|
component_id = match.group(2)
|
||||||
|
else:
|
||||||
|
current_yaml += line
|
||||||
|
|
||||||
|
if component_type is not None:
|
||||||
|
component = parse_prefab_component(current_yaml, component_type, component_id)
|
||||||
|
if component is not None:
|
||||||
|
component_list.append(component)
|
||||||
|
component_map[component_id] = component
|
||||||
|
|
||||||
|
visited_ids = set()
|
||||||
|
resolve_references(component_list[0], component_map, visited_ids)
|
||||||
|
|
||||||
|
return component_list[0]
|
||||||
|
|
||||||
|
|
||||||
|
def find_tracks(prefab):
|
||||||
|
# print(prefab)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def parse_prefab_component(component_yaml, component_type, component_id):
|
||||||
|
loaded = yaml.load(component_yaml, yaml.SafeLoader)
|
||||||
|
loaded["__component_id"] = component_id
|
||||||
|
loaded["__component_type"] = component_type
|
||||||
|
return loaded
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_references(value, component_map, visited_ids):
|
||||||
|
if id(value) in visited_ids:
|
||||||
|
return
|
||||||
|
visited_ids.add(id(value))
|
||||||
|
if isinstance(value, dict):
|
||||||
|
keys = value.keys()
|
||||||
|
elif isinstance(value, list):
|
||||||
|
keys = range(len(value))
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
for key in keys:
|
||||||
|
if isinstance(value[key], dict) and "fileID" in value[key]:
|
||||||
|
file_id = str(value[key]["fileID"])
|
||||||
|
if file_id in component_map:
|
||||||
|
component = component_map[file_id]
|
||||||
|
# Prevent circular references
|
||||||
|
if id(component) not in visited_ids:
|
||||||
|
value[key] = component_map[file_id]
|
||||||
|
|
||||||
|
resolve_references(value[key], component_map, visited_ids)
|
||||||
|
|
||||||
|
|
||||||
|
def process_file(file_path):
|
||||||
|
if file_path.endswith(".prefab.meta"):
|
||||||
|
return
|
||||||
|
|
||||||
|
if not file_path.endswith(".prefab"):
|
||||||
|
print(f"Skipping non-.prefab file: {file_path}")
|
||||||
|
return
|
||||||
|
|
||||||
|
file_path = Path(file_path)
|
||||||
|
output_path = file_path.with_suffix(".json")
|
||||||
|
|
||||||
|
|
||||||
|
print(f"Processing file: {file_path} -> {output_path}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(file_path, encoding="utf8") as infile, open(output_path, 'w', encoding="utf8") as outfile:
|
||||||
|
prefab = parse_prefab(infile)
|
||||||
|
# print(find_tracks(prefab))
|
||||||
|
json.dump(prefab, outfile, indent=4, ensure_ascii=False)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing {file_path}: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def process_directory(directory: str):
|
||||||
|
print(f"Processing directory: {directory}")
|
||||||
|
for entry in os.listdir(directory):
|
||||||
|
full_path = os.path.join(directory, entry)
|
||||||
|
if os.path.isfile(full_path):
|
||||||
|
process_file(full_path)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python prase-prefabs.py <file_or_directory> [<file_or_directory> ...]")
|
||||||
|
return
|
||||||
|
|
||||||
|
for path in sys.argv[1:]:
|
||||||
|
if os.path.isdir(path):
|
||||||
|
process_directory(path)
|
||||||
|
elif os.path.isfile(path):
|
||||||
|
process_file(path)
|
||||||
|
else:
|
||||||
|
print(f"Invalid path: {path}")
|
||||||
|
|
||||||
|
print("Done!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Reference in New Issue
Block a user