// /*=============================================================================== // Copyright (C) 2020 PhantomsXR Ltd. All Rights Reserved. // // This file is part of the XR-MOD SDK. // // The XR-MOD SDK cannot be copied, distributed, or made available to // third-parties for commercial purposes without written permission of PhantomsXR Ltd. // // Contact nswell@phantomsxr.com for licensing requests. // ===============================================================================*/ using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; namespace Phantom.XRMOD.XRMODPackageTools.Editor { public class UtilGuids { private static readonly string[] kDefaultFileExtensions = { // "*.meta", // "*.mat", // "*.anim", // "*.prefab", // "*.unity", // "*.asset" "*.*" }; static public void RegenerateGuids(string _assetsPath, string[] regeneratedExtensions = null) { if (regeneratedExtensions == null) { regeneratedExtensions = kDefaultFileExtensions; } // Get list of working files List filesPaths = new List(); foreach (string extension in regeneratedExtensions) { filesPaths.AddRange( Directory.GetFiles(_assetsPath, extension, SearchOption.AllDirectories) ); } // Create dictionary to hold old-to-new GUID map Dictionary guidOldToNewMap = new Dictionary(); Dictionary> guidsInFileMap = new Dictionary>(); // We must only replace GUIDs for Resources present in Assets. // Otherwise built-in resources (shader, meshes etc) get overwritten. HashSet ownGuids = new HashSet(); // Traverse all files, remember which GUIDs are in which files and generate new GUIDs int counter = 0; foreach (string filePath in filesPaths) { EditorUtility.DisplayProgressBar("Scanning Assets folder", MakeRelativePath(_assetsPath, filePath), counter / (float) filesPaths.Count); string contents = string.Empty; try { contents = File.ReadAllText(filePath); } catch (Exception e) { Debug.LogError(filePath); Debug.LogError(e.ToString()); counter++; continue; } IEnumerable guids = GetGuids(contents); bool isFirstGuid = true; foreach (string oldGuid in guids) { // First GUID in .meta file is always the GUID of the asset itself if (isFirstGuid && Path.GetExtension(filePath) == ".meta") { ownGuids.Add(oldGuid); isFirstGuid = false; } // Generate and save new GUID if we haven't added it before if (!guidOldToNewMap.ContainsKey(oldGuid)) { string newGuid = Guid.NewGuid().ToString("N"); guidOldToNewMap.Add(oldGuid, newGuid); } if (!guidsInFileMap.ContainsKey(filePath)) guidsInFileMap[filePath] = new List(); if (!guidsInFileMap[filePath].Contains(oldGuid)) { guidsInFileMap[filePath].Add(oldGuid); } } counter++; } // Traverse the files again and replace the old GUIDs counter = -1; int guidsInFileMapKeysCount = guidsInFileMap.Keys.Count; foreach (string filePath in guidsInFileMap.Keys) { EditorUtility.DisplayProgressBar("Regenerating GUIDs", MakeRelativePath(_assetsPath, filePath), counter / (float) guidsInFileMapKeysCount); counter++; string contents = File.ReadAllText(filePath); foreach (string oldGuid in guidsInFileMap[filePath]) { if (!ownGuids.Contains(oldGuid)) continue; string newGuid = guidOldToNewMap[oldGuid]; if (string.IsNullOrEmpty(newGuid)) throw new NullReferenceException("newGuid == null"); contents = contents.Replace("guid: " + oldGuid, "guid: " + newGuid); } File.Delete(filePath); File.WriteAllText(filePath, contents); } EditorUtility.ClearProgressBar(); } private static IEnumerable GetGuids(string text) { const string guidStart = "guid: "; const int guidLength = 32; int textLength = text.Length; int guidStartLength = guidStart.Length; List guids = new List(); int index = 0; while (index + guidStartLength + guidLength < textLength) { index = text.IndexOf(guidStart, index, StringComparison.Ordinal); if (index == -1) break; index += guidStartLength; string guid = text.Substring(index, guidLength); index += guidLength; if (IsGuid(guid)) { guids.Add(guid); } } return guids; } private static bool IsGuid(string text) { for (int i = 0; i < text.Length; i++) { char c = text[i]; if ( !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) ) return false; } return true; } private static string MakeRelativePath(string fromPath, string toPath) { Uri fromUri = new Uri(fromPath); Uri toUri = new Uri(toPath); Uri relativeUri = fromUri.MakeRelativeUri(toUri); string relativePath = Uri.UnescapeDataString(relativeUri.ToString()); return relativePath; } } }