#!/usr/bin/env python3 """ Generate catalogue.json from UE5 Content folder. This script scans the Content/Ralpha/Assets directory and generates a machine-readable catalogue with metadata for each asset. Usage: python generate_catalogue.py [--project-path /path/to/RalphaProject] Or run as UE5 commandlet: UE4Editor-Cmd.exe RalphaProject.uproject -run=PythonScript -script=generate_catalogue.py """ import os import json import argparse from pathlib import Path from datetime import datetime def find_uassets(content_path: Path) -> list: """Find all .uasset files in the Content folder.""" assets = [] for uasset in content_path.rglob("*.uasset"): # Skip engine-generated files if "Developers" in str(uasset) or "__External" in str(uasset): continue assets.append(uasset) return assets def parse_asset_path(uasset_path: Path, content_path: Path) -> dict: """Parse a .uasset path into catalogue metadata.""" relative = uasset_path.relative_to(content_path) parts = relative.parts # Generate ID from path asset_id = "_".join(parts).replace(".uasset", "").lower() asset_id = asset_id.replace(" ", "_").replace("-", "_") # Extract category from folder structure if len(parts) > 2: category = "/".join(parts[1:-1]) # Skip 'Ralpha' prefix else: category = "Uncategorized" # Display name from filename name = parts[-1].replace(".uasset", "").replace("_", " ").title() return { "id": asset_id, "name": name, "category": category, "tags": extract_tags(name, category), "path": f"/Game/{'/'.join(parts)}".replace(".uasset", ""), "thumbnail": f"thumbnails/{asset_id}.png", "dimensions": None, # Would need UE5 API to extract "pivot": "bottom_center", "lods": 0, "has_collision": False, "materials": [], "variants": [] } def extract_tags(name: str, category: str) -> list: """Extract search tags from name and category.""" tags = [] # Add words from name for word in name.lower().split(): if len(word) > 2: tags.append(word) # Add category parts for part in category.split("/"): tags.append(part.lower()) return list(set(tags)) def generate_catalogue(project_path: Path) -> dict: """Generate the full catalogue from project content.""" content_path = project_path / "Content" if not content_path.exists(): raise FileNotFoundError(f"Content path not found: {content_path}") assets = find_uassets(content_path) catalogue = { "version": "1.0.0", "generated": datetime.utcnow().isoformat() + "Z", "asset_count": len(assets), "assets": [] } for uasset in sorted(assets): asset_data = parse_asset_path(uasset, content_path) catalogue["assets"].append(asset_data) return catalogue def main(): parser = argparse.ArgumentParser(description="Generate Ralpha asset catalogue") parser.add_argument("--project-path", type=Path, default=Path(__file__).parent.parent.parent, help="Path to UE5 project root") parser.add_argument("--output", type=Path, default=None, help="Output path for catalogue.json") args = parser.parse_args() if args.output is None: args.output = args.project_path / "RalphaData" / "catalogue.json" print(f"Scanning project: {args.project_path}") try: catalogue = generate_catalogue(args.project_path) with open(args.output, "w") as f: json.dump(catalogue, f, indent=2) print(f"Generated catalogue with {catalogue['asset_count']} assets") print(f"Saved to: {args.output}") except FileNotFoundError as e: print(f"Error: {e}") print("Make sure you're running from the project root or specify --project-path") return 1 return 0 if __name__ == "__main__": exit(main())