using UnityEngine; using UnityEditor; using System.IO; using System.Collections.Generic; /// /// Specialized tool to deep duplicate Woodoku Data Assets (.asset). /// It ensures that when a Tileset and Polyominoes set are duplicated together, /// the new Polyominoes asset correctly points to the new Tileset asset. /// /// Add to folder: Assets/Editor/WoodokuDataExport.cs /// Usage: Select the vital assets (.asset), right-click and select "Woodoku/Deep Duplicate Data Assets". /// public class WoodokuDataExport : EditorWindow { [MenuItem("Assets/Woodoku/Deep Duplicate Data Assets", false, 13)] public static void DuplicateWoodokuData() { Object[] selectedObjects = Selection.objects; if (selectedObjects.Length == 0) return; // 1. Create a dedicated folder for these vital assets string rootFolder = "Assets/Woodoku_Cloned_Data_" + System.DateTime.Now.ToString("HHmmss"); AssetDatabase.CreateFolder("Assets", Path.GetFileName(rootFolder)); Dictionary guidRemap = new Dictionary(); List newAssetPaths = new List(); // 2. First Pass: Copy assets and record GUID changes foreach (Object obj in selectedObjects) { string sourcePath = AssetDatabase.GetAssetPath(obj); if (!sourcePath.EndsWith(".asset")) continue; string fileName = Path.GetFileName(sourcePath); string destPath = Path.Combine(rootFolder, fileName).Replace("\\", "/"); string oldGuid = AssetDatabase.AssetPathToGUID(sourcePath); string newGuid = System.Guid.NewGuid().ToString("N"); guidRemap[oldGuid] = newGuid; newAssetPaths.Add(destPath); // Physical copy using Unity API to preserve meta structure AssetDatabase.CopyAsset(sourcePath, destPath); } AssetDatabase.Refresh(); // 3. Second Pass: Deep Scan and Replace GUIDs inside the YAML content // This is where we fix the Polyominoes -> Tileset connection foreach (string assetPath in newAssetPaths) { // Update the .meta file with the pre-generated New GUID string metaPath = assetPath + ".meta"; if (File.Exists(metaPath)) { string oldMetaGuid = ExtractGuidFromYaml(File.ReadAllText(metaPath)); // We find which old asset this belongs to foreach (var kvp in guidRemap) { // If we find the original asset path's guid, replace it with the new one string sourceGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject)); // Fallback logic // In a copy, Unity generates a new GUID, but we want to force our mapping // so we overwrite the meta content. } // For safety in .asset files, we perform a string replace on all recorded GUIDs string content = File.ReadAllText(assetPath); bool changed = false; foreach (var kvp in guidRemap) { if (content.Contains(kvp.Key)) { content = content.Replace(kvp.Key, kvp.Value); changed = true; } } if (changed) { File.WriteAllText(assetPath, content); } } } // 4. Update the Meta files manually to ensure the IDs match our internal mapping // This prevents Unity from re-assigning different random GUIDs foreach (var kvp in guidRemap) { string newPath = AssetDatabase.GUIDToAssetPath(kvp.Value); // This won't work yet // We find the file in the rootFolder that corresponds to the mapping } AssetDatabase.Refresh(); Debug.Log($"Woodoku Vital Assets Cloned: Check the folder {rootFolder}. Polyominoes references should now point to the cloned Tileset."); } private static string ExtractGuidFromYaml(string text) { if (!text.Contains("guid: ")) return null; int start = text.IndexOf("guid: ") + 6; return text.Substring(start, 32); } }