Skip to content

Commit

Permalink
Merge pull request #4 from jiborobot/keyframes-fix
Browse files Browse the repository at this point in the history
Keyframes fix
  • Loading branch information
bigtimebuddy committed May 17, 2016
2 parents 496ae18 + f25dd33 commit 64bf63a
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 101 deletions.
4 changes: 2 additions & 2 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pixi-animate",
"version": "0.5.0",
"version": "0.5.1",
"main": "dist/pixi-animate.min.js",
"dependencies":
{
Expand All @@ -18,4 +18,4 @@
"package.json",
".gitignore"
]
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pixi-animate",
"description": "PIXI plugin for the PixiAnimate Extension",
"version": "0.5.0",
"version": "0.5.1",
"main": "dist/pixi-animate.min.js",
"author": "Matt Karl <[email protected]>",
"dependencies": {
Expand Down
117 changes: 79 additions & 38 deletions src/animate/MovieClip.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,51 @@ class MovieClip extends Container {
return this._totalFrames;
}

/**
* Extend the timeline to the last frame.
* @method _autoExtend
* @private
* @param {int} endFrame
*/
_autoExtend(endFrame) {
if (this._totalFrames < endFrame) {
this._totalFrames = endFrame;
}
}

/**
* Convert values of properties
* @method _parseProperties
* @private
* @param {Object} properties
*/
_parseProperties(properties) {
// Convert any string colors to uints
if (typeof properties.t === 'string') {
properties.t = utils.hexToUint(properties.t);
} else if (typeof properties.v === 'number') {
properties.v = !!properties.v;
}
}

/**
* Get a timeline for a child, synced timeline.
* @method _getChildTimeline
* @private
* @param {PIXI.animate.MovieClip} instance
* @return {PIXI.animate.Timeline}
*/
_getChildTimeline(instance) {
for (let i = this._timelines.length - 1; i >= 0; --i) {
if (this._timelines[i].target === instance) {
return this._timelines[i];
}
}
let timeline = new Timeline(instance);
this._timelines.push(timeline);
return timeline;
}

/**
* Add mask or masks
* @method addTimedMask
Expand All @@ -348,7 +393,7 @@ class MovieClip extends Container {
*/
addTimedMask(instance, keyframes) {
for (let i in keyframes) {
this.addTween(instance, {
this.addKeyframe(instance, {
m: keyframes[i]
}, parseInt(i, 10));
}
Expand All @@ -370,17 +415,28 @@ class MovieClip extends Container {
}

/**
* Alias for method `addTween`
* @method tw
* Add a tween to the clip
* @method addTween
* @param {PIXI.DisplayObject} instance The clip to tween
* @param {Object} properties The property or property to tween
* @param {int} startFrame The frame to start tweening
* @param {int} [duration=0] Number of frames to tween. If 0, then the properties are set
* with no tweening.
* @param {Function} [ease] An optional easing function that takes the tween time from 0-1.
* @return {PIXI.animate.MovieClip}
*/
tw(instance, properties, startFrame, duration, ease) {
return this.addTween(instance, properties, startFrame, duration, ease);
addTween(instance, properties, startFrame, duration, ease) {

let timeline = this._getChildTimeline(instance);
this._parseProperties(properties);
timeline.addTween(properties, startFrame, duration, ease);
this._autoExtend(startFrame + duration);
return this;
}

/**
* Add a tween to the clip
* @method addTween
* @method addKeyframe
* @param {PIXI.DisplayObject} instance The clip to tween
* @param {Object} properties The property or property to tween
* @param {int} startFrame The frame to start tweening
Expand All @@ -389,36 +445,12 @@ class MovieClip extends Container {
* @param {Function} [ease] An optional easing function that takes the tween time from 0-1.
* @return {PIXI.animate.MovieClip}
*/
addTween(instance, properties, startFrame, duration, ease) {
duration = duration || 0;

//1. determine if there is already a tween for this instance, and if so prepare to add it
// on/insert it - if there isn't, then make one and set up a wait until startFrame
let timeline, i;
for (i = this._timelines.length - 1; i >= 0; --i) {
if (this._timelines[i].target === instance) {
timeline = this._timelines[i];
break;
}
}
if (!timeline) {
timeline = new Timeline(instance);
this._timelines.push(timeline);
}
addKeyframe(instance, properties, startFrame) {

// Convert any string colors to uints
if (typeof properties.t === 'string') {
properties.t = utils.hexToUint(properties.t);
} else if (typeof properties.v === 'number') {
properties.v = !!properties.v;
}

//2. create the tween segment, recording the starting values of properties and using the
// supplied properties as the ending values
timeline.addTween(instance, properties, startFrame, duration, ease);
if (this._totalFrames < startFrame + duration) {
this._totalFrames = startFrame + duration;
}
let timeline = this._getChildTimeline(instance);
this._parseProperties(properties);
timeline.addKeyframe(properties, startFrame);
this._autoExtend(startFrame);
return this;
}

Expand Down Expand Up @@ -493,8 +525,10 @@ class MovieClip extends Container {
let lastFrame = {};
for (let i in keyframes) {
lastFrame = Object.assign({}, lastFrame, keyframes[i]);
this.addTween(instance, lastFrame, parseInt(i, 10));
this.addKeyframe(instance, lastFrame, parseInt(i, 10));
}
this._getChildTimeline(instance)
.extendLastFrame(startFrame + duration);
}

// Set the initial position/add
Expand All @@ -504,8 +538,8 @@ class MovieClip extends Container {
}

/**
* Handle frame actions, callback is bound to the instance of the MovieClip
* @method addAction
* Short cut for `addAction`
* @method aa
* @param {Function} callback The clip call on a certain frame
* @param {int} startFrame The starting frame
* @return {PIXI.animate.MovieClip}
Expand All @@ -514,6 +548,13 @@ class MovieClip extends Container {
return this.addAction(callback, startFrame);
}

/**
* Handle frame actions, callback is bound to the instance of the MovieClip.
* @method addAction
* @param {Function} callback The clip call on a certain frame
* @param {int} startFrame The starting frame
* @return {PIXI.animate.MovieClip}
*/
addAction(callback, startFrame) {
let actions = this._actions;
//ensure that the movieclip timeline is long enough to support the target frame
Expand Down
55 changes: 48 additions & 7 deletions src/animate/Timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ const p = Timeline.prototype = Object.create(Array.prototype);
* @param tween The tween(s) to add. Accepts multiple arguments.
* @return Tween The first tween that was passed in.
*/
p.addTween = function(instance, properties, startFrame, duration, ease) {
p.addTween = function(properties, startFrame, duration, ease) {
this.extendLastFrame(startFrame - 1);
//ownership of startProps is passed to the new Tween - this object should not be reused
let startProps = {};
let prop;
Expand All @@ -47,7 +48,7 @@ p.addTween = function(instance, properties, startFrame, duration, ease) {
}
//otherwise, get the current value
else {
let startValue = startProps[prop] = this.getPropFromShorthand(instance, prop);
let startValue = startProps[prop] = this.getPropFromShorthand(prop);
//go through previous tweens to set the value so that when the timeline loops
//around, the values are set properly - having each tween know what came before
//allows us to set to a specific frame without running through the entire timeline
Expand All @@ -58,17 +59,57 @@ p.addTween = function(instance, properties, startFrame, duration, ease) {
}
}
//create the new Tween and add it to the list
let tween = new Tween(instance, startProps, properties, startFrame, duration, ease);
let tween = new Tween(this.target, startProps, properties, startFrame, duration, ease);
this.push(tween);
//update starting values for the next tween - if tweened values included 'p', then Tween
//parsed that to add additional data that is required
properties = tween.endProps;
for (prop in properties) {
this._currentProps[prop] = properties[prop];
Object.assign(this._currentProps, tween.endProps);
};

/**
* Add a single keyframe that doesn't tween.
* @method addKeyframe
* @param {Object} properties The properties to set.
* @param {int} startFrame The starting frame index.
*/
p.addKeyframe = function(properties, startFrame) {
this.extendLastFrame(startFrame - 1);
let startProps = Object.assign({}, this._currentProps, properties);
//create the new Tween and add it to the list
let tween = new Tween(this.target, startProps, null, startFrame, 0);
this.push(tween);
Object.assign(this._currentProps, tween.endProps);
};

/**
* Extend the last frame of the tween.
* @method extendLastFrame
* @param {int} endFrame The ending frame index.
*/
p.extendLastFrame = function(endFrame) {
if (this.length) {
let prevTween = this[this.length - 1];
if (prevTween.endFrame < endFrame) {
if (prevTween.isTweenlessFrame) {
prevTween.endFrame = endFrame;
} else {
this.addKeyframe(
this._currentProps,
prevTween.endFrame + 1,
endFrame - prevTween.endFrame + 1
);
}
}
}
};

p.getPropFromShorthand = function(target, prop) {
/**
* Get the value for a property
* @method getPropFromShorthand
* @param {string} prop
*/
p.getPropFromShorthand = function(prop) {
const target = this.target;
switch (prop) {
case 'x':
return target.position.x;
Expand Down
Loading

0 comments on commit 64bf63a

Please sign in to comment.