diff --git a/Editor/ScenePartitionEditorWindow.cs b/Editor/ScenePartitionEditorWindow.cs index 6744b10..632e020 100644 --- a/Editor/ScenePartitionEditorWindow.cs +++ b/Editor/ScenePartitionEditorWindow.cs @@ -39,15 +39,17 @@ private void DrawSceneDataCache() foreach (KeyValuePair sceneData in scenePartitionSS.SceneDataCache) { + if (sceneData.Key == null || sceneData.Value == null) continue; + EditorGUILayout.LabelField($"{sceneData.Key.name}"); if (sceneData.Value.HasCreatedPartitions) { EditorGUILayout.LabelField($"scenePartitions"); - foreach (KeyValuePair scenePartition in sceneData.Value.ScenePartitions) + foreach (KeyValuePair scenePartition in sceneData.Value.ScenePartitions) { - EditorGUILayout.IntField((int)scenePartition.Value.id); + EditorGUILayout.LongField(scenePartition.Key); } } @@ -57,9 +59,9 @@ private void DrawSceneDataCache() { EditorGUILayout.LabelField($"loadedScenePartitions"); - foreach (KeyValuePair scenePartition in sceneData.Value.LoadedScenePartitions) + foreach (KeyValuePair scenePartition in sceneData.Value.LoadedScenePartitions) { - EditorGUILayout.IntField((int)scenePartition.Value.id); + EditorGUILayout.LongField(scenePartition.Value.id); } } @@ -67,15 +69,15 @@ private void DrawSceneDataCache() { EditorGUILayout.LabelField($"generatedSceneGrid"); - foreach (KeyValuePair> item in sceneData.Value.SceneGrid.Grid) + foreach (KeyValuePair> item in sceneData.Value.SceneGrid.Grid) { EditorGUILayout.IntField("gridId", item.Key); EditorGUI.indentLevel++; - foreach (uint id in item.Value) + foreach (long id in item.Value) { - EditorGUILayout.IntField((int)id); + EditorGUILayout.LongField(id); } EditorGUI.indentLevel--; diff --git a/Editor/ScenePartitionSO.cs b/Editor/ScenePartitionSO.cs index 618a000..9881983 100644 --- a/Editor/ScenePartitionSO.cs +++ b/Editor/ScenePartitionSO.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.IO; -using System.Reflection; using System.Text.RegularExpressions; using UnityEditor; using UnityEditor.SceneManagement; @@ -16,7 +15,7 @@ public class ScenePartitionSO : ScriptableObject public SceneAsset SceneAsset { get; private set; } = null; public string SceneName => SceneAsset == null ? name : SceneAsset.name; - public List alwaysLoadIds = new List { 0, 1, 2, 3, 4 }; + public List alwaysLoadIds = new List { 0, 1, 2, 3, 4 }; public ScenePartitionData Data { @@ -54,7 +53,7 @@ public void CreateScene() public void LoadAll() { CreateScenePartitions(); - SortedSet ids = new SortedSet(Data.ScenePartitions.Keys); + SortedSet ids = new SortedSet(Data.ScenePartitions.Keys); LoadScenePartitions(ids); } @@ -64,7 +63,7 @@ public void LoadAll() public void Reload() { if (!Data.HasLoadedPartitions) return; - LoadScenePartitions(new SortedSet(Data.LoadedScenePartitions.Keys)); + LoadScenePartitions(new SortedSet(Data.LoadedScenePartitions.Keys)); } private void CreateScenePartitions() @@ -81,7 +80,7 @@ private void CreateScenePartitions() } } - private void LoadScenePartitions(SortedSet partitionIds) + private void LoadScenePartitions(SortedSet partitionIds) { if (!Data.HasCreatedPartitions) return; @@ -91,17 +90,15 @@ private void LoadScenePartitions(SortedSet partitionIds) Data.LoadedScenePartitions.Clear(); - // Add default ids. - for (int i = 0; i < alwaysLoadIds.Count; i++) + // Add always load ids. + SortedSet baseIds = GetAlwaysLoadIds(); + foreach (var id in baseIds) { - if (Data.ScenePartitions.ContainsKey(alwaysLoadIds[i])) - { - partitionIds.Add(alwaysLoadIds[i]); - } + partitionIds.Add(id); } // Create scene data. - foreach (uint id in partitionIds) + foreach (long id in partitionIds) { ScenePartition p = Data.ScenePartitions[id]; sceneData.AddRange(File.ReadAllLines(p.filePath)); @@ -181,7 +178,7 @@ private void DeleteLoadedPartitions() { if (!Data.HasLoadedPartitions) return; - foreach (KeyValuePair scenePartition in Data.LoadedScenePartitions) + foreach (KeyValuePair scenePartition in Data.LoadedScenePartitions) { if (!File.Exists(scenePartition.Value.filePath)) continue; @@ -189,15 +186,14 @@ private void DeleteLoadedPartitions() } } - public void LoadPartitions(uint[] ids) + public void LoadPartitions(long[] ids) { - SortedSet partitionIds = new SortedSet(); + SortedSet partitionIds = new SortedSet(); for (int i = 0; i < ids.Length; i++) { - SortedSet connections = ScenePartitionUtils.FindDeeplyLinkedObjects(Data.ScenePartitions, ids[i]); - - foreach (uint c in connections) + SortedSet connections = ScenePartitionUtils.FindDeeplyLinkedObjects(Data.ScenePartitions, ids[i]); + foreach (long c in connections) { partitionIds.Add(c); } @@ -206,36 +202,90 @@ public void LoadPartitions(uint[] ids) LoadScenePartitions(partitionIds); } + private SortedSet GetAlwaysLoadIds() + { + SortedSet partitionIds = new SortedSet(); + + foreach (long id in alwaysLoadIds) + { + SortedSet connections = ScenePartitionUtils.FindDeeplyLinkedObjects(Data.ScenePartitions, id); + foreach (long c in connections) + { + partitionIds.Add(c); + } + } + + return partitionIds; + } + public void GenerateSceneGridData() { - if (!Data.HasCreatedPartitions) return; - LoadAll(); + if (!Data.HasCreatedPartitions) return; + Scene scene = EditorSceneManager.OpenScene(ScenePartitionUtils.GetScenePath(this), OpenSceneMode.Single); GameObject[] rootGameObjects = scene.GetRootGameObjects(); Data.SceneGrid.Grid.Clear(); - // Maybe later switch to getting the data from disk instead of loading the scene and then unloading it again. - foreach (GameObject gameObject in rootGameObjects) + //// Maybe later switch to getting the data from disk instead of loading the scene and then unloading it again. + //foreach (GameObject gameObject in rootGameObjects) + //{ + // // https://forum.unity.com/threads/how-to-get-the-local-identifier-in-file-for-scene-objects.265686/ + // PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance); + // SerializedObject serializedObject = new SerializedObject(gameObject.transform); + // inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null); + // SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile"); + + // long localId = localIdProp.longValue; + + // if (localId == 0) + // { + // if (PrefabUtility.IsPartOfPrefabInstance(gameObject)) + // { + // GlobalObjectId id = GlobalObjectId.GetGlobalObjectIdSlow(gameObject); // We could use this funtion for all objects. Might be a bit slower but is also simple. + // localId = long.Parse(id.targetPrefabId.ToString()); + + // Debug.Log($"{id.assetGUID} | {id.identifierType} | {id.targetObjectId} | {id.targetPrefabId}"); + + // if (id.targetObjectId == 0 && id.targetPrefabId == 0) + // { + // Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}"); + // continue; + // } + // } + // else + // { + // Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}"); + // continue; + // } + // } + + // if (!Data.ScenePartitions.ContainsKey(localId)) + // { + // Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}"); + // continue; + // } + + // Data.SceneGrid.Insert(localId, gameObject.transform.position); + //} + + GlobalObjectId[] ids = new GlobalObjectId[rootGameObjects.Length]; + GlobalObjectId.GetGlobalObjectIdsSlow(rootGameObjects, ids); + + for (int i = 0; i < ids.Length; i++) { - // https://forum.unity.com/threads/how-to-get-the-local-identifier-in-file-for-scene-objects.265686/ - PropertyInfo inspectorModeInfo = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance); - SerializedObject serializedObject = new SerializedObject(gameObject.transform); - inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null); - SerializedProperty localIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile"); + Debug.Log($"{ids[i].assetGUID} | {ids[i].identifierType} | {ids[i].targetObjectId} | {ids[i].targetPrefabId}"); - uint localId = (uint)localIdProp.intValue; - - if (Data.ScenePartitions.ContainsKey(localId)) + if (ids[i].targetPrefabId == 0) // 0 = no prefab. { - Data.SceneGrid.Insert(localId, gameObject.transform.position); + Data.SceneGrid.Insert((long)ids[i].targetObjectId, rootGameObjects[i].transform.position); } else { - Debug.LogWarning($"Could not find LocalIdentfierInFile for {gameObject.transform} {gameObject.name} {gameObject.transform.GetInstanceID()}"); + Data.SceneGrid.Insert((long)ids[i].targetPrefabId, rootGameObjects[i].transform.position); } } @@ -244,10 +294,15 @@ public void GenerateSceneGridData() public void LoadCell(int gridId) { - if (Data.SceneGrid.Grid.TryGetValue(gridId, out List ids)) + if (Data.SceneGrid.Grid.TryGetValue(gridId, out List ids)) { LoadPartitions(ids.ToArray()); } } + + public void ClearCache() + { + data = null; + } } } \ No newline at end of file diff --git a/Editor/ScenePartitionSOEditor.cs b/Editor/ScenePartitionSOEditor.cs index 9ee3ae7..b69446a 100644 --- a/Editor/ScenePartitionSOEditor.cs +++ b/Editor/ScenePartitionSOEditor.cs @@ -7,7 +7,7 @@ namespace VertexColor.ScenePartition.Editor [CustomEditor(typeof(ScenePartitionSO))] public class ScenePartitionSOEditor : UnityEditor.Editor { - private int id = 0; + private long id = 0; private int gridId = 0; public override void OnInspectorGUI() @@ -60,11 +60,11 @@ public override void OnInspectorGUI() EditorGUILayout.Space(); - id = EditorGUILayout.IntField("id", id); + id = EditorGUILayout.LongField("id", id); if (GUILayout.Button("Load Section")) { - scenePartitionSO.LoadPartitions(new uint[1] { (uint)id }); + scenePartitionSO.LoadPartitions(new long[1] { (long)id }); } if (GUILayout.Button("GenerateSceneGrid")) @@ -83,20 +83,26 @@ public override void OnInspectorGUI() { EditorGUILayout.LabelField($"generatedSceneGrid"); - foreach (KeyValuePair> item in scenePartitionSO.Data.SceneGrid.Grid) + foreach (KeyValuePair> item in scenePartitionSO.Data.SceneGrid.Grid) { - EditorGUILayout.IntField("gridId", item.Key); + EditorGUILayout.LongField("gridId", item.Key); EditorGUI.indentLevel++; - foreach (uint id in item.Value) + foreach (long id in item.Value) { - EditorGUILayout.IntField((int)id); + EditorGUILayout.LongField(id); } EditorGUI.indentLevel--; } } + + if (GUILayout.Button("ClearCache")) + { + scenePartitionSO.ClearCache(); + ScenePartitionSS.instance.SceneDataCache.Clear(); + } } } } diff --git a/Editor/ScenePartitionUtils.cs b/Editor/ScenePartitionUtils.cs index d90aca3..56b6cfe 100644 --- a/Editor/ScenePartitionUtils.cs +++ b/Editor/ScenePartitionUtils.cs @@ -26,26 +26,26 @@ public static string GetScenePath(ScenePartitionSO scenePartitionSO) return scenePath; } - public static SortedSet FindDeeplyLinkedObjects(SortedList scenePartitions, uint partitionId) + public static SortedSet FindDeeplyLinkedObjects(SortedList scenePartitions, long partitionId) { - SortedSet linkedObjects = new SortedSet(); + SortedSet linkedObjects = new SortedSet(); FindDeeplyLinkedObjectsRecursive(scenePartitions, partitionId, linkedObjects); return linkedObjects; } - private static void FindDeeplyLinkedObjectsRecursive(SortedList scenePartitions, uint partitionId, SortedSet linkedObjects) + private static void FindDeeplyLinkedObjectsRecursive(SortedList scenePartitions, long partitionId, SortedSet linkedObjects) { if (linkedObjects.Contains(partitionId)) return; if (!scenePartitions.TryGetValue(partitionId, out ScenePartition partition)) return; linkedObjects.Add(partitionId); - foreach (uint reference in partition.references) + foreach (long reference in partition.references) { FindDeeplyLinkedObjectsRecursive(scenePartitions, reference, linkedObjects); if (scenePartitions.TryGetValue(reference, out ScenePartition referencedPartition)) { - foreach (uint subReference in referencedPartition.references) + foreach (long subReference in referencedPartition.references) { FindDeeplyLinkedObjectsRecursive(scenePartitions, subReference, linkedObjects); } diff --git a/Runtime/SceneGrid.cs b/Runtime/SceneGrid.cs index 4edf4f4..b673d7a 100644 --- a/Runtime/SceneGrid.cs +++ b/Runtime/SceneGrid.cs @@ -14,16 +14,16 @@ public class SceneGrid public SceneGridDictionary Grid => grid; - public void Insert(uint id, Vector3 point) + public void Insert(long scenePartitionId, Vector3 point) { int gridId = CalculateGridPosition(point, cellSize); - if (grid.TryGetValue(gridId, out List ids)) + if (grid.TryGetValue(gridId, out List ids)) { - ids.Add(id); + ids.Add(scenePartitionId); } else { - grid.Add(gridId, new List { id }); + grid.Add(gridId, new List { scenePartitionId }); } } @@ -49,5 +49,20 @@ public static (int, int) IntToIntPair(int value) return (x, y); } + + public static long LongPairToLong(long x, long y) + { + // Combine x and y components into a single long + return (x << 32) | (uint)y; + } + + public static (long, long) LongToLongPair(long value) + { + // Extract x and y components from the combined long + long x = value >> 32; + long y = (uint)value; + + return (x, y); + } } } diff --git a/Runtime/ScenePartition.cs b/Runtime/ScenePartition.cs index 6ce135c..e2ec904 100644 --- a/Runtime/ScenePartition.cs +++ b/Runtime/ScenePartition.cs @@ -24,10 +24,11 @@ public int Compare(ScenePartition x, ScenePartition y) [System.Serializable] public class ScenePartition { - public uint id = 0; + public long id = 0; + //public long classId = 0; public string filePath = null; //public string[] data = null; - public UintSortedSet references = new UintSortedSet(); + public LongSortedSet references = new LongSortedSet(); public ScenePartition(string filePath) { @@ -44,9 +45,19 @@ public ScenePartition(string filePath) Match match = Regex.Match(data[0], pattern); if (!match.Success) return; - if (!uint.TryParse(match.Groups[1].Value, out id)) return; + if (!long.TryParse(match.Groups[1].Value, out id)) return; } + //{ // Get class id. + // string pattern = @"!u!(\d+)"; + + // // Find all matches using regex + // Match match = Regex.Match(data[0], pattern); + + // if (!match.Success) return; + // if (!long.TryParse(match.Groups[1].Value, out classId)) return; + //} + { // Get references. string pattern = @"fileID:\s(\d+)"; @@ -57,7 +68,7 @@ public ScenePartition(string filePath) if (!match.Success) continue; - if (uint.TryParse(match.Groups[1].Value, out uint fileNumber)) + if (long.TryParse(match.Groups[1].Value, out long fileNumber)) { if (fileNumber == 0) continue; // 0 == nothing. diff --git a/Runtime/SerializedStructures.cs b/Runtime/SerializedStructures.cs index e14a0c9..8780138 100644 --- a/Runtime/SerializedStructures.cs +++ b/Runtime/SerializedStructures.cs @@ -3,11 +3,11 @@ namespace VertexColor.ScenePartition { [System.Serializable] - public class ScenePartitionSortedList : SerializableSortedList { } + public class ScenePartitionSortedList : SerializableSortedList { } [System.Serializable] - public class UintSortedSet : SerializableSortedSet { } + public class LongSortedSet : SerializableSortedSet { } [System.Serializable] - public class SceneGridDictionary : SerializableDictionary> { } + public class SceneGridDictionary : SerializableDictionary> { } } \ No newline at end of file