private void CloseScreenByLayer(LinkedListNode <LiveScreenInfo> node, PriorityLayer layer, bool quick, UnityAction onFinish)
        {
            if (node != null)
            {
                var screen = node.Value.screen;
                if ((screen.Layer & layer) == 0)
                {
                    CloseScreenByLayer(node.Previous, layer, quick, onFinish);
                }
                else
                {
                    screen.Close(quick, () =>
                    {
                        LinkedListNode <LiveScreenInfo> nextNode = null;

                        if (node.Previous != null && node.Previous.Value.Match(node.Value))
                        {
                            nextNode = node.Previous;
                            screen.Destroy();
                            _liveScreens.Remove(node);
                        }
                        else
                        {
                            ScreenInfo screenInfo = _screens[node.Value.name];

                            if (!screenInfo.screen.Equals(screen))
                            {
                                screen.Destroy();
                            }

                            if (!screenInfo.cached)
                            {
                                screenInfo.screen.Destroy();
                                _screens.Remove(node.Value.name);
                            }

                            nextNode = node.Previous;
                            _liveScreens.Remove(node);
                        }

                        CloseScreenByLayer(nextNode, layer, quick, onFinish);
                    });
                }
                return;
            }

            if (onFinish != null)
            {
                onFinish();
            }
        }
        private void CloseScreenAboveLayer(PriorityLayer layer, bool quick, UnityAction onFinish)
        {
            var node = _liveScreens.Last;

            if (node == null || node.Value.screen.Layer <= layer)
            {
                if (onFinish != null)
                {
                    onFinish();
                }
            }
            else
            {
                node.Value.screen.Close(quick, () =>
                {
                    var screen = node.Value;
                    LiveScreenInfo lowerScreen = null;

                    if (node.Previous != null)
                    {
                        lowerScreen = node.Previous.Value;
                    }

                    if (screen.Match(lowerScreen))
                    {
                        screen.screen.Destroy();
                    }
                    else
                    {
                        ScreenInfo screenInfo = _screens[screen.name];

                        if (!screen.screen.Equals(screenInfo.screen))
                        {
                            screen.screen.Destroy();
                        }

                        if (!screenInfo.cached)
                        {
                            _screens.Remove(screen.name);
                            screen.screen.Destroy();
                        }
                    }

                    _liveScreens.Remove(node);

                    CloseScreenAboveLayer(layer, quick, onFinish);
                });
            }
        }
        /// <summary>
        /// Generate new ID for screen with a specific priority layer
        /// </summary>
        /// <param name="layer">Priority layer for which a new ID is generated</param>
        /// <returns>New ID</returns>
        private int NextId(PriorityLayer layer)
        {
            var ids = _liveScreens
                      .Where(s => s.screen.Layer == layer)
                      .Select(s => s.id)
                      .OrderBy(s => s)
                      .ToArray();

            int nextId = 1;

            for (int i = 0, length = ids.Length; i < length; i++, nextId++)
            {
                if (ids[i] != nextId)
                {
                    break;
                }
            }

            return(nextId);
        }