//----------------------------------------------------------------------------------------------------------------------

        void DeleteSceneCachePlayerPrefab(GameObject prefab)
        {
            Assert.IsTrue(prefab.IsPrefab());

            SceneCachePlayer prefabPlayer = prefab.GetComponent <SceneCachePlayer>();

            Assert.IsNotNull(prefabPlayer);

            string assetsFolder = prefabPlayer.GetAssetsFolder();

            //Check assets folder
            Assert.IsTrue(Directory.Exists(assetsFolder));
            string[] prefabAssetGUIDs = AssetDatabase.FindAssets("", new[] { assetsFolder });
            Assert.Greater(prefabAssetGUIDs.Length, 0);


            //Cleanup
            foreach (string guid in prefabAssetGUIDs)
            {
                AssetDatabase.DeleteAsset(AssetDatabase.GUIDToAssetPath(guid));
            }
            FileUtil.DeleteFileOrDirectory(assetsFolder);

            string prefabPath = AssetDatabase.GetAssetPath(prefab);

            Assert.IsFalse(string.IsNullOrEmpty(prefabPath));
            AssetDatabase.DeleteAsset(prefabPath);

            AssetDatabase.Refresh();
        }
//----------------------------------------------------------------------------------------------------------------------    
    
    internal static void ChangeSceneCacheFile(SceneCachePlayer cachePlayer, string sceneCacheFilePath) {
        string     prefabPath = null;
        GameObject go         = cachePlayer.gameObject;
        //Check if it's possible to reuse the old assetsFolder
        string assetsFolder = cachePlayer.GetAssetsFolder();
        if (string.IsNullOrEmpty(assetsFolder)) {
            MeshSyncRuntimeSettings runtimeSettings = MeshSyncRuntimeSettings.GetOrCreateSettings();        
            string                  scOutputPath    = runtimeSettings.GetSceneCacheOutputPath();            
            assetsFolder = Path.Combine(scOutputPath, Path.GetFileNameWithoutExtension(sceneCacheFilePath));
        }
        
        bool isPrefabInstance = cachePlayer.gameObject.IsPrefabInstance();        
        //We are directly modifying a prefab
        if (!isPrefabInstance && go.IsPrefab()) {
            prefabPath = AssetDatabase.GetAssetPath(go);
            CreateSceneCachePlayerAndPrefab(sceneCacheFilePath, prefabPath, assetsFolder, out SceneCachePlayer player,
                out GameObject newPrefab);
            Object.DestroyImmediate(player.gameObject);
            return;

        } 
        
        if (isPrefabInstance) {
            GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(cachePlayer.gameObject);
            prefabPath = AssetDatabase.GetAssetPath(prefab);
        } 
        
        cachePlayer.CloseCache();
        
        //[TODO-sin: 2020-9-28] Find out if it is possible to do undo properly
        Undo.RegisterFullObjectHierarchyUndo(cachePlayer.gameObject, "SceneCachePlayer");
        
        cachePlayer.Init(assetsFolder);
        cachePlayer.OpenCacheInEditor(sceneCacheFilePath);

        //Save as prefab again
        if (string.IsNullOrEmpty(prefabPath)) {
            return;
        }
        
        //Prevent overwriting ".sc" file itself
        bool isPrefabExt = (Path.GetExtension(prefabPath).ToLower() == ".prefab");
        if (isPrefabExt) {
            cachePlayer.gameObject.SaveAsPrefab(prefabPath);            
        }        
    }
Exemple #3
0
//----------------------------------------------------------------------------------------------------------------------    
    
    internal static void ChangeSceneCacheFile(SceneCachePlayer cachePlayer, string sceneCacheFilePath) {
        string     prefabPath = null;
        GameObject go         = cachePlayer.gameObject;
        //Check if it's possible to reuse the old assetsFolder
        string assetsFolder = cachePlayer.GetAssetsFolder();
        if (string.IsNullOrEmpty(assetsFolder)) {
            MeshSyncProjectSettings projectSettings = MeshSyncProjectSettings.GetOrCreateSettings();        
            string                  scOutputPath    = projectSettings.GetSceneCacheOutputPath();            
            assetsFolder = Path.Combine(scOutputPath, Path.GetFileNameWithoutExtension(sceneCacheFilePath));
        }
        
        bool isPrefabInstance = cachePlayer.gameObject.IsPrefabInstance();        
        //We are directly modifying a prefab
        if (!isPrefabInstance && go.IsPrefab()) {
            prefabPath = AssetDatabase.GetAssetPath(go);
            CreateSceneCachePlayerAndPrefab(sceneCacheFilePath, prefabPath, assetsFolder, out SceneCachePlayer player,
                out GameObject newPrefab);
            Object.DestroyImmediate(player.gameObject);
            return;

        } 
        
        if (isPrefabInstance) {
            GameObject prefab = PrefabUtility.GetCorrespondingObjectFromSource(cachePlayer.gameObject);
            
            //GetCorrespondingObjectFromSource() may return the ".sc" GameObject instead of the prefab
            //due to the SceneCacheImporter
            string assetPath = AssetDatabase.GetAssetPath(prefab);
            if (Path.GetExtension(assetPath).ToLower() == ".prefab") {
                prefabPath = assetPath;
            } else {
                isPrefabInstance = false;
            }            
        } 
        
        cachePlayer.CloseCache();
        
        //[TODO-sin: 2020-9-28] Find out if it is possible to do undo properly
        Undo.RegisterFullObjectHierarchyUndo(cachePlayer.gameObject, "SceneCachePlayer");
        
        Dictionary<string,EntityRecord> prevRecords = new Dictionary<string, EntityRecord>(cachePlayer.GetClientObjects());        
        
        GameObject tempGO = null;
        Dictionary<Transform, Transform> nonPrefabTrans = new Dictionary<Transform, Transform>(); //nonPrefab -> origParent
        if (isPrefabInstance) {
            //Move non-prefab transforms
            tempGO = new GameObject("Temp");
            FindNonPrefabChildren(cachePlayer.transform, ref nonPrefabTrans);
            nonPrefabTrans.Keys.SetParent(tempGO.transform);
            
            PrefabUtility.UnpackPrefabInstance(cachePlayer.gameObject, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);                       
        }


        //remove irrelevant  components of the GameObject if the entity type is different
        void ChangeEntityTypeCB(GameObject updatedGo, TransformData data) {
            string dataPath = data.path;
            if (!prevRecords.ContainsKey(dataPath)) 
                return;

            EntityRecord prevRecord = prevRecords[dataPath];
            if (data.entityType == prevRecord.dataType) 
                return;

            DestroyIrrelevantComponents(updatedGo, data.entityType);
        }


        cachePlayer.onUpdateEntity += ChangeEntityTypeCB;        
        cachePlayer.Init(assetsFolder);
        cachePlayer.OpenCacheInEditor(sceneCacheFilePath);        
        cachePlayer.onUpdateEntity -= ChangeEntityTypeCB;
        
        IDictionary<string,EntityRecord> curRecords = cachePlayer.GetClientObjects();
        DeleteInvalidRecordedGameObjects(prevRecords, curRecords);

        if (!isPrefabInstance) {
            return;
        }
        
        
        cachePlayer.gameObject.SaveAsPrefab(prefabPath); //Save as prefab if it was originally a prefab instance
        
        //Move nonPrefab transforms back
        foreach (KeyValuePair<Transform, Transform> kv in nonPrefabTrans) {
            Transform origParent = kv.Value;
            Transform t          = kv.Key;
            if (null == origParent) {
                ObjectUtility.Destroy(t.gameObject);
            } else {
                t.SetParent(origParent);
            } 
        }
        ObjectUtility.Destroy(tempGO);
        
        
    }