diff --git a/Packages/com.vrchat.UdonSharp/Editor/UdonSharpEditorManager.cs b/Packages/com.vrchat.UdonSharp/Editor/UdonSharpEditorManager.cs index cc24fd26..c4fd0704 100644 --- a/Packages/com.vrchat.UdonSharp/Editor/UdonSharpEditorManager.cs +++ b/Packages/com.vrchat.UdonSharp/Editor/UdonSharpEditorManager.cs @@ -817,6 +817,11 @@ private static void UpgradeAssetsIfNeeded() { UdonSharpEditorUtility.UpgradePrefabs(GetAllPrefabsWithUdonSharpBehaviours()); } + catch (Exception e) + { + UdonSharpUtils.LogError($"Exception while upgrading prefabs. Exception: {e}"); + EditorUtility.DisplayDialog("Error", "Exception while upgrading prefabs! This might be a bug!", "OK"); + } finally { UdonSharpEditorCache.Instance.ClearUpgradePassQueue(); diff --git a/Packages/com.vrchat.UdonSharp/Editor/UdonSharpPrefabDAG.cs b/Packages/com.vrchat.UdonSharp/Editor/UdonSharpPrefabDAG.cs index 746d1229..7f2e3e46 100644 --- a/Packages/com.vrchat.UdonSharp/Editor/UdonSharpPrefabDAG.cs +++ b/Packages/com.vrchat.UdonSharp/Editor/UdonSharpPrefabDAG.cs @@ -29,142 +29,135 @@ private class Vertex public UdonSharpPrefabDAG(IEnumerable allPrefabRoots) { - try + foreach (GameObject prefabRoot in allPrefabRoots) { - foreach (GameObject prefabRoot in allPrefabRoots) + Vertex vert = new Vertex() { Prefab = prefabRoot }; + _vertices.Add(vert); + _vertexLookup.Add(prefabRoot, vert); + } + + foreach (Vertex vertex in _vertices) + { + if (PrefabUtility.IsPartOfVariantPrefab(vertex.Prefab)) { - Vertex vert = new Vertex() { Prefab = prefabRoot }; - _vertices.Add(vert); - _vertexLookup.Add(prefabRoot, vert); + Vertex parent = _vertexLookup[PrefabUtility.GetCorrespondingObjectFromSource(vertex.Prefab)]; + + if (parent == vertex) + { + throw new Exception($"Parent of vertex cannot be the same as the vertex '{vertex.Prefab}'"); + } + + vertex.Parents.Add(parent); + parent.Children.Add(vertex); } - - foreach (Vertex vertex in _vertices) + + foreach (GameObject child in vertex.Prefab.GetComponentsInChildren(true) + .Select(e => e.gameObject)) { - if (PrefabUtility.IsPartOfVariantPrefab(vertex.Prefab)) + if (child == vertex.Prefab) + { + continue; + } + + if (PrefabUtility.IsAnyPrefabInstanceRoot(child)) { - Vertex parent = _vertexLookup[PrefabUtility.GetCorrespondingObjectFromSource(vertex.Prefab)]; + GameObject parentPrefab = PrefabUtility.GetCorrespondingObjectFromSource(child); - if (parent == vertex) + if (parentPrefab == null) { - throw new Exception($"Parent of vertex cannot be the same as the vertex '{vertex.Prefab}'"); + throw new Exception($"ParentPrefab of '{child}' is null"); } - - vertex.Parents.Add(parent); - parent.Children.Add(vertex); - } - foreach (GameObject child in vertex.Prefab.GetComponentsInChildren(true).Select(e => e.gameObject)) - { - if (child == vertex.Prefab) + parentPrefab = parentPrefab.transform.root.gameObject; + + if (parentPrefab == child) { - continue; + throw new Exception($"ParentPrefab cannot be the same as child '{child}'"); } - if (PrefabUtility.IsAnyPrefabInstanceRoot(child)) + // If a nested prefab is referenced that does *not* have any UdonBehaviours on it, it will not be in the vertex list, and does not need to be linked. + if (_vertexLookup.TryGetValue(parentPrefab, out Vertex parent)) { - GameObject parentPrefab = PrefabUtility.GetCorrespondingObjectFromSource(child); - - if (parentPrefab == null) - { - throw new Exception($"ParentPrefab of '{child}' is null"); - } - - parentPrefab = parentPrefab.transform.root.gameObject; - - if (parentPrefab == child) - { - throw new Exception($"ParentPrefab cannot be the same as child '{child}'"); - } - - // If a nested prefab is referenced that does *not* have any UdonBehaviours on it, it will not be in the vertex list, and does not need to be linked. - if (_vertexLookup.TryGetValue(parentPrefab, out Vertex parent)) - { - vertex.Parents.Add(parent); - parent.Children.Add(vertex); - } + vertex.Parents.Add(parent); + parent.Children.Add(vertex); } } } - - // Do sorting - HashSet visitedVertices = new HashSet(); + } + + // Do sorting + HashSet visitedVertices = new HashSet(); - // Orphaned nodes with no parents or children go first - foreach (Vertex vertex in _vertices) + // Orphaned nodes with no parents or children go first + foreach (Vertex vertex in _vertices) + { + if (vertex.Children.Count == 0 && vertex.Parents.Count == 0) { - if (vertex.Children.Count == 0 && vertex.Parents.Count == 0) - { - visitedVertices.Add(vertex); - _sortedVertices.Add(vertex.Prefab); - } + visitedVertices.Add(vertex); + _sortedVertices.Add(vertex.Prefab); } + } - Queue openSet = new Queue(); + Queue openSet = new Queue(); - // Find root nodes with no parents - foreach (Vertex vertex in _vertices) + // Find root nodes with no parents + foreach (Vertex vertex in _vertices) + { + if (!visitedVertices.Contains(vertex) && vertex.Parents.Count == 0) { - if (!visitedVertices.Contains(vertex) && vertex.Parents.Count == 0) - { - openSet.Enqueue(vertex); - } + openSet.Enqueue(vertex); } + } + + while (openSet.Count > 0) + { + Vertex vertex = openSet.Dequeue(); - while (openSet.Count > 0) + if (visitedVertices.Contains(vertex)) { - Vertex vertex = openSet.Dequeue(); + continue; + } - if (visitedVertices.Contains(vertex)) - { - continue; - } + if (vertex.Parents.Count > 0) + { + bool neededParentVisit = false; - if (vertex.Parents.Count > 0) + foreach (Vertex vertexParent in vertex.Parents) { - bool neededParentVisit = false; - - foreach (Vertex vertexParent in vertex.Parents) - { - if (!visitedVertices.Contains(vertexParent)) - { - neededParentVisit = true; - openSet.Enqueue(vertexParent); - } - } - - if (neededParentVisit) + if (!visitedVertices.Contains(vertexParent)) { - // Re-queue to visit after we have traversed the node's parents - openSet.Enqueue(vertex); - continue; + neededParentVisit = true; + openSet.Enqueue(vertexParent); } } - visitedVertices.Add(vertex); - _sortedVertices.Add(vertex.Prefab); - - foreach (Vertex vertexChild in vertex.Children) + if (neededParentVisit) { - openSet.Enqueue(vertexChild); + // Re-queue to visit after we have traversed the node's parents + openSet.Enqueue(vertex); + continue; } } - // Sanity check - foreach (Vertex vertex in _vertices) + visitedVertices.Add(vertex); + _sortedVertices.Add(vertex.Prefab); + + foreach (Vertex vertexChild in vertex.Children) { - if (!visitedVertices.Contains(vertex)) - { - throw new Exception($"Invalid DAG state: node '{vertex.Prefab}' was not visited."); - } + openSet.Enqueue(vertexChild); } - - _sortedPaths = _sortedVertices.Select(AssetDatabase.GetAssetPath).ToList(); } - catch (Exception e) + + // Sanity check + foreach (Vertex vertex in _vertices) { - UdonSharpUtils.LogError($"Exception while sorting prefabs for upgrade. Falling back to non-sorted set, nested prefabs may not upgrade properly. Exception: {e}"); - _sortedPaths = allPrefabRoots.Select(AssetDatabase.GetAssetPath).ToList(); + if (!visitedVertices.Contains(vertex)) + { + throw new Exception($"Invalid DAG state: node '{vertex.Prefab}' was not visited."); + } } + + _sortedPaths = _sortedVertices.Select(AssetDatabase.GetAssetPath).ToList(); } ///