import { Container } from 'inversify'; import { AbleManager, Entity, EntityManager, PlaygroundContext, TransformData } from '../'; import * as chai from 'chai'; const expect = chai.expect; function createContainer(): Container { const child = new Container({defaultScope: 'Singleton'}); child.bind(AbleManager).toSelf(); child.bind(PlaygroundContext).toConstantValue({}); child.bind(EntityManager).toSelf(); return child; } const container = createContainer(); function createTransform(): TransformData { const entity = container.get(EntityManager).createEntity(Entity); return new TransformData(entity); } describe('Playground.schema.transform', () => { it('should decompose negative scale into rotation', () => { const eps = 1e-3; const transform = createTransform(); const parent = createTransform(); const otherTransform = createTransform(); transform.position.x = 20; transform.position.y = 10; transform.scale.x = -2; transform.scale.y = -3; transform.rotation = Math.PI / 6; transform.setParent(parent); otherTransform.setFromMatrix(transform.worldTransform); const position = otherTransform.position; const scale = otherTransform.scale; const skew = otherTransform.skew; expect(position.x).to.be.closeTo(20, eps); expect(position.y).to.be.closeTo(10, eps); expect(scale.x).to.be.closeTo(2, eps); expect(scale.y).to.be.closeTo(3, eps); expect(skew.x).to.equal(0); expect(skew.y).to.equal(0); expect(otherTransform.rotation).to.be.closeTo(-5 * Math.PI / 6, eps); }); it('should decompose mirror into skew', () => { const eps = 1e-3; const transform = createTransform(); const parent = createTransform(); const otherTransform = createTransform(); transform.position.x = 20; transform.position.y = 10; transform.scale.x = 2; transform.scale.y = -3; transform.rotation = Math.PI / 6; transform.setParent(parent); otherTransform.setFromMatrix(transform.worldTransform); const position = otherTransform.position; const scale = otherTransform.scale; const skew = otherTransform.skew; expect(position.x).to.be.closeTo(20, eps); expect(position.y).to.be.closeTo(10, eps); expect(scale.x).to.be.closeTo(2, eps); expect(scale.y).to.be.closeTo(3, eps); expect(skew.x).to.be.closeTo(5 * Math.PI / 6, eps); expect(skew.y).to.be.closeTo(Math.PI / 6, eps); expect(otherTransform.rotation).to.equal(0); }); it('should apply skew before scale, like in adobe animate and spine', () => { // this example looks the same in CSS and in PIXI, made with PIXI-animate by @bigtimebuddy const eps = 1e-3; const transform = createTransform(); const parent = createTransform(); const otherTransform = createTransform(); transform.position.x = 387.8; transform.position.y = 313.95; transform.scale.x = 0.572; transform.scale.y = 4.101; transform.skew.x = -0.873; transform.skew.y = 0.175; transform.setParent(parent); const mat = transform.worldTransform; expect(mat.a).to.be.closeTo(0.563, eps); expect(mat.b).to.be.closeTo(0.100, eps); expect(mat.c).to.be.closeTo(-3.142, eps); expect(mat.d).to.be.closeTo(2.635, eps); expect(mat.tx).to.be.closeTo(387.8, eps); expect(mat.ty).to.be.closeTo(313.95, eps); otherTransform.setFromMatrix(transform.worldTransform); const position = otherTransform.position; const scale = otherTransform.scale; const skew = otherTransform.skew; expect(position.x).to.be.closeTo(387.8, eps); expect(position.y).to.be.closeTo(313.95, eps); expect(scale.x).to.be.closeTo(0.572, eps); expect(scale.y).to.be.closeTo(4.101, eps); expect(skew.x).to.be.closeTo(-0.873, eps); expect(skew.y).to.be.closeTo(0.175, eps); expect(otherTransform.rotation).to.be.equal(0); }); });