From fe73fa15605f68828d5437e4baf041df7daf5361 Mon Sep 17 00:00:00 2001 From: jrouault Date: Wed, 2 Aug 2017 18:29:36 +0900 Subject: [PATCH 1/2] Add destroy method to Playable --- build/tina.js | 1875 +++++++++++++++++++++++---------------------- build/tina.min.js | 4 +- src/Playable.js | 21 +- src/Player.js | 17 +- 4 files changed, 981 insertions(+), 936 deletions(-) diff --git a/build/tina.js b/build/tina.js index 1c5561a..be8a982 100644 --- a/build/tina.js +++ b/build/tina.js @@ -1,187 +1,187 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { - this._transitions[0].from = fromObject; - } - return this; -}; -AbstractTween.prototype._setFrom = function () { - // Copying properties of tweened object - this._from = {}; - for (var p = 0; p < this._properties.length; p += 1) { - var property = this._properties[p]; - this._from[property] = (this._relative === true) ? 0 : this._object[property]; - } - return this._from; -}; -AbstractTween.prototype._getLastTransitionEnding = function () { - if (this._transitions.length > 0) { - return (this._relative === true) ? this._setFrom() : this._transitions[this._transitions.length - 1].to; - } else { - return (this._from === null) ? this._setFrom() : this._from; - } -}; -AbstractTween.prototype.to = function (toObject, duration, easing, easingParam, interpolationParams) { - // The API allows to pass easing names that will be replaced - // by the corresponding easing functions - if (typeof(easing) === 'string') { - // Replacing easing name by easing function - if (easingFunctions[easing] === undefined) { - console.warn('[AbstractTween.to] Given easing does not exist'); - easing = undefined; - } else { - easing = easingFunctions[easing]; - } - } - // Getting previous transition ending as the beginning for the new transition - var fromObject = this._getLastTransitionEnding(); - var TransitionConstructor = (this._relative === true) ? TransitionRelative : Transition; - var transition = new TransitionConstructor( - this._properties, - fromObject, - toObject, - this._duration, // starting time - duration, - easing, - easingParam, - this._interpolations, - interpolationParams - ); - this._transitions.push(transition); - this._duration += duration; - return this; -}; -AbstractTween.prototype.wait = function (duration) { - var toObject = this._getLastTransitionEnding(); - this._transitions.push(new Temporisation(this._duration, duration, toObject, this._properties)); - this._duration += duration; - return this; -}; -AbstractTween.prototype._update = function () { - // Finding transition corresponding to current time - var transition = this._transitions[this._index]; - while (transition.end <= this._time) { - if (this._index === (this._transitions.length - 1)) { - transition.update(this._object, 1); - return; - } - - if (this._relative === true) { - transition.update(this._object, 1); - } - transition = this._transitions[++this._index]; - } - while (this._time <= transition.start) { - if (this._index === 0) { - transition.update(this._object, 0); - return; - } - - if (this._relative === true) { - transition.update(this._object, 0); - } - transition = this._transitions[--this._index]; - } - // Updating the object with respect to the current transition and time - transition.update(this._object, (this._time - transition.start) / transition.duration); -}; -AbstractTween.prototype._validate = function () { - if (this._transitions.length === 0) { - console.warn('[AbstractTween._validate] Cannot start a tween with no transition:', this); - return false; - } - return true; +var Transition = require('./Transition'); +var TransitionRelative = require('./TransitionRelative'); +var easingFunctions = require('./easing'); +var interpolationFunctions = require('./interpolation'); +// Temporisation, used for waiting +function Temporisation(start, duration, toObject, properties) { + this.start = start; + this.end = start + duration; + this.duration = duration; + this.properties = properties; + this.to = toObject; +} +Temporisation.prototype.update = function (object) { + for (var p = 0; p < this.properties.length; p += 1) { + var property = this.properties[p]; + object[property] = this.to[property]; + } +}; +/** + * + * @classdesc + * Manages transition of properties of an object + * + * @param {object} object - Object to tween + * @param {array} properties - Properties of the object to tween + * + */ + function AbstractTween(object, properties) { + // Tweened object + this._object = object; + if ((properties === null || properties === undefined) && (object instanceof Array)) { + // Given object is an array + // Its properties to tween are the indices of the array + properties = []; + for (var p = 0; p < object.length; p += 1) { + properties[p] = p; + } + } + // Properties to tween + this._properties = properties; + // Starting property values + // By default is a copy of given object property values + this._from = null; + // Property interpolations + this._interpolations = null; + // Current transition index + this._index = 0; + // List of transitions of the tween + this._transitions = []; + // Whether the tween is relative + this._relative = false; + // Current time + this._time = 0; + // Total duration + this._duration = 0; +} +module.exports = AbstractTween; +AbstractTween.prototype.relative = function (relative) { + this._relative = relative; + return this; +}; +AbstractTween.prototype.reset = function () { + this._index = 0; + this._duration = 0; + this._transitions = []; + return this; +}; +AbstractTween.prototype.interpolations = function (interpolations) { + // The API allows to pass interpolation names that will be replaced + // by the corresponding interpolation functions + for (var p = 0; p < this._properties.length; p += 1) { + var property = this._properties[p]; + var interpolation = interpolations[property]; + if (interpolation === undefined) { + interpolations[property] = interpolationFunctions.linear; + continue; + } + if (typeof(interpolation) === 'string') { + // Replacing interpolation name by interpolation function + if (interpolationFunctions[interpolation] === undefined) { + console.warn('[AbstractTween.interpolations] Given interpolation does not exist'); + interpolations[property] = interpolationFunctions.linear; + } else { + interpolations[property] = interpolationFunctions[interpolation]; + } + } + } + this._interpolations = interpolations; + return this; +}; +AbstractTween.prototype.from = function (fromObject) { + this._from = fromObject; + if (this._transitions.length > 0) { + this._transitions[0].from = fromObject; + } + return this; +}; +AbstractTween.prototype._setFrom = function () { + // Copying properties of tweened object + this._from = {}; + for (var p = 0; p < this._properties.length; p += 1) { + var property = this._properties[p]; + this._from[property] = (this._relative === true) ? 0 : this._object[property]; + } + return this._from; +}; +AbstractTween.prototype._getLastTransitionEnding = function () { + if (this._transitions.length > 0) { + return (this._relative === true) ? this._setFrom() : this._transitions[this._transitions.length - 1].to; + } else { + return (this._from === null) ? this._setFrom() : this._from; + } +}; +AbstractTween.prototype.to = function (toObject, duration, easing, easingParam, interpolationParams) { + // The API allows to pass easing names that will be replaced + // by the corresponding easing functions + if (typeof(easing) === 'string') { + // Replacing easing name by easing function + if (easingFunctions[easing] === undefined) { + console.warn('[AbstractTween.to] Given easing does not exist'); + easing = undefined; + } else { + easing = easingFunctions[easing]; + } + } + // Getting previous transition ending as the beginning for the new transition + var fromObject = this._getLastTransitionEnding(); + var TransitionConstructor = (this._relative === true) ? TransitionRelative : Transition; + var transition = new TransitionConstructor( + this._properties, + fromObject, + toObject, + this._duration, // starting time + duration, + easing, + easingParam, + this._interpolations, + interpolationParams + ); + this._transitions.push(transition); + this._duration += duration; + return this; +}; +AbstractTween.prototype.wait = function (duration) { + var toObject = this._getLastTransitionEnding(); + this._transitions.push(new Temporisation(this._duration, duration, toObject, this._properties)); + this._duration += duration; + return this; +}; +AbstractTween.prototype._update = function () { + // Finding transition corresponding to current time + var transition = this._transitions[this._index]; + while (transition.end <= this._time) { + if (this._index === (this._transitions.length - 1)) { + transition.update(this._object, 1); + return; + } + + if (this._relative === true) { + transition.update(this._object, 1); + } + transition = this._transitions[++this._index]; + } + while (this._time <= transition.start) { + if (this._index === 0) { + transition.update(this._object, 0); + return; + } + + if (this._relative === true) { + transition.update(this._object, 0); + } + transition = this._transitions[--this._index]; + } + // Updating the object with respect to the current transition and time + transition.update(this._object, (this._time - transition.start) / transition.duration); +}; +AbstractTween.prototype._validate = function () { + if (this._transitions.length === 0) { + console.warn('[AbstractTween._validate] Cannot start a tween with no transition:', this); + return false; + } + return true; }; },{"./Transition":16,"./TransitionRelative":17,"./easing":20,"./interpolation":23}],2:[function(require,module,exports){ @@ -529,32 +529,32 @@ BriefPlayer.prototype._onPlayableRemoved = BriefPlayer.prototype._updateDuration // 'playable:', changedPlayable, 'player:', this); // }; },{"./BriefExtension":2,"./Player":9,"./inherit":22}],5:[function(require,module,exports){ -var BriefPlayable = require('./BriefPlayable'); - -/** - * @classdesc - * Manages tweening of one property or several properties of an object - */ - -function Delay(duration, onComplete) { - if ((this instanceof Delay) === false) { - return new Delay(duration); - } - - BriefPlayable.call(this); - this.reset(duration, onComplete); -} -Delay.prototype = Object.create(BriefPlayable.prototype); -Delay.prototype.constructor = Delay; -module.exports = Delay; - -Delay.prototype.reset = function (duration, onComplete) { - this._duration = duration; - if (onComplete !== undefined) { - this.onComplete(onComplete); - } - - return this; +var BriefPlayable = require('./BriefPlayable'); + +/** + * @classdesc + * Manages tweening of one property or several properties of an object + */ + +function Delay(duration, onComplete) { + if ((this instanceof Delay) === false) { + return new Delay(duration); + } + + BriefPlayable.call(this); + this.reset(duration, onComplete); +} +Delay.prototype = Object.create(BriefPlayable.prototype); +Delay.prototype.constructor = Delay; +module.exports = Delay; + +Delay.prototype.reset = function (duration, onComplete) { + this._duration = duration; + if (onComplete !== undefined) { + this.onComplete(onComplete); + } + + return this; }; },{"./BriefPlayable":3}],6:[function(require,module,exports){ /** @@ -1169,13 +1169,30 @@ Playable.prototype._start = function () { } }; -Playable.prototype.stop = function () { +Playable.prototype.destroy = function () { if (this._player === null) { return this; } // Stopping playable without performing any additional update nor completing - if (this._player._remove(this) === false) { + if (this._player._remove(this, true) === false) { + // Could not be removed + return this; + } + + if (this._onStop !== null) { + this._onStop(); + } + return this; +}; + +Playable.prototype.stop = function () { + if (this._player === null) { + return this; + } + + // Stopping playable while letting it perform a final update and complete + if (this._player._remove(this, false) === false) { // Could not be removed return this; } @@ -1230,273 +1247,279 @@ Playable.prototype._update = function () {}; Playable.prototype._validate = function () {}; },{}],9:[function(require,module,exports){ -var Playable = require('./Playable'); -var DoublyList = require('./DoublyList'); - -/** - * @classdesc - * Manages the update of a list of playable with respect to a given elapsed time. - */ -function Player() { - Playable.call(this); +var Playable = require('./Playable'); +var DoublyList = require('./DoublyList'); + +/** + * @classdesc + * Manages the update of a list of playable with respect to a given elapsed time. + */ +function Player() { + Playable.call(this); + + // A DoublyList, rather than an Array, is used to store playables. + // It allows for faster removal and is similar in speed for iterations. + + // List of active playables handled by this player + this._activePlayables = new DoublyList(); + + // List of inactive playables handled by this player + this._inactivePlayables = new DoublyList(); + + // List of playables that are not handled by this player anymore and are waiting to be removed + this._playablesToRemove = new DoublyList(); + + // Whether to silence warnings + this._silent = true; + + // Whether to trigger the debugger on warnings + this._debug = false; +} +Player.prototype = Object.create(Playable.prototype); +Player.prototype.constructor = Player; +module.exports = Player; + +Player.prototype._add = function (playable) { + if (playable._handle === null) { + // Playable can be added + playable._handle = this._inactivePlayables.add(playable); + playable._player = this; + // this._onPlayableAdded(playable); + return true; + } + + // Playable is already handled, either by this player or by another one + if (playable._handle.container === this._playablesToRemove) { + // Playable was being removed, removing from playables to remove + playable._handle = this._playablesToRemove.removeByReference(playable._handle); + playable._handle = playable._handle.object; + return true; + } + + if (playable._handle.container === this._activePlayables) { + this._warn('[Player._add] Playable is already present, and active'); + return false; + } + + if (playable._handle.container === this._inactivePlayables) { + this._warn('[Player._add] Playable is already present, but inactive (could be starting)'); + return false; + } + + this._warn('[Player._add] Playable is used elsewhere'); + return false; +}; + +Player.prototype._remove = function (playable, immediate) { + if (playable._handle === null) { + this._warn('[Player._remove] Playable is not being used'); + return false; + } + + // Playable is handled, either by this player or by another one + if (playable._handle.container === this._activePlayables) { + if (immediate) { + playable._handle = this._activePlayables.removeByReference(playable._handle); + return true; + } else { + // Playable was active, adding to remove list + playable._handle = this._playablesToRemove.add(playable._handle); + return true; + } + } + + if (playable._handle.container === this._inactivePlayables) { + // Playable was inactive, removing from inactive playables + playable._handle = this._inactivePlayables.removeByReference(playable._handle); + return true; + } + + if (playable._handle.container === this._playablesToRemove) { + this._warn('[Player._remove] Playable is already being removed'); + return false; + } + + this._warn('[Player._remove] Playable is used elsewhere'); + return false; +}; + +Player.prototype.remove = function (playable) { + if (playable._handle.container === this._activePlayables) { + playable.stop(); + } + + this._remove(playable, false); + this._onPlayableRemoved(playable); + return this; +}; + +Player.prototype.removeAll = function () { + // Stopping all active playables + var handle = this._activePlayables.first; + while (handle !== null) { + var next = handle.next; + handle.object.stop(); + handle = next; + } + + this._handlePlayablesToRemove(); + return this; +}; + +Player.prototype.possess = function (playable) { + if (playable._handle === null) { + return false; + } + + return (playable._handle.container === this._activePlayables) || (playable._handle.container === this._inactivePlayables); +}; + +Player.prototype._handlePlayablesToRemove = function () { + while (this._playablesToRemove.length > 0) { + // O(1) where O stands for "Oh yeah" + + // Removing from list of playables to remove + var handle = this._playablesToRemove.pop(); + + // Removing from list of active playables + var playable = handle.object; + playable._handle = this._activePlayables.removeByReference(handle); + } + + if ((this._activePlayables.length === 0) && (this._inactivePlayables.length === 0)) { + this._onAllPlayablesRemoved(); + } +}; + +Player.prototype.clear = function () { + this._activePlayables.clear(); + this._inactivePlayables.clear(); + this._playablesToRemove.clear(); + this._controls.clear(); + return this; +}; + +Player.prototype._warn = function (warning) { + // jshint debug: true + if (this._silent === false) { + console.warn('[TINA]' + warning); + } + + if (this._debug === true) { + debugger; + } +}; + +Player.prototype.silent = function (silent) { + this._silent = silent || false; + return this; +}; + +Player.prototype.debug = function (debug) { + this._debug = debug || false; + return this; +}; + +Player.prototype.stop = function () { + // Stopping all active playables + var handle = this._activePlayables.first; + while (handle !== null) { + var next = handle.next; + var playable = handle.object; + playable.stop(); + handle = next; + } + + this._handlePlayablesToRemove(); + Playable.prototype.stop.call(this); +}; + +Player.prototype._activate = function (playable) { + if (playable._handle.container === this._inactivePlayables) { + this._inactivePlayables.removeByReference(playable._handle); + playable._handle = this._activePlayables.addBack(playable); + } else if (playable._handle.container === this._playablesToRemove) { + // Already in list of active playables + this._playablesToRemove.removeByReference(playable._handle); + playable._handle = playable._handle.object; + } + + playable._active = true; + return true; +}; + +Player.prototype._reactivate = Player.prototype._activate; + +Player.prototype._inactivate = function (playable) { + if (playable._handle === null) { + this._warn('[Player._inactivate] Cannot stop a playable that is not running'); + return false; + } + + if (playable._handle.container === this._activePlayables) { + // O(1) + this._activePlayables.removeByReference(playable._handle); + playable._handle = this._inactivePlayables.addBack(playable); + } + + playable._active = false; + return true; +}; + +Player.prototype._updatePlayableList = function (dt) { + this._handlePlayablesToRemove(); + + var time0, time1; + if (dt > 0) { + time0 = this._time - dt; + time1 = this._time; + } else { + time0 = this._time; + time1 = this._time - dt; + } + + // Activating playables + var handle = this._inactivePlayables.first; + while (handle !== null) { + var playable = handle.object; + + // Fetching handle of next playable + handle = handle.next; + + // Starting if player time within playable bounds + // console.log('Should playable be playing?', playable._startTime, time0, time1, dt) + if (playable._active && playable._overlaps(time0, time1)) { + this._activate(playable); + playable._start(); + } + } +}; + +Player.prototype._update = function (dt, overflow) { + this._updatePlayableList(dt); + for (var handle = this._activePlayables.first; handle !== null; handle = handle.next) { + if (overflow === undefined) { + handle.object._moveTo(this._time, dt); + } else { + handle.object._moveTo(this._time, dt, overflow); + } + } +}; + +// Overridable methods +// Player.prototype._onPlayableAdded = function (/* playable */) {}; +Player.prototype._onPlayableChanged = function (/* playable */) {}; +Player.prototype._onPlayableRemoved = function (/* playable */) {}; +Player.prototype._onAllPlayablesRemoved = function () {}; + +},{"./DoublyList":6,"./Playable":8}],10:[function(require,module,exports){ +var BriefPlayable = require('./BriefPlayable'); +var DoublyList = require('./DoublyList'); - // A DoublyList, rather than an Array, is used to store playables. - // It allows for faster removal and is similar in speed for iterations. - - // List of active playables handled by this player - this._activePlayables = new DoublyList(); - - // List of inactive playables handled by this player - this._inactivePlayables = new DoublyList(); - - // List of playables that are not handled by this player anymore and are waiting to be removed - this._playablesToRemove = new DoublyList(); - - // Whether to silence warnings - this._silent = true; - - // Whether to trigger the debugger on warnings - this._debug = false; -} -Player.prototype = Object.create(Playable.prototype); -Player.prototype.constructor = Player; -module.exports = Player; - -Player.prototype._add = function (playable) { - if (playable._handle === null) { - // Playable can be added - playable._handle = this._inactivePlayables.add(playable); - playable._player = this; - // this._onPlayableAdded(playable); - return true; - } - - // Playable is already handled, either by this player or by another one - if (playable._handle.container === this._playablesToRemove) { - // Playable was being removed, removing from playables to remove - playable._handle = this._playablesToRemove.removeByReference(playable._handle); - playable._handle = playable._handle.object; - return true; - } - - if (playable._handle.container === this._activePlayables) { - this._warn('[Player._add] Playable is already present, and active'); - return false; - } - - if (playable._handle.container === this._inactivePlayables) { - this._warn('[Player._add] Playable is already present, but inactive (could be starting)'); - return false; - } - - this._warn('[Player._add] Playable is used elsewhere'); - return false; -}; - -Player.prototype._remove = function (playable) { - if (playable._handle === null) { - this._warn('[Player._remove] Playable is not being used'); - return false; - } - - // Playable is handled, either by this player or by another one - if (playable._handle.container === this._activePlayables) { - // Playable was active, adding to remove list - playable._handle = this._playablesToRemove.add(playable._handle); - return true; - } - - if (playable._handle.container === this._inactivePlayables) { - // Playable was inactive, removing from inactive playables - playable._handle = this._inactivePlayables.removeByReference(playable._handle); - return true; - } - - if (playable._handle.container === this._playablesToRemove) { - this._warn('[Player._remove] Playable is already being removed'); - return false; - } - - this._warn('[Player._remove] Playable is used elsewhere'); - return false; -}; - -Player.prototype.remove = function (playable) { - if (playable._handle.container === this._activePlayables) { - playable.stop(); - } - - this._remove(playable); - this._onPlayableRemoved(playable); - return this; -}; - -Player.prototype.removeAll = function () { - // Stopping all active playables - var handle = this._activePlayables.first; - while (handle !== null) { - var next = handle.next; - handle.object.stop(); - handle = next; - } - - this._handlePlayablesToRemove(); - return this; -}; - -Player.prototype.possess = function (playable) { - if (playable._handle === null) { - return false; - } - - return (playable._handle.container === this._activePlayables) || (playable._handle.container === this._inactivePlayables); -}; - -Player.prototype._handlePlayablesToRemove = function () { - while (this._playablesToRemove.length > 0) { - // O(1) where O stands for "Oh yeah" - - // Removing from list of playables to remove - var handle = this._playablesToRemove.pop(); - - // Removing from list of active playables - var playable = handle.object; - playable._handle = this._activePlayables.removeByReference(handle); - } - - if ((this._activePlayables.length === 0) && (this._inactivePlayables.length === 0)) { - this._onAllPlayablesRemoved(); - } -}; - -Player.prototype.clear = function () { - this._activePlayables.clear(); - this._inactivePlayables.clear(); - this._playablesToRemove.clear(); - this._controls.clear(); - return this; -}; - -Player.prototype._warn = function (warning) { - // jshint debug: true - if (this._silent === false) { - console.warn('[TINA]' + warning); - } - - if (this._debug === true) { - debugger; - } -}; - -Player.prototype.silent = function (silent) { - this._silent = silent || false; - return this; -}; - -Player.prototype.debug = function (debug) { - this._debug = debug || false; - return this; -}; - -Player.prototype.stop = function () { - // Stopping all active playables - var handle = this._activePlayables.first; - while (handle !== null) { - var next = handle.next; - var playable = handle.object; - playable.stop(); - handle = next; - } - - this._handlePlayablesToRemove(); - Playable.prototype.stop.call(this); -}; - -Player.prototype._activate = function (playable) { - if (playable._handle.container === this._inactivePlayables) { - this._inactivePlayables.removeByReference(playable._handle); - playable._handle = this._activePlayables.addBack(playable); - } else if (playable._handle.container === this._playablesToRemove) { - // Already in list of active playables - this._playablesToRemove.removeByReference(playable._handle); - playable._handle = playable._handle.object; - } - - playable._active = true; - return true; -}; - -Player.prototype._reactivate = Player.prototype._activate; - -Player.prototype._inactivate = function (playable) { - if (playable._handle === null) { - this._warn('[Player._inactivate] Cannot stop a playable that is not running'); - return false; - } - - if (playable._handle.container === this._activePlayables) { - // O(1) - this._activePlayables.removeByReference(playable._handle); - playable._handle = this._inactivePlayables.addBack(playable); - } - - playable._active = false; - return true; -}; - -Player.prototype._updatePlayableList = function (dt) { - this._handlePlayablesToRemove(); - - var time0, time1; - if (dt > 0) { - time0 = this._time - dt; - time1 = this._time; - } else { - time0 = this._time; - time1 = this._time - dt; - } - - // Activating playables - var handle = this._inactivePlayables.first; - while (handle !== null) { - var playable = handle.object; - - // Fetching handle of next playable - handle = handle.next; - - // Starting if player time within playable bounds - // console.log('Should playable be playing?', playable._startTime, time0, time1, dt) - if (playable._active && playable._overlaps(time0, time1)) { - this._activate(playable); - playable._start(); - } - } -}; - -Player.prototype._update = function (dt, overflow) { - this._updatePlayableList(dt); - for (var handle = this._activePlayables.first; handle !== null; handle = handle.next) { - if (overflow === undefined) { - handle.object._moveTo(this._time, dt); - } else { - handle.object._moveTo(this._time, dt, overflow); - } - } -}; - -// Overridable methods -// Player.prototype._onPlayableAdded = function (/* playable */) {}; -Player.prototype._onPlayableChanged = function (/* playable */) {}; -Player.prototype._onPlayableRemoved = function (/* playable */) {}; -Player.prototype._onAllPlayablesRemoved = function () {}; -},{"./DoublyList":6,"./Playable":8}],10:[function(require,module,exports){ -var BriefPlayable = require('./BriefPlayable'); -var DoublyList = require('./DoublyList'); - -function Record(time, values) { - this.time = time; - this.values = values; -} +function Record(time, values) { + this.time = time; + this.values = values; +} function ObjectRecorder(object, properties, onIn, onOut) { this.object = object; @@ -2013,408 +2036,408 @@ Sequence.prototype._onPlayableChanged = Sequence.prototype._reconstruct; },{"./Delay":5,"./DoublyList":6,"./Timeline":14}],12:[function(require,module,exports){ (function (global){ - -var DoublyList = require('./DoublyList'); - -/** - * - * @module TINA - * - * @author Brice Chevalier - * - * @desc - * - * Tweening and INterpolations for Animation - * - * Note: if you want a particular component to be added - * create an issue or contribute at https://github.com/Wizcorp/tina.js - */ - -// window within a browser, global within node -var root; -if (typeof(window) !== 'undefined') { - root = window; -} else if (typeof(global) !== 'undefined') { - root = global; -} else { - console.warn('[TINA] Your environment might not support TINA.'); - root = this; -} - -// Method to trigger automatic updates -var requestAnimFrame = (function(){ - return root.requestAnimationFrame || - root.webkitRequestAnimationFrame || - root.mozRequestAnimationFrame || - root.oRequestAnimationFrame || - root.msRequestAnimationFrame || - function(callback){ - root.setTimeout(callback, 1000 / 60); - }; -})(); - -var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.clearTimeout; - -// Performance.now gives better precision than Date.now -var clock = root.performance || Date; - -var TINA = { - // List of active tweeners handled by TINA - _activeTweeners: new DoublyList(), - - // List of inactive tweeners handled by TINA - _inactiveTweeners: new DoublyList(), - - // List of tweeners that are not handled by this player anymore and are waiting to be removed - _tweenersToRemove: new DoublyList(), - - // _tweeners: [], - - _defaultTweener: null, - - _startTime: 0, - _time: 0, - - _requestFrameId: null, - _paused: false, - - // callbacks - _onStart: null, - _onPause: null, - _onResume: null, - _onUpdate: null, - _onStop: null, - - _pauseOnLostFocus: false, - _pauseOnLostFocusInitialised: false, - - onStart: function (onStart) { - this._onStart = onStart; - return this; - }, - - onUpdate: function (onUpdate) { - this._onUpdate = onUpdate; - return this; - }, - - onStop: function (onStop) { - this._onStop = onStop; - return this; - }, - - onPause: function (onPause) { - this._onPause = onPause; - return this; - }, - - _onPlayableChanged: function () {}, - _onPlayableRemoved: function () {}, - _onAllPlayablesRemoved: function () {}, - - isRunning: function () { - return (this._requestFrameId !== null); - }, - - update: function () { - if (this._paused) { - return; - } - - var now = clock.now() - this._startTime; - var dt = now - this._time; - if (dt < 0) { - // Clock error - // Date.now is based on a clock that is resynchronized - // every 15-20 mins and could cause the timer to go backward in time. - // (legend or reality? not sure, but I think I noticed it once) - // To get some explanation from Paul Irish: - // http://updates.html5rocks.com/2012/08/When-milliseconds-are-not-enough-performance-now - dt = 1; // incrementing time by 1 millisecond - this._startTime -= 1; - this._time += 1; - } else { - this._time = now; - } - - // Removing any tweener that is requested to be removed - while (this._tweenersToRemove.length > 0) { - // Removing from list of tweeners to remove - var tweenerToRemove = this._tweenersToRemove.pop(); - - // Removing from list of active tweeners - tweenerToRemove._handle = this._activeTweeners.removeByReference(tweenerToRemove._handle); - } - - // Activating any inactive tweener - while (this._inactiveTweeners.length > 0) { - // Removing from list of inactive tweeners - var tweenerToActivate = this._inactiveTweeners.pop(); - - // Adding to list of active tweeners - tweenerToActivate._handle = this._activeTweeners.addBack(tweenerToActivate); - tweenerToActivate._start(); - } - - for (var handle = this._activeTweeners.first; handle !== null; handle = handle.next) { - handle.object._moveTo(this._time, dt); - } - - if (this._onUpdate !== null) { - this._onUpdate(this._time, dt); - } - }, - - reset: function () { - // Resetting the clock - // Getting time difference between last update and now - var now = clock.now(); - var dt = now - this._time; - - // Moving starting time by this difference - // As if the time had virtually not moved - this._startTime += dt; - this._time = 0; - }, - - start: function () { - if (this._startAutomaticUpdate() === false) { - return; - } - - if (this._onStart !== null) { - this._onStart(); - } - - while (this._inactiveTweeners.length > 0) { - var handle = this._inactiveTweeners.first; - this._activate(handle.object); - } - - return this; - }, - - stop: function () { - if (this._stopAutomaticUpdate() === false) { - return; - } - - while (this._activePlayables.length > 0) { - var handle = this._activePlayables.first; - handle.object.stop(); - } - - if (this._onStop !== null) { - this._onStop(); - } - - return this; - }, - - // Internal start method, called by start and resume - _startAutomaticUpdate: function () { - if (this._requestFrameId !== null) { - return false; - } - - function updateTINA() { - TINA.update(); - TINA._requestFrameId = requestAnimFrame(updateTINA); - } - - this.reset(); - - // Starting the animation loop - this._requestFrameId = requestAnimFrame(updateTINA); - return true; - }, - - // Internal stop method, called by stop and pause - _stopAutomaticUpdate: function () { - if (this._requestFrameId === null) { - return false; - } - - // Stopping the animation loop - cancelAnimationFrame(this._requestFrameId); - this._requestFrameId = null; - return true; - }, - - pause: function () { - this._paused = true; - if (this._onPause !== null) { - this._onPause(); - } - - return this; - }, - - resume: function () { - this._paused = false; - this._startTime = clock.now() - this._time; - - if (this._onResume !== null) { - this._onResume(); - } - - return this; - }, - - _initialisePauseOnLostFocus: function () { - if (this._pauseOnLostFocusInitialised === true) { - return; - } - - if (document === undefined) { - // Document is not defined (TINA might be running on node.js) - console.warn('[TINA.pauseOnLostFocus] Cannot pause on lost focus because TINA is not running in a webpage (node.js does not allow this functionality)'); - return; - } - - // To handle lost of focus of the page - var hidden, visbilityChange; - if (typeof document.hidden !== 'undefined') { - // Recent browser support - hidden = 'hidden'; - visbilityChange = 'visibilitychange'; - } else if (typeof document.mozHidden !== 'undefined') { - hidden = 'mozHidden'; - visbilityChange = 'mozvisibilitychange'; - } else if (typeof document.msHidden !== 'undefined') { - hidden = 'msHidden'; - visbilityChange = 'msvisibilitychange'; - } else if (typeof document.webkitHidden !== 'undefined') { - hidden = 'webkitHidden'; - visbilityChange = 'webkitvisibilitychange'; - } - - if (typeof document[hidden] === 'undefined') { - console.warn('[Tweener] Cannot pause on lost focus because the browser does not support the Page Visibility API'); - return; - } - - this._pauseOnLostFocusInitialised = true; - - // Handle page visibility change - var wasRunning = false; - document.addEventListener(visbilityChange, function () { - if (document[hidden]) { - // document is hiding - wasRunning = TINA.isRunning(); - if (wasRunning && TINA._pauseOnLostFocus) { - TINA.pause(); - } - } - - if (!document[hidden]) { - // document is back (we missed you buddy) - if (wasRunning && TINA._pauseOnLostFocus) { - // Running TINA only if it was running when the document focus was lost - TINA.resume(); - } - } - }, false); - }, - - pauseOnLostFocus: function (pauseOnLostFocus) { - if (pauseOnLostFocus === true && this._pauseOnLostFocusInitialised === false) { - this._initialisePauseOnLostFocus(); - } - - this._pauseOnLostFocus = pauseOnLostFocus; - return this; - }, - - _add: function (tweener) { - // A tweener is starting - if (this._requestFrameId === null) { - // TINA is not running, starting now - this.start(); - } - - if (tweener._handle === null) { - // Tweener can be added - tweener._handle = this._inactiveTweeners.add(tweener); - tweener._player = this; - tweener._time = (this._time - tweener._startTime) * tweener._speed; - return; - } - - // Tweener is already handled - if (tweener._handle.container === this._tweenersToRemove) { - // Playable was being removed, removing from playables to remove - tweener._handle = this._tweenersToRemove.removeByReference(tweener._handle); - return; - } - }, - - add: function (tweener) { - this._add(tweener); - return this; - }, - - _reactivate: function (tweener) { - this._add(tweener); - return this; - }, - - _inactivate: function (tweener) { - if (tweener._handle !== null) { - this._activePlayables.removeByReference(tweener._handle); - } - - tweener._handle = this._inactiveTweeners.addBack(tweener); - }, - - _remove: function (tweener) { - if (tweener._handle === null) { - return; - } - - // Playable is handled, either by this player or by another one - if (tweener._handle.container === this._activeTweeners) { - // Tweener was active, adding to remove list - tweener._handle = this._tweenersToRemove.add(tweener._handle); - return; - } - - if (tweener._handle.container === this._inactiveTweeners) { - // Tweener was inactive, removing from inactive tweeners - tweener._handle = this._inactiveTweeners.removeByReference(tweener._handle); - return; - } - }, - - remove: function (tweener) { - this._remove(tweener); - return this; - }, - - setDefaultTweener: function (tweener) { - this._defaultTweener = tweener; - return this; - }, - - getDefaultTweener: function () { - if (this._defaultTweener === null) { - // If a default tweener is required but none exist - // Then we create one - var DefaultTweener = this.Timer; - this._defaultTweener = new DefaultTweener(); - } - - return this._defaultTweener; - }, - - _startDefaultTweener: function () { - var defaultTweener = this.getDefaultTweener(); - this._add(defaultTweener); - return defaultTweener; - } -}; - -module.exports = root.TINA = TINA; + +var DoublyList = require('./DoublyList'); + +/** + * + * @module TINA + * + * @author Brice Chevalier + * + * @desc + * + * Tweening and INterpolations for Animation + * + * Note: if you want a particular component to be added + * create an issue or contribute at https://github.com/Wizcorp/tina.js + */ + +// window within a browser, global within node +var root; +if (typeof(window) !== 'undefined') { + root = window; +} else if (typeof(global) !== 'undefined') { + root = global; +} else { + console.warn('[TINA] Your environment might not support TINA.'); + root = this; +} + +// Method to trigger automatic updates +var requestAnimFrame = (function(){ + return root.requestAnimationFrame || + root.webkitRequestAnimationFrame || + root.mozRequestAnimationFrame || + root.oRequestAnimationFrame || + root.msRequestAnimationFrame || + function(callback){ + root.setTimeout(callback, 1000 / 60); + }; +})(); + +var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.clearTimeout; + +// Performance.now gives better precision than Date.now +var clock = root.performance || Date; + +var TINA = { + // List of active tweeners handled by TINA + _activeTweeners: new DoublyList(), + + // List of inactive tweeners handled by TINA + _inactiveTweeners: new DoublyList(), + + // List of tweeners that are not handled by this player anymore and are waiting to be removed + _tweenersToRemove: new DoublyList(), + + // _tweeners: [], + + _defaultTweener: null, + + _startTime: 0, + _time: 0, + + _requestFrameId: null, + _paused: false, + + // callbacks + _onStart: null, + _onPause: null, + _onResume: null, + _onUpdate: null, + _onStop: null, + + _pauseOnLostFocus: false, + _pauseOnLostFocusInitialised: false, + + onStart: function (onStart) { + this._onStart = onStart; + return this; + }, + + onUpdate: function (onUpdate) { + this._onUpdate = onUpdate; + return this; + }, + + onStop: function (onStop) { + this._onStop = onStop; + return this; + }, + + onPause: function (onPause) { + this._onPause = onPause; + return this; + }, + + _onPlayableChanged: function () {}, + _onPlayableRemoved: function () {}, + _onAllPlayablesRemoved: function () {}, + + isRunning: function () { + return (this._requestFrameId !== null); + }, + + update: function () { + if (this._paused) { + return; + } + + var now = clock.now() - this._startTime; + var dt = now - this._time; + if (dt < 0) { + // Clock error + // Date.now is based on a clock that is resynchronized + // every 15-20 mins and could cause the timer to go backward in time. + // (legend or reality? not sure, but I think I noticed it once) + // To get some explanation from Paul Irish: + // http://updates.html5rocks.com/2012/08/When-milliseconds-are-not-enough-performance-now + dt = 1; // incrementing time by 1 millisecond + this._startTime -= 1; + this._time += 1; + } else { + this._time = now; + } + + // Removing any tweener that is requested to be removed + while (this._tweenersToRemove.length > 0) { + // Removing from list of tweeners to remove + var tweenerToRemove = this._tweenersToRemove.pop(); + + // Removing from list of active tweeners + tweenerToRemove._handle = this._activeTweeners.removeByReference(tweenerToRemove._handle); + } + + // Activating any inactive tweener + while (this._inactiveTweeners.length > 0) { + // Removing from list of inactive tweeners + var tweenerToActivate = this._inactiveTweeners.pop(); + + // Adding to list of active tweeners + tweenerToActivate._handle = this._activeTweeners.addBack(tweenerToActivate); + tweenerToActivate._start(); + } + + for (var handle = this._activeTweeners.first; handle !== null; handle = handle.next) { + handle.object._moveTo(this._time, dt); + } + + if (this._onUpdate !== null) { + this._onUpdate(this._time, dt); + } + }, + + reset: function () { + // Resetting the clock + // Getting time difference between last update and now + var now = clock.now(); + var dt = now - this._time; + + // Moving starting time by this difference + // As if the time had virtually not moved + this._startTime += dt; + this._time = 0; + }, + + start: function () { + if (this._startAutomaticUpdate() === false) { + return; + } + + if (this._onStart !== null) { + this._onStart(); + } + + while (this._inactiveTweeners.length > 0) { + var handle = this._inactiveTweeners.first; + this._activate(handle.object); + } + + return this; + }, + + stop: function () { + if (this._stopAutomaticUpdate() === false) { + return; + } + + while (this._activePlayables.length > 0) { + var handle = this._activePlayables.first; + handle.object.stop(); + } + + if (this._onStop !== null) { + this._onStop(); + } + + return this; + }, + + // Internal start method, called by start and resume + _startAutomaticUpdate: function () { + if (this._requestFrameId !== null) { + return false; + } + + function updateTINA() { + TINA.update(); + TINA._requestFrameId = requestAnimFrame(updateTINA); + } + + this.reset(); + + // Starting the animation loop + this._requestFrameId = requestAnimFrame(updateTINA); + return true; + }, + + // Internal stop method, called by stop and pause + _stopAutomaticUpdate: function () { + if (this._requestFrameId === null) { + return false; + } + + // Stopping the animation loop + cancelAnimationFrame(this._requestFrameId); + this._requestFrameId = null; + return true; + }, + + pause: function () { + this._paused = true; + if (this._onPause !== null) { + this._onPause(); + } + + return this; + }, + + resume: function () { + this._paused = false; + this._startTime = clock.now() - this._time; + + if (this._onResume !== null) { + this._onResume(); + } + + return this; + }, + + _initialisePauseOnLostFocus: function () { + if (this._pauseOnLostFocusInitialised === true) { + return; + } + + if (document === undefined) { + // Document is not defined (TINA might be running on node.js) + console.warn('[TINA.pauseOnLostFocus] Cannot pause on lost focus because TINA is not running in a webpage (node.js does not allow this functionality)'); + return; + } + + // To handle lost of focus of the page + var hidden, visbilityChange; + if (typeof document.hidden !== 'undefined') { + // Recent browser support + hidden = 'hidden'; + visbilityChange = 'visibilitychange'; + } else if (typeof document.mozHidden !== 'undefined') { + hidden = 'mozHidden'; + visbilityChange = 'mozvisibilitychange'; + } else if (typeof document.msHidden !== 'undefined') { + hidden = 'msHidden'; + visbilityChange = 'msvisibilitychange'; + } else if (typeof document.webkitHidden !== 'undefined') { + hidden = 'webkitHidden'; + visbilityChange = 'webkitvisibilitychange'; + } + + if (typeof document[hidden] === 'undefined') { + console.warn('[Tweener] Cannot pause on lost focus because the browser does not support the Page Visibility API'); + return; + } + + this._pauseOnLostFocusInitialised = true; + + // Handle page visibility change + var wasRunning = false; + document.addEventListener(visbilityChange, function () { + if (document[hidden]) { + // document is hiding + wasRunning = TINA.isRunning(); + if (wasRunning && TINA._pauseOnLostFocus) { + TINA.pause(); + } + } + + if (!document[hidden]) { + // document is back (we missed you buddy) + if (wasRunning && TINA._pauseOnLostFocus) { + // Running TINA only if it was running when the document focus was lost + TINA.resume(); + } + } + }, false); + }, + + pauseOnLostFocus: function (pauseOnLostFocus) { + if (pauseOnLostFocus === true && this._pauseOnLostFocusInitialised === false) { + this._initialisePauseOnLostFocus(); + } + + this._pauseOnLostFocus = pauseOnLostFocus; + return this; + }, + + _add: function (tweener) { + // A tweener is starting + if (this._requestFrameId === null) { + // TINA is not running, starting now + this.start(); + } + + if (tweener._handle === null) { + // Tweener can be added + tweener._handle = this._inactiveTweeners.add(tweener); + tweener._player = this; + tweener._time = (this._time - tweener._startTime) * tweener._speed; + return; + } + + // Tweener is already handled + if (tweener._handle.container === this._tweenersToRemove) { + // Playable was being removed, removing from playables to remove + tweener._handle = this._tweenersToRemove.removeByReference(tweener._handle); + return; + } + }, + + add: function (tweener) { + this._add(tweener); + return this; + }, + + _reactivate: function (tweener) { + this._add(tweener); + return this; + }, + + _inactivate: function (tweener) { + if (tweener._handle !== null) { + this._activePlayables.removeByReference(tweener._handle); + } + + tweener._handle = this._inactiveTweeners.addBack(tweener); + }, + + _remove: function (tweener) { + if (tweener._handle === null) { + return; + } + + // Playable is handled, either by this player or by another one + if (tweener._handle.container === this._activeTweeners) { + // Tweener was active, adding to remove list + tweener._handle = this._tweenersToRemove.add(tweener._handle); + return; + } + + if (tweener._handle.container === this._inactiveTweeners) { + // Tweener was inactive, removing from inactive tweeners + tweener._handle = this._inactiveTweeners.removeByReference(tweener._handle); + return; + } + }, + + remove: function (tweener) { + this._remove(tweener); + return this; + }, + + setDefaultTweener: function (tweener) { + this._defaultTweener = tweener; + return this; + }, + + getDefaultTweener: function () { + if (this._defaultTweener === null) { + // If a default tweener is required but none exist + // Then we create one + var DefaultTweener = this.Timer; + this._defaultTweener = new DefaultTweener(); + } + + return this._defaultTweener; + }, + + _startDefaultTweener: function () { + var defaultTweener = this.getDefaultTweener(); + this._add(defaultTweener); + return defaultTweener; + } +}; + +module.exports = root.TINA = TINA; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./DoublyList":6}],13:[function(require,module,exports){ @@ -2875,53 +2898,53 @@ Tween.prototype.wait = function (duration) { return this; }; },{"./AbstractTween":1,"./BriefPlayable":3,"./inherit":22}],19:[function(require,module,exports){ -var Player = require('./Player'); -var TINA = require('./TINA'); - -/** - * @classdesc - * Manages the update of a list of playable with respect to a given elapsed time. - */ -function Tweener() { - Player.call(this); - - // TINA is the player for all the tweeners - this._player = TINA; -} -Tweener.prototype = Object.create(Player.prototype); -Tweener.prototype.constructor = Tweener; -module.exports = Tweener; - -Tweener.prototype._reactivate = function (playable) { - if (playable._handle === null) { - // In a tweener, playables are added when reactivated - this._add(playable); - } - - Player.prototype._activate.call(this, playable); -}; - -Tweener.prototype._inactivate = function (playable) { - // In a tweener, playables are removed when inactivated - if (playable._handle !== null) { - // Playable is handled, either by this player or by another one - if (playable._handle.container === this._activePlayables) { - // and adding to remove list - playable._handle = this._playablesToRemove.add(playable._handle); - } - - if (playable._handle.container === this._inactivePlayables) { - // Playable was inactive, removing from inactive playables - playable._handle = this._inactivePlayables.removeByReference(playable._handle); - } - } - - playable._active = false; -}; - -Tweener.prototype.useAsDefault = function () { - TINA.setDefaultTweener(this); - return this; +var Player = require('./Player'); +var TINA = require('./TINA'); + +/** + * @classdesc + * Manages the update of a list of playable with respect to a given elapsed time. + */ +function Tweener() { + Player.call(this); + + // TINA is the player for all the tweeners + this._player = TINA; +} +Tweener.prototype = Object.create(Player.prototype); +Tweener.prototype.constructor = Tweener; +module.exports = Tweener; + +Tweener.prototype._reactivate = function (playable) { + if (playable._handle === null) { + // In a tweener, playables are added when reactivated + this._add(playable); + } + + Player.prototype._activate.call(this, playable); +}; + +Tweener.prototype._inactivate = function (playable) { + // In a tweener, playables are removed when inactivated + if (playable._handle !== null) { + // Playable is handled, either by this player or by another one + if (playable._handle.container === this._activePlayables) { + // and adding to remove list + playable._handle = this._playablesToRemove.add(playable._handle); + } + + if (playable._handle.container === this._inactivePlayables) { + // Playable was inactive, removing from inactive playables + playable._handle = this._inactivePlayables.removeByReference(playable._handle); + } + } + + playable._active = false; +}; + +Tweener.prototype.useAsDefault = function () { + TINA.setDefaultTweener(this); + return this; }; },{"./Player":9,"./TINA":12}],20:[function(require,module,exports){ /** diff --git a/build/tina.min.js b/build/tina.min.js index 01aa41b..f3f2d00 100644 --- a/build/tina.min.js +++ b/build/tina.min.js @@ -20,10 +20,10 @@ function ListNode(t,e,i,s){this.object=t,this.previous=e,this.next=i,this.contai function NestedTween(e,t){if(this instanceof NestedTween==!1)return new NestedTween(e,t);BriefPlayable.call(this),this._tweensPerObject={},this._tweens=[],this._propertyChains={},this._propertyChainStrings=[];for(var r,n,s={},i={},o=0;o0;){var e=this._playablesToRemove.pop();e.object._handle=this._activePlayables.removeByReference(e)}0===this._activePlayables.length&&0===this._inactivePlayables.length&&this._onAllPlayablesRemoved()},Player.prototype.clear=function(){return this._activePlayables.clear(),this._inactivePlayables.clear(),this._playablesToRemove.clear(),this._controls.clear(),this},Player.prototype._warn=function(e){!1===this._silent&&console.warn("[TINA]"+e),this._debug},Player.prototype.silent=function(e){return this._silent=e||!1,this},Player.prototype.debug=function(e){return this._debug=e||!1,this},Player.prototype.stop=function(){for(var e=this._activePlayables.first;null!==e;){var a=e.next;e.object.stop(),e=a}this._handlePlayablesToRemove(),Playable.prototype.stop.call(this)},Player.prototype._activate=function(e){return e._handle.container===this._inactivePlayables?(this._inactivePlayables.removeByReference(e._handle),e._handle=this._activePlayables.addBack(e)):e._handle.container===this._playablesToRemove&&(this._playablesToRemove.removeByReference(e._handle),e._handle=e._handle.object),e._active=!0,!0},Player.prototype._reactivate=Player.prototype._activate,Player.prototype._inactivate=function(e){return null===e._handle?(this._warn("[Player._inactivate] Cannot stop a playable that is not running"),!1):(e._handle.container===this._activePlayables&&(this._activePlayables.removeByReference(e._handle),e._handle=this._inactivePlayables.addBack(e)),e._active=!1,!0)},Player.prototype._updatePlayableList=function(e){this._handlePlayablesToRemove();var a,t;e>0?(a=this._time-e,t=this._time):(a=this._time,t=this._time-e);for(var l=this._inactivePlayables.first;null!==l;){var i=l.object;l=l.next,i._active&&i._overlaps(a,t)&&(this._activate(i),i._start())}},Player.prototype._update=function(e,a){this._updatePlayableList(e);for(var t=this._activePlayables.first;null!==t;t=t.next)void 0===a?t.object._moveTo(this._time,e):t.object._moveTo(this._time,e,a)},Player.prototype._onPlayableChanged=function(){},Player.prototype._onPlayableRemoved=function(){},Player.prototype._onAllPlayablesRemoved=function(){}; +function Player(){Playable.call(this),this._activePlayables=new DoublyList,this._inactivePlayables=new DoublyList,this._playablesToRemove=new DoublyList,this._silent=!0,this._debug=!1}var Playable=require("./Playable"),DoublyList=require("./DoublyList");Player.prototype=Object.create(Playable.prototype),Player.prototype.constructor=Player,module.exports=Player,Player.prototype._add=function(e){return null===e._handle?(e._handle=this._inactivePlayables.add(e),e._player=this,!0):e._handle.container===this._playablesToRemove?(e._handle=this._playablesToRemove.removeByReference(e._handle),e._handle=e._handle.object,!0):e._handle.container===this._activePlayables?(this._warn("[Player._add] Playable is already present, and active"),!1):e._handle.container===this._inactivePlayables?(this._warn("[Player._add] Playable is already present, but inactive (could be starting)"),!1):(this._warn("[Player._add] Playable is used elsewhere"),!1)},Player.prototype._remove=function(e,a){return null===e._handle?(this._warn("[Player._remove] Playable is not being used"),!1):e._handle.container===this._activePlayables?a?(e._handle=this._activePlayables.removeByReference(e._handle),!0):(e._handle=this._playablesToRemove.add(e._handle),!0):e._handle.container===this._inactivePlayables?(e._handle=this._inactivePlayables.removeByReference(e._handle),!0):e._handle.container===this._playablesToRemove?(this._warn("[Player._remove] Playable is already being removed"),!1):(this._warn("[Player._remove] Playable is used elsewhere"),!1)},Player.prototype.remove=function(e){return e._handle.container===this._activePlayables&&e.stop(),this._remove(e,!1),this._onPlayableRemoved(e),this},Player.prototype.removeAll=function(){for(var e=this._activePlayables.first;null!==e;){var a=e.next;e.object.stop(),e=a}return this._handlePlayablesToRemove(),this},Player.prototype.possess=function(e){return null!==e._handle&&(e._handle.container===this._activePlayables||e._handle.container===this._inactivePlayables)},Player.prototype._handlePlayablesToRemove=function(){for(;this._playablesToRemove.length>0;){var e=this._playablesToRemove.pop();e.object._handle=this._activePlayables.removeByReference(e)}0===this._activePlayables.length&&0===this._inactivePlayables.length&&this._onAllPlayablesRemoved()},Player.prototype.clear=function(){return this._activePlayables.clear(),this._inactivePlayables.clear(),this._playablesToRemove.clear(),this._controls.clear(),this},Player.prototype._warn=function(e){!1===this._silent&&console.warn("[TINA]"+e),this._debug},Player.prototype.silent=function(e){return this._silent=e||!1,this},Player.prototype.debug=function(e){return this._debug=e||!1,this},Player.prototype.stop=function(){for(var e=this._activePlayables.first;null!==e;){var a=e.next;e.object.stop(),e=a}this._handlePlayablesToRemove(),Playable.prototype.stop.call(this)},Player.prototype._activate=function(e){return e._handle.container===this._inactivePlayables?(this._inactivePlayables.removeByReference(e._handle),e._handle=this._activePlayables.addBack(e)):e._handle.container===this._playablesToRemove&&(this._playablesToRemove.removeByReference(e._handle),e._handle=e._handle.object),e._active=!0,!0},Player.prototype._reactivate=Player.prototype._activate,Player.prototype._inactivate=function(e){return null===e._handle?(this._warn("[Player._inactivate] Cannot stop a playable that is not running"),!1):(e._handle.container===this._activePlayables&&(this._activePlayables.removeByReference(e._handle),e._handle=this._inactivePlayables.addBack(e)),e._active=!1,!0)},Player.prototype._updatePlayableList=function(e){this._handlePlayablesToRemove();var a,t;e>0?(a=this._time-e,t=this._time):(a=this._time,t=this._time-e);for(var l=this._inactivePlayables.first;null!==l;){var i=l.object;l=l.next,i._active&&i._overlaps(a,t)&&(this._activate(i),i._start())}},Player.prototype._update=function(e,a){this._updatePlayableList(e);for(var t=this._activePlayables.first;null!==t;t=t.next)void 0===a?t.object._moveTo(this._time,e):t.object._moveTo(this._time,e,a)},Player.prototype._onPlayableChanged=function(){},Player.prototype._onPlayableRemoved=function(){},Player.prototype._onAllPlayablesRemoved=function(){}; },{"./DoublyList":6,"./Playable":8}],10:[function(require,module,exports){ function Record(t,e){this.time=t,this.values=e}function ObjectRecorder(t,e,r,i){this.object=t,this.properties=e,this.records=new DoublyList,this.currentRecord=null,this.isIn=!1,this.onIn=r||null,this.onOut=i||null}function Recorder(t){if(this instanceof Recorder==!1)return new Recorder;BriefPlayable.call(this),this._duration=1/0,this._slackTime=0,this._maxRecordingDuration=t||1/0,this._recordedObjects=[],this._recordingObjects={},this._recordingObjectLabels=[],this._recording=!0,this._playing=!1,this._smooth=!1,this._onStartRecording=null,this._onStopRecording=null,this._onStartPlaying=null,this._onStopPlaying=null}var BriefPlayable=require("./BriefPlayable"),DoublyList=require("./DoublyList");ObjectRecorder.prototype.erase=function(t,e){if(e=t;){var o=i.previous;this.records.removeBeReference(i),i=o}return void(null===this.currentRecord.container&&(this.currentRecord=i))}for(var n=this.records.first;null!==n&&n.object.time<=e;){var s=n.next;n.object.time>=t&&this.records.removeBeReference(n),n=s}null===this.currentRecord.container&&(this.currentRecord=n)},ObjectRecorder.prototype.record=function(t,e){if(0!==e||null===this.currentRecord||this.currentRecord.time!==t){for(var r=[],i=0;ithis._maxRecordingDuration?this._maxRecordingDuration:this._time:1/0)*this._iterations/this._speed},Recorder.prototype.smooth=function(t){return this._smooth=t,this},Recorder.prototype.onStartRecording=function(t){return this._onStartRecording=t,this},Recorder.prototype.onStopRecording=function(t){return this._onStopRecording=t,this},Recorder.prototype.onStartPlaying=function(t){return this._onStartPlaying=t,this},Recorder.prototype.onStopPlaying=function(t){return this._onStopPlaying=t,this},Recorder.prototype.reset=function(){return this._recordedObjects=[],this._recordingObjects={},this._recordingObjectLabels=[],this},Recorder.prototype.record=function(t,e,r,i,o){var n=new ObjectRecorder(e,r,i,o);return this._recordingObjects[t]=n,this._recordedObjects.push(n),this._recordingObjectLabels.push(t),this},Recorder.prototype.stopRecordingObject=function(t){delete this._recordingObjects[t];var e=this._recordingObjectLabels.indexOf(t);return-1===e?(console.warn("[Recorder.stopRecordingObject] Trying to stop recording an object that is not being recording:",t),this):(this._recordingObjectLabels.splice(e,1),this)},Recorder.prototype.removeRecordedObject=function(t){var e=this._recordingObjects[t];delete this._recordingObjects[t];var r=this._recordingObjectLabels.indexOf(t);-1!==r&&this._recordingObjectLabels.splice(r,1);var i=this._recordedObjects.indexOf(e);return-1===i?(console.warn("[Recorder.removeRecordedObject] Trying to remove an object that was not recorded:",t),this):(this._recordingObjectLabels.splice(i,1),this)},Recorder.prototype.recording=function(t){return this._recording!==t&&(this._recording=t,!0===this._recording?(!0===this._playing&&(null!==this._onStopPlaying&&this._onStopPlaying(),this._playing=!1),this._duration=1/0,null!==this._player&&this._player._onPlayableChanged(this),null!==this._onStartRecording&&this._onStartRecording()):null!==this._onStopRecording&&this._onStopRecording()),this},Recorder.prototype.playing=function(t){return this._playing!==t&&(this._playing=t,!0===this._playing?(!0===this._recording&&(null!==this._onStopRecording&&this._onStopRecording(),this._recording=!1),this._duration=this._time,this.goToBeginning(this._startTime+this.getDuration()),null!==this._onStartPlaying&&this._onStartPlaying()):null!==this._onStopPlaying&&this._onStopPlaying()),this},Recorder.prototype._update=function(t){var e,r=this._slackTime+this._time;if(!0===this._recording){var i,o;t>0?(i=this._time-this._maxRecordingDuration,o=i>0):(i=this._time,o=i<0);var n=this._recordingObjectLabels.length;for(e=0;e0&&(this._slackTime+=i,this._setStartTime(this._startTime+i),this._player._onPlayableChanged(this))}else if(!0===this._playing){var h=this._recordedObjects.length;for(e=0;e Date: Wed, 2 Aug 2017 19:05:31 +0900 Subject: [PATCH 2/2] Remove duplicated code --- build/tina.js | 22 +++++++--------------- build/tina.min.js | 2 +- src/Playable.js | 22 +++++++--------------- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/build/tina.js b/build/tina.js index be8a982..c5cd3c2 100644 --- a/build/tina.js +++ b/build/tina.js @@ -1169,13 +1169,12 @@ Playable.prototype._start = function () { } }; -Playable.prototype.destroy = function () { +Playable.prototype._stop = function (immediate) { if (this._player === null) { return this; } - // Stopping playable without performing any additional update nor completing - if (this._player._remove(this, true) === false) { + if (this._player._remove(this, immediate) === false) { // Could not be removed return this; } @@ -1187,20 +1186,13 @@ Playable.prototype.destroy = function () { }; Playable.prototype.stop = function () { - if (this._player === null) { - return this; - } - // Stopping playable while letting it perform a final update and complete - if (this._player._remove(this, false) === false) { - // Could not be removed - return this; - } + return this._stop(false); +}; - if (this._onStop !== null) { - this._onStop(); - } - return this; +Playable.prototype.destroy = function () { + // Stopping playable without performing any additional update nor completing + return this._stop(true); }; Playable.prototype.resume = function () { diff --git a/build/tina.min.js b/build/tina.min.js index f3f2d00..e512ade 100644 --- a/build/tina.min.js +++ b/build/tina.min.js @@ -20,7 +20,7 @@ function ListNode(t,e,i,s){this.object=t,this.previous=e,this.next=i,this.contai function NestedTween(e,t){if(this instanceof NestedTween==!1)return new NestedTween(e,t);BriefPlayable.call(this),this._tweensPerObject={},this._tweens=[],this._propertyChains={},this._propertyChainStrings=[];for(var r,n,s={},i={},o=0;o0;){var e=this._playablesToRemove.pop();e.object._handle=this._activePlayables.removeByReference(e)}0===this._activePlayables.length&&0===this._inactivePlayables.length&&this._onAllPlayablesRemoved()},Player.prototype.clear=function(){return this._activePlayables.clear(),this._inactivePlayables.clear(),this._playablesToRemove.clear(),this._controls.clear(),this},Player.prototype._warn=function(e){!1===this._silent&&console.warn("[TINA]"+e),this._debug},Player.prototype.silent=function(e){return this._silent=e||!1,this},Player.prototype.debug=function(e){return this._debug=e||!1,this},Player.prototype.stop=function(){for(var e=this._activePlayables.first;null!==e;){var a=e.next;e.object.stop(),e=a}this._handlePlayablesToRemove(),Playable.prototype.stop.call(this)},Player.prototype._activate=function(e){return e._handle.container===this._inactivePlayables?(this._inactivePlayables.removeByReference(e._handle),e._handle=this._activePlayables.addBack(e)):e._handle.container===this._playablesToRemove&&(this._playablesToRemove.removeByReference(e._handle),e._handle=e._handle.object),e._active=!0,!0},Player.prototype._reactivate=Player.prototype._activate,Player.prototype._inactivate=function(e){return null===e._handle?(this._warn("[Player._inactivate] Cannot stop a playable that is not running"),!1):(e._handle.container===this._activePlayables&&(this._activePlayables.removeByReference(e._handle),e._handle=this._inactivePlayables.addBack(e)),e._active=!1,!0)},Player.prototype._updatePlayableList=function(e){this._handlePlayablesToRemove();var a,t;e>0?(a=this._time-e,t=this._time):(a=this._time,t=this._time-e);for(var l=this._inactivePlayables.first;null!==l;){var i=l.object;l=l.next,i._active&&i._overlaps(a,t)&&(this._activate(i),i._start())}},Player.prototype._update=function(e,a){this._updatePlayableList(e);for(var t=this._activePlayables.first;null!==t;t=t.next)void 0===a?t.object._moveTo(this._time,e):t.object._moveTo(this._time,e,a)},Player.prototype._onPlayableChanged=function(){},Player.prototype._onPlayableRemoved=function(){},Player.prototype._onAllPlayablesRemoved=function(){}; diff --git a/src/Playable.js b/src/Playable.js index b3bdcbf..ae5b3a5 100644 --- a/src/Playable.js +++ b/src/Playable.js @@ -182,13 +182,12 @@ Playable.prototype._start = function () { } }; -Playable.prototype.destroy = function () { +Playable.prototype._stop = function (immediate) { if (this._player === null) { return this; } - // Stopping playable without performing any additional update nor completing - if (this._player._remove(this, true) === false) { + if (this._player._remove(this, immediate) === false) { // Could not be removed return this; } @@ -200,20 +199,13 @@ Playable.prototype.destroy = function () { }; Playable.prototype.stop = function () { - if (this._player === null) { - return this; - } - // Stopping playable while letting it perform a final update and complete - if (this._player._remove(this, false) === false) { - // Could not be removed - return this; - } + return this._stop(false); +}; - if (this._onStop !== null) { - this._onStop(); - } - return this; +Playable.prototype.destroy = function () { + // Stopping playable without performing any additional update nor completing + return this._stop(true); }; Playable.prototype.resume = function () {