private static void UpdateAssets() { updateStarted?.Invoke(); EditorUtility.DisplayProgressBar("Updating connectivity", "Getting ready", 0.0f); updating = true; var activeScene = SceneManager.GetActiveScene(); var activeScenePath = activeScene.path; CheckConnectivityFeatureLayer.CreateReceptorLayer(); CheckConnectivityFeatureLayer.CreateConnectorLayer(); // 1. Update connectivity prefabs. string[] guids = AssetDatabase.FindAssets("", new string[] { PartUtility.connectivityPath }); for (int i = 0; i < guids.Length; i++) { EditorUtility.DisplayProgressBar("Updating connectivity", "Updating connectivity prefabs", 0.25f * i / guids.Length); string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); Connectivity connectivity = AssetDatabase.LoadAssetAtPath <Connectivity>(assetPath); if (connectivity) { if (connectivity.version == 0 && currentVersion == 1) { ConvertVersion_0_To_1(connectivity); } } } // 2. Run through all prefabs and determine dependency graph based on nesting. Also collect all scene paths for later processing. string[] allAssetPaths = AssetDatabase.GetAllAssetPaths(); List <string> scenes = new List <string>(); var index = 0; var dependencyGraph = new DirectedGraph <string>(); var existingDependencyNodes = new Dictionary <string, DirectedGraph <string> .Node>(); foreach (var path in allAssetPaths) { EditorUtility.DisplayProgressBar("Updating connectivity", "Detecting prefab dependencies", 0.25f + 0.25f * index++ / allAssetPaths.Length); int pos = path.IndexOf("/", StringComparison.Ordinal); if (pos < 0 || path.Substring(0, pos) == "Packages") { continue; // Skip assets in packages. } if (path.StartsWith(PartUtility.connectivityPath)) { continue; // Skip connectivity assets. } if (path.StartsWith(PartUtility.collidersPath)) { continue; // Skip collider assets. } if (path.StartsWith(PartUtility.geometryPath)) { continue; // Skip geometry assets. } pos = path.LastIndexOf(".", StringComparison.Ordinal) + 1; string type = path.Substring(pos, path.Length - pos); switch (type) { case "prefab": { var contents = PrefabUtility.LoadPrefabContents(path); var bricks = contents.GetComponentsInChildren <Brick>(true); if (bricks.Length > 0) { FindDependencies(path, bricks, existingDependencyNodes, dependencyGraph); } PrefabUtility.UnloadPrefabContents(contents); } break; case "unity": { scenes.Add(path); } break; } } // 3. Run through dependency sorted prefabs and update+connect connectivity on non-prefab instances. var sortedNodes = dependencyGraph.TopologicalSort(); index = 0; foreach (var node in sortedNodes) { EditorUtility.DisplayProgressBar("Updating connectivity", "Updating prefabs", 0.5f + 0.25f * index++ / sortedNodes.Count); var contents = PrefabUtility.LoadPrefabContents(node.data); var bricks = contents.GetComponentsInChildren <Brick>(true); if (bricks.Length > 0) { if (UpdateConnections(bricks)) { Debug.Log(node.data + " Updated"); } FixConnections(bricks); PrefabUtility.SaveAsPrefabAsset(contents, node.data); } PrefabUtility.UnloadPrefabContents(contents); } // 4. Run through all scenes and update+connect connectivity on non-prefab instances. index = 0; foreach (var path in scenes) { EditorUtility.DisplayProgressBar("Updating connectivity", "Updating scenes", 0.75f + 0.25f * index++ / scenes.Count); Scene scene = EditorSceneManager.OpenScene(path); var gameObjectsInScene = scene.GetRootGameObjects(); foreach (var gameObject in gameObjectsInScene) { if (PrefabUtility.IsPartOfAnyPrefab(gameObject)) { continue; } var bricks = gameObject.GetComponentsInChildren <Brick>(true); if (bricks.Length > 0) { if (UpdateConnections(bricks)) { Debug.Log($" -------- {gameObject.name} Updated"); } FixConnections(bricks); } } EditorSceneManager.SaveScene(scene); } if (activeScenePath.Length != 0) { EditorSceneManager.OpenScene(activeScenePath); } updating = false; EditorUtility.ClearProgressBar(); updateFinished?.Invoke(); }
private static void FindDependencies(string assetPath, Brick[] bricks, Dictionary <string, DirectedGraph <string> .Node> existingNodes, DirectedGraph <string> dependencyGraph) { DirectedGraph <string> .Node node; if (!existingNodes.ContainsKey(assetPath)) { node = new DirectedGraph <string> .Node() { data = assetPath }; existingNodes.Add(assetPath, node); dependencyGraph.AddNode(node); } else { node = existingNodes[assetPath]; } foreach (var brick in bricks) { if (PrefabUtility.IsPartOfPrefabInstance(brick)) { var dependencyAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(brick); DirectedGraph <string> .Node dependencyNode; if (!existingNodes.ContainsKey(dependencyAssetPath)) { dependencyNode = new DirectedGraph <string> .Node() { data = dependencyAssetPath }; existingNodes.Add(dependencyAssetPath, dependencyNode); dependencyGraph.AddNode(dependencyNode); } else { dependencyNode = existingNodes[dependencyAssetPath]; } dependencyGraph.AddEdge(dependencyNode, node); } } }