internal static void Validate(Scene scene, IncrementalHierarchy hierarchy) { ValidateThatHierarchyContainsScene(scene, hierarchy); ValidateThatSceneContainsHierarchy(scene, hierarchy); }
internal static void Remove(IncrementalHierarchy hierarchy, NativeArray <int> instances) { var openInstanceIds = new NativeList <int>(instances.Length, Allocator.Temp); openInstanceIds.AddRange(instances); var tmpChildren = new NativeList <int>(16, Allocator.Temp); // This code currently doesn't make use of the fact that we are always deleting entire subhierarchies while (openInstanceIds.Length > 0) { int id = openInstanceIds[openInstanceIds.Length - 1]; openInstanceIds.Length -= 1; if (!hierarchy.IndexByInstanceId.TryGetValue(id, out int idx)) { continue; } { // push children and remove children array entry var iter = hierarchy.ChildIndicesByIndex.GetValuesForKey(idx); while (iter.MoveNext()) { openInstanceIds.Add(hierarchy.InstanceId[iter.Current]); } hierarchy.ChildIndicesByIndex.Remove(idx); } // Remove-and-swap on the arrays hierarchy.InstanceId.RemoveAtSwapBack(idx); int oldParentIdx = hierarchy.ParentIndex[idx]; hierarchy.ParentIndex.RemoveAtSwapBack(idx); hierarchy.TransformArray.RemoveAtSwapBack(idx); // then patch up the lookup tables hierarchy.IndexByInstanceId.Remove(id); if (oldParentIdx != -1) { hierarchy.ChildIndicesByIndex.Remove(oldParentIdx, idx); } int swappedIdx = hierarchy.InstanceId.Length; if (swappedIdx > 0 && swappedIdx != idx) { // update index to instance id lookup int swappedId = hierarchy.InstanceId[idx]; hierarchy.IndexByInstanceId[swappedId] = idx; // update index to children lookup of parent int swappedParentIdx = hierarchy.ParentIndex[idx]; if (swappedParentIdx != -1) { hierarchy.ChildIndicesByIndex.Remove(swappedParentIdx, swappedIdx); hierarchy.ChildIndicesByIndex.Add(swappedParentIdx, idx); } // update index to children lookup of swapped index var iter = hierarchy.ChildIndicesByIndex.GetValuesForKey(swappedIdx); while (iter.MoveNext()) { tmpChildren.Add(iter.Current); hierarchy.ParentIndex[iter.Current] = idx; } hierarchy.ChildIndicesByIndex.Remove(swappedIdx); for (int i = 0; i < tmpChildren.Length; i++) { hierarchy.ChildIndicesByIndex.Add(idx, tmpChildren[i]); } tmpChildren.Clear(); } } }
static void ValidateThatHierarchyContainsScene(Scene scene, IncrementalHierarchy hierarchy) { Stack <GameObject> open = new Stack <GameObject>(); foreach (var go in scene.GetRootGameObjects()) { open.Push(go); } var childIndexCache = new List <int>(); var childIdCache = new List <int>(); while (open.Count > 0) { var go = open.Pop(); var id = go.GetInstanceID(); if (hierarchy.IndexByInstanceId.TryGetValue(id, out var idx)) { if (go.transform != hierarchy.TransformArray[idx]) { var otherTransform = hierarchy.TransformArray[idx]; var otherId = otherTransform?.gameObject?.GetInstanceID() ?? 0; Debug.LogError($"Object {go} ({go.GetInstanceID()}) is stored at index {idx}, but the transform stored there is {otherTransform} ({otherId})"); } var parentIdx = hierarchy.ParentIndex[idx]; if (go.transform.parent == null && parentIdx != -1) { int parentId = hierarchy.InstanceId[parentIdx]; var parentObj = UnityEditor.EditorUtility.InstanceIDToObject(parentId); Debug.LogError( $"Object {go} ({go.GetInstanceID()}) has no parent, but in the hierarchy parent {parentObj} ({parentId}) is stored"); } else if (go.transform.parent != null) { int parentId = hierarchy.InstanceId[parentIdx]; var parentObjFromTransform = go.transform.parent.gameObject; if (parentObjFromTransform.GetInstanceID() != parentId) { var parentObj = UnityEditor.EditorUtility.InstanceIDToObject(parentId); Debug.LogError( $"Object {go} ({go.GetInstanceID()}) has parent {parentObjFromTransform} ({parentObjFromTransform.GetInstanceID()}), but in the hierarchy parent {parentObj} ({parentId} is stored)"); } } // validate children childIndexCache.Clear(); childIdCache.Clear(); var childIter = hierarchy.ChildIndicesByIndex.GetValuesForKey(idx); while (childIter.MoveNext()) { childIndexCache.Add(childIter.Current); childIdCache.Add(hierarchy.InstanceId[childIter.Current]); } if (childIndexCache.Count != go.transform.childCount) { Debug.LogError( $"Object {go} ({go.GetInstanceID()}) has {go.transform.childCount} children, but in the hierarchy {childIndexCache.Count} children are stored"); } for (int i = 0; i < go.transform.childCount; i++) { var child = go.transform.GetChild(i).gameObject; var childId = child.GetInstanceID(); if (!childIdCache.Contains(childId)) { Debug.LogError( $"Object {go} ({go.GetInstanceID()}) has child {child} ({childId}), but in the hierarchy it is missing"); } } } else { Debug.LogError($"Object {go} ({go.GetInstanceID()}) is not present in the hierarchy"); } for (int i = 0; i < go.transform.childCount; i++) { open.Push(go.transform.GetChild(i).gameObject); } } }
public IncrementalConversionContext(bool isLiveLink) { Dependencies = new ConversionDependencies(isLiveLink); Hierarchy = default; Scene = default; }