static void UpdateParentsIncludedState(PrefabOverridesTreeViewItem item)
 {
     if (item.depth > 0)
     {
         var  parent = item.parent as PrefabOverridesTreeViewItem;
         bool hasIncludedChildren = false;
         bool hasExcludedChildren = false;
         foreach (var child in parent.children)
         {
             var included = (child as PrefabOverridesTreeViewItem).included;
             hasIncludedChildren |= included != ToggleValue.FALSE;
             hasExcludedChildren |= included != ToggleValue.TRUE;
             if (hasIncludedChildren && hasExcludedChildren)
             {
                 break;
             }
         }
         if (hasIncludedChildren && hasExcludedChildren)
         {
             parent.included = ToggleValue.MIXED;
         }
         else if (hasIncludedChildren)
         {
             parent.included = ToggleValue.TRUE;
         }
         else
         {
             parent.included = ToggleValue.FALSE;
         }
         UpdateParentsIncludedState(parent);
     }
 }
 static void UpdateChildrenIncludedState(PrefabOverridesTreeViewItem item, bool v)
 {
     item.included = v ? ToggleValue.TRUE : ToggleValue.FALSE;
     if (item.hasChildren)
     {
         foreach (var child in item.children)
         {
             UpdateChildrenIncludedState(child as PrefabOverridesTreeViewItem, v);
         }
     }
 }
        void DoPreviewPopup(PrefabOverridesTreeViewItem item, Rect rowRect)
        {
            if (item != null)
            {
                // Ensure preview is shown when clicking on an already selected item (the preview might have been closed)
                if (Event.current.type == EventType.MouseDown && rowRect.Contains(Event.current.mousePosition) && !PopupWindowWithoutFocus.IsVisible())
                {
                    m_ShowPreviewForID = item.id;
                }

                // Show preview
                if (item.id == m_ShowPreviewForID && Event.current.type != EventType.Layout)
                {
                    m_ShowPreviewForID = -1;
                    if (item.obj != null)
                    {
                        Rect buttonRect = rowRect;
                        buttonRect.width = EditorGUIUtility.currentViewWidth;
                        Object rowObject = item.obj;

                        Object instance, source;
                        if (item.type == ItemType.REMOVED_OBJECT)
                        {
                            instance = null;
                            source   = rowObject;
                        }
                        else if (item.type == ItemType.ADDED_OBJECT)
                        {
                            instance = rowObject;
                            source   = null;
                        }
                        else
                        {
                            instance = rowObject;
                            source   = PrefabUtility.GetCorrespondingObjectFromSource(rowObject);
                        }

                        PopupWindowWithoutFocus.Show(
                            buttonRect,
                            new ComparisonViewPopup(source, instance, item.singleModification, this),
                            new[] { PopupLocation.Right, PopupLocation.Left, PopupLocation.Below });
                    }
                }
            }
        }
        void DoPreviewPopup(PrefabOverridesTreeViewItem item, Rect rowRect)
        {
            if (item == null || item.obj == null)
            {
                return;
            }

            if (PopupWindowWithoutFocus.IsVisible())
            {
                if (item.id == m_LastShownPreviewWindowRowID)
                {
                    return;
                }
            }

            Rect buttonRect = rowRect;

            buttonRect.width = EditorGUIUtility.currentViewWidth;
            Object rowObject = item.obj;

            Object instance, source;

            if (item.type == ItemType.REMOVED_OBJECT)
            {
                instance = null;
                source   = rowObject;
            }
            else if (item.type == ItemType.ADDED_OBJECT)
            {
                instance = rowObject;
                source   = null;
            }
            else
            {
                instance = rowObject;
                source   = PrefabUtility.GetCorrespondingObjectFromSource(rowObject);
            }

            m_LastShownPreviewWindowRowID = item.id;
            PopupWindowWithoutFocus.Show(
                buttonRect,
                new ComparisonViewPopup(source, instance, item.singleModification, this),
                new[] { PopupLocation.Right, PopupLocation.Left, PopupLocation.Below });
        }
        // Returns true if input gameobject or any of its descendants have modifications, otherwise returns false.
        bool AddTreeViewItemRecursive(TreeViewItem parentItem, GameObject gameObject, Dictionary <int, PrefabOverrides> prefabOverrideMap, IdSequence idSequence)
        {
            var gameObjectItem = new PrefabOverridesTreeViewItem
                                 (
                gameObject.GetInstanceID(),
                parentItem.depth + 1,
                gameObject.name
                                 );

            gameObjectItem.obj = gameObject;

            // We don't know yet if this item should be added to the parent.
            bool shouldAddGameObjectItemToParent = false;

            PrefabOverrides objectModifications;

            prefabOverrideMap.TryGetValue(gameObject.GetInstanceID(), out objectModifications);
            if (objectModifications != null)
            {
                // Added GameObject - note that this earlies out!
                AddedGameObject addedGameObjectData = objectModifications.addedGameObjects.Find(x => x.instanceGameObject == gameObject);
                if (addedGameObjectData != null)
                {
                    gameObjectItem.singleModification = addedGameObjectData;
                    gameObjectItem.type = ItemType.ADDED_OBJECT;

                    parentItem.AddChild(gameObjectItem);
                    return(true);
                }
                else
                {
                    // Modified GameObject
                    ObjectOverride modifiedGameObjectData = objectModifications.objectOverrides.Find(x => x.instanceObject == gameObject);
                    if (modifiedGameObjectData != null)
                    {
                        gameObjectItem.singleModification = modifiedGameObjectData;
                        gameObjectItem.type             = ItemType.PREFAB_OBJECT;
                        shouldAddGameObjectItemToParent = true;
                    }
                }

                // Added components and component modifications
                foreach (var component in gameObject.GetComponents(typeof(Component)))
                {
                    // GetComponents will return Missing Script components as null, we will skip them here to prevent NullReferenceExceptions. (case 1197599)
                    if (component == null)
                    {
                        continue;
                    }

                    // Skip coupled components (they are merged into the display of their owning component)
                    if (component.IsCoupledComponent())
                    {
                        continue;
                    }

                    var componentItem = new PrefabOverridesTreeViewItem
                                        (
                        component.GetInstanceID(),
                        gameObjectItem.depth + 1,
                        ObjectNames.GetInspectorTitle(component)
                                        );
                    componentItem.obj = component;

                    AddedComponent addedComponentData = objectModifications.addedComponents.Find(x => x.instanceComponent == component);
                    if (addedComponentData != null)
                    {
                        // Skip coupled components (they are merged into the display of their owning component)
                        if (addedComponentData.instanceComponent.IsCoupledComponent())
                        {
                            continue;
                        }

                        componentItem.singleModification = addedComponentData;
                        componentItem.type = ItemType.ADDED_OBJECT;
                        gameObjectItem.AddChild(componentItem);
                        shouldAddGameObjectItemToParent = true;
                    }
                    else
                    {
                        var            coupledComponent          = component.GetCoupledComponent();
                        ObjectOverride modifiedObjectData        = objectModifications.objectOverrides.Find(x => x.instanceObject == component);
                        ObjectOverride modifiedCoupledObjectData = (coupledComponent != null) ? objectModifications.objectOverrides.Find(x => x.instanceObject == coupledComponent) : null;

                        if (modifiedObjectData != null || modifiedCoupledObjectData != null)
                        {
                            // If only the coupled component has modifications, create an
                            // ObjectOverride object for the main component since it doesn't exist yet.
                            if (modifiedObjectData == null)
                            {
                                modifiedObjectData = new ObjectOverride()
                                {
                                    instanceObject = component
                                }
                            }
                            ;

                            modifiedObjectData.coupledOverride = modifiedCoupledObjectData;

                            componentItem.singleModification = modifiedObjectData;
                            componentItem.type = ItemType.PREFAB_OBJECT;
                            gameObjectItem.AddChild(componentItem);
                            shouldAddGameObjectItemToParent = true;
                        }
                    }
                }

                // Removed components
                foreach (var removedComponent in objectModifications.removedComponents)
                {
                    // Skip coupled components (they are merged into the display of their owning component)
                    if (removedComponent.assetComponent.IsCoupledComponent())
                    {
                        continue;
                    }

                    var removedComponentItem = new PrefabOverridesTreeViewItem
                                               (
                        idSequence.get(),
                        gameObjectItem.depth + 1,
                        ObjectNames.GetInspectorTitle(removedComponent.assetComponent)
                                               );
                    removedComponentItem.obj = removedComponent.assetComponent;
                    removedComponentItem.singleModification = removedComponent;
                    removedComponentItem.type = ItemType.REMOVED_OBJECT;
                    gameObjectItem.AddChild(removedComponentItem);
                    shouldAddGameObjectItemToParent = true;
                }
            }

            // Recurse into children
            foreach (Transform childTransform in gameObject.transform)
            {
                var childGameObject = childTransform.gameObject;
                shouldAddGameObjectItemToParent |= AddTreeViewItemRecursive(gameObjectItem, childGameObject, prefabOverrideMap, idSequence);
            }

            if (shouldAddGameObjectItemToParent)
            {
                parentItem.AddChild(gameObjectItem);
                if (maxDepthItem == null || gameObjectItem.depth > maxDepthItem.depth)
                {
                    maxDepthItem = gameObjectItem;
                }

                return(true);
            }

            return(false);
        }
        // Returns true if input gameobject or any of its descendants have modifications, otherwise returns false.
        bool AddTreeViewItemRecursive(TreeViewItem parentItem, GameObject gameObject, Dictionary <int, PrefabOverrides> prefabOverrideMap, IdSequence idSequence)
        {
            var gameObjectItem = new PrefabOverridesTreeViewItem
                                 (
                idSequence.get(),
                parentItem.depth + 1,
                gameObject.name
                                 );

            gameObjectItem.obj = gameObject;
            // We don't know yet if this item should be added to the parent.
            bool shouldAddGameObjectItemToParent = false;

            PrefabOverrides objectModifications;

            prefabOverrideMap.TryGetValue(gameObject.GetInstanceID(), out objectModifications);
            if (objectModifications != null)
            {
                // Added GameObject - note that this earlies out!
                AddedGameObject addedGameObjectData = objectModifications.addedGameObjects.Find(x => x.instanceGameObject == gameObject);
                if (addedGameObjectData != null)
                {
                    gameObjectItem.singleModification = addedGameObjectData;
                    gameObjectItem.type = ItemType.ADDED_OBJECT;

                    parentItem.AddChild(gameObjectItem);
                    return(true);
                }
                else
                {
                    // Modified GameObject
                    ObjectOverride modifiedGameObjectData = objectModifications.objectOverrides.Find(x => x.instanceObject == gameObject);
                    if (modifiedGameObjectData != null)
                    {
                        gameObjectItem.singleModification = modifiedGameObjectData;
                        gameObjectItem.type             = ItemType.PREFAB_OBJECT;
                        shouldAddGameObjectItemToParent = true;
                    }
                }

                // Added components and component modifications
                foreach (var component in gameObject.GetComponents(typeof(Component)))
                {
                    var componentItem = new PrefabOverridesTreeViewItem
                                        (
                        idSequence.get(),
                        gameObjectItem.depth + 1,
                        ObjectNames.GetInspectorTitle(component)
                                        );
                    componentItem.obj = component;

                    AddedComponent addedComponentData = objectModifications.addedComponents.Find(x => x.instanceComponent == component);
                    if (addedComponentData != null)
                    {
                        componentItem.singleModification = addedComponentData;
                        componentItem.type = ItemType.ADDED_OBJECT;
                        gameObjectItem.AddChild(componentItem);
                        shouldAddGameObjectItemToParent = true;
                    }
                    else
                    {
                        ObjectOverride modifiedObjectData = objectModifications.objectOverrides.Find(x => x.instanceObject == component);
                        if (modifiedObjectData != null)
                        {
                            componentItem.singleModification = modifiedObjectData;
                            componentItem.type = ItemType.PREFAB_OBJECT;
                            gameObjectItem.AddChild(componentItem);
                            shouldAddGameObjectItemToParent = true;
                        }
                    }
                }

                // Removed components
                foreach (var removedComponent in objectModifications.removedComponents)
                {
                    var removedComponentItem = new PrefabOverridesTreeViewItem
                                               (
                        idSequence.get(),
                        gameObjectItem.depth + 1,
                        ObjectNames.GetInspectorTitle(removedComponent.assetComponent)
                                               );
                    removedComponentItem.obj = removedComponent.assetComponent;
                    removedComponentItem.singleModification = removedComponent;
                    removedComponentItem.type = ItemType.REMOVED_OBJECT;
                    gameObjectItem.AddChild(removedComponentItem);
                    shouldAddGameObjectItemToParent = true;
                }
            }

            // Recurse into children
            foreach (Transform childTransform in gameObject.transform)
            {
                var childGameObject = childTransform.gameObject;
                shouldAddGameObjectItemToParent |= AddTreeViewItemRecursive(gameObjectItem, childGameObject, prefabOverrideMap, idSequence);
            }

            if (shouldAddGameObjectItemToParent)
            {
                parentItem.AddChild(gameObjectItem);
                return(true);
            }

            return(false);
        }