Search Unity

[RELEASED] XmlLayout: Xml-driven UI Framework

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

  1. Dan_lala

    Dan_lala

    Joined:
    May 14, 2015
    Posts:
    42
    after import I get lots of errors:

    import error.png

    Can someone please tell me why?
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,443
    It's not clear from the example if the XML Layouts can refer to any arbitrary class or prefab for XML elements, or just the elements you see in the included demos. For example, I may have acquired other Unity GUI assets like progress bars or styled buttons, which I want to use as-is (not just import their graphics and recreate).
     
  3. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    @Dan_lala

    Hi there, sorry about those error messages. It turns out that in more recent versions of Unity, Unity has changed the default 'API Compatibility Level' from .NET 3.5 to 2.0, and 2.0 doesn't contain the 'Remoting' namespace. However, you can switch from .NET 2.0 to .NET 4.0 by opening your 'Project Settings' (Edit -> Project Settings), and then under 'Player Settings' switching the 'API Compatibility Level' setting from .NET 2.0 to .NET 4.0.




    Additionally, 'Remoting' is only required for MVVM functionality, so if you don't want to use that, then you can disable it and then switch back to .NET 2.0 if you'd prefer by using the XmlLayout Configuration object (Assets -> XmlLayout -> Configuration)



    Sorry about the complication, I built the MVVM side of things when .NET 3.5 was the default setting in Unity, so at the time it seemed harmless enough to have it enabled by default. I intend to have it disabled by default for future versions of XmlLayout (so as to avoid these error messages), but I just need to find a way of disabling it for users who aren't using it, without disabling it for those who are (preferably without requiring them to do anything).
     
  4. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    @halley

    Hi there,

    XmlLayout can use non-standard elements, although in almost all cases it will be necessary to write a little bit of code to let XmlLayout know, for example, where to locate the prefab (if one is needed), how to handle instantiation (if any special handling is required), how to apply attributes (if they require any handling beyond simply passing the value to a field or property on the component). Additionally, the tag handler defines values for auto-complete, e.g. the name of the tag, and any attributes it should have available (and what data types to use for them).

    In general, writing tag handler code is fairly straight-forward, although naturally it is something that gets easier with experience. For example, here is a tag I recently added to support vector images:

    Code (CSharp):
    1. [ElementTagHandler("SVGImage")]
    2.     public class SVGImageTagHandler : ElementTagHandler
    3.     {
    4.         // this is a custom element, add it to the auto complete file
    5.         public override bool isCustomElement { get { return true; } }
    6.      
    7.         // No prefab required
    8.         public override string prefabPath { get { return null; } }
    9.  
    10.         // Specifies which component is the main component of this tag
    11.         public override MonoBehaviour primaryComponent
    12.         {
    13.             get
    14.             {
    15.                 return currentInstanceTransform.GetComponent<XmlLayoutSVGImage>();
    16.             }
    17.         }
    18.  
    19.         // attributes for auto complete
    20.         public override Dictionary<string, string> attributes
    21.         {
    22.             get
    23.             {
    24.                 return new Dictionary<string, string>()
    25.                 {
    26.                     { "image", "xs:string" },
    27.                     { "preserveAspect", "xs:boolean" },
    28.                 };
    29.             }
    30.         }
    31.  
    32.         // create and return an instance of this tag
    33.         // (used by XmlLayout to get an instance when you use the tag)
    34.         public override XmlElement GetInstance(RectTransform parent, XmlLayout xmlLayout, string overridePrefabPath = null)
    35.         {
    36.             var instance = base.GetInstance(parent, xmlLayout, overridePrefabPath);
    37.  
    38.             instance.gameObject.name = "SVGImage";
    39.             instance.gameObject.AddComponent<XmlLayoutSVGImage>();
    40.             instance.gameObject.AddComponent<LayoutElement>();
    41.  
    42.             MatchParentDimensions();
    43.  
    44.             return instance;
    45.         }
    The tag handler for this is fairly simple, it specifies a) that no prefab is used, b) the primary component is of type 'XmlLayoutSVGImage', c) there are two attributes (beyond the default attributes), and d) how to create a new instance (normally only required if no prefab is used). In this case, no special attribute handling is required, so XmlLayout's default 'ApplyAttributes()' behaviour defined in the parent 'ElementTagHandler' class is left as-is (it uses reflection to locate attributes by name, and then attempts to apply values to them without requiring you to define handling for each attribute).

    There's documentation on this available here: http://www.digital-legacy.co.za/XmlLayout/Documentation#CustomTags

    I hope this helps answer your question :)
     
    halley likes this.
  5. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    2,443
    Great! I briefly skimmed that page but didn't quite connect that I would need a custom tag for each custom UI element type I wanted to use from XML. Very informative reply, thanks!
     
  6. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
  7. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    @Dan_lala

    After seeing your post, I have decided that it is really important to get XmlLayout working by default in Unity 2019 without requiring any changes to be made, especially seeing as MVVM is an optional feature that isn't required for many users. As a result, I've made it so that, as of XmlLayout v1.86, MVVM is disabled by default, and these error messages will not be shown. Users can still enable MVVM if they wish (after switching to .NET 4x), but by default MVVM functionality will not be available and the error messages will not be shown when importing XmlLayout into a new project in Unity 2019.

    The unfortunate downside is that users who have been using MVVM previously will have to manually enable MVVM in their projects after importing the updated version, but for everyone else, no changes will need to be made and everything should work out of the box.

    v1.86 has been submitted to the asset store a few minutes ago, and should be available in a day or so. In the meantime, you can still continue as-is by following the steps I outlined in my earlier post - I just wanted to let you know that the problem will has been resolved and won't occur again in future :)
     
  8. Dan_lala

    Dan_lala

    Joined:
    May 14, 2015
    Posts:
    42
    Great! You might also want to change it to a more promiment spot... i had looked at the asset descrition and the online documentation for those errors and must have missed Installing XmlLayout -> Additional Note #2 (found it now on hindsight), ie. it might not be the best way to get this message across (plus it is a bit hidden and not mentioning any errors).

    Thank you very much for you help and this extension!
     
  9. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome! :)
     
  10. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    I have net 4 enabled on 2019.2.16f1
    ran the MVVC example and getting this error. Do you know what this could be.
    Cheers
     

    Attached Files:

  11. DaceZA

    DaceZA

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

    Have you enabled MVVM? In more recent versions of XmlLayout, MVVM is disabled by default. You can enable it by using the XmlLayout Configuration object, which is accessed via the Assets -> XmlLayout -> Configuration menu. On the configuration editor, there is a button at the bottom which you can click to enable or disable MVVM.

    If MVVM is not enabled, then the tags (such as 'List') will not be compiled, which is usually why you why you would see error messages like this one.

    If that doesn't help, it may be necessary to re-import XmlLayout (I noticed that, for some reason, switching between .NET 2.0 and .NET 4.0 can introduce compilation issues which seem to require a re-import. In Unity 2019.3, this seems to have been fixed - switching back and forth between .NET implementations didn't cause the problem anymore).

    I hope this helps!
     
    EmeralLotus likes this.
  12. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    Thank you, this was my problem. Fixed
     
  13. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    I would like to make a scheduling interface like that of Teamweek and wondering if you have tips how it can be done with XMLlayout. Here is a link to a video of the interface

    There are many use cases for this kind of interface. for example, a video or audio editing interface.

     
  14. DaceZA

    DaceZA

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

    You could put together the basic UI using tables (remember that you can nest tables within other table cells if need be) - but setting up the 'tasks' will likely require a bit of code to set up their size/position/etc. depending on the task date/duration/etc. You will probably need to position the task position manually outside of (and above) the the tables.
    Overall I'd say it's definitely doable, but there will be quite a bit of work involved in putting it all together.
     
  15. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Using v1.93 and it seems to be pretty good. However the buttons do not really work well in my case because I want to create a button that has a smaller touchable area than the images I'm using for it. Transition is 'SpriteSwap' but I'm missing the attribute 'targetGraphic' so I can set the path of the image to it!:( BTW it's a button where its images are changed when I hover over it but I can't figure out how to use it properly with xmllayout.:mad:

    Also I do miss support for DoTween (Pro). Otherwise nice work, dude!:D
     
  16. DaceZA

    DaceZA

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

    I've added a targetGraphic attribute for you - you can get it here: https://pastebin.com/FsxbDMvt

    I'll include it in the next version of XmlLayout (v1.94).

    The targetGraphic expects either an internalId (if the target element is a child of the button) or a regular id (if it is not), for example:

    Code (CSharp):
    1.   <Button width="100" height="32" transition="SpriteSwap" color="clear" pressedSprite="Sprites/Icons/Cancel" disabledSprite="Sprites/Icons/Arrow_Right" highlightedSprite="Sprites/Icons/Arrow_Left" targetGraphic="target">
    2.   </Button>
    3.  
    4.   <Image id="target" image="Sprites/Icons/Move" width="128" height="64" raycastTarget="false" />



    PS: Unity recently added a 'selected' state in addition to the original states for selectable elements, I've just added attributes for that as well which will be included in v1.94. If you need them immediately, you can replace your copy of UI/XmlLayout/Custom Attributes/Transition.cs with this: https://pastebin.com/DAfpahus

    As for DoTween, there's nothing stopping you from using it. XmlLayout has its own internal animation system which you can use to create custom animations (See Examples/Animation) if you wish, but with a little bit of code you can easily use DoTween or any other animation framework (after all, elements created by XmlLayout are more-or-less standard Unity UI elements and as such can be interacted with in the same way).

    PS #2 - I'll be sending you an updated XmlLayout package with all of the above, that way you won't need to add anything manually or make any changes when v1.94 comes out.
     
    Last edited: Jan 25, 2020
  17. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Awesome!:) Thank you so much for implementing the targetGraphic-attribute in xmllayout. I will try this ASAP! Now this is some great support!:)
     
  18. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome :)
     
  19. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Is it just me or does xmllayout not work in 2019.3.0f6?:( It disappeared in this Unity version...switching back to v2019.2.12f1.
     
  20. DaceZA

    DaceZA

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

    I've just tested in 2019.3.0f6 and there appears to be an exception being thrown in the example scene, preventing it from being rendered - it looks like Unity may have changed the order of event execution as the Start() method used by one of the examples used to be called after XmlLayout's initialization in earlier versions of Unity, but is now being called before it. Fortunately, it's easy enough to fix, I've just added a delay to that code so that it executes once initialization is complete which fixes the problem - once the exception is removed, the example scene seems to work correctly.

    Outside of the main example scene, everything seemed to work correctly - are other scenes affected for you?

    Here is the fix for the example scene, specifically, UI/XmlLayout/Examples/XmlLayout_Example_ColorSchemeManager.cs (replace your copy of this file with this one and it should sort the example scene out for you): https://pastebin.com/ibZXSaEy
     
  21. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    I will test it in my project but I have the feeling that xmllayout won't work. As I said before it disappeared in my case. When I right-click xmllayout has gone. I try to test xmllayout with 2019.3 and create an empty game project.

    BTW: While importing my project into 2019.3 from 2019.2 Unity changed the asset database from version 1 (deprecated) to version 2. Maybe that's the cause of the issue?

    Update: Finally it works! The problem was that the asset "2D Homing Missiles" from Sean Duffy was not working properly (i.e. there were two GUI-bugs in 2019.3). I removed this asset and now it's working! Thanks for your great support! Much appreciated!:D
     
    Last edited: Feb 5, 2020
  22. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome! I'm glad you managed to get it working :)

    Unfortunately, as you've seen, if the project can't compile due to code in one plugin, that can prevent compilation of the rest of it as well - it's not always the case (for example, plugins in different assemblies usually won't affect one another). If you like, XmlLayout does allow you to have it create its own separate assembly (via the Assets -> XmlLayout -> Configuration menu -> 'Generate Assembly Definition Files'), although naturally (and unfortunately) this menu is only available if XmlLayout was able to compile in the first place :)
     
    Last edited: Feb 6, 2020
  23. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    XMLlayout (v1.94) seems to have some troubles in Unity3D 2019.3.3f1! I tested it with some example-scenes you made and this is the result:

     
  24. DaceZA

    DaceZA

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

    I've just tested out the example scenes in Unity 2019.3.3f1 and they seem to be working normally for me.

    From the screenshots you've provided, that appears to be an issue with either Unity's UI 'Text', or possibly something has gone wrong with the font. The first thing I'd try would be to re-import the font (You can do this by locating the UI/XmlLayout/XmlLayout Standard Assets/Fonts/ folder, right-clicking it, and selecting 'Reimport'). It may be necessary to reload the example scene after doing so. If that doesn't help, then I'd try deleting the XmlLayout folder entirely and then re-importing it from scratch.

    It may also be worth trying to re-import the Unity UI package, you can find it under Packages/Unity UI in the project window.

    Can you give that a try and let me know if it helps? Thanks!
     
  25. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Hi,

    I reverted back to Unity v2019.2.21f1 because their latest version it way too unstable so I cannot test it if it works. Maybe I'll test it at a later time but currently I'm happy with 2019.2.21f1!:)
     
    DaceZA likes this.
  26. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    There's a problem with the slider-object in xmllayout.:(

    When I want to change the knob of the slider I have to use the attribute handleImage, right? So far so good - the image appears but is distorted. So how do I set the width and height of that handle's image?:confused:

    In Unity there is the button "Set Native Size" - but that's not available as an attribute in xmllayout...
     
  27. DaceZA

    DaceZA

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

    I've added two new attributes for you - handleWidth and handleHeight. They'll be included in the next version of XmlLayout, but for now you can get them here: https://pastebin.com/2RJhMSTy
    (Add that script to your project - the official location will be UI/XmlLayout/Custom Attributes/SliderHandleDimensions.cs)

    You can also, if you wish, toggle the 'Preserve Aspect' value using the existing handlePreserveAspect attribute.

    I hope this helps!
     
  28. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Hi,

    thank you so much for implementing these two attributes!:) I really appreciate your work!:D

    BTW: I was looking for the attribute handlePreserveAspect in your online-documentation but couldn't find it.
     
    Last edited: Mar 6, 2020
  29. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Sorry but I got another problem with xmllayout: Is there any possibility to adjust the height and/or the width of the slider's background fill? Just curious because I used two images via the attributes 'backgroundImage' and 'fillImage' and the problem is that the slider's bar now looks kinda distorted (see screenshot):

    As you can see the height of the slider's bar is way too big...:confused:

    One last question: Is there a possibility to add an outline to the slider's bar? I just ask because I used the attributes 'outline' and 'outlineSize' but nothing happened (couldn't see anything)...
     
    Last edited: Mar 8, 2020
  30. DaceZA

    DaceZA

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

    a) By default, the width/height of the background image matches the dimensions of the element - normally I'd recommend just adjusting the size of the Slider element itself. However, if you wish, you can add the following attribute code to your project: https://pastebin.com/p5rdjKMP (I'll add them to the XmlLayout project UI/XmlLayout/Custom Attributes/SliderBackgroundDimensions.cs) This adds the 'sliderBackgroundHeight' and 'sliderBackgroundWidth' attributes to the Slider element.

    b) This was a bug due to how the Slider is set up by default in Unity - the 'outline' attributes add a Unity 'Outline' component to the element, which renders an outline of the object's 'Image' component. However, the Slider doesn't actually have an Image component - the background image is actually on a child object. I've added a special clause to the Outline and Shadow attributes to specify that, for the Slider element, it should actually add the component to the child rather than directly to the slider element itself, and now it works correctly.

    I'll be sending you an updated version of XmlLayout via pm now (with both of the above changes, so you won't need to add the attribute code yourself).

    I hope this helps!
     
  31. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Awesome! Thank you so much for making this great version (just downloaded it and tested it)!:) Keep up the great work (this is really an excellent plugin)!:D
     
  32. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome :)
     
  33. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Just curious: Is there a selectedSprite-state available?

    There seems to be a bug inside your framework: When you want to apply two different sprites for two different images with IDs ('imgCancel' and 'imgApply') then both look the same (Unity's inspector says both have a different source (i.e. file) but in my case they looked the same - that's weird!)...:confused:

    In this code the bug appeared for the first time:
    Code (CSharp):
    1. <HorizontalLayout class="buttonList optionsTxt" id="optionsButtonList">
    2.                 <Button class="btnCancel" onClick="HideOptions();">
    3.                     <image id="imgCancel"><TextMeshPro class="buttonTxt optionsTxt optionsCancelTxt" text="Cancel"/></image>
    4.                 </Button>
    5.                 <Button class="btnApply" onClick="SaveOptions();">
    6.                     <image id="imgApply" class="img"><TextMeshPro class="buttonTxt optionsTxt" text="Apply"/></image>
    7.                 </Button>
    8.             </HorizontalLayout>
    Update: Your framework is almost perfect!:) However - I need to adjust the width / height of the slider's FILL, too. Can you implement a custom attribute for that fill, please? That would be awesome!:D
     
    Last edited: Mar 13, 2020
  34. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    a) Yes, there is - 'selectedSprite'. However, I have just checked and it wasn't working correctly, sorry - I've corrected this.
    b) How are you setting the sprite values? I tried to replicate this issue (using your Xml), but it seemed to work correctly when paired with the following test code:

    Code (CSharp):
    1.     public override void LayoutRebuilt(ParseXmlResult parseResult)
    2.     {
    3.         xmlLayout.GetElementById("imgCancel").SetAndApplyAttribute("image", "Sprites/Layout/Base");
    4.         xmlLayout.GetElementById("imgApply").SetAndApplyAttribute("image", "Sprites/Layout/Button");
    5.     }
    I tested this in Unity 2019.3.3f1. If, in your case, the Image component is showing the correct value, but in the scene it is not, that may be a Unity issue (the Image component is a standard Unity element, XmlLayout just sets its properties using the attributes provided in the Xml).

    c) I've added 'sliderFillAreaWidth' and 'sliderFillAreaHeight' for you - be advised that modifying the fill area can result in unusual behaviour (e.g. Unity sliders are designed to have the background, fill area, and handle area match - if they don't, then you can, for example, drag the handle out of the fill area)

    I'll PM you the update.
     
  35. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Excellent post!:) Thanks so much for implementing those two fill-attributes and fixing the selectedSprite-bug!:D
    I just downloaded the new updated version and I will check it out ASAP...
    BTW: Keep up the great work!:)
     
    Last edited: Mar 13, 2020
  36. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome. Thank you :)
     
  37. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    How do I set the width of a VerticalScrollView's scrollbar?:confused:
     
  38. DaceZA

    DaceZA

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

    You can use the 'verticalScrollbarWidth' property to control the width of the scrollbar.
     
  39. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Excellent! Thank you very much.:) However when I try to force a line break with "/n" using TextMesh Pro nothing happens.o_O How do I force a line break using xmllayout?
     
  40. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    Hi,

    If you need to force a line break without breaking to the next line in the code, you can use the '<br>' tag inside the TextMeshPro text - however, as TextMesh Pro text formatting tags aren't valid Xml, you'll then need to wrap the text in a CDATA block (as per the first example here), e.g.:

    Code (CSharp):
    1. <TextMeshPro>
    2. <![CDATA[Line One<br>Line Two]]>
    3. </TextMeshPro>
    4.  
     
  41. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Ah! Very nice - that works! Thank you very much for your help!:)
     
  42. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome :)
     
  43. anp

    anp

    Joined:
    Jul 1, 2015
    Posts:
    7
    Hi,
    I have been reading documentation and watching youtube tutorials on XmlLayout, and still have a few questions:
    1) If I were to make a custom button prefab and use it via custom xml tag like so:
    Code (CSharp):
    1. <MyButton> Button Text Here </MyButton>
    How could I achieve that?

    2) How can I access children components of that button? Like text or image? I have a button prefab with text and image children components, and would like to know how to set the text and image sprite from inside XmlFile where the button is used. What would my TagHandler class look like?
    My progress: I am able to add custrom attributes to dictionary, and intellisense accepts that, also I am able to load my prefab via prefabPath successfully, but that's about where it ends for me :D

    Code (CSharp):
    1. [ElementTagHandler("MButton")]
    2. public class MButtonHandler : UI.Xml.Tags.ButtonTagHandler
    3. {
    4.     public override bool isCustomElement { get { return true;  } }
    5.  
    6.     public override string prefabPath { get { return "Prefabs/MyButtons/APButton"; } }
    7.  
    8.     public override MonoBehaviour primaryComponent
    9.     {
    10.         get
    11.         {
    12.             return currentInstanceTransform.GetComponent<XmlLayoutButton>();
    13.         }
    14.     }
    15.  
    16.     //attributes for autocomplete
    17.     public override Dictionary<string, string> attributes
    18.     {
    19.         get
    20.         {
    21.             return new Dictionary<string, string>()
    22.             {
    23.                 { "text", "xs:string" }
    24.             };
    25.         }
    26.     }
    27.  
    28.     public override void ApplyAttributes(AttributeDictionary attributesToApply)
    29.     {
    30.         base.ApplyAttributes(attributesToApply);
    31.     }
    32. }
    What am I missing?
     
  44. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174

    Hi there!

    There are several ways you can access the child components - the easiest way is probably to create a custom component with public properties referencing those child components, e.g. something like the following:

    Code (CSharp):
    1.  
    2. public class MButtonComponentReferences : MonoBehaviour
    3. {
    4.      public UnityEngine.UI.Image Image;
    5.      public UnityEngine.UI.Text Text;
    6. }
    7.  
    Then, you can attach that component to your prefab, and assign the public references by dragging the components or GameObjects into the relevant elements in the inspector.

    Then, in your code, you can access them using the new component, e.g.

    Code (CSharp):
    1.  
    2.     public override void ApplyAttributes(AttributeDictionary attributesToApply)
    3.     {
    4.         base.ApplyAttributes(attributesToApply);
    5.  
    6.         var mButtonReferences = currentInstanceTransform.GetComponent<MButtonComponentReferences>();
    7.  
    8.         if (attributesToApply.ContainsKey("mButtonImage")) mButtonReferences.image.sprite = attributesToApply["mButtonImage"].ToSprite();
    9.         if (attributesToApply.ContainsKey("mButtonText")) mButtonReferences.text.text = attributesToApply["mButtonText"];
    10.     }
    11.  
    A second approach is to use GetComponentInChildren<Type>(), although this will only really work to locate components that have a unique type.

    Another possible approach is to generate your button using Xml rather than a prefab with a tag handler that extends BaseXmlTagHandler (http://digital-legacy.co.za/XmlLayout/Documentation#CustomXmlTags)

    In this approach, you provide either some Xml for an Xml File which is then used by XmlLayout to generate your element - if you use this approach, you can then issue your image/text/etc. id values, and then you can locate them using GetElementById(). I've made a tutorial video on this which you can find here:


    I hope this helps!
     
  45. anp

    anp

    Joined:
    Jul 1, 2015
    Posts:
    7
    Thank you very much!
     
  46. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome :)
     
  47. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Hi,

    I have a serious problem with a button I created with xmllayout: When I click on the button it shall fire a method called "BuyThis();". The strange thing is that it doesn't work (not getting fired).

    This is the code:
    Code (CSharp):
    1.  
    2. <TableLayout id="vertContent" class="vertContent" cellBackgroundColor="clear">
    3.                     <Row id="shopModule" class="shopModule" preferredHeight="480">
    4.                         <Cell id="shopContent" class="shopContent" active="false">
    5.                             <VerticalLayout class="shopContent02" spacing="10">
    6.                                 <Image id="shopItemImg" class="shopItemImg" name="shopItemImg">
    7.                                     <TextMeshPro internalId="shopItemHeader" id="shopItemHeader" class="shopItemHeader" text="Novice Bundle"/>
    8.                                     <TextMeshPro internalId="shopItemTxt" id="shopItemTxt" class="shopItemTxt" text="0.99$"/>
    9.                                 </Image>
    10.                                 <Button id="shopBtn" class="shopBtn" name="shopBtn" onClick="BuyThis();">
    11.                                     <image id="imgShopBtn" class="imgShopBtn" name="imgShopBtn"><TextMeshPro id="shopBtnTxt" class="shopBtnTxt shopTxt" text="0.99$"/></image>
    12.                                 </Button>
    13.                             </VerticalLayout>
    14.                         </Cell>
    15.                     </Row>
    16.                     <Row id="shopModule02" class="shopModule" preferredHeight="169"></Row>
    17.                     <Row id="shopModule03" class="shopModule" preferredHeight="169"></Row>
    18.                 </TableLayout>
    19.  
    Now my question is: What might be the problem? Why doesn't get my method fired when I click on the button (is there something interfering)? BTW: There is another button in my GUI and it works - this makes it even stranger...o_O

    Here is some other code:
    Code (CSharp):
    1. <Button
    2.             preferredWidth="242"
    3.             preferredHeight="92"
    4.             highlightedSprite="GUI/gui_levels_btnhover_720p"
    5.             pressedSprite="GUI/gui_levels_btnpress_720p"
    6.             type="simple"
    7.             color="rgba(1,1,1, 0)"
    8.             preserveAspect="true"
    9.             colors="rgb(1,1,1)|rgb(0.1,0.5,0.7)|rgb(0.1,0.5,0.7)"
    10.             textColor="#8fc7fc"
    11.             transition="SpriteSwap"
    12.             onClickSound="Sound/Bleeep-Public_D-17"
    13.             onMouseEnterSound="Sound/High_Bee-Public_D-135"
    14.             raycastTarget="true"
    15.         />
     
  48. DaceZA

    DaceZA

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

    I tested out your code and it turns out that the TextMesh Pro element that is nested within your button is blocking raycasts (preventing clicks from reaching the button element behind it) - if you disable raycasts on that element, then it works okay, e.g.
    Code (CSharp):
    1. <Button id="shopBtn" class="shopBtn" name="shopBtn" onClick="BuyThis();">
    2.     <image id="imgShopBtn" class="imgShopBtn" name="imgShopBtn"><TextMeshPro id="shopBtnTxt" class="shopBtnTxt shopTxt" text="0.99$" raycastTarget="false"/></image>
    3. </Button>
    XmlLayout has code in place to control some of the TextMesh Pro properties (such as RaycastTarget), but only if the <TextMeshPro> element is the first child of like in the example here. It does so by locating the original <Text> element used by the button and replacing it with your <TextMeshPro> element - then, when done this way, attributes like <Button text="0.99$" ... > would be applied to the <TextMeshPro> element. However, if the <TextMeshPro> element isn't the first child, then it just uses the default nested element behaviour, in which case it is just an element with no special relation to the button other than that it is a child of it.

    If you're looking to set the background image and use TextMesh Pro, it's probably best to use something like the following:


    Code (CSharp):
    1. <Button image="/YourPath/YourImage" id="shopBtn" class="shopBtn" name="shopBtn" onClick="BuyThis();">
    2.     <TextMeshPro id="shopBtnTxt" class="shopBtnTxt shopTxt" text="0.99$"/></image>
    3. </Button>
    Then, if you're looking to change the image/etc. of the button, you can do so by changing the image property of the <Button> element, or you could also look into using a sprite swap transition (attributes found here: https://digital-legacy.co.za/XmlLayout/Documentation#InputFields-Button), or alternatively, just using Defaults values with hover/select classes (https://digital-legacy.co.za/XmlLayout/Documentation#Defaults-Hover/Press/SelectClasses) if that is sufficient.

    If you need a nested image, Button elements do provide an 'icon' attribute which you can use to set an image within the button with a few options for configuring how it works and looks/etc. although if you need more than that, adding an image as a child of the button is not an issue, provided you either have it as the second child, or take control over the TextMesh Pro element's attributes yourself (as you've done already with the exception of raycastTarget).

    I hope this helps!
     
  49. drpelz

    drpelz

    Joined:
    Dec 7, 2017
    Posts:
    69
    Thank you very much for your detailed answer! I just figured out the problem: I was adding a listener to the prefab - not the clone. I have several clones of the same prefab and each of them uses a button. I made a small script that iterates through each button of the appropriate clone and attach an onClick-listener to it. Now it works like a charm!:D

    This is the code that saved my day:
    Code (CSharp):
    1. Button[] _buttons = _newModule.GetComponentsInChildren<Button>();
    2.         Button _btn = _buttons[0].GetComponent<Button>();
    3.         _btn.onClick.AddListener(BuyThis);
    Anyways - thanks for your help! This is really some great support!:)
     
  50. DaceZA

    DaceZA

    Joined:
    Dec 19, 2014
    Posts:
    174
    You're welcome, glad you managed to get it sorted!