Search Unity

Sharing/reusing color values

Discussion in 'UIElements' started by cecarlsen, Jul 26, 2019.

  1. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    522
    What is the best practice for storing a palette of colors to be used across a UIElements solution?

    I also need access to the colors from C# because I use generateVisualContent where vertices need tints from the palette.

    I read that Unity plans to support USS variables, but I can't find any information on it.
    https://forum.unity.com/threads/sassy-css.591724/#post-3955354
     
  2. jonathanma_unity

    jonathanma_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    61
    Hi cecarlsen,

    I can confirm that USS variables will be available on 2019.3 starting at 2019.3.0a10.

    With this you will be able to define your color palette as variables and reuse them across your USS files.

    They are compliant with CSS variables so you can refer to this link for more information : https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties

    To access the variables in C# you need to register to the CustomStyleResolvedEvent which is sent to any elements matching variable definitions. From there you can use the ICustomStyle.TryGetValue interface to retrieve the colors.
     
    Last edited: Jul 26, 2019
  3. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    101
    Also by registering to the
    CustomStyleResolvedEvent
    on your element you can read variables and use them in C#, for example in combination with generateVisualContents.

    Code (CSharp):
    1. class MyElement
    2. {
    3.  
    4.    static CustomStyleProperty<Color> s_MyColor = new CustomStyleProperty("my-color");
    5.  
    6.    Color m_Color;
    7.  
    8.    public MyElement()
    9.    {
    10.       RegisterCallback<CustomStyleResolvedEvent>(evt =>
    11.       {
    12.           if (!evt.customStyle.TryGetValue(s_MyColor, out m_Color))
    13.           {
    14.               // assign default color
    15.                m_Color = Color.red
    16.           }
    17.       });
    18.    }
    19. }
     
    cecarlsen and Stardog like this.
  4. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    522
    Thanks again @antoine-unity It works. I encapsulated USS color palette access in a static class like so because I like to have colors global. I call the method from a callback in EditorWindow.OnEnable after adding the stylesheet to the root element. With the given API I don't see how to avoid a lot of name repetitions. It's not pretty and it will get worse as more colors are added.

    Code (CSharp):
    1. public static class Colors
    2. {
    3.     public static Color connection;
    4.     public static Color connectionHover;
    5.     public static Color connectionSelected;
    6.     public static Color connectionSelectedHover;
    7.  
    8.     static CustomStyleProperty<Color> connectionProp = new CustomStyleProperty<Color>( "--connection-color" );
    9.     static CustomStyleProperty<Color> connectionHoverProp = new CustomStyleProperty<Color>( "--connection-hover-color" );
    10.     static CustomStyleProperty<Color> connectionSelectedProp = new CustomStyleProperty<Color>( "--connection-selected-color" );
    11.     static CustomStyleProperty<Color> connectionSelectedHoverProp = new CustomStyleProperty<Color>( "--connection-selected-hover-color" );
    12.  
    13.     public static void ReadColorsFromUSSProperties( CustomStyleResolvedEvent evt )
    14.     {
    15.         evt.customStyle.TryGetValue( connectionProp, out connection );
    16.         evt.customStyle.TryGetValue( connectionHoverProp, out connectionHover );
    17.         evt.customStyle.TryGetValue( connectionSelectedProp, out connectionSelected );
    18.         evt.customStyle.TryGetValue( connectionSelectedHoverProp, out connectionSelectedHover );
    19.     }
    20. }
    EDIT: In USS, all my color variables are defined in :root. Element type specific colors could be placed in their respective USS selectors, but 1) I like to have the colors centralized and 2) it seems like extra work to grab the same colors again and again every time an element of a specific type is created.
     
    Last edited: Jul 29, 2019
  5. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    101
    This API was mostly designed to be used in the context of a single element. Therefore it shouldn't be required to use multiple variables for each state like "hover" or "selected". Instead, if the element is hover and a selector with ":hover" that changes the "--connection-color" exists, the CustomStyleResolvedEvent event will be invoked when the user interacts with it.

    Another way to limit the number of variables is to stick to a color palette with descriptive names such as "--highlight-color", "--accent-color", "--disabled-color", etc.
     
  6. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    522
    Ah, enlightening. I see that I may be working against your design here.

    However, 1) I am drawing many ConnectionElements and I don't see how it can be performant to pick up colors using callbacks in every element and 2) updating the variables inside selectors spreads out my color palette again, which I find messy. I also cannot use more general global descriptive names, because colors like "--highlight-color", "--accent-color", "--disabled-color" varies for my element types.

    I'll get back if find a cleaner solution.