aeq = ( function ( aeq ) {
aeq.extend({
/**
* Gets all the item in a folder or project.
* @method
* @memberof aeq
* @param {FolderItem} [folder=app.project] The Folder to get items from.
* @param {boolean} [deep=true] When `true`, gets items from
* subfolders as well.
* @return {aeq.arrayEx} Array of Item objects
*/
getItems: function ( folder, deep ) {
// If no arguments are given, just return all items in project.
if ( folder === undefined ) {
return aeq.normalizeCollection( app.project.items );
}
deep = setDefault( deep, true );
folder = aeq.project.getFolder( folder );
if ( folder === null ) {
return aeq.arrayEx();
}
if ( deep ) {
return aeq.getItemsDeep( folder );
}
return aeq.normalizeCollection( folder.items );
},
/**
* Returns an {@link aeq.arrayEx} with all items in a folder, and items in
* subfolders.
* @method
* @param {FolderItem} folder The folder to flatten.
* @param {Boolean} returnArrayEx Included so we can skip the converting to
* arrayEx when recursing. It is not meant to
* be used outside of this function.
* @return {aeq.arrayEx} ArrayEx with Item objects.
*/
getItemsDeep: function ( folder, returnArrayEx ) {
var item,
items = [],
len = folder.items.length;
for ( var i = 1; i <= len; i++ ) {
item = folder.items[i];
if ( aeq.isFolderItem( item ) ) {
// Add all items in subfolder to the `items` array.
items.push.apply( items, aeq.getItemsDeep( item, false ) );
}
items.push( item );
}
// Skip converting to arrayEx when function is called by it self.
if ( returnArrayEx === false ) {
return items;
}
return aeq.arrayEx( items );
},
/**
* Gets the all layers where the given Item object is used as a source.
* @method
* @memberof aeq
* @param {Item} item The item to find in comps
* @return {aeq.arrayEx} Array of Layer objects
*/
getItemInComps: function ( item ) {
var layers = [];
aeq.forEach( item.usedIn, function ( comp ) {
aeq.forEachLayer( comp, function ( layer ) {
if ( layer.source === item ) {
layers.push( layer );
}
});
});
return aeq.arrayEx( layers );
},
/**
* Gets all the CompItems in the project. Or all CompItems in the given folder.
* @method
* @memberof aeq
* @param {FolderItem} [folder=app.project] The folder to get comps from.
* @param {boolean} [deep=true] Go through subfolders looking for comps.
* @return {aeq.arrayEx} Array of CompItems
*/
getCompositions: function ( folder, deep ) {
var items = aeq.getItems( folder, deep );
return items.filter( aeq.isComp );
},
/**
* Gets the active CompItem.
* This gets `app.project.activeItem` and verifies that it is a comp. If it
* not, it returns null.
* @method
* @memberof aeq
* @return {CompItem|null} The active comp, or null if there is none.
*/
getActiveComposition: function () {
var activeItem = app.project.activeItem;
if ( aeq.isComp( activeItem ) ) {
return activeItem;
}
return null;
},
/**
* Gets the CompItem with the matching name, or `null` if none is found.
* @method
* @memberof aeq
* @param {string} name The name of the comp to found
* @return {CompItem|null} The comp with the matching name, or null if
* none is found
*/
getComposition: function ( name ) {
var length = app.project.items.length;
for ( var i = 1; i <= length; i++ ) {
var item = app.project.item( i );
if ( item.name === name && aeq.isComp( item ) ) {
return item;
}
}
// If the function have not returned by now, there is no comp with that name
return null;
},
/**
* Gets all layers layers in a comp or an array of comps. This differs from
* `comp.layers` in that this returns an actual array. Instead of a colletion
* with a start index of 1.
* @method
* @memberof aeq
* @param {CompItem[]|CompItem} comps CompItem(s) to get layers from.
* @return {aeq.arrayEx} Layer objects in the comp(s)
*/
getLayers: function ( comps ) {
aeq.assertIsNotNull( comps, 'comps is null' );
var arr = [];
if ( aeq.isComp( comps ) ) {
comps = [ comps ];
}
for ( var c = 0; c < comps.length; c++ ) {
var comp = comps[c];
arr = arr.concat( aeq.normalizeCollection( comp.layers ) );
}
return aeq.arrayEx( arr );
},
/**
* Gets selected layers from a given comp or from the active comp if no comp is given.
* If there is no active comp, an empty array is returned.
* @method
* @memberof aeq
* @param {CompItem} [comp] The comp to get selected layers from.
* @return {aeq.arrayEx} Array of Layer objects.
*/
getSelectedLayers: function ( comp ) {
if ( !aeq.isComp( comp ) ) {
comp = aeq.getActiveComp();
}
if ( comp ) {
return aeq.arrayEx( comp.selectedLayers );
}
return aeq.arrayEx();
},
/**
* Gets selected layers, or all layers if none is selected, from a given comp
* or from the active comp if no comp is given. If there is no active comp,
* an empty array is returned.
* @method
* @memberof aeq
* @param {CompItem} [comp] Comp to get layers from
* @return {aeq.arrayEx} Array of Layer objects
*/
getSelectedLayersOrAll: function ( comp ) {
if ( !aeq.isComp( comp ) ) {
comp = aeq.getActiveComp();
if ( comp === null ) {
return aeq.arrayEx();
}
}
var layers = aeq.getSelectedLayers( comp );
if ( layers.length === 0 ) {
return aeq.getLayers( comp );
}
return layers;
},
/**
* Gets the selected properties on a layer or in a comp. Uses the active comp
* if no argument is given. If there is no active comp, an empty array is
* returned.
* @method
* @memberof aeq
* @param {CompItem|Layer} [obj] The object to get selected properties from.
* Defaults to the active comp.
* @return {aeq.arrayEx} Array of Property objects
*/
getSelectedProperties: function ( obj ) {
if ( !obj ) {
obj = aeq.getActiveComp();
}
if ( obj ) {
return aeq.arrayEx( obj.selectedProperties );
}
return aeq.arrayEx();
},
/**
* Gets all Property objects of all Layer objects in an array.
* @method
* @memberof aeq
* @param {Layer[]} layers Layer Objects to get properties from.
* @param {Object} [options] Options for the function.
* @param {boolean} [options.separate=true] set to true to separate properties
* (e.g separates Position into xPosition and yPosition).
* @param {boolean} [options.groups=false] set to true to include property groups.
* @param {boolean} [options.props=true] set to true to include properties.
* @return {aeq.arrayEx} Array of Property objects
*/
getProperties: function ( layers, options ) {
aeq.assertIsNotNull( layers, 'layer is null' );
options = setDefault( options, { separate: true });
var arr = [];
for ( var l = 0; l < layers.length; l++ ) {
var layer = layers[l];
arr = arr.concat( aeq.getPropertyChildren( layer, options ) );
}
return aeq.arrayEx( arr );
},
/**
* Gets all children of the given layer or propertyGroup. This is a recursive
* function, so it also gets grandchildren an so on.
* @method
* @memberof aeq
* @param {Layer|PropertyGroup} propertyParent Object to get properties from
* @param {Object} [options] Options for the function.
* @param {boolean} [options.separate=true] set to true to separate properties
* (e.g separates Position into xPosition and yPosition).
* @param {boolean} [options.groups=false] set to true to include property groups.
* @param {boolean} [options.props=true] set to true to include properties.
* @return {Array} Array of Property objects
*/
getPropertyChildren: function ( propertyParent, options ) {
var arr = [];
var property;
var len = propertyParent.numProperties;
options = setDefault( options, { separate: false });
for ( var i = 1; i <= len; i++ ) {
property = propertyParent.property( i );
switch ( property.propertyType ) {
case PropertyType.PROPERTY:
if ( options.separate ) {
property = normalizeProperty( propertyParent, property );
}
if ( options.props !== false ) { // On by defualt
arr.push( property );
}
break;
case PropertyType.INDEXED_GROUP:
case PropertyType.NAMED_GROUP:
if ( options.groups === true ) { // Off by default
arr.push( property );
}
arr = arr.concat( aeq.getPropertyChildren( property, options ) );
break;
default:
break;
}
}
return arr;
},
/**
* Gets the propertyGroups inside the effects group from all layers given.
* @method
* @memberof aeq
* @param {Layer[]|Layer} layers The Layer(s) to get effects from.
* @return {aeq.arrayEx} Array of PropertyGroup objects
*/
getEffects: function ( layers ) {
aeq.assertIsNotNull( layers, 'layers is null' );
if ( aeq.isLayer( layers ) ) {
layers = [ layers ];
}
var arr = [];
var len = layers.length;
var effects, effectslen;
for ( var l = 0; l < len; l++ ) {
effects = layers[l].property( 'ADBE Effect Parade' );
if ( effects === null ) {
continue;
}
effectslen = effects.numProperties;
for ( var e = 1; e <= effectslen; e++ ) {
arr.push( effects.property( e ) );
}
}
return aeq.arrayEx( arr );
},
/**
* Gets the Marker property group from the given layer or comp. If no object
* is given, the active comp is used. If there is no active comp, `null` is
* returned.
* Note: Marker groups for comps is only available for After Effects version
* 14.0 and later. If a comp is used in a earlier version. This function will
* return `null`
* @method
* @memberof aeq
* @param {Layer|CompItem} [obj] The object to get the marker group from.
* @return {MarkerPropertyGroup|null} Object marker group, or null if n/a
*/
getMarkerGroup: function ( obj ) {
if ( !obj ) {
obj = aeq.getActiveComp();
}
if ( aeq.isLayer( obj ) ) {
return obj.property( 'ADBE Marker' );
}
if ( aeq.isComp( obj ) && aeq.app.version >= 14.0 ) {
return obj.markerProperty;
}
return null;
},
/**
* Gets all keys on the given property or array of properties. Returns an
* aeq.Keys object which can be used to see all attributes of the key.
* @method
* @memberof aeq
* @param {Property|Property[]} property The Property or Properties to get
* keys from.
* @return {aeq.arrayEx} Array of aeq.Key objects.
*/
getKeys: function ( property ) {
var arr = [],
i, len;
if ( aeq.isArray( property ) ) {
for ( i = 0, len = property.length; i < len; i++ ) {
arr = arr.concat( aeq.getKeys( property[i] ) );
}
return aeq.arrayEx( arr );
}
for ( i = 1, len = property.numKeys; i <= len; i++ ) {
arr.push( aeq.Key( property, i ) );
}
return aeq.arrayEx( arr );
},
getChildren: function ( obj ) {
var ret;
if ( aeq.isComp( obj ) ) {
return aeq.normalizeCollection( obj.layers );
}
if ( aeq.isLayer( obj ) || aeq.isPropertyGroup( obj ) ) {
return aeq.getPropertyChildren( obj, {});
}
if ( aeq.isArray( obj ) ) {
ret = aeq.arrayEx();
aeq.forEach( obj, function ( item ) {
ret.push.apply( ret, aeq.getChildren( item ) );
});
return ret;
}
},
/**
* Collection arrays have indexes in the range `1-Collection.length`, which is
* usually not ideal when programming. This function takes a Collection object
* and converts it to a normal array.
* @method
* @memberof aeq
* @param {Collection} collection The Collection to convert
* @return {aeq.arrayEx} Normalized collection
*/
normalizeCollection: function ( collection ) {
// Because collection objects have a range [1...length], which is not ideal.
// This returns an array with all objects in the collection.
var ret = Array.prototype.slice.call( collection, 1 );
var len = collection.length;
// Because the last object is at index Collection.length and slice only goes up to
// length - 1, we have to push the last object to the return value
if ( len !== 0 ) {
ret.push( collection[len] );
}
return aeq.arrayEx( ret );
},
/**
* Converts frame count to time.
* @method
* @memberof aeq
* @param {number} frames Frame count to convert
* @param {number} frameRate FPS to convert with
* @return {number} Frame count in time
*/
framesToTime: function ( frames, frameRate ) {
return frames / frameRate;
},
/**
* Converts time to frame count.
* @method
* @memberof aeq
* @param {number} time Time to convert
* @param {number} frameRate FPS to convert with
* @return {number} Time in frames
*/
timeToFrames: function ( time, frameRate ) {
return time * frameRate;
}
});
// Short versions of some methods
/**
* @see aeq.getComposition
* @function
*/
aeq.getComp = aeq.getComposition;
/**
* @see aeq.getCompositions
* @function
*/
aeq.getComps = aeq.getCompositions;
/**
* @see aeq.getActiveComposition
* @function
*/
aeq.getActiveComp = aeq.activeComp = aeq.activeComposition = aeq.getActiveComposition;
/**
* @see aeq.getSelectedProperties
* @function
*/
aeq.getSelectedProps = aeq.getSelectedProperties;
/**
* @see aeq.getSelectedLayersOrAll
* @function
*/
aeq.getSelectedOrAllLayers = aeq.getSelectedLayersOrAll;
function normalizeProperty( propertyParent, property ) {
switch ( property.name ) {
case 'X Position':
case 'Y Position':
case 'Z Position':
property = propertyParent.property( 'Position' );
property.dimensionsSeparated = true;
return property.propertyGroup().property( property.name );
default:
return property;
}
}
return aeq;
}( aeq || {}) );