using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; namespace ProjectExporter { public class ProjectExporterController { private const string PythonExecutable = "/Users/sujithpudussery/Documents/UnityProjects/terra-llm/venv/bin/python3"; private const string ConversionScript = "/Users/sujithpudussery/Documents/UnityProjects/terra-llm/Assets/ProjectExporter/source/convert_scene.py"; private static readonly string ProjectRoot = Path.GetDirectoryName(Application.dataPath); private static readonly string OutputDirectory = Path.Combine(ProjectRoot, "Library", "ExportedJSON"); // Finds assets based on a search filter (e.g., "t:Scene") and builds a hierarchical model. public AssetModel GetAssets(string filter) { var root = new AssetModel("Assets", "Assets"); var assetGuids = AssetDatabase.FindAssets(filter, new[] { "Assets" }); foreach (var guid in assetGuids) { var path = AssetDatabase.GUIDToAssetPath(guid); if (filter.Contains("t:ScriptableObject") && !path.EndsWith(".asset")) { continue; } var parts = path.Split('/'); var currentNode = root; for (int i = 1; i < parts.Length; i++) // Start at 1 to skip "Assets" { var part = parts[i]; var child = currentNode.Children.FirstOrDefault(c => c.Name == part); if (child == null) { var currentPath = string.Join("/", parts.Take(i + 1)); child = new AssetModel(currentPath, part); currentNode.Children.Add(child); } currentNode = child; } } return root; } // Lists all files in the ProjectSettings directory. public AssetModel GetProjectSettingsFiles() { var settingsRootPath = Path.Combine(ProjectRoot, "ProjectSettings"); var root = new AssetModel(settingsRootPath, "ProjectSettings"); if (Directory.Exists(settingsRootPath)) { // Filter to only include *.asset files. var files = Directory.GetFiles(settingsRootPath, "*.asset", SearchOption.AllDirectories); foreach (var file in files) { var relativePath = Path.GetRelativePath(ProjectRoot, file); root.Children.Add(new AssetModel(relativePath, Path.GetFileName(file))); } } return root; } // Scans the entire Assets folder for .meta files and builds a hierarchical model. public AssetModel GetAllMetaFiles() { var assetsRootPath = Application.dataPath; // This is the "Assets" folder var root = new AssetModel("Assets", "Assets"); var files = Directory.GetFiles(assetsRootPath, "*.meta", SearchOption.AllDirectories); foreach (var file in files) { var relativePath = "Assets/" + Path.GetRelativePath(assetsRootPath, file).Replace('\\', '/'); var parts = relativePath.Split('/'); var currentNode = root; for (int i = 1; i < parts.Length; i++) // Start at 1 to skip "Assets" { var part = parts[i]; var child = currentNode.Children.FirstOrDefault(c => c.Name == part); if (child == null) { var currentPath = string.Join("/", parts.Take(i + 1)); child = new AssetModel(currentPath, part); currentNode.Children.Add(child); } currentNode = child; } } return root; } // Executes the Python conversion script for the selected assets. public void ExportAssets(AssetModel rootNode) { var assetsToExport = new List(); CollectSelectedAssets(rootNode, assetsToExport); EditorUtility.DisplayProgressBar("Exporting...", "Starting export process...", 0f); try { for (int i = 0; i < assetsToExport.Count; i++) { var relativeAssetPath = assetsToExport[i]; var progress = (float)i / assetsToExport.Count; EditorUtility.DisplayProgressBar("Exporting...", $"Processing {Path.GetFileName(relativeAssetPath)}", progress); var absoluteAssetPath = Path.Combine(ProjectRoot, relativeAssetPath); var outputJsonPath = Path.Combine(OutputDirectory, relativeAssetPath + ".json"); var process = new Process { StartInfo = new ProcessStartInfo { FileName = PythonExecutable, Arguments = $"\"{ConversionScript}\" \"{absoluteAssetPath}\" \"{outputJsonPath}\"", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true } }; process.Start(); string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); if (process.ExitCode != 0) { UnityEngine.Debug.LogError($"Error exporting {relativeAssetPath}: {error}"); } else { UnityEngine.Debug.Log($"Successfully exported {relativeAssetPath}: {output}"); } } } finally { EditorUtility.ClearProgressBar(); } } // Recursively collects the paths of all selected assets. private void CollectSelectedAssets(AssetModel node, List selectedPaths) { // If the node itself is a file and is selected, add it. if (node.Children.Count == 0 && node.IsSelected) { selectedPaths.Add(node.Path); } // Recurse into children foreach (var child in node.Children) { CollectSelectedAssets(child, selectedPaths); } } } }