Author Topic: Set a widget position via their corners? (independent of pivot and rotattion)  (Read 2387 times)

vexe

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 153
    • View Profile
In my inventory, I add and rotate items. But when I rotate and then add, things go wrong since the pivot hasn't been adjusted.

Adding - (in Item.cs):
  1. public void Notify_HasBeenAdded(Slot toSlot)
  2. {
  3.         // stuff
  4.         cachedTransform.localPosition = toSlot.cachedTransform.localPosition;
  5.         // stuff
  6. }
  7.  

Rotating:
  1. public void RotateItem(RotationDirection rotDir)
  2. {
  3.         // stuff
  4.         var tween = TweenRotation.Begin(parent.gameObject, rotAnimTime, parent.localRotation * Quaternion.Euler(0, 0, (rotDir == RotationDirection.Clockwise) ? -90 : 90));
  5.         // stuff
  6. }
  7.  

When I rotate and then add, here's how it looks - See attachment - It was originally topleft, I rotated 90 dgs clkwise, if you look at it, you wouldn't think the pivot is topleft, it would look like as if it was topright, right? but in fact, it's still topleft but rotated.

Using localCorners wouldn't work here cause it relies on getting the offset from the pivot, which is topleft, but looks like topright.

I solved this problem by writing a piece of code that adjusts the pivot according to the rotation.
But I don't wanna use that - it's just not very reusable. So I thought, why not write a method that sets a REAL corner in a widget to a certain position? Like: widget.SetCornerTo(Corners.TopLeft, pos); - That way I could always set the REAL top left corner, without having to worry about rotation, pivots, etc.

I tried, and came up with a formula that says:
  1. newPos = reqPos + (realPivotOffset X realDimensions)
  2.  

Where:
  1. newPos: is the position where the widget will reside by its real pivot.
  2. reqPos:  is the position required to set a certain corner at.
  3. realPivotOffset: is the dist from the corner we're trying to set and the real pivot.
  4. realDimensions: is the real dimensions of the widget - taking rotation into consideration.
  5.  

I'm having trouble getting it to work since I can't seem to find a way to get the realPivotOffset.

realDimensions is easy to find. Originally, the sprite was 150x100 - when I rotated 90 dgs the real dims are 100x150, rotate again back to 150x100, etc. So:

  1. if (widget.localRotation.x % 180 == 90) {
  2.     reaDim.width = widget.height;
  3.     reaDim.height = widget.width;
  4. } else {
  5.     reaDim.width = widget.width;
  6.     reaDim.height = widget.height;
  7. }
  8.  

But just to illustrate, in my attachment example (2nd picture) - (let's set the topleft corner) it would be:
  1. newPos = reqPos + ((1, 0) X (100, 150)) // the gun is actually 150x100, but since it's rotated, it's now 100x150
  2.                                   // the (1, 0) is the dist from the topleft corner, to the real pivot at the topright
  3. newPos = reqPos + (100, 0)
  4. newPos = reqPos + (width, 0)
  5.  

If it wasn't for rotation, it would be as simple as:
  1. 0- cache the original pivot.
  2. 1- set the current pivot to the required corner.
  3. 2- set the widget's position to the required position.
  4. 3- rollback to the original pivot.
  5.  

I also thought of multiplying the localCorners by a transformation (rotation) matrix - that rotates the corners by the rotation of the item - But no idea how to do that... Not even sure how it would help.

To recap, how can I set a widget's position by its corners regardless of its rotation or original pivot? - Something like widget.SetTopLeft(pos);

Thanks a lot!

PS: Had to write the question twice [very frustrating] since the site logged me out the first time I tried to submit.
« Last Edit: November 25, 2013, 05:12:10 AM by vexe »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Easiest thing to do is to use a UIAnchor on your child sprite (the pistol). Make the pistol sprite use a center pivot, and make the UIAnchor anchor to the center of the parent (the border).

Rotate the pistol sprite. Don't rotate the parent sprite (resize it instead).

To boost performance, make sure the UIAnchor is set to "run only once" and execute it yourself when you set the pistol sprite's rotation.

vexe

  • Full Member
  • ***
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 153
    • View Profile
Thanks for your reply. But I don't think just resizing the parent sprite would work since I don't only rotate the item inside the bag, but also when it's held by the cursor - so I have pick where you click + rotate around where you picked. Please see this 45 secs video: http://www.youtube.com/watch?v=ma9tj_jres4&feature=youtu.be

Can you think of something else? is setting a corner position hard?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Well, the widget corners are always calculated using the widget's position, pivot, and dimensions. I suppose you could use a root object, and actually drag this root object instead of the widget itself...

GameObject
- Actual Widget

This game object would be the top left corner, and the actual widget underneath would be rotated / repositioned as needed.