示例#1
0
        private void SetCustomItem(VisualElement ve, DropdownMenuItem item, string[] path, int level)
        {
            ve.Q <Label>(name: "text").text = path[level];

            //don't style sub menu items
            if (path.Length - 1 == level &&
                item is DropdownMenuAction actionItem && actionItem.userData is CustomDropdownItemData data)
            {
                ve.Q(name: "icon").style.backgroundImage = data.icon;
                ve.Q <Label>(name: "hotkey-text").text   = data.hotkey;
            }
            public void AddItem(DropdownMenuItem item, string[] path, int level)
            {
                //leaf item
                if (level == path.Length - 1 || path.Length == 0)
                {
                    if (item is DropdownMenuAction action)
                    {
                        var m = dropdown.actionItemPool.GetPooled();
                        m.Set(action.Execute, this, action.status != DropdownMenuAction.Status.Disabled);
                        dropdown.SetItem(m.target, item, path, level);
                        dropdown.SetItemStatus(m.target, action.status);
                        actionItems.Add(m);
                        menuContainer.Add(m.target);
                    }
                    else
                    {
                        var seperator = dropdown.seperatorPool.GetPooled();
                        seperators.Add(seperator);
                        menuContainer.Add(seperator);
                    }
                }
                //create submenu item
                else
                {
                    if (!subMenus.TryGetValue(path[level], out Menu subMenu))
                    {
                        //create new submenu if it has not been created yet
                        var m = dropdown.subItemPool.GetPooled();
                        subMenu = dropdown.subMenuPool.GetPooled();
                        subMenu.Set(this, m.target);
                        m.Set(this, subMenu, true);
                        dropdown.SetItem(m.target, item, path, level);

                        menuContainer.Add(m.target);
                        subMenus.Add(path[level], subMenu);
                        subItems.Add(m);
                    }
                    //add menu intially so its style is resolved
                    Add(subMenu);
                    subMenu.AddItem(item, path, level + 1);
                }
            }
        // Add a new drop-down list item with the specified values.
        private DropdownMenuItem AddItem(OptionData data, DropdownMenuItem itemTemplate, List <DropdownMenuItem> items)
        {
            // Add a new item to the dropdown.
            DropdownMenuItem item = CreateItem(itemTemplate);

            item.rectTransform.SetParent(itemTemplate.rectTransform.parent, false);

            item.gameObject.SetActive(true);
            item.gameObject.name = "Item " + items.Count + (data.text != null ? ": " + data.text : "");

            // Set the item's data
            if (item.text)
            {
                item.text.text = data.text;
            }
            if (item.image)
            {
                item.image.sprite  = data.image;
                item.image.enabled = (item.image.sprite != null);
            }

            items.Add(item);
            return(item);
        }
示例#4
0
    public void ShowStructureSettingsUI(Structure focus)
    {
        settingsUI.SetActive(true);

        currentFocus = focus;

        settingsHeadderLabel.text = focus.displayName;

        foreach (Paramater p in focus.paramaters)
        {
            if (p is DropdownParamater)
            {
                DropdownMenuItem item = Instantiate(dropdownParamaterUIPrefab, settingsView, false).GetComponent <DropdownMenuItem>();
                item.Setup(p as DropdownParamater);
                currentSettings.Add(item);
            }
            if (p is DecimalParamater)
            {
                DecimalMenuItem item = Instantiate(decimalParamaterUIPrefab, settingsView, false).GetComponent <DecimalMenuItem>();
                item.Setup(p as DecimalParamater);
                currentSettings.Add(item);
            }
        }
    }
 /// <summary>
 ///  Convenience method to explicitly destroy the previously generated Items.
 /// </summary>
 /// <remarks>
 /// Override this method to implement a different way to dispose of an option item.
 /// Likely no action needed since destroying the dropdown list destroys all contained items as well.
 /// </remarks>
 /// <param name="item">The Item to destroy.</param>
 protected virtual void DestroyItem(DropdownMenuItem item)
 {
 }
 /// <summary>
 /// Create a dropdown item based upon the item template.
 /// </summary>
 /// <remarks>
 /// Override this method to implement a different way to obtain an option item.
 /// The option item should correspond to the provided template DropdownItem and its GameObject, equivalent to instantiating a copy of it.
 /// </remarks>
 /// <param name="itemTemplate">e template to create the option item from.</param>
 /// <returns>The created dropdown item component</returns>
 protected virtual DropdownMenuItem CreateItem(DropdownMenuItem itemTemplate)
 {
     return(Instantiate(itemTemplate));
 }
        private void SetupTemplate()
        {
            validTemplate = false;

            if (!_template)
            {
                Debug.LogError("The dropdown template is not assigned. The template needs to be assigned and must have a child GameObject with a Toggle component serving as the item.", this);
                return;
            }

            GameObject templateGo = _template.gameObject;

            templateGo.SetActive(true);
            Button itemButton = _template.GetComponentInChildren <Button>();

            validTemplate = true;
            if (!itemButton || itemButton.transform == template)
            {
                validTemplate = false;
                Debug.LogError("The dropdown template is not valid. The template must have a child GameObject with a Toggle component serving as the item.", template);
            }
            else if (!(itemButton.transform.parent is RectTransform))
            {
                validTemplate = false;
                Debug.LogError("The dropdown template is not valid. The child GameObject with a Toggle component (the item) must have a RectTransform on its parent.", template);
            }
            else if (itemText != null && !itemText.transform.IsChildOf(itemButton.transform))
            {
                validTemplate = false;
                Debug.LogError("The dropdown template is not valid. The Item Text must be on the item GameObject or children of it.", template);
            }
            else if (itemImage != null && !itemImage.transform.IsChildOf(itemButton.transform))
            {
                validTemplate = false;
                Debug.LogError("The dropdown template is not valid. The Item Image must be on the item GameObject or children of it.", template);
            }

            if (!validTemplate)
            {
                templateGo.SetActive(false);
                return;
            }

            DropdownMenuItem item = itemButton.gameObject.AddComponent <DropdownMenuItem>();

            item.text          = _itemText;
            item.image         = _itemImage;
            item.button        = itemButton;
            item.rectTransform = (RectTransform)itemButton.transform;

            // Find the Canvas that this dropdown is a part of
            Canvas    parentCanvas    = null;
            Transform parentTransform = _template.parent;

            while (parentTransform != null)
            {
                parentCanvas = parentTransform.GetComponent <Canvas>();
                if (parentCanvas != null)
                {
                    break;
                }

                parentTransform = parentTransform.parent;
            }

            Canvas popupCanvas = GetOrAddComponent <Canvas>(templateGo);

            popupCanvas.overrideSorting = true;
            popupCanvas.sortingOrder    = 30000;

            // If we have a parent canvas, apply the same raycasters as the parent for consistency.
            if (parentCanvas != null)
            {
                Component[] components = parentCanvas.GetComponents <BaseRaycaster>();
                for (int i = 0; i < components.Length; i++)
                {
                    Type raycasterType = components[i].GetType();
                    if (templateGo.GetComponent(raycasterType) == null)
                    {
                        templateGo.AddComponent(raycasterType);
                    }
                }
            }
            else
            {
                GetOrAddComponent <GraphicRaycaster>(templateGo);
            }

            GetOrAddComponent <CanvasGroup>(templateGo);
            templateGo.SetActive(false);

            validTemplate = true;
        }
        /// <summary>
        /// Show the dropdown.
        ///
        /// Plan for dropdown scrolling to ensure dropdown is contained within screen.
        ///
        /// We assume the Canvas is the screen that the dropdown must be kept inside.
        /// This is always valid for screen space canvas modes.
        /// For world space canvases we don't know how it's used, but it could be e.g. for an in-game monitor.
        /// We consider it a fair constraint that the canvas must be big enough to contain dropdowns.
        /// </summary>
        public void Show(bool forceUpdate = false)
        {
            if (!forceUpdate && (!IsActive() || !IsInteractable() || _dropdown != null))
            {
                return;
            }

            // Get root Canvas.
            var list = ListPool <Canvas> .Get();

            gameObject.GetComponentsInParent(false, list);
            if (list.Count == 0)
            {
                return;
            }

            // case 1064466 rootCanvas should be last element returned by GetComponentsInParent()
            Canvas rootCanvas = list[list.Count - 1];

            for (int i = 0; i < list.Count; i++)
            {
                if (list[i].isRootCanvas)
                {
                    rootCanvas = list[i];
                    break;
                }
            }

            ListPool <Canvas> .Release(list);

            if (!validTemplate)
            {
                SetupTemplate();
                if (!validTemplate)
                {
                    return;
                }
            }

            _template.gameObject.SetActive(true);

            // popupCanvas used to assume the root canvas had the default sorting Layer, next line fixes (case 958281 - [UI] Dropdown list does not copy the parent canvas layer when the panel is opened)
            _template.GetComponent <Canvas>().sortingLayerID = rootCanvas.sortingLayerID;

            // Instantiate the drop-down template
            _dropdown      = CreateDropdownList(_template.gameObject);
            _dropdown.name = "Dropdown List";
            _dropdown.SetActive(true);

            // Make drop-down RectTransform have same values as original.
            RectTransform dropdownRectTransform = _dropdown.transform as RectTransform;

            dropdownRectTransform.SetParent(_template.transform.parent, false);

            // Instantiate the drop-down list items

            // Find the dropdown item and disable it.
            DropdownMenuItem itemTemplate = _dropdown.GetComponentInChildren <DropdownMenuItem>();

            GameObject    content = itemTemplate.rectTransform.parent.gameObject;
            RectTransform contentRectTransform = content.transform as RectTransform;

            itemTemplate.rectTransform.gameObject.SetActive(true);

            // Get the rects of the dropdown and item
            Rect dropdownContentRect = contentRectTransform.rect;
            Rect itemTemplateRect    = itemTemplate.rectTransform.rect;

            // Calculate the visual offset between the item's edges and the background's edges
            Vector2 offsetMin = itemTemplateRect.min - dropdownContentRect.min + (Vector2)itemTemplate.rectTransform.localPosition;
            Vector2 offsetMax = itemTemplateRect.max - dropdownContentRect.max + (Vector2)itemTemplate.rectTransform.localPosition;
            Vector2 itemSize  = itemTemplateRect.size;

            _itemList.Clear();

            Button prev = null;

            for (int i = 0; i < options.Count; ++i)
            {
                OptionData       data = options[i];
                DropdownMenuItem item = AddItem(data, itemTemplate, _itemList);
                if (item == null)
                {
                    continue;
                }

                // Automatically set up a toggle state change listener
                item.button.onClick.AddListener(() => OnSelectItem(item.button));

                // Automatically set up explicit navigation
                if (prev != null)
                {
                    Navigation prevNav   = prev.navigation;
                    Navigation toggleNav = item.button.navigation;
                    prevNav.mode   = Navigation.Mode.Explicit;
                    toggleNav.mode = Navigation.Mode.Explicit;

                    prevNav.selectOnDown   = item.button;
                    prevNav.selectOnRight  = item.button;
                    toggleNav.selectOnLeft = prev;
                    toggleNav.selectOnUp   = prev;

                    prev.navigation        = prevNav;
                    item.button.navigation = toggleNav;
                }
                prev = item.button;
            }

            // Reposition all items now that all of them have been added
            Vector2 sizeDelta = contentRectTransform.sizeDelta;

            sizeDelta.y = itemSize.y * _itemList.Count + offsetMin.y - offsetMax.y;
            contentRectTransform.sizeDelta = sizeDelta;

            float extraSpace = dropdownRectTransform.rect.height - contentRectTransform.rect.height;

            if (extraSpace > 0)
            {
                dropdownRectTransform.sizeDelta = new Vector2(dropdownRectTransform.sizeDelta.x, dropdownRectTransform.sizeDelta.y - extraSpace);
            }

            // Invert anchoring and position if dropdown is partially or fully outside of canvas rect.
            // Typically this will have the effect of placing the dropdown above the button instead of below,
            // but it works as inversion regardless of initial setup.
            Vector3[] corners = new Vector3[4];
            dropdownRectTransform.GetWorldCorners(corners);

            RectTransform rootCanvasRectTransform = rootCanvas.transform as RectTransform;
            Rect          rootCanvasRect          = rootCanvasRectTransform.rect;

            for (int axis = 0; axis < 2; axis++)
            {
                bool outside = false;
                for (int i = 0; i < 4; i++)
                {
                    Vector3 corner = rootCanvasRectTransform.InverseTransformPoint(corners[i]);
                    if ((corner[axis] < rootCanvasRect.min[axis] && !Mathf.Approximately(corner[axis], rootCanvasRect.min[axis])) ||
                        (corner[axis] > rootCanvasRect.max[axis] && !Mathf.Approximately(corner[axis], rootCanvasRect.max[axis])))
                    {
                        outside = true;
                        break;
                    }
                }
                if (outside)
                {
                    RectTransformUtility.FlipLayoutOnAxis(dropdownRectTransform, axis, false, false);
                }
            }

            for (int i = 0; i < _itemList.Count; i++)
            {
                RectTransform itemRect = _itemList[i].rectTransform;
                itemRect.anchorMin        = new Vector2(itemRect.anchorMin.x, 0);
                itemRect.anchorMax        = new Vector2(itemRect.anchorMax.x, 0);
                itemRect.anchoredPosition = new Vector2(itemRect.anchoredPosition.x, offsetMin.y + itemSize.y * (_itemList.Count - 1 - i) + itemSize.y * itemRect.pivot.y);
                itemRect.sizeDelta        = new Vector2(itemRect.sizeDelta.x, itemSize.y);
            }

            // Fade in the popup
            AlphaFadeList(_alphaFadeSpeed, 0f, 1f);

            // Make drop-down template and item template inactive
            _template.gameObject.SetActive(false);
            itemTemplate.gameObject.SetActive(false);

            _blocker = CreateBlocker(rootCanvas);
        }
 private void SetDefaultItem(VisualElement ve, DropdownMenuItem item, string[] path, int level)
 {
     ve.Q <Label>(name: "text").text = path[level];
 }