Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question TypedUxmlAttributeDescription<TimeSpan>

Discussion in 'UI Toolkit' started by CaseyHofland, Jul 10, 2023.

  1. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    542
    I would like to create a
    TimeSpanField
    . I've been trying to stay inline with Unity's practices and want to write a
    UxmlTimeSpanAttributeDescription
    to compliment it.

    Code (CSharp):
    1. using System;
    2. using UnityEngine.UIElements;
    3.  
    4. namespace UnityClock.UIElements
    5. {
    6.     public class TimeSpanField : BaseField<TimeSpan>
    7.     {
    8.         public new class UxmlFactory : UxmlFactory<TimeSpanField, UxmlTraits> { }
    9.  
    10.         public new class UxmlTraits : BaseFieldTraits<TimeSpan, UxmlTimeSpanAttributeDescription> { }
    11.  
    12.         public TimeSpanField() : this(null) { }
    13.  
    14.         public TimeSpanField(string label) : base(label, new Label()) { }
    15.     }
    16. }
    17.  
    Code (CSharp):
    1. using System;
    2. using UnityEngine.UIElements;
    3.  
    4. namespace UnityClock.UIElements
    5. {
    6.     //
    7.     // Summary:
    8.     //     Describes a UXML TimeSpan attribute.
    9.     public class UxmlTimeSpanAttributeDescription : TypedUxmlAttributeDescription<TimeSpan>
    10.     {
    11.         //
    12.         // Summary:
    13.         //     The default value for the attribute, as a string.
    14.         public override string defaultValueAsString => base.defaultValue.ToString();
    15.  
    16.         //
    17.         // Summary:
    18.         //     Constructor.
    19.         public UxmlTimeSpanAttributeDescription ()
    20.         {
    21.             base.type = "System.TimeSpan";
    22.             base.typeNamespace = "http://www.w3.org/2001/XMLSchema";
    23.             base.defaultValue = TimeSpan.Zero;
    24.         }
    25.  
    26.         //
    27.         // Summary:
    28.         //     Retrieves the value of this attribute from the attribute bag. Returns the value
    29.         //     if found; otherwise, it returns defaultValue.
    30.         //
    31.         // Parameters:
    32.         //   bag:
    33.         //     The bag of attributes.
    34.         //
    35.         //   cc:
    36.         //     The context in which the values are retrieved.
    37.         //
    38.         // Returns:
    39.         //     The value of the attribute.
    40.         public override TimeSpan GetValueFromBag(IUxmlAttributes bag, CreationContext cc)
    41.         {
    42.             return GetValueFromBag(bag, cc, (string s, TimeSpan t) => ConvertValueToTimeSpan(s, t), base.defaultValue);
    43.         }
    44.  
    45.         public bool TryGetValueFromBag(IUxmlAttributes bag, CreationContext cc, ref TimeSpan value)
    46.         {
    47.             return TryGetValueFromBag(bag, cc, (string s, TimeSpan t) => ConvertValueToTimeSpan(s, t), base.defaultValue, ref value);
    48.         }
    49.  
    50.         private static TimeSpan ConvertValueToTimeSpan(string v, TimeSpan defaultValue)
    51.         {
    52.             if (v == null || !TimeSpan.TryParse(v, out var result))
    53.             {
    54.                 return defaultValue;
    55.             }
    56.  
    57.             return result;
    58.         }
    59.     }
    60. }
    61.  
    This code runs fine, however my attribute doesn't show up in the UIBuilder.

    TimeSpanField.png vs ExampleField.png where
    ExampleField
    uses a double, otherwise it is the same as
    TimeSpanField
    .

    Normally I would write this off as "TimeSpan can't be serialized" but I thought that AttributeDescriptions are always strings, and use defaultValueAsString and GetValueFromBag to convert between the two.

    I summon thee, @uDamian



    If
    UxmlTimeSpanAttributeDescription
    is not possible, what is my best course of action? My assumption is I will have to inherit from e.g.
    BaseFieldTraits<string, UxmlStringAttributeDescription>
    with a custom
    override Init
    instead, but I've had some conversion errors there, don't exactly know why.
     

    Attached Files:

    SkywardAssembly likes this.
  2. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    542
    Unrelated, but you guys wrote some killer documentation, it was really clear how to pick up creating custom controls!
     
  3. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    542
    Hi 1606917[/URL]]@uDamian wanted to do a quick plug before I try implementing a different solution on Tuesday. I’d rather not go there, because that solution is a lot more icky than I’d like, but sometimes we have to make weird solutions to solve weird problems.
     
  4. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    542
  5. uDamian

    uDamian

    Unity Technologies

    Joined:
    Dec 11, 2017
    Posts:
    1,203
    Indeed, very unlikely to be backported.