예제 #1
0
        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;
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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
     };
 }
예제 #7
0
        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);
     }
 }
예제 #14
0
        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
        }
예제 #15
0
        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);
        }
예제 #16
0
        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);
        }
예제 #21
0
        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));
 }
예제 #24
0
        // 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);
            }
        }
예제 #25
0
        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}");
 }
예제 #27
0
 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);
 }