89 lines
2.8 KiB
Python
89 lines
2.8 KiB
Python
import xml.etree.ElementTree as ET
|
|
import os
|
|
from dataclasses import dataclass, field
|
|
from typing import List, Optional
|
|
from pathlib import Path
|
|
|
|
|
|
@dataclass
|
|
class SourcedFile:
|
|
layer_name: str
|
|
subfolder: Optional[str]
|
|
files: List[str]
|
|
defined_events: List[str] = field(default_factory=list)
|
|
|
|
|
|
def read_psc_file(psc_file: Path) -> List[SourcedFile]:
|
|
tree = ET.parse(psc_file)
|
|
root = tree.getroot()
|
|
# PSC exports may use a default XML namespace.
|
|
for element in root.iter():
|
|
element.tag = element.tag.rsplit("}", 1)[-1]
|
|
|
|
layers = root.findall(".//Layer")
|
|
|
|
layer_info_list: List[SourcedFile] = []
|
|
for layer in layers:
|
|
layer_name = layer.attrib.get("Name")
|
|
subfolder = layer.attrib.get("SubFolder")
|
|
# Scripts-Filenames
|
|
scripts = layer.find("Scripts")
|
|
script_names = []
|
|
if scripts is not None:
|
|
for filename in scripts.findall("Filename"):
|
|
name = filename.attrib.get("Name")
|
|
if name:
|
|
script_names.append(name)
|
|
|
|
# DefinedEvents-Filenames (.def files)
|
|
defined_events = layer.find("DefinedEvents")
|
|
event_names = []
|
|
if defined_events is not None:
|
|
for filename in defined_events.findall("Filename"):
|
|
name = filename.attrib.get("Name")
|
|
if name:
|
|
event_names.append(name)
|
|
|
|
layer_info_list.append(
|
|
SourcedFile(
|
|
layer_name=layer_name,
|
|
subfolder=subfolder,
|
|
files=script_names,
|
|
defined_events=event_names,
|
|
)
|
|
)
|
|
return layer_info_list
|
|
|
|
|
|
def get_all_psc_files(root_path: Path) -> list[Path]:
|
|
return sorted(root_path.rglob("*.psc"), key=lambda path: str(path).casefold())
|
|
|
|
|
|
def _expanded(value) -> Path:
|
|
return Path(os.path.expandvars(value).replace("\\", "/"))
|
|
|
|
|
|
def _layer_files(psc_file: Path, attribute: str, suffix: str) -> list[Path]:
|
|
paths = []
|
|
for layer in read_psc_file(psc_file):
|
|
folder = layer.subfolder or "."
|
|
base = psc_file.parent / _expanded(os.environ.get(folder, folder))
|
|
for name in getattr(layer, attribute):
|
|
filename = _expanded(name)
|
|
if not filename.suffix:
|
|
filename = filename.with_suffix(suffix)
|
|
path = (base / filename).resolve()
|
|
if path.suffix.lower() == suffix:
|
|
paths.append(path)
|
|
return paths
|
|
|
|
|
|
def psc_script_files(psc_file: Path) -> list[Path]:
|
|
"""Resolve layer script paths relative to the PSC, preserving load order."""
|
|
return _layer_files(psc_file, "files", ".tcl")
|
|
|
|
|
|
def psc_defined_event_files(psc_file: Path) -> list[Path]:
|
|
"""Resolve the layers' DefinedEvents (.def) paths relative to the PSC."""
|
|
return _layer_files(psc_file, "defined_events", ".def")
|