Skip to content

Commit

Permalink
Merge pull request #693 from hoonsbory/groupComplete
Browse files Browse the repository at this point in the history
feature: implement group-level onComplete callback
  • Loading branch information
trusktr authored Jan 11, 2025
2 parents 6536e9d + 8743ea8 commit 20079e6
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 0 deletions.
16 changes: 16 additions & 0 deletions dist/tween.amd.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,19 @@ define(['exports'], (function (exports) { 'use strict';
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
};
Group.prototype.onComplete = function (callback) {
var group = this.getAll();
group.forEach(function (tween) {
var prevCallback = tween.getCompleteCallback();
tween.onComplete(function () {
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
if (completedGroup.length === group.length - 1)
callback(group);
});
});
};
return Group;
}());

Expand Down Expand Up @@ -448,6 +461,9 @@ define(['exports'], (function (exports) { 'use strict';
Tween.prototype.getId = function () {
return this._id;
};
Tween.prototype.getCompleteCallback = function () {
return this._onCompleteCallback;
};
Tween.prototype.isPlaying = function () {
return this._isPlaying;
};
Expand Down
16 changes: 16 additions & 0 deletions dist/tween.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ var Group = /** @class */ (function () {
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
};
Group.prototype.onComplete = function (callback) {
var group = this.getAll();
group.forEach(function (tween) {
var prevCallback = tween.getCompleteCallback();
tween.onComplete(function () {
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
if (completedGroup.length === group.length - 1)
callback(group);
});
});
};
return Group;
}());

Expand Down Expand Up @@ -450,6 +463,9 @@ var Tween = /** @class */ (function () {
Tween.prototype.getId = function () {
return this._id;
};
Tween.prototype.getCompleteCallback = function () {
return this._onCompleteCallback;
};
Tween.prototype.isPlaying = function () {
return this._isPlaying;
};
Expand Down
2 changes: 2 additions & 0 deletions dist/tween.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ declare class Tween<T extends UnknownProps = any> {
*/
constructor(object: T, group: true);
getId(): number;
getCompleteCallback(): ((object: T) => void) | undefined;
isPlaying(): boolean;
isPaused(): boolean;
getDuration(): number;
Expand Down Expand Up @@ -181,6 +182,7 @@ declare class Group {
* tweens, and do not rely on tweens being automatically added or removed.
*/
update(time?: number, preserve?: boolean): void;
onComplete(callback: (object: Tween[]) => void): void;
}

declare const now: () => number;
Expand Down
16 changes: 16 additions & 0 deletions dist/tween.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,19 @@ var Group = /** @class */ (function () {
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
};
Group.prototype.onComplete = function (callback) {
var group = this.getAll();
group.forEach(function (tween) {
var prevCallback = tween.getCompleteCallback();
tween.onComplete(function () {
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
if (completedGroup.length === group.length - 1)
callback(group);
});
});
};
return Group;
}());

Expand Down Expand Up @@ -446,6 +459,9 @@ var Tween = /** @class */ (function () {
Tween.prototype.getId = function () {
return this._id;
};
Tween.prototype.getCompleteCallback = function () {
return this._onCompleteCallback;
};
Tween.prototype.isPlaying = function () {
return this._isPlaying;
};
Expand Down
16 changes: 16 additions & 0 deletions dist/tween.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,19 @@
tweenIds = Object.keys(this._tweensAddedDuringUpdate);
}
};
Group.prototype.onComplete = function (callback) {
var group = this.getAll();
group.forEach(function (tween) {
var prevCallback = tween.getCompleteCallback();
tween.onComplete(function () {
prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });
if (completedGroup.length === group.length - 1)
callback(group);
});
});
};
return Group;
}());

Expand Down Expand Up @@ -452,6 +465,9 @@
Tween.prototype.getId = function () {
return this._id;
};
Tween.prototype.getCompleteCallback = function () {
return this._onCompleteCallback;
};
Tween.prototype.isPlaying = function () {
return this._isPlaying;
};
Expand Down
12 changes: 12 additions & 0 deletions src/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,16 @@ export default class Group {
tweenIds = Object.keys(this._tweensAddedDuringUpdate)
}
}
onComplete(callback: (object: Tween[]) => void) {
const group = this.getAll()
group.forEach(tween => {
const prevCallback = tween.getCompleteCallback()
tween.onComplete(() => {
prevCallback?.(tween)
// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.
const completedGroup = group.filter(tween => !tween.isPlaying())
if (completedGroup.length === group.length - 1) callback(group)
})
})
}
}
4 changes: 4 additions & 0 deletions src/Tween.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ export class Tween<T extends UnknownProps = any> {
return this._id
}

getCompleteCallback(): ((object: T) => void) | undefined {
return this._onCompleteCallback
}

isPlaying(): boolean {
return this._isPlaying
}
Expand Down
64 changes: 64 additions & 0 deletions src/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,70 @@ export const tests = {
test.ok(group.getAll() instanceof Array)
test.done()
},
'Custom group.onComplete() should be triggered when all Tweens in the group have reached their completion, and the child Tween.onComplete() should also be fired'(
test: Test,
): void {
TWEEN.removeAll()

const t = new TWEEN.Tween({x: 1}),
t2 = new TWEEN.Tween({x: 1}),
t3 = new TWEEN.Tween({x: 1}),
group = new TWEEN.Group()
let groupCounter = 0,
childCounter = 0,
childCounter2 = 0,
childCounter3 = 0

group.add(t)
group.add(t2)
group.add(t3)

t.to({x: 2}, 1000)
t2.to({x: 2}, 2000)
t3.to({x: 2}, 3000)

t.onComplete(function (): void {
childCounter++
})
t2.onComplete(function (): void {
childCounter2++
})
t3.onComplete(function (): void {
childCounter3++
})
group.onComplete(function (): void {
groupCounter++
})

t.start(0)
t2.start(0)
t3.start(0)

group.update(0)
test.deepEqual(groupCounter, 0)
test.deepEqual(childCounter, 0)
test.deepEqual(childCounter2, 0)
test.deepEqual(childCounter3, 0)

group.update(1000)
test.deepEqual(groupCounter, 0)
test.deepEqual(childCounter, 1)
test.deepEqual(childCounter2, 0)
test.deepEqual(childCounter3, 0)

group.update(2000)
test.deepEqual(childCounter, 1)
test.deepEqual(groupCounter, 0)
test.deepEqual(childCounter2, 1)
test.deepEqual(childCounter3, 0)

group.update(3000)
test.deepEqual(groupCounter, 1)
test.deepEqual(childCounter, 1)
test.deepEqual(childCounter2, 1)
test.deepEqual(childCounter3, 1)
test.done()
},

'Custom group stores tweens instead of global TWEEN group'(test: Test): void {
const group = new TWEEN.Group()
Expand Down

0 comments on commit 20079e6

Please sign in to comment.