Search Unity

Question Call OnValidate (or similar) when recttransform is changed in the inspector

Discussion in 'UGUI & TextMesh Pro' started by Mpx83, May 24, 2023.

  1. Mpx83

    Mpx83

    Joined:
    Apr 4, 2023
    Posts:
    21
    Hi,
    I have made a custom Graphic UI element. The element works fine and if I change one of the parameters in the inspector the element is updated correctly.
    The size of this element is related to the panel in which it is located and this is the only problem.
    If I change the recttransform of the panel, like changing the anchors, The ui element is not resized but only translated because the Onvalidate function is not called when the recttransform is changed.
    I do not know how to make the element update when I resize the panel in the inspector. Any idea?
     
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,981
    When you said a custom Graphics UI element, do you mean you actually subclassed the Graphic class and created your own class? If that's the case, how about overriding OnTransformParentChanged? How do you actually "draw" your element? The UI system uses the OnFillVBO callback to actually fill the object. The object should be invalidated automatically when a parent has changed (unless you overridden one of the necessary callbacks without calling the base implementation).

    We can't really help you without any concrete information on what your custom Graphics UI element does.
     
  3. Mpx83

    Mpx83

    Joined:
    Apr 4, 2023
    Posts:
    21
    So what I did is like this (cut the code because is complicated and I think we will lose focus)
    The Graphic component get as input a Vector2 array with the coordinates of the point of the mesh

    Code (CSharp):
    1. [RequireComponent(typeof(CanvasRenderer))]
    2. public class MyUI : Graphic
    3. {
    4.     [SerializeField] private Vector2[] points;
    5.     // other variables
    6.  
    7.     protected override void OnPopulateMesh(VertexHelper vh)
    8.     {
    9.         // Set the mesh
    10.     }
    11.     public void SetMyUI(Vector2[] InputPoints)
    12.     {
    13.         points = InputPoints;
    14.         SetVerticesDirty();
    15.     }
    16. }
    In the panel there is a controller script that gets several inputs and compute the points of the mesh. To verify that everything is working fine I call the controll routine also in OnValidate(). Like this

    Code (CSharp):
    1. public class myUIController : MonoBehaviour
    2. {
    3.  
    4.     [SerializeField] Variable1;
    5.     [SerializeField] Variable2;
    6.     [SerializeField] Variable3;
    7.     ...
    8.  
    9.     private void Start()
    10.     {
    11.         ComputePoints();
    12.     }
    13.  
    14.     private void OnValidate()
    15.     {
    16.         ComputePoints();
    17.     }
    18.  
    19.     private void ComputePoints()
    20.     {
    21.         //Do all the computation needed
    22.         MyUIObject.SetMyUI(InputPoints);
    23.     }
    24. }
    25.  
    When I change Variable1, Variable2, etc in the Inspector the MyUIObject is updated correctly because OnValidate is called but if I change the RectTransform of the panel to which myUIController is attached nothing is happening because OnValidate is not called. Does this explain better what I'm doing?
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,981
    But OnPopulateMesh is supposed to update the representation of your element. Why do you call your ComputePoints manually outside of the whole UI system? As I said when the parent is changed the object is automatically invalidated and updated. OnValidate should not call "ComputePoints" but simply call SetVerticesDirty or one of the other dirty methods depending on what aspects of the graphic you have changed. Once it's marked as dirty it should be updated automatically. So your calculation should be inside OnPopulateMesh
     
  5. Mpx83

    Mpx83

    Joined:
    Apr 4, 2023
    Posts:
    21
    Thanks. the reason why I did this (other than It's my first try with a Graphic element) is because I create several MyUIObjects as child of my panel, and only one of the input variables change between them while the others are the same. So I though that It was easier to set all the inputs in a controller instead of having to copy the input variables for each of the MyUIObjects. Now it doesn't sound like a great idea......