public IReadOnlyCollection <AbsoluteId> GetSelectedRootIds()
 {
     lock (LockObject)
     {
         return(SelectedRootIds.ToList());
     }
 }
        private void AddToSelection([NotNull] EntityHierarchyElementViewModel element)
        {
            lock (LockObject)
            {
                if (!element.IsSelectable)
                {
                    return;
                }

                // Add the entity id to the selected ids
                SelectedIds.Add(element.Id);

                // Check if one of its parents is in the selection
                var parent = element.TransformParent;
                while (parent != null)
                {
                    if (SelectedIds.Contains(parent.Id))
                    {
                        break;
                    }

                    parent = parent.TransformParent;
                }

                // If so, the SelectedRootIds collection does not need to be updated.
                if (parent != null)
                {
                    return;
                }

                // Otherwise, it's a new root entity in the selection.
                SelectedRootIds.Add(element.Id);

                // Remove its children that were previously root entities in the selection.
                foreach (var child in element.TransformChildren.SelectDeep(x => x.TransformChildren))
                {
                    SelectedRootIds.Remove(child.Id);
                }
            }
        }
        private void RemoveFromSelection([NotNull] EntityHierarchyElementViewModel element)
        {
            lock (LockObject)
            {
                SelectedIds.Remove(element.Id);

                // Remove the root entity from the selected root entities
                if (SelectedRootIds.Remove(element.Id) && element.IsLoaded)
                {
                    // Ensure all children that are selected are properly added to the selected root collection
                    foreach (var child in element.TransformChildren.SelectDeep(x => x.TransformChildren).Where(x => SelectedIds.Contains(x.Id)))
                    {
                        // Check if one of its parents is in the selection
                        var parent = child.TransformParent;
                        while (parent != element && parent != null)
                        {
                            if (SelectedIds.Contains(parent.Id))
                            {
                                break;
                            }

                            parent = parent.TransformParent;
                        }

                        // If so, the SelectedRootIds collection does not need to be updated.
                        if (parent != element)
                        {
                            return;
                        }

                        // Otherwise, it's a new root entity in the selection.
                        SelectedRootIds.Add(child.Id);
                    }
                }
            }
        }
        private void SelectedContentChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (!Editor.SceneInitialized)
            {
                return;
            }

            lock (LockObject)
            {
                // Retrieve old selection to pass it to the event
                var oldSelectionIds = GetSelectedRootIds();

                switch (e.Action)
                {
                case NotifyCollectionChangedAction.Add:
                    foreach (EntityHierarchyItemViewModel newItem in e.NewItems)
                    {
                        var root = newItem as SceneRootViewModel;
                        if (root != null)
                        {
                            AddToSelection(root);
                        }
                        else
                        {
                            foreach (var entity in newItem.InnerSubEntities)
                            {
                                AddToSelection(entity);
                            }
                        }
                    }
                    break;

                case NotifyCollectionChangedAction.Remove:
                    foreach (EntityHierarchyItemViewModel oldItem in e.OldItems)
                    {
                        var root = oldItem as SceneRootViewModel;
                        if (root != null)
                        {
                            RemoveFromSelection(root);
                        }
                        else
                        {
                            foreach (var entity in oldItem.InnerSubEntities)
                            {
                                RemoveFromSelection(entity);
                            }
                        }
                    }
                    break;

                case NotifyCollectionChangedAction.Reset:
                    SelectedIds.Clear();
                    SelectedRootIds.Clear();
                    break;

                case NotifyCollectionChangedAction.Replace:
                case NotifyCollectionChangedAction.Move:
                    throw new NotSupportedException("This operation is not supported.");

                default:
                    throw new ArgumentOutOfRangeException();
                }

                RaiseSelectionUpdated(oldSelectionIds);
            }
        }