extract_low_level.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import argparse
  2. import sys
  3. import json
  4. from pathlib import Path
  5. # Add the utils directory to the Python path
  6. utils_path = Path(__file__).parent / 'utils'
  7. sys.path.append(str(utils_path))
  8. from file_utils import find_files_by_extension
  9. from deep_parser import parse_scene_or_prefab
  10. from json_utils import write_json
  11. from yaml_utils import load_unity_yaml, convert_to_plain_python_types
  12. from hierarchy_utils import HierarchyParser
  13. def main():
  14. """
  15. Main function to run the low-level data extraction process.
  16. """
  17. parser = argparse.ArgumentParser(
  18. description="Generates a deeply detailed, per-GameObject breakdown of scenes and prefabs."
  19. )
  20. parser.add_argument(
  21. "--input",
  22. type=str,
  23. required=True,
  24. help="The root directory of the target Unity project."
  25. )
  26. parser.add_argument(
  27. "--output",
  28. type=str,
  29. required=True,
  30. help="The directory where the generated output folder will be saved."
  31. )
  32. parser.add_argument(
  33. "--indent",
  34. type=int,
  35. default=None,
  36. help="Indentation level for JSON output. Defaults to None (compact)."
  37. )
  38. args = parser.parse_args()
  39. input_dir = Path(args.input).resolve()
  40. output_dir = Path(args.output).resolve()
  41. if not input_dir.is_dir():
  42. print(f"Error: Input path '{input_dir}' is not a valid directory.", file=sys.stderr)
  43. sys.exit(1)
  44. # Create the main output folder, named "LowLevel"
  45. low_level_output_dir = output_dir / "LowLevel"
  46. try:
  47. low_level_output_dir.mkdir(parents=True, exist_ok=True)
  48. print(f"Output will be saved to: {low_level_output_dir}")
  49. except OSError as e:
  50. print(f"Error: Could not create output directory '{low_level_output_dir}'. {e}", file=sys.stderr)
  51. sys.exit(1)
  52. # --- Orchestration ---
  53. assets_dir = input_dir / "Assets"
  54. if not assets_dir.is_dir():
  55. print(f"Error: 'Assets' directory not found in '{input_dir}'.", file=sys.stderr)
  56. return
  57. scene_files = find_files_by_extension(str(assets_dir), '.unity')
  58. prefab_files = find_files_by_extension(str(assets_dir), '.prefab')
  59. files_to_process = scene_files + prefab_files
  60. print(f"\nFound {len(files_to_process)} scene/prefab files to process.")
  61. for file_path_str in files_to_process:
  62. file_path = Path(file_path_str)
  63. print(f"\nProcessing: {file_path.name}")
  64. # --- Deep Parsing for Individual GameObjects ---
  65. gameobject_list = parse_scene_or_prefab(str(file_path))
  66. # Create the output subdirectory for this asset
  67. relative_path = file_path.relative_to(input_dir)
  68. asset_output_dir = low_level_output_dir / relative_path
  69. try:
  70. asset_output_dir.mkdir(parents=True, exist_ok=True)
  71. except OSError as e:
  72. print(f"Error creating directory {asset_output_dir}: {e}", file=sys.stderr)
  73. continue
  74. if gameobject_list:
  75. print(f"Saving {len(gameobject_list)} GameObjects to {asset_output_dir}")
  76. for go_data in gameobject_list:
  77. file_id = go_data.get('fileID')
  78. if file_id:
  79. output_json_path = asset_output_dir / f"{file_id}.json"
  80. try:
  81. write_json(go_data, output_json_path, indent=args.indent)
  82. except Exception as e:
  83. print(f"Error writing to {output_json_path}: {e}", file=sys.stderr)
  84. else:
  85. print(f"Skipped deep parsing for {file_path.name}.")
  86. # --- Hierarchy Parsing for Root Object Identification ---
  87. try:
  88. documents = load_unity_yaml(file_path)
  89. if not documents:
  90. print(f"Could not load YAML from {file_path.name} for hierarchy parsing.")
  91. continue
  92. raw_object_map = {int(doc.anchor.value): doc for doc in documents if hasattr(doc, 'anchor') and doc.anchor is not None}
  93. object_map = {file_id: convert_to_plain_python_types(obj) for file_id, obj in raw_object_map.items()}
  94. parser = HierarchyParser(object_map)
  95. root_object_ids = parser.get_root_object_ids()
  96. # Extract just the fileIDs for the root_objects.json file
  97. root_ids_list = [file_id for file_id, _ in root_object_ids]
  98. if root_ids_list:
  99. roots_output_path = asset_output_dir / "root_objects.json"
  100. write_json(root_ids_list, roots_output_path, indent=args.indent)
  101. print(f"Successfully saved root object list to {roots_output_path}")
  102. except Exception as e:
  103. print(f"Error during hierarchy parsing for {file_path.name}: {e}", file=sys.stderr)
  104. print("\nLow-level extraction complete.")
  105. if __name__ == "__main__":
  106. main()