Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[next] Use degree units for rotation/skew in v5, opt-in for radians #4579

Closed
wants to merge 2 commits into from

Conversation

ivanpopelyshev
Copy link
Collaborator

@ivanpopelyshev ivanpopelyshev commented Jan 4, 2018

Overview

This introduces a 💥 breaking change to default the units in v5 for rotation/skew/etc to degrees instead of radians. Using radians is still available as an opt-in for those who wish to use that unit or for backward compatibility (see Usage below).

Reference #4133

Pros

  • Other Flash-like engines use degrees by default, like libgdx, cocos2d.
  • Better integration with tools like Spine and GSAP
  • No more Math.PI/2 and no guesses in debugger: if rotation is 1.72, how much is that?

Cons

  • Breaking change, although many changes in v5 are breaking.
  • There's extra * DEG_TO_RAD in a few places, please look at changed files.

Usage

For setting the global units to radians add the following line. This is needed if your project internally used radians and you require backward compatibility of functionality. Note: this must be set before any Transforms are created.

PIXI.settings.USE_RADIANS = true;

To override the global setting on a per-Transform basis, you can do this:

const obj = new PIXI.DisplayObject();
obj.transform.useRadians = true;

@ivanpopelyshev ivanpopelyshev changed the base branch from dev to next January 4, 2018 17:50
@bigtimebuddy
Copy link
Member

I'm not convinced this is the best API solution. What if some plugins use radians and some use degrees? You don't want them fighting over this setting.

What do you think about this #4133 (comment) by having angle (degrees) and rotation (radians). it doesn't solve all issues where radians are used, like skew, but I think it's better than this approach.

@ivanpopelyshev
Copy link
Collaborator Author

ivanpopelyshev commented Jan 4, 2018

@bigtimebuddy All plugins will have to make changes for v5 compatibility anyway, there are critical changes. Most of plugins are mine, and you can change stuff in pixi-animate. Also please notice that it works per-transform.

@ivanpopelyshev
Copy link
Collaborator Author

ivanpopelyshev commented Jan 4, 2018

Most of tools also use degrees and not rads. For spine I'll make entirely new runtime and deprecate v3/v4 support in it, there'll be spine for v3-v4 and for v5.

We can remove rads setting in v6

@ivanpopelyshev
Copy link
Collaborator Author

WIP: Graphics.

@bigtimebuddy
Copy link
Member

bigtimebuddy commented Jan 4, 2018

Make setting the degrees or radians a boolean, not setting a numerical value, that can happen behind the scenes. Transform.prototype.useRadians PIXI.settings.USE_RADIANS, or useDegrees/USE_DEGREES

@@ -361,6 +361,7 @@ export default class Matrix
const skewX = -Math.atan2(-c, d);
const skewY = Math.atan2(b, a);

const rad2deg = transform.useRadians ? 1.0 : (180.0 / Math.PI);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider import { RAD_TO_DEG } from './const' and using RAD_TO_DEG here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That'll be extra import line, I think my version is more verbose.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With rollup it’s all flattened anyways so the extra import doesn’t matter. In fact, it’s better to import because this uses a single instance variable and compresses smaller. Verbosity is not useful here and constants should be declared, imo.

this._sx = Math.sin(this._rotation + this.skew._y);
this._cy = -Math.sin(this._rotation - this.skew._x); // cos, added PI/2
this._sy = Math.cos(this._rotation - this.skew._x); // sin, added PI/2
const deg2rad = this.useRadians ? 1.0 : (Math.PI / 180.0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here as above: import { RAD_TO_DEG } from './const'

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^^^

@@ -1,5 +1,5 @@
import { Container, Bounds } from '@pixi/display';
import { BLEND_MODES } from '@pixi/constants';
import { BLEND_MODES, DEG_TO_RAD } from '@pixi/constants';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEG_TO_RAD is in @pixi/math

*
* @static
* @constant
* @memberof PIXI
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be @memberof PIXI.settings

@bigtimebuddy bigtimebuddy changed the title Next degrees [next] Use degree units for rotation/skew in v5, opt-in for radians Jan 4, 2018
Copy link
Member

@bigtimebuddy bigtimebuddy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chatted with @GoodBoyDigital about this and I feel strongly that we need to solicit feedback from the community for breaking changes or we keep the default as radians. It's a dramatic change. While I agree with Chad's original rationale, I don't want to rush this change through without some buy-in.

@fritzy
Copy link

fritzy commented Jan 5, 2018

At first I wondered why, but after reading the issue, better compatibility and being more in line with other tools makes it worth it, IMO.

@tobireif
Copy link
Contributor

tobireif commented Jan 8, 2018

I'm against this because it's a breaking change. Perhaps it could be offered as option? (but the default would be the current state so that nothing gets broken)

On the other hand, people who switch to that new version of PixiJS could get a notification in the console and adjust their code.

@ivanpopelyshev
Copy link
Collaborator Author

@bigtimebuddy need your feedback, whether we make use_radians a property of Transform, and add rad2deg and deg2rad inside.

@brenwell
Copy link
Contributor

brenwell commented Jan 9, 2018

I’m with @tobireif. Add util functions and work on the something more fun instead

@themoonrat
Copy link
Member

I thumbed up, but ultimately for me, internally, I don't really mind. Most of my annoyance is with DisplayObjects having rotation as radians, and it's not friendly using numeric data via json to set a display objects rotation. I'd be happy alone with @bigtimebuddy's comment of an additional getter / setter of 'angle' in degrees to compliment the 'rotation' in radians. 2 ways of accessing/changing the same information, just like setting width/height and setting scale do. Both useful in different contexts.

@markknol
Copy link
Contributor

markknol commented Jan 11, 2018

I vote for keeping radians, I liked that tbh. Degrees are only nice for readability, not for math, There aren't much places you actually need degrees (?). Radians is used in trig functions (sin/cos/etc), so that would be awkward to work with when everything is in degrees. I think for support libraries like spline etc is easier to put a * DEG_TO_RAD once in the code instead of forcing pixi users to use * RAD_TO_DEG in their code.

As alternative you could also add some convenience rotationInDegrees getter/setter function which works with degrees and alters rotation property, but I can understand this might make the api look less nice.

@cursedcoder
Copy link
Member

cursedcoder commented Jan 22, 2018

It is a breaking change – want to remind it is 5.0.0 which states for BREAK in https://semver.org/

Other tools are dependent on us – anyway they will have to migrate with a bunch of breaking changes, this one should not take more than 5 LoC's

Have different setters for everyone – big thumbs up

P.S. In my experience we always converted rads to degrees working with PIXI.

@ivanpopelyshev ivanpopelyshev added this to the v5.0.0-alpha.2 milestone Mar 5, 2018
rads by default, @GoodBoyDigital wants it

derp

useDegrees

better docs

docs fix
@ivanpopelyshev
Copy link
Collaborator Author

Radians are now by default, like in v4. I put link to USE_DEGREES in relevant places in docs.

@ivanpopelyshev ivanpopelyshev removed this from the v5.0.0-alpha.2 milestone Mar 5, 2018
@jonlepage
Copy link
Contributor

jonlepage commented Apr 2, 2018

now this extend will helping

(function (R) {
  Math.cosd = function(d) { return Math.cos(d * R); };
  Math.sind = function(d) { return Math.sin(d * R); };
  Math.tand = function(d) { return Math.tan(d * R); };
})(Math.PI / 180);

Able to get the cosine at 45° by doing Math.cosd(45)
or the sine at 75° by doing Math.sind(75)
or the tangent at 135° by doing Math.tand(135) ....
So I vote yes for my side, I have no other application that works with the radians for rotation.
all my calculations need alway to convert with actual pixi rotation.

@bigtimebuddy
Copy link
Member

bigtimebuddy commented Apr 4, 2018

@ivanpopelyshev I think you dismissed my point about plugins. I'd like to just put a finer point on it. Here's an example:

Here's how we'd implement a simple plugin now that handles rotation:

PIXI.DisplayObject.prototype.flip = function flip() {
  this.rotation += Math.PI;
};

If I wanted to implement this same 3rd party plugin using this PR, I'd probably have to do this:

PIXI.DisplayObject.prototype.flip = function flip() {
  this.rotation += Math.PI * this.transform.rad2deg;
};

So a couple of points about this:

  • The name rad2deg is pretty deceiving here because we are actually normalizing the units not converting them. More appropriate names might be normalizeRadians and normalizeDegrees instead of rad2deg and deg2rad
  • To me this approach is confusing for 3rd-party plugins which utilize rotation and skew. All units need be normalized so it's a big gotcha.
  • Finally, and this is probably very obvious, but this makes the rotation return dynamic. It can return different values in different contexts. This approach feels like an anti-pattern in Pixi, I don't know of other APIs who's return value units changes because of an external switch. I feel like this is an inconsistent API design.

@ivanpopelyshev
Copy link
Collaborator Author

ivanpopelyshev commented Apr 4, 2018

The PR wont be accepted if it will have too many lines of code.

My concern is to enable storage in degrees, and ability to assign degrees to rotation.

I see two ways:

  1. rotation is dynamic field, storage is dynamic field
  2. storage is always degrees, add rotationDeg field

@bigtimebuddy
Copy link
Member

If we were implementing, for example, a tween library and we wanted to support a developer using either seconds or milliseconds, we'd probably make a time property and a timeMs property not create a global static switch.

IMO the easiest solution here it to create an alternative to rotation: e.g., rotationDeg or angle (my preference is for the shorter angle). This would support your storage of rotation in degrees and is much simpler. We should also create a skewDeg or skewAngle ObservablePoint that would update skew point values as well.

@ivanpopelyshev
Copy link
Collaborator Author

Two storage fields is a bad idea, both for core and plugins. Please confirm that you agree to store rotation in degrees.

@bigtimebuddy
Copy link
Member

It’s not creating two storage fields, it’s one storage and one convenience method on DisplayObject. We should continue to store radians in Transform.

@ivanpopelyshev
Copy link
Collaborator Author

ivanpopelyshev commented Apr 4, 2018

We should continue to store radians in Transform.

element.rotationDeg = 30;
console.log(element.rotationDeg === 30);
var deg2rad = Math.PI / 180.0;
var rad2deg = 180.0 / Math.PI;
console.log(30 * deg2rad * rad2deg);

@ivanpopelyshev
Copy link
Collaborator Author

That's why I want to store degrees. Extra multiplication before using trigonometric functions is not a problem, especially when its always there.

@bigtimebuddy
Copy link
Member

It has taken a long time to address this PR, thanks for your patience. Had a chat about this with @GoodBoyDigital and we have decided to close this for a couple of reasons:

  • It creates potential for downstream issues for authors of third-party plugins by creating a requirement that every angle calculation is multiplied by the transform property. We feel like this is overly burdensome.
  • The main problem that this PR is trying to solve for users is providing convenience working with the rotation values. Having a global and per-object switch is too complicated an API solution for the problem we wish to solve. It makes a lot more sense to create a separate API for handling degrees and radians (e.g. angle vs rotation). This is a simpler, more future-forward and less-breaking with v4.
  • One of the goals of this PR is to be able to store degrees internally. This is not a goal that we share with the future of PixiJS.

If anyone is interested, we would welcome another PR which introduces separate DisplayObject angle setter as an alternative API for setting rotation in degrees.

@lock
Copy link

lock bot commented Sep 23, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked and limited conversation to collaborators Sep 23, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants