UNPKG

lottie-web

Version:

After Effects plugin for exporting animations to SVG + JavaScript or canvas + JavaScript

1,237 lines (1,161 loc) 121 kB
var Gtlym = {};var bodymovinWindow = this; (function(){ /****** INIT JSON PARSER ******/ if (typeof JSON !== 'object') { JSON = {}; } (function () { 'use strict'; function f(n) { return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function () { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function () { return this.valueOf(); }; } var cx, escapable, gap, indent, meta, rep; function quote(string) { escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { var i, k, v, length, mind = gap, partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } if (typeof rep === 'function') { value = rep.call(holder, key, value); } switch (typeof value) { case 'string': return quote(value); case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) { return 'null'; } gap += indent; partial = []; if (Object.prototype.toString.apply(value) === '[object Array]') { length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { if (typeof rep[i] === 'string') { k = rep[i]; v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } if (typeof JSON.stringify !== 'function') { escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' }; JSON.stringify = function (value, replacer, space) { var i; gap = ''; indent = ''; if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { indent = space; } rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } return str('', {'': value}); }; } if (typeof JSON.parse !== 'function') { cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; JSON.parse = function (text, reviver) { var j; function walk(holder, key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.prototype.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } if (/^[\],:{}\s]*$/ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { j = eval('(' + text + ')'); return typeof reviver === 'function' ? walk({'': j}, '') : j; } throw new SyntaxError('JSON.parse'); }; } }()); /****** END JSON PARSER ******/ /****** INIT ARRAY POLYFILLS ******/ if (!Array.prototype.forEach) { Array.prototype.forEach = function(callback, thisArg) { var T, k; if (this == null) { throw new TypeError(' this is null or not defined'); } var O = Object(this); var len = O.length >>> 0; if (typeof callback !== "function") { throw new TypeError(callback + ' is not a function'); } if (arguments.length > 1) { T = thisArg; } k = 0; while (k < len) { var kValue; if (k in O) { kValue = O[k]; callback.call(T, kValue, k, O); } k++; } }; } if (!Array.prototype.map) { Array.prototype.map = function(callback, thisArg) { var T, A, k; if (this == null) { throw new TypeError(' this is null or not defined'); } var O = Object(this); var len = O.length >>> 0; if (typeof callback !== 'function') { throw new TypeError(callback + ' is not a function'); } if (arguments.length > 1) { T = thisArg; } A = new Array(len); k = 0; while (k < len) { var kValue, mappedValue; if (k in O) { kValue = O[k]; mappedValue = callback.call(T, kValue, k, O); A[k] = mappedValue; } k++; } return A; }; } /****** END ARRAY POLYFILLS ******/ var console = { log : function(){ $.writeln.call($,arguments); } }; /****** INIT Var Declarations ******/ var helperSolidComp; var helperFootage; //Solid for anchor point fix on shape layers var helperSolid; //Destination export folder var exportFolder; //Interval objects container //var Gtlym = {}; Gtlym.CALL = {}; //Render cancelled flag var renderCancelled = false; //modules var LayerConverter; var rqManager; var extrasInstance; var AsyncManager; var DOMAnimationManager; var CompConverter; var ShapesParser; var EffectsParser; var UI; /****** INIT Assets Manager ******/ (function(){ var ob = {}; var sourceAssets = []; var sourceExportData = []; function reset(){ sourceAssets = []; sourceExportData = []; } function associateLayerToSource(layer, source){ var i=0, len = sourceAssets.length; while(i<len){ if(sourceAssets[i].s === source){ sourceAssets[i].l.push(layer); break; } i+=1; } } function exportFileFromLayer(layer, filesDirectory){ var i = 0, len = sourceAssets.length; var j, jLen, found = false; while(i<len){ j = 0; jLen = sourceAssets[i].l.length; while(j<jLen){ if(sourceAssets[i].l[j] === layer){ found = true; if(sourceAssets[i].exported === false){ var imageName = 'imagen_'+i; var imageExtension = 'png'; var destinationFile = new File(filesDirectory.fullName+'/'+imageName+'.'+imageExtension); sourceAssets[i].f.copy(destinationFile); sourceAssets[i].exported = true; sourceAssets[i].path = 'files/'+imageName+'.'+imageExtension; } } j+=1; } if(found === true){ return i; } i+=1; } } function createAssetsDataForExport(){ sourceAssets.forEach(function(item){ if(item.exported === true){ sourceExportData.push({path:item.path}); } }) } function createLayerSource(file, layer, source){ sourceAssets.push({s:source,f:file,l:[layer], exported:false}); } function getAssetsData(){ return sourceExportData; } ob.getAssetsData = getAssetsData; ob.reset = reset; ob.associateLayerToSource = associateLayerToSource; ob.createLayerSource = createLayerSource; ob.createAssetsDataForExport = createAssetsDataForExport; ob.exportFileFromLayer = exportFileFromLayer; AssetsManager = ob; }()); /****** END Assets Manager ******/ /**** Async Manager ****/ (function(){ var ob = {}; var asyncCount = 0; var callback; var asyncElements = []; function executeCall(item){ item.call(); } function executeAsyncCalls(){ var executingElements = asyncElements.splice(0,asyncElements.length); asyncElements.length = 0; executingElements.forEach(executeCall); asyncCount -= 1; if(asyncCount == 0){ callback.apply(); } } function addAsyncCall(fn){ asyncElements.push(fn); if(asyncElements.length == 1){ asyncCount += 1; //Todo Create async call extrasInstance.setTimeout(executeAsyncCalls,1); } } function addAsyncCounter(){ asyncCount += 1; } function removeAsyncCounter(){ asyncCount -= 1; if(asyncCount == 0){ callback.apply(); } } function getAsyncCounter(){ return asyncCount; } function setCallBack(cb){ callback = cb; } ob.addAsyncCall = addAsyncCall; ob.addAsyncCount = addAsyncCounter; ob.removeAsyncCounter = removeAsyncCounter; ob.getAsyncCounter = getAsyncCounter; ob.setCallBack = setCallBack; AsyncManager = ob; }()); /**** END Async Manager ****/ /****** INIT DOMAnimationMAnager ******/ (function(){ var frameRate = 0; var totalFrames = 0; var firstFrame = 0; var currentRenderFrame = 0; var currentTime = 0; var imageCount = 0; var zCount = 0; var isRenderReady = false; var mainComp; var mainLayers = []; var filesDirectory; var callback; var pendingLayers = []; var totalLayers = 0; var exportedComps = []; function getCompositionAnimationData(compo, compositionData,fDirectory){ exportedComps = []; mainComp = compo; frameRate = mainComp.frameRate; currentRenderFrame = 0; imageCount = 0; zCount = 0; mainLayers = []; totalFrames = mainComp.workAreaDuration*mainComp.frameRate; firstFrame = mainComp.workAreaStart*mainComp.frameRate; //totalFrames = 1; var animationOb = {}; compositionData.animation = animationOb; compositionData.assets = AssetsManager.getAssetsData(); compositionData.v = '2.0.6'; animationOb.layers = mainLayers; animationOb.totalFrames = totalFrames; animationOb.frameRate = frameRate; animationOb.ff = mainComp.workAreaStart; animationOb.compWidth = mainComp.width; animationOb.compHeight = mainComp.height; filesDirectory = fDirectory; iterateComposition(); } function getMaskMode (num){ switch(num){ case MaskMode.NONE: return 'n'; case MaskMode.ADD: return 'a'; case MaskMode.SUBTRACT: return 's'; case MaskMode.INTERSECT: return 'i'; case MaskMode.LIGHTEN: return 'l'; case MaskMode.DARKEN: return 'd'; case MaskMode.DIFFERENCE: return 'f'; } } function addMasksToLayer(layerInfo,layerOb,time){ layerOb.mk = []; var i, len = layerInfo.mask.numProperties, maskShape, maskElement; for(i=0;i<len;i++){ maskElement = layerInfo.mask(i+1); maskShape = layerInfo.mask(i+1).property('maskShape').valueAtTime(time,false); layerOb.mk.push({v:extrasInstance.roundNumber(maskShape.vertices,3), i:extrasInstance.roundNumber(maskShape.inTangents,3), o:extrasInstance.roundNumber(maskShape.outTangents,3), t:extrasInstance.roundNumber(maskElement.property('Mask Opacity').valueAtTime(time,false)/100,3)}); } } function setMasks(masks,layerOb){ layerOb.masksProperties = []; var i, len = masks.numProperties, maskShape, maskElement; for(i=0;i<len;i++){ maskElement = masks(i+1); maskShape = maskElement.property('maskShape').value; var shapeData = { cl:maskShape.closed, inv:maskElement.inverted, mode:getMaskMode(maskElement.maskMode) }; extrasInstance.convertToBezierValues(maskElement.property('maskShape'), frameRate, shapeData,'pt'); extrasInstance.convertToBezierValues(maskElement.property('Mask Opacity'), frameRate, shapeData,'o'); layerOb.masksProperties.push(shapeData); } } function addStillAsset(layerOb,layerInfo){ layerOb.assetId = AssetsManager.exportFileFromLayer(layerInfo,filesDirectory); } function removeExtraData(layersData){ var i, len = layersData.length,j, jLen, shapes; for(i = 0;i<len;i++){ var layerOb = layersData[i]; if(layerOb.enabled == false){ layersData.splice(i,1); i -= 1; len -= 1; continue; } layerOb.lastData = null ; delete layerOb.lastData; if(layerOb.type == 'ShapeLayer'){ shapes = layerOb.shapes; jLen = shapes.length; for(j=0;j<jLen;j++){ shapes[j].lastData = null; delete shapes[j].lastData; } } if(layerOb.type == 'PreCompLayer' && layerOb.layers){ removeExtraData(layerOb.layers); } EffectsParser.saveEffectData(layerOb); } } function processFinalData(layersData){ var i, len = layersData.length; for(i = 0;i<len;i++){ var layerOb = layersData[i]; if(layerOb.type == 'ShapeLayer'){ layerOb.rectData.w = extrasInstance.roundNumber(layerOb.rectData.r - layerOb.rectData.l,3); layerOb.rectData.h = extrasInstance.roundNumber(layerOb.rectData.b - layerOb.rectData.t,3); } if(layerOb.type == 'PreCompLayer' && layerOb.layers){ processFinalData(layerOb.layers); } } } function buildTextData(textDocument){ var textDataOb = {}; textDataOb.font = textDocument.font; textDataOb.fontSize = textDocument.fontSize; textDataOb.fillColor = extrasInstance.arrayRgbToHex(textDocument.fillColor); textDataOb.text = textDocument.text; var justification = ''; switch(textDocument.justification){ case ParagraphJustification.LEFT_JUSTIFY: justification = 'left'; break; case ParagraphJustification.RIGHT_JUSTIFY: justification = 'right'; break; case ParagraphJustification.CENTER_JUSTIFY: justification = 'center'; break; case ParagraphJustification.FULL_JUSTIFY_LASTLINE_LEFT: case ParagraphJustification.FULL_JUSTIFY_LASTLINE_RIGHT: case ParagraphJustification.FULL_JUSTIFY_LASTLINE_CENTER: case ParagraphJustification.FULL_JUSTIFY_LASTLINE_FULL: justification = 'justify'; break; default: justification = 'left'; break; } textDataOb.justification = justification; return textDataOb; } function analyzeNextLayer(){ if(pendingLayers.length == 0){ renderNextFrame(); }else{ var pendingItem = pendingLayers.pop(); UI.setProgress(pendingLayers.length/totalLayers); var layerOb = pendingItem.lOb; var layerInfo = pendingItem.lInfo; var frameRate = pendingItem.frameRate; var lType = extrasInstance.layerType(layerInfo); if(lType == 'AudioLayer' || lType == 'CameraLayer' || (layerInfo.enabled == false && !layerInfo.isTrackMatte)){ //TODO add audios layerOb.enabled = false; extrasInstance.setTimeout(analyzeNextLayer,100); return; }else if(lType == 'TextLayer'){ var textProp = layerInfo.property("Source Text"); var textDocument = textProp.value; layerOb.textData = buildTextData(textDocument); var r = layerInfo.sourceRectAtTime(0, false); layerOb.textData.xOffset = r.left; layerOb.textData.yOffset = r.top; layerOb.textData.width = r.width; layerOb.textData.height = r.height; } //EffectsParser.createEffects(layerInfo,layerOb); if(layerInfo.mask.numProperties>0){ setMasks(layerInfo.mask,layerOb); layerOb.hasMask = true; } layerOb.type = lType; if(lType == 'ShapeLayer'){ ShapesParser.createShapes(layerInfo,layerOb, frameRate); layerOb.rectData = {l:0,t:0,b:0,r:0,w:0,h:0}; } if(layerInfo.parent != null){ layerOb.parent = layerInfo.parent.index - 1; } layerOb.layerName = layerInfo.name; layerOb.threeD = layerInfo.threeDLayer; layerOb.an = {}; if(lType=='PreCompLayer'){ layerOb.width = layerInfo.source.width; layerOb.height = layerInfo.source.height; }else if(lType == 'StillLayer'){ addStillAsset(layerOb,layerInfo); layerOb.width = layerInfo.source.width; layerOb.height = layerInfo.source.height; }else if(lType == 'SolidLayer'){ layerOb.width = layerInfo.source.width; layerOb.height = layerInfo.source.height; layerOb.color = extrasInstance.arrayRgbToHex(layerInfo.source.mainSource.color); }else if(lType == 'ShapeLayer'){ layerOb.width = layerInfo.width; layerOb.height = layerInfo.height; } layerOb.inPoint = layerInfo.inPoint*frameRate; layerOb.outPoint = layerInfo.outPoint*frameRate; layerOb.startTime = layerInfo.startTime*frameRate; layerOb.lastData = {}; layerOb.ks = {}; if(layerInfo.transform.opacity.numKeys>1){ extrasInstance.convertToBezierValues(layerInfo.transform.opacity, frameRate, layerOb.ks,'o'); }else{ layerOb.ks.o = extrasInstance.roundNumber(layerInfo.transform.opacity.valueAtTime(0,false),3); } if(layerInfo.transform.rotation.numKeys>1){ extrasInstance.convertToBezierValues(layerInfo.transform.rotation, frameRate, layerOb.ks,'r'); }else{ layerOb.ks.r = extrasInstance.roundNumber(layerInfo.transform.rotation.valueAtTime(0,false),3); } if(layerInfo.transform.position.dimensionsSeparated){ layerOb.ks.p = {s:true}; extrasInstance.convertToBezierValues(layerInfo.transform['X Position'], frameRate, layerOb.ks.p,'x'); extrasInstance.convertToBezierValues(layerInfo.transform['Y Position'], frameRate, layerOb.ks.p,'y'); }else{ if(layerInfo.transform.position.numKeys>1){ extrasInstance.convertToBezierValues(layerInfo.transform.position, frameRate, layerOb.ks,'p'); }else{ layerOb.ks.p = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(0,false),3); } } if(layerInfo.transform['Anchor Point'].numKeys>1){ if(lType == 'ShapeLayer'){ prepareHelperSolid(layerInfo.transform['Anchor Point'],frameRate,layerOb.ks,'a'); }else{ extrasInstance.convertToBezierValues(layerInfo.transform['Anchor Point'], frameRate, layerOb.ks,'a'); } }else{ layerOb.ks.a = extrasInstance.roundNumber(layerInfo.transform['Anchor Point'].valueAtTime(0,false),3); } if(layerInfo.transform['Scale'].numKeys>1){ extrasInstance.convertToBezierValues(layerInfo.transform['Scale'], frameRate, layerOb.ks,'s'); }else{ layerOb.ks.s = extrasInstance.roundNumber(layerInfo.transform['Scale'].valueAtTime(0,false),3); } if(layerInfo.canSetTimeRemapEnabled && layerInfo.timeRemapEnabled){ extrasInstance.convertToBezierValues(layerInfo['Time Remap'], frameRate, layerOb,'tm'); } checkLayerReady(); } } function checkLayerReady(){ if(renderCancelled){ callback.apply(); }else{ extrasInstance.setTimeout(analyzeNextLayer,100); } } function prepareHelperSolid(property,frameRate,ob,param){ var currentKeyframe = 1; var helperPosition = helperSolid.transform["Anchor Point"]; var jLen = helperPosition.numKeys; while(jLen > 0){ helperPosition.removeKey(1); jLen -= 1; } helperSolidComp.frameRate = frameRate; jLen = property.numKeys; var keyIn, keyOut; var keyInHelper, keyOutHelper; var propertyValueDelta, helperValueDelta; function adjustNextHelperSpeed(){ var j; for(j = 0; j<jLen; j+=1){ keyIn = property.keyInTemporalEase(j+1)[0]; keyOut = property.keyOutTemporalEase(j+1)[0]; keyInHelper = new KeyframeEase(keyIn.speed, keyIn.influence); keyOutHelper = new KeyframeEase(keyOut.speed, keyOut.influence); helperPosition.addKey(property.keyTime(j+1)); helperPosition.setValueAtTime(property.keyTime(j+1),property.valueAtTime(property.keyTime(j+1),true)); helperPosition.setTemporalEaseAtKey(j+1, [keyInHelper], [keyOutHelper]); } correctNextKey(); } function correctNextKey(){ var i= 0, len = 20; if(currentKeyframe !== jLen + 1){ keyIn = property.keyInTemporalEase(currentKeyframe)[0]; keyOut = property.keyOutTemporalEase(currentKeyframe)[0]; propertyValueDelta = property.valueAtTime(property.keyTime(currentKeyframe)+0.01,false); keyOutHelper = helperPosition.keyOutTemporalEase(currentKeyframe); keyInHelper = helperPosition.keyInTemporalEase(currentKeyframe); var flag = true; var currentSpeed, deltaSpeed = 10, dir = 0; var helpValue,helpValue2; if(currentKeyframe != 1){ helpValue = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe),false); helpValue2 = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe-1),false); propertyValueDelta = property.valueAtTime(property.keyTime(currentKeyframe)-0.01,false); helperValueDelta = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe)-0.01,false); currentSpeed = keyInHelper[0].speed; deltaSpeed = Math.abs(keyInHelper[0].speed); if(Math.abs(helperValueDelta[0]) > Math.abs(propertyValueDelta[0]) || Math.abs(helperValueDelta[1]) > Math.abs(propertyValueDelta[1])){ dir = 1; }else{ dir = -1; } while(flag){ helpValue = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe),false); helpValue2 = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe - 1),false); helperValueDelta = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe)-0.01,false); if(Math.abs(helperValueDelta[0]-propertyValueDelta[0]) < 0.001 && Math.abs(helperValueDelta[1]-propertyValueDelta[1]) < 0.001){ flag = false; }else{ if(Math.abs(helperValueDelta[0]) > Math.abs(propertyValueDelta[0]) || Math.abs(helperValueDelta[1]) > Math.abs(propertyValueDelta[1])){ if(dir == 1){ deltaSpeed /= 2; } dir = -1; currentSpeed += deltaSpeed; keyInHelper[0].speed = currentSpeed; helperPosition.setTemporalEaseAtKey(currentKeyframe, keyInHelper, keyOutHelper); }else{ if(dir == -1){ deltaSpeed /= 2; } dir = 1; currentSpeed -= deltaSpeed; keyInHelper[0].speed = currentSpeed; helperPosition.setTemporalEaseAtKey(currentKeyframe, keyInHelper, keyOutHelper); } } i += 1; if(i == len){ keyInHelper[0].speed = keyIn.speed; helperPosition.setTemporalEaseAtKey(currentKeyframe, keyInHelper, keyOutHelper); flag = false; } } } if(currentKeyframe != jLen){ i = 0; flag = true; propertyValueDelta = property.valueAtTime(property.keyTime(currentKeyframe)+0.01,false); helperValueDelta = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe)+0.01,false); helpValue = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe),false); currentSpeed = keyOutHelper[0].speed; deltaSpeed = Math.abs(keyOutHelper[0].speed); if(Math.abs(helperValueDelta[0]) > Math.abs(propertyValueDelta[0]) || Math.abs(helperValueDelta[1]) > Math.abs(propertyValueDelta[1])){ dir = -1; }else{ dir = 1; } while(flag){ helpValue = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe),false); helperValueDelta = helperPosition.valueAtTime(helperPosition.keyTime(currentKeyframe)+0.01,false); if(Math.abs(helperValueDelta[0]-propertyValueDelta[0]) < 0.001 && Math.abs(helperValueDelta[1]-propertyValueDelta[1]) < 0.001){ flag = false; }else{ if(Math.abs(helperValueDelta[0]) > Math.abs(propertyValueDelta[0]) || Math.abs(helperValueDelta[1]) > Math.abs(propertyValueDelta[1]) ){ if(dir == -1){ deltaSpeed /= 2; } dir = 1; currentSpeed -= deltaSpeed; keyOutHelper[0].speed = currentSpeed; helperPosition.setTemporalEaseAtKey(currentKeyframe, keyInHelper, keyOutHelper); }else{ if(dir == 1){ deltaSpeed /= 2; } dir = -1; currentSpeed += deltaSpeed; keyOutHelper[0].speed = currentSpeed; helperPosition.setTemporalEaseAtKey(currentKeyframe, keyInHelper, keyOutHelper); } } i += 1; if(i == len){ keyOutHelper[0].speed = keyOut.speed; helperPosition.setTemporalEaseAtKey(currentKeyframe, keyInHelper, keyOutHelper); flag = false; } } } currentKeyframe += 1; correctNextKey(); }else{ extrasInstance.convertToBezierValues(helperPosition, frameRate, ob,param); } } adjustNextHelperSpeed(); } function createLayers(compo, layersData, frameRate){ var i, len = compo.layers.length; var pendingType; for(i = 0;i<len;i++){ var layerOb = {}; layerOb.ind = i; var layerInfo = compo.layers[i+1]; var lType = extrasInstance.layerType(layerInfo); //$.writeln('layerInfo.isTrackMatte: ',layerInfo.isTrackMatte); //$.writeln('layerInfo.hasTrackMatte: ',layerInfo.hasTrackMatte); layersData.push(layerOb); if(lType == 'AudioLayer' || lType == 'CameraLayer' || (layerInfo.enabled == false && !layerInfo.isTrackMatte)){ //TODO add audios layerOb.enabled = false; continue; } if(layerInfo.hasTrackMatte){ switch(layerInfo.trackMatteType){ case TrackMatteType.ALPHA: pendingType = 1; break; case TrackMatteType.ALPHA_INVERTED: pendingType = 2; break; case TrackMatteType.LUMA: pendingType = 3; break; case TrackMatteType.LUMA_INVERTED : pendingType = 4; break; } layerOb.tt = pendingType; }else if(layerInfo.isTrackMatte){ layerOb.td = 1; } pendingLayers.push({lInfo:layerInfo,lOb:layerOb,frameRate:frameRate}); if(lType=='PreCompLayer'){ var j = 0, jLen = exportedComps.length, isRendered = false; while(j<jLen){ if(exportedComps[j].lInfo.source == layerInfo.source){ isRendered = true; break; } j+=1; } if(isRendered){ if(!exportedComps[j].lOb.compId){ exportedComps[j].lOb.compId = extrasInstance.getRandomName(7); } layerOb.refId = exportedComps[j].lOb.compId; }else{ layerOb.layers = []; createLayers(layerInfo.source,layerOb.layers,layerInfo.source.frameRate); exportedComps.push({ lInfo: layerInfo, lOb: layerOb }) } } } } function getParentSize (name,layers){ var i=0, len = layers.length; while(i<len){ if(layers[i].layerName == name){ return {width:layers[i].width,height:layers[i].height}; } i++; } return {width:0,height:0}; } function traverseAnimation(compo,layersData, frameNum, time){ var i, len = compo.layers.length; for(i = 0;i<len;i++){ var layerInfo = compo.layers[i+1]; var lType = extrasInstance.layerType(layerInfo); if(lType == 'AudioLayer' || lType == 'CameraLayer' || (layerInfo.enabled == false && !layerInfo.isTrackMatte)){ //TODO add audios continue; } var layerOb = layersData[i]; var animData = {}; if(layerOb.hasMask){ addMasksToLayer(layerInfo,animData,time); } animData.tr = {}; animData.tr.p = []; animData.tr.a = []; animData.tr.r = []; animData.tr.s = []; animData.tr.o = {}; if(layerOb.parent != null){ var parentSize = getParentSize(layerOb.parent,layersData); animData.tr.p[0] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[0],3); animData.tr.p[1] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[1],3); }else{ animData.tr.p[0] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[0],3); animData.tr.p[1] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[1],3); } if(layerOb.threeD){ animData.tr.p[2] = extrasInstance.roundNumber(-layerInfo.transform.position.valueAtTime(time,false)[2],3); }else{ animData.tr.p[2] = -zCount; zCount++; } if(lType=='ShapeLayer'){ var r = layerInfo.sourceRectAtTime(frameNum, false); layerOb.rectData.l = extrasInstance.roundNumber(Math.min(r.left,layerOb.rectData.l),3); layerOb.rectData.t = extrasInstance.roundNumber(Math.min(r.top,layerOb.rectData.t),3); layerOb.rectData.r = extrasInstance.roundNumber(Math.max(r.left+r.width,layerOb.rectData.r),3); layerOb.rectData.b = extrasInstance.roundNumber(Math.max(r.top+r.height,layerOb.rectData.b),3); } animData.tr.a[0] = extrasInstance.roundNumber(layerInfo.transform['Anchor Point'].valueAtTime(time,false)[0],3); animData.tr.a[1] = extrasInstance.roundNumber(layerInfo.transform['Anchor Point'].valueAtTime(time,false)[1],3); animData.tr.a[2] = extrasInstance.roundNumber(-layerInfo.transform['Anchor Point'].valueAtTime(time,false)[2],3); animData.tr.s = extrasInstance.roundNumber([(layerInfo.transform['Scale'].valueAtTime(time,false)[0]/100),(layerInfo.transform['Scale'].valueAtTime(time,false)[1]/100),(layerInfo.transform['Scale'].valueAtTime(time,false)[2]/100)],3); if(layerOb.threeD){ animData.tr.r[0] = extrasInstance.roundNumber((layerInfo.transform['X Rotation'].valueAtTime(time,false)+layerInfo.transform['Orientation'].valueAtTime(time,false)[0])*Math.PI/180,3); animData.tr.r[1] = extrasInstance.roundNumber(-(layerInfo.transform['Y Rotation'].valueAtTime(time,false)+layerInfo.transform['Orientation'].valueAtTime(time,false)[1])*Math.PI/180,3); animData.tr.r[2] = extrasInstance.roundNumber((layerInfo.transform['Rotation'].valueAtTime(time,false)+layerInfo.transform['Orientation'].valueAtTime(time,false)[2])*Math.PI/180,3); }else{ animData.tr.r[0] = 0; animData.tr.r[1] = 0; animData.tr.r[2] = extrasInstance.roundNumber(layerInfo.transform['Rotation'].valueAtTime(time,false)*Math.PI/180,3); } animData.tr.o = extrasInstance.roundNumber(layerInfo.transform['Opacity'].valueAtTime(time,false)/100,3); if(lType == 'ShapeLayer'){ ShapesParser.addFrameData(layerInfo,layerOb, frameNum, time); } if(lType == 'PreCompLayer'){ var compoInTime = -layerInfo.startTime; traverseAnimation(layerInfo.source,layerOb.layers, frameNum, time+compoInTime); } //THIS IS REPLACED WITH THE KEYFRAMES. LEAVE THIS FOR NOW. /*if(layerOb.lastData.an == null || extrasInstance.compareObjects(animData,layerOb.lastData.an)==false){ layerOb.an[frameNum] = animData; layerOb.lastData.an = animData; }*/ EffectsParser.renderFrame(layerOb,frameNum); } } function iterateComposition(){ createLayers(mainComp, mainLayers, mainComp.frameRate); // TO TRAVERSE LAYER BY LAYER. NEEDED FOR TIME REMAP? /*renderCompo(mainComp, mainLayers); AssetsManager.createAssetsDataForExport(); removeExtraData(mainLayers); processFinalData(mainLayers); callback.apply();*/ // END TO TRAVERSE LAYER BY LAYER. NEEDED FOR TIME REMAP? totalLayers = pendingLayers.length; extrasInstance.setTimeout(analyzeNextLayer,100); } function iterateLayer(layerInfo, layerOb,frameRate){ var duration =layerInfo.duration; layerOb.st = layerInfo.startTime; var frameNum = 0; var time = layerInfo.startTime; var lType = extrasInstance.layerType(layerInfo); if(lType == 'AudioLayer' || lType == 'CameraLayer' || (layerInfo.enabled == false && !layerInfo.isTrackMatte)){ //TODO add audios return; } while(frameNum < duration*frameRate){ var layerOb = layersData[i]; var animData = {}; if(layerOb.hasMask){ addMasksToLayer(layerInfo,animData,time); } animData.tr = {}; animData.tr.p = []; animData.tr.a = []; animData.tr.r = []; animData.tr.s = []; animData.tr.o = {}; if(layerOb.parent != null){ var parentSize = getParentSize(layerOb.parent,layersData); animData.tr.p[0] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[0],3); animData.tr.p[1] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[1],3); }else{ animData.tr.p[0] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[0],3); animData.tr.p[1] = extrasInstance.roundNumber(layerInfo.transform.position.valueAtTime(time,false)[1],3); } if(layerOb.threeD){ animData.tr.p[2] = extrasInstance.roundNumber(-layerInfo.transform.position.valueAtTime(time,false)[2],3); }else{ animData.tr.p[2] = -zCount; zCount++; } if(lType=='ShapeLayer'){ var r = layerInfo.sourceRectAtTime(frameNum, false); layerOb.rectData.l = extrasInstance.roundNumber(Math.min(r.left,layerOb.rectData.l),3); layerOb.rectData.t = extrasInstance.roundNumber(Math.min(r.top,layerOb.rectData.t),3); layerOb.rectData.r = extrasInstance.roundNumber(Math.max(r.left+r.width,layerOb.rectData.r),3); layerOb.rectData.b = extrasInstance.roundNumber(Math.max(r.top+r.height,layerOb.rectData.b),3); } animData.tr.a[0] = extrasInstance.roundNumber(layerInfo.transform['Anchor Point'].valueAtTime(time,false)[0],3); animData.tr.a[1] = extrasInstance.roundNumber(layerInfo.transform['Anchor Point'].valueAtTime(time,false)[1],3); animData.tr.a[2] = extrasInstance.roundNumber(-layerInfo.transform['Anchor Point'].valueAtTime(time,false)[2],3); animData.tr.s = extrasInstance.roundNumber([(layerInfo.transform['Scale'].valueAtTime(time,false)[0]/100),(layerInfo.transform['Scale'].valueAtTime(time,false)[1]/100),(layerInfo.transform['Scale'].valueAtTime(time,false)[2]/100)],3); if(layerOb.threeD){ animData.tr.r[0] = extrasInstance.roundNumber((layerInfo.transform['X Rotation'].valueAtTime(time,false)+layerInfo.transform['Orientation'].valueAtTime(time,false)[0])*Math.PI/180,3); animData.tr.r[1] = extrasInstance.roundNumber(-(layerInfo.transform['Y Rotation'].valueAtTime(time,false)+layerInfo.transform['Orientation'].valueAtTime(time,false)[1])*Math.PI/180,3); animData.tr.r[2] = extrasInstance.roundNumber((layerInfo.transform['Rotation'].valueAtTime(time,false)+layerInfo.transform['Orientation'].valueAtTime(time,false)[2])*Math.PI/180,3); }else{ animData.tr.r[0] = 0; animData.tr.r[1] = 0; animData.tr.r[2] = extrasInstance.roundNumber(layerInfo.transform['Rotation'].valueAtTime(time,false)*Math.PI/180,3); } animData.tr.o = extrasInstance.roundNumber(layerInfo.transform['Opacity'].valueAtTime(time,false)/100,3); if(lType == 'ShapeLayer'){ ShapesParser.addFrameData(layerInfo,layerOb, frameNum, time); } //THIS IS REPLACED WITH THE KEYFRAMES. BUT SHOULD BE USED FOR EXPRESSION LAYERS. if(layerOb.lastData.an == null || extrasInstance.compareObjects(animData,layerOb.lastData.an)==false){ layerOb.an[frameNum] = animData; layerOb.lastData.an = animData; } //END FOR EXPRESSION LAYERS EffectsParser.renderFrame(layerOb,frameNum); frameNum += 1; time += 1/frameRate; } //traverseAnimation(layerInfo.source,layerOb.layers, frameNum, time+compoInTime); if(lType == 'PreCompLayer'){ var i, len = layerInfo.source.layers.length; for(i = 0;i<len;i++){ iterateLayer(layerInfo.source.layers[i+1],layerOb.layers[i],layerInfo.source.frameRate); } } } function renderCompo(compo, mainLayers){ //var duration = compo.duration; var i, len = compo.layers.length; for(i = 0;i<len;i++){ iterateLayer(compo.layers[i+1],mainLayers[i],compo.frameRate); } } function renderNextFrame(){ /*if(currentRenderFrame < totalFrames && renderCancelled === false){ renderFrame(); currentRenderFrame +=1; renderNextFrame(); //extrasInstance.setTimeout(renderNextFrame,50); }else{ isRenderReady = true; checkRenderReady(); }*/ isRenderReady = true; checkRenderReady(); } function checkRenderReady(){ if(AsyncManager.getAsyncCounter() == 0 && isRenderReady == true){ AssetsManager.createAssetsDataForExport(); removeExtraData(mainLayers); processFinalData(mainLayers); callback.apply(); } } function renderFrame(){ currentTime = (currentRenderFrame+firstFrame)/frameRate; zCount = 0; traverseAnimation(mainComp,mainLayers, currentRenderFrame,currentTime); } function setCallback(cb){ callback = cb; } AsyncManager.setCallBack(checkRenderReady); var ob = {}; ob.getCompositionAnimationData = getCompositionAnimationData; ob.setCallback = setCallback; DOMAnimationManager = ob; }()); /****** END DOMAnimationMAnager ******/ /****** INIT Effects Parser ******/ (function(){ var ob = {}; var registeredEffects = {}; function createEffects(layerInfo,layerOb){ if(layerInfo.effect.numProperties>0){ layerOb.eff = []; var i, len = layerInfo.effect.numProperties, name; for(i=0;i<len;i++){ name = layerInfo.effect(i+1).name; if(registeredEffects[name] != null){ layerOb.eff.push({parser: registeredEffects[name], id:registeredEffects[name].registerElement(layerInfo.effect(i+1))}); } } } } function renderFrame(layerOb,frameNum){ if(layerOb.eff){ layerOb.eff.forEach(function(item){ item.parser.renderFrame(frameNum); }); } } function saveEffectData(layerOb){ if(layerOb.eff){ layerOb.eff = layerOb.eff.map(function(item){ return item.parser.getData(item.id); }); } } function registerEffect(name,object){ registeredEffects[name] = object; } ob.registerEffect = registerEffect; ob.createEffects = createEffects; ob.renderFrame = renderFrame; ob.saveEffectData = saveEffectData; EffectsParser = ob; }()); /****** END Effects Parser ******/ /****** INIT Effects Stroke Parser ******/ (function(){ var ob = {}; var registeredElements = []; var lastValues = {}; function renderFrame(frameNum, id){ var effectData = registeredElements[id]; var effectInfo = effectData.elem; for(var s in effectData.animated){ var propertyValue = getPropertyValue(effectInfo[s].value,getPropertyType(s)); if(lastValues[s] == null || !extrasInstance.compareObjects(propertyValue,lastValues[s])){ effectData.animated[s][frameNum] = propertyValue; lastValues[s] = propertyValue; } } } function getPropertyValue(value,type){ switch(type) { case 'color': return extrasInstance.arrayRgbToHex(value); break; default: return value; break; } } function getPropertyType(propertyName){ var i = 0;len = animatableProperties.length; while(i<len){ if(animatableProperties[i].name == propertyName){ return animatableProperties[i].type; } i++; } return ''; } function getData(id){ return registeredElements[id]; } function registerElement(elem){ var effectData = { type: 'Stroke', effectInfo : elem, effectDataPath : elem['Path'].value, allMasks : elem['All Masks'].value, strokeSequentially : elem['Stroke Sequentially'].value, animated: {}, singleValue: {} }; registeredElements.push(effectData); animatableProperties.forEach(function(item){ if(elem[item.name].numKeys == 0){ effectData.singleValue[item.name] = getPropertyValue(effectInfo[item.name].value, item.type); }else{ effectData.animated[item.name] = {}; } }); return registeredElements.length; } var animatableProperties = [{name:'Color',type:'color'},{name:'Brush Size',type:'simple'},{name:'Brush Hardness',type:'simple'},{name:'Opacity',type:'simple'},{name:'Start',type:'simple'},{name:'End',type:'simple'},{name:'Spacing',type:'simple'},{n