Get Size Of Sprite In UIToolkit Space

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

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.

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

VisualElement e = this.GetComponent<UIDocument>().rootVisualElement.Q("tower");
        float s = Toolkit.GetCanvasScaleFactor(this.GetComponent<UIDocument>().panelSettings);

        float width = tower1.GetComponent<SpriteRenderer>().bounds.size.x;
        float height = tower1.GetComponent<SpriteRenderer>().bounds.size.y;
     
        float worldScreenHeight = Camera.main.orthographicSize * 2.0f;
        float worldScreenWidth = worldScreenHeight / Screen.height * Screen.width;


        e.style.width = worldScreenWidth / width;
        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?

This might help, but needs to be adapted to your use case:

    public Rect transformToPanel(RectTransform t, Camera camera)
    {
        // Transform from camera space into world space
        Vector2 rtSize = (Vector2) t.lossyScale;
        Vector3 rtPos = t.position;
        Vector3 oPos = new(rtPos.x - rtSize.x / 2, rtPos.y + rtSize.y / 2, rtPos.z);
        Rect rIcon = RuntimePanelUtils.CameraTransformWorldToPanelRect(_tooltip.canvas.panel, oPos, rtSize, camera);
 
        // It seems like it's positioned relative to the bottom left of the panel
        Rect rContainer = _mapContainer.worldBound;
        Rect rPanel = _tooltip.canvas.worldBound;
        Vector2 offset = new(rContainer.xMin - rPanel.xMin, rContainer.yMax - rPanel.yMax);
        Rect result = new(rIcon.position + offset, rIcon.size);
        return result;
    }

The magic bit for you should be RuntimePanelUtils.CameraTransformWorldToPanelRect

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.

I figured it out thanks for the help! The RuntimePanelUtils was the trick!

Here is the solution:

    private Vector2 Pixels(SpriteRenderer spriteRenderer)
    {      
        Vector3 min = spriteRenderer.bounds.min;
        Vector3 max = spriteRenderer.bounds.max;
       
        Vector3 screenMin = RuntimePanelUtils.CameraTransformWorldToPanel(this.GetComponent<UIDocument>().rootVisualElement.panel, min, Camera.main);
        Vector3 screenMax = RuntimePanelUtils.CameraTransformWorldToPanel(this.GetComponent<UIDocument>().rootVisualElement.panel, max, Camera.main);
       
        float screenWidth = screenMax.x - screenMin.x;
        float screenHeight = screenMax.y - screenMin.y;

        return new Vector2(Mathf.Abs(screenWidth), Mathf.Abs(screenHeight));
    }