Search Unity

[RELEASED] XmlLayout: Xml-driven UI Framework

Discussion in 'Assets and Asset Store' started by DaceZA, May 3, 2016.

  1. NeonTanto

    NeonTanto

    Joined:
    Jun 19, 2013
    Posts:
    156
    @DaceZA , Hi!
    I have several questions before buy:
    1) Can I link from one Tag object from another Tag with custom attributes? For example something like this:
    Code (CSharp):
    1. <MyTag id="myTag1" downObject="myTag2">
    2. <MyTag id="myTag2" upObject="myTag1">
    In my game split screen its important mode and I use "several event system hack" and I need set selectable links by hands.
    2) Can I access to style values from controller? I use custom components (because I dont have EventSystem.current in normal way) and animations provided by DOTween, its very handy and usefull, but get some data for animations from style will be nice. For example I create styles:
    Code (CSharp):
    1. <Button class="normal" color="#FFFFFF" duration="1.0"/>
    2. <Button class="selected" color="#FF0000" duration="0.5" />
    3. <Button class="neighborSelected" color="#880000" duration="0.5"/>
    And in controller I get "color" property from needed class (or information that it not defined) of button and make desicion how I need construct animation and launche them.
     
    Last edited: Mar 20, 2017
  2. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    Thanks for your interest!

    1) I've implemented most of the Selectable attributes, I'll just need to add some custom handling to allow you to explicitly set these links - I'll get right on that and include it in the next version of XmlLayout (v1.30).

    EDIT: I've added and tested these attributes, they seem to work correctly. I'll be submitting v1.30 to the Asset Store today.

    (You can also extend XmlLayout and add any custom attributes you wish)


    2) Yes, you can access any defaults (styles) values in the controller via the xmlLayout.defaultAttributeValues property, for example:

    Code (CSharp):
    1. var myAttributeValue = xmlLayout.defaultAttributeValues["elementType"]["class"]["attribute"];
    The values are stored as strings, but XmlLayout does also provide extension methods for you to convert them into whatever data type you need, e.g. .ToColor(), .ToColorBlock(), etc. so if, for example, you needed a color:
    Code (CSharp):
    1. var normalButtonColor = xmlLayout.defaultAttributeValues["Button"]["normal"]["color"].ToColor();

    Accessing data that hasn't been defined via an attribute (whether that attribute is set directly on the element or defined via a class) is a little trickier, generally what you'd need to do in that case is access the element directly, e.g.

    Code (CSharp):
    1. var myButton = xmlLayout.GetElementById<Button>("myButton"); // this will return the 'Button' component
    2. var someValue = myButton.property;
     
    Last edited: Mar 20, 2017
  3. NeonTanto

    NeonTanto

    Joined:
    Jun 19, 2013
    Posts:
    156
    Its very nice! I buy your system in near future! =)
     
  4. IronNinjaGames

    IronNinjaGames

    Joined:
    Jun 14, 2014
    Posts:
    14
    @DaceZA --

    Bought the product and am very happy with it so far. Just a few questions:

    How do I leverage an XML layout as a class...? For example, let's say I have an element like this:

    "MyCustomXMLLayout.xml"
    <Image...
    <Image...
    <Text...
    ...etc.
    </Image>

    I'm used to having a way to designate that as a class within its own file and then reuse in other XMLs like this:

    <VerticalLayout...
    <MyCustomXMLLayout/>
    <MyCustomXMLLayout/>
    <MyCustomXMLLayout/>
    ...etc.
    </VerticalLayout>

    Is it possible to do this within the asset framework as shown above... or do I need to do it with the <Defaults> section...?
     
  5. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    @IronNinjaGames

    Hi!

    There are several ways you can achieve this sort of effect:

    The first is via the <Include path="path/to/MyCustomXMLLayout.xml" /> tag (http://www.digital-legacy.co.za/XmlLayout/Documentation#Include). This tag includes the Xml from the specified file in the parent document when generating the interface - any events/etc. will be tied to the parent controller. Please note that the Xml file must be accessible to XmlLayout through a Resources folder or a Resource database (as with all paths in XmlLayout).

    The second is via the <ChildXmlLayout viewPath="path/to/MyCustomXmlLayout.xml" controller="Full.Name.Of.Controller.Class.Including.Namespaces"> tag (http://www.digital-legacy.co.za/XmlLayout/Documentation#ChildXmlLayout). This tag will create a new XmlLayout, assign the specified Xml document to it, and (optionally) instantiate a new controller of the specified class for it and nest it within the parent interface. In this case, events/etc. will be tied to the child layout's controller. As with the <Include /> tag, the specified viewPath must be accessible to XmlLayout.

    The third, more complex approach would be to create an entirely new custom tag (http://www.digital-legacy.co.za/XmlLayout/Documentation#CustomTags). This allows you to specify a prefab of your choice for the tag and customize what attributes/etc. are available to it, and how they function.

    I hope this helps!
     
  6. IronNinjaGames

    IronNinjaGames

    Joined:
    Jun 14, 2014
    Posts:
    14
    Thanks!

    One more question... I'm trying to set up a dynamic scroll list for a mobile app. When setting up a scrollRect there is normally hold-and-drag scrolling automatically built in. But when replicated this in the framework, that functionality doesn't appear to be accessible (maybe it's an attribute I'm not seeing?)

    For example:

    <VerticalScrollView width="100%" height="100%" movementType="Elastic" verticalScrollbarVisibility="Permanent" noScrollbars="1">
    <VerticalLayout contentSizeFitter="vertical" >
    <Image preferredHeight="100" color="red"/>
    ...etc...
    </VerticalLayout>
    </VerticalScrollView>

    Like when making this from scratch in Unity UI, this appears to build the scroll view, content, and verticallayout all correctly -- but the hold-and-drag scrolling capability doesn't appear to be active with the framework. Is there a step I'm missing?
     
  7. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    I tried out your example code and the drag functionality seemed to be working fine - have you maybe added child elements which are blocking raycasts? (for example, buttons, or any elements with any kind of pointer events). In Unity, whenever the pointer is over any element which has 'blockRaycasts' or 'raycastTarget' set to true, then elements behind them will not be able to receive any pointer events (even if the blocking element is completely transparent), which can sometimes be confusing. Unfortunately, it is necessary for these child elements to block raycasts in order for them to use pointer events themselves.

    I had a similar issue in the past (I had a ScrollRect nested within another ScrollRect, and only the child was responding to drag events as it was blocking raycasts to the parent) which I solved by writing a new component which responded to drag events on the child and passed them on to the parent. I don't know if this would help you in this case, I'm not sure how feasible it is for you to add a component to the children and set it up (this would have to be done in code, probably in LayoutRebuilt() on the controller).

    Here is the code for the 'PassThroughDragEvents' component I built: https://pastebin.com/FFTVj0Ye
    (Note, this is part of the PagedRect package, which is why it is in the UI.Pagination namespace; you may wish to move it to a different one). Basically what this component requires is a reference to the target GameObject(s), in this case, the ScrollRect, as well as a list of target components (Desired Target Types), which in this case would be a single entry, 'ScrollRect'. You can then optionally specify whether to pass through horizontal drag events, vertical drag events, or both.

    Then, whenever the child element receives a drag event, it will analyze the event to determine if it meets the requirements and then call the appropriate drag event methods on the target component(s) on the target gameobject(s).

    All of this is of course assuming that the issue is to do with raycasts being blocked... If you're still stuck, please let me know and I will see what I can do.
     
  8. NeonTanto

    NeonTanto

    Joined:
    Jun 19, 2013
    Posts:
    156
    @DaceZA, hi again! What you can say about css3 like animations? Do you have any plans in this direction?
     
  9. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    @mf_andreich

    Hi!

    At the moment, no, there are no plans for anything like that, however it does look interesting - maybe in the future :)
     
  10. NeonTanto

    NeonTanto

    Joined:
    Jun 19, 2013
    Posts:
    156
    Its sad. )))
     
  11. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    88
    I'm just digging into this asset, and I'm having a little trouble figuring out how to set up flexible sections. For example, here's my XML:

    <VerticalScrollView anchorMin="0 0" anchorMax="1 1" offsetXY="0 0" sizeDelta="0 0">
    <TableLayout id="container" flexibleHeight="1">
    <Row preferredHeight="30">
    <Text class="h1">Unowned Upgrades</Text>
    </Row>
    <Row flexibleHeight="1">
    <GridLayout id="unowned_upgrades" class="upgrades">
    <!-- Upgrade Panel Template -->
    <UpgradePanel id="upgradeTemplate" class="upgrade" active="false" />
    <!-- End of Upgrade Panel Template -->

    <UpgradePanel id="mock1" class="upgrade" active="true" />
    <UpgradePanel id="mock2" class="upgrade" active="true" />
    <UpgradePanel id="mock3" class="upgrade" active="true" />
    <UpgradePanel id="mock4" class="upgrade" active="true" />
    <UpgradePanel id="mock5" class="upgrade" active="true" />
    </GridLayout>
    </Row>

    <Row preferredHeight="30">
    <Text class="h1">Owned Upgrades</Text>
    </Row>
    <Row flexibleHeight="1">
    <GridLayout id="owned_upgrades" class="upgrades">
    </GridLayout>
    </Row>
    </TableLayout>
    </VerticalScrollView>

    The UpgradePanels are a custom element with a fixed size, but they're added dynamically. Even in the editor, though, the first section doesn't expand to the size of the 5 mock panels.
     
  12. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi greay,

    Unfortunately, Table Rows don't support changing size to fit their content dynamically, at least not without adding some code to handle it when adding items. While the 'flexibleHeight' attribute is available for most elements, in the case of table rows, it will have no effect.

    There are several approaches you can use to implement this functionality - the first, and generally, easiest, would be to use a nested TableLayout instead of a GridLayout. The downside would be that you would manually have to add rows / cells, which you wouldn't have to do with a GridLayout. The 'Shop' example shows how this can be done - you can find the code in UI/XmlLayout/Examples/XmlLayout_Example_Shop.cs.

    An alternative approach would be to set the height manually, and then adjust it when adding content to the grid, e.g. something like this (please note, this is off the top of my head and is untested, but it should work)

    Code (CSharp):
    1. void AddItem()
    2.    {
    3.        var row = xmlLayout.GetElementById<TableRow>("row");
    4.        var template = xmlLayout.GetElementById("upgradeTemplate");
    5.        var gridLayout = xmlLayout.GetElementById<GridLayoutGroup>("unowned_upgrades");
    6.  
    7.        // instantiate the new item based on the template and initialize it
    8.        var newItem = GameObject.Instantiate(template);
    9.        newItem.Initialise(xmlLayout, (RectTransform)newItem.transform, template.tagHandler);
    10.  
    11.        // Add any code necessary to customize 'newItem' here
    12.  
    13.        // get the number of items in the grid
    14.        var itemCount = gridLayout.transform.childCount;
    15.        // work out how many items there will be per row
    16.        var itemsPerRow = ((RectTransform)gridLayout.transform).rect.width / template.rectTransform.rect.width;
    17.        // work out how many rows there will be, then work out how high the grid layout should be
    18.        var calculatedHeight = (itemCount / itemsPerRow) * template.rectTransform.rect.height;
    19.  
    20.        // set the new preferred height of the row
    21.        row.preferredHeight = calculatedHeight;
    22.    }
    23. /code]
     
    greay likes this.
  13. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    88
    Hmm, yeah, I was hoping there might be a completely dynamic way, but calculating the row height when adding an item is a pretty straightforward solution. Thanks!

    EDIT: is there a way to make the table itself expand to fit all the rows, or do I have to do a similar calculation for all the rows?
     
    Last edited: Aug 18, 2017
  14. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    88
    Also, how do you disable the cursor override?
     
  15. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    a) Yes, you can use the TableLayout's 'autoCalculateHeight' attribute, which will cause the TableLayout's height to be the sum of the height of all of its rows.

    b) By default, the cursor system is supposed to be inactive unless a cursor attribute is detected, however I have just tested it and I see that the cursor system is picking up the default 'blank' value for the cursor attributes on the XmlLayout tag itself - I've just made a correction to prevent this. I'll PM you a link with the updated version, which should prevent XmlLayout from attempting to control cursors when no cursor attributes have been defined.

    Hope this helps!
     
  16. RoyArtorius

    RoyArtorius

    Joined:
    Jul 11, 2013
    Posts:
    73
    Hi there,

    I'm very interested in this asset, but I do have one question before I decide on getting (I may get it regardless because it looks so good).

    Is it possible to load a XML Layout from a file after the game is built? What I'm trying to do is allow the player/user to mod the game's ui so they could create their own gui and menus.
     
  17. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi ZackLeodrano,

    Thanks for your interest!

    XmlLayout supports loading/changing Xml at runtime, so yes, you can definitely create a moddable UI :)
     
  18. RoyArtorius

    RoyArtorius

    Joined:
    Jul 11, 2013
    Posts:
    73
    Awesome! I'm definitely getting your asset :D
     
  19. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Enjoy!

    To change Xml at runtime, the XmlLayout object has an 'Xml' string property which you can set/manipulate as you wish. To rebuild the layout using the updated Xml, you can call the XmlLayout object's 'RebuildLayout()' method.
     
  20. RoyArtorius

    RoyArtorius

    Joined:
    Jul 11, 2013
    Posts:
    73
    Got it! Thanks!
     
  21. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Is it possible to make changes to a GUI within the editor.. For example: add/remove GUI elements in the unity editor and then have the XML file update with the new changes?
     
  22. greay

    greay

    Joined:
    Mar 23, 2011
    Posts:
    88
    Very happy with this asset so far. It's made my life a lot easier. There's 2 more issues that I'm seeing:

    1. In my main UI prefab scene, which uses XMLLayout and PagedRect, the scene always shows unsaved changes. This isn't a dealbreaker by any means, but I never know if the changes are important or not.
    2. It sounds like this might be a Unity bug, but I'm having trouble pinpointing the cause – I have a script with a coroutine attached to my layout object. After the first yield, the coroutine simply stops. This only happens when the UI scene is loaded additively; if I run the UI scene by itself, it works as normal.
     
  23. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Hi, is there a way to drag and drop to reorder items in TableLayout list
     
  24. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    I am getting deeper into Xmllayout and trying to make a Vertical Scrollist with custom list items and would love to get some tips on how to create a custom tag for playlistItemTemplate below:

    Question:
    1. What is the best way to wrap up the playlistItemTemplate so that it can best work in a data driven scrollist.
    Cheers

    <XmlLayout xmlns="http://www.w3schools.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../../../Configuration/XmlLayout.xsd">

    <Include path="Xml/TNT_Styles.xml" />


    <TableLayout class="noCellBackground" height="100" width="256" rectAlignment="MiddleLeft" offsetXY="0 0" useGlobalCellPadding="false">

    <Row class="viewport">
    <Cell dontUseTableCellBackground="true">
    <VerticalScrollView class="scrollView" color="rgb(0,0,0,0.75)" id="scriptInputScrollView">
    <TableLayout class="noCellBackground" height="100" width="256" rectAlignment="MiddleLeft" offsetXY="5 2" useGlobalCellPadding="false">
    <Row><cell></cell><cell></cell></Row>
    <ToggleGroup >
    <VerticalLayout padding="0" spacing="0" id="playlistButtons" >
    <!-- This is a template which will be used by the XmlLayoutController to create the menu buttons dynamically -->

    <Row preferredHeight="32" id="playlistItemTemplate" active="false">
    <cell width="20" rectAlignment="MiddleLeft">
    <Toggle isOn="0" active="true" id="toggle"></Toggle>
    </cell>
    <cell width="200">
    <Button active="true" id="button" >Hi</Button>
    </cell> ​
    </Row> ​

    </VerticalLayout>
    </ToggleGroup>

    </TableLayout>
    </VerticalScrollView>
    </Cell>
    </Row>
    </TableLayout>

    </XmlLayout>
     
    Last edited: Aug 27, 2017
  25. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    First attempt at creating a customTag.

    1. Made a prefab out of the code snippet from above:

    <Row preferredHeight="32" id="playlistItemTemplate" active="false">
    <cell width="20" rectAlignment="MiddleLeft">
    <Toggle isOn="0" active="true" id="toggle"></Toggle>​
    </cell>
    <cell width="200">
    <Button active="true" id="button" >Hi</Button>​
    </cell>​
    </Row>​

    2. Made a file, ListItemTagHandler.cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using UI.Xml;

    // The Tag name will be determined as the name of the class with 'TagHandler' removed,
    // e.g. TextTagHandler -> <Text>
    public class ListItemTagHandler : ElementTagHandler
    {
    public override MonoBehaviour primaryComponent
    {
    get
    {
    if (currentInstanceTransform == null) return null;

    // Replace <Text> with the MonoBehaviour that you feel best fits as the 'primary' component of this Xml Tag
    // e.g. <Text> -> Text, <Button> -> Button
    return currentInstanceTransform.GetComponentInChildren<Button>();
    }
    }

    public override string prefabPath
    {
    get
    {
    // by default, XmlLayout will use the following path: Resources/XmlLayout Prefabs/{Element Name}TagHandler
    // if you wish to use this path, you can safely remove this property
    // otherwise, you may define a new path here - please note that the Prefab path must be located within a Resources directory
    //string path = "/Users/TNTmac/Spiral/Assets/TNT/Resources/Prefabs/ListItem";
    return base.prefabPath;
    }
    }
    /*
    public override bool ParseChildElements(System.Xml.XmlNode xmlNode)
    {
    // If this function returns true, then XmlLayout will NOT attempt to process any nested child elements further
    // This is used to process elements such as Text or DropDown which have special handling and do not supported regular nested elements


    // if no special child handling is required, then this method can safely be removed

    return base.ParseChildElements(xmlNode);
    }
    */

    public override void ApplyAttributes(AttributeDictionary attributesToApply)
    {
    base.ApplyAttributes(attributesToApply);

    // Add any special attribute handling here, e.g.
    Debug.Log("primaryComponent=" + primaryComponent);
    var xmlBt = primaryComponent.GetComponent<XmlLayoutButton>();
    if(attributesToApply.ContainsKey("text")) xmlBt.TextComponent.text = attributesToApply["text"];

    // A large number of string extension functions have been provided in the UI.Xml namespace, e.g. ToColor(), ToColorBlock(), ToVector2(), ToRectOffset(), ToSprite(), ToFont(), etc.
    // The full list is available in the UI.Xml.ConversionExtensions class
    // Please note that ALL attribute names within the AttributeDictionary be in lower case within this method

    // if no special attribute handling is required, this method can safely be removed
    }

    protected override void HandleEventAttribute(string eventName, string eventValue)
    {
    // Add any special event handling here
    // for examples on how to do this, see the source code of:
    // - ToggleTagHandler
    // - ToggleGroupTagHandler

    // Please note that this function will ONLY be called for event attributes which have been defined
    // by the propery 'EventAttributeNames' which can be overriden in this class to define custom names
    // The default EventAttributeNames are:
    // -onClick
    // -onMouseEnter
    // -onMouseExit


    base.HandleEventAttribute(eventName, eventValue);
    }

    public override bool isCustomElement
    {
    get
    {
    return true;
    }
    }
    }​

    3. Changed original xml above to use the new customTag:

    <XmlLayout xmlns="http://www.w3schools.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../../../Configuration/XmlLayout.xsd">

    <Include path="Xml/TNT_Styles.xml" />


    <TableLayout class="noCellBackground" height="100" width="256" rectAlignment="MiddleLeft" offsetXY="0 0" useGlobalCellPadding="false">

    <Row class="viewport">
    <Cell dontUseTableCellBackground="true">
    <VerticalScrollView class="scrollView" color="rgb(0,0,0,0.75)" id="scriptInputScrollView">
    <TableLayout class="noCellBackground" height="100" width="256" rectAlignment="MiddleLeft" offsetXY="5 2" useGlobalCellPadding="false">
    <Row><cell></cell><cell></cell></Row>
    <ToggleGroup >
    <VerticalLayout padding="0" spacing="0" id="listItemHolder" >
    <!-- This is a template which will be used by the XmlLayoutController to create the menu buttons dynamically -->
    <ListItem id="listItemTemplate" active="false" > </ListItem>


    </VerticalLayout>
    </ToggleGroup>

    </TableLayout>
    </VerticalScrollView>
    </Cell>
    </Row>
    </TableLayout>

    </XmlLayout>​

    4. Code to instantiate the listItems:


    void AddPlaylistItem(string itemName, XmlElement inlistItemHolder, XmlElement listItemTemplate)
    {
    // Create a copy of the template
    var listItem = Instantiate(listItemTemplate);
    listItem.name = itemName;

    // Access the XmlElement component and initialise it for this new button
    var listItemXml = listItem.GetComponent<XmlElement>();
    listItemXml.Initialise(xmlLayout, (RectTransform)listItem.transform, listItemTemplate.tagHandler);


    inlistItemHolder.AddChildElement(listItem);

    listItemXml.SetAttribute("text", itemName);
    listItemXml.SetAttribute("active", "true");
    listItemXml.ApplyAttributes();
    }
    5. Result, the custom ListItems are created perfectly in the game. The problem I am getting is that when I hover over the created ListItems, I get the following error.

    NullReferenceException: Object reference not set to an instance of an object
    UI.Xml.ElementTagHandler.ClassChanged () (at Assets/UI/XmlLayout/ElementTagHandler.cs:727)
    UI.Xml.XmlElement.ClassChanged () (at Assets/UI/XmlLayout/XmlElement.cs:421)
    UI.Xml.XmlElement.AddClass (System.String name) (at Assets/UI/XmlLayout/XmlElement.cs:388)
    UI.Xml.XmlElement.<Select>m__12 (System.String c) (at Assets/UI/XmlLayout/XmlElement/XmlElement.Selectable.cs:52)
    System.Collections.Generic.List`1[T].ForEach (System.Action`1[T] action) (at /Users/builduser/buildslave/mono/build/mcs/class/referencesource/mscorlib/system/collections/generic/list.cs:564)
    UI.Xml.XmlElement.Select () (at Assets/UI/XmlLayout/XmlElement/XmlElement.Selectable.cs:52)
    UI.Xml.XmlElement.NotifySelectionStateChanged (UI.Xml.XmlElement+SelectionState newSelectionState) (at Assets/UI/XmlLayout/XmlElement/XmlElement.Selectable.cs:25)
    UI.Xml.XmlLayoutButton.NotifyButtonStateChanged (UI.Xml.XmlElement+SelectionState newSelectionState) (at Assets/UI/XmlLayout/Custom Elements/XmlLayoutButton.cs:84)
    UI.Xml.XmlLayoutButtonComponent.DoStateTransition (UnityEngine.UI.Selectable+SelectionState state, System.Boolean instant) (at Assets/UI/XmlLayout/Custom Elements/XmlLayoutButtonComponent.cs:27)
    UnityEngine.UI.Selectable.InternalEvaluateAndTransitionToSelectionState (System.Boolean instant) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Selectable.cs:583)
    UnityEngine.UI.Selectable.EvaluateAndTransitionToSelectionState (UnityEngine.EventSystems.BaseEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Selectable.cs:575)
    UnityEngine.UI.Selectable.OnPointerEnter (UnityEngine.EventSystems.PointerEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Selectable.cs:611)
    UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerEnterHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:22)
    UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at /Users/builduser/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:261)
    UnityEngine.EventSystems.EventSystem:Update()
     
  26. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Sorry about the delay here, Unity hasn't been sending me notifications of posts here again. Please remember that if you need a response asap, you can always get hold of me @ support@digital-legacy.co.za :)

    Sorry, but no, that isn't possible with XmlLayout - it's strictly one-way (Xml -> GUI).

    1. Sorry about that, that is PagedRect, which takes various steps to ensure that everything is all set up correctly, which Unity picks up as changes to the scene. XmlLayout will also usually mark the scene as dirty (once) as it rebuilds layouts when the scene loads, unless the layout has 'Rebuild on Awake" set to false.
    2. That does sound like it could be a Unity issue, the only reason why a coroutine should stop without explicitly being instructed to do so is if the object is made inactive or is destroyed. Perhaps you could try starting the coroutine after a short delay? (You could try using the XmlLayoutTimer class to do so).



    Unfortunately, no. While rows in a TableLayout can be re-ordered at any time, they do not support being dragged.
     
  27. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    The reason for that is that the XmlElements in your prefab are not associated with any particular XmlLayout (as they have been created outside of the XmlLayout system). As such, when they attempt to access their parent XmlLayout object, a null reference exception is triggered. Creating elements in this way is unfortunately not supported by XmlLayout, unless you were to iterate through each XmlElement in the prefab (the row, each cell, and their contents) and initialise the XmlElement components with the XmlElement.Initialise() method.

    You could, however, create the row manually (via Tablelayout), and create a prefab using that. You'd have to access its child cells/elements via GetComponentInChildren() (as they won't have XmlLayout ids), but it should work.
     
  28. icog

    icog

    Joined:
    Sep 24, 2017
    Posts:
    1
    I come from an Android development background and wanted to see if there is a way to do something similar to the following:

    With Android, I can say that "textColorPrimary" has a value of "#3F51B5". Then I can reference this color in any xml layout by using "@Color/textColorPrimary" rather than hard-coding the value everywhere. Is there any way to do something similar with XmlLayout? I believe you can reference eleven colors that Unity defines (such as "white"), but if there is a way you can define a color in a single location and use it throughout the project that would be amazing.

    =======================================
    Example Android files:

    Filename: colors.xml
    ````
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <color name="textColorPrimary">#3F51B5</color>
    </resources>
    ````

    The color is then used in another file:

    Filename: example.xml
    ````
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/example_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
    android:id="@+id/example_textview_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="@Color/textColorPrimary"
    android:textStyle="bold" />

    </FrameLayout>
    ````
     
  29. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Unfortunately, at the moment, that isn't supported, but it's an interesting idea that I may implement in the future.

    You can use Unity named colors, yes, although I'd advise caution using them as some platforms have different sets of named colors (for some reason).

    What you can do, however, and this is the approach I'd generally recommend, is define visual styles using the 'Defaults' tag: http://www.digital-legacy.co.za/XmlLayout/Documentation#Defaults
     
  30. unity_N7Mv18UwkDRu_A

    unity_N7Mv18UwkDRu_A

    Joined:
    Sep 25, 2017
    Posts:
    2
  31. fau7

    fau7

    Joined:
    Jan 24, 2018
    Posts:
    48
    Hi guys,
    First of all I want to thank you for this great asset. It gives me a certain level of confidence building applications.
    But I am having an issue right now.
    I have connected the database to the MVVM example. I have added an extra functionality or modified the code to meet the requirement. That is, when I add a data to the list there opens a Message Dialog window. If the user accepts the changes the data is inserted to the database. No issues here. I can observe that the data is inserted successfully to the database. But I am having a problem updating the data table in the scene.. I have been trying to parse the data to a game object. I can not find a way to update the data rows in the view after the insertion. I would be grateful if anyone could help me a way out of this stalemate :/
    Thanks again for this great asset. I love assets with the ability to extend the code through MVVM, MVC etc... Appreciate the effort behind the XML-UI.
    Best wishes
    Fau
     
    Last edited: Jul 29, 2018
  32. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi there,

    I'm glad you like XmlLayout! :)

    In general, with MVVM, you will need to manipulate the data in the ViewModel in order to update what is displayed, so, when you're inserting data into the database, you'll also need to add an item to ViewModel's collection, something like this:

    Code (CSharp):
    1. viewModel.listItems.Add(new ExampleListItem { column1 = "value1", column2 = "value2" });
    ^ Where 'value1' and 'value2' are the values you just inserted to the database.

    That should be all that is necessary for you to update the display. An alternative approach would be to perhaps reload the data from the database (assuming you're doing that in PrepopulateViewModelData(), you could call that method again), although that would force XmlLayout to unnecessarily replace the entire display (not a big problem, but not as efficient as it could be).
     
  33. fau7

    fau7

    Joined:
    Jan 24, 2018
    Posts:
    48
    Hi DaceZA,

    I have solved it :) I have simply passed the ObservableList data property of the ViewModel as a reference to the message dialog. And added the populated data (if confirmed by the user at the message dialog) as you have told. Thank you so much for the reply. By the way I have come up with another issue. In the login screen I am using the InputField. I want to mask out the password. Unity has the asterixChar method for the InputField object. I can't make use of this method. :/

    I have created a reference to the xml layout. And tried calling the method in the Awake method. Unfortunately I was not successful...

    XmlElementReference<InputField> pPassword;
    void Awake(){
    pPassword= XmlElementReference<InputField>("password");
    }

    https://docs.unity3d.com/ScriptReference/UI.InputField-asteriskChar.html

    Could please also make a reference to that. I have other questions in the row coming :D Thank you DaceZA.
     
  34. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    I see what you mean, I've added the 'asteriskChar' attribute to <InputField>, so now you can go
    Code (CSharp):
    1. <InputField contentType="Password" asteriskChar="#"></InputField>
    I'll PM you the update now.
     
  35. fau7

    fau7

    Joined:
    Jan 24, 2018
    Posts:
    48
    Thank you so much DaceZA for the fantastic support.
     
  36. fau7

    fau7

    Joined:
    Jan 24, 2018
    Posts:
    48
    Hi DaceZa
    Thank you for the wonderful support here. And I have an incredibly short but a difficult question for you.
    Will there be a support for MVVM in WebGL? I just want to know your projection and thoughts.
    I wish you a fantastic weekend.
    With best wishes
    Fau
     
  37. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    You're welcome :)

    Unfortunately at the moment, the only reason why MVVM isn't supported in WebGL is because Unity's implementation of IL2CPP lacks a feature that is fundamental to the MVVM implementation (specifically, Remoting and transparent proxies). I have asked Unity as to whether or not this is going to be added, but to be honest, it doesn't sound like it will be anytime soon - Remoting is rarely used, so I imagine it isn't a major focus for the Unity team.

    Perhaps at some point I may be able to build some kind of workaround, but I'm really not sure, the proxy system is what lets XmlLayout know that ViewModel properties have been changed (without requiring users to manually notify XmlLayout of the change), which is naturally an important part of the process, so working out a way around that is tricky. Dependency Injection is a possible alternative, but I've yet to find a way to get that working without having to install addons into Visual Studio/etc. which is something I want to avoid as a) I can't include that in the asset package, and b) many XmlLayout users don't use Visual Studio.

    All in all, I'm sorry to say, the odds are not good at the moment :(

    Kind Regards,
    Dace
     
  38. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Really awesome work on this package.

    I am making a music player that has a reorderable playlist of songs on a mobile touch device.
    Is it possible to do drag and drop to reorder the songs.

    Cheers.
     
  39. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Noticed that the drag and drop example has a strange thing going on with the mouse pointer. As I drag the object, the mouse seems to lag behind quite a big distance as the object is being moved away from where it was dragged from. Here is a video screen shot.
    https://drive.google.com/open?id=1kIq_C2DWzax6IMZE5tevYq1-3LZp2Elw
     
  40. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi there,

    I see what you mean - XmlLayout uses Unity's OnDrag event's data to figure out where the element should go (using delta values) and this has sometimes seemed a little bit off. I wasn't able to break it quite as spectacularly as in your video, but I think I understand why it's happening (in my case it was usually only off by a few pixels, and only if you dragged pretty quickly, but that may depend on system performance or something along those lines).

    As the delta values seem to be unreliable, I've switched over to a new system using the pointer's position - the element will now always be moved to the pointer position when dragging. The upside is that it's always in the right place, the downside is that the elements position relative to the pointer is determined by its pivot value, which means that when you drag an element, it first 'snaps' to the pointer rather than being dragged relative to the point on which you start dragging it. I may be able to find a way around this (I'll take a look soon), but for now even with this drawback it does seem better, so I'm going to keep that change in for the next version of XmlLayout.

    Secondly, with regards to a reorderable list, yes, it can be done, but it is a little bit tricky. I've spent the past few hours building an example of this for you, and I think I'm now satisfied with how it's working. You can find the new example in the UI/XmlLayout/Examples/ReorderableList folder (including the scene, xml file, and controller). It is rather complicated, but hopefully it will serve to show you how this can be achieved :)

    I will be sending you the updated version of XmlLayout directly in a moment.

    I hope this helps!
     
  41. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Wow, thanks for your attention on the drag issue and your effort for making an example to demonstrate the power and flexibility of XmlLayout.
     
  42. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Thank you for sending the example.
    Super helpful. Really helps to learn from the example and see how it works
     
  43. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    In this music player project the design calls for a song list that is in effect an accordion style GUI.
    Each song is a row in the accordion. When the row is expanded, it can contain other gui elements. For example, it could also contain a horizontal sound slider or a series or check boxes, sound slider (because multiple sounds can be played at the same time and the sound slider is like a mixing control.

    Actually while on the topic of Accordion, I realized that there is not an example of an accordion in the package.

    It would be really amazing to have the Accordion because it is truly a workhorse on mobile devices.

    https://www.smashingmagazine.com/2017/06/designing-perfect-accordion-checklist/
    https://www.nngroup.com/articles/mobile-accordions/

    Cheers, and thanks for your help and the great work on this package.
     
  44. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    You're welcome :)

    I'll consider looking into the Accordion, it probably would be a good feature to add, although it may be a little while before I can get around to it.
     
  45. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Thanks for your consideration.
    Having an accordion in XmlLayout would be really cool, perhaps when you have time, it might not take so long because looks like most of the components are already there. Of course you are the master of this package so you would have a much better idea. I also checked some of the other GUI packages on the asset store and the most popular ones like Ngui, New Ui widget have builtin dragable accordions.

    Thanks again for the amazing work.
     
  46. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi there,

    I've spent some time working on an Accordion element, and I think it's shaping up nicely - I'm going to send an update through to you so you can take a look and see if it meets your requirements :)
     
    fau7 likes this.
  47. antsonthetree

    antsonthetree

    Joined:
    May 15, 2015
    Posts:
    102
    Hello - Does XmlLayout have any methods for displaying a modal type dialog? I've looked over the doc but I don't see anything in there about that.
     
  48. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi there,

    XmlLayout doesn't have any built-in shortcuts for displaying modal dialogs, but you can fairly easily construct a modal dialog in XmlLayout and use it as necessary. The example scene uses a simple modal dialog for a few things; you can see it's implementation here: http://www.digital-legacy.co.za/XmlLayout/Demo#MessageDialog
    and it's usage here: http://www.digital-legacy.co.za/XmlLayout/Demo#OptionsMenu

    Alternatively, you may also want to look into another of my products, uDialog, which is specifically designed for generating dialogs (modal or otherwise): https://www.assetstore.unity3d.com/en/#!/content/57454
    That said, under normal circumstances, I would probably just build a dialog in XmlLayout rather than mixing two different approaches :)

    I hope this helps!
     
  49. RiccardoAxed

    RiccardoAxed

    Joined:
    Aug 29, 2017
    Posts:
    119
    Hi, just bought the asset and I'm impatient to start using it.

    I would just ask you if it can be used in VR. Namely, if it's possibile to use a custom input system (like gaze-time input or Oculus controller) to detect which UI element the user is interacting with, then procedurally fire the standard mouse events, to allow XmlLayout to call the respective handlers (onClick,onMouseEnter/Exit), to show the tooltips and so on.

    Of course, any other suggestion will be very appreciated! :)

    Riccardo
     
  50. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi Riccardo,

    Yes, certainly - provided the VR input system fires standard onClick / onMouseEnter / onMouseExit events, then there should be no issues with XmlLayout event-handling. Some VR input modules do, and some don't - but any that support that standard Unity UI will work fine with XmlLayout.

    I haven't worked with VR very much myself, but I do recall doing some work for a client using with a VR input module that worked fine with Unity UI - I believe it was based on this: https://github.com/patcat/GoogleCar...r/Assets/Cardboard/Scripts/GazeInputModule.cs

    The asset I did some work on was this: https://assetstore.unity.com/packages/templates/systems/mobile-vr-inventory-system-91529 (specifically, I built the user interface for it, which uses the standard Unity UI).

    I hope this helps!

    Kind Regards,
    Digital Legacy