Replicating Unity's Rect Tranform tool at runtime.

I’ve been beating my head against the wall for a week now off and on trying to figure this out. I want the same functionality you get with the tool in Unity, but at runtime for a level editor I’m working on.

 private void OnMouseDown() {
        pointerStart = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        sizeStart = myTool.myEditingObject.GetComponent<SpriteRenderer>().bounds.size;
        scaleStart = myTool.myEditingObject.transform.localScale;
        positionStart = myTool.myEditingObject.transform.localPosition;
    }

    private void OnMouseDrag() {
        if (scaleSide == ScaleSide.RIGHT) {
            pointerTravel = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition) - pointerStart;
            scaleX = ((sizeStart.x + pointerTravel.x) / sizeStart.x) * scaleStart.x;
            positionX = positionStart.x + (pointerTravel.x / 2);

            var scale = new Vector2(scaleX, myTool.myEditingObject.localScale.y);
            var pos = new Vector2(positionX, myTool.myEditingObject.localPosition.y);

            myTool.Scale(scale, pos); //Just applies the above math to the object the math is meant for.
        }

This code works perfectly… that is, until you rotate the object. Then it falls apart.

There is a gif of the problem.

Basically, I need to figure out the math to move against the mouse on the Y axis like I do for X to compensate for the new downward motion when the object is rotated. Unfortunately, myself and everyone I’ve talked to in a few gamedev Discord’s can’t seem to get it to work just right.

Any help appreciated, thanks! :slight_smile:

Your pointerTravel vector is a worldspace vector. You should transform that vector into the local space of your object. Though you have to use InverseTransformDirection as that will only apply the inverse rotation without scale or translation.

Just do this:

pointerTravel = (Vector2)Camera.main.ScreenToWorldPoint(Input.mousePosition) - pointerStart;
pointerTravel = myTool.myEditingObject.transform.InverseTransformDirection(pointerTravel);

Now “pointerTravel” is in local space of your object. So even if the object is rotated so it’s x axis points downwards, a movement downwards will still result in a positive “x” value in local space.

edit
ps: Keep in mind that your translation assumes that the pivot is in the center of the object. If you moved the pivot this line would be wrong:

positionX = positionStart.x + (pointerTravel.x / 2);

You should do this instead:

positionX = positionStart.x + (pointerTravel.x * yourRectTransform.pivot.x);

This of course assumes that you actually try to operate on an UI object that has a RectTransform.

Note that this only applies to the “right” side. For the left side you would need to use

positionX = positionStart.x + (pointerTravel.x * (1f - yourRectTransform.pivot.x));

The pivot is defined as a normalized position within your rect. So pivot.x is 0 when the pivot is at the left side. The scale always scale around the pivot. So when dragging the left side we need to apply 100% of the translation. When dragging the right side with the pivot left the translation will be 0%.

Hi!
Did you manage to fix this in the end? If so, how?
Thanks!

Have anyone fixed this issues yet? I ran into the same problem with @Katalyst and had no way to make it right.