public static string GetPath(Hash128 sceneGUID, PathType type, string subsectionName) { if (sceneGUID == new Hash128()) { return(""); } string sceneName = sceneGUID.ToString(); if (!String.IsNullOrEmpty(subsectionName)) { sceneName += "_" + subsectionName; } if (type == PathType.EntitiesSharedComponents) { return("Assets/EntityCache/Resources/" + sceneName + "_shared.prefab"); } if (type == PathType.EntitiesHeader) { return("Assets/EntityCache/Resources/" + sceneName + "_header.asset"); } if (type == PathType.EntitiesBinary) { return("Assets/StreamingAssets/EntityCache/" + sceneName + ".entities"); } throw new ArgumentException(); }
public void UpdateObjectManifest(Hash128 guid, AssetObjectManifest manifest) { var resolved = _Assets[guid]; resolved.AssetObjectManifest = manifest; _Assets[guid] = resolved; }
public void UpdateTargetHash(Hash128 guid, Hash128 targetHash) { var resolved = _Assets[guid]; resolved.TargetHash = targetHash; _Assets[guid] = resolved; }
public static string GetLoadPath(Hash128 sceneGUID, PathType type, int sectionIndex) { if (type == PathType.EntitiesSharedComponents) { return($"{sceneGUID}_{sectionIndex}_shared"); } else if (type == PathType.EntitiesHeader) { return(GetPath(sceneGUID, type, "")); } var path = GetPath(sceneGUID, type, sectionIndex.ToString()); if (type == PathType.EntitiesBinary) { return(Application.streamingAssetsPath + "/EntityCache/" + Path.GetFileName(path)); } else if (type == PathType.EntitiesSharedComponents) { return(Path.GetFileNameWithoutExtension(path)); } else { return(path); } }
void AddLiveLinkChangeSet(Hash128 sceneGUID, List <LiveLinkChangeSet> changeSets, LiveLinkMode mode) { var liveLink = GetLiveLink(sceneGUID); var editScene = _GUIDToEditScene[sceneGUID]; // The current behaviour is that we do incremental conversion until we release the hot control // This is to avoid any unexpected stalls // Optimally the undo system would tell us if only properties have changed, but currently we don't have such an event stream. var sceneDirtyID = GetSceneDirtyID(editScene); var updateLiveLink = true; if (IsHotControlActive()) { if (liveLink != null) { sceneDirtyID = liveLink.LiveLinkDirtyID; } else { updateLiveLink = false; EditorUpdateUtility.EditModeQueuePlayerLoopUpdate(); } } else { if (liveLink != null && liveLink.LiveLinkDirtyID != sceneDirtyID) { liveLink.RequestCleanConversion(); } } if (updateLiveLink) { //@TODO: need one place that LiveLinkDiffGenerators are managed. UpdateLiveLink does a Dispose() // but this must be paired with membership in _SceneGUIDToLiveLink. not good to have multiple places // doing ownership management. // // also: when implementing an improvement to this, be sure to deal with exceptions, which can occur // during conversion. if (liveLink != null) { _SceneGUIDToLiveLink.Remove(sceneGUID); } try { changeSets.Add(LiveLinkDiffGenerator.UpdateLiveLink(editScene, sceneGUID, ref liveLink, sceneDirtyID, mode, _BuildSettings)); } finally { if (liveLink != null) { _SceneGUIDToLiveLink.Add(sceneGUID, liveLink); } } } }
public void AddAsset(Hash128 guid, Hash128 targetHash, AssetObjectManifest manifest, AssetBundle assetBundle) { _Assets[guid] = new Resolved { AssetObjectManifest = manifest, AssetBundle = assetBundle, TargetHash = targetHash }; }
public static string CalculateStreamingAssetsPath(Hash128 containerIdentifier) { StringBuilder sb = new StringBuilder(128); sb.Append(Application.streamingAssetsPath); sb.Append("/SavedSceneStates/"); sb.Append(containerIdentifier.ToString()); sb.Append(".sav"); return(sb.ToString()); }
public static Hash128 GetSubSceneArtifactHash(Hash128 sceneGUID, Hash128 buildConfigurationGUID, ImportMode importMode) { var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(sceneGUID, buildConfigurationGUID); if (!s_HashToString.TryGetValue(guid, out var guidString)) { guidString = s_HashToString[guid] = guid.ToString(); } return(AssetDatabaseCompatibility.GetArtifactHash(guidString, SubSceneImporterType, importMode)); }
public AssetBundle GetAssetBundle(Hash128 requestedGUID) { if (_Assets.TryGetValue(requestedGUID, out var resolved)) { return(resolved.AssetBundle); } else { return(null); } }
void AddLiveLinkChangeSet(ref LiveLinkDiffGenerator liveLink, Hash128 sceneGUID, List <LiveLinkChangeSet> changeSets, LiveLinkMode mode) { var editScene = _GUIDToEditScene[sceneGUID]; int sceneDirtyID = 0; #if !UNITY_2020_2_OR_NEWER // The current behaviour is that we do incremental conversion until we release the hot control // This is to avoid any unexpected stalls if (IsHotControlActive()) { if (liveLink == null) { EditorUpdateUtility.EditModeQueuePlayerLoopUpdate(); return; } sceneDirtyID = liveLink.LiveLinkDirtyID; } else { sceneDirtyID = GetSceneDirtyID(editScene); if (liveLink != null && liveLink.LiveLinkDirtyID != sceneDirtyID) { liveLink.RequestCleanConversion(); } } #endif //@TODO: need one place that LiveLinkDiffGenerators are managed. UpdateLiveLink does a Dispose() // but this must be paired with membership in _SceneGUIDToLiveLink. not good to have multiple places // doing ownership management. // // also: when implementing an improvement to this, be sure to deal with exceptions, which can occur // during conversion. if (liveLink != null) { _SceneGUIDToLiveLink.Remove(sceneGUID); } try { changeSets.Add(LiveLinkDiffGenerator.UpdateLiveLink(editScene, sceneGUID, ref liveLink, sceneDirtyID, mode, _BuildConfigurationGUID, _BuildConfiguration)); } finally { if (liveLink != null) { _SceneGUIDToLiveLink.Add(sceneGUID, liveLink); } } }
public static Hash128 GetObjectGuidHash(Object asset) { Assert.IsNotNull(asset, "Asset cannot be null"); if (!AssetDatabase.Contains(asset)) { return(new Hash128((uint)asset.GetInstanceID(), 0, 0, 0)); } AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long fileId); var guidHash = new Hash128(guid); var fileIdHash = new Hash128((uint)fileId, 0, 0, 0); guidHash.Value += fileIdHash.Value; return(guidHash); }
public static Hash128 GetSubSceneArtifactHash(Hash128 sceneGUID, Hash128 buildConfigurationGUID, bool isBuildingForEditor, ImportMode importMode) { var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(sceneGUID, buildConfigurationGUID, isBuildingForEditor, out var mustRequestRefresh); if (mustRequestRefresh) { UnityEditor.AssetDatabase.Refresh(); } if (!s_HashToString.TryGetValue(guid, out var guidString)) { guidString = s_HashToString[guid] = guid.ToString(); } return(AssetDatabaseCompatibility.GetArtifactHash(guidString, SubSceneImporterType, importMode)); }
public void UnloadAsset(Hash128 assetId) { if (_Assets.TryGetValue(assetId, out var resolved)) { if (resolved.AssetBundle != null) { resolved.AssetBundle.Unload(true); } if (resolved.AssetObjectManifest != null) { Object.DestroyImmediate(resolved.AssetObjectManifest); } _Assets.Remove(assetId); } }
public void SetUpOnce() { #if UNITY_EDITOR try { BuildConfiguration.CreateAsset(m_BuildConfigPath, config => { config.SetComponent(new SceneList { SceneInfos = new List <SceneList.SceneInfo> { new SceneList.SceneInfo { Scene = GlobalObjectId.GetGlobalObjectIdSlow( AssetDatabase.LoadAssetAtPath <SceneAsset>(m_SubScenePath)) } } }); }); m_BuildConfigurationGUID = new GUID(AssetDatabase.AssetPathToGUID(m_BuildConfigPath)); m_SceneGUID = new GUID(AssetDatabase.AssetPathToGUID(m_SubScenePath)); var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(m_SceneGUID, m_BuildConfigurationGUID, true, out var requestRefresh); if (requestRefresh) { AssetDatabase.Refresh(); } m_SceneWithBuildSettingsPath = SceneWithBuildConfigurationGUIDs.GetSceneWithBuildSettingsPath(guid); EntityScenesPaths.GetSubSceneArtifactHash(m_SceneGUID, m_BuildConfigurationGUID, true, ImportMode.Synchronous); } catch { AssetDatabase.DeleteAsset(m_TempPath); AssetDatabase.DeleteAsset(m_SceneWithBuildSettingsPath); throw; } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); #else //TODO: Playmode test not supported yet m_SceneGUID = new Unity.Entities.Hash128(); #endif }
public LiveLinkConnection(Hash128 buildSettingsGuid) { _BuildSettingsGUID = buildSettingsGuid; if (buildSettingsGuid != default) { _BuildSettings = BuildSettings.LoadAsset(buildSettingsGuid); if (_BuildSettings == null) { Debug.LogError($"Unable to load build settings asset from guid {buildSettingsGuid}."); } } Undo.postprocessModifications += PostprocessModifications; Undo.undoRedoPerformed += GlobalDirtyLiveLink; _RemovedScenes = new NativeList <Hash128>(Allocator.Persistent); }
public static string GetPathAndCreateDirectory(Hash128 sceneGUID, PathType type, string subsectionName) { var path = GetPath(sceneGUID, type, subsectionName); if (String.IsNullOrEmpty(path)) { return(""); } var dir = Path.GetDirectoryName(path); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } return(path); }
public LiveLinkConnection(Hash128 buildConfigurationGuid) { _BuildConfigurationGUID = buildConfigurationGuid; if (buildConfigurationGuid != default) { _BuildConfiguration = BuildConfiguration.LoadAsset(buildConfigurationGuid); if (_BuildConfiguration == null) { Debug.LogError($"Unable to load build configuration asset from guid {buildConfigurationGuid}."); } } Undo.postprocessModifications += PostprocessModifications; Undo.undoRedoPerformed += GlobalDirtyLiveLink; _RemovedScenes = new NativeList <Hash128>(Allocator.Persistent); m_AssetDependencies = new UnsafeHashMap <GUID, byte>(100, Allocator.Persistent); k_AllConnections.Add(this); }
public static string RelativePathInStreamingAssetsFolderFor(Hash128 sceneGUID, PathType type, int sectionIndex) { var extension = GetExtension(type); switch (type) { case PathType.EntitiesBinary: return($"SubScenes/{sceneGUID}.{sectionIndex}.{extension}"); case PathType.EntitiesHeader: return($"SubScenes/{sceneGUID}.{extension}"); case PathType.EntitiesUnityObjectReferences: return($"SubScenes/{sceneGUID}.{sectionIndex}.bundle"); default: throw new ArgumentException(); } }
public void Validate(Hash128 guid) { if (!_Assets.TryGetValue(guid, out var resolved)) { Debug.LogError("GlobalAssetObjectResolver Validate failed! => GUID not known"); return; } if (resolved.AssetBundle == null) { Debug.LogError($"GlobalAssetObjectResolver Validate failed! => AssetBundle '{guid.ToString()}' not loadable"); return; } if (resolved.AssetObjectManifest == null) { if (!resolved.AssetBundle.isStreamedSceneAssetBundle) { Debug.LogError($"GlobalAssetObjectResolver Validate failed! => ObjectManifest in '{guid.ToString()}' not loadable"); } return; } //@TODO: We currently have no way of stripping objects that are editor only, // so we can't perform these checks because some of these objects will in fact be null #if false for (int i = 0; i < resolved.AssetObjectManifest.Objects.Length; i++) { Object obj = resolved.AssetObjectManifest.Objects[i]; if (obj == null) { //@TODO: Follow up with ryan why these are failing if (guid.ToString() != k_BuiltInResourcesGuid) { Debug.LogError($"Object in '{guid.ToString()}' not loadable at index {i}."); } } } #endif }
public LiveLinkConnection(Hash128 buildConfigurationGuid) { _BuildConfigurationGUID = buildConfigurationGuid; if (buildConfigurationGuid != default) { _BuildConfiguration = BuildConfiguration.LoadAsset(buildConfigurationGuid); if (_BuildConfiguration == null) { Debug.LogError($"Unable to load build configuration asset from guid {buildConfigurationGuid}."); } } #if UNITY_2020_2_OR_NEWER ObjectChangeEvents.changesPublished += OnEditorChangeEvents; EditorSceneManager.sceneOpened += SceneOpened; EditorSceneManager.sceneClosed += SceneClosed; #else Undo.postprocessModifications += PostprocessModifications; Undo.undoRedoPerformed += OnUndoPerformed; #endif _RemovedScenes = new NativeList <Hash128>(Allocator.Persistent); k_AllConnections.Add(this); }
public void SendInitialScenes(int playerId) { var sceneList = _BuildConfiguration.GetComponent <SceneList>(); var nonEmbeddedStartupScenes = new List <string>(); foreach (var path in sceneList.GetScenePathsToLoad()) { if (SceneImporterData.CanLiveLinkScene(path)) { nonEmbeddedStartupScenes.Add(path); } } if (nonEmbeddedStartupScenes.Count > 0) { var sceneIds = new NativeArray <Hash128>(nonEmbeddedStartupScenes.Count, Allocator.Temp); for (int i = 0; i < nonEmbeddedStartupScenes.Count; i++) { sceneIds[i] = new Hash128(AssetDatabase.AssetPathToGUID(nonEmbeddedStartupScenes[i])); } EditorConnection.instance.SendArray(LiveLinkMsg.ResponseConnectLiveLink, sceneIds, playerId); sceneIds.Dispose(); } }
public NativeArray <Hash128> GetInitialScenes(int playerId, Allocator allocator) { var sceneList = _BuildConfiguration.GetComponent <SceneList>(); var nonEmbeddedStartupScenes = new List <string>(); foreach (var path in sceneList.GetScenePathsToLoad()) { if (SceneImporterData.CanLiveLinkScene(path)) { nonEmbeddedStartupScenes.Add(path); } } if (nonEmbeddedStartupScenes.Count > 0) { var sceneIds = new NativeArray <Hash128>(nonEmbeddedStartupScenes.Count, allocator); for (int i = 0; i < nonEmbeddedStartupScenes.Count; i++) { sceneIds[i] = new Hash128(AssetDatabase.AssetPathToGUID(nonEmbeddedStartupScenes[i])); } return(sceneIds); } return(new NativeArray <Hash128>(0, allocator)); }
public bool HasAsset(Hash128 hash) { return(_Assets.ContainsKey(hash)); }
// index -1 means 'use current index' public static int ReadContainerFromDisk(this PersistentSceneSystem persistentSceneSystem, Hash128 containerIdentifier, int index = -1) { // Path string path = CalculateStreamingAssetsPath(containerIdentifier); Debug.Assert(File.Exists(path)); // Read From Disk using (var fileStream = new StreamBinaryReader(path)) { PersistentDataStorage dataStorage = persistentSceneSystem.PersistentDataStorage; int amountEntitiesInFile = fileStream.ReadInt(); if (!dataStorage.IsInitialized(containerIdentifier)) { // Read before the scene has been loaded once this session int amountBytesOfRawData = fileStream.ReadInt(); NativeArray <byte> rawData = new NativeArray <byte>(amountBytesOfRawData, Allocator.Persistent); fileStream.ReadArray(rawData, rawData.Length); dataStorage.AddUninitializedSceneContainer(containerIdentifier, rawData); } else { int currentEntityCapacity = dataStorage.GetEntityCapacity(containerIdentifier, out bool isPool); if (amountEntitiesInFile != currentEntityCapacity) { if (isPool) { persistentSceneSystem.InstantChangePoolCapacity(containerIdentifier, amountEntitiesInFile); } else { throw new InvalidDataException($"The data in \"{path}\" is invalid. (.sav data only stays valid as long as the subscene doesn't change)"); } } // Container (Important that it happens after potential capacity change!) PersistentDataContainer container; if (index == -1) { container = dataStorage.GetWriteContainerForCurrentIndex(containerIdentifier); } else { int oldIndex = dataStorage.NonWrappedIndex; dataStorage.ToIndex(index); container = dataStorage.GetWriteContainerForCurrentIndex(containerIdentifier); dataStorage.ToIndex(oldIndex); } // Read Data From Disk NativeArray <byte> rawData = container.GetRawData(); int amountBytesOfRawData = fileStream.ReadInt(); if (amountBytesOfRawData != rawData.Length) { // Extra integrity Check throw new InvalidDataException($"The data in \"{path}\" is invalid. (maybe component data structs changed?)"); } fileStream.ReadArray(rawData, rawData.Length); } return(amountEntitiesInFile); } }
internal void GetConversionInfo(PersistencySettings persistencySettings, List <PersistableTypeHandle> listToFill, out int indexInScene, out Hash128 typeHandleCombinationHash) { Debug.Assert(listToFill.Count == 0); foreach (var fullTypeName in FullTypeNamesToPersist) { if (persistencySettings.ContainsType(fullTypeName)) { listToFill.Add(persistencySettings.GetPersistableTypeHandleFromFullTypeName(fullTypeName)); } else if (!string.IsNullOrEmpty(fullTypeName)) { Debug.LogWarning($"Ignoring non-persistable type {fullTypeName} (Did it get removed from PersistencySettings?)"); } } indexInScene = CalculateArrayIndex(persistencySettings); typeHandleCombinationHash = persistencySettings.GetTypeHandleCombinationHash(FullTypeNamesToPersist); }
public static string GetCachePath(Hash128 targetHash) { return($"{PersistentDataPath}/{k_LiveLinkCacheDir}/{targetHash}"); }
public static bool DoesContainerExistOnDisk(this PersistentSceneSystem persistentSceneSystem, Hash128 containerIdentifier) { return(File.Exists(CalculateStreamingAssetsPath(containerIdentifier))); }
public bool HasScene(Hash128 sceneGuid) { return(_LoadedScenes.Contains(sceneGuid)); }
public static string GetLoadPath(Hash128 sceneGUID, PathType type, int sectionIndex) { return(StreamingAssetsPath + "/" + RelativePathFolderFor(sceneGUID, type, sectionIndex)); }
LiveLinkDiffGenerator GetLiveLink(Hash128 sceneGUID) { _SceneGUIDToLiveLink.TryGetValue(sceneGUID, out var liveLink); return(liveLink); }