extract_mid_level.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import argparse
  2. import sys
  3. import json
  4. import shutil
  5. from pathlib import Path
  6. # Add the utils directory to the Python path
  7. utils_path = Path(__file__).parent / 'utils'
  8. sys.path.append(str(utils_path))
  9. from file_utils import replicate_directory_structure, find_files_by_extension, create_guid_to_path_map
  10. from json_utils import write_json
  11. from scene_processor import UnitySceneProcessor
  12. def generate_guid_mappers(input_dir, output_dir, indent=None):
  13. """
  14. Finds all .meta files and generates JSON files mapping GUIDs to asset paths.
  15. """
  16. print("\n--- Starting GUID Mapper Generation ---")
  17. assets_dir = input_dir / "Assets"
  18. if not assets_dir.is_dir():
  19. print(f"Error: 'Assets' directory not found in '{input_dir}'", file=sys.stderr)
  20. return
  21. meta_files = find_files_by_extension(str(assets_dir), '.meta')
  22. print(f"Found {len(meta_files)} .meta files to process.")
  23. asset_type_map = {
  24. '.prefab': 'prefabs', '.unity': 'scenes', '.mat': 'materials',
  25. '.cs': 'scripts', '.png': 'textures', '.jpg': 'textures',
  26. '.jpeg': 'textures', '.asset': 'scriptable_objects',
  27. }
  28. guid_maps = {value: {} for value in asset_type_map.values()}
  29. guid_maps['others'] = {}
  30. for meta_file_path_str in meta_files:
  31. meta_file_path = Path(meta_file_path_str)
  32. asset_file_path = Path(meta_file_path_str.rsplit('.meta', 1)[0])
  33. if not asset_file_path.is_file():
  34. continue
  35. guid = None
  36. try:
  37. with open(meta_file_path, 'r', encoding='utf-8') as f:
  38. for line in f:
  39. if line.strip().startswith('guid:'):
  40. guid = line.strip().split(':')[1].strip()
  41. break
  42. except Exception as e:
  43. print(f"Warning: Could not read or parse guid from {meta_file_path}. {e}", file=sys.stderr)
  44. continue
  45. if guid:
  46. asset_ext = asset_file_path.suffix.lower()
  47. asset_type = asset_type_map.get(asset_ext, 'others')
  48. relative_path = asset_file_path.relative_to(input_dir).as_posix()
  49. guid_maps[asset_type][guid] = relative_path
  50. mappers_dir = output_dir / "GuidMappers"
  51. try:
  52. mappers_dir.mkdir(parents=True, exist_ok=True)
  53. for asset_type, guid_map in guid_maps.items():
  54. if guid_map:
  55. output_path = mappers_dir / f"{asset_type}.json"
  56. write_json(guid_map, output_path, indent=indent)
  57. print(f"Successfully created GUID mappers in {mappers_dir}")
  58. except OSError as e:
  59. print(f"Error: Could not create GUID mapper directory or files. {e}", file=sys.stderr)
  60. def main():
  61. """
  62. Main function to run the mid-level data extraction process.
  63. This script orchestrates the parsing of scene and prefab files.
  64. """
  65. parser = argparse.ArgumentParser(
  66. description="Generates a virtual representation of the project's structure."
  67. )
  68. parser.add_argument(
  69. "--input",
  70. type=str,
  71. required=True,
  72. help="The root directory of the target Unity project."
  73. )
  74. parser.add_argument(
  75. "--output",
  76. type=str,
  77. required=True,
  78. help="The directory where the generated output folder will be saved."
  79. )
  80. parser.add_argument(
  81. "--indent",
  82. type=int,
  83. default=None,
  84. help="Indentation level for JSON output. Defaults to None (compact)."
  85. )
  86. args = parser.parse_args()
  87. input_dir = Path(args.input).resolve()
  88. output_dir = Path(args.output).resolve()
  89. if not input_dir.is_dir():
  90. print(f"Error: Input path '{input_dir}' is not a valid directory.", file=sys.stderr)
  91. sys.exit(1)
  92. # --- Setup Output Directories ---
  93. mid_level_output_dir = output_dir / "MidLevel"
  94. output_assets_dir = mid_level_output_dir / "Assets"
  95. try:
  96. output_assets_dir.mkdir(parents=True, exist_ok=True)
  97. print(f"Output will be saved to: {mid_level_output_dir}")
  98. except OSError as e:
  99. print(f"Error: Could not create output directory '{mid_level_output_dir}'. {e}", file=sys.stderr)
  100. sys.exit(1)
  101. assets_dir = input_dir / "Assets"
  102. if not assets_dir.is_dir():
  103. print(f"Warning: 'Assets' directory not found in '{input_dir}'. Skipping all processing.", file=sys.stderr)
  104. return
  105. # --- Task 1: Replicate 'Assets' directory structure ---
  106. print(f"\n--- Replicating 'Assets' directory structure ---")
  107. replicate_directory_structure(str(assets_dir), str(output_assets_dir))
  108. print("Directory structure replication complete.")
  109. # --- Task 2: Generate GUID Map ---
  110. print("\n--- Generating GUID Map ---")
  111. guid_map = create_guid_to_path_map(str(input_dir))
  112. guid_map_path = mid_level_output_dir / "guid_map.json"
  113. try:
  114. # Use the new centralized utility
  115. write_json(guid_map, guid_map_path, indent=args.indent)
  116. print(f"Successfully created GUID map: {guid_map_path}")
  117. except Exception as e:
  118. print(f"Error writing GUID map: {e}", file=sys.stderr)
  119. sys.exit(1)
  120. # --- Task 3: Generate Detailed GUID Mappers ---
  121. generate_guid_mappers(input_dir, mid_level_output_dir, indent=args.indent)
  122. # --- Task 4: Orchestrate Scene and Prefab Parsing ---
  123. print("\n--- Starting Scene/Prefab Parsing Orchestration ---")
  124. scene_files = find_files_by_extension(str(assets_dir), '.unity')
  125. prefab_files = find_files_by_extension(str(assets_dir), '.prefab')
  126. files_to_process = scene_files + prefab_files
  127. print(f"Found {len(files_to_process)} scene/prefab files to process.")
  128. # Create a single processor instance to use for all files
  129. processor = UnitySceneProcessor(guid_map)
  130. for file_path_str in files_to_process:
  131. file_path = Path(file_path_str)
  132. relative_path = file_path.relative_to(assets_dir)
  133. output_path = output_assets_dir / relative_path
  134. output_path = output_path.with_suffix('.json')
  135. try:
  136. print(f"\n--- Processing: {file_path.name} ---")
  137. # Process the file and get the result
  138. result = processor.process_file(file_path)
  139. # Ensure the output directory exists
  140. output_path.parent.mkdir(parents=True, exist_ok=True)
  141. # Write the result using the centralized utility
  142. write_json(result, output_path, indent=args.indent)
  143. print(f"Successfully processed {file_path.name} -> {output_path}")
  144. except Exception as e:
  145. print(f"Error processing {file_path.name}: {e}", file=sys.stderr)
  146. # Potentially continue to the next file
  147. # sys.exit(1)
  148. print("\nMid-level extraction complete.")
  149. if __name__ == "__main__":
  150. main()