Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Get Size Of Sprite In UIToolkit Space

Discussion in 'UI Toolkit' started by TomTheMan59, Oct 11, 2021.

  1. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    355
    I have been trying to figure this out for a long time, but it seems like either I am missing something or it just isn't possible right now.

    I have a sprite on a sprite renderer that is scaled down. PPU is 100

    Screen Shot 2021-10-11 at 1.41.16 PM.png

    I need to size a UIToolkit image the exact same size as this sprite. I am able to do this with the native resolution of my game, but any other resolution fails.

    Screen Shot 2021-10-11 at 1.42.11 PM.png

    I tried everything I could using the scale factor, but that doesn't work.

    Here is the code to scale it perfectly on the native resolution

    Code (CSharp):
    1.  
    2. VisualElement e = this.GetComponent<UIDocument>().rootVisualElement.Q("tower");
    3.         float s = Toolkit.GetCanvasScaleFactor(this.GetComponent<UIDocument>().panelSettings);
    4.  
    5.         float width = tower1.GetComponent<SpriteRenderer>().bounds.size.x;
    6.         float height = tower1.GetComponent<SpriteRenderer>().bounds.size.y;
    7.      
    8.         float worldScreenHeight = Camera.main.orthographicSize * 2.0f;
    9.         float worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;
    10.  
    11.  
    12.         e.style.width = worldScreenWidth / width;
    13.         e.style.height = worldScreenHeight / height;
    Multiplying any of these numbers by the scale factor will not give the results needed which it should? If it works perfectly on the native resolution, the scale factor is the only "factor" that is missing for the other resolutions?

    What am I missing?
     
  2. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    This might help, but needs to be adapted to your use case:

    Code (CSharp):
    1.  
    2.     public Rect transformToPanel(RectTransform t, Camera camera)
    3.     {
    4.         // Transform from camera space into world space
    5.         Vector2 rtSize = (Vector2) t.lossyScale;
    6.         Vector3 rtPos = t.position;
    7.         Vector3 oPos = new(rtPos.x - rtSize.x / 2, rtPos.y + rtSize.y / 2, rtPos.z);
    8.         Rect rIcon = RuntimePanelUtils.CameraTransformWorldToPanelRect(_tooltip.canvas.panel, oPos, rtSize, camera);
    9.  
    10.         // It seems like it's positioned relative to the bottom left of the panel
    11.         Rect rContainer = _mapContainer.worldBound;
    12.         Rect rPanel = _tooltip.canvas.worldBound;
    13.         Vector2 offset = new(rContainer.xMin - rPanel.xMin, rContainer.yMax - rPanel.yMax);
    14.         Rect result = new(rIcon.position + offset, rIcon.size);
    15.         return result;
    16.     }
    The magic bit for you should be RuntimePanelUtils.CameraTransformWorldToPanelRect
     
    Last edited: Oct 14, 2021
  3. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    355
    Thank you so much for posting! However, I am very confused. It seems like your code converts positions. What I am after is setting a VisualElement to the same width/height of a sprite renderer.
     
  4. TomTheMan59

    TomTheMan59

    Joined:
    Mar 8, 2021
    Posts:
    355
    I figured it out thanks for the help! The RuntimePanelUtils was the trick!

    Here is the solution:

    Code (CSharp):
    1.     private Vector2 Pixels(SpriteRenderer spriteRenderer)
    2.     {      
    3.         Vector3 min = spriteRenderer.bounds.min;
    4.         Vector3 max = spriteRenderer.bounds.max;
    5.        
    6.         Vector3 screenMin = RuntimePanelUtils.CameraTransformWorldToPanel(this.GetComponent<UIDocument>().rootVisualElement.panel, min, Camera.main);
    7.         Vector3 screenMax = RuntimePanelUtils.CameraTransformWorldToPanel(this.GetComponent<UIDocument>().rootVisualElement.panel, max, Camera.main);
    8.        
    9.         float screenWidth = screenMax.x - screenMin.x;
    10.         float screenHeight = screenMax.y - screenMin.y;
    11.  
    12.         return new Vector2(Mathf.Abs(screenWidth), Mathf.Abs(screenHeight));
    13.     }