diff --git a/Editor/ScenePartition.cs b/Editor/ScenePartition.cs index 7e89a78..130faa6 100644 --- a/Editor/ScenePartition.cs +++ b/Editor/ScenePartition.cs @@ -27,7 +27,7 @@ public class ScenePartition public uint id = 0; public string filePath = null; public string[] data = null; - public HashSet references = new HashSet(); + public SerializableSortedSet references = new SerializableSortedSet(); public ScenePartition(string filePath) { diff --git a/Editor/ScenePartitionDataSO.cs b/Editor/ScenePartitionDataSO.cs new file mode 100644 index 0000000..f5775e4 --- /dev/null +++ b/Editor/ScenePartitionDataSO.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace VertexColor.ScenePartition.Editor +{ + [CreateAssetMenu(fileName = "Scene", menuName = "Max/ScenePartitionDataSO")] + public class ScenePartitionDataSO : ScriptableObject + { + public bool hasCreatedPartitions => scenePartitions != null && scenePartitions.Count > 0; + public SerializableSortedList scenePartitions = new SerializableSortedList(); + + public bool hasLoadedPartitions => loadedScenePartitions != null && loadedScenePartitions.Count > 0; + public SerializableSortedList loadedScenePartitions = new SerializableSortedList(); + } +} \ No newline at end of file diff --git a/Editor/ScenePartitionDataSO.cs.meta b/Editor/ScenePartitionDataSO.cs.meta new file mode 100644 index 0000000..6766ee5 --- /dev/null +++ b/Editor/ScenePartitionDataSO.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 53d6bea45132f6d4aa3aa1631099564e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ScenePartitionDataSOEditor.cs b/Editor/ScenePartitionDataSOEditor.cs new file mode 100644 index 0000000..0d2fab5 --- /dev/null +++ b/Editor/ScenePartitionDataSOEditor.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using UnityEditor; + +namespace VertexColor.ScenePartition.Editor +{ + [CustomEditor(typeof(ScenePartitionDataSO))] + public class ScenePartitionDataSOEditor : UnityEditor.Editor + { + public override void OnInspectorGUI() + { + ScenePartitionDataSO scenePartitionDataSO = (target as ScenePartitionDataSO); + + DrawDefaultInspector(); + + serializedObject.Update(); + //EditorGUILayout.PropertyField(sceneAssetProperty); + serializedObject.ApplyModifiedProperties(); + + EditorGUILayout.Space(); + + using (new EditorGUI.DisabledGroupScope(true)) + { + if (scenePartitionDataSO.hasCreatedPartitions) + { + EditorGUILayout.LabelField($"scenePartitions"); + + foreach (KeyValuePair scenePartition in scenePartitionDataSO.scenePartitions) + { + EditorGUILayout.IntField((int)scenePartition.Value.id); + if (scenePartition.Value.references != null && scenePartition.Value.references.Count > 0) + { + EditorGUI.indentLevel++; + foreach (var reference in scenePartition.Value.references) + { + EditorGUILayout.IntField((int)reference); + } + EditorGUI.indentLevel--; + } + } + } + + EditorGUILayout.Space(); + + if (scenePartitionDataSO.hasLoadedPartitions) + { + EditorGUILayout.LabelField($"loadedScenePartitions"); + + foreach (KeyValuePair scenePartition in scenePartitionDataSO.loadedScenePartitions) + { + EditorGUILayout.IntField((int)scenePartition.Value.id); + if (scenePartition.Value.references != null && scenePartition.Value.references.Count > 0) + { + EditorGUI.indentLevel++; + foreach (var reference in scenePartition.Value.references) + { + EditorGUILayout.IntField((int)reference); + } + EditorGUI.indentLevel--; + } + } + } + } + } + } +} diff --git a/Editor/ScenePartitionDataSOEditor.cs.meta b/Editor/ScenePartitionDataSOEditor.cs.meta new file mode 100644 index 0000000..a05e854 --- /dev/null +++ b/Editor/ScenePartitionDataSOEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b9bf98e36efc7b4dbac2b8a7be74407 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ScenePartitionSO.cs b/Editor/ScenePartitionSO.cs index c92bf16..c91c335 100644 --- a/Editor/ScenePartitionSO.cs +++ b/Editor/ScenePartitionSO.cs @@ -13,12 +13,9 @@ public class ScenePartitionSO : ScriptableObject [field: SerializeField] public SceneAsset sceneAsset { get; private set; } = null; public string sceneName => sceneAsset == null ? name : sceneAsset.name; + public ScenePartitionDataSO scenePartitionData = null; - public bool hasCreatedPartitions => scenePartitions != null && scenePartitions.Count > 0; - public SortedList scenePartitions = null; - - public bool hasLoadedPartitions => loadedScenePartitions != null && loadedScenePartitions.Count > 0; - public SortedList loadedScenePartitions = null; + public List alwaysLoadIds = new List { 0, 1, 2, 3, 4 }; public void CreateScene() { @@ -43,7 +40,7 @@ public void CreateScene() public void LoadAll() { CreateScenePartitions(); - SortedSet ids = new SortedSet(scenePartitions.Keys); + SortedSet ids = new SortedSet(scenePartitionData.scenePartitions.Keys); LoadScenePartitions(ids); } @@ -52,34 +49,40 @@ private void CreateScenePartitions() string dataPath = ScenePartitionUtils.GetDataPath(this); string[] files = Directory.GetFiles(dataPath); - scenePartitions = new SortedList(); + scenePartitionData.scenePartitions = new SerializableSortedList(); for (int i = 0; i < files.Length; i++) { ScenePartition scenePartition = new ScenePartition(files[i]); - scenePartitions.Add(scenePartition.id, scenePartition); + scenePartitionData.scenePartitions.Add(scenePartition.id, scenePartition); } } private void LoadScenePartitions(SortedSet partitionIds) { - if (!hasCreatedPartitions) return; + if (!scenePartitionData.hasCreatedPartitions) return; string scenePath = ScenePartitionUtils.GetScenePath(this); List data = new List(); - loadedScenePartitions = new SortedList(); + scenePartitionData.loadedScenePartitions.Clear(); - // Add the header. - partitionIds.Add(0); + // Add default ids. + for (int i = 0; i < alwaysLoadIds.Count; i++) + { + if (scenePartitionData.scenePartitions.ContainsKey(alwaysLoadIds[i])) + { + partitionIds.Add(alwaysLoadIds[i]); + } + } // Create scene data. foreach (uint id in partitionIds) { - ScenePartition p = scenePartitions[id]; + ScenePartition p = scenePartitionData.scenePartitions[id]; data.AddRange(p.data); - loadedScenePartitions.Add(p.id, p); + scenePartitionData.loadedScenePartitions.Add(p.id, p); } // Create scene. @@ -91,9 +94,10 @@ private void LoadScenePartitions(SortedSet partitionIds) /// /// Convert scene to partitions and save them to disk. /// - public void SaveAll() + public void Save() { - if (!hasCreatedPartitions) return; + if (!scenePartitionData.hasCreatedPartitions) return; + if (!scenePartitionData.hasLoadedPartitions) return; DeleteLoadedPartitions(); // Delete the loaded partitions from disk so we can write the new ones. @@ -140,23 +144,23 @@ public void Unload() EditorSceneManager.SaveScene(scene); - scenePartitions.Clear(); + scenePartitionData.scenePartitions.Clear(); AssetDatabase.Refresh(); } private void DeleteLoadedPartitions() { - if (!hasCreatedPartitions) return; + if (!scenePartitionData.hasCreatedPartitions) return; - foreach (KeyValuePair scenePartition in scenePartitions) + foreach (KeyValuePair scenePartition in scenePartitionData.scenePartitions) { if (!File.Exists(scenePartition.Value.filePath)) continue; File.Delete(scenePartition.Value.filePath); } - scenePartitions.Clear(); + scenePartitionData.loadedScenePartitions.Clear(); } public void LoadPartitions(uint[] ids) @@ -165,7 +169,7 @@ public void LoadPartitions(uint[] ids) for (int i = 0; i < ids.Length; i++) { - SortedSet connections = ScenePartitionUtils.FindDeeplyLinkedObjects(scenePartitions, ids[i]); + SortedSet connections = ScenePartitionUtils.FindDeeplyLinkedObjects(scenePartitionData.scenePartitions, ids[i]); foreach (uint c in connections) { diff --git a/Editor/ScenePartitionSOEditor.cs b/Editor/ScenePartitionSOEditor.cs index 2118176..20558b4 100644 --- a/Editor/ScenePartitionSOEditor.cs +++ b/Editor/ScenePartitionSOEditor.cs @@ -34,11 +34,11 @@ public override void OnInspectorGUI() scenePartitionSO.LoadAll(); } - if (scenePartitionSO.hasCreatedPartitions) + if (scenePartitionSO.scenePartitionData.hasCreatedPartitions) { - if (GUILayout.Button("Save All")) + if (GUILayout.Button("Save")) { - scenePartitionSO.SaveAll(); + scenePartitionSO.Save(); } } @@ -58,50 +58,11 @@ public override void OnInspectorGUI() id = EditorGUILayout.IntField("id", id); - if (GUILayout.Button("Test Load")) + if (GUILayout.Button("Load Section")) { scenePartitionSO.LoadPartitions(new uint[1] { (uint)id }); } } - - EditorGUILayout.Space(); - - using (new EditorGUI.DisabledGroupScope(true)) - { - if (scenePartitionSO.hasCreatedPartitions) - { - EditorGUILayout.LabelField($"scenePartitions"); - - foreach (System.Collections.Generic.KeyValuePair scenePartition in scenePartitionSO.scenePartitions) - { - EditorGUILayout.IntField((int)scenePartition.Value.id); - EditorGUI.indentLevel++; - foreach (var reference in scenePartition.Value.references) - { - EditorGUILayout.IntField((int)reference); - } - EditorGUI.indentLevel--; - } - } - - EditorGUILayout.Space(); - - if (scenePartitionSO.hasLoadedPartitions) - { - EditorGUILayout.LabelField($"loadedScenePartitions"); - - foreach (System.Collections.Generic.KeyValuePair scenePartition in scenePartitionSO.loadedScenePartitions) - { - EditorGUILayout.IntField((int)scenePartition.Value.id); - EditorGUI.indentLevel++; - foreach (var reference in scenePartition.Value.references) - { - EditorGUILayout.IntField((int)reference); - } - EditorGUI.indentLevel--; - } - } - } } } } \ No newline at end of file diff --git a/Runtime/SerializationUtility.cs b/Runtime/SerializationUtility.cs new file mode 100644 index 0000000..e69202d --- /dev/null +++ b/Runtime/SerializationUtility.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace VertexColor.ScenePartition +{ + [Serializable] + public class SerializableDictionary : Dictionary, ISerializationCallbackReceiver + { + [SerializeField] + private List keys = new List(); + [SerializeField] + private List values = new List(); + + public void OnBeforeSerialize() + { + keys.Clear(); + values.Clear(); + + foreach (KeyValuePair pair in this) + { + keys.Add(pair.Key); + values.Add(pair.Value); + } + } + + public void OnAfterDeserialize() + { + Clear(); + + if (keys.Count != values.Count) + { + throw new Exception("Error: Key and value count does not match in the dictionary."); + } + + for (int i = 0; i < keys.Count; i++) + { + Add(keys[i], values[i]); + } + } + } + + [Serializable] + public class SerializableSortedList : SortedList, ISerializationCallbackReceiver + { + [SerializeField] + private List keys = new List(); + [SerializeField] + private List values = new List(); + + public void OnBeforeSerialize() + { + keys.Clear(); + values.Clear(); + + foreach (KeyValuePair pair in this) + { + keys.Add(pair.Key); + values.Add(pair.Value); + } + } + + public void OnAfterDeserialize() + { + Clear(); + + if (keys.Count != values.Count) + { + throw new Exception("Error: Key and value count does not match in the dictionary."); + } + + for (int i = 0; i < keys.Count; i++) + { + Add(keys[i], values[i]); + } + } + } + + [Serializable] + public class SerializableSortedSet : SortedSet, ISerializationCallbackReceiver + { + [SerializeField] + private List elements = new List(); + + public void OnBeforeSerialize() + { + elements.Clear(); + elements.AddRange(this); + } + + public void OnAfterDeserialize() + { + Clear(); + + for (int i = 0; i < elements.Count; i++) + { + Add(elements[i]); + } + } + } +} \ No newline at end of file diff --git a/Runtime/SerializationUtility.cs.meta b/Runtime/SerializationUtility.cs.meta new file mode 100644 index 0000000..35999cb --- /dev/null +++ b/Runtime/SerializationUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d20cd39f6cd10914188acde7ee871339 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: