Gamua / Starling-Framework

The Cross Platform Game Engine
http://www.starling-framework.org
Other
2.85k stars 819 forks source link

Incorrect transformation (via width/height) while rotation #895

Closed Maligan closed 8 years ago

Maligan commented 8 years ago

If set width/height of display object while it rotated - display object become invalid transformed: I use this code for reproduce error:

package
{
    import flash.display.Sprite;

    import starling.core.Starling;

    public class Main extends Sprite
    {
        private var _starling:Starling;

        public function Main()
        {
            _starling = new Starling(MainStarling, stage);
            _starling.start();
        }
    }
}

import flash.utils.setInterval;

import starling.core.Starling;
import starling.display.Quad;
import starling.display.Sprite;
import starling.utils.Color;

class MainStarling extends Sprite
{
    private static const SPINNER_SIZE:int = 32;

    private var _spinner:Quad;

    public function MainStarling():void
    {
        _spinner = new Quad(SPINNER_SIZE, SPINNER_SIZE, Color.RED);
        _spinner.alignPivot();
        _spinner.x = _spinner.y = 100;

        Starling.juggler.tween(_spinner, 1, { repeatCount: 0, rotation: 2*Math.PI });
        addChild(_spinner);

        setInterval(update, 23); // for example 23...
    }

    public function update():void
    {
        _spinner.width = SPINNER_SIZE;
        _spinner.height = SPINNER_SIZE;
    }
}

Expected: ss 2016-08-23 at 02 28 47

Result: (distortion can be very various!) ss 2016-08-23 at 02 29 50

Maligan commented 8 years ago

Well, as I see in code this is not bug, this behaviour has logic, but... but I knocked down by this.

JohnBlackburne commented 8 years ago

Change the two lines to

    _spinner.scaleX = 1;
    _spinner.scaleY = 1;

Does that do what you expected? The difference between setting the width and setting the scale is the former queries the current width before rescaling it to fit. If you don’t want to do that and just want to make it bigger or smaller then setting the scale makes sense.

Maligan commented 8 years ago

Not exactly what I need :-(

At any time I have desired display object size (e.g. 32x32, 17x23 ...etc.) for simple Quads or Images it is possible calculate scale (via texture size) for setup size, but for complex display tree, or for Images with tileGrid or scale9Grid I have no current unrotated size for calculate new scale coefficient.

And there are some problems to store current unrotated size in parallel with starling's display object bounds

Now I make fast decision: (1) reset rotation to zero, (2) set size, (3) restore rotation. Not good but it works

JohnBlackburne commented 8 years ago

It’s unclear to me what you are trying to do, but it sounds like an internal logic problem more than a graphics API one, i.e. a problem that can be solved by deriving the scale from whatever the rotating thing represents, and how it relates to other objects in the scene.

Another idea, a variant on the above. If you only have one constraint, such as width or height, you could try something like

_spinner.width = SPINNER_SIZE; _spinner.scaleY = _spinner.scaleX;

A bit hacky but something else to try.

Maligan commented 8 years ago

Ok, thank you for your time :-) Yesterday I thought that it is my internal logic problem, because starling is doing everything transformation correctly, but...

I try to implement layout system:
It is a close analogue of what I want to do is CSS3 rotateZ transformation: http://www.w3schools.com/cssref/playit.asp?filename=playcss_transform_rotatez It is not change DOM layout, but allow rotation of the objects.

For example:

  1. There is parent sprite has static size: width & height = 100px
  2. Children image have dinamic size: 100% of parent size:
    example
  3. After this I try to rotate child image
  4. And then I change parent sprite size, new coordinates were sended to child, and I obtain this misunderstanding between my code's logic and logic of starling code.

But actually that's not a problem of Starling, but mine, so that the issue can be closed.

PrimaryFeather commented 8 years ago

One more thing: in Starling 2, the Quad class has a new method that was previously only available on Image (and can now do more than before).

Replace your update method with this one:

public function update():void
{
    _spinner.readjustSize(SPINNER_SIZE, SPINNER_SIZE);
}

This method actually sets the size of the quad in its unrotated state (i.e. in its local coordinate system). That should do the trick!