public bool UpdateSelection(HashSet <CSGNode> newTargetNodes, HashSet <Transform> newTargetOthers)
        {
            if (newTargetNodes == null)
            {
                newTargetNodes = new HashSet <CSGNode>();
            }
            if (newTargetOthers == null)
            {
                newTargetOthers = new HashSet <Transform>();
            }

            this.RemovedNodes  = null;
            this.RemovedOthers = null;

            this.AddedNodes  = null;
            this.AddedOthers = null;

            var foundRemovedNodes = new List <CSGNode>();

            if (this.NodeTargets != null &&
                this.NodeTargets.Length > 0)
            {
                if (newTargetNodes.Count == 0)
                {
                    foundRemovedNodes.AddRange(this.NodeTargets);
                }
                else
                {
                    for (int i = 0; i < this.NodeTargets.Length; i++)
                    {
                        if (!this.NodeTargets[i] ||
                            !newTargetNodes.Contains(this.NodeTargets[i]))
                        {
                            foundRemovedNodes.Add(this.NodeTargets[i]);
                        }
                    }
                }
            }

            var foundRemovedOthers = new List <Transform>();

            if (this.OtherTargets != null &&
                this.OtherTargets.Length > 0)
            {
                if (newTargetOthers.Count == 0)
                {
                    foundRemovedOthers.AddRange(this.OtherTargets);
                }
                else
                {
                    for (int i = 0; i < this.OtherTargets.Length; i++)
                    {
                        if (!this.OtherTargets[i] ||
                            !newTargetOthers.Contains(this.OtherTargets[i]))
                        {
                            foundRemovedOthers.Add(this.OtherTargets[i]);
                        }
                    }
                }
            }

            var originalTargetNodeCount  = (this.NodeTargets == null) ? 0 : this.NodeTargets.Length;
            var originalTargetOtherCount = (this.OtherTargets == null) ? 0 : this.OtherTargets.Length;

            // If our counts are the same and nothing is removed (and nothing could've been added), nothing has changed.
            if (newTargetNodes.Count == originalTargetNodeCount &&
                newTargetOthers.Count == originalTargetOtherCount &&
                foundRemovedNodes.Count == 0 &&
                foundRemovedOthers.Count == 0)
            {
                //Debug.Log(originalTargetNodeCount + " " + originalTargetOtherCount + " " + newTargetNodes .Count + " " + newTargetOthers .Count);
                return(false);
            }

            Validate();

            foreach (var node in foundRemovedNodes)
            {
                ArrayUtility.Remove(ref this.NodeTargets, node);

                var brush = node as CSGBrush;
                if (brush != null)
                {
                    ArrayUtility.Remove(ref this.BrushTargets, brush);
                    continue;
                }
                var operation = node as CSGOperation;
                if (node is CSGOperation)
                {
                    ArrayUtility.Remove(ref this.OperationTargets, operation);
                    continue;
                }
                var model = node as CSGModel;
                if (node is CSGModel)
                {
                    ArrayUtility.Remove(ref this.ModelTargets, model);
                    continue;
                }
            }

            foreach (var other in foundRemovedOthers)
            {
                ArrayUtility.Remove(ref this.OtherTargets, other);
            }

            var foundAddedNodes = new List <CSGNode>();

            foreach (var node in newTargetNodes)
            {
                if (this.NodeTargets != null &&
                    ArrayUtility.Contains(this.NodeTargets, node))
                {
                    continue;
                }

                if (this.NodeTargets == null)
                {
                    this.NodeTargets = new CSGNode[] { node };
                }
                else
                {
                    ArrayUtility.Add(ref this.NodeTargets, node);
                }

                foundAddedNodes.Add(node);

                if (SelectionUtility.IsPrefab(node.gameObject))
                {
                    continue;
                }

                var brush = node as CSGBrush;
                if (brush != null)
                {
                    if (this.BrushTargets == null)
                    {
                        this.BrushTargets = new CSGBrush[] { brush }
                    }
                    ;
                    else
                    {
                        ArrayUtility.Add(ref this.BrushTargets, brush);
                    }
                    continue;
                }
                var operation = node as CSGOperation;
                if (node is CSGOperation)
                {
                    if (this.OperationTargets == null)
                    {
                        this.OperationTargets = new CSGOperation[] { operation }
                    }
                    ;
                    else
                    {
                        ArrayUtility.Add(ref this.OperationTargets, operation);
                    }
                    continue;
                }
                var model = node as CSGModel;
                if (node is CSGModel)
                {
                    if (this.ModelTargets == null)
                    {
                        this.ModelTargets = new CSGModel[] { model }
                    }
                    ;
                    else
                    {
                        ArrayUtility.Add(ref this.ModelTargets, model);
                    }
                    continue;
                }
            }

            var foundAddedOthers = new List <Transform>();

            foreach (var other in newTargetOthers)
            {
                if (this.OtherTargets != null &&
                    ArrayUtility.Contains(this.OtherTargets, other))
                {
                    continue;
                }

                if (this.OtherTargets == null)
                {
                    this.OtherTargets = new Transform[] { other }
                }
                ;
                else
                {
                    ArrayUtility.Add(ref this.OtherTargets, other);
                }
                foundAddedOthers.Add(other);
            }

            for (int i = foundAddedNodes.Count - 1; i >= 0; i--)
            {
                var node  = foundAddedNodes[i];
                var brush = node as CSGBrush;
                if (brush != null)
                {
                    var brush_cache = InternalCSGModelManager.GetBrushCache(brush);
                    if (brush_cache == null ||
                        brush_cache.childData == null ||
                        brush_cache.childData.Model == null)
                    {
                        continue;
                    }

                    var childModel = brush_cache.childData.Model;
                    if (childModel &&
                        childModel.isActiveAndEnabled)
                    {
                        SelectionUtility.LastUsedModel = childModel;
                    }
                    break;
                }
                var operation = node as CSGOperation;
                if (operation != null)
                {
                    var operation_cache = InternalCSGModelManager.GetOperationCache(operation);
                    if (operation_cache == null ||
                        operation_cache.ChildData == null ||
                        operation_cache.ChildData.Model == null)
                    {
                        continue;
                    }

                    SelectionUtility.LastUsedModel = operation_cache.ChildData.Model;
                    break;
                }
                var model = node as CSGModel;
                if (model &&
                    model.isActiveAndEnabled)
                {
                    SelectionUtility.LastUsedModel = model;
                    break;
                }
            }

            this.RemovedNodes  = foundRemovedNodes.ToArray();
            this.RemovedOthers = foundRemovedOthers.ToArray();

            this.AddedNodes  = foundAddedNodes.ToArray();
            this.AddedOthers = foundAddedOthers.ToArray();

            return(foundAddedNodes.Count > 0 || foundRemovedNodes.Count > 0 || foundAddedOthers.Count > 0 || foundRemovedOthers.Count > 0);
        }