diff --git a/.eslintrc b/.eslintrc index 5dce277..f3bb6d0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -25,7 +25,10 @@ "warn", "stroustrup" ], - "curly": "warn", + "curly": [ + "warn", + "multi-line" + ], "semi": [ "warn", "always" diff --git a/package.json b/package.json index 3d97b5a..acb3a16 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pixijs-actions", - "version": "1.2.0", + "version": "1.2.1", "author": "Reece Como ", "authors": [ "Reece Como ", diff --git a/src/__tests__/Action.test.ts b/src/__tests__/Action.test.ts index bc04b79..a187489 100644 --- a/src/__tests__/Action.test.ts +++ b/src/__tests__/Action.test.ts @@ -225,6 +225,30 @@ describe('Action Chaining', () => { expect((action as any).actions.length).toBe(2); expect((action as any)._squashedActions().length).toBe(11); }); + + it('completes regression case', () => { + const otherNodeA = new Container(); + const otherNodeB = new Container(); + + let myRunCompleted = false; + + const action = Action.sequence([ + Action.group([ + Action.waitForDuration(0.25), + Action.run(() => otherNodeA.run(Action.moveByX(2, 1.0))), + Action.run(() => otherNodeB.run(Action.moveByX(2, 1.0))), + ]), + Action.run(() => myRunCompleted = true), + ]); + + const myNode = new Container(); + myNode.run(action); + + simulateTime(0.28); + + expect(myNode.hasActions()).toBe(false); + expect(myRunCompleted).toBe(true); + }); }); describe('group()', () => { @@ -269,6 +293,28 @@ describe('Action Chaining', () => { myNode.removeAllActions(); }); + + it('should work with waitForDuration()', () => { + const otherNodeA = new Container(); + const otherNodeB = new Container(); + + const action = Action.group([ + Action.waitForDuration(0.25), + Action.run(() => otherNodeA.run(Action.moveByX(2, 1.0))), + Action.run(() => otherNodeB.run(Action.moveByX(2, 1.0))), + ]); + + expect(action.duration).toBeCloseTo(0.25); + expect(action.scaledDuration).toBeCloseTo(0.25); + + const myNode = new Container(); + myNode.runWithKey(action, 'myTriggerAction'); + + simulateTime(0.3); + + expect(myNode.action('myTriggerAction')).toBeUndefined(); + expect(myNode.hasActions()).toBe(false); + }); }); describe('repeat()', () => { diff --git a/src/actions/chainable/GroupAction.ts b/src/actions/chainable/GroupAction.ts index e0ac0fa..108693c 100644 --- a/src/actions/chainable/GroupAction.ts +++ b/src/actions/chainable/GroupAction.ts @@ -30,21 +30,19 @@ export class GroupAction extends Action { ticker: IActionTicker, deltaTime: number, ): void { - let allDone = true; - const relativeTimeDelta = ticker.scaledDuration === Infinity + const relativeDeltaTime = ticker.scaledDuration === Infinity ? deltaTime * this.speed : dt * ticker.scaledDuration; + let allDone = true; for (const childTicker of ticker.data.childTickers as IActionTicker[]) { - if (!childTicker.isDone) { - allDone = false; - childTicker.tick(relativeTimeDelta); - } - } + if (childTicker.isDone) continue; - if (allDone) { - ticker.isDone = true; + allDone = false; + childTicker.tick(relativeDeltaTime); } + + if (allDone) ticker.isDone = true; } protected onTickerDidReset(ticker: IActionTicker): any { diff --git a/src/actions/chainable/RepeatAction.ts b/src/actions/chainable/RepeatAction.ts index 087c585..8031e19 100644 --- a/src/actions/chainable/RepeatAction.ts +++ b/src/actions/chainable/RepeatAction.ts @@ -40,18 +40,18 @@ export class RepeatAction extends Action { deltaTime: number ): void { const childTicker: IActionTicker = ticker.data.childTicker; - let remainingTimeDelta = deltaTime * this.speed; + let remainingDeltaTime = deltaTime * this.speed; - remainingTimeDelta = childTicker.tick(remainingTimeDelta); + remainingDeltaTime = childTicker.tick(remainingDeltaTime); - if (remainingTimeDelta > 0 || childTicker.scaledDuration === 0) { + if (remainingDeltaTime > 0 || childTicker.scaledDuration === 0) { if (++ticker.data.n >= this.repeats) { ticker.isDone = true; return; } childTicker.reset(); - remainingTimeDelta = childTicker.tick(remainingTimeDelta); + remainingDeltaTime = childTicker.tick(remainingDeltaTime); } } diff --git a/src/actions/chainable/RepeatForeverAction.ts b/src/actions/chainable/RepeatForeverAction.ts index e09c0d2..9bef2a1 100644 --- a/src/actions/chainable/RepeatForeverAction.ts +++ b/src/actions/chainable/RepeatForeverAction.ts @@ -38,13 +38,13 @@ export class RepeatForeverAction extends Action { deltaTime: number ): void { const childTicker: IActionTicker = ticker.data.childTicker; - let remainingTimeDelta = deltaTime * ticker.speed; + let remainingDeltaTime = deltaTime * ticker.speed; - remainingTimeDelta = childTicker.tick(remainingTimeDelta); + remainingDeltaTime = childTicker.tick(remainingDeltaTime); - if (remainingTimeDelta > 0) { + if (remainingDeltaTime > 0) { childTicker.reset(); - remainingTimeDelta = childTicker.tick(remainingTimeDelta); + remainingDeltaTime = childTicker.tick(remainingDeltaTime); } } diff --git a/src/actions/chainable/SequenceAction.ts b/src/actions/chainable/SequenceAction.ts index 78afd86..1ee82dc 100644 --- a/src/actions/chainable/SequenceAction.ts +++ b/src/actions/chainable/SequenceAction.ts @@ -32,32 +32,21 @@ export class SequenceAction extends Action { ticker: IActionTicker, deltaTime: number, ): void { - let allDone = true; - let remainingTimeDelta = ticker.scaledDuration === Infinity + let remainingDeltaTime = ticker.scaledDuration === Infinity ? deltaTime * this.speed : dt * ticker.scaledDuration; for (const childTicker of ticker.data.childTickers as IActionTicker[]) { - if (!childTicker.isDone) { + if (childTicker.isDone) continue; - if (remainingTimeDelta > 0 || childTicker.scaledDuration === 0) { - remainingTimeDelta = childTicker.tick(remainingTimeDelta); - } - else { - allDone = false; - break; - } + remainingDeltaTime = childTicker.tick(remainingDeltaTime); - if (remainingTimeDelta < 0) { - allDone = false; - break; - } + if (remainingDeltaTime < 0) { + return; // Cannot continue to next: Current action not completed yet. } } - if (allDone) { - ticker.isDone = true; - } + ticker.isDone = true; } protected onTickerDidReset(ticker: IActionTicker): any { diff --git a/src/lib/Action.ts b/src/lib/Action.ts index 5db4aee..e9c35d1 100644 --- a/src/lib/Action.ts +++ b/src/lib/Action.ts @@ -2,6 +2,7 @@ import { TimingMode, TimingModeFn } from '../TimingMode'; import { IActionTicker } from './IActionTicker'; export abstract class Action { + public log = false; // ----- Default Timing Modes: ----- diff --git a/src/lib/ActionTicker.ts b/src/lib/ActionTicker.ts index 20b4dd5..44cef59 100644 --- a/src/lib/ActionTicker.ts +++ b/src/lib/ActionTicker.ts @@ -2,7 +2,7 @@ import { Action } from "./Action"; import { TimingModeFn } from "../TimingMode"; const EPSILON = 0.0000000001; -const EPSILON_ONE = 1 - EPSILON; +const EPSILON_1 = 1 - EPSILON; /** * An internal utility class that runs (or "ticks") stateless @@ -240,11 +240,11 @@ export class ActionTicker { return; } - const scaledTimeDelta = deltaTime * this.speed; + const scaledDeltaTime = deltaTime * this.speed; + // Instantaneous actions: if (this.scaledDuration === 0) { - // Instantaneous action. - (action as any).onTick(this.target, 1.0, 1.0, this, scaledTimeDelta); + (action as any).onTick(this.target, 1.0, 1.0, this, scaledDeltaTime); this.isDone = true; // Remove completed action. @@ -253,18 +253,18 @@ export class ActionTicker { return deltaTime; // relinquish the full time. } - if (deltaTime === 0) { + if (deltaTime === 0 && this.timeDistance < EPSILON_1) { return -1; // Early exit, no progress. } const b = this.easedTimeDistance; - this._elapsed += scaledTimeDelta; + this._elapsed += scaledDeltaTime; const t = this.easedTimeDistance; const dt = t - b; - (action as any).onTick(this.target, t, dt, this, scaledTimeDelta); + (action as any).onTick(this.target, t, dt, this, scaledDeltaTime); - if (this.isDone || (this.autoComplete && this.timeDistance >= EPSILON_ONE)) { + if (this.isDone || (this.autoComplete && this.timeDistance >= EPSILON_1)) { this.isDone = true; // Remove completed action.