static FileVFXComponents FindComponentsInScene(HashSet <GameObject> prefabs) { string path = EditorSceneManager.GetActiveScene().path; try { var objects = EditorSceneManager.GetActiveScene().GetRootGameObjects(); FileVFXComponents infos = new FileVFXComponents(); infos.path = path; infos.componentPaths = new Dictionary <string, ComponentData>(); foreach (var obj in objects) { FindVFXInGameObjectRecurse(infos, obj, "", prefabs, false); } return(infos); } catch (System.Exception) { Debug.Log("Error analyzing scene" + path); EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); throw; } }
static void SetComponentInPrefab(FileVFXComponents infos) { var go = AssetDatabase.LoadAssetAtPath <GameObject>(infos.path); SetVFXInGameObjectRecurse(infos, go, ""); EditorUtility.SetDirty(go); }
static void SetComponentsInScene(FileVFXComponents infos) { var objects = EditorSceneManager.GetActiveScene().GetRootGameObjects(); foreach (var obj in objects) { SetVFXInGameObjectRecurse(infos, obj, ""); } }
public static void MigrateComponentsCurrentScnene() { HashSet <GameObject> prefabs = new HashSet <GameObject>(); FileVFXComponents components = FindComponentsInScene(prefabs); List <FileVFXComponents> prefabsInfos = new List <FileVFXComponents>(); foreach (var prefab in prefabs) { prefabsInfos.Add(FindComponentsInPrefab(prefab)); Debug.Log("Found prefab : " + AssetDatabase.GetAssetPath(prefab)); } foreach (var path in components.componentPaths.Values.Union(prefabsInfos.SelectMany(t => t.componentPaths.Values)).Distinct()) { VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(path.assetPath); if (asset == null) { AssetDatabase.ImportAsset(path.assetPath); asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(path.assetPath); } if (asset != null) { var resource = asset.GetResource(); resource.ValidateAsset(); try { var graph = resource.GetOrCreateGraph(); graph.RecompileIfNeeded(); EditorUtility.SetDirty(graph); } catch (System.Exception e) { Debug.LogError("Couldn't resave vfx" + path.assetPath + " " + e.Message); } } } SetComponentsInScene(components); EditorSceneManager.SaveScene(EditorSceneManager.GetSceneByPath(components.path)); }
static FileVFXComponents FindComponentsInPrefab(GameObject prefab) { string path = AssetDatabase.GetAssetPath(prefab); try { FileVFXComponents infos = new FileVFXComponents(); infos.path = path; infos.componentPaths = new Dictionary <string, ComponentData>(); FindVFXInGameObjectRecurse(infos, prefab, "", null, false); return(infos); } catch (System.Exception) { Debug.Log("Error analyzing prefab" + path); throw; } }
static void SetVFXInGameObjectRecurse(FileVFXComponents infos, GameObject go, string path) { VisualEffect effect = go.GetComponent <VisualEffect>(); if (effect != null) { string componentPath = path + "/" + effect.name; ComponentData componentData; if (infos.componentPaths.TryGetValue(componentPath, out componentData)) { //if (effect.visualEffectAsset == null) { string assetPath = componentData.assetPath; if (assetPath != null) { VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(componentData.assetPath); if (asset == null) { Debug.Log("Couldn't load used asset:" + componentData.assetPath); } EditorUtility.SetDirty(effect); effect.visualEffectAsset = asset; } else { if (effect.visualEffectAsset == null) { Debug.LogError("Component " + componentPath + " asset should have been set with its prefab be didn't in scene " + infos.path); } } SerializedObject obj = new SerializedObject(effect); foreach (var value in componentData.values) { string property = "m_PropertySheet." + value.Key + ".m_Array"; SerializedProperty arrayProp = obj.FindProperty(property); foreach (var setter in value.Value) { bool found = false; for (int i = 0; i < arrayProp.arraySize; ++i) { var elementProp = arrayProp.GetArrayElementAtIndex(i); if (elementProp.FindPropertyRelative("m_Name").stringValue == setter.Key) { m_Setters[value.Key].set(elementProp.FindPropertyRelative("m_Value"), setter.Value); elementProp.FindPropertyRelative("m_Overridden").boolValue = true; found = true; break; } } if (!found) { Debug.LogWarning("Asset : " + assetPath + " no longer seems to have a parameter " + setter.Key + " of type " + value.Key.Substring(2) + "referenced from " + componentPath + " in scene" + infos.path); } else { Debug.Log("Asset : " + assetPath + " restored parameter " + setter.Key + " of type " + value.Key.Substring(2) + "referenced from " + componentPath + " in scene" + infos.path); } } } foreach (var value in componentData.prefabOverrides) { string property = "m_PropertySheet." + value.Key + ".m_Array"; SerializedProperty arrayProp = obj.FindProperty(property); foreach (var setter in value.Value) { for (int i = 0; i < arrayProp.arraySize; ++i) { var elementProp = arrayProp.GetArrayElementAtIndex(i); if (elementProp.FindPropertyRelative("m_Name").stringValue == setter.Key) { elementProp.FindPropertyRelative("m_Overridden").boolValue = setter.Value; break; } } } } obj.ApplyModifiedProperties(); Debug.Log("Restoring component :" + componentPath + "of scene :" + infos.path + " to have asset :" + assetPath); } } } foreach (UnityEngine.Transform child in go.transform) { SetVFXInGameObjectRecurse(infos, child.gameObject, path + "/" + go.name); } }
static void FindVFXInGameObjectRecurse(FileVFXComponents infos, GameObject go, string path, HashSet <GameObject> prefabs, bool isInPrefab) { if (prefabs != null && !isInPrefab && PrefabUtility.GetCorrespondingObjectFromSource(go) != null) { prefabs.Add(PrefabUtility.GetCorrespondingObjectFromSource(go) as GameObject); isInPrefab = true; } VisualEffect effect = go.GetComponent <VisualEffect>(); if (effect != null) { string componentPath = path + "/" + effect.name; if (!object.ReferenceEquals(effect.visualEffectAsset, null)) { string assetPath = AssetDatabase.GetAssetPath(effect.visualEffectAsset.GetInstanceID()); if (string.IsNullOrEmpty(assetPath) || effect.visualEffectAsset == null) { throw new System.InvalidOperationException("Effect+" + componentPath + " of scene" + infos.path + " invalid. Please fix it before migration"); } Dictionary <string, Dictionary <string, object> > values = new Dictionary <string, Dictionary <string, object> >(); Dictionary <string, Dictionary <string, bool> > prefaboverride = new Dictionary <string, Dictionary <string, bool> >(); SerializedObject obj = new SerializedObject(effect); if (assetPath.Contains("Gradient")) { Debug.Log(""); } bool hasOneValue = false; foreach (var setter in m_Setters) { string property = "m_PropertySheet." + setter.Key + ".m_Array"; SerializedProperty arrayProp = obj.FindProperty(property); if (arrayProp.arraySize > 0) { values[setter.Key] = new Dictionary <string, object>(); for (int i = 0; i < arrayProp.arraySize; ++i) { var elementProp = arrayProp.GetArrayElementAtIndex(i); var overridenProp = elementProp.FindPropertyRelative("m_Overridden"); bool overridenInPrefab = isInPrefab && overridenProp.prefabOverride; var valueProp = elementProp.FindPropertyRelative("m_Value"); if ((!isInPrefab && overridenProp.boolValue) || (isInPrefab && valueProp.prefabOverride)) { values[setter.Key].Add(elementProp.FindPropertyRelative("m_Name").stringValue, setter.Value.get(valueProp)); hasOneValue = true; } if (overridenInPrefab) { if (!prefaboverride.ContainsKey(setter.Key)) { prefaboverride[setter.Key] = new Dictionary <string, bool>(); } prefaboverride[setter.Key].Add(elementProp.FindPropertyRelative("m_Name").stringValue, overridenProp.boolValue); hasOneValue = true; } } } } //Skip components that are in a prefab and don't have overridden parameters because some have the same path. bool hasAssetSet = !isInPrefab || obj.FindProperty("m_Asset").prefabOverride; if (hasOneValue || hasAssetSet) { if (infos.componentPaths.ContainsKey(componentPath)) { Debug.LogError("Two components have the path" + componentPath); } infos.componentPaths.Add(componentPath, new ComponentData() { assetPath = hasAssetSet ? assetPath : null, values = values, prefabOverrides = prefaboverride }); } } else { Debug.LogWarning("VisualEffect has no asset" + componentPath + " of scene" + infos.path); } } foreach (UnityEngine.Transform child in go.transform) { FindVFXInGameObjectRecurse(infos, child.gameObject, path + "/" + go.name, prefabs, isInPrefab); } }