using System.Collections.Generic; using System.Linq; using UnityEngine; using System; using Newtonsoft.Json.Linq; using SLZ.Serialize; using UnityEngine.Serialization; #if UNITY_EDITOR using UnityEditor; using UnityEditor.SceneManagement; #endif namespace SLZ.Marrow.Warehouse { public class LevelCrate : Crate { [FormerlySerializedAs("_assetReference")] [SerializeField] private MarrowScene _mainAsset; public override MarrowAsset MainAsset { get => _mainAsset; set { if (value != null && value.GetType() == typeof(MarrowAsset)) { _mainAsset = new MarrowScene(value.AssetGUID); } else { _mainAsset = (MarrowScene)value; } } } public MarrowScene MainScene { get => _mainAsset; set => _mainAsset = value; } [SerializeField] private List _additionalAssetReferences = new List(); [Tooltip("Level has multiple scenes")] [SerializeField] private bool _multiScene = false; public bool MultiScene { get => _multiScene; set => _multiScene = value; } [Tooltip("Scenes that also load in when the root scene loads, and will stay always loaded in until level change")] [SerializeField] private List _persistentScenes = new List(); public List PersistentScenes => _persistentScenes; [Tooltip("Scenes that will be loaded dynamically in the level, for example: Chunk scenes loaded through a Chunk Trigger. All chunked scenes must be included here or they will not be included in the build")] [SerializeField] private List _chunkScenes = new List(); public List ChunkScenes => _chunkScenes; [Tooltip("Scenes that will ONLY load in the editor at design time, outside of playmode. They will NOT load in during builds, and will NOT be included in builds")] [SerializeField] private List _editorScenes = new List(); public List EditorScenes => _editorScenes; #if UNITY_EDITOR private string CURSED_SCENE_GUID = "99c9720ab356a0642a771bea13969a05"; [ContextMenu("Validate Scene Guid")] public void ValidateSceneGUID() { if (!string.IsNullOrEmpty(MainScene.AssetGUID)) { if (MainScene.AssetGUID == CURSED_SCENE_GUID) { var scenePath = AssetDatabase.GUIDToAssetPath(CURSED_SCENE_GUID); var metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(scenePath); var metaText = System.IO.File.ReadAllText(metaPath); if (metaText.Contains(CURSED_SCENE_GUID) && metaText.Contains($"guid: {CURSED_SCENE_GUID}")) { string newGuid = System.Guid.NewGuid().ToString("N"); metaText = metaText.Replace($"guid: {CURSED_SCENE_GUID}", $"guid: {newGuid}"); System.IO.File.WriteAllText(metaPath, metaText); MainScene = new MarrowScene(newGuid); EditorUtility.SetDirty(this); AssetDatabase.ImportAsset(scenePath); AssetDatabase.SaveAssetIfDirty(this); AssetDatabase.Refresh(); } } } } #endif #if UNITY_EDITOR public override System.Type AssetType { get => typeof(SceneAsset); } #else #endif #if UNITY_EDITOR public SceneSetup[] ToEditorSceneSetups() { var allScenesForEditor = new List(); allScenesForEditor.Add(MainScene); allScenesForEditor.AddRange(PersistentScenes.Select(assetRef => assetRef).Where(scene => scene.EditorAsset != null || scene.AssetGUID != string.Empty)); allScenesForEditor.AddRange(ChunkScenes.Select(assetRef => assetRef).Where(scene => scene.EditorAsset != null || scene.AssetGUID != string.Empty)); allScenesForEditor.AddRange(EditorScenes.Select(assetRef => assetRef).Where(scene => scene.EditorAsset != null || scene.AssetGUID != string.Empty)); var ret = new SceneSetup[allScenesForEditor.Count]; bool first = true; for (var i = 0; i < allScenesForEditor.Count; i++) { var sceneAsset = allScenesForEditor[i]; var sceneSetup = new SceneSetup { path = AssetDatabase.GUIDToAssetPath(sceneAsset.AssetGUID), isActive = first, isLoaded = true }; if (first) first = false; ret[i] = sceneSetup; } return ret; } #endif public override void ImportPackedAssets(Dictionary packedAssets) { if (packedAssets.TryGetValue("PersistentScenes", out var packedAsset) && packedAsset.HasSubAssets()) { foreach (var subAsset in packedAsset.subAssets) { PersistentScenes.Add(new MarrowScene(subAsset.subAsset.AssetGUID)); } } if (packedAssets.TryGetValue("ChunkScenes", out packedAsset) && packedAsset.HasSubAssets()) { foreach (var subAsset in packedAsset.subAssets) { ChunkScenes.Add(new MarrowScene(subAsset.subAsset.AssetGUID)); } } } public override List ExportPackedAssets() { base.ExportPackedAssets(); Type sceneAssetType = typeof(UnityEngine.SceneManagement.Scene); List subAssets = new List(); for (var i = 0; i < _persistentScenes.Count; i++) { var persistentScene = _persistentScenes[i]; string subTitle = i.ToString(); #if UNITY_EDITOR subTitle = $"{(persistentScene.EditorAsset != null ? MarrowSDK.SanitizeName(persistentScene.EditorAsset.name) : "")}-{subTitle}"; #endif subAssets.Add(new PackedSubAsset(subTitle, persistentScene)); } PackedAssets.Add(new PackedAsset("PersistentScenes", subAssets, sceneAssetType, "_persistentScenes")); subAssets = new List(); for (var i = 0; i < _chunkScenes.Count; i++) { var chunkScene = _chunkScenes[i]; string subTitle = i.ToString(); #if UNITY_EDITOR subTitle = $"{(chunkScene.EditorAsset != null ? MarrowSDK.SanitizeName(chunkScene.EditorAsset.name) : "")}-{subTitle}"; #endif subAssets.Add(new PackedSubAsset(subTitle, chunkScene)); } PackedAssets.Add(new PackedAsset("ChunkScenes", subAssets, sceneAssetType, "_chunkScenes")); return PackedAssets; } public override void Pack(ObjectStore store, JObject json) { base.Pack(store, json); json.Add("multiscene", MultiScene); } public override void Unpack(ObjectStore store, string objectId) { base.Unpack(store, objectId); if (store.TryGetJSON("multiscene", objectId, out JToken barcodeValue)) { _multiScene = barcodeValue.ToObject(); } } } }