Ejemplo n.º 1
0
    public void AttributeDictionary_Remove_KeyValuePair_Success()
    {
        // Arrange
        var attributes = new AttributeDictionary();

        attributes.Add(new KeyValuePair <string, string>("zero", "0"));
        attributes.Add(new KeyValuePair <string, string>("one", "1"));
        attributes.Add(new KeyValuePair <string, string>("two", "2"));

        // Act
        var result = attributes.Remove(new KeyValuePair <string, string>("one", "1"));

        // Assert
        Assert.True(result);
        Assert.Equal(2, attributes.Count);
        Assert.Collection(
            attributes,
            kvp => Assert.Equal(new KeyValuePair <string, string>("two", "2"), kvp),
            kvp => Assert.Equal(new KeyValuePair <string, string>("zero", "0"), kvp));
    }
        public override void ApplyAttributes(AttributeDictionary attributesToApply)
        {
            if (currentInstanceTransform == null)
            {
                return;
            }

            if (currentXmlElement.name == "GameObject" || currentXmlElement.name == "Xml Element")
            {
                currentXmlElement.name = "TextMesh Pro";
            }

            var go = currentInstanceTransform.gameObject;

            //var mt = new MethodTimer("TMP::Get/Add Component");
            var tmp = go.GetComponent <TextMeshProUGUI>() ?? go.AddComponent <TextMeshProUGUI>();
            //mt.Dispose();

            // If we don't add a LayoutElement component, TextMeshPro will use up any layout parameters (as it uses the ILayoutElement interface)
            // and it doesn't use them in the same way as a LayoutElement so things like, for example, 'flexibleWidth' will not work as expected
            // by adding a LayoutElement, we ensure that the TMP element responds to layout attributes in the same way as other elements
            var layoutElement = tmp.GetComponent <LayoutElement>();

            if (layoutElement == null)
            {
                tmp.gameObject.AddComponent <LayoutElement>();
            }

            if (!attributesToApply.ContainsKey("dontMatchParentDimensions") && !currentXmlElement.HasAttribute("delayedProcessingScheduled"))
            {
                MatchParentDimensions();
            }

            // default alignment, as per standard UI text
            if (!attributesToApply.ContainsKey("alignment") && !currentXmlElement.attributes.ContainsKey("alignment"))
            {
                tmp.alignment = TextAlignmentOptions.Center;
            }

            // default font size, as per standard UI text
            if (!attributesToApply.ContainsKey("fontSize") && !currentXmlElement.attributes.ContainsKey("fontSize"))
            {
                tmp.fontSize = 14f;
            }

            Material fontMaterial = null;

            if (attributesToApply.ContainsKey("fontMaterial"))
            {
                if (currentXmlLayoutInstance.textMeshProMaterials.ContainsKey(attributesToApply["fontMaterial"]))
                {
                    fontMaterial = currentXmlLayoutInstance.textMeshProMaterials[attributesToApply["fontMaterial"]];
                    attributesToApply.Remove("fontMaterial");
                }
            }

            //using (new MethodTimer("TMP::Base::ApplyAttributes"))
            {
                base.ApplyAttributes(attributesToApply);
            }

            if (fontMaterial != null)
            {
                tmp.fontMaterial = fontMaterial;
            }

            if (attributesToApply.ContainsKey("colorGradient"))
            {
                tmp.enableVertexGradient = true;
            }

            if (attributesToApply.ContainsKey("text"))
            {
                tmp.text = StringExtensions.DecodeEncodedNonAsciiCharacters(attributesToApply["text"]);
            }

            // For some reason, some TMP properties (such as text)
            // will not accept changes until after some internal TMP setup
            // has been completed. As such, it is necessary to delay our processing briefly
            // and then attempt to apply attributes again.
            // This only needs to be done once, as further ApplyAttributes() calls
            // will happen after TMP has already completed its setup.
            if (!currentXmlElement.HasAttribute("delayedProcessingScheduled"))
            {
                var attributeDictionaryCopy = attributesToApply;
                var _currentElement         = currentXmlElement;
                XmlLayoutTimer.AtEndOfFrame(() =>
                {
                    if (_currentElement != null)
                    {
                        if (_currentElement.gameObject.activeInHierarchy)
                        {
                            _currentElement.ApplyAttributes();
                        }
                        else
                        {
                            _currentElement.m_onEnableEventsOnceOff.Enqueue(() =>
                            {
                                _currentElement.ApplyAttributes(attributeDictionaryCopy);
                            });
                        }
                    }
                }, _currentElement, true);
                currentXmlElement.attributes.AddIfKeyNotExists("delayedProcessingScheduled", "true");
            }
            else
            {
                // TextMeshPro seems to sometimes ignore changes to the color property;
                // calling it again sorts this out
                if (attributesToApply.ContainsKey("color") && !attributesToApply.ContainsKey("delayedColorSet"))
                {
                    var _currentElement = currentXmlElement;
                    XmlLayoutTimer.AtEndOfFrame(() =>
                    {
                        _currentElement.ApplyAttributes(new Dictionary <string, string>()
                        {
                            { "color", attributesToApply["color"] },
                            { "delayedColorSet", "1" }
                        });

                        _currentElement.RemoveAttribute("delayedColorSet");
                    }, _currentElement, true);
                }
            }
        }
Ejemplo n.º 3
0
        public override void ApplyAttributes(AttributeDictionary attributes)
        {
            var pagedRectTagHandler = PagedRectTagHandler.CurrentPagedRectTagHandler;

            if (pagedRectTagHandler == null)
            {
                Debug.Log("[XmlLayout] Error: PaginationButtonTemplate: Unable to locate PagedRect instance.");
            }
            else
            {
                var pagedRectInstance = pagedRectTagHandler.currentInstanceTransform.GetComponent <PagedRect>();

                var type = attributes.GetValue("type");

                Button buttonInstance = null;

                switch (type.ToLower())
                {
                case "currentpage":
                    if (pagedRectInstance.ButtonTemplate_CurrentPage != null)
                    {
                        buttonInstance = pagedRectInstance.ButtonTemplate_CurrentPage.Button;
                    }
                    break;

                case "otherpages":
                    if (pagedRectInstance.ButtonTemplate_OtherPages != null)
                    {
                        buttonInstance = pagedRectInstance.ButtonTemplate_OtherPages.Button;
                    }
                    break;

                case "disabledpages":
                    if (pagedRectInstance.ButtonTemplate_DisabledPage != null)
                    {
                        buttonInstance = pagedRectInstance.ButtonTemplate_DisabledPage.Button;
                    }
                    break;

                case "next":
                    if (pagedRectInstance.Button_NextPage != null)
                    {
                        buttonInstance = pagedRectInstance.Button_NextPage.Button;
                    }
                    break;

                case "previous":
                    if (pagedRectInstance.Button_PreviousPage != null)
                    {
                        buttonInstance = pagedRectInstance.Button_PreviousPage.Button;
                    }
                    break;

                case "first":
                    if (pagedRectInstance.Button_FirstPage != null)
                    {
                        buttonInstance = pagedRectInstance.Button_FirstPage.Button;
                    }
                    break;

                case "last":
                    if (pagedRectInstance.Button_LastPage != null)
                    {
                        buttonInstance = pagedRectInstance.Button_LastPage.Button;
                    }
                    break;
                }

                if (buttonInstance == null)
                {
                    Debug.Log("[XmlLayout][PaginationButtonTemplate] Unable to locate button template for '" + type + "'");
                }
                else
                {
                    var tagHandler = XmlLayoutUtilities.GetXmlTagHandler("PaginationButton");
                    tagHandler.SetInstance(buttonInstance.transform as RectTransform, this.currentXmlLayoutInstance);
                    attributes.Remove("type");
                    tagHandler.ApplyAttributes(attributes);
                }
            }
        }
        public override void ApplyAttributes(AttributeDictionary attributesToApply)
        {
            base.ApplyAttributes(attributesToApply);

            var inputField = primaryComponent as InputField;

            var textComponents = new List <Text> {
                inputField.textComponent
            };

            if (inputField.placeholder != null)
            {
                var placeholderText = inputField.placeholder.GetComponent <Text>();
                if (placeholderText != null)
                {
                    textComponents.Add(placeholderText);
                }

                if (attributesToApply.ContainsKey("placeholdertext"))
                {
                    placeholderText.text = StringExtensions.DecodeEncodedNonAsciiCharacters(attributesToApply["placeholdertext"]);
                }
            }

            foreach (var textComponent in textComponents)
            {
                var tagHandler = XmlLayoutUtilities.GetXmlTagHandler("Text");
                tagHandler.SetInstance(textComponent.rectTransform, this.currentXmlLayoutInstance);

                var textAttributes = new AttributeDictionary(
                    attributesToApply.Where(a => TextTagHandler.TextAttributes.Contains(a.Key, StringComparer.OrdinalIgnoreCase))
                    .ToDictionary(a => a.Key, b => b.Value));

                if (attributesToApply.ContainsKey("textshadow"))
                {
                    textAttributes.Add("shadow", attributesToApply["textshadow"]);
                }
                if (attributesToApply.ContainsKey("textoutline"))
                {
                    textAttributes.Add("outline", attributesToApply["textoutline"]);
                }
                if (attributesToApply.ContainsKey("textcolor"))
                {
                    textAttributes.Add("color", attributesToApply["textcolor"]);
                }
                if (attributesToApply.ContainsKey("textalignment"))
                {
                    textAttributes.Add("alignment", attributesToApply["textalignment"]);
                }

                textAttributes.Remove("text");

                if (attributesToApply.ContainsKey("textoffset"))
                {
                    var offset = attributesToApply["textoffset"].ToRectOffset();
                    textAttributes.Add("offsetMin", String.Format("{0} {1}", offset.left, offset.bottom));
                    textAttributes.Add("offsetMax", String.Format("-{0} -{1}", offset.right, offset.top));
                }

                tagHandler.ApplyAttributes(textAttributes);
            }
        }
Ejemplo n.º 5
0
        public override void ApplyAttributes(AttributeDictionary attributesToApply)
        {
            // necessary for elements which don't use a prefab
            MatchParentDimensions();

            // If multiple child layouts are nested, then ApplyAttributes() will be called for each before this method has finished executing
            // This becomes an issue, because tag handlers are singletons intended to deal with a single element in one go,
            // which means that the 'currentXmlElement' reference will be replaced with the child, which causes several issues
            // this is also true of all other references, although in this case only 'currentXmlElement' causes any trouble
            // It may be necessary in future to modify the way tag handlers work such that each XmlLayout reference has its own collection of tag handlers,
            // although that will require a small amount of additional memory and processing
            var _currentXmlElement = currentXmlElement;

            _currentXmlElement.name = "ChildXmlLayout";

            base.ApplyAttributes(attributesToApply);

            // Don't pass 'id' on
            attributesToApply.Remove("id");
            attributesToApply.Remove("internalId");

            // if we've already been initialized, don't repeat the process
            if (_currentXmlElement.GetAttribute("initialized") != null)
            {
                // attempt to apply the attributes to the child
                // I've removed this for the time being; as there are potential issues with properties e.g. width="50%" would make
                // the container use width="50%" and then the child would be 50% width of that
                //
                // var _childXmlLayout = _currentXmlElement.childElements.FirstOrDefault(t => t.tagType == "XmlLayout");
                // if(_childXmlLayout != null) _childXmlLayout.ApplyAttributes(attributesToApply);

                return;
            }

            var viewPath = attributesToApply.GetValue <string>("viewPath");

            if (String.IsNullOrEmpty(viewPath))
            {
                Debug.LogWarning("[XmlLayout][Warning][ChildXmlLayout]:: The 'viewPath' attribute is required.");
                return;
            }

            // validate viewPath
            var xmlFile = XmlLayoutResourceDatabase.instance.GetResource <TextAsset>(viewPath);

            if (xmlFile == null)
            {
                Debug.LogWarning("[XmlLayout][Warning][ChildXmlLayout]:: View '" + viewPath + "' not found. Please ensure that the view is accessible via an XmlLayout Resource Database (or is in a Resources folder).");
                return;
            }

            Type controllerType     = null;
            var  controllerTypeName = attributesToApply.GetValue <string>("controller");

            if (!String.IsNullOrEmpty(controllerTypeName))
            {
                // controllerType = Type.GetType(controllerTypeName, false, true);
                controllerType = GetTypeFromStringName(controllerTypeName);

                if (controllerType == null)
                {
                    Debug.LogWarning("[XmlLayout][Warning][ChildXmlLayout]:: Controller Type '" + controllerTypeName + "' not found. Please ensure that the full class name (including the namespace, if the class is located within one). For example: MyNamespace.MyLayoutControllerType");
                }
            }

            bool passEventsToParentController = false;

            if (controllerType == null)
            {
                controllerType = typeof(XmlLayoutController);
                passEventsToParentController = true;
            }

            var childXmlLayout = XmlLayoutFactory.Instantiate(currentInstanceTransform, viewPath, controllerType);

            childXmlLayout.ParentLayout        = _currentXmlElement.xmlLayoutInstance;
            childXmlLayout.ForceRebuildOnAwake = false;

            if (passEventsToParentController)
            {
                childXmlLayout.XmlLayoutController.EventTarget = currentXmlLayoutInstance.XmlLayoutController;
            }

            // Adding a sub-canvas may (slightly) improve performance
            if (_currentXmlElement.gameObject.GetComponent <Canvas>() == null)
            {
                _currentXmlElement.gameObject.AddComponent <Canvas>();
            }
            if (_currentXmlElement.gameObject.GetComponent <GraphicRaycaster>() == null)
            {
                _currentXmlElement.gameObject.AddComponent <GraphicRaycaster>();
            }

            childXmlLayout.XmlElement.tagType = "XmlLayout";

            _currentXmlElement.AddChildElement(childXmlLayout.XmlElement, false);

            _currentXmlElement.SetAttribute("initialized", "true");

            childXmlLayout.XmlElement.ApplyAttributes(attributesToApply);

            // For some reason, the child XmlLayout offset Min/Max values are incorrect, so we need to force them to be zero
            if (!attributesToApply.ContainsKey("offsetMax"))
            {
                childXmlLayout.XmlElement.rectTransform.offsetMax = Vector2.zero;
            }
            if (!attributesToApply.ContainsKey("offsetMin"))
            {
                childXmlLayout.XmlElement.rectTransform.offsetMin = Vector2.zero;
            }
        }
Ejemplo n.º 6
0
        public void AttributeDictionary_Remove_KeyValuePair_Failure()
        {
            // Arrange
            var attributes = new AttributeDictionary();

            attributes.Add(new KeyValuePair<string, string>("zero", "0"));
            attributes.Add(new KeyValuePair<string, string>("one", "1"));
            attributes.Add(new KeyValuePair<string, string>("two", "2"));

            // Act
            var result = attributes.Remove(new KeyValuePair<string, string>("one", "0"));

            // Assert
            Assert.False(result);
            Assert.Equal(3, attributes.Count);
            Assert.Collection(
                attributes,
                kvp => Assert.Equal(new KeyValuePair<string, string>("one", "1"), kvp),
                kvp => Assert.Equal(new KeyValuePair<string, string>("two", "2"), kvp),
                kvp => Assert.Equal(new KeyValuePair<string, string>("zero", "0"), kvp));
        }