The Problem at hand:
Simplified
Given an UnityEngine.Ui.Image How does one find the X,Y position of a normalised offset (like 0.4, 0.3 from the top left) inside that image in ScreenSpace units like 400,300
I guess I need to find the top left ScreenSpace value and then knowing the rendered total size of the image scale the normalised offsets by the actual size ratio expressed in pixels.
Figure 2 shows the normalisedOffsets that are to be used
So, in precis, I need to find the offset in ScreenSpace pixels of the topLeft of the Rect I have stored against the image.
I recognise it is probably a combination of Camera.main.ViewportToWorldPoint() and some reference to the bounds, possibly scaling that by backgroundImage.sprite.pixelsPerUnit?
Struggling to visualise how to exactly get this done.
thanks
I guess you don't have any scale or rotation in the image parents and the position Y is 0.
First you can get the position of the upper left corner of your image with rectTransform.GetWorldCorners()
:
//Upper left corner
Vector3[] v = new Vector3[4];
image.rectTransform.GetWorldCorners(v);
var recPos = v[1];
Then you have to transform your normalized offset to a world space offset by a ratio between your image size and your rect size and add the position of the top left corner:
var recWidth = image.rectTransform.sizeDelta.x;
var imgWidth = image.sprite.texture.width;
var realOffsetX = offsetX * (recWidth / imgWidth);
var realPosX = recPos.x + realOffsetX;
(It is the same formula for the Y coordinate but you have to subtract by your ratio realOffsetY
because the offset is calculated from the top left corner)
Here is the full method:
private Vector3 GetPositionOffset(Image image, float offsetX, float offsetY)
{
//Upper left corner
Vector3[] v = new Vector3[4];
image.rectTransform.GetWorldCorners(v);
var recPos = v[1];
//X coordinate
var recWidth = image.rectTransform.sizeDelta.x;
var imgWidth = image.sprite.texture.width;
var realOffsetX = offsetX * (recWidth / imgWidth);
var realPosX = recPos.x + realOffsetX;
//Y coordinate
var recHeight = image.rectTransform.sizeDelta.y;
var imgHeight = image.sprite.texture.height;
var realOffsetY = offsetY * (recWidth / imgWidth);
var realPosY = recPos.y - realOffsetY;
//Position
return new Vector3(realPosX, realPosY, image.transform.position.z);
}
Then if you want this World space to screen space just use the camera method:
camera.WorldToScreenPoint(positionOffset);