From 83776072c93a395e3221ea73ad99f079295399cf Mon Sep 17 00:00:00 2001 From: max Date: Sun, 30 Jul 2023 01:36:26 +0200 Subject: [PATCH] SceneObjectNames & ObjectInfo - Try to get the scene object names - Try to get the object type - Try to get create object info --- Editor/ScenePartitionSO.cs | 200 ++++++++++++++++++++++++++++++++++++- 1 file changed, 197 insertions(+), 3 deletions(-) diff --git a/Editor/ScenePartitionSO.cs b/Editor/ScenePartitionSO.cs index 11cb951..54ae701 100644 --- a/Editor/ScenePartitionSO.cs +++ b/Editor/ScenePartitionSO.cs @@ -141,28 +141,37 @@ public void Save() { DeleteLoadedPartitions(); // Delete the loaded partitions from disk so we can write the new ones. - string pattern = @"&(\d+)"; + const string objectIdPattern = @"&(\d+)"; string dataPath = ScenePartitionUtils.GetDataPath(this); string scenePath = ScenePartitionUtils.GetScenePath(this); // Read the data from the scene file. string[] sceneData = File.ReadAllLines(scenePath); + Dictionary sceneObjectNameById = GetSceneObjectNames(in sceneData); + // Split it into blocks. int lastIndex = sceneData.Length; for (int i = sceneData.Length - 1; i >= 0; i--) { if (sceneData[i].StartsWith("---")) // --- is the start of a new yaml document. { - Match match = Regex.Match(sceneData[i], pattern); + Match match = Regex.Match(sceneData[i], objectIdPattern); if (match.Success) { // Extract the file number string id = match.Groups[1].Value; + ulong objectId = ulong.Parse(id); + + string extraInfo = ""; + if (TryGetObjectInfo(in sceneData, in sceneObjectNameById, i, lastIndex, objectId, out string objectInfo)) + { + extraInfo = $"-{objectInfo}"; + } // Write data to disk. - File.WriteAllLines($"{dataPath}/{SceneName}-{id}.yaml", sceneData[i..lastIndex]); + File.WriteAllLines($"{dataPath}/{SceneName}-{id}{extraInfo}.yaml", sceneData[i..lastIndex]); } lastIndex = i; @@ -377,5 +386,190 @@ public void ClearCache() { data = null; } + + private Dictionary GetSceneObjectNames(in string[] sceneData) + { + using ProfilerUtility.ProfilerScope profilerScope = new(nameof(GetSceneObjectNames)); + + Dictionary sceneObjectNameById = new Dictionary(); + + const string objectIdPattern = @"&(\d+)"; + + int lastIndex = sceneData.Length; + for (int i = sceneData.Length - 1; i >= 0; i--) + { + bool foundName = false; + + { // GameObjects. + const string gameObjectHeaderPattern = "--- !u!1 &"; + if (!foundName && sceneData[i].StartsWith(gameObjectHeaderPattern)) + { + + Match match = Regex.Match(sceneData[i], objectIdPattern); + if (!match.Success) continue; + if (!ulong.TryParse(match.Groups[1].Value, out ulong id)) continue; + + for (int j = i; j < lastIndex; j++) + { + const string namePattern = "m_Name: "; + int nameStartIndex = sceneData[j].LastIndexOf(namePattern); + if (nameStartIndex < 0) continue; + + nameStartIndex += namePattern.Length; + + string name = sceneData[j][nameStartIndex..]; + sceneObjectNameById.Add(id, name); + foundName = true; + break; + } + } + } + + { // Prefabs. + const string prefabHeaderPattern = "--- !u!1001 &"; + if (!foundName && sceneData[i].StartsWith(prefabHeaderPattern)) + { + Match match = Regex.Match(sceneData[i], objectIdPattern); + if (!match.Success) continue; + if (!ulong.TryParse(match.Groups[1].Value, out ulong id)) continue; + + // Get name form property override in Scene. + for (int j = i; j < lastIndex; j++) + { + const string propertyPattern = "propertyPath: m_Name"; + int propertyStartIndex = sceneData[j].LastIndexOf(propertyPattern); + if (propertyStartIndex < 0) continue; + + const string valuePattern = "value: "; + int valueStartIndex = sceneData[j + 1].LastIndexOf(valuePattern); + if (valueStartIndex < 0) continue; + + valueStartIndex += valuePattern.Length; + + string name = sceneData[j + 1][valueStartIndex..]; + sceneObjectNameById.Add(id, name); + foundName = true; + break; + } + + // Get name from prefab in AssetDatabase. + if (!foundName) + { + // Find the match using regex + const string guidPattern = @"guid:\s(\w+)"; + Match guidMatch = Regex.Match(sceneData[lastIndex - 1], guidPattern); + + if (guidMatch.Success) + { + // Extract the GUID + string guid = guidMatch.Groups[1].Value; + + string path = AssetDatabase.GUIDToAssetPath(guid); + string name = Path.GetFileNameWithoutExtension(path); + sceneObjectNameById.Add(id, name); + foundName = true; + } + } + } + } + + if (sceneData[i].StartsWith("---")) + { + lastIndex = i; + continue; + } + } + + return sceneObjectNameById; + } + + private bool TryGetObjectTypeName(string data, out string objectTypeName) + { + objectTypeName = data.Remove(data.Length - 1); + return true; + } + + private bool TryGetObjectInfo(in string[] sceneData, in Dictionary sceneObjectNameById, int index, int lastIndex, ulong objectId, out string objectInfo) + { + using ProfilerUtility.ProfilerScope profilerScope = new(nameof(TryGetObjectInfo)); + + objectInfo = ""; + + // Try get scene object name. + bool foundSceneObjectName = false; + + // If it is a gameObject or prefab try to get the name directly. + const string gameObjectHeaderPattern = "--- !u!1 &"; + const string prefabHeaderPattern = "--- !u!1001 &"; + if (!foundSceneObjectName && sceneData[index].StartsWith(gameObjectHeaderPattern) || sceneData[index].StartsWith(prefabHeaderPattern)) + { + if (sceneObjectNameById.TryGetValue(objectId, out string sceneObjectName)) + { + objectInfo += $"-{sceneObjectName}"; + foundSceneObjectName = true; + } + } + + if (!foundSceneObjectName) + { + // Most components have a property that links to the GameObject. + for (int j = index; j < lastIndex; j++) + { + const string gameObjectPattern = @"m_GameObject:\s{fileID:\s(\d+)}"; + + // Find the match using regex + Match gameObjectMatch = Regex.Match(sceneData[j], gameObjectPattern); + + if (!gameObjectMatch.Success) continue; + + if (ulong.TryParse(gameObjectMatch.Groups[1].Value, out ulong fileNumber)) + { + if (fileNumber == 0) break; // 0 == nothing. + if (!sceneObjectNameById.TryGetValue(fileNumber, out string sceneObjectName)) break; + + objectInfo += $"-{sceneObjectName}"; + foundSceneObjectName = true; + } + + break; + } + } + + if (!foundSceneObjectName) + { + // Some have a property that links to the PrefabInstance. + for (int j = index; j < lastIndex; j++) + { + const string prefabInstancePattern = @"m_PrefabInstance:\s{fileID:\s(\d+)}"; + + // Find the match using regex + Match prefabInstanceMatch = Regex.Match(sceneData[j], prefabInstancePattern); + + if (!prefabInstanceMatch.Success) continue; + + if (ulong.TryParse(prefabInstanceMatch.Groups[1].Value, out ulong fileNumber)) + { + if (fileNumber == 0) break; // 0 == nothing. + if (!sceneObjectNameById.TryGetValue(fileNumber, out string sceneObjectName)) break; + + objectInfo += $"-{sceneObjectName}"; + foundSceneObjectName = true; + } + + break; + } + } + + bool foundObjectTypeName = false; + + // Try get object type name. + if (TryGetObjectTypeName(sceneData[index + 1], out string objectTypeName)) + { + objectInfo += $"-{objectTypeName}"; + foundObjectTypeName = true; + } + + return foundSceneObjectName || foundObjectTypeName; + } } } \ No newline at end of file