diff --git a/src/AnimationSupport/AnimationInterfaceSupport.js b/src/AnimationSupport/AnimationInterfaceSupport.js
deleted file mode 100644
index f45bcd933..000000000
--- a/src/AnimationSupport/AnimationInterfaceSupport.js
+++ /dev/null
@@ -1,366 +0,0 @@
-require('enyo');
-
-var
- kind = require('../kind'),
- animator = require('./Core'),
- frame = require('./Frame'),
- utils = require('../utils'),
- dispatcher = require('../dispatcher');
-
-var extend = kind.statics.extend;
-
-kind.concatenated.push('animation');
-
-var AnimationInterfaceSupport = {
-
- /**
- * @private
- */
- patterns: [],
-
- /**
- * @private
- */
- checkX: 0,
-
- /**
- * @private
- */
- checkY: 0,
-
- /**
- * @private
- */
- deltaX: 0,
-
- /**
- * @private
- */
- deltaY: 0,
-
- /**
- * @private
- */
- translateX: 0,
-
- /**
- * @private
- */
- translateY: 0,
-
- /**
- * @private
- */
- scrollValue: 0,
-
- /**
- * @private
- */
- deltaValueX: 0,
-
- /**
- * @private
- */
- deltaValueY: 0,
-
- /**
- * @private
- */
- checkDragStartX: 0,
-
- /**
- * @private
- */
- checkDragStartY: 0,
-
- /**
- * @private
- */
- deltaDragValueX: 0,
-
- /**
- * @private
- */
- deltaDragValueY: 0,
-
- /**
- * @private
- */
- setAnimateOne: 0,
-
- /**
- * @private
- */
- setAnimateTwo: 0,
-
- /**
- * @private
- */
- setAnimateThree: 0,
-
- /**
- * @private
- */
- eventArray: [
- "dragstart",
- "dragend",
- "drag",
- "flick",
- "down",
- "move",
- "scroll",
- // "mousewheel",
- "touchstart",
- "touchmove",
- "touchend",
- "mousemove"
- ],
-
- /**
- * @public
- */
- initialize: function() {
- var i, eventArrayLength = this.eventArray.length;
- for (i = 0; i < eventArrayLength; i++) {
- dispatcher.listen(this.node, this.eventArray[i], this.bindSafely(this.detectTheEvent));
- }
- },
-
- /**
- * @public
- */
- detectTheEvent: function(inSender, inEvent) {
- var eventType = inSender.type;
- switch (eventType) {
- case "dragstart":
- this.touchDragStart(inSender, inEvent, inSender.pageX, inSender.pageY);
- break;
- case "drag":
- this.touchDragMove(inSender, inEvent, inSender.pageX, inSender.pageY);
- break;
- case "dragend":
- this.touchDragEnd(inSender, inEvent);
- break;
- case "flick":
- this.handleMyEvent(inSender, inEvent);
- break;
- case "down":
- this.handleMyEvent(inSender, inEvent);
- break;
- case "move":
- this.handleMyEvent(inSender, inEvent);
- break;
- case "scroll":
- this.scrollEvent(inSender, inEvent);
- break;
- case "mousewheel":
- this.mousewheelEvent(inSender, inEvent);
- break;
- case "touchstart":
- this.touchDragStart(inSender, inEvent, inSender.targetTouches[0].pageX, inSender.targetTouches[0].pageY);
- break;
- case "touchmove":
- this.touchDragMove(inSender, inEvent, inSender.targetTouches[0].pageX, inSender.targetTouches[0].pageY);
- break;
- case "touchend":
- this.touchDragEnd(inSender, inEvent);
- break;
- case "mousemove":
- this.touchDragMove(inSender, inEvent, (inEvent, inSender.pageX) / 1.5, (inSender.pageY) / 1.5);
- break;
- default:
- this.handleMyEvent(inSender, inEvent);
- }
- },
-
- /**
- * @public
- */
- touchDragStart: function(inSender, inEvent, x, y) {
- this.checkX = x;
- this.checkY = y;
- },
-
- /**
- * @public
- */
- touchDragMove: function(inSender, inEvent, x, y) {
- var currentX = x,
- currentY = y;
-
- if (currentX !== 0 || currentY !== 0) {
- this.deltaValueX = this.checkX - currentX;
-
- this.checkX = currentX; // set the initial position to the current position while moving
-
- this.deltaValueY = this.checkY - currentY;
-
- this.checkY = currentY; // set the initial position to the current position while moving
-
- //call commonTasks function with delta values
- this.translateX = this.translateX + this.deltaValueX;
- this.translateY = this.translateY + this.deltaValueY;
-
- this.setAnimateOne = this.translateX;
- this.setAnimateTwo = this.translateX;
- this.setAnimateThree = this.translateY;
-
- }
-
- },
-
- /**
- * @public
- */
- touchDragEnd: function(inSender, inEvent, x, y) {
- this.checkX = 0;
- this.checkY = 0;
- this.deltaValueX = 0;
- this.deltaValueY = 0;
- },
-
- /**
- * @public
- */
- scrollEvent: function(inSender, inEvent) {
- var delta = inSender.deltaY,
- scrollTop = inSender.target.scrollTop,
- scrollLeft = inSender.target.scrollLeft;
-
- if (this.scrollValue === 0) {
- this.scrollValue = inSender.target.scrollTop;
- }
-
- delta = inSender.target.scrollTop - this.scrollValue;
-
- this.deltaX = scrollLeft - this.deltaX;
- this.deltaY = scrollTop - this.deltaY;
- this.scrollValue = scrollTop;
-
- this.translateX = this.translateX + this.deltaX;
- this.translateY = this.translateY + this.deltaY;
-
- //call commonTasks function with delta values
- this.setAnimateOne = delta;
- this.setAnimateTwo = this.translateX;
- this.setAnimateThree = this.translateY;
-
-
- this.deltaX = scrollLeft;
- this.deltaY = scrollTop;
- },
-
- /**
- * @public
- */
- mousewheelEvent: function(inSender, inEvent) {
- var delta = inSender.deltaY,
- deltaX = inSender.wheelDeltaX,
- deltaY = inSender.wheelDeltaY;
-
- this.translateX = this.translateX + deltaX;
- this.translateY = this.translateY + deltaY;
-
- //call commonTasks function with delta values
- this.setAnimateOne = delta;
- this.setAnimateTwo = (-1 * (this.translateX));
- this.setAnimateThree = (-1 * (this.translateY));
- if (this.patterns[0].name === "Slideable" || this.patterns[0].name === "Parallax") {
- this.setAnimateTwo = this.setAnimateThree;
- }
- },
-
- /**
- * @public
- */
- commonTasks: function(delta, deltax, deltay) {
- var patternsLength = this.patterns.length;
- if (delta !== 0) {
- delta = delta / Math.abs(delta);
- }
- //Call specific interface
- for (var i = 0; i < patternsLength; i++) {
- if (this.patterns[i].name === "Fadeable") {
- this.patterns[i].fadeByDelta.call(this, delta);
- } else if (this.patterns[i].name === "Flippable") {
- this.patterns[i].doFlip.call(this, delta);
- } else if (this.patterns[i].name === "Slideable") {
- if (this.parallax === true) {
- for (var j = 0; j < this.children.length; j++) {
- var current = this.children[j];
- animator.trigger(current);
- this.patterns[i].slide.call(current, (-1 * deltax / current.speed), (-1 * deltay / current.speed), 0);
- current.start(true);
- }
- } else {
- this.patterns[i].slide.call(this, (-1 * deltax), (-1 * deltay), 0);
- }
- }
- if (this.patterns[i].name !== "Slideable") {
- this.setAnimateOne = 0;
- this.setAnimateTwo = 0;
- this.setAnimateThree = 0;
- }
- }
- this.start(true);
- },
-
- /**
- * @public
- */
- handleMyEvent: function(inSender, inEvent) {
- /*TODO:*/
- },
-
- /**
- * @public
- */
- commitAnimation: function(x, y, z) {
- var i, len;
-
- if (this.patterns && Object.prototype.toString.call(this.patterns) === "[object Array]" && (len = this.patterns.length)) {
- for (i = 0; i < len; i++) {
- /*if (typeof this.patterns[i].triggerEvent === 'function') {
- patterns[i].triggerEvent();
- }*/
- this.commonTasks(this.setAnimateOne, this.setAnimateTwo, this.setAnimateThree);
- }
- }
- },
-
- /**
- * @private
- */
- rendered: kind.inherit(function(sup) {
- return function() {
- sup.apply(this, arguments);
- this.initialize();
- };
- })
-};
-
-module.exports = AnimationInterfaceSupport;
-
-/**
- Hijacking original behaviour as in other Enyo supports.
-*/
-var sup = kind.concatHandler;
-
-/**
- * @private
- */
-kind.concatHandler = function(ctor, props, instance) {
- sup.call(this, ctor, props, instance);
- var aPattern = props.pattern;
- if (aPattern && Object.prototype.toString.call(aPattern) === "[object Array]") {
- var proto = ctor.prototype || ctor;
- extend(AnimationInterfaceSupport, proto);
-
- this.patterns = aPattern;
- var len = this.patterns.length;
- for (var i = 0; i < len; i++) {
- extend(this.patterns[i], proto);
- }
- animator.register(proto);
- }
-};
diff --git a/src/AnimationSupport/AnimationSupport.js b/src/AnimationSupport/AnimationSupport.js
deleted file mode 100644
index f7894217b..000000000
--- a/src/AnimationSupport/AnimationSupport.js
+++ /dev/null
@@ -1,295 +0,0 @@
-require('enyo');
-
-var
- kind = require('../kind'),
- animation = require('./Core'),
- activator = require('./KeyFrame'),
- delegator = require('./EventDelegator'),
- EventEmitter = require('../EventEmitter'),
- FrameEditor = require('./FrameEditor'),
- frame = require('./Frame'),
- utils = require('../utils');
-
-var extend = kind.statics.extend;
-
-kind.concatenated.push('animation');
-
-var AnimationSupport = {
-
- /**
- * @private
- */
- //name: 'AnimationSupport',
- animating: false,
-
- /**
- * To keep a character active for it to apply some other
- * animation at runtime. This gives a preformance boost when on
- * character an animation is reapplied.
- * @default false - So the once the animation is completed, it has to be retriggered to
- * start a new animation.
- * @private
- */
- active: false,
-
- /**
- * Holds variouts states of animation.
- * Like: 'started' - Character animation has started(within rAF)
- * 'paused' - Character animation has paused(within rAF)
- * 'resumed' - Character animation has resumed(within rAF)
- * 'completed' - Character animation has finished(within rAF)
- * @private
- */
- animationState: "",
-
- /**
- * To check if the event delta value is changed
- * @private
- */
- deltaChanged: false,
-
- /**
- * To hold the name of the animation event which occured on the character
- * @private
- */
- eventName: "",
-
- /**
- * Holds delta value in the order [x, y, z, rad]
- * @private
- */
- animDelta: [],
-
-
- vScrollX: 0,
-
- vScrollY: 0,
-
- vScrollZ: 0,
-
- prevDur: 0,
-
- totalDuration: 0,
-
-
- /**
- * Maximum threshold for animation
- * @private
- */
- animMaxThreshold: [],
-
- _animPose: [],
-
- _pose: [],
-
- mixins: [EventEmitter, FrameEditor],
-
- _eventCache: {},
-
-
- /**
- * Check if the character is suitable for animation
- * @public
- */
- ready: function() {
- var ret = this.generated && this.animating;
- if (ret && this._startTime)
- ret = this._startTime <= utils.perfNow();
-
- if(ret) this.set('animationState', 'started');
- return ret;
- },
-
- /**
- * Sets current animation state for this character
- * @public
- */
- setInitial: function (initial) {
- this._startAnim = initial ? frame.copy(initial) : {};
- },
-
-
- /**
- * Sets animation distance for this character
- * @public
- */
- setDistance: function (dist) {
- this.distance = dist;
- },
-
- /**
- * Gets animation distance for this character
- * @public
- */
- getDistance: function () {
- return this.distance;
- },
-
- /**
- * Gets current state of animation for this character
- * @public
- */
- initiate: function (current) {
- var dom = this.hasNode(), dur,
- pose = frame.getComputedProperty(dom, undefined, current);
- pose.duration = 0;
- this._animPose = [];
- this._animPose.push(pose);
- this.currentState = pose.currentState;
- frame.accelerate(dom, pose.matrix);
-
- if(this.animate !== true) {
- dur = this.getDuration() || 0;
- this.addAnimation(this.animate, dur);
- }
- },
-
- /**
- * Adds new animation on already existing animation for this character.
- * @public
- */
- addAnimation: function (newProp, duration) {
- if (this.prevDur === 0 && duration === 0) {
- this._animPose[0] = {animate: newProp, duration: 0};
- } else {
- this.prevDur = duration || this.prevDur;
- this.totalDuration += this.prevDur;
- this._animPose.push({animate: newProp, duration: this.totalDuration});
- }
- },
-
- /**
- * Sets new animation for this character.
- * @public
- */
- setAnimation: function (newProp) {
- this._prop = newProp;
- },
-
-
- /**
- * Sets the delta values of x, y and z for events
- * @param {Object} obj - Object contains dX, dY and dZ as keys
- * @public
- */
- setAnimationDelta: function (ev) {
- this._eventCache.dX = ev.dX + this._eventCache.dX || 0;
- this._eventCache.dY = ev.dY + this._eventCache.dY || 0;
- this._eventCache.dZ = ev.dZ + this._eventCache.dZ || 0;
- this._eventCache[ev.vtype] = ev;
-
- this.deltaChanged = true;
- this.eventCacheUpdated = true;
-
- },
-
- /**
- * Gets the delta values of x, y and z for events
- * @public
- */
- getAnimationDelta: function () {
- return this._eventCache[this._virtualEvent];
- },
- /**
- * Gets how long animation is active on this character
- * @public
- */
- getDuration: function() {
- return this._duration || this.duration;
- },
-
- /**
- * Sets how long animation should be active on this character
- * @public
- */
- setDuration: function (newDuration) {
- this._duration = newDuration;
- },
-
- /**
- * Idnetify when the character has done animating.
- * This triggers "onAnimated" event on this character
- * @public
- */
- completed: function() {
- return this.onAnimated && this.onAnimated(this);
- },
-
- /**
- * Trigger animation for this character.
- * @public
- */
- start: function (active, delay) {
- this._startTime = utils.perfNow() + (delay || 0) ;
- this._lastTime = this._startTime + this._duration;
- this.animating = true;
- this.active = active;
- },
-
- /**
- * Trigger the registered event to all the listeners
- * @public
- */
- triggerEvent: function () {
- this.deltaChanged = false;
- return delegator.emitEvent(this, this.getAnimationDelta());
- },
-
- /**
- * @private
- */
- rendered: kind.inherit(function (sup) {
- return function () {
- sup.apply(this, arguments);
- this.initiate();
- if (this.handleAnimationEvents) {
- delegator.register(this);
- }
- };
- }),
-
- /**
- * @private
- */
- destroy: kind.inherit(function(sup) {
- return function() {
- animation.remove(this);
- animation.deRegister(this);
- if (this.handleAnimationEvents) {
- delegator.deRegister(this);
- }
- sup.apply(this, arguments);
- };
- })
-};
-
-module.exports = AnimationSupport;
-
-/**
- Hijacking original behaviour as in other Enyo supports.
-*/
-var sup = kind.concatHandler;
-
-/**
-* @private
-*/
-kind.concatHandler = function (ctor, props, instance) {
- sup.call(this, ctor, props, instance);
- if (props.animate || props.keyFrame || props.pattern || props.handleAnimationEvents) {
- var proto = ctor.prototype || ctor;
- extend(AnimationSupport, proto);
- // if (props.keyFrame && typeof props.keyFrame != 'function') {
- // activator.animate(proto, props);
- // }
- if ((props.animate && typeof props.animate != 'function' ) ||
- (props.keyFrame && typeof props.keyFrame != 'function')) {
- animation.trigger(proto);
- }
- if (props.handleAnimationEvents && typeof props.handleAnimationEvents != 'function') {
- animation.register(proto);
- }
- if (props.pattern && typeof props.pattern != 'function') {
- animation.register(proto);
- }
- }
-};
\ No newline at end of file
diff --git a/src/AnimationSupport/Core.js b/src/AnimationSupport/Core.js
deleted file mode 100644
index 723bd4fdf..000000000
--- a/src/AnimationSupport/Core.js
+++ /dev/null
@@ -1,221 +0,0 @@
-require('enyo');
-
-var
- kind = require('../kind'),
- animation = require('../animation'),
- utils = require('../utils'),
- director = require('./Director');
-
-var ts, wasTs,
- CoreObject = require('../CoreObject');
-
-/**
-* This module returns the Loop singleton
-* Core module is responsible for handling all animations happening in Enyo.
-* The responsibilities of this module is to;
-* - Trigger vendor specific rAF.
-* - Knowing all elements which have requested for animation.
-* - Tween animation frames for each characters.
-*
-* @module enyo/Core
-*/
-module.exports = kind.singleton({
- /** @lends module:enyo/Core */
-
- /**
- * @private
- */
- name: 'enyo.Core',
- /**
- * @private
- */
- kind: CoreObject,
-
- /**
- * @private
- */
- chracs: [],
-
- /**
- * @private
- */
- evnts: [],
-
- /**
- * @private
- */
- req: 0,
-
- /**
- * @private
- */
- running: false,
-
- /**
- * Core base API to start animation functionalities.
- * The purpose of this method is to check if the animation is already started or not
- * otherwise wake up core to handle animation for a character.
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- * @parameter charc- Animation character
- *
- * @public
- */
- trigger: function (charc) {
- if (!charc.animating) {
- this.chracs.push(charc);
- }
- if (!this.running) {
- this.running = true;
- this.start();
- }
- },
-
- /**
- * Core public API to check if core is handling animation for particular
- * document element.
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- * @parameter charc- Animation character
- *
- * @public
- */
- exists: function (eventTarget) {
- for (var i = 0; i < this.chracs.length; i++) {
- if (this.chracs[i].hasNode() === eventTarget) { // Already Animating
- return this.chracs[i];
- }
- }
- },
-
- /**
- * Animator public API to remove animation happening on a particular
- * document element.
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- * @parameter charc- Animation character
- *
- * @public
- */
- remove: function (curr) {
- var i = this.chracs.indexOf(curr);
- if (i >= 0) this.chracs.splice(i, 1);
- },
-
- /**
- * Animator public API to pause animation happening on all the
- * characters.
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- *
- * @public
- */
- pause: function () {
- for (var i = 0; i < this.chracs.length; i++) {
- this.chracs[i].animating = false;
- }
- },
-
-
- /**
- * Animator public API to register character with event
- *
- * @parameter charc- Animation character
- *
- * @public
- */
- register: function (charc) {
- this.deRegister(charc);
- this.evnts.push(charc);
- this.remove(charc);
- charc.animating = true;
-
- if (!this.isTicking) {
- this.dummy();
- this.isTicking = true;
- }
- },
-
- deRegister: function (curr) {
- var idx = this.evnts.indexOf(curr);
- if (idx >= 0) this.evnts.splice(idx, 1);
- },
-
- /**
- * @private
- */
- start: function () {
- this.req = animation.requestAnimationFrame(this.bindSafely(this.loop));
- },
-
- /**
- * @private
- */
- cancel: function () {
- animation.cancelRequestAnimationFrame(this.req);
- },
-
- /**
- * @private
- */
- loop: function () {
- var i, curr,
- len = this.chracs.length;
-
- if (len <= 0) {
- this.cancel();
- this.running = false;
- return;
- }
-
- for (i = 0; i < len; i++) {
- curr = this.chracs[i];
- if (curr && curr.ready()) {
- ts = utils.perfNow();
- director.take(curr, ts - (curr.wasTs || ts));
- curr.wasTs = ts;
- }
- }
- this.start();
- },
-
- /**
- * @private
- */
- eventLoop: function () {
- var i, curr, status, evlen = this.evnts.length;
- for (i = 0; i < evlen; i++) {
- curr = this.evnts[i];
- if (this.evnts[i].patterns && typeof this.evnts[i].patterns.length > 0) {
- this.evnts[i].commitAnimation();
- }
- ts = utils.perfNow();
- if (curr && curr.ready()) {
- if (curr.deltaChanged) {
- status = curr.triggerEvent();
- }
- if (!status && curr.eventCacheUpdated) {
- director.shot(curr, ts - (wasTs || ts));
- }
- }
- wasTs = ts;
- }
- this.dummy();
- },
-
- /**
- * TODO: Merge this implementation with actual start
- * @private
- */
- dummy: function () {
- animation.requestAnimationFrame(this.eventLoop.bind(this));
- }
-});
\ No newline at end of file
diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js
index 12ec4ba3a..7deb94795 100644
--- a/src/AnimationSupport/Director.js
+++ b/src/AnimationSupport/Director.js
@@ -1,105 +1,137 @@
require('enyo');
-var frame = require('./Frame'),
- tween = require('./Tween'),
- utils = require('../utils');
+var tween = require('./Tween'),
+ utils = require('../utils');
+
+var dur, tm, t;
/**
-* This module returns the Loop singleton
-* Core module is responsible for handling all animations happening in Enyo.
-* The responsibilities of this module is to;
-* - Trigger vendor specific rAF.
-* - Knowing all elements which have requested for animation.
-* - Tween animation frames for each characters.
-*
-* @module enyo/Core
+* Contains the declaration for the {@link module:enyo/AnimationSupport/Director} module.
+* This modules exposes the features to support 'Director' approach.
+* @module enyo/AnimationSupport/Director
*/
module.exports = {
-/**
- * Tweens public API which notifies to change current state of
- * a character. This method is normally trigger by the Animation Core to
- * update the animating characters state based on the current timestamp.
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- * @parameter chrac- Animating character
- * ts- DOMHighResTimeStamp
- *
- * @public
+
+ /**
+ * This method checks if all the actors of the given {@link @module enyo/AnimationSupport/Scene} object
+ * is rendered. If the actors are rendered then all them are initialized and prepared to be ready for animation.
+ * @param {@link @module enyo/AnimationSupport/Scene} scene Scene which contains actors to be prepared for animation.
+ * @return {boolean} Returns true if all the actors
+ * of the scene is active and ready for action,
+ * otherwise false
*/
-
- take: function(actor, ts) {
- var dur = actor.totalDuration,
- tm = actor.rolePlay(ts);
-
- if (tm < 0) return;
- if (tm < dur) {
- this.action(actor, tm);
- } else {
- this.action(actor, tm);
- this.cut(actor);
- }
- },
+ roll: function (scene) {
+ var actor,
+ actors = scene.rolePlays ? scene.rolePlays[scene.getID()]: [],
+ l = actors ? actors.length: 0,
+ active = true;
- cut: function (actor) {
- actor.animating = false;
- actor.timeline = 0;
- actor.completed(actor);
- actor.set('animationState', 'completed');
- if (!actor.active) {
- // this.remove(actor);
+ for (var i = 0; i < l; i++) {
+ actor = actors[i];
+ if(actor.generated) {
+ tween.init(actor);
+ active = false;
+ }
}
+ scene.active = active;
},
- action: function(actor, since) {
- var pose, t,
- index = this.poseByTime(actor._animPose, since),
- props = actor._animPose[index],
- prevDur = actor._animPose[(index - 1) < 0 ? 0 : (index - 1)].duration,
- currentAnimSince = since - prevDur,
- runningDur = props.duration - prevDur;
- if (!props._startAnim) {
- pose = frame.getComputedProperty(actor.hasNode(), props.animate, actor.currentState);
- utils.mixin(props, pose);
- }
+ /**
+ * take method is invloved in time based animation. This method will
+ * be executed continuously in order tween the actor for every frame until the animation
+ * is completed (i.e. until elapsed time is equal to the duration).
+ * be animated based on the delta and the acceleration.
+ * @param {@link @module enyo/AnimationSupport/Scene} scene Scene on which the animation will be performed
+ * @param {Number} ts Elapsed time since the animation of this pose has started (ratio in factor of 1)
+ */
+ take: function (scene, ts) {
+ dur = scene.span;
+ tm = scene.timeline;
- if (currentAnimSince < 0) return;
- if (currentAnimSince <= runningDur && runningDur !== 0) {
- t = currentAnimSince / runningDur;
- tween.step(actor, props, ( t > 0.98) ? t = 1 : t, runningDur);
+ if (isNaN(tm) || tm < 0) return;
+ if (tm <= dur) {
+ scene.pose = scene.action(ts, scene.pose);
} else {
- tween.step(actor, props, 1, runningDur);
+ scene.timeline = dur;
+ scene.animating = false;
}
},
- poseByTime: function(arr, duration) {
- var startIndex = 0,
- stopIndex = arr.length - 1,
- middle = Math.floor((stopIndex + startIndex) / 2);
+ /**
+ * action is the primary method which triggers the animation of the actor for every frame.
+ * This method calculates the start and end animation positions and the elapsed time since the animation
+ * has started and tweens the actor based on the these values.
+ * @param {Object} pose Animation poses
+ * @param {@link module:enyo/Component~Component} actor Component on which the animation should be performed
+ * @param {Number} since Elapsed time since the animation of this pose has started
+ * @param {Number} dur Total duration of this pose
+ */
+ action: function (pose, actor, since, dur) {
+ if (!pose._startAnim) tween.init(actor, pose);
- if(duration === 0) {
- return startIndex;
+ if (since < 0) since = 0;
+ if (since <= dur && dur !== 0) {
+ t = since / dur;
+ tween.step(actor, pose, ( t > 0.98) ? 1 : t, dur);
+ } else {
+ tween.step(actor, pose, 1, dur);
}
+ },
+
+ /**
+ * Casts an actor or all the actors in the array to the given scene.
+ * @param {@link module:enyo/Component~Component} actors actor or Array of actors which needs to be casted in the scene.
+ * @param {@link @module enyo/AnimationSupport/Scene} scene Scene to which the actors has to be connected.
+ */
+ cast: function (actors, scene) {
+ var acts = utils.isArray(actors) ? actors : [actors],
+ id = scene.getID(),
+ rolePlays = scene.rolePlays || {};
- while (arr[middle].duration != duration && startIndex < stopIndex) {
- if (duration < arr[middle].duration) {
- stopIndex = middle;
- } else if (duration > arr[middle].duration) {
- startIndex = middle + 1;
- }
-
- middle = Math.floor((stopIndex + startIndex) / 2);
+ if (!rolePlays[id]) {
+ rolePlays[id] = acts;
+ } else {
+ rolePlays[id] = acts.reduce(function(actors, actor) {
+ actors.push( actor );
+ return actors;
+ }, rolePlays[id]);
}
+ scene.rolePlays = rolePlays;
+ },
- return (arr[middle].duration != duration) ? startIndex : middle;
+ /**
+ * Disconnects actor or Array of actors from the scene
+ * @param {Array.} actors actor or Array of actors which needs to be casted in the scene.
+ * @param {@link @module enyo/AnimationSupport/Scene} scene Scene from which the actors has to be removed.
+ */
+ reject: function (scene, actors) {
+ var id = scene.getID(), acts,
+ rolePlays = scene.rolePlays || [];
+ actors = actors || rolePlays[id];
+ acts = utils.isArray(actors) ? actors : [actors];
+ if (rolePlays[id]) {
+ rolePlays[id] = acts.reduce(function(actors, actor) {
+ var i = actors.indexOf(actor);
+ if (i >= 0) actors.splice(i, 1);
+ return actors;
+ }, rolePlays[id]);
+ }
+ scene.rolePlays = rolePlays;
},
- shot: function(chrac, ts) {
- var v1, s, a, v,
+ /**
+ * shot method is invloved in distance based animation in which the distance definite and
+ * indefinite (Event based animations). This method calculates the distance to which the actor has to
+ * be animated based on the delta and the acceleration.
+ * @param {@link module:enyo/Component~Component} actor Component on which the animation should be performed
+ * @param {Number} ts delta distance
+ * @return {Number} The distance to which the actor has to be transformed
+ */
+ shot: function(actor, ts) {
+ var v1, s, a, v = 0,
t = ts,
- dt = chrac._eventCache,
- dir = this.angle(chrac.direction),
+ dt = actor.getAnimationDelta(),
+ dir = this.angle(actor.direction),
v0 = dt.velocity || 0;
v1 = dt[dir] / t;
@@ -115,10 +147,13 @@ module.exports = {
dt[dir] = 0;
}
dt.velocity = v1;
- this.take(chrac, dt[dir] > 0 ? v : -v);
- }
+ }
+ return dt[dir] > 0 ? v : -v;
},
+ /**
+ * @private
+ */
angle: function (direction) {
switch(direction) {
case "X" :
diff --git a/src/AnimationSupport/Easings.js b/src/AnimationSupport/Easings.js
index cfcbf6d58..8ec19ab99 100644
--- a/src/AnimationSupport/Easings.js
+++ b/src/AnimationSupport/Easings.js
@@ -1,25 +1,32 @@
/**
- * Interface to achieve Easings in various animations
- *
- * @module enyo/AnimationSupport/Easings
- * @public
+ * Beginning time
+ * @type {number}
*/
-var matrixUtil = require('./Matrix');
-
var b = 0,
- c = 1;
-var temp = null,
+ /**
+ * Change in time
+ * @type {number}
+ */
+ c = 1,
+ temp = null,
tempProp = null,
tempOldState = [],
tempNewState = [];
+/**
+ * This module provdes an interface to achieve various types of Easings in animations
+ *
+ * @module enyo/AnimationSupport/Easings
+ */
+var easings = module.exports = {
-var easings = {
/**
+ * Use this function to check whether the ease object has changed or not.
* @public
- * apply the function to check whether the ease object has changed
- * @params currentEase : the ease object which is currently available
+ * @param {object} currentEase - ease object which we want to check
+ * @return {boolean} - Boolean value for easechanged.
+ * True - Yes. The ease object got changed.
+ * False - No. The ease object has not changed.
*/
-
easeChanged: function(currentEase) {
if (temp === null) { // setting the values for the first time
@@ -36,10 +43,12 @@ var easings = {
}
},
+
/**
+ * Use this function to check whether the animating property of the object has changed or not
* @public
- * apply the function to check whether the animating property of the object has changed
- * @params currentProp : the animating property of the object which is currently available
+ * @param {string} currentProp - Name of the animating property like - "Translate/Opacity/Scale/Rotate"
+ * @return {boolean} - Boolean value for propChange. Either True or False
*/
propChange: function(currentProp) {
@@ -57,12 +66,13 @@ var easings = {
}
},
+
/**
+ * Use this function to check whether the oldState of the object has changed or not
* @public
- * apply the function to check whether the oldState of the object has changed
- * @params currentOldState : the oldState of the object which is currently available
+ * @param {object} currentOldState - currentOldState object
+ * @return {boolean} - Boolean value for oldStateChange. Either True or False
*/
-
oldStateChange: function(currentOldState) {
if (tempOldState === null) { // setting the values for the first time
@@ -80,12 +90,13 @@ var easings = {
}
},
+
/**
- * @public
- * apply the function to check whether the newState of the object has changed
- * @params currentOldState : the newState of the object which is currently available
+ * Use this function to check whether the newStateChange of the object has changed or not
+ * @public
+ * @param {object} currentNewState -currentNewState object
+ * @return {boolean} - Boolean value for newStateChange. Either True or False
*/
-
newStateChange: function(currentNewState) {
if (tempNewState === null) { // setting the values for the first time
@@ -103,12 +114,14 @@ var easings = {
}
},
+
/**
+ * Use this function to compare the states which are arrays
* @public
- * apply the function to compare the states which are arrays
- * @params currentOldState : x is the previous state and y is the current state
+ * @param {Number[]} x - old array of the same
+ * @param {Number[]} y - current array of the same
+ * @return {boolean} - True/ False after comparing the parameters
*/
-
compareStates: function(x, y) {
var xLen = x.length;
var yLen = y.length;
@@ -134,40 +147,12 @@ var easings = {
return true;
},
- calculateEase: function(easeObj, startPoint, endPoint) {
- var order = (easeObj && Object.keys(easeObj).length) ? (Object.keys(easeObj).length + 1) : 0;
- var controlPoints = [startPoint],
- bValues = [],
- m1 = [],
- m2 = [],
- m3 = [],
- m4 = [],
- l = 0;
-
- var t, a;
- for (var key in easeObj) {
- t = parseFloat(key) / 100;
- a = parseFloat(easeObj[key]) / 100;
- bValues = easings.getBezierValues(t, order);
- bValues.shift();
- m1.push(a - bValues.pop());
- m2.push(bValues);
- }
-
- m3 = matrixUtil.inverseN(m2, bValues.length);
-
- m4 = matrixUtil.multiplyN(m3, m1);
- l = m4.length;
- for (var i = 0; i < l; i++) {
- controlPoints.push([m4[i], m4[i], m4[i]]);
- }
-
- controlPoints.push(endPoint);
- return controlPoints;
- },
/**
+ * This function returns the coefficents based on the order and the current position
* @private
- * @params n: order, k: current position
+ * @param {number} n - order
+ * @param {number} k - current position
+ * @return {object} - coefficients
*/
getCoeff: function(n, k) {
n = parseInt(n, 10);
@@ -189,9 +174,13 @@ var easings = {
return n * this.getCoeff(n - 1, k - 1) / k;
},
+
/**
+ * Function to get the bezier coeffients based on the time and order
* @public
- * @params t: time, n: order
+ * @param {number} t - time
+ * @param {number} n - order
+ * @return {object} - bezier coefficients
*/
getBezierValues: function(t, n) {
t = parseFloat(t, 10),
@@ -206,7 +195,7 @@ var easings = {
var c,
values = [],
-
+
x = (1 - t),
y = t;
//
@@ -220,154 +209,231 @@ var easings = {
return values;
},
-
+ /**
+ * Current time multiplied with duration
+ * @public
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} - time
+ */
timeCheck: function(t, d) {
t = t * d;
return t;
},
+
/**
+ * EaseInQuad
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} - calculated time
*/
easeInQuad: function(t, d) {
t = easings.timeCheck(t, d);
return c * (t /= d) * t + b;
},
+
/**
+ * EaseOutQuad
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutQuad: function(t, d) {
t = easings.timeCheck(t, d);
return -c * (t /= d) * (t - 2) + b;
},
+
/**
+ * EaseInOutQuad
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutQuad: function(t, d) {
t = easings.timeCheck(t, d);
if ((t /= d / 2) < 1) return c / 2 * t * t + b;
return -c / 2 * ((--t) * (t - 2) - 1) + b;
},
+
/**
+ * EaseInCubic
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInCubic: function(t, d) {
t = easings.timeCheck(t, d);
return c * (t /= d) * t * t + b;
},
+
/**
+ * EaseOutCubic
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutCubic: function(t, d) {
t = easings.timeCheck(t, d);
return c * ((t = t / d - 1) * t * t + 1) + b;
},
+
/**
+ * EaseInOutCubic
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutCubic: function(t, d) {
t = easings.timeCheck(t, d);
if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
return c / 2 * ((t -= 2) * t * t + 2) + b;
},
+
/**
+ * EaseInQuart
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInQuart: function(t, d) {
t = easings.timeCheck(t, d);
return c * (t /= d) * t * t * t + b;
},
+
/**
+ * EaseOutQuart
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutQuart: function(t, d) {
t = easings.timeCheck(t, d);
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
},
+
/**
+ * EaseInOutQuart
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutQuart: function(t, d) {
t = easings.timeCheck(t, d);
if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
},
+
/**
+ * EaseInQuint
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInQuint: function(t, d) {
t = easings.timeCheck(t, d);
return c * (t /= d) * t * t * t * t + b;
},
/**
+ * EaseOutQuint
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutQuint: function(t, d) {
t = easings.timeCheck(t, d);
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
},
+
/**
+ * EaseInOutQuint
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutQuint: function(t, d) {
t = easings.timeCheck(t, d);
if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
},
+
/**
+ * EaseInSine
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInSine: function(t, d) {
t = easings.timeCheck(t, d);
return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
},
+
/**
+ * EaseOutSine
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutSine: function(t, d) {
t = easings.timeCheck(t, d);
return c * Math.sin(t / d * (Math.PI / 2)) + b;
},
+
/**
+ * EaseInOutSine
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutSine: function(t, d) {
t = easings.timeCheck(t, d);
return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
},
+
/**
+ * EaseInExpo
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInExpo: function(t, d) {
t = easings.timeCheck(t, d);
return (t === 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
},
+
/**
+ * EaseOutExpo
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutExpo: function(t, d) {
t = easings.timeCheck(t, d);
return (t === d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
},
+
/**
+ * EaseInOutExpo
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutExpo: function(t, d) {
t = easings.timeCheck(t, d);
@@ -376,34 +442,50 @@ var easings = {
if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
},
+
/**
+ * EaseInCirc
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInCirc: function(t, d) {
t = easings.timeCheck(t, d);
return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
},
+
/**
+ * EaseOutCirc
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutCirc: function(t, d) {
t = easings.timeCheck(t, d);
return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
},
+
/**
+ * EaseInOutCirc
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutCirc: function(t, d) {
t = easings.timeCheck(t, d);
if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
},
+
/**
+ * EaseInElastic
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInElastic: function(t, d) {
var a = c,
@@ -419,9 +501,13 @@ var easings = {
} else s = p / (2 * Math.PI) * Math.asin(c / a);
return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
},
+
/**
+ * EaseOutElastic
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutElastic: function(t, d) {
var a = c,
@@ -437,9 +523,13 @@ var easings = {
} else s = p / (2 * Math.PI) * Math.asin(c / a);
return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
},
+
/**
+ * EaseInOutElastic
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutElastic: function(t, d) {
var a = c,
@@ -456,27 +546,39 @@ var easings = {
if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
},
+
/**
+ * EaseInBack
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInBack: function(t, d, s) {
t = easings.timeCheck(t, d);
if (!s) s = 1.70158;
return c * (t /= d) * t * ((s + 1) * t - s) + b;
},
+
/**
+ * EaseOutBack
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutBack: function(t, d, s) {
t = easings.timeCheck(t, d);
if (s === undefined) s = 1.70158;
return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
},
+
/**
+ * EaseInOutBack
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutBack: function(t, d, s) {
t = easings.timeCheck(t, d);
@@ -484,17 +586,25 @@ var easings = {
if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
},
+
/**
+ * EaseInBounce
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInBounce: function(t, d) {
t = easings.timeCheck(t, d);
return c - easings.easeOutBounce((d - t) / d, d) + b;
},
+
/**
+ * EaseOutBounce
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeOutBounce: function(t, d) {
t = easings.timeCheck(t, d);
@@ -508,9 +618,13 @@ var easings = {
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
}
},
+
/**
+ * EaseInOutBounce
* @public
- * apply the below type of ease to the DOM element
+ * @param {number} t - current time
+ * @param {number} d - duration
+ * @return {number} calculated time
*/
easeInOutBounce: function(t, d) {
t = easings.timeCheck(t, d);
@@ -519,4 +633,3 @@ var easings = {
}
};
-module.exports = easings;
diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js
deleted file mode 100644
index b2691cf27..000000000
--- a/src/AnimationSupport/EventDelegator.js
+++ /dev/null
@@ -1,222 +0,0 @@
-require('enyo');
-
-var
- dispatcher = require('../dispatcher'),
- emitter = require('../EventEmitter');
-
-
-var eventsMap = {
- vdrag: "drag",
- vscroll: "scroll",
- vmousewheel: "mousewheel",
- vtouch: "touchmove",
- drag: "vdrag",
- scroll: "vscroll",
- mousewheel: "vmousewheel",
- touchmove: "vtouch"
-};
-/**
-* This module handles the animation events for the character.
-* If the character has opted to have animations handled by animation framework,
-* then it can add "handleAnimationEvents" as true as its property.
-* The character can also mention which events he wants to be handled by the framework by
-* providing list of animation events in "animationEvents" block like;
-* {
-* name: "myKind",
-* animationEvents: [
-* "scroll",
-* "mousewheel",
-* "touchstart",
-* "touchmove",
-* "touchend"
-* ]
-* }
-*
-* By default these events are handled within the framework(others for now have to be handled by the application).
-*
-* This module is here temporarily, need to have a proper mechanism
-* like dispatcher to handle animation related events along with application events.
-*
-* @module enyo/AnimationSupport/EventDelegator
-*/
-var EventDelegator = {
-
- /**
- * @private
- */
- eventArray: [
- "drag",
- "scroll",
- "dragstart",
- "mousewheel",
- "touchstart",
- "touchmove",
- "touchend"
- ],
-
- /**
- * Attaches the evnet handlers to the character either its own events or
- * else default events with the framework. As of now only these events are
- * supported;
- * - scroll
- * - touch
- * - mousewheel
- * @public
- */
- register: function (charc) {
- var events = charc.handleAnimationEvents || {};
- for (var key in events) {
- this.addRemoveListener(charc, key, events[key]);
- }
- },
-
- /**
- * Detaches the evnet handlers from the character either its own events or
- * else default events from with the framework. As of now only these events are
- * supported;
- * - scroll
- * - touch
- * - mousewheel
- * @public
- */
- deRegister: function (charc) {
- var events = charc.handleAnimationEvents || {};
- for (var key in events) {
- this.addRemoveListener(charc, key, events[key], true);
- }
- },
-
- /**
- * @private
- */
- addRemoveListener: function(charc, name, callback, remove) {
- var d = remove ? dispatcher.stopListening : dispatcher.listen,
- e = eventsMap[name];
- d(charc.hasNode(), e, charc.bindSafely(this[e + 'Event'], charc));
-
- var fn = remove ? emitter.off : emitter.on;
- fn.apply(emitter, [name, charc[callback], charc]);
- },
-
- /**
- * @private
- */
- emitEvent: function(charc, data) {
- return emitter.vemit.call(emitter, data);
- },
-
- /**
- * @private
- */
- touchstartEvent: function (sender, inEvent) {
- sender.touchX = inEvent.targetTouches[0].pageX;
- sender.touchY = inEvent.targetTouches[0].pageY;
- },
-
- /**
- * @private
- */
- touchmoveEvent: function (sender, inEvent) {
- var x = inEvent.targetTouches[0].pageX,
- y = inEvent.targetTouches[0].pageY;
-
- if(x !== 0 || y !== 0) {
- /*sender.animDelta[0] = sender.touchX - x;
- sender.animDelta[1] = sender.touchY - y;
- sender.animDelta[2] = 0;*/
-
- // var o = {
- // dX: (sender.touchX - x),
- // dY: (sender.touchY - y),
- // dZ: 0
- // };
- // sender.setAnimationDelta(o);
- // sender.touchX = x;
- // sender.touchY = y;
-
- // this.eventName = eventsMap[inEvent.type];
-
- console.log(inEvent.targetTouches[0]);
-
- inEvent.dX = inEvent.deltaX;
- inEvent.dY = inEvent.deltaY;
- inEvent.dZ = 0;
- inEvent.vtype = eventsMap[inEvent.type];
-
- inSender.setAnimationDelta(inEvent);
- inSender._virtualEvent = eventsMap[inEvent.type];
- }
- },
-
- /**
- * @private
- */
- touchendEvent: function (sender, ev) {
- sender.touchX = 0;
- sender.touchY = 0;
- },
-
- /**
- * @private
- */
- scrollEvent: function (inSender, inEvent) {
- inEvent.dX = inEvent.deltaX;
- inEvent.dY = inEvent.deltaY;
- inEvent.dZ = 0;
- inEvent.vtype = eventsMap[inEvent.type];
-
- inSender.setAnimationDelta(inEvent);
- inSender._virtualEvent = eventsMap[inEvent.type];
- },
-
- /**
- * @private
- */
- dragstartEvent: function (inSender, inEvent) {
- this.dragLeft = inEvent.offsetX,
- this.dragTop = inEvent.offsetY;
- },
-
- /**
- * @private
- */
- dragEvent: function (inSender, inEvent) {
- var dragLeft = inEvent.offsetX,
- dragTop = inEvent.offsetY;
- if (dragLeft && dragTop) {
- this.deltaX = this.dragLeft - dragLeft;
- this.deltaY = this.dragTop - dragTop;
-
- this.dragLeft = dragLeft,
- this.dragTop = dragTop;
-
- /*this.animDelta[0] = this.deltaX;
- this.animDelta[1] = this.deltaY;
- this.animDelta[2] = 0;*/
-
- var o = {
- dX: this.deltaX,
- dY: this.deltaY,
- dZ: 0
- };
- this.setAnimationDelta(o);
-
- this.eventName = eventsMap[inEvent.type];
- }
- },
-
- /**
- * @private
- */
- mousewheelEvent: function (sender, inEvent) {
- inEvent.dX = inEvent.deltaX;
- inEvent.dY = inEvent.deltaY;
- inEvent.dZ = 0;
- inEvent.vtype = eventsMap[inEvent.type];
-
- sender.setAnimationDelta(inEvent);
- sender._virtualEvent = eventsMap[inEvent.type];
- }
-};
-
-module.exports = EventDelegator;
\ No newline at end of file
diff --git a/src/AnimationSupport/Fadeable.js b/src/AnimationSupport/Fadeable.js
deleted file mode 100644
index 425589767..000000000
--- a/src/AnimationSupport/Fadeable.js
+++ /dev/null
@@ -1,86 +0,0 @@
-var
- kind = require('../kind'),
- animation = require('./Core');
-
-/**
- * Interface to achieve fade animation
- *
- * @module enyo/AnimationSupport/Fadeable
- * @public
- */
-module.exports = {
-
- /**
- * @private
- */
- name: 'Fadeable',
-
- /**
- * To start animation
- */
- animate: true,
-
- /**
- * @private
- */
- fadableValue: 0,
-
- /**
- * @public
- * Make the character invisible
- */
- invisible: function() {
- this.addAnimation({
- opacity: 0
- });
- },
-
- /**
- * @public
- * Make the character transparent
- * @default 0.5
- * @parameter value - set transparency value
- */
- transparent: function(value) {
- value = value || 0.5;
- this.addAnimation({
- opacity: value
- });
- },
-
- /**
- * @public
- * Make the character visible
- */
- opaque: function() {
- this.addAnimation({
- opacity: 1
- });
- },
-
- /**
- * @public
- * Fade element based on event trigger
- */
- fadeByDelta: function(deltaValue) {
- if (deltaValue !== 0) {
- this.fadableValue = this.fadableValue + deltaValue * 0.1;
- if (this.fadableValue <= 0) {
- this.fadableValue = 0;
- } else if (this.fadableValue >= 1) {
- this.fadableValue = 1;
- }
- }
- this.addAnimation({
- opacity: this.fadableValue
- });
- },
-
- /**
- * @public
- * Bubble the fadeable event
- */
- /*triggerEvent: function(e) {
- this.doFadeStart();
- }*/
-};
diff --git a/src/AnimationSupport/Flippable.js b/src/AnimationSupport/Flippable.js
deleted file mode 100644
index aaa5c727c..000000000
--- a/src/AnimationSupport/Flippable.js
+++ /dev/null
@@ -1,71 +0,0 @@
-var
- kind = require('../kind'),
- animation = require('./Core');
-
-/**
- * Interface to achieve flip animation
- *
- * @module enyo/AnimationSupport/Flippable
- * @public
- */
-module.exports = {
-
- /**
- * @private
- */
- name: 'Flippable',
-
- /**
- * To start animation
- */
- animate: true,
-
- /**
- * Specifies the direction of flip. Accepted value are 'X', 'Y', 'Z'
- *
- * @type {String}
- * @default 'X'
- * @public
- */
- flipDirection: 'X',
-
- /**
- * Specifies the flip up-to angle. Accepted value are in degree
- *
- * @type {Number}
- * @default '0'
- * @public
- */
- flipAngle: 0,
-
- /**
- * @public
- * apply animation to the flippable DOM object
- */
- doFlip: function(deltaValue) {
- this.setAxis(deltaValue);
- },
-
- /**
- * @public
- * set axis of rotation of flippable DOM object
- */
- setAxis: function(delta) {
- var css = {};
- var dir = "";
- this.flipAngle = this.flipAngle + delta * 10;
- switch (this.flipDirection) {
- case "X":
- dir = "1,0,0," + this.flipAngle;
- break;
- case "Y":
- dir = "0,1,0," + this.flipAngle;
- break;
- case "Z":
- dir = "0,0,1," + this.flipAngle;
- break;
- }
- css["rotate"] = dir;
- this.addAnimation(css);
- }
-};
diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js
index 2393d0f77..64958157a 100644
--- a/src/AnimationSupport/Frame.js
+++ b/src/AnimationSupport/Frame.js
@@ -1,34 +1,40 @@
+/*jslint white: true*/
require('enyo');
var
Dom = require('../dom'),
Vector = require('./Vector'),
+ utils = require('../utils'),
Matrix = require('./Matrix');
var
- COLOR = {"color": 1, "backgroundColor": 1},
- TRANSFORM = {"translate": 1, "translateX": 1, "translateY": 1, "translateZ": 1, "rotateX": 1, "rotateY": 1, "rotateZ": 1, "rotate": 1, "skew": 1, "scale": 1, "perspective": 1};
+ BORDER = {'border-radius': 1, 'border-top-left-radius': 1, 'border-top-right-radius': 1, 'border-bottom-left-radius': 1, 'border-bottom-right-radius': 1, 'border-image-slice': 1},
+ COLOR = {'color': 1, 'background-color': 1, 'border-color': 1, 'border-top-color': 1, 'border-left-color': 1, 'border-right-color': 1, 'border-bottom-color': 1, 'fill': 1, 'flood-color': 1,'lighting-color': 1, 'stop-color': 1, 'outline-color': 1},
+ INT_UNIT = {'z-index': 1},
+ OPACITY = {'opacity': 1, 'flood-opacity': 1, 'stop-opacity': 1, 'fill-opacity': 1, 'stroke-opacity': 1},
+ TRANSFORM = {translate: 1, translateX: 1, translateY: 1, translateZ: 1, rotateX: 1, rotateY: 1, rotateZ: 1, rotate: 1, skew: 1, scale: 1, perspective: 1};
/**
-* Frame is a module responsible for providing animation features required for a frame.
-* This module exposes bunch of animation API's like matrix calculation,
-* fetching inital DOM properties and also applying style updates to DOM.
-*
-* These methods need to be merged with DOM API's of enyo.
-*
-* @module enyo/AnimationSupport/Frame
-*/
+ * Frame is a module responsible for providing animation features required for a frame.
+ * This module exposes bunch of animation API's like matrix calculation,
+ * fetching initial DOM properties and also applying style updates to DOM.
+ *
+ * These methods need to be merged with DOM API's of enyo.
+ *
+ * @module enyo/AnimationSupport/Frame
+ */
var frame = module.exports = {
/**
- * @public
- * Creates a matrix based on transformation vectors.
- * @param: trns- translate vector
- * rot - rotate quaternion vector
- * sc - scale vector
- * sq - sqew vector
- * per - perspective vector
- */
- recomposeMatrix: function(trns, rot, sc, sq, per) {
+ * Calculate matrix3d of a frame based on transformation vectors.
+ * @public
+ * @param {Number[]} trns Translate vector
+ * @param {Number[]} rot Rotate quaternion vector
+ * @param {Number[]} sc Scale vector
+ * @param {Number[]} sq Skew vector
+ * @param {Number[]} per Perspective vector
+ * @return {Number[]} Final Matrix3d for particular frame
+ */
+ recomposeMatrix: function (trns, rot, sc, sq, per) {
var i,
x = rot[0],
y = rot[1],
@@ -91,13 +97,13 @@ var frame = module.exports = {
},
/**
- * @public
- * Get transformation vectors out of matrix
- * @param matrix - Transformation matrix
- * ret - Return object which holds translate,
- * rotate, scale, sqew & perspective.
- */
- decomposeMatrix: function(matrix, ret) {
+ * Decompose transformation vectors into various properties out of matrix3d.
+ * @public
+ * @param {Number[]} matrix Matrix3d
+ * @param {Object} ret To store various transformation properties like translate, rotate, scale, skew and perspective.
+ * @return {Boolean} true, if matrix exists else false.
+ */
+ decomposeMatrix: function (matrix, ret) {
var i,
tV = [],
rV = [],
@@ -135,7 +141,7 @@ var frame = module.exports = {
row[1] = Vector.normalize(row[1]);
skV[0] /= scV[1];
- // Compute XZ and YZ shears, orthogonalize 3rd row
+ // Compute XZ and YZ shears, orthogonalized 3rd row
skV[1] = Vector.dot(row[0], row[2]);
row[2] = Vector.combine(row[2], row[0], 1.0, -skV[1]);
skV[2] = Vector.dot(row[1], row[2]);
@@ -175,34 +181,43 @@ var frame = module.exports = {
},
/**
- * Clones an array based on offset value.
- * @public
- */
- copy: function(v, offset) {
+ * Clones an array based on offset value.
+ * @public
+ * @param {Object} v Object with transformation properties like translate, rotate, scale, skew and perspective.
+ * @param {Number} offset Determine how many Object to copy.
+ * @return {Number[]} Array with sliced value based on offset.
+ */
+ copy: function (v, offset) {
return Array.prototype.slice.call(v, offset || 0);
},
/**
- * Validates if property is a transform property.
- * @public
- */
- isTransform: function(transform) {
+ * Validates if property is a transform property.
+ * @public
+ * @param {String} transform Any transform property, for which we want to identify whether or not the property is transform.
+ * @return {Number} Value of the required transform property.
+ */
+ isTransform: function (transform) {
return TRANSFORM[transform];
},
/**
- * Applies trasnformation to DOM element with the matrix values.
- * @public
- */
- accelerate: function (ele, m) {
+ * Applies transformation to DOM element with the Matrix3d values.
+ * @public
+ * @param {enyo.Component} actor Component to be animated.
+ * @param {Number[]} m Matrix3d
+ */
+ accelerate: function (actor, m) {
m = m ? m : Matrix.identity();
- frame.setTransformProperty(ele, m);
+ frame.setTransformProperty(actor, m);
},
/**
- * Reform matrix 2D to 3D
- * @public
- */
+ * Reform matrix 2D to 3D
+ * @public
+ * @param {Number[]} v Matrix(2d)
+ * @return {Number[]} Matrix3d
+ */
parseMatrix: function (v) {
var m = Matrix.identity();
v = v.replace(/^\w*\(/, '').replace(')', '');
@@ -221,19 +236,33 @@ var frame = module.exports = {
},
/**
- * Converts comma seperated values to array.
- * @public
- */
+ * Converts comma separated values to array.
+ * @public
+ * @param {String} val Value of required animation in any property.
+ * @return {Number[]} Create array from val.
+ */
parseValue: function (val) {
return val.toString().split(",").map(function(v) {
return parseFloat(v, 10);
});
},
+ parseShortHand: function (val, length) {
+ var res;
+ if (val.indexOf('rgb') === 0) {
+ res = this.parseValue(val.split(')')[0].replace(/^\w*\(/, '').concat(val.split(')')[1]));
+ } else {
+ res = this.parseValue(val.split('rgb(')[1].replace(')',',').concat(val.split('rgb(')[0]).replace(/, $/,''));
+ }
+ return res.concat(Array(length - res.length).fill(0));
+ },
+
/**
- * Gets a matrix for DOM element.
- * @public
- */
+ * Gets a matrix for DOM element.
+ * @public
+ * @param {HTMLElement} style CSS style declaration.
+ * @return {Number[]} Matrix3d
+ */
getMatrix: function (style) {
var m = style.getPropertyValue('transform') ||
style.getPropertyValue('-moz-transform') ||
@@ -247,16 +276,21 @@ var frame = module.exports = {
},
/**
- * Gets a style property applied from the DOM element.
- * @param: style - Computed style of a DOM.
- * key - property name for which style has to be fetched.
- * @public
- */
+ * Gets a style property applied from the DOM element.
+ * @public
+ * @param {HTMLElement} style Computed style of a DOM.
+ * @param {String} key Property name for which style has to be fetched.
+ * @return {Number|HTMLElement}
+ */
getStyleValue: function (style, key) {
var v = style.getPropertyValue(key) || style[key];
- if (v === undefined || v === null || v == "auto") {
+ if (!v || v === "auto") {
return 0;
}
+ if (key === 'box-shadow') {
+ if (v === 'none') return Array(7).fill(0);
+ return v.split(')')[0].replace(/^\w*\(/, '').concat(v.split(')')[1].split(' ').join(','));
+ }
if (COLOR[key]) {
return v.replace(/^\w*\(/, '').replace(')', '');
}
@@ -267,60 +301,82 @@ var frame = module.exports = {
return v;
},
-
/**
- * Applies style property to DOM element.
- * @public
- */
- setProperty: function (ele, prop, val) {
+ * Applies style property to DOM element.
+ * @public
+ * @param {enyo.Component} actor Component to be animated.
+ * @param {String} prop CSS property to be applied.
+ * @param {Number} val Value of the property applied.
+ */
+ setProperty: function (actor, prop, val) {
if (COLOR[prop]) {
val = val.map(function(v) { return parseInt(v, 10);});
- val = 'rgb('+ val + ')';
- } else if (prop == 'opacity') {
+ val = 'rgb('+ val + ')';
+ } else if(INT_UNIT[prop]) {
+ val = parseInt(val[0], 10);
+ } else if (BORDER[prop]) {
+ val = val[0] + '%';
+ } else if (OPACITY[prop]) {
val = val[0].toFixed(6);
val = (val <= 0) ? '0.000001' : val;
+ } else if (prop === 'box-shadow') {
+ val = 'rgb('+ val.slice(0, 3).map(function(v) { return parseInt(v, 10);})
+ + ') ' + val.slice(3).map(function(v) {return v + 'px'}).join(' ');
} else {
val = val[0] + 'px';
}
- ele.style[prop] = val;
+
+ actor.addStyles(prop + ':' + val + ';');
},
/**
- * Applies transform property to DOM element.
- * @public
- */
- setTransformProperty: function (element, matrix) {
+ * Applies transform property to DOM element.
+ * @public
+ * @param {enyo.Component} actor Component to be animated.
+ * @param {Number[]} matrix Matrix3d
+ */
+ setTransformProperty: function (actor, matrix) {
var mat = Matrix.toString(matrix);
- element.style.transform = mat;
+ /*element.style.transform = mat;
element.style.webkitTransform = mat;
element.style.MozTransform = mat;
element.style.msTransform = mat;
- element.style.OTransform = mat;
+ element.style.OTransform = mat;*/
+ actor.addStyles('transform:' + mat + ';'
+ + 'webkitTransform:' + mat + ';'
+ + 'MozTransform:' + mat + ';'
+ + 'msTransform' + mat + ';'
+ + 'OTransform' + mat + ';');
},
/**
- * Get DOM node animation properties.
- * @param: node- DOM node
- * props- Properties to fetch from DOM.
- * initial-Default properties to be applied.
- * @public
- */
+ * Get DOM node animation properties.
+ * @public
+ * @param {HTMLElement} node DOM node
+ * @param {Object} props Properties to fetch from DOM.
+ * @param {Object} initial Default properties to be applied.
+ * @return {Object} Object with various animation properties.
+ */
getComputedProperty: function (node, props, initial) {
if(!node) return;
var eP = {},
- sP = initial ? this.copy(initial) : {},
+ sP = initial ? utils.mixin({}, initial) : {},
tP = {},
dP = {},
- m, k, v,
+ m, k, u, v,
s = initial ? undefined : Dom.getComputedStyle(node);
for (k in props) {
v = sP[k];
if (!this.isTransform(k)) {
v = v || this.getStyleValue(s || Dom.getComputedStyle(node), k);
- eP[k] = this.parseValue(props[k]);
sP[k] = this.parseValue(v);
+ if (k === 'box-shadow' || COLOR[k]) {
+ eP[k] = this.parseShortHand(props[k], sP[k].length);
+ } else {
+ eP[k] = this.parseValue(props[k]);
+ }
} else {
v = this.parseValue(props[k]);
//tP[k] = k == 'rotate' ? Vector.toQuant(v) : v;
@@ -330,7 +386,7 @@ var frame = module.exports = {
if (initial) {
dP.translate = initial.translate;
- dP.rotate = initial.rotate;
+ dP.rotate = initial.rotate.length < 4 ? Vector.toQuant(initial.rotate) : initial.rotate;
dP.scale = initial.scale;
dP.skew = initial.skew;
dP.perspective = initial.perspective;
@@ -346,10 +402,18 @@ var frame = module.exports = {
return {_startAnim: sP, _endAnim: eP, _transform: dP, currentState: dP, matrix: m, props: props};
},
+ /**
+ * Get DOM node animation distance.
+ * @public
+ * @param {HTMLElement} prop DOM node properties.
+ * @param {Object} initalProp Initial properties to fetch from DOM.
+ * @param {Object} finalProp Final properties to be applied.
+ * @return {Object} Total computed distance to animate.
+ */
getComputedDistance: function (prop, initalProp, finalProp) {
var k, sV, eV, dst, tot = 0;
for (k in prop) {
- sV = k==='rotate' ? Vector.quantToVector(initalProp[k]) : initalProp[k];
+ sV = (k === 'rotate' ? Vector.quantToVector(initalProp[k]) : initalProp[k]);
eV = finalProp[k];
dst = Vector.distance(eV, sV);
tot += dst;
diff --git a/src/AnimationSupport/FrameEditor.js b/src/AnimationSupport/FrameEditor.js
deleted file mode 100644
index 20632f5fb..000000000
--- a/src/AnimationSupport/FrameEditor.js
+++ /dev/null
@@ -1,63 +0,0 @@
-require('enyo');
-
-module.exports = {
-/**
- *
- *
- * @public
- */
-
- timeline: 0,
- _cachedValue: 0,
- _frameSpeed: 1,
-
-
- cache: function(){
- if(this._frameSpeed === 0){
- this._frameSpeed = this._cachedValue;
- }
- },
- play : function (){
- this._frameSpeed = 1;
- },
-
- resume: function() {
- this.cache();
- this._frameSpeed *= 1;
- },
-
- pause: function () {
- this._cachedValue = this._frameSpeed;
- this._frameSpeed = 0;
- },
-
- reverse: function () {
- this.cache();
- this._frameSpeed *= -1;
- },
-
- fast: function (mul) {
- this.cache();
- this._frameSpeed *= mul;
- },
-
- slow: function (mul) {
- this.cache();
- this._frameSpeed *= mul;
- },
-
- stop: function () {
- this._cachedValue = 1;
- this._frameSpeed = 0;
- this.timeline = 0;
- },
-
- rolePlay: function (t) {
- this.timeline += _rolePlay(t, this._frameSpeed);
- return this.timeline;
- }
-};
-
-function _rolePlay(t, mul) {
- return mul * t;
-}
\ No newline at end of file
diff --git a/src/AnimationSupport/HierarchicalMixin.js b/src/AnimationSupport/HierarchicalMixin.js
deleted file mode 100644
index e618f58c4..000000000
--- a/src/AnimationSupport/HierarchicalMixin.js
+++ /dev/null
@@ -1,120 +0,0 @@
-require('enyo');
-
-var
- kind = require('../kind'),
- Dom = require('../dom'),
- animation = require('./Core'),
- VerticalDelegate = require('../VerticalDelegate');
-
-/**
-* A mixin support for Hierarchical components
-* @module enyo/HierarchicalMixin
-*/
-module.exports = {
- /**
- * @private
- */
- _pageScrolltop: 0,
-
- /**
- * @private
- */
- _paged: false,
-
- /**
- * Mixin creation
- *
- * @method
- * @private
- */
- create: kind.inherit(function(sup) {
- return function() {
- sup.apply(this, arguments);
- this.addListener('paging', this._pagingHandler.bind(this));
- this.clientHeight = Dom.getWindowHeight();
- };
- }),
-
- /**
- * Mixin creation
- *
- * @method
- * @private
- */
- didScroll: kind.inherit(function(sup) {
- return function() {
- sup.apply(this, arguments);
- var top = event ? event.scrollBounds.top : 0;
- if (this._paged) {
- this._pageScrolltop = top;
- this._paged = false;
- }
- this._animateChild(this.controls, event ? event.scrollBounds.top - this._pageScrolltop: 0);
- };
- }),
-
- /**
- * Handler for pagging event when its triggered from vertical delegate of data grid list
- *
- * @method
- * @private
- */
- _pagingHandler: function() {
- this._paged = true;
- for (var i=0, node; (node = this.controls[i]); i++) {
- node._bounds = node.getAbsoluteBounds();
- }
- },
-
- /**
- * Apply animation on all the child nodes which are visible inside the viewport
- *
- * @method
- * @private
- */
- _animateChild: function(nodes, top) {
- var showing;
- for (var i=0, node; (node = nodes[i]); i++) {
- showing = this._getNodeShowing(node, top);
- if (node.hasNode() && showing && !node.animating) {
- node.start(true);
- }
- }
- },
-
- /**
- * Checks if the node element in visible inside the viewport
- *
- * @method
- * @private
- */
- _getNodeShowing: function(node, top) {
- var showing, rect = node._bounds;
- if (rect) {
- showing = ((rect.top >= top) && ((rect.top - top) <= this.clientHeight));
- } else {
- showing = false;
- }
- return showing;
- }
-};
-
-/**
- Hijacking original behaviour of delegates.
-*/
-var sup = VerticalDelegate.generate;
-
-VerticalDelegate.generate = function(list) {
- sup.call(this, list);
- for (var i=0, p; (p=list.pages[i]); ++i) {
- for (var j=0, c; (c=p.children[j]); ++j) {
- c._bounds = c.getAbsoluteBounds();
- c.animate = list.animate;
- c.duration = list.duration;
- animation.trigger(c);
- if (list._getNodeShowing(c, 0)) {
- c.start(true);
- }
- }
- }
-};
\ No newline at end of file
diff --git a/src/AnimationSupport/KeyFrame.js b/src/AnimationSupport/KeyFrame.js
deleted file mode 100644
index 61b904498..000000000
--- a/src/AnimationSupport/KeyFrame.js
+++ /dev/null
@@ -1,133 +0,0 @@
-require('enyo');
-
-var
- kind = require('../kind'),
- animation = require('./Core'),
- utils = require('../utils'),
- CoreObject = require('../CoreObject');
-
-/**
- * This module returns the Loop singleton
- * @module enyo/KeyFrame
- */
-var keyFrame = module.exports = kind.singleton({
- /** @lends module:enyo/KeyFrame */
-
- /**
- * @private
- */
- name: 'enyo.KeyFrame',
- /**
- * @private
- */
- kind: CoreObject,
-
- /**
- * KeyFrame base API to perform animation on any document element
- * repersented as a Character. The purpose of this method is to add a new
- * character to Animation Core based on animation properties passed as
- * parameter to this function and also to manage the frames allocated to
- * each of individual poses.
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- * @parameter charc- Character responsible for animation.
- * keyframe- Key frame Animation propeties represented as CSS objects.
- * like: {0: {"rotateX": "0"}, 50: {"rotateX": "90"}, 100: {"rotateX": "180"}}
- * @public
- */
- animate: function(charc, proto) {
- var prop, easeInd,
- cb = proto.completed,
- keyframe = proto.keyFrame;
- charc.keyProps = [];
- charc.keyTime = [];
- charc.currentIndex = 0;
- for (prop in keyframe) {
- charc.keyTime.push(prop);
- charc.keyProps.push(keyframe[prop]);
- }
- charc.keyframeCallback = cb;
- charc.totalDuration = proto.duration;
- this.keyFraming(charc);
- charc.completed = this.bindSafely(this.reframe);
- //this.keyFraming(charc);
- this.trigger(charc);
- },
-
- /**
- * KeyFrame's public API to reverse an animation.
- * The purpose of this method is to find the animating character based on
- * the DOM provided and reversing a keyframe animation by interchanging its intial
- * state with final state and final state with current state
- *
- * As of now this method is provided as an interface for application
- * to directly trigger an animation. However, this will be later made private
- * and will be accessible only by the interfaces exposed by framework.
- * @parameter dom- Document element on which animation will be reversed.
- *
- * @public
- */
- reverse: function(dom) {
- var charc = animation.exists(dom),
- finalState, duration;
- if (charc) {
- finalState = charc._startAnim;
- duration = utils.perfNow() - charc.initialTime;
- animation.remove(charc);
-
- charc.setAnimation(finalState);
- charc.setInitial(charc.currentState);
- charc.setDuration(duration);
- charc.totalDuration = duration;
- charc.keyProps = [];
- charc.keyTime = [];
- charc.animating = false;
- this.trigger(charc);
- }
- },
-
- trigger: function(charc) {
- if (charc.handleAnimationEvents && typeof charc.handleAnimationEvents != 'function') {
- animation.register(charc);
- } else
- animation.trigger(charc);
- }
-});
-
-/**
- * @private
- */
-keyFrame.keyFraming = function(charc) {
- var index = charc.currentIndex || 0,
- old = charc.keyTime[index - 1] || 0,
- next = charc.keyTime[index],
- total = charc.totalDuration,
- change = total ? total * ((next - old) / 100) : "0";
- charc.addAnimation(charc.keyProps[index]);
-
- // code to separate the ease component from keyframe and making it available for animation
- if (charc.keyProps[index].hasOwnProperty('ease')) {
- charc.ease = charc.keyProps[index].ease;
- delete charc.keyProps[index].ease;
- }
-
- if (charc.totalDuration) charc.setDuration(change);
- charc.animating = false;
- charc.currentIndex = index;
-};
-
-/**
- * @private
- */
-keyFrame.reframe = function(charc) {
- charc.reverse ? charc.currentIndex-- : charc.currentIndex++;
- if (charc.currentIndex >= 0 && charc.currentIndex < charc.keyTime.length) {
- this.keyFraming(charc);
- charc.start(true);
- } else {
- //Tigerring callback function at end of animation
- charc.keyframeCallback && charc.keyframeCallback(this);
- }
-};
diff --git a/src/AnimationSupport/Matrix.js b/src/AnimationSupport/Matrix.js
index fb59144ed..9befb02c4 100644
--- a/src/AnimationSupport/Matrix.js
+++ b/src/AnimationSupport/Matrix.js
@@ -1,56 +1,81 @@
require('enyo');
/**
-* Matrix module for matrix related calculation
-*
-* @module enyo/AnimationSupport/Matrix
-*/
+ * Matrix module for matrix related calculation
+ *
+ * @module enyo/AnimationSupport/Matrix
+ */
module.exports = {
/**
- * @public
- */
+ * To create Identity Matrix3d (4X4 order).
+ * @public
+ * @return {Number[]} Identity Matrix3d
+ */
identity: function() {
return [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];
},
/**
- * @public
- */
+ * To translate in any dimension based on co-ordinates.
+ * @public
+ * @param {Number} x Translate value in X axis
+ * @param {Number} y Translate value in Y axis
+ * @param {Number} z Translate value in Z axis
+ * @return {Number[]} Matrix3d
+ */
translate: function (x, y, z) {
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y ? y : 0, z ? z : 0, 1];
},
/**
- * @public
- */
+ * To translate in x dimension
+ * @public
+ * @param {Number} x Translate value in X axis
+ * @return {Number[]} Matrix3d
+ */
translateX: function (x) {
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x ? x : 0, 0, 0, 1];
},
/**
- * @public
- */
+ * To translate in y dimension
+ * @public
+ * @param {Number} y Translate value in Y axis
+ * @return {Number[]} Matrix3d
+ */
translateY: function (y) {
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, y ? y : 0, 0, 1];
},
/**
- * @public
- */
+ * To translate in z dimension
+ * @public
+ * @param {Number} z Translate value in Z axis
+ * @return {Number[]} Matrix3d
+ */
translateZ: function (z) {
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, z ? z : 0, 1];
},
/**
- * @public
- */
+ * To scale in any dimension
+ * @public
+ * @param {Number} x Scale value in X axis
+ * @param {Number} y Scale value in Y axis
+ * @param {Number} z Scale value in Z axis
+ * @return {Number[]} Matrix3d
+ */
scale: function (x, y, z) {
return [x, 0, 0, 0, 0, y ? y : 1, 0, 0, 0, 0, z ? z : 1, 0, 0, 0, 0, 1];
},
/**
- * @public
- */
+ * To skew in any dimension (skew can only happen in 2d)
+ * @public
+ * @param {Number} a Skew value in X axis
+ * @param {Number} b Skew value in Y axis
+ * @return {Number[]} Matrix3d
+ */
skew: function (a, b) {
a = a ? Math.tan(a * Math.PI / 180): 0;
b = b ? Math.tan(b * Math.PI / 180): 0;
@@ -58,8 +83,11 @@ module.exports = {
},
/**
- * @public
- */
+ * To rotate in x-axis
+ * @public
+ * @param {Number} a Rotate value in X axis
+ * @return {Number[]} Matrix3d
+ */
rotateX: function (a) {
var cosa, sina;
a = a * Math.PI / 180;
@@ -69,8 +97,11 @@ module.exports = {
},
/**
- * @public
- */
+ * To rotate in y-axis
+ * @public
+ * @param {Number} b Rotate value in Y axis
+ * @return {Number[]} Matrix3d
+ */
rotateY: function (b) {
var cosb, sinb;
b = b * Math.PI / 180;
@@ -80,8 +111,11 @@ module.exports = {
},
/**
- * @public
- */
+ * To rotate in z-axis
+ * @public
+ * @param {Number} g Rotate value in Z axis
+ * @return {Number[]} Matrix3d
+ */
rotateZ: function (g) {
var cosg, sing;
g = g * Math.PI / 180;
@@ -91,8 +125,13 @@ module.exports = {
},
/**
- * @public
- */
+ * To rotate in any dimension
+ * @public
+ * @param {Number} a Rotate value in X axis
+ * @param {Number} b Rotate value in Y axis
+ * @param {Number} g Rotate value in Z axis
+ * @return {Number[]} Matrix3d
+ */
rotate: function (a, b, g) {
a = a * Math.PI / 180;
b = b * Math.PI / 180;
@@ -122,8 +161,12 @@ module.exports = {
},
/**
- * @public
- */
+ * To multiply 2 Martix3d (4x4 order)
+ * @public
+ * @param {Number[]} m1 1st Matrix3d
+ * @param {Number[]} m2 2nd Matrix3d
+ * @return {Number[]} Resultant Matrix3d
+ */
multiply: function(m1, m2) {
return [
m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2],
@@ -146,8 +189,12 @@ module.exports = {
},
/**
- * @public
- */
+ * To multiply 2 matrices (NxN order)
+ * @public
+ * @param {Number[]} m1 1st Matrix of order N
+ * @param {Number[]} m2 2nd Matrix of order N
+ * @return {Number[]} Resultant Matrix of order N
+ */
multiplyN: function(m1, m2) {
var i, j, sum,
m = [],
@@ -165,8 +212,12 @@ module.exports = {
},
/**
- * @public
- */
+ * To inverse matrix of order N
+ * @public
+ * @param {Number[]} matrix Matrix (NxN order)
+ * @param {Number} n Order of the matrix
+ * @return {Number[]} Inverted Matrix
+ */
inverseN: function(matrix, n) {
var i, j, k, r, t,
precision = 100000,
@@ -212,8 +263,11 @@ module.exports = {
},
/**
- * @public
- */
+ * Convert Matrix3d array to Matrix3d String
+ * @public
+ * @param {Number[]} m Matrix3d Array
+ * @return {String} Matrix3d String
+ */
toString: function (m) {
var ms = 'matrix3d(';
for (var i = 0; i < 15; i++) {
diff --git a/src/AnimationSupport/Parallax.js b/src/AnimationSupport/Parallax.js
deleted file mode 100644
index e52680d8c..000000000
--- a/src/AnimationSupport/Parallax.js
+++ /dev/null
@@ -1,63 +0,0 @@
-/*jslint white: true*/
-var
- kind = require('../kind'),
- utils = require('../utils'),
- animation = require('./Core'),
- Slideable = require('enyo/AnimationSupport/Slideable');
-
-/**
- * Interface to achieve Parallax animation
- *
- * @module enyo/AnimationSupport/Parallax
- * @public
- */
-module.exports = {
-
- /**
- * @private
- */
- name: 'Parallax',
-
- /**
- * @private
- */
- animate: true,
-
- /**
- * @public
- *
- */
- rendered: kind.inherit(function(sup) {
- return function() {
- sup.apply(this, arguments);
- this.doParallax(this);
- };
- }),
-
- /**
- * @public
- *
- */
- commonTasks: function(delta, deltax, deltay) {
- var children = this.children;
- for (var i = 0; i < children.length; i++) {
- var speed = children[i].speed;
- children[i].slide.call(children[i], (-1 * deltax) / speed, (-1 * deltay) / speed, 0);
- children[i].start(true);
- }
- },
-
- /**
- * @public
- *
- */
- doParallax: function(container, deltax, deltay) {
- var container = this.children;
- for (var i = 0; i < this.children.length; i++) {
- var currentElement = this.children[i];
- utils.mixin(currentElement, Slideable);
- animation.trigger(currentElement);
- }
- }
-
-};
diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js
new file mode 100644
index 000000000..fa6b7ad4a
--- /dev/null
+++ b/src/AnimationSupport/Scene.js
@@ -0,0 +1,405 @@
+var
+ editor = require('./SceneEditor'),
+ director = require('./Director'),
+ animation = require('../animation'),
+ utils = require('../utils');
+
+/**
+ * This module exports "Scene" which is a class/constructor so that we can create an instance of the same.
+ * We can define all the animation properties we want in the application in the instance of the "Scene".
+ *
+ * @module enyo/AnimationSupport/Scene
+ */
+var Scene = module.exports = function(props) {
+ var scene = Scene.create(),
+ dur = props.duration || 0;
+
+ utils.mixin(scene, editor);
+
+ if (props.animation) {
+ var anims = utils.isArray(props.animation) ? props.animation : [props.animation];
+
+ for (var i = 0; i < anims.length; i++) {
+ scene.addAnimation(anims[i], anims[i].span || anims[i].duration || dur, anims[i].delay);
+ delete anims[i].duration;
+ delete anims[i].delay;
+ }
+ delete props.animation;
+ delete props.duration;
+ }
+
+ utils.mixin(scene, props);
+ utils.mixin(scene, SceneAction);
+ return scene;
+};
+
+
+/**
+ * Creates a empty instance of scene.
+ * Can be used for runtime creation of animations
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ * @return {Object} An instance of the constructor
+ */
+Scene.create = function() {
+ return new sceneConstructor(utils.uid("@"));
+};
+
+
+/**
+ * Connects an actor/s to a scene.
+ * All the actors should be added before initiating animation otherwise actors will animate for remaining time span
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ * @param {Object} actors - The elements which needs to be animated
+ * @param {Object} scene - The instance of the Scene we've created in the application
+ */
+Scene.link = function(actors, scene) {
+ director.cast(actors, scene);
+};
+
+
+/**
+ * Disconnects an actor/s from a scene.
+ * (Actors could be delinked during the animation
+ * however they will current their state when delinked)
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ * @param {Object} actors - The elements which needs to be animated
+ * @param {Object} scene - The instance of the Scene we've created in the application
+ */
+Scene.delink = function(actors, scene) {
+ director.reject(scene, actors);
+};
+
+
+/**
+ * Function to construct all the scenes instantiated from the Scene
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ * @param {number} id - id of the scene generated when created
+ * @return {object} Constructed instance
+ */
+var sceneConstructor = function(id) {
+ var
+ _ts, _wasts, _req,
+ _framerate = 16.6,
+ /**
+ * Stores the id of the instance created
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ * @type {Array}
+ */
+ _id = id,
+
+ /**
+ * Holds refereneces of the all animations added to this scene.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ * @type {Array}
+ */
+ _poses = [],
+
+ /**
+ * Holds old animation time span, useful for scenarios where same
+ * time span is expected to be added for the latest added animation.
+ * This provides the felxibility to add animation without duration.
+ *
+ * Like: scene.addAnimation({translate: '50,0,0'});
+ *
+ * As no duration is mentioned the old animations duration is taken.
+ * @type {Number}
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ */
+ _prevDur = 0;
+
+ /**
+ * An exposed property to know if know the animating state of this scene.
+ * 'true' - the scene is asked for animation(doesn't mean animation is happening)
+ * 'false' - the scene is not active(has completed or its actors are not visible)
+ * @type {Boolean}
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.animating = false;
+
+ /**
+ * An exposed property to know if the scene is ready with actors performing action.
+ * 'true' - the scene actors are ready for action
+ * 'false' - some or all actors are not ready
+ * @type {Boolean}
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.active = false;
+
+ /**
+ * Holds refereneces of complete time span for this scene.
+ * @type {Number}
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.span = 0;
+
+
+ /**
+ * Function used to loop in all the animations in a scene
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ */
+ function loop() {
+ if (this.animating) {
+ _ts = utils.perfNow();
+ _ts = _ts - (_wasts !== undefined ? _wasts : _ts);
+ _ts = (_ts > _framerate) ? _framerate : _ts;
+ director.take(this, _ts);
+ _wasts = _ts;
+ this.trigger(true);
+ } else {
+ _wasts = undefined;
+ this.cancel();
+ this.completed && this.completed();
+ }
+ }
+ /**
+ * Function used to make start the animation if it is "true" for animating.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.ready = function() {
+ if (this.animating) {
+ if (!this.active) {
+ director.roll(this);
+ }
+ return this.active;
+ }
+ return false;
+ };
+
+ /**
+ * Cancel the animation
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.cancel = function() {
+ animation.cancelRequestAnimationFrame(_req);
+ };
+
+
+ /**
+ * Triggers the Request Animation Frame
+ * @param {boolean} force - A boolean value for letting the rAF start.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.trigger = function(force) {
+ if (force || !this.animating) {
+ _req = animation.requestAnimationFrame(utils.bindSafely(this, loop));
+ }
+ };
+
+
+ /**
+ * Gets the unique ID assigned to this sceen.
+ * @return {number} - id
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.getID = function() {
+ return _id;
+ };
+
+
+ /**
+ * Returns the life span/duration of this sceen.
+ * @return {number} life span/duration of this sceen
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.totalSpan = function() {
+ return this.span;
+ };
+
+ /**
+ * Adds new animation on already existing animation for this character.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.addAnimation = function(newProp, span, delay) {
+ if (_prevDur === 0 && span === 0) {
+ var index = 0;
+ if (delay) {
+ _prevDur = delay;
+ this.span += _prevDur;
+ _poses[index++] = {
+ span: this.span
+ };
+ }
+ _prevDur = 0;
+ _poses[index] = {
+ animate: newProp,
+ span: this.span
+ };
+ } else {
+ if (delay) {
+ _prevDur = delay;
+ this.span += _prevDur;
+ _poses.push({
+ span: this.span
+ });
+ }
+ _prevDur = span || _prevDur;
+ this.span += _prevDur;
+ _poses.push({
+ animate: newProp,
+ span: this.span
+ });
+ }
+ };
+ /**
+ * Function which returns the length of the poses.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ * @return {number} - length of the poses
+ */
+ this.length = function() {
+ return _poses.length;
+ };
+ /**
+ * Returns animation pose index for a particular
+ * instance of time from the list of
+ * animations added to the scene.
+ * @param {number} span - Time span from the animation timeline
+ * @return {number} - index of the animation
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.animateAtTime = function(span) {
+ var startIndex = 0,
+ stopIndex = _poses.length - 1,
+ middle = Math.floor((stopIndex + startIndex) / 2);
+
+ if (span === 0) {
+ return startIndex;
+ }
+
+ while (_poses[middle].span != span && startIndex < stopIndex) {
+ if (span < _poses[middle].span) {
+ stopIndex = middle;
+ } else if (span > _poses[middle].span) {
+ startIndex = middle + 1;
+ }
+
+ middle = Math.floor((stopIndex + startIndex) / 2);
+ }
+ return (_poses[middle].span != span) ? startIndex : middle;
+ };
+
+ /**
+ * Clears/removes the animation
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.clearAnimation = function() {
+ for (var i = 0; i < _poses.length; i++) {
+ _poses[i]._startAnim = undefined;
+ }
+ };
+
+ /**
+ * Returns animation pose based on index from the list of
+ * animations added to this scene.
+ * @param {number} index - animation's index from the list of animations
+ * @return {Object} pose of the animation based on the index in the list
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.getAnimation = function(index) {
+ return index < 0 || _poses[index];
+ };
+
+ /**
+ * Sets the newly added animation to the poses
+ * @param {Numner} index - index to which the new animation should set
+ * @param {Object} pose - newly added animation
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.setAnimation = function(index, pose) {
+ _poses[index] = pose;
+ };
+
+
+ //TODO: Move these events to Event Delegator
+ /**
+ * Event to identify when the scene has done animating.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.completed = function() {};
+
+ /**
+ * Event to identify when the scene has done a step(rAF updatation of time) in the animation.
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.step = function() {};
+
+ /**
+ * Event to identify when the actor has done animating.
+ * @param {Object} actor - animating element
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @public
+ */
+ this.actorCompleted = function(actor) {};
+};
+
+/**
+ * SceneAction exposes the api which performs the action on the animation in a given scene
+ * @type {Object}
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ */
+var SceneAction = {
+ /**
+ * This function initiates action on the animation
+ * from the list of animations for a given scene.
+ * @param {number} ts - timespan
+ * @param {Object} pose - pose from the animation list
+ * @return {Object} - pose
+ * @memberOf module:enyo/AnimationSupport/Scene
+ * @private
+ */
+ action: function(ts, pose) {
+ var past,
+ actor,
+ actors,i,
+ tm = this.rolePlay(ts),
+ index = this.animateAtTime(tm);
+
+ if (index < 0) {
+ return;
+ }
+ pose = this.getAnimation(index);
+ past = pose.animate;
+
+ if (past instanceof sceneConstructor) {
+ past._frameSpeed = this._frameSpeed;
+ director.take(past, ts);
+ } else {
+ past = index ? this.getAnimation(index - 1).span : 0;
+ actors = this.rolePlays[this.getID()];
+ for (i = 0; (actor = actors[i]); i++) {
+ if (actor.generated) {
+ director.action(pose,
+ actors[i],
+ tm - past,
+ pose.span - past);
+ this.step && this.step(actor);
+ }
+ }
+ }
+ return pose;
+ }
+};
\ No newline at end of file
diff --git a/src/AnimationSupport/SceneActor.js b/src/AnimationSupport/SceneActor.js
new file mode 100644
index 000000000..81eb194fd
--- /dev/null
+++ b/src/AnimationSupport/SceneActor.js
@@ -0,0 +1,65 @@
+var
+ Scene = require('./Scene'),
+ director = require('./Director'),
+ utils = require('../utils');
+
+var
+ tm, actor, actors, len, dur;
+
+var CharacterAction = {
+ /**
+ * Overridden function initiates action on the animation
+ * for the given scene actor.
+ * @param {number} ts - timespan
+ * @param {Object} pose - pose from the animation list
+ * @return {Object} - pose
+ * @memberOf module:enyo/AnimationSupport/SceneActor
+ * @private
+ * @override
+ */
+ action: function (ts, pose) {
+ var i, past, index;
+
+ actors = this.rolePlays[this.getID()];
+ len = actors.length;
+ dur = this.span;
+ for (i = 0; (actor = actors[i]); i++) {
+ //give priority to individual actor than scene.
+ if (!actor._frameSpeed) {
+ actor._frameSpeed = this._frameSpeed;
+ }
+
+ if (actor.generated && actor._frameSpeed) {
+ tm = this.rolePlay(ts, actor);
+ if (isNaN(tm) || tm < 0) continue;
+ else if (tm <= dur) {
+ index = this.animateAtTime(tm);
+ pose = this.getAnimation(index);
+ past = index ? this.getAnimation(index - 1).span : 0;
+ director.action(pose, actor, tm - past, pose.span - past);
+ this.step && this.step(actor);
+ } else {
+ actor.timeline = dur;
+ actor._frameSpeed = 0;
+ this.actorCompleted && this.actorCompleted(actor);
+ }
+ }
+ }
+ return pose;
+ }
+};
+
+/**
+ * Scene Actor is used to individually manage all the actors
+ * The Scene Actor is similar to Scene but can receive
+ * an actor for playing the animation.
+ * Scene Actor's play when called without the actor,
+ * it works same as Scene playing all the actors.
+ * Usage - SceneActorInstance.play(actor)
+ * @module enyo/AnimationSupport/SceneActor
+ */
+module.exports = function(props) {
+ var scene = Scene(props);
+ utils.mixin(scene, CharacterAction);
+ return scene;
+};
diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js
new file mode 100644
index 000000000..14824613a
--- /dev/null
+++ b/src/AnimationSupport/SceneEditor.js
@@ -0,0 +1,192 @@
+require('enyo');
+
+/**
+* @module enyo/AnimationSupport/SceneEditor
+*/
+
+/**
+* This modules exposes API's for controlling animations.
+* @private
+*/
+module.exports = {
+ /**
+ * @private
+ */
+ timeline: 0,
+ /**
+ * @private
+ */
+ _cachedValue: 0,
+ /**
+ * @private
+ */
+ _frameSpeed: 0,
+ /**
+ * @private
+ */
+ _startTime: 0,
+
+ /**
+ * @private
+ */
+ cache: function(actor) {
+ actor = actor || this;
+ if(actor._frameSpeed === 0){
+ actor._frameSpeed = actor._cachedValue;
+ }
+ this.animating = true;
+ },
+
+ /**
+ * Starts the animation of the actor given in argument.
+ * If actor is not provided, animation of all the components linked to the {@link module:enyo/AnimationSupport/Scene} will be started.
+ * @param [Component]{@link module:enyo/Component~Component} actor The component to be animated
+ * @public
+ */
+ play: function (actor) {
+ actor = actor || this;
+ actor._frameSpeed = 1;
+ if (isNaN(actor.timeline) || !actor.timeline) {
+ actor.timeline = 0;
+ }
+ this.trigger();
+ this.animating = true;
+ },
+
+ /**
+ * Resumes the paused animation of the actor given in argument.
+ * If actor is not provided, animation of all the components linked to the {@link module:enyo/AnimationSupport/Scene} will be resumed.
+ * @param [Component]{@link module:enyo/Component~Component} actor The component to be animated
+ * @public
+ */
+ resume: function(actor) {
+ this.cache(actor);
+ actor = actor || this;
+ actor._frameSpeed *= 1;
+ },
+
+ /**
+ * Pauses the animation of the actor given in argument.
+ * If actor is not provided, animation of all the components linked to the {@link module:enyo/AnimationSupport/Scene} will be paused.
+ * @param [Component]{@link module:enyo/Component~Component} actor The component to be animated
+ * @public
+ */
+ pause: function (actor) {
+ actor = actor || this;
+ actor._cachedValue = actor._frameSpeed;
+ actor._frameSpeed = 0;
+ },
+
+ /**
+ * Reverses the animation of the actor given in argument.
+ * If actor is not provided, animation of all the components linked to the {@link module:enyo/AnimationSupport/Scene} will be reversed.
+ * @param [Component]{@link module:enyo/Component~Component} actor The component to be animated
+ * @public
+ */
+ reverse: function (actor) {
+ this.cache(actor);
+ actor = actor || this;
+ actor._frameSpeed *= -1;
+ },
+
+ /**
+ * fast description goes here
+ * @param {Number} mul description goes here
+ * @param [Component]{@link module:enyo/Component~Component} actor description goes here
+ * @public
+ */
+ fast: function (mul, actor) {
+ this.cache(actor);
+ actor = actor || this;
+ actor._frameSpeed *= mul;
+ },
+
+ /**
+ * slow description goes here
+ * @param {Number} mul description goes here
+ * @param [Component]{@link module:enyo/Component~Component} actor description goes here
+ * @public
+ */
+ slow: function (mul, actor) {
+ this.cache(actor);
+ actor = actor || this;
+ actor._frameSpeed *= mul;
+ },
+
+ /**
+ * Changes the speed of the animation.
+ * Speed of the animation changed based on the factor.
+ * To slow down the speed use values between 0 and 1. For Example 0.5 to reduce the speed by 50%.
+ * To increase the speed use values above 1. For Example 2 to increase the speed by 200%.
+ * Animation will be paused if factor is 0. To pause the animation use {@link enyo/AnimationSupport/SceneEditor.pause pause} API.
+ * Speed will not be affected incase of negative multiplication factor.
+ * @param {Number} factor Multiplication factor which changes the speed
+ * @param [Component {@link module:enyo/Component~Component}] actor The component whose animating speed should be changed
+ * @public
+ */
+ speed: function(mul, actor) {
+ if (mul < 0) return;
+ this.cache(actor);
+ actor = actor || this;
+ actor._frameSpeed *= mul;
+ },
+
+ /**
+ * Stops the animation of the actor given in argument.
+ * If actor is not provided, animation of all the components linked to the {@link module:enyo/AnimationSupport/Scene} will be stopped.
+ * @param [Component]{@link module:enyo/Component~Component} actor The component to be animated
+ * @public
+ */
+ stop: function (actor) {
+ actor = actor || this;
+ actor._cachedValue = 1;
+ actor._frameSpeed = 0;
+ actor.timeline = 0;
+ this.animating = false;
+ this.cancel();
+ },
+
+ /**
+ * Seeks the animation of the actor to the position provided in timeline
+ * The value of timeline should be between 0 to duration of the animation.
+ * @param {Number} timeline Value in timeline where the animation has to be seeked
+ * @param [Component]{@link module:enyo/Component~Component} actor The component to be animated
+ * @public
+ */
+ seek: function(timeline, actor) {
+ actor = actor || this;
+ if (this.animating !== true) {
+ this.play(actor);
+ this.pause(actor);
+ }
+ actor.timeline = timeline;
+ },
+
+ /**
+ * rolePlay updated the timeline of the actor which is currently animating.
+ * @param {Number} t Elapsed time since the animation of this pose has started (ratio in factor of 1)
+ * @param {@link module:enyo/Component~Component} actor The component which is animating
+ * @return {Number} Returns the updated timeline of the actor
+ * @access public
+ */
+ rolePlay: function (t, actor) {
+ actor = actor || this;
+ if (actor.timeline === undefined || actor.timeline < 0)
+ actor.timeline = 0;
+
+ if(actor.delay > 0) {
+ actor.delay -= _rolePlay(t, actor._frameSpeed);
+ } else {
+ actor.timeline += _rolePlay(t, actor._frameSpeed);
+ }
+ return actor.timeline;
+ }
+};
+
+/**
+ * Returns the time based on the current speed of animation.
+ * @private
+ */
+function _rolePlay(t, mul) {
+ return mul * t;
+}
\ No newline at end of file
diff --git a/src/AnimationSupport/SceneEvent.js b/src/AnimationSupport/SceneEvent.js
new file mode 100644
index 000000000..0a13e1040
--- /dev/null
+++ b/src/AnimationSupport/SceneEvent.js
@@ -0,0 +1,275 @@
+var
+ Scene = require('./Scene'),
+ director = require('./Director'),
+ dispatcher = require('../dispatcher'),
+ emitter = require('../EventEmitter'),
+ utils = require('../utils');
+
+var eventsMap = {
+ vdrag: "drag",
+ vscroll: "scroll",
+ vmousewheel: "mousewheel",
+ vtouch: "touchmove",
+ drag: "vdrag",
+ scroll: "vscroll",
+ mousewheel: "vmousewheel",
+ touchmove: "vtouch"
+};
+
+
+/**
+* This module handles the animation events for the character.
+* If the character has opted to have animations handled by animation framework,
+* then it can add "handleAnimationEvents" as true as its property.
+* The character can also mention which events he wants to be handled by the framework by
+* providing list of animation events in "handlers" block like;
+* {
+* name: "myKind",
+* handlers: [
+* "scroll",
+* "mousewheel",
+* "touchstart",
+* "touchmove",
+* "touchend"
+* ]
+* }
+*
+* By default these events are handled within the framework(others for now have to be handled by the application).
+*/
+var EventDelegator = {
+
+ /**
+ * Attaches the evnet handlers to the character either its own events or
+ * else default events with the framework. As of now only these events are
+ * supported;
+ * - scroll
+ * - touch
+ * - mousewheel
+ * @public
+ */
+ register: function (scene, charc) {
+ var events = scene.handlers || {};
+ for (var key in events) {
+ this.addRemoveListener(scene, charc, key, events[key]);
+ }
+ },
+
+ /**
+ * Detaches the evnet handlers from the character either its own events or
+ * else default events from with the framework. As of now only these events are
+ * supported;
+ * - scroll
+ * - touch
+ * - mousewheel
+ * @public
+ */
+ deRegister: function (scene, charc) {
+ var events = scene.handlers || {};
+ for (var key in events) {
+ this.addRemoveListener(scene, charc, key, events[key], true);
+ }
+ },
+
+ /**
+ * @private
+ */
+ addRemoveListener: function(scene, charc, name, callback, remove) {
+ var d = remove ? dispatcher.stopListening : dispatcher.listen,
+ e = eventsMap[name];
+ d(charc.hasNode(), e, charc.bindSafely(this[e + 'Event'], charc));
+
+ var fn = remove ? emitter.off : emitter.on;
+ fn.apply(emitter, [name, scene[callback], charc]);
+ },
+
+ /**
+ * @private
+ */
+ emitEvent: function(action, name) {
+ emitter.emit(name,
+ action.eventOriginator,
+ action.getAnimationDelta());
+ },
+
+ /**
+ * @private
+ */
+ touchmoveEvent: function (sender, inEvent) {
+ var x = inEvent.targetTouches[0].pageX,
+ y = inEvent.targetTouches[0].pageY;
+
+ if(x !== 0 || y !== 0) {
+ inEvent.dX = x;
+ inEvent.dY = y;
+ inEvent.dZ = 0;
+ inEvent.vtype = eventsMap['touchmove'];
+ EventAction.setAnimationDelta(inEvent);
+ }
+ },
+
+ /**
+ * @private
+ */
+ scrollEvent: function (inSender, inEvent) {
+ inEvent.dX = inEvent.deltaX;
+ inEvent.dY = inEvent.deltaY;
+ inEvent.dZ = 0;
+ inEvent.vtype = eventsMap['scroll'];
+ EventAction.setAnimationDelta(inEvent);
+ },
+
+ /**
+ * @private
+ */
+ dragEvent: function (inSender, inEvent) {
+ inEvent.dX = inEvent.offsetX;
+ inEvent.dY = inEvent.offsetY;
+ inEvent.dZ = 0;
+ inEvent.vtype = eventsMap['drag'];
+ EventAction.setAnimationDelta(inEvent);
+ },
+
+ /**
+ * @private
+ */
+ mousewheelEvent: function (sender, inEvent) {
+ inEvent.dX = inEvent.deltaX;
+ inEvent.dY = inEvent.deltaY;
+ inEvent.dZ = 0;
+ inEvent.vtype = eventsMap[inEvent.type];
+ EventAction.setAnimationDelta(inEvent);
+ }
+};
+
+
+
+var sup,
+
+ /**
+ * Holds references for DOM event updates to be used for
+ * virtual events.
+ * @private
+ */
+ _eventCache = {},
+
+ /**
+ * Checks if registered DOM event is been triggered for the actors
+ * added to this scene.
+ * @private
+ */
+ _isTriggered = false,
+
+ /**
+ * Holds refereneces of the activator who has initiated a virtual
+ * event for the actor/s in this scene.
+ * @private
+ */
+ _triggerer = '';
+
+var EventAction = {
+
+ eventOriginator: undefined,
+
+ /**
+ * Sets the delta values of x, y and z for events
+ * @param {Object} obj - Object contains dX, dY and dZ as keys
+ * @memberOf module:enyo/AnimationSupport/SceneEvent
+ * @public
+ */
+ setAnimationDelta: function(ev) {
+ _eventCache.dX = ev.dX + _eventCache.dX || 0;
+ _eventCache.dY = ev.dY + _eventCache.dY || 0;
+ _eventCache.dZ = ev.dZ + _eventCache.dZ || 0;
+ _eventCache[ev.vtype] = ev;
+
+ _isTriggered = true;
+ _triggerer = ev.vtype;
+ },
+
+ /**
+ * To get event changes captured, for delta values of x, y and z.
+ * @return {Object} delta - pose
+ * @memberOf module:enyo/AnimationSupport/SceneEvent
+ * @public
+ */
+ getAnimationDelta: function() {
+ return _eventCache;
+ },
+
+ /**
+ * To be when an virtual event has to be triggered for the last event captured.
+ * @return {void}
+ * @memberOf module:enyo/AnimationSupport/SceneEvent
+ * @public
+ */
+ triggerEvent: function() {
+ _isTriggered = false;
+ EventDelegator.emitEvent(this, _triggerer);
+ },
+
+ /**
+ * To be used when an actor is registerd for event tracking.
+ * Its keeps track of only on actor which is refered as
+ * the originator.
+ * @param {Object} actor - Component on which events will be captured.
+ * @return {void}
+ * @memberOf module:enyo/AnimationSupport/SceneEvent
+ * @public
+ */
+ register: function (actor) {
+ if (this.handlers) {
+ this.eventOriginator = actor;
+ EventDelegator.register(this, actor);
+ }
+ },
+
+ /**
+ * Overridden function initiates action on the animation
+ * for the given scene event.
+ * @param {number} ts - timespan
+ * @param {Object} pose - pose from the animation list
+ * @return {Object} - pose
+ * @memberOf module:enyo/AnimationSupport/SceneEvent
+ * @private
+ * @override
+ */
+ action: function (ts, pose) {
+ if (_isTriggered && _triggerer && this.handlers && this.handlers[_triggerer] !== undefined) {
+ if (this.handlers[_triggerer] === "") {
+ ts = director.shot(this, ts);
+ pose = sup.call(this, ts, pose);
+ if(ts === 0) _isTriggered = false;
+ } else {
+ this.triggerEvent();
+ }
+ }
+ return pose;
+ }
+};
+
+
+/**
+ * Scene Event A child entity of Scene which helps
+ * to perform user interaction based animations.
+ * This Scene can register virtual events for actors
+ * to enhance performance of delegation of events.
+ * SceneEvent can hold many actors on which animation has
+ * to performed, however only one actor{originator} can be
+ * registered for event tracking.
+ * To capture events which are tracked by SceneEvent,
+ * handlers could be added within the scene block with there
+ * respective call backs.
+ * Usage - var sceneInstance = SceneEvent({
+ * animation: [{ rotate: "180,0,0"}],
+ * handlers: {vmousewheel: ""},
+ * });
+ * sceneInstance.register(eventActor);
+ * sceneInstance.play();
+ * @module enyo/AnimationSupport/SceneEvent
+ */
+module.exports = function(props) {
+ var scene = Scene(props);
+ sup = scene.action;
+ utils.mixin(scene, EventAction);
+ return scene;
+};
\ No newline at end of file
diff --git a/src/AnimationSupport/Slideable.js b/src/AnimationSupport/Slideable.js
deleted file mode 100644
index 77284ba94..000000000
--- a/src/AnimationSupport/Slideable.js
+++ /dev/null
@@ -1,98 +0,0 @@
-var
- kind = require('../kind'),
- animation = require('./Core');
-
-/**
- * Interface to achieve slide animation
- *
- * @module enyo/AnimationSupport/Slideable
- * @public
- */
-module.exports = {
-
- /**
- * @private
- */
- name: 'Slideable',
-
- /**
- * To start animation
- */
- animate: true,
-
- /**
- * @public
- * slide animation in left direction
- * @parameter: slideDistance - distance in pixels to slide in left direction
- */
- left: function(slideDistance) {
- this.slide((-1 * slideDistance), 0, 0);
- },
-
- /**
- * @public
- * slide animation in right direction
- * @parameter: slideDistance - distance in pixels to slide in right direction
- */
- right: function(slideDistance) {
- this.slide(slideDistance, 0, 0);
- },
-
- /**
- * @public
- * slide animation upward
- * @parameter: slideDistance - distance in pixels to slide upward
- */
- up: function(slideDistance) {
- this.slide(0, (-1 * slideDistance), 0);
- },
-
- /**
- * @public
- * slide animation downward
- * @parameter: slideDistance - distance in pixels to slide downward
- */
- down: function(slideDistance) {
- this.slide(0, slideDistance, 0);
- },
-
- /**
- * @public
- * slide animation in custom direction
- * @parameter: x - css property to slide in x-axis direction
- * @parameter: y - css property to slide in y-axis direction
- * @parameter: z - css property to slide in z-axis direction
- */
- slide: function(x, y, z) {
- x = x || 0;
- y = y || 0;
- z = z || 0;
- switch (this.direction) {
- case "horizontal":
- this.addAnimation({
- translate: x + "," + 0 + "," + 0
- });
- break;
- case "vertical":
- this.addAnimation({
- translate: 0 + "," + y + "," + 0
- });
- break;
- case "depth":
- this.addAnimation({
- translate: 0 + "," + 0 + "," + x
- });
- break;
- case "depthForward":
- this.addAnimation({
- translate: x + "," + 0 + "," + -0.009 * x
- });
- break;
-
- default:
- this.addAnimation({
- translate: x + "," + y + "," + z
- });
- }
- }
-};
diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js
index cf419dce3..d4319771f 100644
--- a/src/AnimationSupport/Tween.js
+++ b/src/AnimationSupport/Tween.js
@@ -2,12 +2,12 @@ require('enyo');
var
frame = require('./Frame'),
- easings = require('./Easings'),
- matrixUtil = require('./Matrix'),
+ Easings = require('./Easings'),
Vector = require('./Vector'),
+ Matrix = require('./Matrix'),
utils = require('../utils');
-var oldState, newState, node, matrix, cState = [];
+var fn, state, ease, points, path, oldState, newState, node, matrix, cState = [];
/**
* Tween is a module responsible for creating intermediate frames for an animation.
* The responsibilities of this module is to;
@@ -17,128 +17,286 @@ var oldState, newState, node, matrix, cState = [];
* @module enyo/AnimationSupport/Tween
*/
module.exports = {
-
+
/**
* @private
*/
- step: function(charc, pose, t, d) {
- var k, c, pts, tState, oState, ease, points;
+ init: function (actor, pose, initial) {
+ if (!(actor && pose && pose.animate)) return;
+ node = actor.hasNode();
+ utils.mixin(pose, frame.getComputedProperty(node, pose.animate, initial || actor.currentState));
+ actor.currentState = pose.currentState;
+ return pose;
+ },
- node = charc.node;
- newState = pose._endAnim;
- ease = pose.animate && pose.animate.ease ? pose.animate.ease: this.ease;
- oldState = pose._startAnim;
- charc.currentState = charc.currentState || {};
+ /**
+ * Step represents state of the actor at any point of time in the animation.
+ * @param {Object} actor - Element to be animated
+ * @param {Object} pose - Current behavior in the animation (at a given time)
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @param {Number} d - Duration of the current pose
+ * @memberOf module:enyo/AnimationSupport/Tween
+ * @private
+ */
+ step: function(actor, pose, t, d) {
+ if (!(actor && pose && pose.animate)) return;
+ if (t<0) t=0;
+ if (t>1) t=1;
+ var k;
+ node = actor.hasNode();
+ state = actor.currentState = actor.currentState || pose.currentState || {};
+ points = pose.controlPoints = pose.controlPoints || {};
+ ease = pose.animate && pose.animate.ease ? pose.animate.ease : this.ease;
+ path = pose.animate && pose.animate.path;
- if (pose.props) {
+ if (pose.props) {
for (k in pose.props) {
- cState = frame.copy(charc.currentState[k] || []);
- if (newState[k]) {
- if (ease && (typeof ease !== 'function')) {
- var checkEaseChange = easings.easeChanged(ease);
- var propChange = easings.propChange(k);
+ if (!pose._endAnim[k]) {
+ continue;
+ }
- if (!charc.controlPoints || (propChange === true || checkEaseChange === true)) {
- // for the first time or either of Ease/Propery changed
- charc.controlPoints = easings.calculateEase(ease, frame.copy(oldState[k]), frame.copy(newState[k]));
- } else if (propChange === false && checkEaseChange === false) {
- // for the cases where property and ease remain same and the states are varying
- var oldStateCheck = easings.oldStateChange(frame.copy(oldState[k]));
- var newStateCheck = easings.newStateChange(frame.copy(newState[k]));
- if (oldStateCheck === true || newStateCheck === true) {
- charc.controlPoints = easings.calculateEase(ease, frame.copy(oldState[k]), frame.copy(newState[k]));
- }
- }
- cState = this.getBezier(t, charc.controlPoints, cState);
- if (k == 'rotate')
- cState = Vector.toQuant(cState);
+ cState = utils.clone(state[k] || []);
+ newState = utils.clone(pose._endAnim[k]);
+ oldState = utils.clone(pose._startAnim[k]);
+
+ if (ease && (typeof ease !== 'function')) {
+ if (k == 'rotate') {
+ newState = Vector.toQuant(newState);
+ points[k] = points[k] ||
+ this.bezierSPoints(ease, oldState, newState, pose.props[k], points[k]);
+ fn = this.bezierSpline;
+ } else {
+ points[k] = points[k] ||
+ this.bezierPoints(ease, oldState, newState, points[k]);
+ fn = this.bezier;
+ }
+ cState = fn.call(this, t, points[k], cState);
+ } else {
+ if (k == 'rotate') {
+ newState = Vector.toQuant(newState);
+ fn = this.slerp;
} else {
- if (k == 'rotate') {
- tState = Vector.toQuant(newState[k]);
- oState = oldState[k];
- c = this.slerp;
- } else {
- tState = newState[k];
- oState = oldState[k];
- c = this.lerp;
- }
- cState = c(oState, tState, ease(t, d), cState);
+ fn = this.lerp;
}
+ cState = fn.call(this, oldState, newState, ease(t, d), cState);
}
-
+
if (!frame.isTransform(k)) {
- frame.setProperty(node, k, cState);
+
+ frame.setProperty(actor, k, cState);
}
- charc.currentState[k] = cState;
+ state[k] = cState;
}
} else {
- utils.mixin(charc.currentState,oldState);
+ utils.mixin(state, oldState);
}
- if (charc.path) {
- points = this.getBezier(t, charc.path, charc.currentState.translate, true);
- charc.currentState.translate = points;
+
+ //TODO: Support for properties other than translate
+ if (path) {
+ this.traversePath(t, path, state.translate);
}
+
matrix = frame.recomposeMatrix(
- charc.currentState.translate,
- charc.currentState.rotate,
- charc.currentState.scale,
- charc.currentState.skew,
- charc.currentState.perspective
+ state.translate,
+ state.rotate,
+ state.scale,
+ state.skew,
+ state.perspective
);
- frame.accelerate(node, matrix);
-
- charc.animationStep && charc.animationStep(t,matrix);
+ frame.accelerate(actor, matrix);
+ state.matrix = matrix;
+ pose.currentState = state;
},
/**
+ * Overridden function for applying the default ease.
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @return {Number} t
+ * @memberOf module:enyo/AnimationSupport/Tween
* @private
+ * @override
*/
ease: function(t) {
return t;
},
- //Without control points
- beizerSlerpPoints: function(ease, startQuat, endQuat, endPoint) {
- var tm, ag, q, key,
- splinePoints = {},
- eD = frame.parseValue(endPoint),
- aN = startQuat;
+ /**
+ * Draws linear interpolation between two values.
+ * @param {Number[]} vA - origin vector
+ * @param {Number[]} vB - Destination vector
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @param {Number[]} vR - Resultant vector
+ * @return {Number[]} vR
+ * @memberOf module:enyo/AnimationSupport/Tween
+ * @private
+ */
+ lerp: function(vA, vB, t, vR) {
+ if (!vA) return;
+ if (!vR) vR = [];
+ var i, l = vA.length;
- if (ease && Object.keys(ease).length > 0) {
- for (key in ease) {
- tm = parseFloat(key) / 100;
- ag = parseFloat(ease[key]);
- eD.pop(); // remove angle from end point.
- eD[eD.length] = ag;
- q = Vector.toQuant(frame.copy(eD));
- splinePoints[tm] = [aN, q];
- aN = q;
+ for (i = 0; i < l; i++) {
+ vR[i] = (1 - t) * vA[i] + t * vB[i];
+ }
+ return vR;
+ },
+
+ /**
+ * Draws sperical linear interpolation between two values.
+ * @param {Number[]} qA Quaternion origin
+ * @param {Number[]} qB - Quaternion destination
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @param {Number[]} qR - Resultant quaternion
+ * @return {Number[]} qR
+ * @memberOf module:enyo/AnimationSupport/Tween
+ * @private
+ */
+ slerp: function(qA, qB, t, qR) {
+ if (!qA) return;
+ if (!qR) qR = [];
+ var a,
+ b,
+ theta,
+ dot = Vector.quantDot(qA, qB),
+ l = qA.length;
+
+ dot = Math.min(Math.max(dot, -1.0), 1.0);
+ if (dot == 1.0) {
+ qR = frame.copy(qA);
+ return qR;
+ }
+ theta = Math.acos(dot);
+ for (var i = 0; i < l; i++) {
+ a = (Math.sin((1 - t) * theta) / Math.sin(theta)) * qA[i];
+ b = (Math.sin(t * theta) / Math.sin(theta)) * qB[i];
+ qR[i] = a + b;
+ }
+ return qR;
+ },
+
+ /**
+ * Creates bezier curve path for animation.
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @param {Number[]} points - knot and control points
+ * @param {Number[]} vR - Resulting points
+ * @return {Number[]} vR
+ * @memberOf module:enyo/AnimationSupport/Tween
+ */
+ bezier: function(t, points, vR) {
+ if (!points) return;
+ if (!vR) vR = [];
+
+ var i, j,
+ c = points.length,
+ l = points[0].length,
+ lastIndex = (c - 1),
+ startPoint = points[0],
+ endPoint = points[lastIndex],
+ values = Easings.getBezierValues(t, lastIndex);
+
+ for (i = 0; i < l; i++) {
+ vR[i] = 0;
+ for (j = 0; j < c; j++) {
+ if ((j > 0) && (j < (c - 1))) {
+ vR[i] = vR[i] + ((startPoint[i] + (points[j][i] * (endPoint[i] - startPoint[i]))) * values[j]);
+ } else {
+ vR[i] = vR[i] + (points[j][i] * values[j]);
+ }
}
- splinePoints[1] = [aN, endQuat];
}
- return splinePoints;
+ return vR;
},
- //Without control points
- beizerSlerp: function(t, points, vR) {
- var p, key;
- for (p in points) {
- if (p >= t) key = p;
+ /**
+ * Returns the control points for bezier curve.
+ * @param {Object} easeObj- The easing object with values.
+ * @param {Number[]} startPoint - Starting point of the curve
+ * @param {Number[]} endPoint - End point of the curve
+ * @param {Number[]} points - control points
+ * @return {Number[]} points
+ * @memberOf module:enyo/AnimationSupport/Tween
+ */
+ bezierPoints: function(easeObj, startPoint, endPoint, points) {
+ if (!easeObj) return;
+ var order = (easeObj && Object.keys(easeObj).length) ? (Object.keys(easeObj).length + 1) : 0;
+ var bValues = [],
+ m1 = [],
+ m2 = [],
+ m3 = [],
+ m4 = [],
+ l = 0;
+ points = [startPoint];
+
+ var t, a;
+ for (var key in easeObj) {
+ t = parseFloat(key) / 100;
+ a = parseFloat(easeObj[key]) / 100;
+ bValues = Easings.getBezierValues(t, order);
+ bValues.shift();
+ m1.push(a - bValues.pop());
+ m2.push(bValues);
+ }
+
+ m3 = Matrix.inverseN(m2, bValues.length);
+ m4 = Matrix.multiplyN(m3, m1);
+ l = m4.length;
+ for (var i = 0; i < l; i++) {
+ points.push([m4[i], m4[i], m4[i]]);
+ }
+
+ points.push(endPoint);
+ return points;
+ },
+
+ /**
+ * Traverses the path of the animation
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @param {Number[]} path - Array of points
+ * @param {Number[]} vR Resulatant Array
+ * @return {Number[]} vR
+ * @memberOf module:enyo/AnimationSupport/Tween
+ */
+ traversePath: function (t, path, vR) {
+ if (!path) return;
+ if (!vR) vR = [];
+
+ var i, j,
+ c = path.length,
+ l = path[0].length,
+ lastIndex = (c - 1),
+ values = Easings.getBezierValues(t, lastIndex);
+
+ for (i = 0; i < l; i++) {
+ vR[i] = 0;
+ for (j = 0; j < c; j++) {
+ vR[i] = vR[i] + (path[j][i] * values[j]);
+ }
}
- vR = this.slerp(points[key][0], points[key][1], t);
return vR;
},
- //With control points
- beizerSPoints: function(ease, startQuat, endQuat, endPoint) {
- var splinePoints = {},
- time = [0],
+ /**
+ * Returns the control points for bezier spline.
+ * @param {Object} ease- The easing object with values.
+ * @param {Number[]} startQuat - Quaternion origin
+ * @param {Number[]} endQuat - Quaternion destination
+ * @param {Number[]} endPoint - Final Destination point
+ * @param {Number[]} splinePoints - spline control points
+ * @return {Number[]} splinePoints
+ * @memberOf module:enyo/AnimationSupport/Tween
+ */
+ bezierSPoints: function(ease, startQuat, endQuat, endPoint, splinePoints) {
+ if (!ease) return;
+ var time = [0],
quats = [startQuat];
var t, a, q, n, _a, aI, bN,
eD = frame.parseValue(endPoint);
- if (ease && Object.keys(ease).length > 0) {
+ splinePoints = splinePoints || {};
+ quats.push(startQuat);
+ time.push(0);
+ if (Object.keys(ease).length > 0) {
for (var key in ease) {
t = parseFloat(key) / 100;
a = parseFloat(ease[key]);
@@ -150,8 +308,9 @@ module.exports = {
}
quats.push(endQuat);
time.push(1);
-
n = quats.length - 1;
+ ai = this.slerp(startQuat, endQuat, 0);
+ splinePoints[0] = [quats[0], aI, aI, quats[1]];
for (var i = 0, j = 1; i < n; i++, j++) {
if (i === 0) {
aI = this.slerp(quats[0], this.slerp(quats[2], quats[1], 2.0), 1.0 / 3);
@@ -171,14 +330,24 @@ module.exports = {
return splinePoints;
},
- //With control points
- beizerSpline: function(t, points, vR) {
+ /**
+ * Creates bezier spline path for animation.
+ * @param {Number} t - Fraction which represents the animation (between 0 to 1)
+ * @param {Number[]} points - knot and control points
+ * @param {Number[]} vR - Resulting points
+ * @return {Number[]} vR
+ * @memberOf module:enyo/AnimationSupport/Tween
+ */
+ bezierSpline: function(t, points, vR) {
+ if (!points) return;
if (!vR) vR = [];
- var Q0, Q1, Q2, R0, R1;
-
- var p, key, pts;
+ var Q0, Q1, Q2, R0, R1,
+ p, key, pts;
for (p in points) {
- if (p >= t) key = p;
+ if (p >= t) {
+ key = p;
+ break;
+ }
}
pts = points[key];
@@ -192,75 +361,5 @@ module.exports = {
} else
vR = this.slerp(pts[0], pts[1], t);
return vR;
- },
-
- lerp: function(vA, vB, t, vR) {
- if (!vR) vR = [];
- var i, l = vA.length;
-
- for (i = 0; i < l; i++) {
- vR[i] = (1 - t) * vA[i] + t * vB[i];
- }
- return vR;
- },
-
- slerp: function(qA, qB, t, qR) {
- if (!qR) qR = [];
- var a,
- b,
- theta,
- dot = Vector.quantDot(qA, qB),
- l = qA.length;
-
- dot = Math.min(Math.max(dot, -1.0), 1.0);
-
- if (dot == 1.0) {
- qR = frame.copy(qA);
- return qR;
- }
-
- theta = Math.acos(dot);
- for (var i = 0; i < l; i++) {
- a = (Math.sin((1 - t) * theta) / Math.sin(theta)) * qA[i];
- b = (Math.sin(t * theta) / Math.sin(theta)) * qB[i];
- qR[i] = a + b;
- }
-
- return qR;
- },
-
- /**
- * @public
- * @params t: time, points: knot and control points, vR: resulting point
- */
- getBezier: function(t, points, vR, isPath) {
-
- if (!vR) vR = [];
-
- var i, j,
- c = points.length,
- l = points[0].length,
- lastIndex = (c - 1),
- startPoint = points[0],
- endPoint = points[lastIndex],
- values = easings.getBezierValues(t, lastIndex);
-
- for (i = 0; i < l; i++) {
- vR[i] = 0;
- for (j = 0; j < c; j++) {
- if(isPath){
- vR[i] = vR[i] + (points[j][i] * values[j]);
- }
- else {
- if((j > 0) && (j < (c - 1))){
- vR[i] = vR[i] + ((startPoint[i] + (points[j][i] * (endPoint[i] - startPoint[i]))) * values[j]);
- } else {
- vR[i] = vR[i] + (points[j][i] * values[j]);
- }
- }
- }
- }
- return vR;
}
-
-};
+};
\ No newline at end of file
diff --git a/src/AnimationSupport/Vector.js b/src/AnimationSupport/Vector.js
index 7d46b85b6..9f0db08e3 100644
--- a/src/AnimationSupport/Vector.js
+++ b/src/AnimationSupport/Vector.js
@@ -9,6 +9,10 @@ require('enyo');
module.exports = {
/**
* Divides vector with a scalar value.
+ * @param {Number[]} v - vector
+ * @param {Number} s - scalar value to divide
+ * @return {Number[]} resultant vector
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
divide: function (v, s) {
@@ -17,6 +21,10 @@ module.exports = {
/**
* Add vector/quant with a vector/quant.
+ * @param {Number[]} q1 - vector/quant
+ * @param {Number[]} q2 - vector/quant
+ * @return {Number[]} added vector/quant
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
add: function (q1, q2) {
@@ -30,6 +38,10 @@ module.exports = {
/**
* Sub vector/quant with a vector/quant.
+ * @param {Number[]} q1 - vector/quant
+ * @param {Number[]} q2 - vector/quant
+ * @return {Number[]} subracted vector/quant
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
subtract: function (q1, q2) {
@@ -43,6 +55,10 @@ module.exports = {
/**
* Multiply vector/quant with a vector/quant.
+ * @param {Number[]} v - vector
+ * @param {Number} s - scalar value to divide
+ * @return {Number[]} resultant vector
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
multiply: function (q, s) {
@@ -55,6 +71,11 @@ module.exports = {
/**
* Limits the vector/quant between a maximum and minimum value.
+ * @param {Number[]} q - vector/quant
+ * @param {Number} max - maximum range value
+ * @param {Number} min - minimum range value
+ * @return {Number[]} resultant vector/quant
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
range: function (q, max, min) {
@@ -63,42 +84,14 @@ module.exports = {
}
},
- /**
- * Compares each vector/qunat with a scalar value to check if its equal.
- * Returns true when all the vector/quant values are equal to this scalar value.
- * @public
- */
- equalS: function (q1, s) {
- return (q1.length > 0) && q1.every(function (e, i) {
- return e === (s || 0);
- });
- },
-
- /**
- * Compares each vector/qunat with a scalar value to check if its greater.
- * Returns true when all the vector/quant values are greater or equal to this scalar value.
- * @public
- */
- greaterS: function (q1, s) {
- return (q1.length > 0) && q1.every(function (e, i) {
- return e >= (s || 0);
- });
- },
-
- /**
- * Compares each vector/qunat with a scalar value to check if its lesser.
- * Returns true when all the vector/quant values are lesser or equal to this scalar value.
- * @public
- */
- lesserS: function (q1, s) {
- return (q1.length > 0) && q1.every(function (e, i) {
- return e < (s || 0);
- });
- },
-
/**
* Evaluates the gap between two vector values.
* Returns the absolute distance between two vectors.
+ * @param {Number[]} v1 - vector
+ * @param {Number[]} v2 - vector
+ * @param {Number} d - distance between vector
+ * @return {Number} distance between vector
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
distance: function (v1, v2, d) {
@@ -110,6 +103,11 @@ module.exports = {
/**
* Evaluates the gap between two quanterions values
* Returns the absolute distance between two quanterions.
+ * @param {Number[]} v1 - quant
+ * @param {Number[]} v2 - quant
+ * @param {Number} d - distance between quant
+ * @return {Number} distance between quant
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
quantDistance: function (q1, q2, d) {
@@ -121,6 +119,10 @@ module.exports = {
/**
* Gives the direction of motion from one vector to other.
* Returns true if moving towards positive direction.
+ * @param {Number[]} v1 - quant
+ * @param {Number[]} v2 - quant
+ * @return {boolean} true if positive, false otherwise.
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
direction: function (q1, q2) {
@@ -129,6 +131,9 @@ module.exports = {
/**
* Retunns an inverse of a quanterion.
+ * @param {Number[]} q - quant
+ * @return {Number[]} resultant quant
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
quantInverse: function (q) {
@@ -137,31 +142,34 @@ module.exports = {
},
/**
- * Length of 3D vectors
- * @public
- */
- sumS: function (q, s) {
- return q[0] * s + q[1] * s + q[2] * s + q[3] !== undefined ? q[3] * s : 0;
- },
-
- /**
- * Length of 3D vectors
+ * Length of a vector
+ * @param {Number[]} v - vetor
+ * @return {Number} resultant length
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
- len: function (q) {
- return Math.sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2]);
+ len: function (v) {
+ return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
},
/**
* Dot product of 3D vectors
+ * @param {Number[]} v1 - vetor
+ * @param {Number[]} v2 - vetor
+ * @return {Number} resultant dot product
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
- dot: function (q1, q2) {
- return (q1[0] * q2[0]) + (q1[1] * q2[1]) + (q1[2] * q2[2]) + (q1[3] !== undefined && q2[3] !== undefined ? (q1[3] * q2[3]) : 0);
+ dot: function (v1, v2) {
+ return (v1[0] * v2[0]) + (v1[1] * v2[1]) + (v1[2] * v2[2]) + (v1[3] !== undefined && v2[3] !== undefined ? (v1[3] * v2[3]) : 0);
},
/**
- * Dot product of 3D vectors
+ * Dot product of 3D quanterion
+ * @param {Number[]} q1 - quanterion
+ * @param {Number[]} q2 - quanterion
+ * @return {Number} resultant dot product
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
quantDot: function (q1, q2) {
@@ -169,7 +177,11 @@ module.exports = {
},
/**
- * Quant Dot product of 3D vectors
+ * Quant Cross product of 3D quanterion
+ * @param {Number[]} q1 - quanterion
+ * @param {Number[]} q2 - quanterion
+ * @return {Number[]} resultant cross product
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
quantCross: function (q1, q2) {
@@ -183,19 +195,26 @@ module.exports = {
/**
* Cross product of two vectors
+ * @param {Number[]} v1 - vetor
+ * @param {Number[]} v2 - vetor
+ * @return {Number[]} resultant cross product
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
- cross: function (q1, q2) {
+ cross: function (v1, v2) {
return [
- q1[1] * q2[2] - q1[2] * q2[1],
- q1[2] * q2[0] - q1[0] * q2[2],
- q1[0] * q2[1] - q1[1] * q2[0]
+ v1[1] * v2[2] - v1[2] * v2[1],
+ v1[2] * v2[0] - v1[0] * v2[2],
+ v1[0] * v2[1] - v1[1] * v2[0]
];
},
/**
* Normalizing a vector is obtaining another unit vector in the same direction.
* To normalize a vector, divide the vector by its magnitude.
+ * @param {Number[]} q1 - quanterion
+ * @return {Number[]} resultant quanterion
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
normalize: function (q) {
@@ -205,6 +224,12 @@ module.exports = {
/**
* Combine scalar values with two vectors.
* Required during parsing scaler values matrix.
+ * @param {Number[]} a - first vector
+ * @param {Number[]} b - second vector
+ * @param {Number[]} ascl - first vector scalar
+ * @param {Number[]} ascl - second vector scalar
+ * @return {Number[]} resultant vector
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
combine: function (a, b, ascl, bscl) {
@@ -215,6 +240,9 @@ module.exports = {
/**
* Converts a quaternion vector to a rotation vector.
+ * @param {Number[]} rv - quanterion
+ * @return {Number[]} resultant rotation vector
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
toVector: function (rv) {
@@ -226,6 +254,9 @@ module.exports = {
/**
* Converts a rotation vector to a quaternion vector.
+ * @param {Number[]} v - vector
+ * @return {Number[]} resultant quaternion
+ * @memberOf module:enyo/AnimationSupport/Vector
* @public
*/
toQuant: function (v) {
@@ -248,6 +279,13 @@ module.exports = {
return q;
},
+ /**
+ * Converts a quaternion vector vector to a rotation vector.
+ * @param {Number[]} q - quaternion
+ * @return {Number[]} resultant vector
+ * @memberOf module:enyo/AnimationSupport/Vector
+ * @public
+ */
quantToVector: function (q) {
var vector = [], h, a, b,
x2 = q[0] * q[0],
diff --git a/src/UiComponent.js b/src/UiComponent.js
index 011ee7138..29d9e2c03 100644
--- a/src/UiComponent.js
+++ b/src/UiComponent.js
@@ -8,9 +8,7 @@ require('enyo');
var
kind = require('./kind'),
utils = require('./utils'),
- master = require('./master'),
- AnimationSupport = require('./AnimationSupport/AnimationSupport'),
- AnimationInterfaceSupport = require('./AnimationSupport/AnimationInterfaceSupport');
+ master = require('./master');
var
Component = require('./Component');
@@ -130,12 +128,7 @@ var UiComponent = module.exports = kind(
onresize: 'handleResize'
},
- /**
- * Adding animation support for controls
- * @private
- */
- mixins: [AnimationSupport, AnimationInterfaceSupport],
-
+
/**
* When set, provides a [control]{@link module:enyo/Control~Control} reference used to indicate where a
* newly-created [component]{@link module:enyo/Component~Component} should be added in the
diff --git a/test/tests/NewTweenTest.js b/test/tests/NewTweenTest.js
new file mode 100644
index 000000000..157ec587f
--- /dev/null
+++ b/test/tests/NewTweenTest.js
@@ -0,0 +1,380 @@
+var expect = chai.expect;
+
+var
+ kind = require('enyo/kind'),
+ Control = require('enyo/Control'),
+ Scene = require('enyo/AnimationSupport/Scene'),
+ Vector = require('enyo/AnimationSupport/Vector'),
+ Tween = require('enyo/AnimationSupport/Tween');
+
+var b = 0,
+ c = 1;
+
+var parseMatrix = function (v) {
+ var m = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];
+ v = v.replace(/^\w*\(/, '').replace(')', '');
+ v = parseValue(v);
+ if (v.length <= 6) {
+ m[0] = v[0];
+ m[1] = v[1];
+ m[4] = v[2];
+ m[5] = v[3];
+ m[12] = v[4];
+ m[13] = v[5];
+ } else {
+ m = v;
+ }
+ return m;
+};
+
+var parseValue = function (val) {
+ return val.toString().split(",").map(function(v) {
+ return parseFloat(v, 10);
+ });
+};
+
+var translateScene = Scene({
+ animation: {
+ translate: "100, 0, 0"
+ },
+ duration: 100
+});
+
+var rotateScene = Scene({
+ animation: {
+ rotate: "100, 0, 0"
+ },
+ duration: 100
+});
+
+var traverseScene = Scene({
+ animation: {
+ path: [[0,0,0],[0,-50,0],[50,-50,0],[50,50,0],[0,50,0]]
+ },
+ duration: 100
+});
+
+
+describe("Tween", function() {
+ var TestControl, testControl;
+ before(function () {
+ TestControl = kind({
+ name: 'TestControl',
+ kind: Control,
+ components: [{
+ name: "childDiv",
+ }]
+ });
+
+ testControl = new TestControl({parentNode: document.body});
+
+ });
+
+ after(function () {
+ testControl.destroy();
+ TestControl = null;
+ });
+
+ describe("Tween.init", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var scene = Tween.init();
+ expect(scene).to.equal(undefined);
+ });
+
+ it("should return undefined when pose have no animation property", function() {
+ var scene = Tween.init(1, 1);
+ expect(scene).to.equal(undefined);
+ });
+
+ it("should return object with keys include '_startAnim' and '_endAnim'", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ expect(pose).to.have.any.keys('_startAnim', '_endAnim');
+ });
+ });
+
+ describe("Tween.step", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var scene = Tween.step();
+ expect(scene).to.equal(undefined);
+ });
+
+ it("should return undefined when pose have no animation property", function() {
+ var scene = Tween.step(1, 1);
+ expect(scene).to.equal(undefined);
+ });
+
+ it("DOM should be at initial position at t = -0.1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, -0.1, 100);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
+ });
+
+ it("DOM should be at initial position at t = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 0, 100);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
+ });
+
+ it("DOM should not be at initial position at t = 0.1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 0.1, 100);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.not.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
+ });
+
+ it("DOM should not be at final position at t = 0.9", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 0.9, 100);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.not.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 0, 0, 1]);
+ });
+
+ it("DOM should be at final position at t = 1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 1, 100);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 0, 0, 1]);
+ });
+
+ it("DOM should be at final position at t = 1.1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 1.1, 100);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 0, 0, 1]);
+ });
+
+ it("DOM should be at final position at t = 0 if d = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 0, 0);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 0, 0, 1]);
+ });
+
+ it("DOM should be at final position at t = 1 if d = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ Tween.step(testControl.$.childDiv, pose, 1, 0);
+ var m = parseMatrix(testControl.$.childDiv.node.style.transform);
+ expect(m).to.deep.equal([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 100, 0, 0, 1]);
+ });
+ });
+
+ describe("Tween.lerp", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.lerp();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return '_startAnim.translate' matrix when t = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var m = Tween.lerp(pose._startAnim.translate, pose._endAnim.translate, 0);
+ expect(m).to.deep.equal(pose._startAnim.translate);
+ });
+
+ it("should return '_endAnim.translate' matrix when t = 1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var m = Tween.lerp(pose._startAnim.translate, pose._endAnim.translate, 1);
+ expect(m).to.deep.equal(pose._endAnim.translate);
+ });
+ });
+
+ describe("Tween.slerp", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.slerp();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return '_startAnim.rotate' matrix when t = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, rotateScene);
+ var pose = rotateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var poseEndAnimToQuant = Vector.toQuant(pose._endAnim.rotate);
+ var m = Tween.slerp(pose._startAnim.rotate, poseEndAnimToQuant, 0);
+ expect(m).to.deep.equal(pose._startAnim.rotate);
+ });
+
+ it("should return '_endAnim.rotate' matrix when t = 1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, rotateScene);
+ var pose = rotateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var poseEndAnimToQuant = Vector.toQuant(pose._endAnim.rotate);
+ var m = Tween.slerp(pose._startAnim.rotate, poseEndAnimToQuant, 1);
+ expect(m).to.deep.equal(poseEndAnimToQuant);
+ });
+ });
+
+ describe("Tween.bezier", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.bezier();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return '_startAnim.translate' matrix when t = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var bezierPoints = Tween.bezierPoints({20: 60, 80: 40}, pose._startAnim.translate, pose._endAnim.translate);
+ var m = Tween.bezier(0, bezierPoints);
+ expect(m).to.deep.equal(pose._startAnim.translate);
+ });
+
+ it("should return '_endAnim.translate' matrix when t = 1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var bezierPoints = Tween.bezierPoints({20: 60, 80: 40}, pose._startAnim.translate, pose._endAnim.translate);
+ var m = Tween.bezier(1, bezierPoints);
+ expect(m).to.deep.equal(pose._endAnim.translate);
+ });
+ });
+
+ describe("Tween.bezierPoints", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.bezierPoints();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return '_startAnim.translate' on array[0]", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var m = Tween.bezierPoints({20: 60, 80: 40}, pose._startAnim.translate, pose._endAnim.translate);
+ expect(m[0]).to.deep.equal(pose._startAnim.translate);
+ });
+
+ it("should return '_endAnim.translate' on array[3]", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, translateScene);
+ var pose = translateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var m = Tween.bezierPoints({20: 60, 80: 40}, pose._startAnim.translate, pose._endAnim.translate);
+ expect(m[3]).to.deep.equal(pose._endAnim.translate);
+ });
+ });
+
+ describe("Tween.traversePath", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.traversePath();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return initial path array value when t = 0", function() {
+ testControl.render();
+ /*Scene.link(testControl.$.childDiv, traverseScene);
+ var pose = traverseScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);*/
+ var m = Tween.traversePath(0, [[0,0,0],[0,-50,0],[50,-50,0],[50,50,0],[0,50,0]]);
+ expect(m).to.deep.equal([0,0,0]);
+ });
+
+ it("should return final path array when t = 1", function() {
+ testControl.render();
+ var m = Tween.traversePath(1, [[0,0,0],[0,-50,0],[50,-50,0],[50,50,0],[0,50,0]]);
+ expect(m).to.deep.equal([0,50,0]);
+ });
+ });
+
+ describe("Tween.bezierSpline", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.bezierSpline();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return '_startAnim.rotate' matrix when t = 0", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, rotateScene);
+ var pose = rotateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var poseEndAnimToQuant = Vector.toQuant(pose._endAnim.rotate);
+ var bezierSPoints = Tween.bezierSPoints({20: 60, 80: 40}, pose._startAnim.rotate, poseEndAnimToQuant, "100, 0, 0");
+ var m = Tween.bezierSpline(0, bezierSPoints);
+ expect(m).to.deep.equal(pose._startAnim.rotate);
+ });
+
+ it("should return '_endAnim.rotate' matrix when t = 1", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, rotateScene);
+ var pose = rotateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var poseEndAnimToQuant = Vector.toQuant(pose._endAnim.rotate);
+ var bezierSPoints = Tween.bezierSPoints({20: 60, 80: 40}, pose._startAnim.rotate, poseEndAnimToQuant, "100, 0, 0");
+ var m = Tween.bezierSpline(1, bezierSPoints);
+ expect(m).to.deep.equal(poseEndAnimToQuant);
+ });
+ });
+
+ describe("Tween.bezierSPoints", function() {
+
+ it("should return undefined when called without any parameters", function() {
+ var m = Tween.bezierSPoints();
+ expect(m).to.equal(undefined);
+ });
+
+ it("should return '_startAnim.rotate' on array[0][0]", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, rotateScene);
+ var pose = rotateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var poseEndAnimToQuant = Vector.toQuant(pose._endAnim.rotate);
+ var m = Tween.bezierSPoints({20: 60, 80: 40}, pose._startAnim.rotate, poseEndAnimToQuant, "100, 0, 0");
+ expect(m[0][0]).to.deep.equal(pose._startAnim.rotate);
+ });
+
+ it("should return '_endAnim.rotate' on array[1][3]", function() {
+ testControl.render();
+ Scene.link(testControl.$.childDiv, rotateScene);
+ var pose = rotateScene.getAnimation(0);
+ pose = Tween.init(testControl.$.childDiv, pose);
+ var poseEndAnimToQuant = Vector.toQuant(pose._endAnim.rotate);
+ var m = Tween.bezierSPoints({20: 60, 80: 40}, pose._startAnim.rotate, poseEndAnimToQuant, "100, 0, 0");
+ expect(m[1][3]).to.deep.equal(poseEndAnimToQuant);
+ });
+ });
+});
\ No newline at end of file