From 6c290f4367cfba61ac6695bbfdaf818d8d943b89 Mon Sep 17 00:00:00 2001 From: Reece Como Date: Thu, 25 Apr 2024 17:29:06 +1000 Subject: [PATCH] v1.1.4 squash nested sequences, fix speedBy(), reformat --- README.md | 16 ++- package-lock.json | 4 +- package.json | 2 +- src/Action.ts | 4 +- src/__tests__/Action.test.ts | 111 +++++++++++++++++- src/actions/chainable/GroupAction.ts | 7 +- src/actions/chainable/RepeatAction.ts | 24 ++-- src/actions/chainable/RepeatForeverAction.ts | 9 +- src/actions/chainable/SequenceAction.ts | 33 ++++-- src/actions/custom/CustomAction.ts | 3 +- src/actions/custom/RunBlockAction.ts | 3 +- src/actions/delay/DelayAction.ts | 1 - .../RunOnChildWithNameAction.ts | 4 +- .../display-object/SetVisibleAction.ts | 2 +- src/actions/follow-path/FollowPathAction.ts | 8 +- src/actions/move/MoveByAction.ts | 7 +- src/actions/move/MoveToAction.ts | 6 +- src/actions/rotate/RotateByAction.ts | 4 +- src/actions/rotate/RotateToAction.ts | 4 +- src/actions/scale/ScaleByAction.ts | 6 +- src/actions/scale/ScaleToAction.ts | 7 +- src/actions/scale/ScaleToSizeAction.ts | 18 +-- src/actions/speed/SpeedByAction.ts | 12 +- src/actions/speed/SpeedToAction.ts | 19 +-- .../{FadeByAction.ts => FadeAlphaByAction.ts} | 5 +- .../{FadeToAction.ts => FadeAlphaToAction.ts} | 7 +- src/actions/transparency/FadeInAction.ts | 21 ++-- src/actions/transparency/FadeOutAction.ts | 22 ++-- src/actions/transparency/index.ts | 4 +- src/lib/Action.ts | 8 +- 30 files changed, 246 insertions(+), 135 deletions(-) rename src/actions/transparency/{FadeByAction.ts => FadeAlphaByAction.ts} (85%) rename src/actions/transparency/{FadeToAction.ts => FadeAlphaToAction.ts} (83%) diff --git a/README.md b/README.md index 44ccfb7..2821c56 100644 --- a/README.md +++ b/README.md @@ -180,9 +180,9 @@ You can customize the speed curve of actions like so: ```ts // Use the defaults -Action.fadeIn(0.3).easeInOut(); Action.fadeIn(0.3).easeIn(); Action.fadeIn(0.3).easeOut(); +Action.fadeIn(0.3).easeInOut(); // Set a TimingMode Action.fadeIn(0.3).setTimingMode(TimingMode.easeInOutCubic); @@ -222,17 +222,15 @@ Actions are stateless and reusable, so you can create complex animations once, a ```ts /** A nice gentle rock back and forth. */ const rockBackAndForth = Action.repeatForever( - Action.sequence([ - Action.group([ + Action.group([ + Action.sequence([ Action.moveByX(5, 0.33).easeOut(), - Action.rotateByDegrees(-2, 0.33).easeOut(), - ]), - Action.group([ Action.moveByX(-10, 0.34).easeInOut(), - Action.rotateByDegrees(4, 0.34).easeInOut(), - ]), - Action.group([ Action.moveByX(5, 0.33).easeIn(), + ]), + Action.sequence([ + Action.rotateByDegrees(-2, 0.33).easeOut(), + Action.rotateByDegrees(4, 0.34).easeInOut(), Action.rotateByDegrees(-2, 0.33).easeIn(), ]), ]) diff --git a/package-lock.json b/package-lock.json index 3499b3e..377046e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pixijs-actions", - "version": "1.1.3", + "version": "1.1.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "pixijs-actions", - "version": "1.1.3", + "version": "1.1.4", "license": "MIT", "devDependencies": { "@types/jest": "^29.2.6", diff --git a/package.json b/package.json index a1d239d..58f96e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pixijs-actions", - "version": "1.1.3", + "version": "1.1.4", "author": "Reece Como ", "authors": [ "Reece Como ", diff --git a/src/Action.ts b/src/Action.ts index 5a58753..38a4c07 100644 --- a/src/Action.ts +++ b/src/Action.ts @@ -6,7 +6,7 @@ import { FadeByAction, FadeInAction, FadeOutAction, - FadeToAction, + FadeAlphaToAction, FollowPathAction, GroupAction, MoveByAction, @@ -479,7 +479,7 @@ export abstract class _ extends Action { * change anything. */ public static fadeAlphaTo(alpha: number, duration: TimeInterval): Action { - return new FadeToAction(alpha, duration); + return new FadeAlphaToAction(alpha, duration); } /** diff --git a/src/__tests__/Action.test.ts b/src/__tests__/Action.test.ts index 797035c..6df32b0 100644 --- a/src/__tests__/Action.test.ts +++ b/src/__tests__/Action.test.ts @@ -78,7 +78,6 @@ describe('Action Chaining', () => { simulateTime(1.0); expect(node.position.x).toBeCloseTo(10.0); - simulateTime(1.0); expect(node.position.x).toBeCloseTo(5.0); @@ -90,6 +89,68 @@ describe('Action Chaining', () => { expect(node.position.x).toBeCloseTo(-5.0); expect(node.hasActions()).toBe(false); }); + + it('successfully completes nested sequences', () => { + // this test secretly makes sure squashing works + const action = Action.sequence([ + Action.sequence([ + Action.sequence([ + Action.moveByX(5, 1.0), + Action.moveByX(-5, 1.0) + ]), + Action.sequence([ + Action.sequence([ + Action.moveByX(5, 1.0), + Action.moveByX(5, 1.0), + ]), + Action.sequence([ // Runs with custom timing mode + Action.rotateBy(Math.PI, 0.5), + Action.rotateBy(Math.PI, 0.5), + ]).easeInOut(), + ]), + Action.group([ // Also has 'actions' but not a SequenceAction + Action.fadeOut(0.5), + Action.scaleTo({ width: 2, height: 2 }, 1.0), + ]), + ]), + Action.sequence([ + Action.sequence([ + Action.moveByY(-5, 1.0), + Action.moveByY(5, 1.0), + ]), + Action.sequence([ + Action.sequence([ + Action.moveByY(5, 1.0), + Action.moveByY(5, 1.0), + ]), + Action.sequence([ // Runs at half speed + Action.fadeAlphaTo(0.25, 1.0), + Action.fadeAlphaBy(0.5, 1.0), + ]).setSpeed(2), + ]), + ]), + ]); + + expect(action.duration).toBeCloseTo(11.0); + expect(action.scaledDuration).toBeCloseTo(11.0); + + const node = new Container(); + node.run(action); + + simulateTime(11.0); + expect(node.position.x).toBeCloseTo(10); + expect(node.position.y).toBeCloseTo(10); + expect(node.rotation).toBeCloseTo(Math.PI * 2); + expect(node.alpha).toBeCloseTo(0.75); + + // Sanity check: We completed. + expect(node.hasActions()).toBe(false); + + // Ignore that this tests the underlying implementation. + // Just a lazy hack to make sure it's working nicely. + expect((action as any).actions.length).toBe(2); + expect((action as any)._squashedActions().length).toBe(11); + }); }); describe('group()', () => { @@ -373,6 +434,54 @@ describe('Action', () => { expect(childNode.hasActions()).toBe(false); }); }); + + describe('speedTo()', () => { + it('changes the nodes action speed', () => { + const myNode = new Container(); + + myNode.run(Action.speedTo(2, 0)); + + simulateTime(0.01, 1); + + expect(myNode.speed).toBeCloseTo(2); + }); + + it('changes the nodes action speed over time', () => { + const myNode = new Container(); + + myNode.run(Action.speedTo(2, 10.0)); + + simulateTime(8.0); + + // Completes early because speed changes + expect(myNode.speed).toBeCloseTo(2); + expect(myNode.hasActions()).toBe(false); + }); + }); + + describe('speedBy()', () => { + it('changes the nodes action speed', () => { + const myNode = new Container(); + + myNode.run(Action.speedBy(1, 0)); + + simulateTime(0.01, 1); + + expect(myNode.speed).toBeCloseTo(2); + }); + + it('changes the nodes action speed over time', () => { + const myNode = new Container(); + + myNode.run(Action.speedBy(1, 10.0)); + + simulateTime(8.0); + + // Completes early because speed changes + expect(myNode.speed).toBeCloseTo(2); + expect(myNode.hasActions()).toBe(false); + }); + }); }); describe('Action and nodes', () => { diff --git a/src/actions/chainable/GroupAction.ts b/src/actions/chainable/GroupAction.ts index 4272509..711dd0f 100644 --- a/src/actions/chainable/GroupAction.ts +++ b/src/actions/chainable/GroupAction.ts @@ -6,12 +6,7 @@ export class GroupAction extends Action { public constructor( protected readonly actions: Action[] ) { - super( - // Max duration: - Math.max(...actions.map(action => action.scaledDuration)) - ); - - this.actions = actions; + super(Math.max(...actions.map(action => action.scaledDuration))); } public reversed(): Action { diff --git a/src/actions/chainable/RepeatAction.ts b/src/actions/chainable/RepeatAction.ts index 04456c5..087c585 100644 --- a/src/actions/chainable/RepeatAction.ts +++ b/src/actions/chainable/RepeatAction.ts @@ -1,20 +1,16 @@ - import { Action } from '../../lib/Action'; import { IActionTicker } from '../../lib/IActionTicker'; import { ActionTicker } from '../../lib/ActionTicker'; export class RepeatAction extends Action { public constructor( - protected readonly action: Action, - protected readonly repeats: number, + protected readonly action: Action, + protected readonly repeats: number, ) { - super( - // Duration: - action.scaledDuration * repeats - ); + super(action.scaledDuration * repeats); - if (Math.round(repeats) !== repeats || repeats < 0) { - throw new Error('Repeats must be a positive integer.'); + if (!Number.isInteger(repeats) || repeats < 0) { + throw new RangeError('The number of repeats must be a positive integer.'); } } @@ -36,8 +32,14 @@ export class RepeatAction extends Action { }; } - protected onTick(target: TargetNode, t: number, dt: number, ticker: IActionTicker, deltaTime: number): void { - let childTicker: IActionTicker = ticker.data.childTicker; + protected onTick( + target: TargetNode, + t: number, + dt: number, + ticker: IActionTicker, + deltaTime: number + ): void { + const childTicker: IActionTicker = ticker.data.childTicker; let remainingTimeDelta = deltaTime * this.speed; remainingTimeDelta = childTicker.tick(remainingTimeDelta); diff --git a/src/actions/chainable/RepeatForeverAction.ts b/src/actions/chainable/RepeatForeverAction.ts index 6d7762c..e09c0d2 100644 --- a/src/actions/chainable/RepeatForeverAction.ts +++ b/src/actions/chainable/RepeatForeverAction.ts @@ -1,16 +1,15 @@ - import { Action } from '../../lib/Action'; import { IActionTicker } from '../../lib/IActionTicker'; import { ActionTicker } from '../../lib/ActionTicker'; export class RepeatForeverAction extends Action { public constructor( - protected readonly action: Action + protected readonly action: Action ) { super(Infinity); - if (action.duration <= 0) { - throw new Error('The action to be repeated must have a non-instantaneous duration.'); + if (action.scaledDuration <= 0) { + throw new TypeError('The action to be repeated must have a non-instantaneous duration.'); } } @@ -21,6 +20,8 @@ export class RepeatForeverAction extends Action { } protected onSetupTicker(target: TargetNode, ticker: IActionTicker): any { + ticker.autoComplete = false; + const childTicker = new ActionTicker(undefined, target, this.action); childTicker.timingMode = (x: number) => ticker.timingMode(childTicker.timingMode(x)); diff --git a/src/actions/chainable/SequenceAction.ts b/src/actions/chainable/SequenceAction.ts index b9272a4..e705fc8 100644 --- a/src/actions/chainable/SequenceAction.ts +++ b/src/actions/chainable/SequenceAction.ts @@ -1,16 +1,13 @@ import { Action } from '../../lib/Action'; import { IActionTicker } from '../../lib/IActionTicker'; import { ActionTicker } from '../../lib/ActionTicker'; +import { TimingMode } from '../../TimingMode'; export class SequenceAction extends Action { public constructor( - protected readonly actions: Action[] + protected actions: Action[] ) { - super( - // Total duration: - actions.reduce((total, action) => total + action.scaledDuration, 0) - ); - this.actions = actions; + super(actions.reduce((total, action) => total + action.scaledDuration, 0)); } public reversed(): Action { @@ -23,7 +20,8 @@ export class SequenceAction extends Action { ticker.autoComplete = false; return { - childTickers: this.actions.map(action => new ActionTicker(undefined, target, action)) + childTickers: this._squashedActions() + .map(action => new ActionTicker(undefined, target, action)) }; } @@ -62,4 +60,25 @@ export class SequenceAction extends Action { protected onTickerDidReset(ticker: IActionTicker): any { ticker.data.childTickers.forEach((ticker: IActionTicker) => ticker.reset()); } + + // ----- Implementation: ----- + + protected _squashedActions(): Action[] { + const actions: Action[] = []; + + for (const action of this.actions) { + if ( + action instanceof SequenceAction + && action.speed === 1 + && action.timingMode === TimingMode.linear + ) { + actions.push(...action._squashedActions()); + } + else { + actions.push(action); + } + } + + return actions; + } } diff --git a/src/actions/custom/CustomAction.ts b/src/actions/custom/CustomAction.ts index e1fc8e5..5a55d45 100644 --- a/src/actions/custom/CustomAction.ts +++ b/src/actions/custom/CustomAction.ts @@ -1,10 +1,9 @@ - import { Action } from '../../lib/Action'; export class CustomAction extends Action { public constructor( duration: TimeInterval, - protected readonly stepFn: (target: TargetNode, t: number, dt: number) => void + protected readonly stepFn: (target: TargetNode, t: number, dt: number) => void ) { super(duration); } diff --git a/src/actions/custom/RunBlockAction.ts b/src/actions/custom/RunBlockAction.ts index ab7c9c8..e1cd0b8 100644 --- a/src/actions/custom/RunBlockAction.ts +++ b/src/actions/custom/RunBlockAction.ts @@ -1,9 +1,8 @@ - import { Action } from '../../lib/Action'; export class RunBlockAction extends Action { public constructor( - protected readonly block: () => void + protected readonly block: () => void ) { super(0); } diff --git a/src/actions/delay/DelayAction.ts b/src/actions/delay/DelayAction.ts index ee29203..6cfab3a 100644 --- a/src/actions/delay/DelayAction.ts +++ b/src/actions/delay/DelayAction.ts @@ -1,4 +1,3 @@ - import { Action } from '../../lib/Action'; export class DelayAction extends Action { diff --git a/src/actions/display-object/RunOnChildWithNameAction.ts b/src/actions/display-object/RunOnChildWithNameAction.ts index 25d6e7e..478a5f1 100644 --- a/src/actions/display-object/RunOnChildWithNameAction.ts +++ b/src/actions/display-object/RunOnChildWithNameAction.ts @@ -2,8 +2,8 @@ import { Action } from '../../lib/Action'; export class RunOnChildWithNameAction extends Action { public constructor( - protected readonly action: Action, - protected readonly name: string, + protected readonly action: Action, + protected readonly name: string, ) { super(0); } diff --git a/src/actions/display-object/SetVisibleAction.ts b/src/actions/display-object/SetVisibleAction.ts index 612dc56..85157b0 100644 --- a/src/actions/display-object/SetVisibleAction.ts +++ b/src/actions/display-object/SetVisibleAction.ts @@ -2,7 +2,7 @@ import { Action } from '../../lib/Action'; export class SetVisibleAction extends Action { public constructor( - protected readonly visible: boolean, + protected readonly visible: boolean, ) { super(0); } diff --git a/src/actions/follow-path/FollowPathAction.ts b/src/actions/follow-path/FollowPathAction.ts index c13f91f..a558257 100644 --- a/src/actions/follow-path/FollowPathAction.ts +++ b/src/actions/follow-path/FollowPathAction.ts @@ -1,4 +1,3 @@ - import { IActionTicker } from 'src/lib/IActionTicker'; import { Action } from '../../lib/Action'; @@ -13,9 +12,9 @@ export class FollowPathAction extends Action { public constructor( path: VectorLike[], duration: number, - protected readonly asOffset: boolean, - protected readonly orientToPath: boolean, - protected readonly fixedSpeed: boolean, + protected readonly asOffset: boolean, + protected readonly orientToPath: boolean, + protected readonly fixedSpeed: boolean, ) { super(duration); this.path = path; @@ -25,6 +24,7 @@ export class FollowPathAction extends Action { if (orientToPath || fixedSpeed) { const [totalDist, segmentLengths] = FollowPathAction.getLength(path); this.segmentLengths = segmentLengths; + if (fixedSpeed) { this.segmentWeights = segmentLengths.map(v => v / (totalDist || 1)); } diff --git a/src/actions/move/MoveByAction.ts b/src/actions/move/MoveByAction.ts index e3228f3..cf48522 100644 --- a/src/actions/move/MoveByAction.ts +++ b/src/actions/move/MoveByAction.ts @@ -1,11 +1,10 @@ - import { Action } from '../../lib/Action'; export class MoveByAction extends Action { public constructor( - protected readonly x: number, - protected readonly y: number, - duration: number, + protected readonly x: number, + protected readonly y: number, + duration: number, ) { super(duration); } diff --git a/src/actions/move/MoveToAction.ts b/src/actions/move/MoveToAction.ts index 78a8c7a..85c1e00 100644 --- a/src/actions/move/MoveToAction.ts +++ b/src/actions/move/MoveToAction.ts @@ -4,9 +4,9 @@ import { DelayAction } from '../delay'; export class MoveToAction extends Action { public constructor( - protected readonly x: number | undefined, - protected readonly y: number | undefined, - duration: TimeInterval, + protected readonly x: number | undefined, + protected readonly y: number | undefined, + duration: TimeInterval, ) { super(duration); } diff --git a/src/actions/rotate/RotateByAction.ts b/src/actions/rotate/RotateByAction.ts index 55ddb91..5c6bb69 100644 --- a/src/actions/rotate/RotateByAction.ts +++ b/src/actions/rotate/RotateByAction.ts @@ -2,8 +2,8 @@ import { Action } from '../../lib/Action'; export class RotateByAction extends Action { public constructor( - protected readonly rotation: number, - duration: TimeInterval, + protected readonly rotation: number, + duration: TimeInterval, ) { super(duration); } diff --git a/src/actions/rotate/RotateToAction.ts b/src/actions/rotate/RotateToAction.ts index cdfa044..a2cd27d 100644 --- a/src/actions/rotate/RotateToAction.ts +++ b/src/actions/rotate/RotateToAction.ts @@ -4,8 +4,8 @@ import { DelayAction } from '../delay'; export class RotateToAction extends Action { public constructor( - protected readonly rotation: number, - duration: TimeInterval, + protected readonly rotation: number, + duration: TimeInterval, ) { super(duration); } diff --git a/src/actions/scale/ScaleByAction.ts b/src/actions/scale/ScaleByAction.ts index 533d219..5868950 100644 --- a/src/actions/scale/ScaleByAction.ts +++ b/src/actions/scale/ScaleByAction.ts @@ -3,9 +3,9 @@ import { IActionTicker } from '../../lib/IActionTicker'; export class ScaleByAction extends Action { public constructor( - protected readonly x: number, - protected readonly y: number, - duration: TimeInterval, + protected readonly x: number, + protected readonly y: number, + duration: TimeInterval, ) { super(duration); } diff --git a/src/actions/scale/ScaleToAction.ts b/src/actions/scale/ScaleToAction.ts index ff8fa10..ab9e2f7 100644 --- a/src/actions/scale/ScaleToAction.ts +++ b/src/actions/scale/ScaleToAction.ts @@ -1,13 +1,12 @@ - import { Action } from '../../lib/Action'; import { IActionTicker } from '../../lib/IActionTicker'; import { DelayAction } from '../delay'; export class ScaleToAction extends Action { public constructor( - protected readonly x: number | undefined, - protected readonly y: number | undefined, - duration: TimeInterval, + protected readonly x: number | undefined, + protected readonly y: number | undefined, + duration: TimeInterval, ) { super(duration); } diff --git a/src/actions/scale/ScaleToSizeAction.ts b/src/actions/scale/ScaleToSizeAction.ts index a65e289..1e5dbb6 100644 --- a/src/actions/scale/ScaleToSizeAction.ts +++ b/src/actions/scale/ScaleToSizeAction.ts @@ -4,9 +4,9 @@ import { DelayAction } from '../delay'; export class ScaleToSizeAction extends Action { public constructor( - protected readonly width: number, - protected readonly height: number, - duration: TimeInterval, + protected readonly width: number, + protected readonly height: number, + duration: TimeInterval, ) { super(duration); } @@ -16,18 +16,18 @@ export class ScaleToSizeAction extends Action { } protected onSetupTicker(target: SizedTargetNode): any { - if (target.width === undefined) { - throw new Error('Action can only be run against a target with a width & height.'); + if (typeof target.width !== 'number' || typeof target.height !== 'number') { + throw new TypeError("The target must have numeric 'width' and 'height'."); } return { - sW: target.width, - sH: target.height, + width: target.width, + height: target.height, }; } protected onTick(target: SizedTargetNode, t: number, dt: number, ticker: IActionTicker): void { - target.width = ticker.data.sW + (this.width - ticker.data.sW) * t; - target.height = ticker.data.sH + (this.height - ticker.data.sH) * t; + target.width = ticker.data.width + (this.width - ticker.data.width) * t; + target.height = ticker.data.height + (this.height - ticker.data.height) * t; } } diff --git a/src/actions/speed/SpeedByAction.ts b/src/actions/speed/SpeedByAction.ts index 596381d..267f1cb 100644 --- a/src/actions/speed/SpeedByAction.ts +++ b/src/actions/speed/SpeedByAction.ts @@ -2,19 +2,19 @@ import { Action } from '../../lib/Action'; export class SpeedByAction extends Action { public constructor( - protected readonly _speed: number, - duration: TimeInterval, + protected readonly _speed: number, + duration: TimeInterval, ) { super(duration); } - protected onTick(target: TargetNode, t: number, dt: number): void { - target.rotation += this._speed * dt; - } - public reversed(): Action { return new SpeedByAction(-this._speed, this.duration) .setTimingMode(this.timingMode) .setSpeed(this.speed); } + + protected onTick(target: TargetNode, t: number, dt: number): void { + target.speed += this._speed * dt; + } } diff --git a/src/actions/speed/SpeedToAction.ts b/src/actions/speed/SpeedToAction.ts index 5142558..9aba64d 100644 --- a/src/actions/speed/SpeedToAction.ts +++ b/src/actions/speed/SpeedToAction.ts @@ -1,12 +1,11 @@ - import { Action } from '../../lib/Action'; import { IActionTicker } from '../../lib/IActionTicker'; import { DelayAction } from '../delay'; export class SpeedToAction extends Action { public constructor( - protected readonly _speed: number, - duration: TimeInterval, + protected readonly _speed: number, + duration: TimeInterval, ) { super(duration); } @@ -15,13 +14,19 @@ export class SpeedToAction extends Action { return new DelayAction(this.scaledDuration); } - protected onSetupTicker(target: TargetNode): any { + protected onSetupTicker(target: TargetNode, ticker: IActionTicker): any { return { - startSpeed: target.speed + startSpeed: target.speed, }; } - protected onTick(target: TargetNode, t: number, dt: number, ticker: IActionTicker): void { - target.rotation = ticker.data.startRotation + (this._speed - ticker.data.startSpeed) * t; + protected onTick( + target: TargetNode, + t: number, + dt: number, + ticker: IActionTicker, + deltaTime: number, + ): void { + target.speed = ticker.data.startSpeed + (this._speed - ticker.data.startSpeed) * t; } } diff --git a/src/actions/transparency/FadeByAction.ts b/src/actions/transparency/FadeAlphaByAction.ts similarity index 85% rename from src/actions/transparency/FadeByAction.ts rename to src/actions/transparency/FadeAlphaByAction.ts index 4250d00..51cfcea 100644 --- a/src/actions/transparency/FadeByAction.ts +++ b/src/actions/transparency/FadeAlphaByAction.ts @@ -1,10 +1,9 @@ - import { Action } from '../../lib/Action'; export class FadeByAction extends Action { public constructor( - protected readonly alpha: number, - duration: TimeInterval, + protected readonly alpha: number, + duration: TimeInterval, ) { super(duration); } diff --git a/src/actions/transparency/FadeToAction.ts b/src/actions/transparency/FadeAlphaToAction.ts similarity index 83% rename from src/actions/transparency/FadeToAction.ts rename to src/actions/transparency/FadeAlphaToAction.ts index 11936b2..f7f803d 100644 --- a/src/actions/transparency/FadeToAction.ts +++ b/src/actions/transparency/FadeAlphaToAction.ts @@ -1,12 +1,11 @@ - import { Action } from '../../lib/Action'; import { IActionTicker } from '../../lib/IActionTicker'; import { DelayAction } from '../delay'; -export class FadeToAction extends Action { +export class FadeAlphaToAction extends Action { public constructor( - protected readonly alpha: number, - duration: TimeInterval + protected readonly alpha: number, + duration: TimeInterval ) { super(duration); } diff --git a/src/actions/transparency/FadeInAction.ts b/src/actions/transparency/FadeInAction.ts index 6b53083..0c920c4 100644 --- a/src/actions/transparency/FadeInAction.ts +++ b/src/actions/transparency/FadeInAction.ts @@ -1,21 +1,14 @@ import { Action } from '../../lib/Action'; -import { IActionTicker } from '../../lib/IActionTicker'; -import { FadeOutAction } from './FadeOutAction'; +import { FadeAlphaToAction } from './FadeAlphaToAction'; + +export class FadeInAction extends FadeAlphaToAction { + public constructor(duration: number) { + super(1, duration); + } -export class FadeInAction extends Action { public reversed(): Action { - return new FadeOutAction(this.duration) + return new FadeAlphaToAction(0, this.duration) .setTimingMode(this.timingMode) .setSpeed(this.speed); } - - protected onSetupTicker(target: TargetNode): any { - return { - startAlpha: target.alpha - }; - } - - protected onTick(target: TargetNode, t: number, dt: number, ticker: IActionTicker): void { - target.alpha = ticker.data.startAlpha + (1.0 - ticker.data.startAlpha) * t; - } } diff --git a/src/actions/transparency/FadeOutAction.ts b/src/actions/transparency/FadeOutAction.ts index 0667987..7e753fe 100644 --- a/src/actions/transparency/FadeOutAction.ts +++ b/src/actions/transparency/FadeOutAction.ts @@ -1,22 +1,14 @@ - import { Action } from '../../lib/Action'; -import { IActionTicker } from '../../lib/IActionTicker'; -import { FadeInAction } from './FadeInAction'; +import { FadeAlphaToAction } from './FadeAlphaToAction'; + +export class FadeOutAction extends FadeAlphaToAction { + public constructor(duration: number) { + super(0, duration); + } -export class FadeOutAction extends Action { public reversed(): Action { - return new FadeInAction(this.duration) + return new FadeAlphaToAction(1, this.duration) .setTimingMode(this.timingMode) .setSpeed(this.speed); } - - protected onSetupTicker(target: TargetNode): any { - return { - startAlpha: target.alpha - }; - } - - protected onTick(target: TargetNode, t: number, dt: number, ticker: IActionTicker): void { - target.alpha = ticker.data.startAlpha + (0.0 - ticker.data.startAlpha) * t; - } } diff --git a/src/actions/transparency/index.ts b/src/actions/transparency/index.ts index 18b2a48..05dfb90 100644 --- a/src/actions/transparency/index.ts +++ b/src/actions/transparency/index.ts @@ -1,4 +1,4 @@ -export * from './FadeByAction'; +export * from './FadeAlphaByAction'; export * from './FadeInAction'; export * from './FadeOutAction'; -export * from './FadeToAction'; +export * from './FadeAlphaToAction'; diff --git a/src/lib/Action.ts b/src/lib/Action.ts index d196b8c..00bc34b 100644 --- a/src/lib/Action.ts +++ b/src/lib/Action.ts @@ -17,12 +17,16 @@ export abstract class Action { /** The duration required to complete an action. */ public readonly duration: TimeInterval, /** A speed factor that modifies how fast an action runs. */ - public speed: number = 1.0, + public speed: number = 1, /** A setting that controls the speed curve of an animation. */ public timingMode: TimingModeFn = TimingMode.linear, /** @deprecated A global category bitmask which can be used to group actions. */ public categoryMask: number = 0x1, - ) {} + ) { + if (duration < 0) { + throw new RangeError('Action duration must be 0 or more.'); + } + } /** Duration of the action after its local speed scalar is applied. */ public get scaledDuration(): number {