From bf5220e85efb9cd7bd4c73d7f24fbb8410222fa6 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Thu, 31 Dec 2015 20:39:14 +0530 Subject: [PATCH 01/22] New director approach for animation Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- .../AnimationInterfaceSupport.js | 366 ------------------ src/AnimationSupport/AnimationSupport.js | 295 -------------- src/AnimationSupport/Director.js | 70 ++-- src/AnimationSupport/Fadeable.js | 86 ---- src/AnimationSupport/Flippable.js | 71 ---- src/AnimationSupport/HierarchicalMixin.js | 120 ------ src/AnimationSupport/KeyFrame.js | 133 ------- src/AnimationSupport/Parallax.js | 63 --- src/AnimationSupport/Scene.js | 161 ++++++++ .../{FrameEditor.js => SceneEditor.js} | 7 +- src/AnimationSupport/Slideable.js | 98 ----- src/AnimationSupport/Tween.js | 25 +- src/UiComponent.js | 11 +- 13 files changed, 228 insertions(+), 1278 deletions(-) delete mode 100644 src/AnimationSupport/AnimationInterfaceSupport.js delete mode 100644 src/AnimationSupport/AnimationSupport.js delete mode 100644 src/AnimationSupport/Fadeable.js delete mode 100644 src/AnimationSupport/Flippable.js delete mode 100644 src/AnimationSupport/HierarchicalMixin.js delete mode 100644 src/AnimationSupport/KeyFrame.js delete mode 100644 src/AnimationSupport/Parallax.js create mode 100644 src/AnimationSupport/Scene.js rename src/AnimationSupport/{FrameEditor.js => SceneEditor.js} (89%) delete mode 100644 src/AnimationSupport/Slideable.js 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/Director.js b/src/AnimationSupport/Director.js index 12ec4ba3a..a88d6d133 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -4,6 +4,8 @@ var frame = require('./Frame'), tween = require('./Tween'), utils = require('../utils'); +var rolePlays = {}; + /** * This module returns the Loop singleton * Core module is responsible for handling all animations happening in Enyo. @@ -29,36 +31,43 @@ module.exports = { * @public */ - take: function(actor, ts) { - var dur = actor.totalDuration, - tm = actor.rolePlay(ts); + take: function(scene, ts) { + var dur = scene.totalDuration, + tm = scene.rolePlay(ts), + actors = rolePlays[scene]; if (tm < 0) return; - if (tm < dur) { - this.action(actor, tm); + if (tm <= dur) { + for (var i = 0; i < actors.length; i++) { + if(actors[i].generated) + this.action(actors[i], scene, tm); + } } else { - this.action(actor, tm); - this.cut(actor); + this.cut(scene); } }, - cut: function (actor) { - actor.animating = false; - actor.timeline = 0; - actor.completed(actor); - actor.set('animationState', 'completed'); - if (!actor.active) { - // this.remove(actor); - } + cut: function (scene) { + scene.animating = false; + scene.timeline = 0; + scene.completed(scene); }, - 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; + action: function(actor, scene, since) { + var pose, t, prevDur, currentAnimSince, runningDur, + index = scene.animateAtTime(since), + props = scene.getAnimation(index); + + if(index) { + prevDur = scene.getAnimation(index - 1).duration; + } else { + if (!actor._initialPose) this.firstShot(actor); + prevDur = actor._initialPose.duration; + } + + currentAnimSince = since - prevDur, + runningDur = props.duration - prevDur; + if (!props._startAnim) { pose = frame.getComputedProperty(actor.hasNode(), props.animate, actor.currentState); utils.mixin(props, pose); @@ -73,6 +82,23 @@ module.exports = { } }, + rolePlay: function (actors, scene) { + rolePlays[scene] = utils.isArray(actors) ? actors : [actors]; + }, + + /** + * Gets current state of animation for this character + * @public + */ + firstShot: function (actor) { + var dom = actor.hasNode(), + pose = frame.getComputedProperty(dom, undefined); + pose.duration = 0; + actor._initialPose = pose; + actor.currentState = pose.currentState; + frame.accelerate(dom, pose.matrix); + }, + poseByTime: function(arr, duration) { var startIndex = 0, stopIndex = arr.length - 1, 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/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/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..1868315b6 --- /dev/null +++ b/src/AnimationSupport/Scene.js @@ -0,0 +1,161 @@ +var + SceneEditor = require('./SceneEditor'), + animation = require('./Core'), + delegator = require('./EventDelegator'), + director = require('./Director'), + utils = require('../utils'); + +var Scene = module.exports = function (props){ + var scene = Scene.create(); + utils.mixin(scene, SceneEditor); + + if(props.animation) { + scene.addAnimation(props.animation, props.duration || 0); + } + animation.trigger(scene); + return scene; +}; + +Scene.create = function () { + return new sceneConstructor(); +}; + +Scene.link = function(actors, scene) { + director.rolePlay(actors, scene); + scene.hasActors = true; +}; + +var sceneConstructor = function () { + var _poses = [], + + _eventCache = {}, + + _prevDur = 0, + + //_isActive = true, + + //_state, + + _isTriggered = false, + + _triggerer; + + + this.totalDuration = 0; + this.animating = false; + this.hasActors = false; + + this.ready = function() { + var ret = this.animating && this.hasActors !== undefined; + if (ret && this._startTime) + ret = this._startTime <= utils.perfNow(); + return ret; + }; + + + /** + * Adds new animation on already existing animation for this character. + * @public + */ + this.addAnimation = function (newProp, duration) { + if (_prevDur === 0 && duration === 0) { + _poses[0] = {animate: newProp, duration: 0}; + } else { + _prevDur = duration || _prevDur; + this.totalDuration += _prevDur; + _poses.push({animate: newProp, duration: this.totalDuration}); + } + }; + + this.animateAtTime = function(duration) { + var startIndex = 0, + stopIndex = _poses.length - 1, + middle = Math.floor((stopIndex + startIndex) / 2); + + if(duration === 0) { + return startIndex; + } + + while (_poses[middle].duration != duration && startIndex < stopIndex) { + if (duration < _poses[middle].duration) { + stopIndex = middle; + } else if (duration > _poses[middle].duration) { + startIndex = middle + 1; + } + + middle = Math.floor((stopIndex + startIndex) / 2); + } + + return (_poses[middle].duration != duration) ? startIndex : middle; + }, + + this.getAnimation = function(index) { + return index < 0 || _poses[index]; + }, + + /** + * Sets new animation for this character. + * @public + */ + this.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 + */ + this.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; + this.eventCacheUpdated = true; + }; + + /** + * Gets the delta values of x, y and z for events + * @public + */ + this.getAnimationDelta = function () { + return _eventCache[_triggerer]; + }; + + /** + * Idnetify when the character has done animating. + * This triggers "onAnimated" event on this character + * @public + */ + this.completed = function() { + return this.onAnimated && this.onAnimated(this); + }; + + + /** + * Trigger the registered event to all the listeners + * @public + */ + this.triggerEvent = function () { + _isTriggered = false; + return delegator.emitEvent(this, this.getAnimationDelta()); + }; + +}; + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AnimationSupport/FrameEditor.js b/src/AnimationSupport/SceneEditor.js similarity index 89% rename from src/AnimationSupport/FrameEditor.js rename to src/AnimationSupport/SceneEditor.js index 20632f5fb..37a15e128 100644 --- a/src/AnimationSupport/FrameEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -10,15 +10,18 @@ module.exports = { timeline: 0, _cachedValue: 0, _frameSpeed: 1, - + _startTime: 0, cache: function(){ if(this._frameSpeed === 0){ this._frameSpeed = this._cachedValue; } }, - play : function (){ + + play : function (delay){ this._frameSpeed = 1; + this.animating = true; + this._startTime += (delay || 0); }, resume: function() { 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..f2dd56345 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -22,22 +22,20 @@ module.exports = { * @private */ step: function(charc, pose, t, d) { - var k, c, pts, tState, oState, ease, points; + var k, c, tState, oState, ease, points; node = charc.node; newState = pose._endAnim; ease = pose.animate && pose.animate.ease ? pose.animate.ease: this.ease; oldState = pose._startAnim; charc.currentState = charc.currentState || {}; - - 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 checkEaseChange = easings.easeChanged(ease); var propChange = easings.propChange(k); - 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])); @@ -55,7 +53,7 @@ module.exports = { } else { if (k == 'rotate') { tState = Vector.toQuant(newState[k]); - oState = oldState[k]; + oState = Vector.toQuant(oldState[k]); c = this.slerp; } else { tState = newState[k]; @@ -71,10 +69,11 @@ module.exports = { } charc.currentState[k] = cState; } - } else { + } + else{ utils.mixin(charc.currentState,oldState); } - if (charc.path) { + if(charc.path){ points = this.getBezier(t, charc.path, charc.currentState.translate, true); charc.currentState.translate = points; } @@ -90,6 +89,7 @@ module.exports = { charc.animationStep && charc.animationStep(t,matrix); }, + /** * @private */ @@ -194,6 +194,8 @@ module.exports = { return vR; }, + + lerp: function(vA, vB, t, vR) { if (!vR) vR = []; var i, l = vA.length; @@ -211,21 +213,18 @@ module.exports = { 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; }, @@ -244,7 +243,6 @@ module.exports = { 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++) { @@ -263,4 +261,5 @@ module.exports = { return vR; } + }; 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 From a7ddcd3ce6e23f13c36f0061447017629a61d9e3 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Mon, 4 Jan 2016 22:22:14 +0530 Subject: [PATCH 02/22] updated branch with multiple comp support - Multiple component animating in parallel. - Path updates in the branch Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Core.js | 49 +--- src/AnimationSupport/Director.js | 84 +++--- src/AnimationSupport/Easings.js | 4 +- src/AnimationSupport/EventDelegator.js | 13 - src/AnimationSupport/Scene.js | 358 ++++++++++++++++--------- src/AnimationSupport/SceneEditor.js | 10 +- src/AnimationSupport/Tween.js | 39 ++- 7 files changed, 296 insertions(+), 261 deletions(-) diff --git a/src/AnimationSupport/Core.js b/src/AnimationSupport/Core.js index 723bd4fdf..d3e032c67 100644 --- a/src/AnimationSupport/Core.js +++ b/src/AnimationSupport/Core.js @@ -4,10 +4,10 @@ var kind = require('../kind'), animation = require('../animation'), utils = require('../utils'), + CoreObject = require('../CoreObject'), director = require('./Director'); -var ts, wasTs, - CoreObject = require('../CoreObject'); +var ts, wasTs; /** * This module returns the Loop singleton @@ -176,46 +176,21 @@ module.exports = kind.singleton({ return; } + ts = utils.perfNow(); 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)); + //TODO: have a check to handle event based and time based together + if (curr._isTriggered && this.getAnimationDelta()) { + if (!curr.triggerEvent()) { + director.shot(curr, ts - (wasTs || ts)); + } + } else { + director.take(curr, ts - (wasTs || ts)); } } - wasTs = ts; } - this.dummy(); - }, - - /** - * TODO: Merge this implementation with actual start - * @private - */ - dummy: function () { - animation.requestAnimationFrame(this.eventLoop.bind(this)); + wasTs = ts; + this.start(); } }); \ No newline at end of file diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index a88d6d133..c79063603 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -7,35 +7,16 @@ var frame = require('./Frame'), var rolePlays = {}; /** -* 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 +* This modules exposes the features to support 'Director' approach. +* @module enyo/AnimationSupport/Scene */ 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 - */ take: function(scene, ts) { - var dur = scene.totalDuration, + var dur = scene.totalSpan(), tm = scene.rolePlay(ts), actors = rolePlays[scene]; - + if (tm < 0) return; if (tm <= dur) { for (var i = 0; i < actors.length; i++) { @@ -50,7 +31,9 @@ module.exports = { cut: function (scene) { scene.animating = false; scene.timeline = 0; - scene.completed(scene); + + //TODO: Use Event Delegator to emit this event. + scene.completed && scene.completed(scene); }, action: function(actor, scene, since) { @@ -77,19 +60,38 @@ module.exports = { if (currentAnimSince <= runningDur && runningDur !== 0) { t = currentAnimSince / runningDur; tween.step(actor, props, ( t > 0.98) ? t = 1 : t, runningDur); + + //TODO: Use Event Delegator to emit this event. + scene.step && scene.step(actor, t); } else { tween.step(actor, props, 1, runningDur); } }, - rolePlay: function (actors, scene) { - rolePlays[scene] = utils.isArray(actors) ? actors : [actors]; + casting: function (actors, scene) { + var acts = utils.isArray(actors) ? actors : [actors]; + if (!rolePlays[scene]) { + rolePlays[scene] = acts; + } else { + rolePlays[scene] = acts.reduce(function(actors, actor) { + actors.push( actor ); + return actors; + }, rolePlays[scene]); + } + }, + + reject: function (scene, actors) { + actors = actors || rolePlays[scene]; + var acts = utils.isArray(actors) ? actors : [actors]; + if (rolePlays[scene]) { + rolePlays[scene] = acts.reduce(function(actors, actor) { + var i = actors.indexOf(actor); + if (i >= 0) actors.splice(i, 1); + return actors; + }, rolePlays[scene]); + } }, - /** - * Gets current state of animation for this character - * @public - */ firstShot: function (actor) { var dom = actor.hasNode(), pose = frame.getComputedProperty(dom, undefined); @@ -99,28 +101,6 @@ module.exports = { frame.accelerate(dom, pose.matrix); }, - poseByTime: function(arr, duration) { - var startIndex = 0, - stopIndex = arr.length - 1, - middle = Math.floor((stopIndex + startIndex) / 2); - - if(duration === 0) { - return startIndex; - } - - 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); - } - - return (arr[middle].duration != duration) ? startIndex : middle; - }, - shot: function(chrac, ts) { var v1, s, a, v, t = ts, diff --git a/src/AnimationSupport/Easings.js b/src/AnimationSupport/Easings.js index cfcbf6d58..0a4673621 100644 --- a/src/AnimationSupport/Easings.js +++ b/src/AnimationSupport/Easings.js @@ -7,8 +7,8 @@ var matrixUtil = require('./Matrix'); var b = 0, - c = 1; -var temp = null, + c = 1, + temp = null, tempProp = null, tempOldState = [], tempNewState = []; diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js index b2691cf27..6ee26bdaa 100644 --- a/src/AnimationSupport/EventDelegator.js +++ b/src/AnimationSupport/EventDelegator.js @@ -41,19 +41,6 @@ var eventsMap = { */ 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 diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 1868315b6..76b5006fb 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -1,78 +1,182 @@ -var - SceneEditor = require('./SceneEditor'), - animation = require('./Core'), - delegator = require('./EventDelegator'), - director = require('./Director'), - utils = require('../utils'); - -var Scene = module.exports = function (props){ - var scene = Scene.create(); - utils.mixin(scene, SceneEditor); - - if(props.animation) { - scene.addAnimation(props.animation, props.duration || 0); - } - animation.trigger(scene); - return scene; +var + editor = require('./SceneEditor'), + core = require('./Core'), + delegator = require('./EventDelegator'), + director = require('./Director'), + utils = require('../utils'); + +/** + * Scene is used to generate animation structure. + * + * @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].duration || dur); + delete anims[i].duration; + } + delete props.animation; + } + + utils.mixin(scene, props); + core.trigger(scene); + return scene; }; -Scene.create = function () { - return new sceneConstructor(); + +/** + * Creates a empty instance of scene. + * (To used for runtime creation of animations) + */ +Scene.create = function() { + return new sceneConstructor(); }; + +/** + * Connects an actor/s to a scene. + * (All the actors should be added before initiating animation + * otherwise actors will animate for remaining time span) + */ Scene.link = function(actors, scene) { - director.rolePlay(actors, scene); + director.casting(actors, scene); scene.hasActors = true; }; -var sceneConstructor = function () { - var _poses = [], - - _eventCache = {}, - - _prevDur = 0, - - //_isActive = true, - - //_state, - - _isTriggered = false, - - _triggerer; - - - this.totalDuration = 0; - this.animating = false; - this.hasActors = false; - - this.ready = function() { - var ret = this.animating && this.hasActors !== undefined; - if (ret && this._startTime) - ret = this._startTime <= utils.perfNow(); - return ret; - }; +/** + * Disconnects an actor/s from a scene. + * (Actors could be delinked during the animation + * however they will current their state when delinked) + */ +Scene.delink = function(actors, scene) { + director.reject(scene, actors); + scene.hasActors = true; +}; - /** - * Adds new animation on already existing animation for this character. - * @public - */ - this.addAnimation = function (newProp, duration) { - if (_prevDur === 0 && duration === 0) { - _poses[0] = {animate: newProp, duration: 0}; - } else { - _prevDur = duration || _prevDur; - this.totalDuration += _prevDur; - _poses.push({animate: newProp, duration: this.totalDuration}); - } - }; - this.animateAtTime = function(duration) { +var sceneConstructor = function() { + var + /** + * Holds refereneces of the all animations added to this scene. + * @private + */ + _poses = [], + + /** + * Holds references for DOM event updates to be used for + * virtual events. + * @private + */ + _eventCache = {}, + + /** + * 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. + * @private + */ + _prevDur = 0, + + /** + * 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 = '', + + /** + * Holds refereneces of complete time span for this scene. + * @private + */ + _totalDuration = 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) + * @public + */ + this.animating = false; + + /** + * An exposed property to know if there are actors existing in this scene. + * 'true' - the scene has some actors + * 'false' - the scene without any actors + * @public + */ + this.hasActors = false; + + /** + * Checks if the sceen is/should be animating or not. + * @public + */ + this.ready = function() { + var ret = this.animating && this.hasActors !== undefined; + if (ret && this._startTime) + ret = this._startTime <= utils.perfNow(); + return ret; + }; + + /** + * Returns the life span/duration of this sceen. + * @public + */ + this.totalSpan = function() { + return _totalDuration; + }; + + /** + * Adds new animation on already existing animation for this character. + * @public + */ + this.addAnimation = function(newProp, duration) { + if (_prevDur === 0 && duration === 0) { + _poses[0] = { + animate: newProp, + duration: 0 + }; + } else { + _prevDur = duration || _prevDur; + _totalDuration += _prevDur; + _poses.push({ + animate: newProp, + duration: _totalDuration + }); + } + }; + + /** + * Returns animation pose index from the list of + * animations added to this scene for a particular + * instance of time. + * @private + */ + this.animateAtTime = function(duration) { var startIndex = 0, stopIndex = _poses.length - 1, middle = Math.floor((stopIndex + startIndex) / 2); - if(duration === 0) { + if (duration === 0) { return startIndex; } @@ -87,75 +191,69 @@ var sceneConstructor = function () { } return (_poses[middle].duration != duration) ? startIndex : middle; - }, + }; + /** + * Returns animation pose based on index from the list of + * animations added to this scene. + * @public + */ this.getAnimation = function(index) { - return index < 0 || _poses[index]; - }, - - /** - * Sets new animation for this character. - * @public - */ - this.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 - */ - this.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; - this.eventCacheUpdated = true; - }; - - /** - * Gets the delta values of x, y and z for events - * @public - */ - this.getAnimationDelta = function () { - return _eventCache[_triggerer]; - }; - - /** - * Idnetify when the character has done animating. - * This triggers "onAnimated" event on this character - * @public - */ - this.completed = function() { - return this.onAnimated && this.onAnimated(this); - }; - - - /** - * Trigger the registered event to all the listeners - * @public - */ - this.triggerEvent = function () { - _isTriggered = false; - return delegator.emitEvent(this, this.getAnimationDelta()); - }; - -}; - - - - - - - - - - - - - \ No newline at end of file + return index < 0 || _poses[index]; + }; + + /** + * Sets new animation for this character. + * @public + */ + this.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 + */ + this.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; + }; + + /** + * Gets the delta values of x, y and z for events + * @public + */ + this.getAnimationDelta = function() { + return _eventCache[_triggerer]; + }; + + /** + * Trigger the registered event to all the listeners + * @public + */ + this.triggerEvent = function() { + _isTriggered = false; + return delegator.emitEvent(this, this.getAnimationDelta()); + }; + + + //TODO: Move these events to Event Delegator + /** + * Event to identify when the scene has done animating. + * @public + */ + this.completed = function() {}; + + /** + * Event to identify when the scene has done animating. + * @public + */ + this.step = function() {}; +}; \ No newline at end of file diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js index 37a15e128..68c3d793f 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -1,11 +1,10 @@ require('enyo'); -module.exports = { /** - * - * - * @public - */ +* This modules exposes API's for controlling animations. +* @private +*/ +module.exports = { timeline: 0, _cachedValue: 0, @@ -21,7 +20,6 @@ module.exports = { play : function (delay){ this._frameSpeed = 1; this.animating = true; - this._startTime += (delay || 0); }, resume: function() { diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index f2dd56345..44c26c37e 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -3,7 +3,6 @@ require('enyo'); var frame = require('./Frame'), easings = require('./Easings'), - matrixUtil = require('./Matrix'), Vector = require('./Vector'), utils = require('../utils'); @@ -17,19 +16,20 @@ var oldState, newState, node, matrix, cState = []; * @module enyo/AnimationSupport/Tween */ module.exports = { - + /** * @private */ step: function(charc, pose, t, d) { - var k, c, tState, oState, ease, points; + var k, c, tState, oState, ease, points, path; node = charc.node; newState = pose._endAnim; - ease = pose.animate && pose.animate.ease ? pose.animate.ease: this.ease; + ease = pose.animate && pose.animate.ease ? pose.animate.ease : this.ease; + path = pose.animate && pose.animate.path; oldState = pose._startAnim; charc.currentState = charc.currentState || {}; - if(pose.props){ + if (pose.props) { for (k in pose.props) { cState = frame.copy(charc.currentState[k] || []); if (newState[k]) { @@ -48,7 +48,7 @@ module.exports = { } } cState = this.getBezier(t, charc.controlPoints, cState); - if (k == 'rotate') + if (k == 'rotate') cState = Vector.toQuant(cState); } else { if (k == 'rotate') { @@ -69,14 +69,15 @@ module.exports = { } charc.currentState[k] = cState; } + } else { + utils.mixin(charc.currentState, oldState); } - else{ - utils.mixin(charc.currentState,oldState); - } - if(charc.path){ - points = this.getBezier(t, charc.path, charc.currentState.translate, true); + + if (path) { + points = this.getBezier(t, path, charc.currentState.translate, true); charc.currentState.translate = points; } + matrix = frame.recomposeMatrix( charc.currentState.translate, charc.currentState.rotate, @@ -85,8 +86,7 @@ module.exports = { charc.currentState.perspective ); frame.accelerate(node, matrix); - - charc.animationStep && charc.animationStep(t,matrix); + charc.currentState.matrix = matrix; }, @@ -246,20 +246,17 @@ module.exports = { for (i = 0; i < l; i++) { vR[i] = 0; for (j = 0; j < c; j++) { - if(isPath){ + if (isPath) { vR[i] = vR[i] + (points[j][i] * values[j]); - } - else { - if((j > 0) && (j < (c - 1))){ + } 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 From 9dc7d563a0774b09e1aa23270025f2d78b7bae76 Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Wed, 6 Jan 2016 12:26:57 +0530 Subject: [PATCH 03/22] Fixed some issue related to multiple animation Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Director.js | 24 ++++++++++++++---------- src/AnimationSupport/Scene.js | 13 ++++++++++--- src/AnimationSupport/Tween.js | 2 +- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index c79063603..a4d438b73 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -15,7 +15,7 @@ module.exports = { take: function(scene, ts) { var dur = scene.totalSpan(), tm = scene.rolePlay(ts), - actors = rolePlays[scene]; + actors = rolePlays[scene.getID()]; if (tm < 0) return; if (tm <= dur) { @@ -69,26 +69,29 @@ module.exports = { }, casting: function (actors, scene) { - var acts = utils.isArray(actors) ? actors : [actors]; - if (!rolePlays[scene]) { - rolePlays[scene] = acts; + var acts = utils.isArray(actors) ? actors : [actors], + id = scene.getID(); + + if (!rolePlays[id]) { + rolePlays[id] = acts; } else { - rolePlays[scene] = acts.reduce(function(actors, actor) { + rolePlays[id] = acts.reduce(function(actors, actor) { actors.push( actor ); return actors; - }, rolePlays[scene]); + }, rolePlays[id]); } }, reject: function (scene, actors) { - actors = actors || rolePlays[scene]; + var id = scene.getID(); + actors = actors || rolePlays[id]; var acts = utils.isArray(actors) ? actors : [actors]; - if (rolePlays[scene]) { - rolePlays[scene] = acts.reduce(function(actors, actor) { + 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[scene]); + }, rolePlays[id]); } }, @@ -98,6 +101,7 @@ module.exports = { pose.duration = 0; actor._initialPose = pose; actor.currentState = pose.currentState; + frame.accelerate(dom, pose.matrix); }, diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 76b5006fb..b8928d2e4 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -15,9 +15,9 @@ var Scene = module.exports = function(props) { 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].duration || dur); delete anims[i].duration; @@ -36,7 +36,7 @@ var Scene = module.exports = function(props) { * (To used for runtime creation of animations) */ Scene.create = function() { - return new sceneConstructor(); + return new sceneConstructor("@"+ utils.perfNow()); }; @@ -62,8 +62,10 @@ Scene.delink = function(actors, scene) { }; -var sceneConstructor = function() { +var sceneConstructor = function(id) { var + + _id = id, /** * Holds refereneces of the all animations added to this scene. * @private @@ -126,6 +128,11 @@ var sceneConstructor = function() { */ this.hasActors = false; + + this.getID = function () { + return _id; + }; + /** * Checks if the sceen is/should be animating or not. * @public diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 44c26c37e..bae4bceaa 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -53,7 +53,7 @@ module.exports = { } else { if (k == 'rotate') { tState = Vector.toQuant(newState[k]); - oState = Vector.toQuant(oldState[k]); + oState = oldState[k]; c = this.slerp; } else { tState = newState[k]; From da705d6eec49f42438c773f6089bf15e65f3c882 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Wed, 6 Jan 2016 22:31:12 +0530 Subject: [PATCH 04/22] Updated changes for ease and load time rendering Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Core.js | 94 +++----- src/AnimationSupport/Director.js | 27 ++- src/AnimationSupport/Easings.js | 32 --- src/AnimationSupport/EventDelegator.js | 4 +- src/AnimationSupport/Scene.js | 35 ++- src/AnimationSupport/Tween.js | 291 +++++++++++++------------ 6 files changed, 224 insertions(+), 259 deletions(-) diff --git a/src/AnimationSupport/Core.js b/src/AnimationSupport/Core.js index d3e032c67..90cb77f16 100644 --- a/src/AnimationSupport/Core.js +++ b/src/AnimationSupport/Core.js @@ -2,10 +2,10 @@ require('enyo'); var kind = require('../kind'), - animation = require('../animation'), utils = require('../utils'), - CoreObject = require('../CoreObject'), - director = require('./Director'); + director = require('./Director'), + animation = require('../animation'), + CoreObject = require('../CoreObject'); var ts, wasTs; @@ -14,8 +14,7 @@ var ts, wasTs; * 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. +* - Update director to handle scenes. * * @module enyo/Core */ @@ -34,7 +33,7 @@ module.exports = kind.singleton({ /** * @private */ - chracs: [], + scenes: [], /** * @private @@ -54,18 +53,18 @@ module.exports = kind.singleton({ /** * 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. + * otherwise wake up core to handle animation for a scene. * * 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 + * @parameter scene- Animation scene * * @public */ - trigger: function (charc) { - if (!charc.animating) { - this.chracs.push(charc); + trigger: function (scene) { + if (!scene.animating) { + this.scenes.push(scene); } if (!this.running) { this.running = true; @@ -73,25 +72,6 @@ module.exports = kind.singleton({ } }, - /** - * 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. @@ -99,18 +79,18 @@ module.exports = kind.singleton({ * 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 + * @parameter scene- Animation scene * * @public */ - remove: function (curr) { - var i = this.chracs.indexOf(curr); - if (i >= 0) this.chracs.splice(i, 1); + remove: function (scene) { + var i = this.scenes.indexOf(scene); + if (i >= 0) this.scenes.splice(i, 1); }, /** * Animator public API to pause animation happening on all the - * characters. + * scenes. * * As of now this method is provided as an interface for application * to directly trigger an animation. However, this will be later made private @@ -119,36 +99,12 @@ module.exports = kind.singleton({ * @public */ pause: function () { - for (var i = 0; i < this.chracs.length; i++) { - this.chracs[i].animating = false; + for (var i = 0; i < this.scenes.length; i++) { + this.scenes[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 */ @@ -167,8 +123,8 @@ module.exports = kind.singleton({ * @private */ loop: function () { - var i, curr, - len = this.chracs.length; + var i, scene, + len = this.scenes.length; if (len <= 0) { this.cancel(); @@ -178,15 +134,15 @@ module.exports = kind.singleton({ ts = utils.perfNow(); for (i = 0; i < len; i++) { - curr = this.chracs[i]; - if (curr && curr.ready()) { + scene = this.scenes[i]; + if (scene && scene.ready()) { //TODO: have a check to handle event based and time based together - if (curr._isTriggered && this.getAnimationDelta()) { - if (!curr.triggerEvent()) { - director.shot(curr, ts - (wasTs || ts)); + if (scene._isTriggered && this.getAnimationDelta()) { + if (!scene.triggerEvent()) { + director.shot(scene, ts - (wasTs || ts)); } } else { - director.take(curr, ts - (wasTs || ts)); + director.take(scene, ts - (wasTs || ts)); } } } diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index a4d438b73..9a322b460 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -11,6 +11,23 @@ var rolePlays = {}; * @module enyo/AnimationSupport/Scene */ module.exports = { + + roll: function (scene) { + var actor, + actors = rolePlays[scene.getID()], + l = actors ? actors.length: 0, + active = l > 0; + + for (var i = 0; i < l; i++) { + actor = actors[i]; + if(actor.generated && !actor._initialPose) { + this.firstShot(actor); + scene.register(actor); + active = false; + } + } + scene.active = active; + }, take: function(scene, ts) { var dur = scene.totalSpan(), @@ -68,7 +85,7 @@ module.exports = { } }, - casting: function (actors, scene) { + cast: function (actors, scene) { var acts = utils.isArray(actors) ? actors : [actors], id = scene.getID(); @@ -105,11 +122,11 @@ module.exports = { frame.accelerate(dom, pose.matrix); }, - shot: function(chrac, ts) { + shot: function(actor, ts) { var v1, s, a, v, t = ts, - dt = chrac._eventCache, - dir = this.angle(chrac.direction), + dt = actor._eventCache, + dir = this.angle(actor.direction), v0 = dt.velocity || 0; v1 = dt[dir] / t; @@ -125,7 +142,7 @@ module.exports = { dt[dir] = 0; } dt.velocity = v1; - this.take(chrac, dt[dir] > 0 ? v : -v); + this.take(actor, dt[dir] > 0 ? v : -v); } }, diff --git a/src/AnimationSupport/Easings.js b/src/AnimationSupport/Easings.js index 0a4673621..c40289695 100644 --- a/src/AnimationSupport/Easings.js +++ b/src/AnimationSupport/Easings.js @@ -4,7 +4,6 @@ * @module enyo/AnimationSupport/Easings * @public */ -var matrixUtil = require('./Matrix'); var b = 0, c = 1, @@ -134,37 +133,6 @@ 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; - }, /** * @private * @params n: order, k: current position diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js index 6ee26bdaa..65341c64a 100644 --- a/src/AnimationSupport/EventDelegator.js +++ b/src/AnimationSupport/EventDelegator.js @@ -50,8 +50,8 @@ var EventDelegator = { * - mousewheel * @public */ - register: function (charc) { - var events = charc.handleAnimationEvents || {}; + register: function (events) { + events = events || {}; for (var key in events) { this.addRemoveListener(charc, key, events[key]); } diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index b8928d2e4..5f0dbff8b 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -15,6 +15,7 @@ var Scene = module.exports = function(props) { dur = props.duration || 0; utils.mixin(scene, editor); + if (props.animation) { var anims = utils.isArray(props.animation) ? props.animation : [props.animation]; @@ -23,8 +24,10 @@ var Scene = module.exports = function(props) { delete anims[i].duration; } delete props.animation; + delete props.duration; } + utils.mixin(scene, props); core.trigger(scene); return scene; @@ -46,8 +49,7 @@ Scene.create = function() { * otherwise actors will animate for remaining time span) */ Scene.link = function(actors, scene) { - director.casting(actors, scene); - scene.hasActors = true; + director.cast(actors, scene); }; @@ -58,7 +60,6 @@ Scene.link = function(actors, scene) { */ Scene.delink = function(actors, scene) { director.reject(scene, actors); - scene.hasActors = true; }; @@ -121,12 +122,12 @@ var sceneConstructor = function(id) { this.animating = false; /** - * An exposed property to know if there are actors existing in this scene. - * 'true' - the scene has some actors - * 'false' - the scene without any actors + * 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 * @public */ - this.hasActors = false; + this.active = false; this.getID = function () { @@ -138,10 +139,12 @@ var sceneConstructor = function(id) { * @public */ this.ready = function() { - var ret = this.animating && this.hasActors !== undefined; - if (ret && this._startTime) - ret = this._startTime <= utils.perfNow(); - return ret; + if (this.animating) { + if (this.active) return true; + director.roll(this); + this._startTime = utils.perfNow(); + } + return false; }; /** @@ -250,6 +253,16 @@ var sceneConstructor = function(id) { return delegator.emitEvent(this, this.getAnimationDelta()); }; + /** + * Activates handles for generated actors + * @public + */ + this.register = function (actor) { + if (this.handlers) { + delegator.register(this, actor); + } + }; + //TODO: Move these events to Event Delegator /** diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index bae4bceaa..33282fec7 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -2,8 +2,9 @@ require('enyo'); var frame = require('./Frame'), - easings = require('./Easings'), + Easings = require('./Easings'), Vector = require('./Vector'), + Matrix = require('./Matrix'), utils = require('../utils'); var oldState, newState, node, matrix, cState = []; @@ -20,73 +21,70 @@ module.exports = { /** * @private */ - step: function(charc, pose, t, d) { - var k, c, tState, oState, ease, points, path; + step: function(actor, pose, t, d) { + var k, c, state, ease, points, path; - node = charc.node; - newState = pose._endAnim; + node = actor.node; + state = actor.currentState = actor.currentState || {}; + points = pose.controlPoints = pose.controlPoints || {}; ease = pose.animate && pose.animate.ease ? pose.animate.ease : this.ease; path = pose.animate && pose.animate.path; - oldState = pose._startAnim; - charc.currentState = charc.currentState || {}; + 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 (!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); + if (!pose._endAnim[k]) { + continue; + } + + 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]); + c = this.bezierSpline; } 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); + points[k] = points[k] || + this.bezierPoints(ease, oldState, newState, points[k]); + c = this.bezier; } + cState = c.call(this, t, points[k], cState); + } else { + if (k == 'rotate') { + newState = Vector.toQuant(newState); + c = this.slerp; + } else { + c = this.lerp; + } + cState = c.call(this, oldState, newState, ease(t, d), cState); } - + if (!frame.isTransform(k)) { frame.setProperty(node, k, cState); } - charc.currentState[k] = cState; + state[k] = cState; } } else { - utils.mixin(charc.currentState, oldState); + utils.mixin(state, oldState); } + //TODO: Support for properties other than translate if (path) { - points = this.getBezier(t, path, charc.currentState.translate, true); - charc.currentState.translate = points; + 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.currentState.matrix = matrix; + state.matrix = matrix; }, @@ -96,48 +94,127 @@ module.exports = { ease: function(t) { return t; }, + + lerp: function(vA, vB, t, vR) { + if (!vR) vR = []; + var i, l = vA.length; - //Without control points - beizerSlerpPoints: function(ease, startQuat, endQuat, endPoint) { - var tm, ag, q, key, - splinePoints = {}, - eD = frame.parseValue(endPoint), - aN = startQuat; + for (i = 0; i < l; i++) { + vR[i] = (1 - t) * vA[i] + t * vB[i]; + } + return vR; + }, - 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; + 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 + */ + bezier: function(t, points, vR) { + + 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; + bezierPoints: function(easeObj, startPoint, endPoint, points) { + 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; + }, + + traversePath: function (t, path, vR) { + 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], + bezierSPoints: function(ease, startQuat, endQuat, endPoint, splinePoints) { + var time = [0], quats = [startQuat]; var t, a, q, n, _a, aI, bN, eD = frame.parseValue(endPoint); + splinePoints = splinePoints || {}; + if (ease && Object.keys(ease).length > 0) { for (var key in ease) { t = parseFloat(key) / 100; @@ -172,7 +249,7 @@ module.exports = { }, //With control points - beizerSpline: function(t, points, vR) { + bezierSpline: function(t, points, vR) { if (!vR) vR = []; var Q0, Q1, Q2, R0, R1; @@ -192,71 +269,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 From f938428a319cd0ffad91eeebf280f29f9cff370f Mon Sep 17 00:00:00 2001 From: Madala Cholan Satyanarayana Date: Fri, 8 Jan 2016 19:25:07 +0530 Subject: [PATCH 05/22] Updates in the scene approach Enyo-DCO-1.1-Signed-off-by:Madala Satyanarayana --- src/AnimationSupport/Director.js | 50 ++++++++++++------- src/AnimationSupport/EventDelegator.js | 2 - src/AnimationSupport/Scene.js | 10 ++-- src/AnimationSupport/SceneEditor.js | 68 +++++++++++++++----------- src/AnimationSupport/Tween.js | 14 +++--- 5 files changed, 85 insertions(+), 59 deletions(-) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index 9a322b460..dc10f4513 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -22,7 +22,6 @@ module.exports = { actor = actors[i]; if(actor.generated && !actor._initialPose) { this.firstShot(actor); - scene.register(actor); active = false; } } @@ -30,27 +29,32 @@ module.exports = { }, take: function(scene, ts) { - var dur = scene.totalSpan(), - tm = scene.rolePlay(ts), - actors = rolePlays[scene.getID()]; - - if (tm < 0) return; - if (tm <= dur) { - for (var i = 0; i < actors.length; i++) { - if(actors[i].generated) + var tm, stm, actor, + dur = scene.totalSpan(), + active = false, + actors = rolePlays[scene.getID()], + l = actors.length; + + if (scene._frameSpeed) { + stm = scene.rolePlay(ts, actor); + } + for (var i = 0; i < l; i++) { + actor = actors[i]; + if (actor.generated) { + actor = stm ? scene : actor; + tm = stm || scene.rolePlay(ts, actor); + tm -= (actor._startTime || 0); + if (isNaN(tm) || tm <= 0) continue; + if (tm < dur) { this.action(actors[i], scene, tm); + active = true; + } else { + actor.timeline = dur; + this.cut(scene, actor); + } } - } else { - this.cut(scene); } - }, - - cut: function (scene) { - scene.animating = false; - scene.timeline = 0; - - //TODO: Use Event Delegator to emit this event. - scene.completed && scene.completed(scene); + scene.animating = active; }, action: function(actor, scene, since) { @@ -85,6 +89,14 @@ module.exports = { } }, + + cut: function (scene, actor) { + //TODO: Use Event Delegator to emit this event. + //scene.clearAnimation(); + scene.completed && scene.completed(actor); + }, + + cast: function (actors, scene) { var acts = utils.isArray(actors) ? actors : [actors], id = scene.getID(); diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js index 65341c64a..ab8fc36b5 100644 --- a/src/AnimationSupport/EventDelegator.js +++ b/src/AnimationSupport/EventDelegator.js @@ -200,9 +200,7 @@ var EventDelegator = { inEvent.dY = inEvent.deltaY; inEvent.dZ = 0; inEvent.vtype = eventsMap[inEvent.type]; - sender.setAnimationDelta(inEvent); - sender._virtualEvent = eventsMap[inEvent.type]; } }; diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 5f0dbff8b..a0a02a600 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -27,7 +27,6 @@ var Scene = module.exports = function(props) { delete props.duration; } - utils.mixin(scene, props); core.trigger(scene); return scene; @@ -142,7 +141,6 @@ var sceneConstructor = function(id) { if (this.animating) { if (this.active) return true; director.roll(this); - this._startTime = utils.perfNow(); } return false; }; @@ -203,6 +201,12 @@ var sceneConstructor = function(id) { return (_poses[middle].duration != duration) ? startIndex : middle; }; + 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. @@ -259,7 +263,7 @@ var sceneConstructor = function(id) { */ this.register = function (actor) { if (this.handlers) { - delegator.register(this, actor); + delegator.register(actor, this.handlers); } }; diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js index 68c3d793f..0a9ae54df 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -8,54 +8,66 @@ module.exports = { timeline: 0, _cachedValue: 0, - _frameSpeed: 1, + _frameSpeed: 0, _startTime: 0, - cache: function(){ - if(this._frameSpeed === 0){ - this._frameSpeed = this._cachedValue; + cache: function(actor) { + actor = actor || this; + if(actor._frameSpeed === 0){ + actor._frameSpeed = actor._cachedValue; } + this.animating = true; }, - play : function (delay){ - this._frameSpeed = 1; + play: function (actor) { + actor = actor || this; + actor._frameSpeed = 1; this.animating = true; + actor._startTime = (actor.delay || 0); }, - resume: function() { - this.cache(); - this._frameSpeed *= 1; + resume: function(actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= 1; }, - pause: function () { - this._cachedValue = this._frameSpeed; - this._frameSpeed = 0; + pause: function (actor) { + actor = actor || this; + actor._cachedValue = actor._frameSpeed; + actor._frameSpeed = 0; }, - reverse: function () { - this.cache(); - this._frameSpeed *= -1; + reverse: function (actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= -1; }, - fast: function (mul) { - this.cache(); - this._frameSpeed *= mul; + fast: function (mul, actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= mul; }, - slow: function (mul) { - this.cache(); - this._frameSpeed *= mul; + slow: function (mul, actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= mul; }, - stop: function () { - this._cachedValue = 1; - this._frameSpeed = 0; - this.timeline = 0; + stop: function (actor) { + actor = actor || this; + actor._cachedValue = 1; + actor._frameSpeed = 0; + actor.timeline = 0; }, - rolePlay: function (t) { - this.timeline += _rolePlay(t, this._frameSpeed); - return this.timeline; + rolePlay: function (t, actor) { + actor = actor || this; + if (!actor.timeline || actor.timeline < 0) actor.timeline = 0; + actor.timeline += _rolePlay(t, actor._frameSpeed); + return actor.timeline; } }; diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 33282fec7..757793500 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -22,7 +22,7 @@ module.exports = { * @private */ step: function(actor, pose, t, d) { - var k, c, state, ease, points, path; + var k, fn, state, ease, points, path; node = actor.node; state = actor.currentState = actor.currentState || {}; @@ -45,21 +45,21 @@ module.exports = { newState = Vector.toQuant(newState); points[k] = points[k] || this.bezierSPoints(ease, oldState, newState, pose.props[k], points[k]); - c = this.bezierSpline; + fn = this.bezierSpline; } else { points[k] = points[k] || this.bezierPoints(ease, oldState, newState, points[k]); - c = this.bezier; + fn = this.bezier; } - cState = c.call(this, t, points[k], cState); + cState = fn.call(this, t, points[k], cState); } else { if (k == 'rotate') { newState = Vector.toQuant(newState); - c = this.slerp; + fn = this.slerp; } else { - c = this.lerp; + fn = this.lerp; } - cState = c.call(this, oldState, newState, ease(t, d), cState); + cState = fn.call(this, oldState, newState, ease(t, d), cState); } if (!frame.isTransform(k)) { From ec1c21e8d6c43854f7a5566c5adbb306ee32ad05 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Fri, 8 Jan 2016 20:09:24 +0530 Subject: [PATCH 06/22] Making scene active Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Director.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index dc10f4513..f8e16b7c6 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -37,6 +37,7 @@ module.exports = { if (scene._frameSpeed) { stm = scene.rolePlay(ts, actor); + active = true; } for (var i = 0; i < l; i++) { actor = actors[i]; From d33cbe14d578e2db6d298944f7c3a4d27f4813c2 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Thu, 21 Jan 2016 16:30:40 +0530 Subject: [PATCH 07/22] Updates of scene with raf Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Core.js | 152 -------- src/AnimationSupport/Director.js | 109 ++---- src/AnimationSupport/EventDelegator.js | 6 +- src/AnimationSupport/Scene.js | 494 +++++++++++++------------ src/AnimationSupport/SceneActor.js | 48 +++ src/AnimationSupport/SceneEditor.js | 19 +- src/AnimationSupport/SceneEvent.js | 104 ++++++ src/AnimationSupport/Tween.js | 3 +- 8 files changed, 465 insertions(+), 470 deletions(-) delete mode 100644 src/AnimationSupport/Core.js create mode 100644 src/AnimationSupport/SceneActor.js create mode 100644 src/AnimationSupport/SceneEvent.js diff --git a/src/AnimationSupport/Core.js b/src/AnimationSupport/Core.js deleted file mode 100644 index 90cb77f16..000000000 --- a/src/AnimationSupport/Core.js +++ /dev/null @@ -1,152 +0,0 @@ -require('enyo'); - -var - kind = require('../kind'), - utils = require('../utils'), - director = require('./Director'), - animation = require('../animation'), - CoreObject = require('../CoreObject'); - -var ts, wasTs; - -/** -* 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. -* - Update director to handle scenes. -* -* @module enyo/Core -*/ -module.exports = kind.singleton({ - /** @lends module:enyo/Core */ - - /** - * @private - */ - name: 'enyo.Core', - /** - * @private - */ - kind: CoreObject, - - /** - * @private - */ - scenes: [], - - /** - * @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 scene. - * - * 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 scene- Animation scene - * - * @public - */ - trigger: function (scene) { - if (!scene.animating) { - this.scenes.push(scene); - } - if (!this.running) { - this.running = true; - this.start(); - } - }, - - /** - * 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 scene- Animation scene - * - * @public - */ - remove: function (scene) { - var i = this.scenes.indexOf(scene); - if (i >= 0) this.scenes.splice(i, 1); - }, - - /** - * Animator public API to pause animation happening on all the - * scenes. - * - * 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.scenes.length; i++) { - this.scenes[i].animating = false; - } - }, - - - /** - * @private - */ - start: function () { - this.req = animation.requestAnimationFrame(this.bindSafely(this.loop)); - }, - - /** - * @private - */ - cancel: function () { - animation.cancelRequestAnimationFrame(this.req); - }, - - /** - * @private - */ - loop: function () { - var i, scene, - len = this.scenes.length; - - if (len <= 0) { - this.cancel(); - this.running = false; - return; - } - - ts = utils.perfNow(); - for (i = 0; i < len; i++) { - scene = this.scenes[i]; - if (scene && scene.ready()) { - //TODO: have a check to handle event based and time based together - if (scene._isTriggered && this.getAnimationDelta()) { - if (!scene.triggerEvent()) { - director.shot(scene, ts - (wasTs || ts)); - } - } else { - director.take(scene, ts - (wasTs || ts)); - } - } - } - wasTs = ts; - this.start(); - } -}); \ No newline at end of file diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index f8e16b7c6..506014a9c 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -4,7 +4,7 @@ var frame = require('./Frame'), tween = require('./Tween'), utils = require('../utils'); -var rolePlays = {}; +//var rolePlays = {}; /** * This modules exposes the features to support 'Director' approach. @@ -14,9 +14,9 @@ module.exports = { roll: function (scene) { var actor, - actors = rolePlays[scene.getID()], + actors = scene.rolePlays ? scene.rolePlays[scene.getID()]: [], l = actors ? actors.length: 0, - active = l > 0; + active = true; for (var i = 0; i < l; i++) { actor = actors[i]; @@ -27,80 +27,47 @@ module.exports = { } scene.active = active; }, - - take: function(scene, ts) { - var tm, stm, actor, - dur = scene.totalSpan(), - active = false, - actors = rolePlays[scene.getID()], - l = actors.length; - if (scene._frameSpeed) { - stm = scene.rolePlay(ts, actor); - active = true; + take: function (scene, ts) { + var pose, + dur = scene.span, + tm = scene.timeline; + + //TODO: need to find the right spot for capturing inital pose. + if (!scene.active) { + this.roll(scene); } - for (var i = 0; i < l; i++) { - actor = actors[i]; - if (actor.generated) { - actor = stm ? scene : actor; - tm = stm || scene.rolePlay(ts, actor); - tm -= (actor._startTime || 0); - if (isNaN(tm) || tm <= 0) continue; - if (tm < dur) { - this.action(actors[i], scene, tm); - active = true; - } else { - actor.timeline = dur; - this.cut(scene, actor); - } - } + if (isNaN(tm) || tm < 0) return; + if (tm <= dur) { + pose = scene.action(ts, pose); + //TODO: Use Event Delegator to emit this event. + scene.step && scene.step(pose); + } else { + scene.timeline = dur; + scene.animating = false; } - scene.animating = active; }, - action: function(actor, scene, since) { - var pose, t, prevDur, currentAnimSince, runningDur, - index = scene.animateAtTime(since), - props = scene.getAnimation(index); - - if(index) { - prevDur = scene.getAnimation(index - 1).duration; - } else { - if (!actor._initialPose) this.firstShot(actor); - prevDur = actor._initialPose.duration; - } - - currentAnimSince = since - prevDur, - runningDur = props.duration - prevDur; + action: function (pose, actor, since, dur) { + var t; - if (!props._startAnim) { - pose = frame.getComputedProperty(actor.hasNode(), props.animate, actor.currentState); - utils.mixin(props, pose); + if (!pose._startAnim) { + utils.mixin(pose, + frame.getComputedProperty(actor.hasNode(), pose.animate, actor.currentState)); } - - if (currentAnimSince < 0) return; - if (currentAnimSince <= runningDur && runningDur !== 0) { - t = currentAnimSince / runningDur; - tween.step(actor, props, ( t > 0.98) ? t = 1 : t, runningDur); - - //TODO: Use Event Delegator to emit this event. - scene.step && scene.step(actor, t); + 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, props, 1, runningDur); + tween.step(actor, pose, 1, dur); } }, - - - cut: function (scene, actor) { - //TODO: Use Event Delegator to emit this event. - //scene.clearAnimation(); - scene.completed && scene.completed(actor); - }, - - + cast: function (actors, scene) { var acts = utils.isArray(actors) ? actors : [actors], - id = scene.getID(); + id = scene.getID(), + rolePlays = scene.rolePlays || []; if (!rolePlays[id]) { rolePlays[id] = acts; @@ -110,12 +77,14 @@ module.exports = { return actors; }, rolePlays[id]); } + scene.rolePlays = rolePlays; }, reject: function (scene, actors) { - var id = scene.getID(); + var id = scene.getID(), acts, + rolePlays = scene.rolePlays || []; actors = actors || rolePlays[id]; - var acts = utils.isArray(actors) ? actors : [actors]; + acts = utils.isArray(actors) ? actors : [actors]; if (rolePlays[id]) { rolePlays[id] = acts.reduce(function(actors, actor) { var i = actors.indexOf(actor); @@ -123,16 +92,16 @@ module.exports = { return actors; }, rolePlays[id]); } + scene.rolePlays = rolePlays; }, firstShot: function (actor) { var dom = actor.hasNode(), pose = frame.getComputedProperty(dom, undefined); - pose.duration = 0; + pose.span = 0; actor._initialPose = pose; actor.currentState = pose.currentState; - - frame.accelerate(dom, pose.matrix); + // frame.accelerate(dom, pose.matrix); }, shot: function(actor, ts) { diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js index ab8fc36b5..349f839cc 100644 --- a/src/AnimationSupport/EventDelegator.js +++ b/src/AnimationSupport/EventDelegator.js @@ -50,7 +50,7 @@ var EventDelegator = { * - mousewheel * @public */ - register: function (events) { + register: function (charc, events) { events = events || {}; for (var key in events) { this.addRemoveListener(charc, key, events[key]); @@ -66,8 +66,8 @@ var EventDelegator = { * - mousewheel * @public */ - deRegister: function (charc) { - var events = charc.handleAnimationEvents || {}; + deRegister: function (charc, events) { + events = events || {}; for (var key in events) { this.addRemoveListener(charc, key, events[key], true); } diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index a0a02a600..f240a23e5 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -1,35 +1,33 @@ var - editor = require('./SceneEditor'), - core = require('./Core'), - delegator = require('./EventDelegator'), - director = require('./Director'), - utils = require('../utils'); + editor = require('./SceneEditor'), + director = require('./Director'), + animation = require('../animation'), + utils = require('../utils'); /** * Scene is used to generate animation structure. - * * @module enyo/AnimationSupport/Scene */ var Scene = module.exports = function(props) { - var scene = Scene.create(), - dur = props.duration || 0; + var scene = Scene.create(), + dur = props.duration || 0; - utils.mixin(scene, editor); + utils.mixin(scene, editor); - if (props.animation) { - var anims = utils.isArray(props.animation) ? props.animation : [props.animation]; + 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].duration || dur); - delete anims[i].duration; - } - delete props.animation; - delete props.duration; - } + for (var i = 0; i < anims.length; i++) { + scene.addAnimation(anims[i], anims[i].span || anims[i].duration || dur); + delete anims[i].duration; + } + delete props.animation; + delete props.duration; + } - utils.mixin(scene, props); - core.trigger(scene); - return scene; + utils.mixin(scene, props); + utils.mixin(scene, SceneAction); + return scene; }; @@ -38,7 +36,7 @@ var Scene = module.exports = function(props) { * (To used for runtime creation of animations) */ Scene.create = function() { - return new sceneConstructor("@"+ utils.perfNow()); + return new sceneConstructor("@"+ utils.perfNow()); }; @@ -48,7 +46,7 @@ Scene.create = function() { * otherwise actors will animate for remaining time span) */ Scene.link = function(actors, scene) { - director.cast(actors, scene); + director.cast(actors, scene); }; @@ -58,226 +56,240 @@ Scene.link = function(actors, scene) { * however they will current their state when delinked) */ Scene.delink = function(actors, scene) { - director.reject(scene, actors); + director.reject(scene, actors); }; var sceneConstructor = function(id) { - var - - _id = id, - /** - * Holds refereneces of the all animations added to this scene. - * @private - */ - _poses = [], - - /** - * Holds references for DOM event updates to be used for - * virtual events. - * @private - */ - _eventCache = {}, - - /** - * 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. - * @private - */ - _prevDur = 0, - - /** - * 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 = '', - - /** - * Holds refereneces of complete time span for this scene. - * @private - */ - _totalDuration = 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) - * @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 - * @public - */ - this.active = false; - - - this.getID = function () { - return _id; - }; - - /** - * Checks if the sceen is/should be animating or not. - * @public - */ - this.ready = function() { - if (this.animating) { - if (this.active) return true; - director.roll(this); - } - return false; - }; - - /** - * Returns the life span/duration of this sceen. - * @public - */ - this.totalSpan = function() { - return _totalDuration; - }; - - /** - * Adds new animation on already existing animation for this character. - * @public - */ - this.addAnimation = function(newProp, duration) { - if (_prevDur === 0 && duration === 0) { - _poses[0] = { - animate: newProp, - duration: 0 - }; - } else { - _prevDur = duration || _prevDur; - _totalDuration += _prevDur; - _poses.push({ - animate: newProp, - duration: _totalDuration - }); - } - }; - - /** - * Returns animation pose index from the list of - * animations added to this scene for a particular - * instance of time. - * @private - */ - this.animateAtTime = function(duration) { - var startIndex = 0, - stopIndex = _poses.length - 1, - middle = Math.floor((stopIndex + startIndex) / 2); - - if (duration === 0) { - return startIndex; - } - - while (_poses[middle].duration != duration && startIndex < stopIndex) { - if (duration < _poses[middle].duration) { - stopIndex = middle; - } else if (duration > _poses[middle].duration) { - startIndex = middle + 1; - } - - middle = Math.floor((stopIndex + startIndex) / 2); - } - - return (_poses[middle].duration != duration) ? startIndex : middle; - }; - - 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. - * @public - */ - this.getAnimation = function(index) { - return index < 0 || _poses[index]; - }; - - /** - * Sets new animation for this character. - * @public - */ - this.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 - */ - this.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; - }; - - /** - * Gets the delta values of x, y and z for events - * @public - */ - this.getAnimationDelta = function() { - return _eventCache[_triggerer]; - }; - - /** - * Trigger the registered event to all the listeners - * @public - */ - this.triggerEvent = function() { - _isTriggered = false; - return delegator.emitEvent(this, this.getAnimationDelta()); - }; - - /** - * Activates handles for generated actors - * @public - */ - this.register = function (actor) { - if (this.handlers) { - delegator.register(actor, this.handlers); - } - }; - - - //TODO: Move these events to Event Delegator - /** - * Event to identify when the scene has done animating. - * @public - */ - this.completed = function() {}; - - /** - * Event to identify when the scene has done animating. - * @public - */ - this.step = function() {}; + var + _ts , _wasts, _req, + _framerate = 16.6, + + _id = id, + + /** + * Holds refereneces of the all animations added to this scene. + * @private + */ + _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. + * @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) + * @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 + * @public + */ + this.active = false; + + /** + * Holds refereneces of complete time span for this scene. + * @private + */ + this.span = 0; + + + /** + * @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(); + } + } + + this.ready = function () { + if (this.animating) { + if (!this.active) { + director.roll(this); + } + return this.active; + } + return false; + }; + + /** + * @private + */ + this.cancel= function () { + animation.cancelRequestAnimationFrame(_req); + }; + + + /** + * @public + */ + this.trigger = function (force) { + if (force || !this.animating) { + _req = animation.requestAnimationFrame(utils.bindSafely(this, loop)); + } + }; + + /** + * Gets the unique ID assigned to this sceen + * @public + */ + this.getID = function () { + return _id; + }; + + /** + * Returns the life span/duration of this sceen. + * @public + */ + this.totalSpan = function() { + return this.span; + }; + + /** + * Adds new animation on already existing animation for this character. + * @public + */ + this.addAnimation = function(newProp, span) { + if (_prevDur === 0 && span === 0) { + _poses[0] = { + animate: newProp, + span: 0 + }; + } else { + _prevDur = span || _prevDur; + this.span += _prevDur; + _poses.push({ + animate: newProp, + span: this.span + }); + } + }; + + /** + * Returns animation pose index from the list of + * animations added to this scene for a particular + * instance of time. + * @private + */ + 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; + }; + + 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. + * @public + */ + this.getAnimation = function(index) { + return index < 0 || _poses[index]; + }; + + /** + * Sets new animation for this character. + * @public + */ + this.setAnimation = function(newProp) { + this._prop = newProp; + }; + + + //TODO: Move these events to Event Delegator + /** + * Event to identify when the scene has done animating. + * @public + */ + this.completed = function() {}; + + /** + * Event to identify when the scene has done animating. + * @public + */ + this.step = function() {}; + + /** + * Event to identify when the actor has done animating. + * @public + */ + this.actorCompleted= function(actor) {}; +}; + + +var SceneAction = { + action: function (ts, pose) { + var past, + actors, + l, i, + tm = this.rolePlay(ts), + index = this.animateAtTime(tm); + + if(index < 0) { + return; + } + pose = 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()]; + l = actors.length; + for (i = 0; i < l; i++) { + director.action(pose, + actors[i], + tm - past, + pose.span - past); + } + } + 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..70d6a94c0 --- /dev/null +++ b/src/AnimationSupport/SceneActor.js @@ -0,0 +1,48 @@ +var + Scene = require('./Scene'), + director = require('./Director'), + utils = require('../utils'); + +var CharacterAction = { + action: function (ts, pose) { + var i, actor, tm, past, index, + dur = this.span, + actors = this.rolePlays[this.getID()], + l = actors.length; + + for (i = 0; i < l; i++) { + actor = actors[i]; + if (actor.generated) { + if (!actor._frameSpeed) { + actor._frameSpeed = this._frameSpeed; + } + tm = this.rolePlay(ts, actor); + if (isNaN(tm) || tm < 0) continue; + if (tm > dur) { + actor.timeline = dur; + } + index = this.animateAtTime(tm); + pose = pose || this.getAnimation(index); + past = index ? this.getAnimation(index - 1).span : 0; + director.action(pose, actor, tm - past, pose.span - past); + + if(actor.timeline === dur) { + this.actorCompleted && this.actorCompleted(actor); + } + } + } + + //TODO: return list of actors working in this sceen + return pose; + } +}; + +/** + * Scene is used to generate animation structure. + * @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 index 0a9ae54df..d2db7ca5e 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -22,8 +22,12 @@ module.exports = { play: function (actor) { actor = actor || this; actor._frameSpeed = 1; - this.animating = true; actor._startTime = (actor.delay || 0); + if (isNaN(actor.timeline) || !actor.timeline) { + actor.timeline = 0; + } + this.trigger(); + this.animating = true; }, resume: function(actor) { @@ -61,12 +65,21 @@ module.exports = { actor._cachedValue = 1; actor._frameSpeed = 0; actor.timeline = 0; + this.animating = false; + this.cancel(); }, rolePlay: function (t, actor) { actor = actor || this; - if (!actor.timeline || actor.timeline < 0) actor.timeline = 0; - actor.timeline += _rolePlay(t, actor._frameSpeed); + if (actor.timeline === undefined || actor.timeline < 0) + actor.timeline = 0; + + if(actor.delay > 0) { + console.log(actor.name, actor.delay); + actor.delay -= _rolePlay(t, actor._frameSpeed); + } else { + actor.timeline += _rolePlay(t, actor._frameSpeed); + } return actor.timeline; } }; diff --git a/src/AnimationSupport/SceneEvent.js b/src/AnimationSupport/SceneEvent.js new file mode 100644 index 000000000..2a9194c95 --- /dev/null +++ b/src/AnimationSupport/SceneEvent.js @@ -0,0 +1,104 @@ +var + Scene = require('./Scene'), + director = require('./Director'), + delegator = require('./EventDelegator'), + utils = require('../utils'); + +var + /** + * 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 = { + + /** + * 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) { + _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; + }, + + /** + * Gets the delta values of x, y and z for events + * @public + */ + getAnimationDelta: function() { + return _eventCache[_triggerer]; + }, + + /** + * Trigger the registered event to all the listeners + * @public + */ + triggerEvent: function() { + _isTriggered = false; + return delegator.emitEvent(this, this.getAnimationDelta()); + }, + + /** + * Activates handles for generated actors + * @public + */ + register: function (actor) { + if (this.handlers) { + delegator.register(actor, this.handlers); + } + }, + + action: function (ts, pose) { + if (_isTriggered && this.getAnimationDelta()) { + if (!this.triggerEvent()) { + director.shot(this, ts); + } + } + return pose; + } +}; + + +/** + * Registers an actor/s from a scene. + * (Actors could be delinked during the animation + * however they will current their state when delinked) + */ +Scene.register = function(actor, scene) { + delegator.register(scene, actors); +}; + + +/** + * Scene is used to generate animation structure. + * @module enyo/AnimationSupport/SceneEvent + */ +module.exports = function(props) { + var scene = Scene(props); + utils.mixin(scene, EventAction); + return scene; +}; + diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 757793500..56ef4dee3 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -25,7 +25,7 @@ module.exports = { var k, fn, state, ease, points, path; node = actor.node; - state = actor.currentState = actor.currentState || {}; + 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; @@ -85,6 +85,7 @@ module.exports = { ); frame.accelerate(node, matrix); state.matrix = matrix; + pose.currentState = state; }, From 3507b4b66eb4936cfbb3cdfaf704b82b9a85a1fe Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Thu, 28 Jan 2016 22:36:42 +0530 Subject: [PATCH 08/22] Smart event changes Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Director.js | 8 +- src/AnimationSupport/EventDelegator.js | 207 ------------------------- src/AnimationSupport/Scene.js | 3 +- src/AnimationSupport/SceneEvent.js | 184 +++++++++++++++++++--- 4 files changed, 168 insertions(+), 234 deletions(-) delete mode 100644 src/AnimationSupport/EventDelegator.js diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index 506014a9c..2f2ab20f6 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -105,9 +105,9 @@ module.exports = { }, shot: function(actor, ts) { - var v1, s, a, v, + var v1, s, a, v = 0, t = ts, - dt = actor._eventCache, + dt = actor.getAnimationDelta(), dir = this.angle(actor.direction), v0 = dt.velocity || 0; @@ -124,8 +124,8 @@ module.exports = { dt[dir] = 0; } dt.velocity = v1; - this.take(actor, dt[dir] > 0 ? v : -v); - } + } + return dt[dir] > 0 ? v : -v; }, angle: function (direction) { diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js deleted file mode 100644 index 349f839cc..000000000 --- a/src/AnimationSupport/EventDelegator.js +++ /dev/null @@ -1,207 +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 = { - - /** - * 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, events) { - events = events || {}; - 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, events) { - events = events || {}; - 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); - } -}; - -module.exports = EventDelegator; \ No newline at end of file diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index f240a23e5..5f861bdd3 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -36,7 +36,7 @@ var Scene = module.exports = function(props) { * (To used for runtime creation of animations) */ Scene.create = function() { - return new sceneConstructor("@"+ utils.perfNow()); + return new sceneConstructor(utils.uid("@")); }; @@ -288,6 +288,7 @@ var SceneAction = { actors[i], tm - past, pose.span - past); + } } return pose; diff --git a/src/AnimationSupport/SceneEvent.js b/src/AnimationSupport/SceneEvent.js index 2a9194c95..4b57d248c 100644 --- a/src/AnimationSupport/SceneEvent.js +++ b/src/AnimationSupport/SceneEvent.js @@ -1,10 +1,155 @@ var Scene = require('./Scene'), director = require('./Director'), - delegator = require('./EventDelegator'), + dispatcher = require('../dispatcher'), + emitter = require('../EventEmitter'), utils = require('../utils'); -var +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 = { + + /** + * 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. @@ -25,10 +170,10 @@ var * @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 @@ -49,7 +194,7 @@ var EventAction = { * @public */ getAnimationDelta: function() { - return _eventCache[_triggerer]; + return _eventCache; }, /** @@ -58,7 +203,7 @@ var EventAction = { */ triggerEvent: function() { _isTriggered = false; - return delegator.emitEvent(this, this.getAnimationDelta()); + EventDelegator.emitEvent(this, _triggerer); }, /** @@ -67,14 +212,19 @@ var EventAction = { */ register: function (actor) { if (this.handlers) { - delegator.register(actor, this.handlers); + this.eventOriginator = actor; + EventDelegator.register(this, actor); } }, action: function (ts, pose) { - if (_isTriggered && this.getAnimationDelta()) { - if (!this.triggerEvent()) { - director.shot(this, ts); + 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; @@ -82,23 +232,13 @@ var EventAction = { }; -/** - * Registers an actor/s from a scene. - * (Actors could be delinked during the animation - * however they will current their state when delinked) - */ -Scene.register = function(actor, scene) { - delegator.register(scene, actors); -}; - - /** * Scene is used to generate animation structure. * @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 From fa5f469e2d5ccbc743299868767923371c029a08 Mon Sep 17 00:00:00 2001 From: Madala Cholan Satyanarayana Date: Fri, 29 Jan 2016 20:54:16 +0530 Subject: [PATCH 09/22] Seek feature applied Enyo-DCO-1.1-Signed-off-by:Madala Satyanarayana --- src/AnimationSupport/Director.js | 1 - src/AnimationSupport/EventDelegator.js | 206 ++++++++++ src/AnimationSupport/Scene.js | 498 ++++++++++++------------- src/AnimationSupport/SceneActor.js | 2 + src/AnimationSupport/SceneEditor.js | 151 ++++---- 5 files changed, 536 insertions(+), 322 deletions(-) create mode 100644 src/AnimationSupport/EventDelegator.js diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index 2f2ab20f6..678ac1713 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -41,7 +41,6 @@ module.exports = { if (tm <= dur) { pose = scene.action(ts, pose); //TODO: Use Event Delegator to emit this event. - scene.step && scene.step(pose); } else { scene.timeline = dur; scene.animating = false; diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js new file mode 100644 index 000000000..09d9281c7 --- /dev/null +++ b/src/AnimationSupport/EventDelegator.js @@ -0,0 +1,206 @@ +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 = { + + /** + * 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, events) { + events = events || {}; + 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, events) { + events = events || {}; + 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]; + + + 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); + } +}; + +module.exports = EventDelegator; diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 5f861bdd3..1b189d61d 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -1,33 +1,33 @@ var - editor = require('./SceneEditor'), - director = require('./Director'), - animation = require('../animation'), - utils = require('../utils'); + editor = require('./SceneEditor'), + director = require('./Director'), + animation = require('../animation'), + utils = require('../utils'); /** * Scene is used to generate animation structure. * @module enyo/AnimationSupport/Scene */ var Scene = module.exports = function(props) { - var scene = Scene.create(), - dur = props.duration || 0; + var scene = Scene.create(), + dur = props.duration || 0; - utils.mixin(scene, editor); + utils.mixin(scene, editor); - if (props.animation) { - var anims = utils.isArray(props.animation) ? props.animation : [props.animation]; + 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); - delete anims[i].duration; - } - delete props.animation; - delete props.duration; - } + for (var i = 0; i < anims.length; i++) { + scene.addAnimation(anims[i], anims[i].span || anims[i].duration || dur); + delete anims[i].duration; + } + delete props.animation; + delete props.duration; + } - utils.mixin(scene, props); - utils.mixin(scene, SceneAction); - return scene; + utils.mixin(scene, props); + utils.mixin(scene, SceneAction); + return scene; }; @@ -46,7 +46,7 @@ Scene.create = function() { * otherwise actors will animate for remaining time span) */ Scene.link = function(actors, scene) { - director.cast(actors, scene); + director.cast(actors, scene); }; @@ -56,241 +56,241 @@ Scene.link = function(actors, scene) { * however they will current their state when delinked) */ Scene.delink = function(actors, scene) { - director.reject(scene, actors); + director.reject(scene, actors); }; var sceneConstructor = function(id) { - var - _ts , _wasts, _req, - _framerate = 16.6, - - _id = id, - - /** - * Holds refereneces of the all animations added to this scene. - * @private - */ - _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. - * @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) - * @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 - * @public - */ - this.active = false; - - /** - * Holds refereneces of complete time span for this scene. - * @private - */ - this.span = 0; - - - /** - * @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(); - } - } - - this.ready = function () { - if (this.animating) { - if (!this.active) { - director.roll(this); - } - return this.active; - } - return false; - }; - - /** - * @private - */ - this.cancel= function () { - animation.cancelRequestAnimationFrame(_req); - }; - - - /** - * @public - */ - this.trigger = function (force) { - if (force || !this.animating) { - _req = animation.requestAnimationFrame(utils.bindSafely(this, loop)); - } - }; - - /** - * Gets the unique ID assigned to this sceen - * @public - */ - this.getID = function () { - return _id; - }; - - /** - * Returns the life span/duration of this sceen. - * @public - */ - this.totalSpan = function() { - return this.span; - }; - - /** - * Adds new animation on already existing animation for this character. - * @public - */ - this.addAnimation = function(newProp, span) { - if (_prevDur === 0 && span === 0) { - _poses[0] = { - animate: newProp, - span: 0 - }; - } else { - _prevDur = span || _prevDur; - this.span += _prevDur; - _poses.push({ - animate: newProp, - span: this.span - }); - } - }; - - /** - * Returns animation pose index from the list of - * animations added to this scene for a particular - * instance of time. - * @private - */ - 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; - }; - - 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. - * @public - */ - this.getAnimation = function(index) { - return index < 0 || _poses[index]; - }; - - /** - * Sets new animation for this character. - * @public - */ - this.setAnimation = function(newProp) { - this._prop = newProp; - }; - - - //TODO: Move these events to Event Delegator - /** - * Event to identify when the scene has done animating. - * @public - */ - this.completed = function() {}; - - /** - * Event to identify when the scene has done animating. - * @public - */ - this.step = function() {}; - - /** - * Event to identify when the actor has done animating. - * @public - */ - this.actorCompleted= function(actor) {}; + var + _ts, _wasts, _req, + _framerate = 16.6, + + _id = id, + + /** + * Holds refereneces of the all animations added to this scene. + * @private + */ + _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. + * @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) + * @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 + * @public + */ + this.active = false; + + /** + * Holds refereneces of complete time span for this scene. + * @private + */ + this.span = 0; + + + /** + * @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(); + } + } + + this.ready = function() { + if (this.animating) { + if (!this.active) { + director.roll(this); + } + return this.active; + } + return false; + }; + + /** + * @private + */ + this.cancel = function() { + animation.cancelRequestAnimationFrame(_req); + }; + + + /** + * @public + */ + this.trigger = function(force) { + if (force || !this.animating) { + _req = animation.requestAnimationFrame(utils.bindSafely(this, loop)); + } + }; + + /** + * Gets the unique ID assigned to this sceen + * @public + */ + this.getID = function() { + return _id; + }; + + /** + * Returns the life span/duration of this sceen. + * @public + */ + this.totalSpan = function() { + return this.span; + }; + + /** + * Adds new animation on already existing animation for this character. + * @public + */ + this.addAnimation = function(newProp, span) { + if (_prevDur === 0 && span === 0) { + _poses[0] = { + animate: newProp, + span: 0 + }; + } else { + _prevDur = span || _prevDur; + this.span += _prevDur; + _poses.push({ + animate: newProp, + span: this.span + }); + } + }; + + /** + * Returns animation pose index from the list of + * animations added to this scene for a particular + * instance of time. + * @private + */ + 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; + }; + + 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. + * @public + */ + this.getAnimation = function(index) { + return index < 0 || _poses[index]; + }; + + /** + * Sets new animation for this character. + * @public + */ + this.setAnimation = function(newProp) { + this._prop = newProp; + }; + + + //TODO: Move these events to Event Delegator + /** + * Event to identify when the scene has done animating. + * @public + */ + this.completed = function() {}; + + /** + * Event to identify when the scene has done animating. + * @public + */ + this.step = function() {}; + + /** + * Event to identify when the actor has done animating. + * @public + */ + this.actorCompleted = function(actor) {}; }; var SceneAction = { - action: function (ts, pose) { - var past, - actors, - l, i, - tm = this.rolePlay(ts), - index = this.animateAtTime(tm); - - if(index < 0) { - return; - } - pose = 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()]; - l = actors.length; - for (i = 0; i < l; i++) { - director.action(pose, - actors[i], - tm - past, - pose.span - past); - - } - } - return pose; - } + action: function(ts, pose) { + var past, + actors, + l, i, + tm = this.rolePlay(ts), + index = this.animateAtTime(tm); + + if (index < 0) { + return; + } + pose = 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()]; + l = actors.length; + for (i = 0; i < l; i++) { + director.action(pose, + actors[i], + tm - past, + pose.span - past); + this.step && this.step(actors[i]); + } + } + return pose; + } }; \ No newline at end of file diff --git a/src/AnimationSupport/SceneActor.js b/src/AnimationSupport/SceneActor.js index 70d6a94c0..1f526d3c5 100644 --- a/src/AnimationSupport/SceneActor.js +++ b/src/AnimationSupport/SceneActor.js @@ -26,6 +26,8 @@ var CharacterAction = { past = index ? this.getAnimation(index - 1).span : 0; director.action(pose, actor, tm - past, pose.span - past); + this.step && this.step(actor); + if(actor.timeline === dur) { this.actorCompleted && this.actorCompleted(actor); } diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js index d2db7ca5e..4b3e6c806 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -1,89 +1,96 @@ require('enyo'); /** -* This modules exposes API's for controlling animations. -* @private -*/ + * This modules exposes API's for controlling animations. + * @private + */ module.exports = { - timeline: 0, - _cachedValue: 0, - _frameSpeed: 0, - _startTime: 0, + timeline: 0, + _cachedValue: 0, + _frameSpeed: 0, + _startTime: 0, - cache: function(actor) { - actor = actor || this; - if(actor._frameSpeed === 0){ - actor._frameSpeed = actor._cachedValue; - } - this.animating = true; - }, - - play: function (actor) { - actor = actor || this; - actor._frameSpeed = 1; - actor._startTime = (actor.delay || 0); - if (isNaN(actor.timeline) || !actor.timeline) { - actor.timeline = 0; - } - this.trigger(); - this.animating = true; - }, + cache: function(actor) { + actor = actor || this; + if (actor._frameSpeed === 0) { + actor._frameSpeed = actor._cachedValue; + } + this.animating = true; + }, - resume: function(actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= 1; - }, + play: function(actor) { + actor = actor || this; + actor._frameSpeed = 1; + actor._startTime = (actor.delay || 0); + if (isNaN(actor.timeline) || !actor.timeline) { + actor.timeline = 0; + } + this.trigger(); + this.animating = true; + }, - pause: function (actor) { - actor = actor || this; - actor._cachedValue = actor._frameSpeed; - actor._frameSpeed = 0; - }, + resume: function(actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= 1; + }, - reverse: function (actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= -1; - }, + pause: function(actor) { + actor = actor || this; + actor._cachedValue = actor._frameSpeed; + actor._frameSpeed = 0; + }, - fast: function (mul, actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= mul; - }, + reverse: function(actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= -1; + }, - slow: function (mul, actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= mul; - }, + fast: function(mul, actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= mul; + }, - stop: function (actor) { - actor = actor || this; - actor._cachedValue = 1; - actor._frameSpeed = 0; - actor.timeline = 0; - this.animating = false; - this.cancel(); - }, + slow: function(mul, actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= mul; + }, - rolePlay: function (t, actor) { - actor = actor || this; - if (actor.timeline === undefined || actor.timeline < 0) - actor.timeline = 0; - - if(actor.delay > 0) { - console.log(actor.name, actor.delay); - actor.delay -= _rolePlay(t, actor._frameSpeed); - } else { - actor.timeline += _rolePlay(t, actor._frameSpeed); - } - return actor.timeline; - } + stop: function(actor) { + actor = actor || this; + actor._cachedValue = 1; + actor._frameSpeed = 0; + actor.timeline = 0; + this.animating = false; + this.cancel(); + }, + seek: function(timeline, actor) { + actor = actor || this; + if (this.animating !== true) { + this.play(actor); + this.pause(actor); + } + actor.timeline = timeline; + }, + + 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; + } }; function _rolePlay(t, mul) { - return mul * t; + return mul * t; } \ No newline at end of file From 2393ac0486cb92eeca1622215ef69fa3b20877ec Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Wed, 3 Feb 2016 12:55:51 +0530 Subject: [PATCH 10/22] some issue fixes related to -Scene not reinitialized when played again. -Calculating all poses initially. Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Director.js | 26 +- src/AnimationSupport/Frame.js | 8 +- src/AnimationSupport/Scene.js | 500 ++++++++++++++-------------- src/AnimationSupport/SceneActor.js | 5 +- src/AnimationSupport/SceneEditor.js | 143 ++++---- src/AnimationSupport/Tween.js | 3 +- 6 files changed, 352 insertions(+), 333 deletions(-) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index 678ac1713..c6b9db884 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -20,8 +20,8 @@ module.exports = { for (var i = 0; i < l; i++) { actor = actors[i]; - if(actor.generated && !actor._initialPose) { - this.firstShot(actor); + if(actor.generated) { + this.firstShot(scene, actor); active = false; } } @@ -66,7 +66,7 @@ module.exports = { cast: function (actors, scene) { var acts = utils.isArray(actors) ? actors : [actors], id = scene.getID(), - rolePlays = scene.rolePlays || []; + rolePlays = scene.rolePlays || {}; if (!rolePlays[id]) { rolePlays[id] = acts; @@ -94,13 +94,23 @@ module.exports = { scene.rolePlays = rolePlays; }, - firstShot: function (actor) { + firstShot: function (scene, actor) { var dom = actor.hasNode(), - pose = frame.getComputedProperty(dom, undefined); - pose.span = 0; - actor._initialPose = pose; - actor.currentState = pose.currentState; + l = scene.length(), + oldPose = frame.getComputedProperty(dom, undefined), + pose; + oldPose.span = 0; + actor._initialPose = oldPose; + actor.currentState = oldPose.currentState; // frame.accelerate(dom, pose.matrix); + + + for(var i=0; i < l; i++) { + pose = scene.getAnimation(i); + utils.mixin(pose, frame.getComputedProperty(actor.hasNode(), pose.animate, oldPose._endAnim)); + scene.setAnimation(i, pose); + oldPose = pose; + } }, shot: function(actor, ts) { diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js index 2393d0f77..b0b9f780c 100644 --- a/src/AnimationSupport/Frame.js +++ b/src/AnimationSupport/Frame.js @@ -3,6 +3,7 @@ require('enyo'); var Dom = require('../dom'), Vector = require('./Vector'), + utils = require('../utils'), Matrix = require('./Matrix'); var @@ -282,7 +283,8 @@ var frame = module.exports = { } else { val = val[0] + 'px'; } - ele.style[prop] = val; + if(ele) + ele.style[prop] = val; }, /** @@ -309,7 +311,7 @@ var frame = module.exports = { if(!node) return; var eP = {}, - sP = initial ? this.copy(initial) : {}, + sP = initial ? utils.mixin({}, initial) : {}, tP = {}, dP = {}, m, k, v, @@ -330,7 +332,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; diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 1b189d61d..872177450 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -1,33 +1,33 @@ var - editor = require('./SceneEditor'), - director = require('./Director'), - animation = require('../animation'), - utils = require('../utils'); + editor = require('./SceneEditor'), + director = require('./Director'), + animation = require('../animation'), + utils = require('../utils'); /** * Scene is used to generate animation structure. * @module enyo/AnimationSupport/Scene */ var Scene = module.exports = function(props) { - var scene = Scene.create(), - dur = props.duration || 0; + var scene = Scene.create(), + dur = props.duration || 0; - utils.mixin(scene, editor); + utils.mixin(scene, editor); - if (props.animation) { - var anims = utils.isArray(props.animation) ? props.animation : [props.animation]; + 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); - delete anims[i].duration; - } - delete props.animation; - delete props.duration; - } + for (var i = 0; i < anims.length; i++) { + scene.addAnimation(anims[i], anims[i].span || anims[i].duration || dur); + delete anims[i].duration; + } + delete props.animation; + delete props.duration; + } - utils.mixin(scene, props); - utils.mixin(scene, SceneAction); - return scene; + utils.mixin(scene, props); + utils.mixin(scene, SceneAction); + return scene; }; @@ -46,7 +46,7 @@ Scene.create = function() { * otherwise actors will animate for remaining time span) */ Scene.link = function(actors, scene) { - director.cast(actors, scene); + director.cast(actors, scene); }; @@ -56,241 +56,245 @@ Scene.link = function(actors, scene) { * however they will current their state when delinked) */ Scene.delink = function(actors, scene) { - director.reject(scene, actors); + director.reject(scene, actors); }; var sceneConstructor = function(id) { - var - _ts, _wasts, _req, - _framerate = 16.6, - - _id = id, - - /** - * Holds refereneces of the all animations added to this scene. - * @private - */ - _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. - * @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) - * @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 - * @public - */ - this.active = false; - - /** - * Holds refereneces of complete time span for this scene. - * @private - */ - this.span = 0; - - - /** - * @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(); - } - } - - this.ready = function() { - if (this.animating) { - if (!this.active) { - director.roll(this); - } - return this.active; - } - return false; - }; - - /** - * @private - */ - this.cancel = function() { - animation.cancelRequestAnimationFrame(_req); - }; - - - /** - * @public - */ - this.trigger = function(force) { - if (force || !this.animating) { - _req = animation.requestAnimationFrame(utils.bindSafely(this, loop)); - } - }; - - /** - * Gets the unique ID assigned to this sceen - * @public - */ - this.getID = function() { - return _id; - }; - - /** - * Returns the life span/duration of this sceen. - * @public - */ - this.totalSpan = function() { - return this.span; - }; - - /** - * Adds new animation on already existing animation for this character. - * @public - */ - this.addAnimation = function(newProp, span) { - if (_prevDur === 0 && span === 0) { - _poses[0] = { - animate: newProp, - span: 0 - }; - } else { - _prevDur = span || _prevDur; - this.span += _prevDur; - _poses.push({ - animate: newProp, - span: this.span - }); - } - }; - - /** - * Returns animation pose index from the list of - * animations added to this scene for a particular - * instance of time. - * @private - */ - 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; - }; - - 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. - * @public - */ - this.getAnimation = function(index) { - return index < 0 || _poses[index]; - }; - - /** - * Sets new animation for this character. - * @public - */ - this.setAnimation = function(newProp) { - this._prop = newProp; - }; - - - //TODO: Move these events to Event Delegator - /** - * Event to identify when the scene has done animating. - * @public - */ - this.completed = function() {}; - - /** - * Event to identify when the scene has done animating. - * @public - */ - this.step = function() {}; - - /** - * Event to identify when the actor has done animating. - * @public - */ - this.actorCompleted = function(actor) {}; + var + _ts , _wasts, _req, + _framerate = 16.6, + + _id = id, + + /** + * Holds refereneces of the all animations added to this scene. + * @private + */ + _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. + * @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) + * @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 + * @public + */ + this.active = false; + + /** + * Holds refereneces of complete time span for this scene. + * @private + */ + this.span = 0; + + + /** + * @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(); + } + } + + this.ready = function () { + if (this.animating) { + if (!this.active) { + director.roll(this); + } + return this.active; + } + return false; + }; + + /** + * @private + */ + this.cancel= function () { + animation.cancelRequestAnimationFrame(_req); + }; + + + /** + * @public + */ + this.trigger = function (force) { + if (force || !this.animating) { + _req = animation.requestAnimationFrame(utils.bindSafely(this, loop)); + } + }; + + /** + * Gets the unique ID assigned to this sceen + * @public + */ + this.getID = function () { + return _id; + }; + + /** + * Returns the life span/duration of this sceen. + * @public + */ + this.totalSpan = function() { + return this.span; + }; + + /** + * Adds new animation on already existing animation for this character. + * @public + */ + this.addAnimation = function(newProp, span) { + if (_prevDur === 0 && span === 0) { + _poses[0] = { + animate: newProp, + span: 0 + }; + } else { + _prevDur = span || _prevDur; + this.span += _prevDur; + _poses.push({ + animate: newProp, + span: this.span + }); + } + }; + + this.length = function() { + return _poses.length; + }; + + /** + * Returns animation pose index from the list of + * animations added to this scene for a particular + * instance of time. + * @private + */ + 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; + }; + + 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. + * @public + */ + this.getAnimation = function(index) { + return index < 0 || _poses[index]; + }; + + /** + * Sets new animation for this character. + * @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. + * @public + */ + this.completed = function() {}; + + /** + * Event to identify when the scene has done animating. + * @public + */ + this.step = function() {}; + + /** + * Event to identify when the actor has done animating. + * @public + */ + this.actorCompleted= function(actor) {}; }; var SceneAction = { - action: function(ts, pose) { - var past, - actors, - l, i, - tm = this.rolePlay(ts), - index = this.animateAtTime(tm); - - if (index < 0) { - return; - } - pose = 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()]; - l = actors.length; - for (i = 0; i < l; i++) { - director.action(pose, - actors[i], - tm - past, - pose.span - past); + action: function (ts, pose) { + var past, + actors, + l, i, + tm = this.rolePlay(ts), + index = this.animateAtTime(tm); + + if(index < 0) { + return; + } + pose = 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()]; + l = actors.length; + for (i = 0; i < l; i++) { + director.action(pose, + actors[i], + tm - past, + pose.span - past); this.step && this.step(actors[i]); - } - } - return pose; - } + } + } + return pose; + } }; \ No newline at end of file diff --git a/src/AnimationSupport/SceneActor.js b/src/AnimationSupport/SceneActor.js index 1f526d3c5..5991158ac 100644 --- a/src/AnimationSupport/SceneActor.js +++ b/src/AnimationSupport/SceneActor.js @@ -16,13 +16,14 @@ var CharacterAction = { if (!actor._frameSpeed) { actor._frameSpeed = this._frameSpeed; } - tm = this.rolePlay(ts, actor); + + tm = this.rolePlay(ts, actor); if (isNaN(tm) || tm < 0) continue; if (tm > dur) { actor.timeline = dur; } index = this.animateAtTime(tm); - pose = pose || this.getAnimation(index); + pose = this.getAnimation(index); past = index ? this.getAnimation(index - 1).span : 0; director.action(pose, actor, tm - past, pose.span - past); diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js index 4b3e6c806..42d4e99db 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -1,73 +1,73 @@ require('enyo'); /** - * This modules exposes API's for controlling animations. - * @private - */ +* This modules exposes API's for controlling animations. +* @private +*/ module.exports = { - timeline: 0, - _cachedValue: 0, - _frameSpeed: 0, - _startTime: 0, + timeline: 0, + _cachedValue: 0, + _frameSpeed: 0, + _startTime: 0, - cache: function(actor) { - actor = actor || this; - if (actor._frameSpeed === 0) { - actor._frameSpeed = actor._cachedValue; - } - this.animating = true; - }, + cache: function(actor) { + actor = actor || this; + if(actor._frameSpeed === 0){ + actor._frameSpeed = actor._cachedValue; + } + this.animating = true; + }, + + play: function (actor) { + actor = actor || this; + actor._frameSpeed = 1; + actor._startTime = (actor.delay || 0); + if (isNaN(actor.timeline) || !actor.timeline) { + actor.timeline = 0; + } + this.trigger(); + this.animating = true; + }, - play: function(actor) { - actor = actor || this; - actor._frameSpeed = 1; - actor._startTime = (actor.delay || 0); - if (isNaN(actor.timeline) || !actor.timeline) { - actor.timeline = 0; - } - this.trigger(); - this.animating = true; - }, + resume: function(actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= 1; + }, - resume: function(actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= 1; - }, - - pause: function(actor) { - actor = actor || this; - actor._cachedValue = actor._frameSpeed; - actor._frameSpeed = 0; - }, + pause: function (actor) { + actor = actor || this; + actor._cachedValue = actor._frameSpeed; + actor._frameSpeed = 0; + }, - reverse: function(actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= -1; - }, + reverse: function (actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= -1; + }, - fast: function(mul, actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= mul; - }, + fast: function (mul, actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= mul; + }, - slow: function(mul, actor) { - this.cache(actor); - actor = actor || this; - actor._frameSpeed *= mul; - }, + slow: function (mul, actor) { + this.cache(actor); + actor = actor || this; + actor._frameSpeed *= mul; + }, - stop: function(actor) { - actor = actor || this; - actor._cachedValue = 1; - actor._frameSpeed = 0; - actor.timeline = 0; - this.animating = false; - this.cancel(); - }, + stop: function (actor) { + actor = actor || this; + actor._cachedValue = 1; + actor._frameSpeed = 0; + actor.timeline = 0; + this.animating = false; + this.cancel(); + }, seek: function(timeline, actor) { actor = actor || this; if (this.animating !== true) { @@ -77,20 +77,21 @@ module.exports = { actor.timeline = timeline; }, - 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; - } + rolePlay: function (t, actor) { + actor = actor || this; + if (actor.timeline === undefined || actor.timeline < 0) + actor.timeline = 0; + + if(actor.delay > 0) { + console.log(actor.name, actor.delay); + actor.delay -= _rolePlay(t, actor._frameSpeed); + } else { + actor.timeline += _rolePlay(t, actor._frameSpeed); + } + return actor.timeline; + } }; function _rolePlay(t, mul) { - return mul * t; + return mul * t; } \ No newline at end of file diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 56ef4dee3..00e4ac90b 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -24,7 +24,7 @@ module.exports = { step: function(actor, pose, t, d) { var k, fn, state, ease, points, path; - node = actor.node; + 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; @@ -63,6 +63,7 @@ module.exports = { } if (!frame.isTransform(k)) { + frame.setProperty(node, k, cState); } state[k] = cState; From 482b4a3831a99837c239723f18267641a660d80c Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Thu, 4 Feb 2016 16:50:24 +0530 Subject: [PATCH 11/22] Added JSdocs for Matrix.js and Frame.js Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Frame.js | 166 ++++++++++++++++++++------------- src/AnimationSupport/Matrix.js | 122 +++++++++++++++++------- 2 files changed, 187 insertions(+), 101 deletions(-) diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js index b0b9f780c..6636e0d36 100644 --- a/src/AnimationSupport/Frame.js +++ b/src/AnimationSupport/Frame.js @@ -1,3 +1,4 @@ +/*jslint white: true*/ require('enyo'); var @@ -7,29 +8,31 @@ var 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}; + 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}; /** -* 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) { + "use strict"; var i, x = rot[0], y = rot[1], @@ -92,13 +95,14 @@ 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) { + "use strict"; var i, tV = [], rV = [], @@ -136,7 +140,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]); @@ -176,34 +180,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 - */ + * Applies transformation to DOM element with the Matrix3d values. + * @public + * @param {HTMLElement} ele Element which is going to animate. + * @param {Number[]} m Matrix3d + */ accelerate: function (ele, m) { m = m ? m : Matrix.identity(); frame.setTransformProperty(ele, 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(')', ''); @@ -222,9 +235,11 @@ 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); @@ -232,9 +247,11 @@ var frame = module.exports = { }, /** - * 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') || @@ -248,11 +265,12 @@ 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") { @@ -268,11 +286,13 @@ var frame = module.exports = { return v; }, - /** - * Applies style property to DOM element. - * @public - */ + * Applies style property to DOM element. + * @public + * @param {HTMLElement} ele DOM element to be animated. + * @param {String} prop CSS property to be applied. + * @param {Number} val Value of the property applied. + */ setProperty: function (ele, prop, val) { if (COLOR[prop]) { val = val.map(function(v) { return parseInt(v, 10);}); @@ -283,14 +303,17 @@ var frame = module.exports = { } else { val = val[0] + 'px'; } - if(ele) + if (ele) { ele.style[prop] = val; + } }, /** - * Applies transform property to DOM element. - * @public - */ + * Applies transform property to DOM element. + * @public + * @param {HTMLElement} element HTML element which is going to animate. + * @param {Number[]} matrix Matrix3d + */ setTransformProperty: function (element, matrix) { var mat = Matrix.toString(matrix); element.style.transform = mat; @@ -301,12 +324,13 @@ var frame = module.exports = { }, /** - * 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; @@ -348,10 +372,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/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++) { From ef168b4f9092f3722e6b0d001bfde2cd1340abf3 Mon Sep 17 00:00:00 2001 From: Madala Cholan Satyanarayana Date: Fri, 5 Feb 2016 12:19:18 +0530 Subject: [PATCH 12/22] Documentation of Easings and Scene API's Enyo-DCO-1.1-Signed-off-by:Madala Satyanarayana --- src/AnimationSupport/Easings.js | 257 +++++++++++--- src/AnimationSupport/Scene.js | 605 ++++++++++++++++++-------------- 2 files changed, 547 insertions(+), 315 deletions(-) diff --git a/src/AnimationSupport/Easings.js b/src/AnimationSupport/Easings.js index c40289695..8ec19ab99 100644 --- a/src/AnimationSupport/Easings.js +++ b/src/AnimationSupport/Easings.js @@ -1,24 +1,32 @@ /** - * Interface to achieve Easings in various animations - * - * @module enyo/AnimationSupport/Easings - * @public + * Beginning time + * @type {number} */ - var b = 0, + /** + * 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 @@ -35,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) { @@ -56,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 @@ -79,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 @@ -102,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,8 +148,11 @@ var easings = { }, /** + * 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); @@ -157,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), @@ -174,7 +195,7 @@ var easings = { var c, values = [], - + x = (1 - t), y = t; // @@ -188,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); @@ -344,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, @@ -387,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, @@ -405,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, @@ -424,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); @@ -452,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); @@ -476,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); @@ -487,4 +633,3 @@ var easings = { } }; -module.exports = easings; diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 872177450..5ca4eec1a 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -1,300 +1,387 @@ var - editor = require('./SceneEditor'), - director = require('./Director'), - animation = require('../animation'), - utils = require('../utils'); + editor = require('./SceneEditor'), + director = require('./Director'), + animation = require('../animation'), + utils = require('../utils'); /** - * Scene is used to generate animation structure. + * 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; + var scene = Scene.create(), + dur = props.duration || 0; - utils.mixin(scene, editor); + utils.mixin(scene, editor); - if (props.animation) { - var anims = utils.isArray(props.animation) ? props.animation : [props.animation]; + 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); - delete anims[i].duration; - } - delete props.animation; - delete props.duration; - } + for (var i = 0; i < anims.length; i++) { + scene.addAnimation(anims[i], anims[i].span || anims[i].duration || dur); + delete anims[i].duration; + } + delete props.animation; + delete props.duration; + } - utils.mixin(scene, props); - utils.mixin(scene, SceneAction); - return scene; + utils.mixin(scene, props); + utils.mixin(scene, SceneAction); + return scene; }; /** * Creates a empty instance of scene. - * (To used for runtime creation of animations) + * 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("@")); + 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) + * 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); + director.cast(actors, scene); }; /** * Disconnects an actor/s from a scene. - * (Actors could be delinked during the animation + * (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); + 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, - - _id = id, - - /** - * Holds refereneces of the all animations added to this scene. - * @private - */ - _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. - * @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) - * @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 - * @public - */ - this.active = false; - - /** - * Holds refereneces of complete time span for this scene. - * @private - */ - this.span = 0; - - - /** - * @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(); - } - } - - this.ready = function () { - if (this.animating) { - if (!this.active) { - director.roll(this); - } - return this.active; - } - return false; - }; - - /** - * @private - */ - this.cancel= function () { - animation.cancelRequestAnimationFrame(_req); - }; - - - /** - * @public - */ - this.trigger = function (force) { - if (force || !this.animating) { - _req = animation.requestAnimationFrame(utils.bindSafely(this, loop)); - } - }; - - /** - * Gets the unique ID assigned to this sceen - * @public - */ - this.getID = function () { - return _id; - }; - - /** - * Returns the life span/duration of this sceen. - * @public - */ - this.totalSpan = function() { - return this.span; - }; - - /** - * Adds new animation on already existing animation for this character. - * @public - */ - this.addAnimation = function(newProp, span) { - if (_prevDur === 0 && span === 0) { - _poses[0] = { - animate: newProp, - span: 0 - }; - } else { - _prevDur = span || _prevDur; - this.span += _prevDur; - _poses.push({ - animate: newProp, - span: this.span - }); - } - }; - - this.length = function() { - return _poses.length; - }; - - /** - * Returns animation pose index from the list of - * animations added to this scene for a particular - * instance of time. - * @private - */ - 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; - }; - - 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. - * @public - */ - this.getAnimation = function(index) { - return index < 0 || _poses[index]; - }; - - /** - * Sets new animation for this character. - * @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. - * @public - */ - this.completed = function() {}; - - /** - * Event to identify when the scene has done animating. - * @public - */ - this.step = function() {}; - - /** - * Event to identify when the actor has done animating. - * @public - */ - this.actorCompleted= function(actor) {}; + 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) { + if (_prevDur === 0 && span === 0) { + _poses[0] = { + animate: newProp, + span: 0 + }; + } else { + _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 = { - action: function (ts, pose) { - var past, - actors, - l, i, - tm = this.rolePlay(ts), - index = this.animateAtTime(tm); - - if(index < 0) { - return; - } - pose = 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()]; - l = actors.length; - for (i = 0; i < l; i++) { - director.action(pose, - actors[i], - tm - past, - pose.span - past); + /** + * 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, + actors, + l, i, + tm = this.rolePlay(ts), + index = this.animateAtTime(tm); + + if (index < 0) { + return; + } + pose = 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()]; + l = actors.length; + for (i = 0; i < l; i++) { + director.action(pose, + actors[i], + tm - past, + pose.span - past); this.step && this.step(actors[i]); - } - } - return pose; - } + } + } + return pose; + } }; \ No newline at end of file From 7b79f0e6854a80c5b31daa6be17636e5ec99b5dd Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Fri, 12 Feb 2016 15:30:47 +0530 Subject: [PATCH 13/22] Some fixes - Initiating actors when they start animating - SceneActor looping for required actors only. - docs updated. Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/Director.js | 42 +++---------------- src/AnimationSupport/Frame.js | 3 ++ src/AnimationSupport/Scene.js | 19 +++++---- src/AnimationSupport/SceneActor.js | 64 ++++++++++++++++++----------- src/AnimationSupport/SceneEditor.js | 3 -- src/AnimationSupport/SceneEvent.js | 53 +++++++++++++++++++----- src/AnimationSupport/Tween.js | 18 ++++++-- 7 files changed, 115 insertions(+), 87 deletions(-) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index c6b9db884..920343769 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -1,10 +1,9 @@ require('enyo'); -var frame = require('./Frame'), - tween = require('./Tween'), +var tween = require('./Tween'), utils = require('../utils'); -//var rolePlays = {}; +var pose, dur, tm, t; /** * This modules exposes the features to support 'Director' approach. @@ -21,7 +20,7 @@ module.exports = { for (var i = 0; i < l; i++) { actor = actors[i]; if(actor.generated) { - this.firstShot(scene, actor); + tween.init(actor); active = false; } } @@ -29,18 +28,12 @@ module.exports = { }, take: function (scene, ts) { - var pose, - dur = scene.span, - tm = scene.timeline; + dur = scene.span; + tm = scene.timeline; - //TODO: need to find the right spot for capturing inital pose. - if (!scene.active) { - this.roll(scene); - } if (isNaN(tm) || tm < 0) return; if (tm <= dur) { pose = scene.action(ts, pose); - //TODO: Use Event Delegator to emit this event. } else { scene.timeline = dur; scene.animating = false; @@ -48,12 +41,8 @@ module.exports = { }, action: function (pose, actor, since, dur) { - var t; + if (!pose._startAnim) tween.init(actor, pose); - if (!pose._startAnim) { - utils.mixin(pose, - frame.getComputedProperty(actor.hasNode(), pose.animate, actor.currentState)); - } if (since < 0) since = 0; if (since <= dur && dur !== 0) { t = since / dur; @@ -94,25 +83,6 @@ module.exports = { scene.rolePlays = rolePlays; }, - firstShot: function (scene, actor) { - var dom = actor.hasNode(), - l = scene.length(), - oldPose = frame.getComputedProperty(dom, undefined), - pose; - oldPose.span = 0; - actor._initialPose = oldPose; - actor.currentState = oldPose.currentState; - // frame.accelerate(dom, pose.matrix); - - - for(var i=0; i < l; i++) { - pose = scene.getAnimation(i); - utils.mixin(pose, frame.getComputedProperty(actor.hasNode(), pose.animate, oldPose._endAnim)); - scene.setAnimation(i, pose); - oldPose = pose; - } - }, - shot: function(actor, ts) { var v1, s, a, v = 0, t = ts, diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js index 6636e0d36..029db91ae 100644 --- a/src/AnimationSupport/Frame.js +++ b/src/AnimationSupport/Frame.js @@ -9,6 +9,7 @@ var var COLOR = {color: 1, backgroundColor: 1}, + INT_UNIT = {zIndex: 1}, TRANSFORM = {translate: 1, translateX: 1, translateY: 1, translateZ: 1, rotateX: 1, rotateY: 1, rotateZ: 1, rotate: 1, skew: 1, scale: 1, perspective: 1}; /** @@ -297,6 +298,8 @@ var frame = module.exports = { if (COLOR[prop]) { val = val.map(function(v) { return parseInt(v, 10);}); val = 'rgb('+ val + ')'; + } else if(INT_UNIT[prop]) { + val = parseInt(val[0], 10); } else if (prop == 'opacity') { val = val[0].toFixed(6); val = (val <= 0) ? '0.000001' : val; diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 5ca4eec1a..4be5b3b4f 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -356,8 +356,8 @@ var SceneAction = { */ action: function(ts, pose) { var past, - actors, - l, i, + actor, + actors,i, tm = this.rolePlay(ts), index = this.animateAtTime(tm); @@ -373,13 +373,14 @@ var SceneAction = { } else { past = index ? this.getAnimation(index - 1).span : 0; actors = this.rolePlays[this.getID()]; - l = actors.length; - for (i = 0; i < l; i++) { - director.action(pose, - actors[i], - tm - past, - pose.span - past); - this.step && this.step(actors[i]); + 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; diff --git a/src/AnimationSupport/SceneActor.js b/src/AnimationSupport/SceneActor.js index 5991158ac..81eb194fd 100644 --- a/src/AnimationSupport/SceneActor.js +++ b/src/AnimationSupport/SceneActor.js @@ -3,45 +3,59 @@ var 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, actor, tm, past, index, - dur = this.span, - actors = this.rolePlays[this.getID()], - l = actors.length; + 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; + } - for (i = 0; i < l; i++) { - actor = actors[i]; - if (actor.generated) { - if (!actor._frameSpeed) { - actor._frameSpeed = this._frameSpeed; - } - + if (actor.generated && actor._frameSpeed) { tm = this.rolePlay(ts, actor); if (isNaN(tm) || tm < 0) continue; - if (tm > dur) { + 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; - } - 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); - - if(actor.timeline === dur) { - this.actorCompleted && this.actorCompleted(actor); + actor._frameSpeed = 0; + this.actorCompleted && this.actorCompleted(actor); } } } - - //TODO: return list of actors working in this sceen return pose; } }; /** - * Scene is used to generate animation structure. + * 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) { diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js index 42d4e99db..7d631a5fc 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -9,7 +9,6 @@ module.exports = { timeline: 0, _cachedValue: 0, _frameSpeed: 0, - _startTime: 0, cache: function(actor) { actor = actor || this; @@ -22,7 +21,6 @@ module.exports = { play: function (actor) { actor = actor || this; actor._frameSpeed = 1; - actor._startTime = (actor.delay || 0); if (isNaN(actor.timeline) || !actor.timeline) { actor.timeline = 0; } @@ -83,7 +81,6 @@ module.exports = { actor.timeline = 0; if(actor.delay > 0) { - console.log(actor.name, actor.delay); actor.delay -= _rolePlay(t, actor._frameSpeed); } else { actor.timeline += _rolePlay(t, actor._frameSpeed); diff --git a/src/AnimationSupport/SceneEvent.js b/src/AnimationSupport/SceneEvent.js index 4b57d248c..0a13e1040 100644 --- a/src/AnimationSupport/SceneEvent.js +++ b/src/AnimationSupport/SceneEvent.js @@ -22,10 +22,10 @@ var eventsMap = { * 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; +* providing list of animation events in "handlers" block like; * { * name: "myKind", -* animationEvents: [ +* handlers: [ * "scroll", * "mousewheel", * "touchstart", @@ -35,11 +35,6 @@ var eventsMap = { * } * * 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 = { @@ -170,6 +165,7 @@ var sup, * @private */ _triggerer = ''; + var EventAction = { eventOriginator: undefined, @@ -177,6 +173,7 @@ var EventAction = { /** * 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) { @@ -190,7 +187,9 @@ var EventAction = { }, /** - * Gets the delta values of x, y and z for events + * 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() { @@ -198,7 +197,9 @@ var EventAction = { }, /** - * Trigger the registered event to all the listeners + * 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() { @@ -207,7 +208,12 @@ var EventAction = { }, /** - * Activates handles for generated actors + * 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) { @@ -217,6 +223,16 @@ var EventAction = { } }, + /** + * 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] === "") { @@ -233,7 +249,22 @@ var EventAction = { /** - * Scene is used to generate animation structure. + * 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) { diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 00e4ac90b..e3499c55c 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -7,7 +7,7 @@ var 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; @@ -18,11 +18,24 @@ var oldState, newState, node, matrix, cState = []; */ module.exports = { + /** + * @private + */ + init: function (actor, pose, initial) { + node = actor.hasNode(); + if (pose && pose.animate) { + utils.mixin(pose, + frame.getComputedProperty(node, pose.animate, initial || actor.currentState)); + actor.currentState = pose.currentState; + } + return pose; + }, + /** * @private */ step: function(actor, pose, t, d) { - var k, fn, state, ease, points, path; + var k; node = actor.hasNode(); state = actor.currentState = actor.currentState || pose.currentState || {}; @@ -89,7 +102,6 @@ module.exports = { pose.currentState = state; }, - /** * @private */ From b396dd303799e2f478ece1c7cf874d29b74407d8 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Mon, 15 Feb 2016 15:03:19 +0530 Subject: [PATCH 14/22] Docs for Tween module. Enyo-DCO-1.1-Signed-off-by:Anish Ramesan --- src/AnimationSupport/Tween.js | 82 ++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index e3499c55c..00dec62b6 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -32,8 +32,14 @@ module.exports = { }, /** - * @private - */ + * 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) { var k; @@ -103,12 +109,27 @@ module.exports = { }, /** + * 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; }, - + + /** + * 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 (!vR) vR = []; var i, l = vA.length; @@ -119,6 +140,16 @@ module.exports = { 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 (!qR) qR = []; var a, @@ -142,8 +173,12 @@ module.exports = { }, /** - * @public - * @params t: time, points: knot and control points, vR: resulting point + * 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) { @@ -170,6 +205,15 @@ module.exports = { return vR; }, + /** + * 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) { var order = (easeObj && Object.keys(easeObj).length) ? (Object.keys(easeObj).length + 1) : 0; var bValues = [], @@ -201,6 +245,14 @@ module.exports = { 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 (!vR) vR = []; @@ -219,7 +271,16 @@ module.exports = { return vR; }, - //With control points + /** + * 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) { var time = [0], quats = [startQuat]; @@ -262,7 +323,14 @@ module.exports = { return splinePoints; }, - //With control points + /** + * 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 (!vR) vR = []; var Q0, Q1, Q2, R0, R1; From 7bcaf4ae693284343e346f2b452ee81457d3b2ff Mon Sep 17 00:00:00 2001 From: "rajkumar.selvam" Date: Mon, 15 Feb 2016 17:09:57 +0530 Subject: [PATCH 15/22] Docs for Director and SceneEditor modules. Enyo-DCO-1.1-Signed-off-by:Rajkumar Selvam --- src/AnimationSupport/Director.js | 49 +++++++++++++- src/AnimationSupport/Frame.js | 34 +++++----- src/AnimationSupport/SceneEditor.js | 100 +++++++++++++++++++++++++++- src/AnimationSupport/Tween.js | 4 +- 4 files changed, 167 insertions(+), 20 deletions(-) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index 920343769..719199534 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -6,11 +6,20 @@ var tween = require('./Tween'), var pose, dur, tm, t; /** +* Contains the declaration for the {@link module:enyo/AnimationSupport/Director} module. * This modules exposes the features to support 'Director' approach. -* @module enyo/AnimationSupport/Scene +* @module enyo/AnimationSupport/Director */ module.exports = { + /** + * 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 + */ roll: function (scene) { var actor, actors = scene.rolePlays ? scene.rolePlays[scene.getID()]: [], @@ -27,6 +36,14 @@ module.exports = { scene.active = active; }, + /** + * 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; @@ -40,6 +57,15 @@ module.exports = { } }, + /** + * 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); @@ -52,6 +78,11 @@ module.exports = { } }, + /** + * 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(), @@ -68,6 +99,11 @@ module.exports = { scene.rolePlays = rolePlays; }, + /** + * 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 || []; @@ -83,6 +119,14 @@ module.exports = { scene.rolePlays = rolePlays; }, + /** + * 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, @@ -107,6 +151,9 @@ module.exports = { return dt[dir] > 0 ? v : -v; }, + /** + * @private + */ angle: function (direction) { switch(direction) { case "X" : diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js index 029db91ae..57a3a2bb5 100644 --- a/src/AnimationSupport/Frame.js +++ b/src/AnimationSupport/Frame.js @@ -33,7 +33,6 @@ var frame = module.exports = { * @return {Number[]} Final Matrix3d for particular frame */ recomposeMatrix: function (trns, rot, sc, sq, per) { - "use strict"; var i, x = rot[0], y = rot[1], @@ -103,7 +102,6 @@ var frame = module.exports = { * @return {Boolean} true, if matrix exists else false. */ decomposeMatrix: function (matrix, ret) { - "use strict"; var i, tV = [], rV = [], @@ -204,12 +202,12 @@ var frame = module.exports = { /** * Applies transformation to DOM element with the Matrix3d values. * @public - * @param {HTMLElement} ele Element which is going to animate. + * @param {enyo.Component} actor Component to be animated. * @param {Number[]} m Matrix3d */ - accelerate: function (ele, m) { + accelerate: function (actor, m) { m = m ? m : Matrix.identity(); - frame.setTransformProperty(ele, m); + frame.setTransformProperty(actor, m); }, /** @@ -290,11 +288,11 @@ var frame = module.exports = { /** * Applies style property to DOM element. * @public - * @param {HTMLElement} ele DOM element to be animated. - * @param {String} prop CSS property to be applied. + * @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 (ele, prop, val) { + setProperty: function (actor, prop, val) { if (COLOR[prop]) { val = val.map(function(v) { return parseInt(v, 10);}); val = 'rgb('+ val + ')'; @@ -306,24 +304,28 @@ var frame = module.exports = { } else { val = val[0] + 'px'; } - if (ele) { - ele.style[prop] = val; - } + + actor.addStyles(prop + ':' + val + ';'); }, /** * Applies transform property to DOM element. * @public - * @param {HTMLElement} element HTML element which is going to animate. - * @param {Number[]} matrix Matrix3d + * @param {enyo.Component} actor Component to be animated. + * @param {Number[]} matrix Matrix3d */ - setTransformProperty: function (element, matrix) { + 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 + ';'); }, /** diff --git a/src/AnimationSupport/SceneEditor.js b/src/AnimationSupport/SceneEditor.js index 7d631a5fc..14824613a 100644 --- a/src/AnimationSupport/SceneEditor.js +++ b/src/AnimationSupport/SceneEditor.js @@ -1,15 +1,34 @@ 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){ @@ -18,6 +37,12 @@ module.exports = { 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; @@ -28,36 +53,90 @@ module.exports = { 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; @@ -66,6 +145,14 @@ module.exports = { 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) { @@ -75,6 +162,13 @@ module.exports = { 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) @@ -89,6 +183,10 @@ module.exports = { } }; +/** + * 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/Tween.js b/src/AnimationSupport/Tween.js index 00dec62b6..81d8bfa49 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -83,7 +83,7 @@ module.exports = { if (!frame.isTransform(k)) { - frame.setProperty(node, k, cState); + frame.setProperty(actor, k, cState); } state[k] = cState; } @@ -103,7 +103,7 @@ module.exports = { state.skew, state.perspective ); - frame.accelerate(node, matrix); + frame.accelerate(actor, matrix); state.matrix = matrix; pose.currentState = state; }, From 9d5fe8ada0a63750ce47db95b9ecfb4ea13bd694 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Wed, 17 Feb 2016 13:43:26 +0530 Subject: [PATCH 16/22] Removed Event Delegator and docs for vector Enyo-DCO-1.1-Signed-off-by: Anish Ramesan --- src/AnimationSupport/EventDelegator.js | 206 ------------------------- src/AnimationSupport/Tween.js | 5 +- src/AnimationSupport/Vector.js | 142 ++++++++++------- 3 files changed, 92 insertions(+), 261 deletions(-) delete mode 100644 src/AnimationSupport/EventDelegator.js diff --git a/src/AnimationSupport/EventDelegator.js b/src/AnimationSupport/EventDelegator.js deleted file mode 100644 index 09d9281c7..000000000 --- a/src/AnimationSupport/EventDelegator.js +++ /dev/null @@ -1,206 +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 = { - - /** - * 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, events) { - events = events || {}; - 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, events) { - events = events || {}; - 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]; - - - 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); - } -}; - -module.exports = EventDelegator; diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 81d8bfa49..03f968231 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -333,9 +333,8 @@ module.exports = { */ bezierSpline: function(t, points, vR) { 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; } 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], From 168bd41f6f079078fc4444a2598daf0b0aba7f9d Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Wed, 17 Feb 2016 16:52:07 +0530 Subject: [PATCH 17/22] Added Test case for Tween and some correction. Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Tween.js | 33 ++- test/tests/NewTweenTest.js | 380 ++++++++++++++++++++++++++++++++++ 2 files changed, 402 insertions(+), 11 deletions(-) create mode 100644 test/tests/NewTweenTest.js diff --git a/src/AnimationSupport/Tween.js b/src/AnimationSupport/Tween.js index 03f968231..d4319771f 100644 --- a/src/AnimationSupport/Tween.js +++ b/src/AnimationSupport/Tween.js @@ -22,12 +22,10 @@ module.exports = { * @private */ init: function (actor, pose, initial) { + if (!(actor && pose && pose.animate)) return; node = actor.hasNode(); - if (pose && pose.animate) { - utils.mixin(pose, - frame.getComputedProperty(node, pose.animate, initial || actor.currentState)); - actor.currentState = pose.currentState; - } + utils.mixin(pose, frame.getComputedProperty(node, pose.animate, initial || actor.currentState)); + actor.currentState = pose.currentState; return pose; }, @@ -41,8 +39,10 @@ module.exports = { * @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 || {}; @@ -131,6 +131,7 @@ module.exports = { * @private */ lerp: function(vA, vB, t, vR) { + if (!vA) return; if (!vR) vR = []; var i, l = vA.length; @@ -151,6 +152,7 @@ module.exports = { * @private */ slerp: function(qA, qB, t, qR) { + if (!qA) return; if (!qR) qR = []; var a, b, @@ -181,7 +183,7 @@ module.exports = { * @memberOf module:enyo/AnimationSupport/Tween */ bezier: function(t, points, vR) { - + if (!points) return; if (!vR) vR = []; var i, j, @@ -215,6 +217,7 @@ module.exports = { * @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 = [], @@ -254,6 +257,7 @@ module.exports = { * @memberOf module:enyo/AnimationSupport/Tween */ traversePath: function (t, path, vR) { + if (!path) return; if (!vR) vR = []; var i, j, @@ -282,6 +286,7 @@ module.exports = { * @memberOf module:enyo/AnimationSupport/Tween */ bezierSPoints: function(ease, startQuat, endQuat, endPoint, splinePoints) { + if (!ease) return; var time = [0], quats = [startQuat]; @@ -289,8 +294,9 @@ module.exports = { eD = frame.parseValue(endPoint); splinePoints = splinePoints || {}; - - if (ease && Object.keys(ease).length > 0) { + 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]); @@ -302,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); @@ -332,11 +339,15 @@ module.exports = { * @memberOf module:enyo/AnimationSupport/Tween */ bezierSpline: function(t, points, vR) { + if (!points) return; if (!vR) vR = []; 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]; 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 From 86342211178005c1cc95046d87335c894d08e370 Mon Sep 17 00:00:00 2001 From: Anish_Ramesan Date: Tue, 23 Feb 2016 15:56:32 +0530 Subject: [PATCH 18/22] pose not identified issue fix. Enyo-DCO-1.1-Signed-off-by: Anish Ramesa --- src/AnimationSupport/Scene.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 4be5b3b4f..3be48f4b9 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -364,7 +364,7 @@ var SceneAction = { if (index < 0) { return; } - pose = pose || this.getAnimation(index); + pose = this.getAnimation(index); past = pose.animate; if (past instanceof sceneConstructor) { From 84def63ed1d6607189b51f582da12a5789d49c09 Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Wed, 2 Mar 2016 14:55:46 +0530 Subject: [PATCH 19/22] Fixed some bug for multiple scene scenario Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Director.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AnimationSupport/Director.js b/src/AnimationSupport/Director.js index 719199534..7deb94795 100644 --- a/src/AnimationSupport/Director.js +++ b/src/AnimationSupport/Director.js @@ -1,9 +1,9 @@ require('enyo'); var tween = require('./Tween'), - utils = require('../utils'); + utils = require('../utils'); -var pose, dur, tm, t; +var dur, tm, t; /** * Contains the declaration for the {@link module:enyo/AnimationSupport/Director} module. @@ -50,7 +50,7 @@ module.exports = { if (isNaN(tm) || tm < 0) return; if (tm <= dur) { - pose = scene.action(ts, pose); + scene.pose = scene.action(ts, scene.pose); } else { scene.timeline = dur; scene.animating = false; From 3f772cb4dcf7ca1fa1f0909bafcf080fe927bbe2 Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Tue, 8 Mar 2016 16:03:43 +0530 Subject: [PATCH 20/22] Now support delay in between animations of a scene Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Scene.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/AnimationSupport/Scene.js b/src/AnimationSupport/Scene.js index 3be48f4b9..fa6b7ad4a 100644 --- a/src/AnimationSupport/Scene.js +++ b/src/AnimationSupport/Scene.js @@ -20,8 +20,9 @@ var Scene = module.exports = function(props) { 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); + 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; @@ -225,13 +226,29 @@ var sceneConstructor = function(id) { * @memberOf module:enyo/AnimationSupport/Scene * @public */ - this.addAnimation = function(newProp, span) { + this.addAnimation = function(newProp, span, delay) { if (_prevDur === 0 && span === 0) { - _poses[0] = { + var index = 0; + if (delay) { + _prevDur = delay; + this.span += _prevDur; + _poses[index++] = { + span: this.span + }; + } + _prevDur = 0; + _poses[index] = { animate: newProp, - span: 0 + span: this.span }; } else { + if (delay) { + _prevDur = delay; + this.span += _prevDur; + _poses.push({ + span: this.span + }); + } _prevDur = span || _prevDur; this.span += _prevDur; _poses.push({ From 57f55513fc7c152f689944666a821adb13197050 Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Wed, 9 Mar 2016 17:12:22 +0530 Subject: [PATCH 21/22] Add support for various color, radius and opacity Use these properties as it as in css. Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Frame.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js index 57a3a2bb5..954ccc989 100644 --- a/src/AnimationSupport/Frame.js +++ b/src/AnimationSupport/Frame.js @@ -8,8 +8,10 @@ var Matrix = require('./Matrix'); var - COLOR = {color: 1, backgroundColor: 1}, - INT_UNIT = {zIndex: 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}; /** @@ -295,10 +297,12 @@ var frame = module.exports = { setProperty: function (actor, prop, val) { if (COLOR[prop]) { val = val.map(function(v) { return parseInt(v, 10);}); - val = 'rgb('+ val + ')'; + val = 'rgb('+ val + ')'; } else if(INT_UNIT[prop]) { val = parseInt(val[0], 10); - } else if (prop == 'opacity') { + } else if (BORDER[prop]) { + val = val[0] + '%'; + } else if (OPACITY[prop]) { val = val[0].toFixed(6); val = (val <= 0) ? '0.000001' : val; } else { From 99934471775bacec0a5ba081707905efa4fc0f73 Mon Sep 17 00:00:00 2001 From: Ankur Mishra Date: Fri, 11 Mar 2016 15:27:25 +0530 Subject: [PATCH 22/22] Add Support for box-shadow Now we can use color value in rgb within the animation value itself. Enyo-DCO-1.1-Signed-off-by: Ankur Mishra --- src/AnimationSupport/Frame.js | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/AnimationSupport/Frame.js b/src/AnimationSupport/Frame.js index 954ccc989..64958157a 100644 --- a/src/AnimationSupport/Frame.js +++ b/src/AnimationSupport/Frame.js @@ -247,6 +247,16 @@ var frame = module.exports = { }); }, + 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 @@ -274,9 +284,13 @@ var frame = module.exports = { */ 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(')', ''); } @@ -305,6 +319,9 @@ var frame = module.exports = { } 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'; } @@ -347,15 +364,19 @@ var frame = module.exports = { 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;