From 6a58c2c75eb486216d6651e090274f81d1bfba2f Mon Sep 17 00:00:00 2001 From: cainmartin Date: Wed, 12 Jul 2017 03:16:13 +0100 Subject: [PATCH 1/2] Fix or issue #61 - iterations not working correctly when paused --- build/tina.js | 554 +++++++++++++++++++++--------------------- build/tina.min.js | 4 +- package.json | 80 +++--- src/BriefExtension.js | 4 + src/Playable.js | 484 ++++++++++++++++++------------------ 5 files changed, 567 insertions(+), 559 deletions(-) diff --git a/build/tina.js b/build/tina.js index 8113686..0dbd8f8 100644 --- a/build/tina.js +++ b/build/tina.js @@ -184,280 +184,284 @@ AbstractTween.prototype._validate = function () { return true; }; },{"./Transition":16,"./TransitionRelative":17,"./easing":20,"./interpolation":23}],2:[function(require,module,exports){ - -function BriefExtension() { - // Local duration of the playable, independent from speed and iterations - this._duration = 0; - - // On complete callback - this._onComplete = null; - - // Once complete callback - this._onceComplete = null; - - // Playing options - this._iterations = 1; // Number of times to iterate the playable - this._pingpong = false; // To make the playable go backward on even iterations - this._persist = false; // To keep the playable running instead of completing -} - -module.exports = BriefExtension; - -BriefExtension.prototype.setSpeed = function (speed) { - if (speed === 0) { - if (this._speed !== 0) { - // Setting timeStart as if new speed was 1 - this._startTime += this._time / this._speed - this._time; - } - } else { - if (this._speed === 0) { - // If current speed is 0, - // it corresponds to a virtual speed of 1 - // when it comes to determing where the starting time is - this._startTime += this._time - this._time / speed; - } else { - this._startTime += this._time / this._speed - this._time / speed; - } - } - - this._speed = speed; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } -}; - -BriefExtension.prototype.onComplete = function (onComplete) { this._onComplete = onComplete; return this; }; -BriefExtension.prototype.onceComplete = function (onceComplete) { this._onceComplete = onceComplete; return this; }; - -BriefExtension.prototype.getDuration = function () { - // Duration from outside the playable - return this._duration * this._iterations / this._speed; -}; - -BriefExtension.prototype._setDuration = function (duration) { - this._duration = duration; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } -}; - -BriefExtension.prototype._extendDuration = function (durationExtension) { - this._duration += durationExtension; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } -}; - -BriefExtension.prototype._getEndTime = function () { - if (this._speed > 0) { - return this._startTime + this.getDuration(); - } else if (this._speed < 0) { - return this._startTime; - } else { - return Infinity; - } -}; - -BriefExtension.prototype._setStartTime = function (startTime) { - if (this._speed > 0) { - this._startTime = startTime; - } else if (this._speed < 0) { - this._startTime = startTime - this.getDuration(); - } else { - this._startTime = Infinity; - } -}; - -BriefExtension.prototype._getStartTime = function () { - if (this._speed > 0) { - return this._startTime; - } else if (this._speed < 0) { - return this._startTime + this.getDuration(); - } else { - return -Infinity; - } -}; - -BriefExtension.prototype._isTimeWithin = function (time) { - if (this._speed > 0) { - return (this._startTime < time) && (time < this._startTime + this.getDuration()); - } else if (this._speed < 0) { - return (this._startTime + this.getDuration() < time) && (time < this._startTime); - } else { - return true; - } -}; - -BriefExtension.prototype._overlaps = function (time0, time1) { - if (this._speed > 0) { - return (this._startTime - time1) * (this._startTime + this.getDuration() - time0) <= 0; - } else if (this._speed < 0) { - return (this._startTime + this.getDuration() - time1) * (this._startTime - time0) <= 0; - } else { - return true; - } -}; - -BriefExtension.prototype.goToEnd = function () { - if (this._iterations === Infinity) { - return this.goTo(this._duration / this._speed, 0); - } - - return this.goTo(this.getDuration(), this._iterations - 1); -}; - -BriefExtension.prototype.loop = function () { - return this.iterations(Infinity); -}; - -BriefExtension.prototype.iterations = function (iterations) { - if (iterations < 0) { - console.warn('[BriefExtension.iterations] Number of iterations cannot be negative'); - return this; - } - - this._iterations = iterations; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } - return this; -}; - -BriefExtension.prototype.persist = function (persist) { - this._persist = persist; - return this; -}; - -BriefExtension.prototype.pingpong = function (pingpong) { - this._pingpong = pingpong; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } - return this; -}; - -BriefExtension.prototype._complete = function (overflow) { - if (this._persist === true) { - // Playable is persisting - // i.e it never completes - this._startTime += overflow; - this._player._onPlayableChanged(this); - return; - } - - // Inactivating playable before it completes - // So that the playable can be reactivated again within _onComplete callback - if (this._player._inactivate(this) === false) { - // Could not be completed - return this; - } - - if (this._onComplete !== null) { - this._onComplete(overflow); - } - - if (this._onceComplete !== null) { - var onceComplete = this._onceComplete; - this._onceComplete = null; - onceComplete(overflow); - } -}; - -var epsilon = 1e-6; -BriefExtension.prototype._moveTo = function (time, dt, playerOverflow) { - dt *= this._speed; - - // So many conditions!! - // That is why this extension exists - // i.e playables without durations do not need all those options - - // Computing overflow and clamping time - var overflow; - if (dt !== 0) { - if (this._iterations === 1) { - // Converting into local time (relative to speed and starting time) - this._time = (time - this._startTime) * this._speed; - if (dt > 0) { - if (this._time >= this._duration) { - overflow = this._time - this._duration; - // dt -= overflow; - this._time = this._duration; - } else if (this._time < 0) { - - } - } else if (dt < 0) { - if (this._time <= 0) { - overflow = this._time; - // dt -= overflow; - this._time = 0; - } - } - } else { - time = (time - this._startTime) * this._speed; - - // Iteration at current update - var iteration = time / this._duration; - if (dt > 0) { - if (0 <= iteration && iteration < this._iterations) { - this._time = time % this._duration; - } else { - overflow = (iteration - this._iterations) * this._duration; - this._time = this._duration * (1 - (Math.ceil(this._iterations) - this._iterations)); - } - } else if (dt < 0) { - if (0 <= iteration && iteration < this._iterations) { - this._time = time % this._duration; - } else { - overflow = iteration * this._duration; - this._time = 0; - } - } - - if ((this._pingpong === true)) { - if (overflow === undefined) { - if ((Math.ceil(iteration) & 1) === 0) { - this._time = this._duration - this._time; - } - } else { - if (Math.ceil(this._iterations) === this._iterations) { - if ((Math.ceil(this._iterations) & 1) === 0) { - this._time = this._duration - this._time; - } - } - } - } - } - } - - if (playerOverflow !== undefined && overflow === undefined) { - // Ensuring that the playable overflows when its player overflows - // This conditional is to deal with Murphy's law: - // There is one in a billion chance that a player completes while one of his playable - // does not complete due to stupid rounding errors - if (dt > 0 && this.duration - this._time < epsilon) { - // overflow = Math.max((time - this._startTime) * this._speed - this._duration * this._iterations, overflow); - overflow = playerOverflow; - this._time = this._duration; - } else if (dt < 0 && this._time < epsilon) { - // overflow = Math.min((time - this._startTime) * this._speed, overflow); - overflow = playerOverflow; - this._time = 0; - } - } - - this._update(dt, overflow); - - if (this._onUpdate !== null) { - if (overflow === undefined) { - this._onUpdate(this._time, dt); - } else { - this._onUpdate(this._time, dt - overflow); - } - } - - if (overflow !== undefined) { - this._complete(overflow); - } + +function BriefExtension() { + // Local duration of the playable, independent from speed and iterations + this._duration = 0; + + // On complete callback + this._onComplete = null; + + // Once complete callback + this._onceComplete = null; + + // Playing options + this._iterations = 1; // Number of times to iterate the playable + this._currentIterations = 0; // Number of complete iterations + this._pingpong = false; // To make the playable go backward on even iterations + this._persist = false; // To keep the playable running instead of completing +} + +module.exports = BriefExtension; + +BriefExtension.prototype.setSpeed = function (speed) { + if (speed === 0) { + if (this._speed !== 0) { + // Setting timeStart as if new speed was 1 + this._startTime += this._time / this._speed - this._time; + } + } else { + if (this._speed === 0) { + // If current speed is 0, + // it corresponds to a virtual speed of 1 + // when it comes to determing where the starting time is + this._startTime += this._time - this._time / speed; + } else { + this._startTime += this._time / this._speed - this._time / speed; + } + } + + this._speed = speed; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } +}; + +BriefExtension.prototype.onComplete = function (onComplete) { this._onComplete = onComplete; return this; }; +BriefExtension.prototype.onceComplete = function (onceComplete) { this._onceComplete = onceComplete; return this; }; + +BriefExtension.prototype.getDuration = function () { + // Duration from outside the playable + return this._duration * this._iterations / this._speed; +}; + +BriefExtension.prototype._setDuration = function (duration) { + this._duration = duration; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } +}; + +BriefExtension.prototype._extendDuration = function (durationExtension) { + this._duration += durationExtension; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } +}; + +BriefExtension.prototype._getEndTime = function () { + if (this._speed > 0) { + return this._startTime + this.getDuration(); + } else if (this._speed < 0) { + return this._startTime; + } else { + return Infinity; + } +}; + +BriefExtension.prototype._setStartTime = function (startTime) { + if (this._speed > 0) { + this._startTime = startTime; + } else if (this._speed < 0) { + this._startTime = startTime - this.getDuration(); + } else { + this._startTime = Infinity; + } +}; + +BriefExtension.prototype._getStartTime = function () { + if (this._speed > 0) { + return this._startTime; + } else if (this._speed < 0) { + return this._startTime + this.getDuration(); + } else { + return -Infinity; + } +}; + +BriefExtension.prototype._isTimeWithin = function (time) { + if (this._speed > 0) { + return (this._startTime < time) && (time < this._startTime + this.getDuration()); + } else if (this._speed < 0) { + return (this._startTime + this.getDuration() < time) && (time < this._startTime); + } else { + return true; + } +}; + +BriefExtension.prototype._overlaps = function (time0, time1) { + if (this._speed > 0) { + return (this._startTime - time1) * (this._startTime + this.getDuration() - time0) <= 0; + } else if (this._speed < 0) { + return (this._startTime + this.getDuration() - time1) * (this._startTime - time0) <= 0; + } else { + return true; + } +}; + +BriefExtension.prototype.goToEnd = function () { + if (this._iterations === Infinity) { + return this.goTo(this._duration / this._speed, 0); + } + + return this.goTo(this.getDuration(), this._iterations - 1); +}; + +BriefExtension.prototype.loop = function () { + return this.iterations(Infinity); +}; + +BriefExtension.prototype.iterations = function (iterations) { + if (iterations < 0) { + console.warn('[BriefExtension.iterations] Number of iterations cannot be negative'); + return this; + } + + this._iterations = iterations; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } + return this; +}; + +BriefExtension.prototype.persist = function (persist) { + this._persist = persist; + return this; +}; + +BriefExtension.prototype.pingpong = function (pingpong) { + this._pingpong = pingpong; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } + return this; +}; + +BriefExtension.prototype._complete = function (overflow) { + if (this._persist === true) { + // Playable is persisting + // i.e it never completes + this._startTime += overflow; + this._player._onPlayableChanged(this); + return; + } + + // Inactivating playable before it completes + // So that the playable can be reactivated again within _onComplete callback + if (this._player._inactivate(this) === false) { + // Could not be completed + return this; + } + + if (this._onComplete !== null) { + this._onComplete(overflow); + } + + if (this._onceComplete !== null) { + var onceComplete = this._onceComplete; + this._onceComplete = null; + onceComplete(overflow); + } +}; + +var epsilon = 1e-6; +BriefExtension.prototype._moveTo = function (time, dt, playerOverflow) { + dt *= this._speed; + + // So many conditions!! + // That is why this extension exists + // i.e playables without durations do not need all those options + + // Computing overflow and clamping time + var overflow; + if (dt !== 0) { + if (this._iterations === 1) { + // Converting into local time (relative to speed and starting time) + this._time = (time - this._startTime) * this._speed; + if (dt > 0) { + if (this._time >= this._duration) { + overflow = this._time - this._duration; + // dt -= overflow; + this._time = this._duration; + } else if (this._time < 0) { + + } + } else if (dt < 0) { + if (this._time <= 0) { + overflow = this._time; + // dt -= overflow; + this._time = 0; + } + } + } else { + time = (time - this._startTime) * this._speed; + + // Iteration at current update + var iteration = time / this._duration; + // Track the current number of iterations + this._currentIterations = Math.floor(iteration); + + if (dt > 0) { + if (0 <= iteration && iteration < this._iterations) { + this._time = time % this._duration; + } else { + overflow = (iteration - this._iterations) * this._duration; + this._time = this._duration * (1 - (Math.ceil(this._iterations) - this._iterations)); + } + } else if (dt < 0) { + if (0 <= iteration && iteration < this._iterations) { + this._time = time % this._duration; + } else { + overflow = iteration * this._duration; + this._time = 0; + } + } + + if ((this._pingpong === true)) { + if (overflow === undefined) { + if ((Math.ceil(iteration) & 1) === 0) { + this._time = this._duration - this._time; + } + } else { + if (Math.ceil(this._iterations) === this._iterations) { + if ((Math.ceil(this._iterations) & 1) === 0) { + this._time = this._duration - this._time; + } + } + } + } + } + } + + if (playerOverflow !== undefined && overflow === undefined) { + // Ensuring that the playable overflows when its player overflows + // This conditional is to deal with Murphy's law: + // There is one in a billion chance that a player completes while one of his playable + // does not complete due to stupid rounding errors + if (dt > 0 && this.duration - this._time < epsilon) { + // overflow = Math.max((time - this._startTime) * this._speed - this._duration * this._iterations, overflow); + overflow = playerOverflow; + this._time = this._duration; + } else if (dt < 0 && this._time < epsilon) { + // overflow = Math.min((time - this._startTime) * this._speed, overflow); + overflow = playerOverflow; + this._time = 0; + } + } + + this._update(dt, overflow); + + if (this._onUpdate !== null) { + if (overflow === undefined) { + this._onUpdate(this._time, dt); + } else { + this._onUpdate(this._time, dt - overflow); + } + } + + if (overflow !== undefined) { + this._complete(overflow); + } }; },{}],3:[function(require,module,exports){ var inherit = require('./inherit'); @@ -1188,7 +1192,7 @@ Playable.prototype.resume = function () { } // Resetting starting time so that the playable starts off where it left off - this._startTime = this._player._time - this._time / this._speed; + this._startTime = this._player._time - (this._time + (this._duration * this._currentIterations)) / this._speed; if (this._onResume !== null) { this._onResume(); diff --git a/build/tina.min.js b/build/tina.min.js index 54ef13a..01aa41b 100644 --- a/build/tina.min.js +++ b/build/tina.min.js @@ -2,7 +2,7 @@ function Temporisation(t,i,n,s){this.start=t,this.end=t+i,this.duration=i,this.properties=s,this.to=n}function AbstractTween(t,i){if(this._object=t,(null===i||void 0===i)&&t instanceof Array){i=[];for(var n=0;n0&&(this._transitions[0].from=t),this},AbstractTween.prototype._setFrom=function(){this._from={};for(var t=0;t0?!0===this._relative?this._setFrom():this._transitions[this._transitions.length-1].to:null===this._from?this._setFrom():this._from},AbstractTween.prototype.to=function(t,i,n,s,e){"string"==typeof n&&(void 0===easingFunctions[n]?(console.warn("[AbstractTween.to] Given easing does not exist"),n=void 0):n=easingFunctions[n]);var r=this._getLastTransitionEnding(),o=!0===this._relative?TransitionRelative:Transition,a=new o(this._properties,r,t,this._duration,i,n,s,this._interpolations,e);return this._transitions.push(a),this._duration+=i,this},AbstractTween.prototype.wait=function(t){var i=this._getLastTransitionEnding();return this._transitions.push(new Temporisation(this._duration,t,i,this._properties)),this._duration+=t,this},AbstractTween.prototype._update=function(){for(var t=this._transitions[this._index];t.end<=this._time;){if(this._index===this._transitions.length-1)return void t.update(this._object,1);!0===this._relative&&t.update(this._object,1),t=this._transitions[++this._index]}for(;this._time<=t.start;){if(0===this._index)return void t.update(this._object,0);!0===this._relative&&t.update(this._object,0),t=this._transitions[--this._index]}t.update(this._object,(this._time-t.start)/t.duration)},AbstractTween.prototype._validate=function(){return 0!==this._transitions.length||(console.warn("[AbstractTween._validate] Cannot start a tween with no transition:",this),!1)}; },{"./Transition":16,"./TransitionRelative":17,"./easing":20,"./interpolation":23}],2:[function(require,module,exports){ -function BriefExtension(){this._duration=0,this._onComplete=null,this._onceComplete=null,this._iterations=1,this._pingpong=!1,this._persist=!1}module.exports=BriefExtension,BriefExtension.prototype.setSpeed=function(t){0===t?0!==this._speed&&(this._startTime+=this._time/this._speed-this._time):0===this._speed?this._startTime+=this._time-this._time/t:this._startTime+=this._time/this._speed-this._time/t,this._speed=t,null!==this._player&&this._player._onPlayableChanged(this)},BriefExtension.prototype.onComplete=function(t){return this._onComplete=t,this},BriefExtension.prototype.onceComplete=function(t){return this._onceComplete=t,this},BriefExtension.prototype.getDuration=function(){return this._duration*this._iterations/this._speed},BriefExtension.prototype._setDuration=function(t){this._duration=t,null!==this._player&&this._player._onPlayableChanged(this)},BriefExtension.prototype._extendDuration=function(t){this._duration+=t,null!==this._player&&this._player._onPlayableChanged(this)},BriefExtension.prototype._getEndTime=function(){return this._speed>0?this._startTime+this.getDuration():this._speed<0?this._startTime:1/0},BriefExtension.prototype._setStartTime=function(t){this._speed>0?this._startTime=t:this._speed<0?this._startTime=t-this.getDuration():this._startTime=1/0},BriefExtension.prototype._getStartTime=function(){return this._speed>0?this._startTime:this._speed<0?this._startTime+this.getDuration():-1/0},BriefExtension.prototype._isTimeWithin=function(t){return this._speed>0?this._startTime0?(this._startTime-i)*(this._startTime+this.getDuration()-t)<=0:!(this._speed<0)||(this._startTime+this.getDuration()-i)*(this._startTime-t)<=0},BriefExtension.prototype.goToEnd=function(){return this._iterations===1/0?this.goTo(this._duration/this._speed,0):this.goTo(this.getDuration(),this._iterations-1)},BriefExtension.prototype.loop=function(){return this.iterations(1/0)},BriefExtension.prototype.iterations=function(t){return t<0?(console.warn("[BriefExtension.iterations] Number of iterations cannot be negative"),this):(this._iterations=t,null!==this._player&&this._player._onPlayableChanged(this),this)},BriefExtension.prototype.persist=function(t){return this._persist=t,this},BriefExtension.prototype.pingpong=function(t){return this._pingpong=t,null!==this._player&&this._player._onPlayableChanged(this),this},BriefExtension.prototype._complete=function(t){if(!0===this._persist)return this._startTime+=t,void this._player._onPlayableChanged(this);if(!1===this._player._inactivate(this))return this;if(null!==this._onComplete&&this._onComplete(t),null!==this._onceComplete){var i=this._onceComplete;this._onceComplete=null,i(t)}};var epsilon=1e-6;BriefExtension.prototype._moveTo=function(t,i,e){i*=this._speed;var s;if(0!==i)if(1===this._iterations)this._time=(t-this._startTime)*this._speed,i>0?this._time>=this._duration?(s=this._time-this._duration,this._time=this._duration):this._time:i<0&&this._time<=0&&(s=this._time,this._time=0);else{t=(t-this._startTime)*this._speed;var n=t/this._duration;i>0?0<=n&&n0&&this.duration-this._time0?this._startTime+this.getDuration():this._speed<0?this._startTime:1/0},BriefExtension.prototype._setStartTime=function(t){this._speed>0?this._startTime=t:this._speed<0?this._startTime=t-this.getDuration():this._startTime=1/0},BriefExtension.prototype._getStartTime=function(){return this._speed>0?this._startTime:this._speed<0?this._startTime+this.getDuration():-1/0},BriefExtension.prototype._isTimeWithin=function(t){return this._speed>0?this._startTime0?(this._startTime-i)*(this._startTime+this.getDuration()-t)<=0:!(this._speed<0)||(this._startTime+this.getDuration()-i)*(this._startTime-t)<=0},BriefExtension.prototype.goToEnd=function(){return this._iterations===1/0?this.goTo(this._duration/this._speed,0):this.goTo(this.getDuration(),this._iterations-1)},BriefExtension.prototype.loop=function(){return this.iterations(1/0)},BriefExtension.prototype.iterations=function(t){return t<0?(console.warn("[BriefExtension.iterations] Number of iterations cannot be negative"),this):(this._iterations=t,null!==this._player&&this._player._onPlayableChanged(this),this)},BriefExtension.prototype.persist=function(t){return this._persist=t,this},BriefExtension.prototype.pingpong=function(t){return this._pingpong=t,null!==this._player&&this._player._onPlayableChanged(this),this},BriefExtension.prototype._complete=function(t){if(!0===this._persist)return this._startTime+=t,void this._player._onPlayableChanged(this);if(!1===this._player._inactivate(this))return this;if(null!==this._onComplete&&this._onComplete(t),null!==this._onceComplete){var i=this._onceComplete;this._onceComplete=null,i(t)}};var epsilon=1e-6;BriefExtension.prototype._moveTo=function(t,i,e){i*=this._speed;var s;if(0!==i)if(1===this._iterations)this._time=(t-this._startTime)*this._speed,i>0?this._time>=this._duration?(s=this._time-this._duration,this._time=this._duration):this._time:i<0&&this._time<=0&&(s=this._time,this._time=0);else{t=(t-this._startTime)*this._speed;var n=t/this._duration;this._currentIterations=Math.floor(n),i>0?0<=n&&n0&&this.duration-this._time0;){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/package.json b/package.json index 63366ab..8435e7c 100644 --- a/package.json +++ b/package.json @@ -1,40 +1,40 @@ -{ - "name": "tina", - "version": "0.3.22", - "description": "Tweening and INterpolations for Animation", - "main": "src/index.js", - "scripts": { - "build": "jshint src && browserify -t uglifyify src/index.js -o build/tina.min.js && browserify src/index.js -o build/tina.js", - "test": "jshint src" - }, - "repository": { - "type": "git", - "url": "https://github.com/Wizcorp/tina.git" - }, - "devDependencies": { - "jshint": "~2.8.0", - "uglifyify": "~3.0.1", - "browserify": "~11.0.0" - }, - "keywords": [ - "tween", - "tweener", - "tweening", - "animation", - "easing", - "interpolation", - "animation", - "timeline", - "sequence", - "recorder", - "gsap", - "tweenjs", - "tween.js" - ], - "author": "bchevalier", - "license": "MIT", - "bugs": { - "url": "https://github.com/Wizcorp/tina/issues" - }, - "homepage": "https://github.com/Wizcorp/tina" -} +{ + "name": "tina", + "version": "0.3.23", + "description": "Tweening and INterpolations for Animation", + "main": "src/index.js", + "scripts": { + "build": "jshint src && browserify -t uglifyify src/index.js -o build/tina.min.js && browserify src/index.js -o build/tina.js", + "test": "jshint src" + }, + "repository": { + "type": "git", + "url": "https://github.com/Wizcorp/tina.git" + }, + "devDependencies": { + "jshint": "~2.8.0", + "uglifyify": "~3.0.1", + "browserify": "~11.0.0" + }, + "keywords": [ + "tween", + "tweener", + "tweening", + "animation", + "easing", + "interpolation", + "animation", + "timeline", + "sequence", + "recorder", + "gsap", + "tweenjs", + "tween.js" + ], + "author": "bchevalier", + "license": "MIT", + "bugs": { + "url": "https://github.com/Wizcorp/tina/issues" + }, + "homepage": "https://github.com/Wizcorp/tina" +} diff --git a/src/BriefExtension.js b/src/BriefExtension.js index 9ca32a6..a8daa3a 100644 --- a/src/BriefExtension.js +++ b/src/BriefExtension.js @@ -11,6 +11,7 @@ function BriefExtension() { // Playing options this._iterations = 1; // Number of times to iterate the playable + this._currentIterations = 0; // Number of complete iterations this._pingpong = false; // To make the playable go backward on even iterations this._persist = false; // To keep the playable running instead of completing } @@ -211,6 +212,9 @@ BriefExtension.prototype._moveTo = function (time, dt, playerOverflow) { // Iteration at current update var iteration = time / this._duration; + // Track the current number of iterations + this._currentIterations = Math.floor(iteration); + if (dt > 0) { if (0 <= iteration && iteration < this._iterations) { this._time = time % this._duration; diff --git a/src/Playable.js b/src/Playable.js index 3c502d1..afe41d1 100644 --- a/src/Playable.js +++ b/src/Playable.js @@ -1,243 +1,243 @@ -/** @class */ -function Playable() { - // Player component handling this playable - this._player = null; - - // Handle of the playable within its player - this._handle = null; - - // An inactive playable cannot run even within its time boundaries when its parent is running - this._active = true; - - // Starting time, is global (relative to its player time) - this._startTime = 0; - - // Current time, is local (relative to starting time) - // i.e this._time === 0 implies this._player._time === this._startTime - this._time = 0; - - // Playing speed of the playable - this._speed = 1; - - // Callbacks - this._onStart = null; - this._onPause = null; - this._onResume = null; - this._onUpdate = null; - this._onStop = null; -} - -module.exports = Playable; - -Object.defineProperty(Playable.prototype, 'speed', { - get: function () { return this._speed; }, - set: function (speed) { - this.setSpeed(speed); - } -}); - -Object.defineProperty(Playable.prototype, 'time', { - get: function () { return this._time; }, - set: function (time) { - this.goTo(time); - } -}); - -Playable.prototype.onStart = function (onStart) { this._onStart = onStart; return this; }; -Playable.prototype.onUpdate = function (onUpdate) { this._onUpdate = onUpdate; return this; }; -Playable.prototype.onStop = function (onStop) { this._onStop = onStop; return this; }; -Playable.prototype.onPause = function (onPause) { this._onPause = onPause; return this; }; -Playable.prototype.onResume = function (onResume) { this._onResume = onResume; return this; }; - -Playable.prototype.tweener = function (tweener) { - if (tweener === null || tweener === undefined) { - console.warn('[Playable.tweener] Given tweener is invalid:', tweener); - return this; - } - - this._player = tweener; - return this; -}; - -Playable.prototype.setSpeed = function (speed) { - if (speed < 0) { - console.warn('[Playable.speed] This playable cannot have negative speed'); - return; - } - - if (speed === 0) { - if (this._speed !== 0) { - // Setting timeStart as if new speed was 1 - this._startTime += this._time / this._speed - this._time; - } - } else { - if (this._speed === 0) { - // If current speed is 0, - // it corresponds to a virtual speed of 1 - // when it comes to determing where the starting time is - this._startTime += this._time - this._time / speed; - } else { - this._startTime += this._time / this._speed - this._time / speed; - } - } - - this._speed = speed; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } -}; - -Playable.prototype.goTo = function (timePosition, iteration) { - if (this._iterations === 1) { - if(this._speed === 0) { - // Speed is virtually 1 - this._startTime += this._time - timePosition; - } else { - // Offsetting starting time with respect to current time and speed - this._startTime += (this._time - timePosition) / this._speed; - } - } else { - iteration = iteration || 0; - if(this._speed === 0) { - // Speed is virtually 1 - this._startTime += this._time - timePosition - iteration * this._duration; - } else { - // Offsetting starting time with respect to current time and speed - this._startTime += (this._time - timePosition - iteration * this._duration) / this._speed; - } - } - - this._time = timePosition; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } - return this; -}; - -Playable.prototype.goToBeginning = function () { - return this.goTo(0, 0); -}; - -Playable.prototype.getDuration = function () { - return Infinity; -}; - -Playable.prototype._getEndTime = function () { - return Infinity; -}; - -Playable.prototype._setStartTime = function (startTime) { - this._startTime = startTime; -}; - -Playable.prototype._getStartTime = function () { - return this._startTime; -}; - -Playable.prototype._isWithin = function (time) { - return this._startTime < time; -}; - -Playable.prototype._overlaps = function (time0, time1) { - return (time0 - this._startTime) * (time1 - this._startTime) <= 0; -}; - -Playable.prototype.rewind = function () { - this.goTo(0, 0); - return this; -}; - -Playable.prototype.delay = function (delay) { - return this.start(-delay); -}; - -Playable.prototype.start = function (timeOffset) { - if (this._player === null) { - this._player = TINA._startDefaultTweener(); - } - - if (this._validate() === false) { - // Did not pass validation - return this; - } - - if (timeOffset === undefined || timeOffset === null) { - timeOffset = 0; - } - - this._time = timeOffset; - this._startTime = this._player._time - timeOffset; - - if (this._player._reactivate(this) === false) { - // Could not be added to player - return this; - } - - return this; -}; - -Playable.prototype._start = function () { - if (this._onStart !== null) { - this._onStart(); - } -}; - -Playable.prototype.stop = function () { - if (this._player === null) { - return this; - } - - // Stopping playable without performing any additional update nor completing - if (this._player._remove(this) === false) { - // Could not be removed - return this; - } - - if (this._onStop !== null) { - this._onStop(); - } - return this; -}; - -Playable.prototype.resume = function () { - if (this._player === null || this._player._reactivate(this) === false) { - // Could not be resumed - return this; - } - - // Resetting starting time so that the playable starts off where it left off - this._startTime = this._player._time - this._time / this._speed; - - if (this._onResume !== null) { - this._onResume(); - } - return this; -}; - -Playable.prototype.pause = function () { - if (this._player === null || this._player._inactivate(this) === false) { - // Could not be paused - return this; - } - - if (this._onPause !== null) { - this._onPause(); - } - - return this; -}; - -Playable.prototype._moveTo = function (time, dt) { - dt *= this._speed; - - this._time = (time - this._startTime) * this._speed; - this._update(dt); - - if (this._onUpdate !== null) { - this._onUpdate(this._time, dt); - } -}; - -// Overridable methods -Playable.prototype._update = function () {}; +/** @class */ +function Playable() { + // Player component handling this playable + this._player = null; + + // Handle of the playable within its player + this._handle = null; + + // An inactive playable cannot run even within its time boundaries when its parent is running + this._active = true; + + // Starting time, is global (relative to its player time) + this._startTime = 0; + + // Current time, is local (relative to starting time) + // i.e this._time === 0 implies this._player._time === this._startTime + this._time = 0; + + // Playing speed of the playable + this._speed = 1; + + // Callbacks + this._onStart = null; + this._onPause = null; + this._onResume = null; + this._onUpdate = null; + this._onStop = null; +} + +module.exports = Playable; + +Object.defineProperty(Playable.prototype, 'speed', { + get: function () { return this._speed; }, + set: function (speed) { + this.setSpeed(speed); + } +}); + +Object.defineProperty(Playable.prototype, 'time', { + get: function () { return this._time; }, + set: function (time) { + this.goTo(time); + } +}); + +Playable.prototype.onStart = function (onStart) { this._onStart = onStart; return this; }; +Playable.prototype.onUpdate = function (onUpdate) { this._onUpdate = onUpdate; return this; }; +Playable.prototype.onStop = function (onStop) { this._onStop = onStop; return this; }; +Playable.prototype.onPause = function (onPause) { this._onPause = onPause; return this; }; +Playable.prototype.onResume = function (onResume) { this._onResume = onResume; return this; }; + +Playable.prototype.tweener = function (tweener) { + if (tweener === null || tweener === undefined) { + console.warn('[Playable.tweener] Given tweener is invalid:', tweener); + return this; + } + + this._player = tweener; + return this; +}; + +Playable.prototype.setSpeed = function (speed) { + if (speed < 0) { + console.warn('[Playable.speed] This playable cannot have negative speed'); + return; + } + + if (speed === 0) { + if (this._speed !== 0) { + // Setting timeStart as if new speed was 1 + this._startTime += this._time / this._speed - this._time; + } + } else { + if (this._speed === 0) { + // If current speed is 0, + // it corresponds to a virtual speed of 1 + // when it comes to determing where the starting time is + this._startTime += this._time - this._time / speed; + } else { + this._startTime += this._time / this._speed - this._time / speed; + } + } + + this._speed = speed; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } +}; + +Playable.prototype.goTo = function (timePosition, iteration) { + if (this._iterations === 1) { + if(this._speed === 0) { + // Speed is virtually 1 + this._startTime += this._time - timePosition; + } else { + // Offsetting starting time with respect to current time and speed + this._startTime += (this._time - timePosition) / this._speed; + } + } else { + iteration = iteration || 0; + if(this._speed === 0) { + // Speed is virtually 1 + this._startTime += this._time - timePosition - iteration * this._duration; + } else { + // Offsetting starting time with respect to current time and speed + this._startTime += (this._time - timePosition - iteration * this._duration) / this._speed; + } + } + + this._time = timePosition; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } + return this; +}; + +Playable.prototype.goToBeginning = function () { + return this.goTo(0, 0); +}; + +Playable.prototype.getDuration = function () { + return Infinity; +}; + +Playable.prototype._getEndTime = function () { + return Infinity; +}; + +Playable.prototype._setStartTime = function (startTime) { + this._startTime = startTime; +}; + +Playable.prototype._getStartTime = function () { + return this._startTime; +}; + +Playable.prototype._isWithin = function (time) { + return this._startTime < time; +}; + +Playable.prototype._overlaps = function (time0, time1) { + return (time0 - this._startTime) * (time1 - this._startTime) <= 0; +}; + +Playable.prototype.rewind = function () { + this.goTo(0, 0); + return this; +}; + +Playable.prototype.delay = function (delay) { + return this.start(-delay); +}; + +Playable.prototype.start = function (timeOffset) { + if (this._player === null) { + this._player = TINA._startDefaultTweener(); + } + + if (this._validate() === false) { + // Did not pass validation + return this; + } + + if (timeOffset === undefined || timeOffset === null) { + timeOffset = 0; + } + + this._time = timeOffset; + this._startTime = this._player._time - timeOffset; + + if (this._player._reactivate(this) === false) { + // Could not be added to player + return this; + } + + return this; +}; + +Playable.prototype._start = function () { + if (this._onStart !== null) { + this._onStart(); + } +}; + +Playable.prototype.stop = function () { + if (this._player === null) { + return this; + } + + // Stopping playable without performing any additional update nor completing + if (this._player._remove(this) === false) { + // Could not be removed + return this; + } + + if (this._onStop !== null) { + this._onStop(); + } + return this; +}; + +Playable.prototype.resume = function () { + if (this._player === null || this._player._reactivate(this) === false) { + // Could not be resumed + return this; + } + + // Resetting starting time so that the playable starts off where it left off + this._startTime = this._player._time - (this._time + (this._duration * this._currentIterations)) / this._speed; + + if (this._onResume !== null) { + this._onResume(); + } + return this; +}; + +Playable.prototype.pause = function () { + if (this._player === null || this._player._inactivate(this) === false) { + // Could not be paused + return this; + } + + if (this._onPause !== null) { + this._onPause(); + } + + return this; +}; + +Playable.prototype._moveTo = function (time, dt) { + dt *= this._speed; + + this._time = (time - this._startTime) * this._speed; + this._update(dt); + + if (this._onUpdate !== null) { + this._onUpdate(this._time, dt); + } +}; + +// Overridable methods +Playable.prototype._update = function () {}; Playable.prototype._validate = function () {}; \ No newline at end of file From 5fc4eb9179f369fbeb2ba76170f180ccc98a4f03 Mon Sep 17 00:00:00 2001 From: cainmartin Date: Wed, 12 Jul 2017 04:25:23 +0100 Subject: [PATCH 2/2] Fixed line endings / added .editorconfig file --- .editorconfig | 25 +++ build/tina.js | 512 ++++++++++++++++++++++--------------------- src/BriefPlayable.js | 28 +-- src/Playable.js | 486 ++++++++++++++++++++-------------------- 4 files changed, 539 insertions(+), 512 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..79ba7a8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,25 @@ +# EditorConfig is awesome: http://EditorConfig.org +# Download a plugin for your favorite editor from http://editorconfig.org/#download + +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true + +[*.{html}] +insert_final_newline = true +indent_style = tab + +[*.js] +insert_final_newline = true +indent_style = tab + +[*.json] +insert_final_newline = false +indent_style = tab + +[package.json] +indent_style = space +indent_size = 2 diff --git a/build/tina.js b/build/tina.js index 0dbd8f8..1c5561a 100644 --- a/build/tina.js +++ b/build/tina.js @@ -464,20 +464,21 @@ BriefExtension.prototype._moveTo = function (time, dt, playerOverflow) { } }; },{}],3:[function(require,module,exports){ -var inherit = require('./inherit'); -var Playable = require('./Playable'); -var BriefExtension = require('./BriefExtension'); - -function BriefPlayable() { - Playable.call(this); - BriefExtension.call(this); -} - -BriefPlayable.prototype = Object.create(Playable.prototype); -BriefPlayable.prototype.constructor = BriefPlayable; -inherit(BriefPlayable, BriefExtension); - +var inherit = require('./inherit'); +var Playable = require('./Playable'); +var BriefExtension = require('./BriefExtension'); + +function BriefPlayable() { + Playable.call(this); + BriefExtension.call(this); +} + +BriefPlayable.prototype = Object.create(Playable.prototype); +BriefPlayable.prototype.constructor = BriefPlayable; +inherit(BriefPlayable, BriefExtension); + module.exports = BriefPlayable; + },{"./BriefExtension":2,"./Playable":8,"./inherit":22}],4:[function(require,module,exports){ var inherit = require('./inherit'); var Player = require('./Player'); @@ -984,249 +985,250 @@ NestedTween.prototype._update = function () { } }; },{"./AbstractTween":1,"./BriefPlayable":3}],8:[function(require,module,exports){ -/** @class */ -function Playable() { - // Player component handling this playable - this._player = null; - - // Handle of the playable within its player - this._handle = null; - - // An inactive playable cannot run even within its time boundaries when its parent is running - this._active = true; - - // Starting time, is global (relative to its player time) - this._startTime = 0; - - // Current time, is local (relative to starting time) - // i.e this._time === 0 implies this._player._time === this._startTime - this._time = 0; - - // Playing speed of the playable - this._speed = 1; - - // Callbacks - this._onStart = null; - this._onPause = null; - this._onResume = null; - this._onUpdate = null; - this._onStop = null; -} - -module.exports = Playable; - -Object.defineProperty(Playable.prototype, 'speed', { - get: function () { return this._speed; }, - set: function (speed) { - this.setSpeed(speed); - } -}); - -Object.defineProperty(Playable.prototype, 'time', { - get: function () { return this._time; }, - set: function (time) { - this.goTo(time); - } -}); - -Playable.prototype.onStart = function (onStart) { this._onStart = onStart; return this; }; -Playable.prototype.onUpdate = function (onUpdate) { this._onUpdate = onUpdate; return this; }; -Playable.prototype.onStop = function (onStop) { this._onStop = onStop; return this; }; -Playable.prototype.onPause = function (onPause) { this._onPause = onPause; return this; }; -Playable.prototype.onResume = function (onResume) { this._onResume = onResume; return this; }; - -Playable.prototype.tweener = function (tweener) { - if (tweener === null || tweener === undefined) { - console.warn('[Playable.tweener] Given tweener is invalid:', tweener); - return this; - } - - this._player = tweener; - return this; -}; - -Playable.prototype.setSpeed = function (speed) { - if (speed < 0) { - console.warn('[Playable.speed] This playable cannot have negative speed'); - return; - } - - if (speed === 0) { - if (this._speed !== 0) { - // Setting timeStart as if new speed was 1 - this._startTime += this._time / this._speed - this._time; - } - } else { - if (this._speed === 0) { - // If current speed is 0, - // it corresponds to a virtual speed of 1 - // when it comes to determing where the starting time is - this._startTime += this._time - this._time / speed; - } else { - this._startTime += this._time / this._speed - this._time / speed; - } - } - - this._speed = speed; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } -}; - -Playable.prototype.goTo = function (timePosition, iteration) { - if (this._iterations === 1) { - if(this._speed === 0) { - // Speed is virtually 1 - this._startTime += this._time - timePosition; - } else { - // Offsetting starting time with respect to current time and speed - this._startTime += (this._time - timePosition) / this._speed; - } - } else { - iteration = iteration || 0; - if(this._speed === 0) { - // Speed is virtually 1 - this._startTime += this._time - timePosition - iteration * this._duration; - } else { - // Offsetting starting time with respect to current time and speed - this._startTime += (this._time - timePosition - iteration * this._duration) / this._speed; - } - } - - this._time = timePosition; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } - return this; -}; - -Playable.prototype.goToBeginning = function () { - return this.goTo(0, 0); -}; - -Playable.prototype.getDuration = function () { - return Infinity; -}; - -Playable.prototype._getEndTime = function () { - return Infinity; -}; - -Playable.prototype._setStartTime = function (startTime) { - this._startTime = startTime; -}; - -Playable.prototype._getStartTime = function () { - return this._startTime; -}; - -Playable.prototype._isWithin = function (time) { - return this._startTime < time; -}; - -Playable.prototype._overlaps = function (time0, time1) { - return (time0 - this._startTime) * (time1 - this._startTime) <= 0; -}; - -Playable.prototype.rewind = function () { - this.goTo(0, 0); - return this; -}; - -Playable.prototype.delay = function (delay) { - return this.start(-delay); -}; - -Playable.prototype.start = function (timeOffset) { - if (this._player === null) { - this._player = TINA._startDefaultTweener(); - } - - if (this._validate() === false) { - // Did not pass validation - return this; - } - - if (timeOffset === undefined || timeOffset === null) { - timeOffset = 0; - } - - this._time = timeOffset; - this._startTime = this._player._time - timeOffset; - - if (this._player._reactivate(this) === false) { - // Could not be added to player - return this; - } - - return this; -}; - -Playable.prototype._start = function () { - if (this._onStart !== null) { - this._onStart(); - } -}; - -Playable.prototype.stop = function () { - if (this._player === null) { - return this; - } - - // Stopping playable without performing any additional update nor completing - if (this._player._remove(this) === false) { - // Could not be removed - return this; - } - - if (this._onStop !== null) { - this._onStop(); - } - return this; -}; - -Playable.prototype.resume = function () { - if (this._player === null || this._player._reactivate(this) === false) { - // Could not be resumed - return this; - } - - // Resetting starting time so that the playable starts off where it left off - this._startTime = this._player._time - (this._time + (this._duration * this._currentIterations)) / this._speed; - - if (this._onResume !== null) { - this._onResume(); - } - return this; -}; - -Playable.prototype.pause = function () { - if (this._player === null || this._player._inactivate(this) === false) { - // Could not be paused - return this; - } - - if (this._onPause !== null) { - this._onPause(); - } - - return this; -}; - -Playable.prototype._moveTo = function (time, dt) { - dt *= this._speed; - - this._time = (time - this._startTime) * this._speed; - this._update(dt); - - if (this._onUpdate !== null) { - this._onUpdate(this._time, dt); - } -}; - -// Overridable methods -Playable.prototype._update = function () {}; +/** @class */ +function Playable() { + // Player component handling this playable + this._player = null; + + // Handle of the playable within its player + this._handle = null; + + // An inactive playable cannot run even within its time boundaries when its parent is running + this._active = true; + + // Starting time, is global (relative to its player time) + this._startTime = 0; + + // Current time, is local (relative to starting time) + // i.e this._time === 0 implies this._player._time === this._startTime + this._time = 0; + + // Playing speed of the playable + this._speed = 1; + + // Callbacks + this._onStart = null; + this._onPause = null; + this._onResume = null; + this._onUpdate = null; + this._onStop = null; +} + +module.exports = Playable; + +Object.defineProperty(Playable.prototype, 'speed', { + get: function () { return this._speed; }, + set: function (speed) { + this.setSpeed(speed); + } +}); + +Object.defineProperty(Playable.prototype, 'time', { + get: function () { return this._time; }, + set: function (time) { + this.goTo(time); + } +}); + +Playable.prototype.onStart = function (onStart) { this._onStart = onStart; return this; }; +Playable.prototype.onUpdate = function (onUpdate) { this._onUpdate = onUpdate; return this; }; +Playable.prototype.onStop = function (onStop) { this._onStop = onStop; return this; }; +Playable.prototype.onPause = function (onPause) { this._onPause = onPause; return this; }; +Playable.prototype.onResume = function (onResume) { this._onResume = onResume; return this; }; + +Playable.prototype.tweener = function (tweener) { + if (tweener === null || tweener === undefined) { + console.warn('[Playable.tweener] Given tweener is invalid:', tweener); + return this; + } + + this._player = tweener; + return this; +}; + +Playable.prototype.setSpeed = function (speed) { + if (speed < 0) { + console.warn('[Playable.speed] This playable cannot have negative speed'); + return; + } + + if (speed === 0) { + if (this._speed !== 0) { + // Setting timeStart as if new speed was 1 + this._startTime += this._time / this._speed - this._time; + } + } else { + if (this._speed === 0) { + // If current speed is 0, + // it corresponds to a virtual speed of 1 + // when it comes to determing where the starting time is + this._startTime += this._time - this._time / speed; + } else { + this._startTime += this._time / this._speed - this._time / speed; + } + } + + this._speed = speed; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } +}; + +Playable.prototype.goTo = function (timePosition, iteration) { + if (this._iterations === 1) { + if(this._speed === 0) { + // Speed is virtually 1 + this._startTime += this._time - timePosition; + } else { + // Offsetting starting time with respect to current time and speed + this._startTime += (this._time - timePosition) / this._speed; + } + } else { + iteration = iteration || 0; + if(this._speed === 0) { + // Speed is virtually 1 + this._startTime += this._time - timePosition - iteration * this._duration; + } else { + // Offsetting starting time with respect to current time and speed + this._startTime += (this._time - timePosition - iteration * this._duration) / this._speed; + } + } + + this._time = timePosition; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } + return this; +}; + +Playable.prototype.goToBeginning = function () { + return this.goTo(0, 0); +}; + +Playable.prototype.getDuration = function () { + return Infinity; +}; + +Playable.prototype._getEndTime = function () { + return Infinity; +}; + +Playable.prototype._setStartTime = function (startTime) { + this._startTime = startTime; +}; + +Playable.prototype._getStartTime = function () { + return this._startTime; +}; + +Playable.prototype._isWithin = function (time) { + return this._startTime < time; +}; + +Playable.prototype._overlaps = function (time0, time1) { + return (time0 - this._startTime) * (time1 - this._startTime) <= 0; +}; + +Playable.prototype.rewind = function () { + this.goTo(0, 0); + return this; +}; + +Playable.prototype.delay = function (delay) { + return this.start(-delay); +}; + +Playable.prototype.start = function (timeOffset) { + if (this._player === null) { + this._player = TINA._startDefaultTweener(); + } + + if (this._validate() === false) { + // Did not pass validation + return this; + } + + if (timeOffset === undefined || timeOffset === null) { + timeOffset = 0; + } + + this._time = timeOffset; + this._startTime = this._player._time - timeOffset; + + if (this._player._reactivate(this) === false) { + // Could not be added to player + return this; + } + + return this; +}; + +Playable.prototype._start = function () { + if (this._onStart !== null) { + this._onStart(); + } +}; + +Playable.prototype.stop = function () { + if (this._player === null) { + return this; + } + + // Stopping playable without performing any additional update nor completing + if (this._player._remove(this) === false) { + // Could not be removed + return this; + } + + if (this._onStop !== null) { + this._onStop(); + } + return this; +}; + +Playable.prototype.resume = function () { + if (this._player === null || this._player._reactivate(this) === false) { + // Could not be resumed + return this; + } + + // Resetting starting time so that the playable starts off where it left off + this._startTime = this._player._time - (this._time + (this._duration * this._currentIterations)) / this._speed; + + if (this._onResume !== null) { + this._onResume(); + } + return this; +}; + +Playable.prototype.pause = function () { + if (this._player === null || this._player._inactivate(this) === false) { + // Could not be paused + return this; + } + + if (this._onPause !== null) { + this._onPause(); + } + + return this; +}; + +Playable.prototype._moveTo = function (time, dt) { + dt *= this._speed; + + this._time = (time - this._startTime) * this._speed; + this._update(dt); + + if (this._onUpdate !== null) { + this._onUpdate(this._time, dt); + } +}; + +// Overridable methods +Playable.prototype._update = function () {}; Playable.prototype._validate = function () {}; + },{}],9:[function(require,module,exports){ var Playable = require('./Playable'); var DoublyList = require('./DoublyList'); diff --git a/src/BriefPlayable.js b/src/BriefPlayable.js index c7f0769..b59d34f 100644 --- a/src/BriefPlayable.js +++ b/src/BriefPlayable.js @@ -1,14 +1,14 @@ -var inherit = require('./inherit'); -var Playable = require('./Playable'); -var BriefExtension = require('./BriefExtension'); - -function BriefPlayable() { - Playable.call(this); - BriefExtension.call(this); -} - -BriefPlayable.prototype = Object.create(Playable.prototype); -BriefPlayable.prototype.constructor = BriefPlayable; -inherit(BriefPlayable, BriefExtension); - -module.exports = BriefPlayable; \ No newline at end of file +var inherit = require('./inherit'); +var Playable = require('./Playable'); +var BriefExtension = require('./BriefExtension'); + +function BriefPlayable() { + Playable.call(this); + BriefExtension.call(this); +} + +BriefPlayable.prototype = Object.create(Playable.prototype); +BriefPlayable.prototype.constructor = BriefPlayable; +inherit(BriefPlayable, BriefExtension); + +module.exports = BriefPlayable; diff --git a/src/Playable.js b/src/Playable.js index afe41d1..e8ddbe5 100644 --- a/src/Playable.js +++ b/src/Playable.js @@ -1,243 +1,243 @@ -/** @class */ -function Playable() { - // Player component handling this playable - this._player = null; - - // Handle of the playable within its player - this._handle = null; - - // An inactive playable cannot run even within its time boundaries when its parent is running - this._active = true; - - // Starting time, is global (relative to its player time) - this._startTime = 0; - - // Current time, is local (relative to starting time) - // i.e this._time === 0 implies this._player._time === this._startTime - this._time = 0; - - // Playing speed of the playable - this._speed = 1; - - // Callbacks - this._onStart = null; - this._onPause = null; - this._onResume = null; - this._onUpdate = null; - this._onStop = null; -} - -module.exports = Playable; - -Object.defineProperty(Playable.prototype, 'speed', { - get: function () { return this._speed; }, - set: function (speed) { - this.setSpeed(speed); - } -}); - -Object.defineProperty(Playable.prototype, 'time', { - get: function () { return this._time; }, - set: function (time) { - this.goTo(time); - } -}); - -Playable.prototype.onStart = function (onStart) { this._onStart = onStart; return this; }; -Playable.prototype.onUpdate = function (onUpdate) { this._onUpdate = onUpdate; return this; }; -Playable.prototype.onStop = function (onStop) { this._onStop = onStop; return this; }; -Playable.prototype.onPause = function (onPause) { this._onPause = onPause; return this; }; -Playable.prototype.onResume = function (onResume) { this._onResume = onResume; return this; }; - -Playable.prototype.tweener = function (tweener) { - if (tweener === null || tweener === undefined) { - console.warn('[Playable.tweener] Given tweener is invalid:', tweener); - return this; - } - - this._player = tweener; - return this; -}; - -Playable.prototype.setSpeed = function (speed) { - if (speed < 0) { - console.warn('[Playable.speed] This playable cannot have negative speed'); - return; - } - - if (speed === 0) { - if (this._speed !== 0) { - // Setting timeStart as if new speed was 1 - this._startTime += this._time / this._speed - this._time; - } - } else { - if (this._speed === 0) { - // If current speed is 0, - // it corresponds to a virtual speed of 1 - // when it comes to determing where the starting time is - this._startTime += this._time - this._time / speed; - } else { - this._startTime += this._time / this._speed - this._time / speed; - } - } - - this._speed = speed; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } -}; - -Playable.prototype.goTo = function (timePosition, iteration) { - if (this._iterations === 1) { - if(this._speed === 0) { - // Speed is virtually 1 - this._startTime += this._time - timePosition; - } else { - // Offsetting starting time with respect to current time and speed - this._startTime += (this._time - timePosition) / this._speed; - } - } else { - iteration = iteration || 0; - if(this._speed === 0) { - // Speed is virtually 1 - this._startTime += this._time - timePosition - iteration * this._duration; - } else { - // Offsetting starting time with respect to current time and speed - this._startTime += (this._time - timePosition - iteration * this._duration) / this._speed; - } - } - - this._time = timePosition; - if (this._player !== null) { - this._player._onPlayableChanged(this); - } - return this; -}; - -Playable.prototype.goToBeginning = function () { - return this.goTo(0, 0); -}; - -Playable.prototype.getDuration = function () { - return Infinity; -}; - -Playable.prototype._getEndTime = function () { - return Infinity; -}; - -Playable.prototype._setStartTime = function (startTime) { - this._startTime = startTime; -}; - -Playable.prototype._getStartTime = function () { - return this._startTime; -}; - -Playable.prototype._isWithin = function (time) { - return this._startTime < time; -}; - -Playable.prototype._overlaps = function (time0, time1) { - return (time0 - this._startTime) * (time1 - this._startTime) <= 0; -}; - -Playable.prototype.rewind = function () { - this.goTo(0, 0); - return this; -}; - -Playable.prototype.delay = function (delay) { - return this.start(-delay); -}; - -Playable.prototype.start = function (timeOffset) { - if (this._player === null) { - this._player = TINA._startDefaultTweener(); - } - - if (this._validate() === false) { - // Did not pass validation - return this; - } - - if (timeOffset === undefined || timeOffset === null) { - timeOffset = 0; - } - - this._time = timeOffset; - this._startTime = this._player._time - timeOffset; - - if (this._player._reactivate(this) === false) { - // Could not be added to player - return this; - } - - return this; -}; - -Playable.prototype._start = function () { - if (this._onStart !== null) { - this._onStart(); - } -}; - -Playable.prototype.stop = function () { - if (this._player === null) { - return this; - } - - // Stopping playable without performing any additional update nor completing - if (this._player._remove(this) === false) { - // Could not be removed - return this; - } - - if (this._onStop !== null) { - this._onStop(); - } - return this; -}; - -Playable.prototype.resume = function () { - if (this._player === null || this._player._reactivate(this) === false) { - // Could not be resumed - return this; - } - - // Resetting starting time so that the playable starts off where it left off - this._startTime = this._player._time - (this._time + (this._duration * this._currentIterations)) / this._speed; - - if (this._onResume !== null) { - this._onResume(); - } - return this; -}; - -Playable.prototype.pause = function () { - if (this._player === null || this._player._inactivate(this) === false) { - // Could not be paused - return this; - } - - if (this._onPause !== null) { - this._onPause(); - } - - return this; -}; - -Playable.prototype._moveTo = function (time, dt) { - dt *= this._speed; - - this._time = (time - this._startTime) * this._speed; - this._update(dt); - - if (this._onUpdate !== null) { - this._onUpdate(this._time, dt); - } -}; - -// Overridable methods -Playable.prototype._update = function () {}; -Playable.prototype._validate = function () {}; \ No newline at end of file +/** @class */ +function Playable() { + // Player component handling this playable + this._player = null; + + // Handle of the playable within its player + this._handle = null; + + // An inactive playable cannot run even within its time boundaries when its parent is running + this._active = true; + + // Starting time, is global (relative to its player time) + this._startTime = 0; + + // Current time, is local (relative to starting time) + // i.e this._time === 0 implies this._player._time === this._startTime + this._time = 0; + + // Playing speed of the playable + this._speed = 1; + + // Callbacks + this._onStart = null; + this._onPause = null; + this._onResume = null; + this._onUpdate = null; + this._onStop = null; +} + +module.exports = Playable; + +Object.defineProperty(Playable.prototype, 'speed', { + get: function () { return this._speed; }, + set: function (speed) { + this.setSpeed(speed); + } +}); + +Object.defineProperty(Playable.prototype, 'time', { + get: function () { return this._time; }, + set: function (time) { + this.goTo(time); + } +}); + +Playable.prototype.onStart = function (onStart) { this._onStart = onStart; return this; }; +Playable.prototype.onUpdate = function (onUpdate) { this._onUpdate = onUpdate; return this; }; +Playable.prototype.onStop = function (onStop) { this._onStop = onStop; return this; }; +Playable.prototype.onPause = function (onPause) { this._onPause = onPause; return this; }; +Playable.prototype.onResume = function (onResume) { this._onResume = onResume; return this; }; + +Playable.prototype.tweener = function (tweener) { + if (tweener === null || tweener === undefined) { + console.warn('[Playable.tweener] Given tweener is invalid:', tweener); + return this; + } + + this._player = tweener; + return this; +}; + +Playable.prototype.setSpeed = function (speed) { + if (speed < 0) { + console.warn('[Playable.speed] This playable cannot have negative speed'); + return; + } + + if (speed === 0) { + if (this._speed !== 0) { + // Setting timeStart as if new speed was 1 + this._startTime += this._time / this._speed - this._time; + } + } else { + if (this._speed === 0) { + // If current speed is 0, + // it corresponds to a virtual speed of 1 + // when it comes to determing where the starting time is + this._startTime += this._time - this._time / speed; + } else { + this._startTime += this._time / this._speed - this._time / speed; + } + } + + this._speed = speed; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } +}; + +Playable.prototype.goTo = function (timePosition, iteration) { + if (this._iterations === 1) { + if(this._speed === 0) { + // Speed is virtually 1 + this._startTime += this._time - timePosition; + } else { + // Offsetting starting time with respect to current time and speed + this._startTime += (this._time - timePosition) / this._speed; + } + } else { + iteration = iteration || 0; + if(this._speed === 0) { + // Speed is virtually 1 + this._startTime += this._time - timePosition - iteration * this._duration; + } else { + // Offsetting starting time with respect to current time and speed + this._startTime += (this._time - timePosition - iteration * this._duration) / this._speed; + } + } + + this._time = timePosition; + if (this._player !== null) { + this._player._onPlayableChanged(this); + } + return this; +}; + +Playable.prototype.goToBeginning = function () { + return this.goTo(0, 0); +}; + +Playable.prototype.getDuration = function () { + return Infinity; +}; + +Playable.prototype._getEndTime = function () { + return Infinity; +}; + +Playable.prototype._setStartTime = function (startTime) { + this._startTime = startTime; +}; + +Playable.prototype._getStartTime = function () { + return this._startTime; +}; + +Playable.prototype._isWithin = function (time) { + return this._startTime < time; +}; + +Playable.prototype._overlaps = function (time0, time1) { + return (time0 - this._startTime) * (time1 - this._startTime) <= 0; +}; + +Playable.prototype.rewind = function () { + this.goTo(0, 0); + return this; +}; + +Playable.prototype.delay = function (delay) { + return this.start(-delay); +}; + +Playable.prototype.start = function (timeOffset) { + if (this._player === null) { + this._player = TINA._startDefaultTweener(); + } + + if (this._validate() === false) { + // Did not pass validation + return this; + } + + if (timeOffset === undefined || timeOffset === null) { + timeOffset = 0; + } + + this._time = timeOffset; + this._startTime = this._player._time - timeOffset; + + if (this._player._reactivate(this) === false) { + // Could not be added to player + return this; + } + + return this; +}; + +Playable.prototype._start = function () { + if (this._onStart !== null) { + this._onStart(); + } +}; + +Playable.prototype.stop = function () { + if (this._player === null) { + return this; + } + + // Stopping playable without performing any additional update nor completing + if (this._player._remove(this) === false) { + // Could not be removed + return this; + } + + if (this._onStop !== null) { + this._onStop(); + } + return this; +}; + +Playable.prototype.resume = function () { + if (this._player === null || this._player._reactivate(this) === false) { + // Could not be resumed + return this; + } + + // Resetting starting time so that the playable starts off where it left off + this._startTime = this._player._time - (this._time + (this._duration * this._currentIterations)) / this._speed; + + if (this._onResume !== null) { + this._onResume(); + } + return this; +}; + +Playable.prototype.pause = function () { + if (this._player === null || this._player._inactivate(this) === false) { + // Could not be paused + return this; + } + + if (this._onPause !== null) { + this._onPause(); + } + + return this; +}; + +Playable.prototype._moveTo = function (time, dt) { + dt *= this._speed; + + this._time = (time - this._startTime) * this._speed; + this._update(dt); + + if (this._onUpdate !== null) { + this._onUpdate(this._time, dt); + } +}; + +// Overridable methods +Playable.prototype._update = function () {}; +Playable.prototype._validate = function () {};