Example #1
0
        public static unsafe Hash128 CreateBuildConfigurationSceneFile(Hash128 sceneGUID, Hash128 buildConfigurationGUID)
        {
            var guid  = ComputeBuildConfigurationGUID(sceneGUID, buildConfigurationGUID);
            var guids = new SceneWithBuildConfigurationGUIDs {
                SceneGUID = sceneGUID, BuildConfiguration = buildConfigurationGUID
            };
            var dir      = "Assets/SceneDependencyCache";
            var fileName = $"{dir}/{guid}.sceneWithBuildConfiguration";

            if (!File.Exists(fileName))
            {
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
                using (var writer = new Entities.Serialization.StreamBinaryWriter(fileName))
                {
                    writer.WriteBytes(&guids, sizeof(SceneWithBuildConfigurationGUIDs));
                }
                File.WriteAllText(fileName + ".meta",
                                  $"fileFormatVersion: 2\nguid: {guid}\nDefaultImporter:\n  externalObjects: {{}}\n  userData:\n  assetBundleName:\n  assetBundleVariant:\n");

                // Refresh is necessary because it appears the asset pipeline
                // can't depend on an asset on disk that has not yet been refreshed.
                AssetDatabase.Refresh();
            }
            return(guid);
        }
        public static unsafe Hash128 EnsureExistsFor(Hash128 sceneGUID, Hash128 buildConfigurationGUID, out bool mustRequestRefresh)
        {
            mustRequestRefresh = false;
            var guid = ComputeBuildConfigurationGUID(sceneGUID, buildConfigurationGUID);

            if (s_BuildConfigurationCreated.Contains(guid))
            {
                return(guid);
            }

            var sceneWithBuildConfigurationGUIDs = new SceneWithBuildConfigurationGUIDs {
                SceneGUID = sceneGUID, BuildConfiguration = buildConfigurationGUID, DirtyValue = 0
            };

            var fileName = GetSceneWithBuildSettingsPath(ref guid);

            if (!File.Exists(fileName))
            {
                WriteSceneWithBuildSettings(ref guid, ref sceneWithBuildConfigurationGUIDs, fileName);
                mustRequestRefresh = true;
            }

            s_BuildConfigurationCreated.Add(guid);

            return(guid);
        }
Example #3
0
        public static unsafe Hash128 EnsureExistsFor(Hash128 sceneGUID, Hash128 buildConfigurationGUID)
        {
            var guid = ComputeBuildConfigurationGUID(sceneGUID, buildConfigurationGUID);

            if (s_BuildConfigurationCreated.Contains(guid))
            {
                return(guid);
            }

            var guids = new SceneWithBuildConfigurationGUIDs {
                SceneGUID = sceneGUID, BuildConfiguration = buildConfigurationGUID
            };

            var fileName = $"{k_SceneDependencyCachePath}/{guid}.sceneWithBuildSettings";

            if (!File.Exists(fileName))
            {
                Directory.CreateDirectory(k_SceneDependencyCachePath);
                using (var writer = new StreamBinaryWriter(fileName))
                {
                    writer.WriteBytes(&guids, sizeof(SceneWithBuildConfigurationGUIDs));
                }
                File.WriteAllText(fileName + ".meta",
                                  $"fileFormatVersion: 2\nguid: {guid}\nDefaultImporter:\n  externalObjects: {{}}\n  userData:\n  assetBundleName:\n  assetBundleVariant:\n");

                // Refresh is necessary because it appears the asset pipeline
                // can't depend on an asset on disk that has not yet been refreshed.
                AssetDatabase.Refresh();
            }

            s_BuildConfigurationCreated.Add(guid);

            return(guid);
        }
        public static unsafe SceneWithBuildConfigurationGUIDs ReadFromFile(string path)
        {
            SceneWithBuildConfigurationGUIDs sceneWithBuildConfiguration = default;

            using (var reader = new StreamBinaryReader(path))
            {
                reader.ReadBytes(&sceneWithBuildConfiguration, sizeof(SceneWithBuildConfigurationGUIDs));
            }
            return(sceneWithBuildConfiguration);
        }
        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));
        }
Example #6
0
        public static Hash128 GetSubSceneArtifactHash(Hash128 sceneGUID, Hash128 buildConfigurationGUID, UnityEditor.Experimental.AssetDatabaseExperimental.ImportSyncMode syncMode)
        {
            var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(sceneGUID, buildConfigurationGUID);

            if (!s_HashToString.TryGetValue(guid, out var guidString))
            {
                guidString = s_HashToString[guid] = guid.ToString();
            }
            return(UnityEditor.Experimental.AssetDatabaseExperimental.GetArtifactHash(guidString, SubSceneImporterType, syncMode));
        }
 private static unsafe void WriteSceneWithBuildSettings(ref Hash128 guid, ref SceneWithBuildConfigurationGUIDs sceneWithBuildConfigurationGUIDs, string path)
 {
     Directory.CreateDirectory(k_SceneDependencyCachePath);
     using (var writer = new StreamBinaryWriter(path))
     {
         fixed(void *vp = &sceneWithBuildConfigurationGUIDs)
         {
             writer.WriteBytes(vp, sizeof(SceneWithBuildConfigurationGUIDs));
         }
     }
     File.WriteAllText(path + ".meta",
                       $"fileFormatVersion: 2\nguid: {guid}\nDefaultImporter:\n  externalObjects: {{}}\n  userData:\n  assetBundleName:\n  assetBundleVariant:\n");
 }
        static unsafe Hash128 ComputeBuildConfigurationGUID(Hash128 sceneGUID, Hash128 buildConfigurationGUID)
        {
            var guids = new SceneWithBuildConfigurationGUIDs {
                SceneGUID = sceneGUID, BuildConfiguration = buildConfigurationGUID
            };
            Hash128 guid;

            guid.Value.x = math.hash(&guids, sizeof(SceneWithBuildConfigurationGUIDs));
            guid.Value.y = math.hash(&guids, sizeof(SceneWithBuildConfigurationGUIDs), 0x96a755e2);
            guid.Value.z = math.hash(&guids, sizeof(SceneWithBuildConfigurationGUIDs), 0x4e936206);
            guid.Value.w = math.hash(&guids, sizeof(SceneWithBuildConfigurationGUIDs), 0xac602639);
            return(guid);
        }
        public static Hash128 Dirty(Hash128 sceneGUID, Hash128 buildConfigurationGUID)
        {
            var guid     = ComputeBuildConfigurationGUID(sceneGUID, buildConfigurationGUID);
            var fileName = GetSceneWithBuildSettingsPath(ref guid);

            if (File.Exists(fileName))
            {
                var sceneWithBuildConfigurationGUIDs = new SceneWithBuildConfigurationGUIDs {
                    SceneGUID = sceneGUID, BuildConfiguration = buildConfigurationGUID, DirtyValue = DateTime.UtcNow.Ticks
                };
                WriteSceneWithBuildSettings(ref guid, ref sceneWithBuildConfigurationGUIDs, fileName);
            }

            return(guid);
        }
        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));
        }
        private static unsafe void WriteSceneWithBuildSettings(ref Hash128 guid, ref SceneWithBuildConfigurationGUIDs sceneWithBuildConfigurationGUIDs, string path)
        {
            Directory.CreateDirectory(k_SceneDependencyCachePath);
            using (var writer = new StreamBinaryWriter(path))
            {
                fixed(void *vp = &sceneWithBuildConfigurationGUIDs)
                {
                    writer.WriteBytes(vp, sizeof(SceneWithBuildConfigurationGUIDs));
                }
            }
            File.WriteAllText(path + ".meta",
                              $"fileFormatVersion: 2\nguid: {guid}\nDefaultImporter:\n  externalObjects: {{}}\n  userData:\n  assetBundleName:\n  assetBundleVariant:\n");

            // Refresh is necessary because it appears the asset pipeline
            // can't depend on an asset on disk that has not yet been refreshed.
            AssetDatabase.Refresh();
        }
Example #12
0
        private static unsafe void WriteEntitySceneWithBuildConfig(Hash128 guid, SceneWithBuildConfigurationGUIDs sceneWithBuildConfigurationGUIDs, string path)
        {
            var previousPath = AssetDatabaseCompatibility.GuidToPath(guid);

            if (!string.IsNullOrEmpty(previousPath) && previousPath != path)
            {
                UnityEngine.Debug.LogError($"EntitySceneWithBuildConfig guid is not unique {guid}. ScenePath: '{AssetDatabaseCompatibility.GuidToPath(sceneWithBuildConfigurationGUIDs.SceneGUID)}' Conflicting GUID: '{previousPath}'");
            }

            Directory.CreateDirectory(k_SceneDependencyCachePath);
            using (var writer = new StreamBinaryWriter(path))
            {
                writer.WriteBytes(&sceneWithBuildConfigurationGUIDs, sizeof(SceneWithBuildConfigurationGUIDs));
            }
            File.WriteAllText(path + ".meta",
                              $"fileFormatVersion: 2\nguid: {guid}\nDefaultImporter:\n  externalObjects: {{}}\n  userData:\n  assetBundleName:\n  assetBundleVariant:\n");
        }
Example #13
0
        static bool DirtyFile(Hash128 sceneGUID, Hash128 buildConfigurationGUID, bool isBuildingForEditor)
        {
            var guid     = ComputeBuildConfigurationGUID(sceneGUID, buildConfigurationGUID, isBuildingForEditor);
            var fileName = GetSceneWithBuildSettingsPath(guid);

            if (File.Exists(fileName))
            {
                var sceneWithBuildConfigurationGUIDs = new SceneWithBuildConfigurationGUIDs
                {
                    SceneGUID           = sceneGUID,
                    BuildConfiguration  = buildConfigurationGUID,
                    IsBuildingForEditor = isBuildingForEditor,
                    DirtyValue          = DateTime.UtcNow.Ticks
                };
                WriteEntitySceneWithBuildConfig(guid, sceneWithBuildConfigurationGUIDs, GetSceneWithBuildSettingsPath(guid));
                return(true);
            }
            else
            {
                return(false);
            }
        }
        protected override void OnUpdate()
        {
            SceneWithBuildConfigurationGUIDs.ValidateBuildSettingsCache();

            var sceneSystem            = World.GetExistingSystem <SceneSystem>();
            var buildConfigurationGUID = sceneSystem.BuildConfigurationGUID;

            // Add scene entities that haven't been encountered yet
            if (!m_AddScenes.IsEmptyIgnoreFilter)
            {
                //@TODO: Should use Entities.ForEach but we are missing
                // 1. Entities.ForEach support with execute always (ILPP compilation not taking effect on first domain reload)
                // 2. Entities.ForEach not supporting explicit queries

                using (var addScenes = m_AddScenes.ToEntityArray(Allocator.TempJob))
                {
                    var trackerStates = new NativeArray <AssetDependencyTrackerState>(addScenes.Length, Allocator.Temp);
                    for (int i = 0; i != addScenes.Length; i++)
                    {
                        var sceneEntity        = addScenes[i];
                        var scene              = EntityManager.GetComponentData <SceneReference>(sceneEntity);
                        var requestSceneLoaded = EntityManager.GetComponentData <RequestSceneLoaded>(sceneEntity);

                        var guid = SceneWithBuildConfigurationGUIDs.EnsureExistsFor(scene.SceneGUID,
                                                                                    buildConfigurationGUID, out var requireRefresh);
                        var async = (requestSceneLoaded.LoadFlags & SceneLoadFlags.BlockOnImport) == 0;

                        LogResolving(async ? "Adding Async" : "Adding Sync", guid);

                        _AssetDependencyTracker.Add(guid, sceneEntity, async);
                        if (requireRefresh)
                        {
                            _AssetDependencyTracker.RequestRefresh();
                        }

                        trackerStates[i] = new AssetDependencyTrackerState {
                            SceneAndBuildConfigGUID = guid
                        };
                    }

                    EntityManager.AddComponentData(m_AddScenes, trackerStates);
                    trackerStates.Dispose();
                }
            }

            // Remove scene entities that were added and should no longer be tracked
            if (!m_RemoveScenes.IsEmptyIgnoreFilter)
            {
                using (var removeEntities = m_RemoveScenes.ToEntityArray(Allocator.TempJob))
                    using (var removeGuids =
                               m_RemoveScenes.ToComponentDataArray <AssetDependencyTrackerState>(Allocator.TempJob))
                    {
                        for (int i = 0; i != removeEntities.Length; i++)
                        {
                            LogResolving("Removing", removeGuids[i].SceneAndBuildConfigGUID);
                            _AssetDependencyTracker.Remove(removeGuids[i].SceneAndBuildConfigGUID, removeEntities[i]);
                        }
                    }

                EntityManager.RemoveComponent <AssetDependencyTrackerState>(m_RemoveScenes);
            }

            // Process any scenes that have completed their asset import
            var isDone = _AssetDependencyTracker.GetCompleted(_Changed);

            foreach (var change in _Changed)
            {
                var sceneEntity = change.UserKey;
                LogResolving($"Resolving: {change.Asset} -> {change.ArtifactID}");

                if (!m_ValidSceneMask.Matches(sceneEntity))
                {
                    throw new InvalidOperationException("entity should have been removed from tracker already");
                }

                // Unload any previous state
                var unloadFlags = SceneSystem.UnloadParameters.DestroySectionProxyEntities |
                                  SceneSystem.UnloadParameters.DontRemoveRequestSceneLoaded;
                sceneSystem.UnloadScene(sceneEntity, unloadFlags);

                // Resolve new state
                var scene   = EntityManager.GetComponentData <SceneReference>(change.UserKey);
                var request = EntityManager.GetComponentData <RequestSceneLoaded>(change.UserKey);
                if (change.ArtifactID != default)
                {
                    ResolveSceneSectionUtility.ResolveSceneSections(EntityManager, change.UserKey, scene.SceneGUID,
                                                                    request, change.ArtifactID);
                }
                else
                {
                    Debug.LogError(
                        $"Failed to import entity scene because the automatically generated SceneAndBuildConfigGUID asset was not present: '{AssetDatabaseCompatibility.GuidToPath(scene.SceneGUID)}' -> '{AssetDatabaseCompatibility.GuidToPath(change.Asset)}'");
                }
            }

            if (!isDone)
            {
                EditorUpdateUtility.EditModeQueuePlayerLoopUpdate();
            }
        }
        //@TODO: What happens if we change source assets between queuing a request for the first time and it being resolved?

        protected override void OnUpdate()
        {
            //TODO: How can we disable systems in specific builds?
#if !UNITY_EDITOR
            Enabled = !LiveLinkUtility.LiveLinkEnabled;
            if (!Enabled)
            {
                return;
            }
#else
            SceneWithBuildConfigurationGUIDs.ValidateBuildSettingsCache();
#endif
            var buildConfigurationGUID = World.GetExistingSystem <SceneSystem>().BuildConfigurationGUID;

            UpdateSceneContentsChanged(buildConfigurationGUID);

#if UNITY_EDITOR && !USE_SUBSCENE_EDITORBUNDLES
            Entities.With(m_ImportingScenes).ForEach((Entity sceneEntity, ref SceneReference scene, ref RequestSceneLoaded requestSceneLoaded) =>
            {
                var hash = EntityScenesPaths.GetSubSceneArtifactHash(scene.SceneGUID, buildConfigurationGUID, ImportMode.NoImport);
                if (hash.IsValid)
                {
                    LogResolving("Polling Importing (completed)", scene.SceneGUID);
                    ResolveScene(sceneEntity, ref scene, requestSceneLoaded, hash);
                }
                else
                {
                    LogResolving("Polling Importing (not complete)", scene.SceneGUID);
                }
            });
#endif


            //@TODO: Temporary workaround to prevent crash after build player
            if (m_ScenesToRequest.IsEmptyIgnoreFilter)
            {
                return;
            }

            // We are seeing this scene for the first time, so we need to schedule a request.
            Entities.With(m_ScenesToRequest).ForEach((Entity sceneEntity, ref SceneReference scene, ref RequestSceneLoaded requestSceneLoaded) =>
            {
#if UNITY_EDITOR && !USE_SUBSCENE_EDITORBUNDLES
                var blocking   = (requestSceneLoaded.LoadFlags & SceneLoadFlags.BlockOnImport) != 0;
                var importMode = blocking ? ImportMode.Synchronous : ImportMode.Asynchronous;

                var hash = EntityScenesPaths.GetSubSceneArtifactHash(scene.SceneGUID, buildConfigurationGUID, importMode);
                if (hash.IsValid)
                {
                    LogResolving(blocking ? "Blocking import (completed)" : "Queue not yet requested (completed)", scene.SceneGUID);
                    ResolveScene(sceneEntity, ref scene, requestSceneLoaded, hash);
                }
                else
                {
                    LogResolving(blocking ? "Blocking import (failed)" : "Queue not yet requested (not complete)", scene.SceneGUID);
                }
#else
                ResolveScene(sceneEntity, ref scene, requestSceneLoaded, new Hash128());
#endif
            });
            EntityManager.AddComponent(m_ScenesToRequest, ComponentType.ReadWrite <ResolvedSectionEntity>());
        }