// ==================== |-------------------| ====================
// ==================== | Duik16_api-simple | ====================
// ==================== |-------------------| ====================
// ==================== |-------------------| ====================
// ==================== | Duik16_api-header | ====================
// ==================== |-------------------| ====================
/* License
Duik - Duduf IK Tools
Copyright (c) 2008 - 2020 Nicolas Dufresne, Rainbox Productions
https://rainboxlab.org
This file is part of Duik.
Duik is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Duik is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Duik. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* To use the Duik API, just include the API file in the beginning of your script.<br />
* Most of the methods work without any parameter but use the context (the active composition, the selected layers and properties).<br />
* If you need lower-level methods, for example being able to set an IK on specific layers or to wiggle specific properties,<br />
* you should use the {@link http://duaef-docs.rainboxlab.org/ | DuAEF Framework} - Duduf After Effects Framework, which Duik is based on.<br />
* A {@link http://duaef-reference.rainboxlab.org/ | complete reference of this framework is available here}.<br />
* The API is contained in the <code>Duik</code> object, and DuAEF is also made available in the <code>DuAEF</code> object.<br />
* @example
* //encapsulate everything to avoid global variables !important!
* (function(thisObj) {
* //include the API
* #include 'Duik16_api.jsxinc'
* //Now the Duik API is available in the Duik object, and DuAEF is also available.
*
* //We need to initialize DuAEF before using it. You must provide a script name and version.
* DuAEF.init("Your Awesome Script Name", "1.0.2");
*
* //Now you can create your UI if any, and initialize what you need.
* //DuAEF can be of great help, it has a lot of methods for creating the UI, handle After Effects, and more.
* //Read the reference at duaef-reference.rainboxlab.org
*
* //When everything is ready and before using the Duik API,
* //We need to tell DuAEF we're entering run state so it can finish to prepare its stuff.
* DuAEF.enterRunTime();
*
* // Create a hominoid structure
* // The whole API is contained in the Duik object
* Duik.structures.mammal();
* // Select all Structures
* Duik.structures.select();
* // Run the Autorig
* Duik.constraints.autorig();
* // Select all controllers
* Duik.controllers.select();
* // Make the character walk!
* Duik.automation.walk();
* //Have Fun!
* })(this);
* @author Nicolas Dufresne and contributors
* @copyright 2017 - 2020 Nicolas Dufresne, Rainbox Productions
* @version 16.2.27
* @license GPL-3.0 <br />
* Duik is free software: you can redistribute it and/or modify<br />
* it under the terms of the GNU General Public License as published by<br />
* the Free Software Foundation, either version 3 of the License, or<br />
* (at your option) any later version.<br />
*<br />
* Duik is distributed in the hope that it will be useful,<br />
* but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
* GNU General Public License for more details.<br />
*<br />
* You should have received a copy of the GNU General Public License<br />
* along with Duik. If not, see {@link http://www.gnu.org/licenses/}.
* @namespace
*/
var Duik = {};
// ==================== |----------------| ====================
// ==================== | Duik16_license | ====================
// ==================== |----------------| ====================
/* License
Duik - Duduf IK Tools
Copyright (c) 2008 - 2020 Nicolas Dufresne, Rainbox Productions
https://rainboxlab.org
__Contributors:__
Nicolas Dufresne - Lead developer
Kevin Masson - Developer
__Translations:__
eZioPan – Simplified Chinese
Ana Arce – Spanish
Adam Szczepański – Polish
René Andritsch - German
__Thanks to:__
Dan Ebberts - Writing the first IK Expressions
Eric Epstein - making the IK's work with 3D Layers
Kevin Schires – Including images in the script
Matias Poggini – Bezier IK feature
Eric Epstein - Making the IK's work with 3D Layers
Assia Chioukh and Quentin Saint-Georges – User Guides composition
Motion Cafe – Ideas and feedback
Fous d’anim – Ideas and feedback
__Duik makes use of:__
• x2js
Copyright (c) 2011-2013 Abdulla Abdurakhmanov
Original sources are available at https://code.google.com/p/x2js/
Licensed under the Apache License, Version 2.0
• json2
See http://www.JSON.org/js.html
Public Domain
• seedRandom
Copyright (c) David Bau
Licensed under the MIT license
• FFMpeg
See http://ffmpeg.org
• DuFFMpeg
Copyright (c) 2017 Nicolas Dufresne and Rainbox Productions
Sources available at https://github.com/Rainbox-dev/DuFFMpeg
Licensed under the GNU General Public License v3
This file is part of Duik.
Duik is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Duik is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Duik. If not, see <http://www.gnu.org/licenses/>.
*/// ==================== |---------------------| ====================
// ==================== | Duik16_api_required | ====================
// ==================== |---------------------| ====================
var standAlone = true;
//create a settings object
var settingsFile;
if (app.settings.haveSetting(DuAEF.scriptName,"settingsFile")) settingsFile = new File(app.settings.getSetting(DuAEF.scriptName,"settingsFile"));
var settings = new DuSettings(DuAEF.scriptName,settingsFile);// ==================== |----------------------| ====================
// ==================== | Duik16_api-functions | ====================
// ==================== |----------------------| ====================
// ==================== |-----------------------------| ====================
// ==================== | Duik16_automation_functions | ====================
// ==================== |-----------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/automations.html | Automations}<br />
* Read the {@link http://duik-docs.rainboxlab.org | Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/automations.html | Automations} for more information about each method.<br />
* <code>#include 'Duik16_automation_functions.jsxinc'</code>
* @namespace
*/
Duik.automation = {}
/**
* All the automation methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.automation.functions = []
//The functions
Duik.automation.functions.push( { name:"Effector", fn:"Duik.automation.effector()" } );
/**
* Creates an Effector
* @param {Layer} [effectorLayer] - An optional pre-existing effector
*/
Duik.automation.effector = function ( effectorLayer )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
effectorLayer = def( effectorLayer, DuAEF.Duik.getLayer(DuAEF.Duik.LayerTypes.EFFECTOR,true) );
DuAEF.DuAE.App.beginUndoGroup( "Effector" );
var effector = {};
//Check if there already is an effector in the selection
effector.effectorLayer = effectorLayer;
var layers = DuAEF.DuAE.Comp.unselectLayers();
if (layers.length == 0) return;
var it = new Iterator(layers);
it.do(function (layer)
{
effector.effect = null;
for ( var j = 0 ; j < layer.props.length ; j++)
{
effector = DuAEF.Duik.Automation.effector(layer.props[j],effector.effect,effector.effectorLayer);
}
});
if (effector) if (effector.effectorLayer) effector.effectorLayer.selected = true;
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Wiggle", fn:"Duik.automation.wiggle()" } );
/**
* Wiggle
* @param {boolean} [separateDimensions=false] - Wether to separate the dimensions to wiggle them with a different random seed.
* @param {boolean} [unifiedControl=true] - Wether to add a single control for all properties, or one for each
*/
Duik.automation.wiggle = function ( separateDimensions, unifiedControl )
{
separateDimensions = def ( separateDimensions, false );
unifiedControl = def ( unifiedControl, true );
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Wiggle");
var effect = null;
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0 ; i < props.length ; i++)
{
if ( !unifiedControl ) DuAEF.Duik.Automation.wiggle(props[i], separateDimensions );
else effect = DuAEF.Duik.Automation.wiggle(props[i], separateDimensions ,effect);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Spring", fn:"Duik.automation.spring()" } );
/**
* Spring
*/
Duik.automation.spring = function ( )
{
var effects = Duik.animation.klean(false, false, true, true, false);
if (effects.length == 0) return;
//deactivate the anticipation and the interpolation, and disable simulated mode
for (var i = 0, n = effects.length; i < n; i++)
{
var effect = effects[i];
effect(DuAEF.Duik.PseudoEffects.KLEANER.index['Anticipation_Checkbox']).setValue(0);
effect(DuAEF.Duik.PseudoEffects.KLEANER.index['Smart Interpolation_Checkbox']).setValue(0);
effect(DuAEF.Duik.PseudoEffects.KLEANER.index['Spatial Options_Mode_Popup']).setValue(1);
effect( DuAEF.Duik.PseudoEffects.KLEANER.index['Follow Through_Elasticity random_Slider'] ).setValue(0);
effect( DuAEF.Duik.PseudoEffects.KLEANER.index['Follow Through_Damping random_Slider'] ).setValue(0);
effect( DuAEF.Duik.PseudoEffects.KLEANER.index['Overlap (simulation)_Overlap random_Slider'] ).setValue(0);
}
}
Duik.automation.functions.push( { name:"Swing", fn:"Duik.automation.swing()" } );
/**
* Swing
*/
Duik.automation.swing = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Swing");
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0 ; i < props.length ; i++)
{
DuAEF.Duik.Automation.swing(props[i]);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Blink", fn:"Duik.automation.blink()" } );
/**
* Blink
*/
Duik.automation.blink = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Blink");
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0 ; i < props.length ; i++)
{
DuAEF.Duik.Automation.blink(props[i]);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Wheel", fn:"Duik.automation.wheel()" } );
/**
* Wheel
*/
Duik.automation.wheel = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("Wheel");
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0; i<layers.length ; i++)
{
DuAEF.Duik.Automation.wheel(layers[i]);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Move Away", fn:"Duik.automation.moveAway()" } );
/**
* Move Away
*/
Duik.automation.moveAway = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("Move Away");
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0; i<layers.length ; i++)
{
DuAEF.Duik.Automation.moveAway(layers[i]);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Paint Rig", fn:"Duik.automation.paintRig()" } );
/**
* Paint Rig
*/
Duik.automation.paintRig = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("Paint Rig");
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0; i<layers.length ; i++)
{
DuAEF.Duik.Automation.paintRig(layers[i]);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Walk Cycle", fn:"Duik.automation.walk()" } );
/**
* Procedural Walk Cycle<br />
* The method in the Duik API only automatically creates walk cycles with selected Duik Controllers.<br />
* To create a walk cycle on a custom rig, or a character rigged with another script/extension, use the {@link http://duaef-docs.rainboxlab.org/Framework-Reference/DuAEF.Duik.Automation.html#.walk | DuAEF API} instead with its lower level methods.
*/
Duik.automation.walk = function ( )
{
var ctrls = DuAEF.Duik.Controller.getControllers(undefined,true);
DuAEF.DuAE.App.beginUndoGroup("Walk cycle");
DuAEF.DuAE.Project.setProgressMode(true);
DuAEF.Duik.Automation.autoWalk(ctrls);
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.automation.functions.push( { name:"Looper", fn:"Duik.automation.loop()" } );
/**
* Looper
*/
Duik.automation.loop = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
var effect = null;
DuAEF.DuAE.App.beginUndoGroup("Looper");
var itProps = new Iterator(props);
itProps.do(function(prop)
{
effect = DuAEF.Duik.Automation.loop(prop,effect);
});
DuAEF.DuAE.App.endUndoGroup();
}// ==================== |------------------------------| ====================
// ==================== | Duik16_constraints_functions | ====================
// ==================== |------------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html | Constraints}<br />
* Read the {@link http://duik-docs.rainboxlab.org | Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html | Constraints} for more information about each method.<br />
* <code>#include 'Duik16_constraints_functions.jsxinc'</code>
* @namespace
*/
Duik.constraints = {}
/**
* All the constraints methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.constraints.functions = []
//The functions
Duik.constraints.functions.push( { name:"Auto-rig & IK", fn:"Duik.constraints.autorig()" } );
/**
* Auto-Rig & IK
* @param {boolean} [bakeStructures=true] - Wether to bake the structures after the Auto-rig has completed. Improves performance.
*/
Duik.constraints.autorig = function ( bakeStructures )
{
bakeStructures = def ( bakeStructures, true );
var layers = DuAEF.DuAE.Comp.unselectLayers();
if ( layers.length == 0 ) return;
//check if there are 3D Layers
for (var i = 0, n = layers.length; i < n; i++)
{
if (layers[i].threeDLayer)
{
alert(tr("Some of the selected layers are 3D, but the auto-rig can't rig 3D layers, sorry!"));
return;
}
}
DuAEF.DuAE.App.beginUndoGroup( "Autorig" );
DuAEF.DuAE.Project.setProgressMode( true );
DuAEF.Duik.Autorig.rig( layers, settings.data.autorigTailIK, !settings.data.ik3Layer );
if ( bakeStructures )
{
var structure = new Structure( layers );
structure.bakeAppearence();
}
DuAEF.DuAE.Project.setProgressMode( false );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"IK", fn:"Duik.constraints.ik()" } );
/**
* Create IK using selected layers
*/
Duik.constraints.ik = function ( )
{
var layers = DuAEF.DuAE.Comp.unselectLayers();
if (layers.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup( "IK" );
DuAEF.DuAE.Project.setProgressMode(true);
var ctrl = DuAEF.Duik.Rigging.ik(layers,null,false,!settings.data.ik3Layer);
if(ctrl.length > 1) ctrl = ctrl[1];
else ctrl = ctrl[0];
ctrl.layer.selected = true;
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Bézier IK", fn:"Duik.constraints.bezierIk()" } );
/**
* Create Bézier IK using selected layers
*/
Duik.constraints.bezierIk = function ( )
{
var layers = DuAEF.DuAE.Comp.unselectLayers();
if (layers.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup( "Bézier IK" );
DuAEF.DuAE.Project.setProgressMode(true);
var ctrl = DuAEF.Duik.Rigging.ik(layers,undefined,true);
ctrl[1].layer.selected = true;
DuAEF.DuAE.Project.setProgressMode(false);
app.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Connector", fn:"Duik.constraints.quickConnector()" } );
/**
* Quick Connector
*/
Duik.constraints.quickConnector = function ()
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if ( props.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup("Connector" );
DuAEF.Duik.Rigging.quickConnector( props );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Bones", fn:"Duik.constraints.bones()" } );
/**
* Add bones
* @param {boolean} [randomColor=false] - Wether to assign a random color to the bones
* @param {boolean} [tangents=true] - Wether to create bones for the tangents in case the selected property is a Bézier path
*/
Duik.constraints.bones = function ( randomColor, tangents )
{
randomColor = def( randomColor, false );
tangents = def( tangents, true );
var props = DuAEF.DuAE.Comp.getSelectedProps();
//just create a single bone without any prop
if (props.length == 0)
{
DuAEF.DuAE.App.beginUndoGroup( "Create bones" );
var bone = DuAEF.Duik.Bone.createBone();
bone.layer.selected = true;
DuAEF.DuAE.App.endUndoGroup();
return;
}
DuAEF.DuAE.App.beginUndoGroup( "Create bones" );
DuAEF.DuAE.Project.setProgressMode( true );
if ( randomColor ) DuAEF.Duik.Bone.color = DuAEF.DuJS.Color.random();
else if (settings.data.boneColor) DuAEF.Duik.Bone.color = DuAEF.DuJS.Color.hexToRGB( settings.data.boneColor );
var bones = [];
var itProps = new Iterator( props );
itProps.do( function( prop )
{
bones = bones.concat( DuAEF.Duik.Bone.addBone( prop, undefined, tangents ) );
} );
//if nothing was created
if ( bones.length == 0 )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var itLayers = new Iterator( layers );
//Try to find puppet pins
itLayers.do( function( layer )
{
var pins = DuAEF.DuAE.Layer.getPuppetPins( layer );
var itPins = new Iterator( pins );
itPins.do( function( pin )
{
bones.push( DuAEF.Duik.Bone.addBone( pin, undefined, tangents ) );
} );
} );
//Try any spatial property
if ( bones.length == 0 )
{
itProps.do( function( prop )
{
bones = bones.concat( DuAEF.Duik.Bone.addBones( prop, undefined, tangents ) );
} );
}
}
DuAEF.DuAE.Comp.selectLayers( bones );
DuAEF.DuAE.Project.setProgressMode( false );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Quick Parent", fn:"Duik.constraints.autoParent()" } );
Duik.constraints.functions.push( { name:"Quick Parent Orphans", fn:"Duik.constraints.autoParent(true)" } );
/**
* Auto-Parent. Parent selected layers to the last selected one.
* @param {boolean} [orphansOnly=false] - When true, parent only the orphans to the last selected layers
*/
Duik.constraints.autoParent = function ( orphansOnly )
{
orphansOnly = def(orphansOnly, false);
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
DuAEF.DuAE.App.beginUndoGroup( "Auto-parent layers" );
DuAEF.DuAE.Layer.parent( layers, undefined, orphansOnly );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Parent Constraint", fn:"Duik.constraints.parentConstraint()" } );
/**
* Parent Constraint
*/
Duik.constraints.parentConstraint = function ( )
{
var layers = DuAEF.DuAE.Comp.unselectLayers();
if ( layers.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup( "Parent link" );
for ( var i = 0; i < layers.length; i++ )
{
DuAEF.Duik.Rigging.parentConstraint( layers[ i ] );
}
DuAEF.DuAE.Comp.selectLayers( layers );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Path Constraint", fn:"Duik.constraints.pathConstraint()" } );
/**
* Path Constraint
* @param {Property} [path] - The path to use to constrain the selected layers.<br />
* If undefined, Duik will use the first path selected on the last selected layer.
* @return {boolean} True if a constraint was created, false if no path was found and nothing has been done
*/
Duik.constraints.pathConstraint = function ( path )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if ( !comp ) return false;
var layers = comp.selectedLayers;
if ( typeof path === 'undefined' && layers.length < 2) return false;
if ( typeof path === 'undefined' )
{
var pathLayer = layers.pop();
var pathProps = DuAEF.DuAE.Layer.getSelectedProps( pathLayer, PropertyValueType.SHAPE )
if (pathProps.length == 0) return false;
path = pathProps.pop();
}
DuAEF.DuAE.App.beginUndoGroup( "Path constraint" );
var it = new Iterator(layers);
it.do(function (layer) {
DuAEF.Duik.Rigging.pathConstraint( layer, path );
});
DuAEF.DuAE.App.endUndoGroup();
return true;
}
Duik.constraints.functions.push( { name:"Position Constraint", fn:"Duik.constraints.positionConstraint()" } );
/**
* Position Constraint
*/
Duik.constraints.positionConstraint = function ( )
{
var layers = DuAEF.DuAE.Comp.unselectLayers();
if ( layers.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup( "Orientation Constraint" );
for ( var i = 0; i < layers.length; i++ )
{
DuAEF.Duik.Rigging.positionConstraint( layers[ i ] );
}
DuAEF.DuAE.Comp.selectLayers( layers );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Orientation Constraint", fn:"Duik.constraints.orientationConstraint()" } );
/**
* Orientation Constraint
*/
Duik.constraints.orientationConstraint = function ( )
{
var layers = DuAEF.DuAE.Comp.unselectLayers();
if ( layers.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup( "Orientation Constraint" );
for ( var i = 0; i < layers.length; i++ )
{
DuAEF.Duik.Rigging.orientationConstraint( layers[ i ] );
}
DuAEF.DuAE.Comp.selectLayers( layers );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"List", fn:"Duik.constraints.list()" } );
/**
* List
*/
Duik.constraints.list = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup( "List" );
var layers = DuAEF.DuAE.Comp.unselectLayers();
for (var i = 0 ; i < props.length ; i++)
{
DuAEF.Duik.Automation.list(props[i]);
}
DuAEF.DuAE.Comp.selectLayers(layers);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Expose Transform", fn:"Duik.constraints.exposeTransform()" } );
/**
* Expose Transform
*/
Duik.constraints.exposeTransform = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("Expose Transform");
var layers = DuAEF.DuAE.Comp.unselectLayers();
var ctrls = [];
if (layers.length == 0) ctrls.push(DuAEF.Duik.Rigging.exposeTransform(comp));
else
{
for (var i = 0, num = layers.length ; i < num ; i++)
{
var ctrl = DuAEF.Duik.Rigging.exposeTransform(comp,layers[i]);
ctrls.push(ctrl);
}
}
DuAEF.DuAE.Comp.selectLayers(ctrls);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Zero", fn:"Duik.constraints.zero()" } );
/**
* Add Zero
*/
Duik.constraints.zero = function ( )
{
DuAEF.DuAE.Comp.doSelectedLayers( DuAEF.Duik.Rigging.addZero, "Add zero" );
}
Duik.constraints.functions.push( { name:"Reset Transform (PRS)", fn:"Duik.constraints.resetPRS()" } );
/**
* Reset Transform (set to Zero)
*/
Duik.constraints.resetPRS = function ( )
{
DuAEF.DuAE.Comp.doSelectedLayers( DuAEF.Duik.Animation.resetPRS, "Reset PRS" );
}
Duik.constraints.functions.push( { name:"Lock Property", fn:"Duik.constraints.lockProperty()" } );
/**
* Lock Property
*/
Duik.constraints.lockProperty = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if ( props.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup( "Lock properties" );
DuAEF.DuAE.Property.lock( props );
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Separate Dimensions", fn:"Duik.constraints.separateDimensions()" } );
/**
* Separate Dimensions
*/
Duik.constraints.separateDimensions = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if ( props.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup( "Separate dimensions" );
for ( var i = 0, num = props.length; i < num; i++ )
{
DuAEF.Duik.Rigging.separateDimensions( props[ i ] );
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Locator", fn:"Duik.constraints.locator()" } );
/**
* Add Locator
*/
Duik.constraints.locator = function ( )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
DuAEF.DuAE.App.beginUndoGroup( "Add Locator(s)" );
if ( layers.length )
{
new Iterator( layers ).do( function( layer )
{
DuAEF.Duik.Rigging.addLocator( layer );
} );
}
else
{
DuAEF.Duik.Rigging.addLocator();
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.constraints.functions.push( { name:"Extract Locators", fn:"Duik.constraints.extractLocators()" } );
/**
* Extract Locators
* @param {boolean} [useMasterProperties=true] - Wether to use master properties instead of expressions to extract the controllers. True by default if Ae >= 17.0
*/
Duik.constraints.extractLocators = function ( useMasterProperties )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
if ( layers.length == 0 ) return;
DuAEF.DuAE.App.beginUndoGroup( "Extract Locators" );
new Iterator( layers ).do( function( layer )
{
DuAEF.Duik.Rigging.extractLocators( layer, useMasterProperties );
} );
DuAEF.DuAE.App.endUndoGroup();
}// ==================== |-----------------------------| ====================
// ==================== | Duik16_structures_functions | ====================
// ==================== |-----------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/structures.html | Structures}<br />
* Read the {@link http://duik-docs.rainboxlab.org | Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/structures.html | Structures} for more information about each method.<br />
* <code>#include 'Duik16_structures_functions.jsxinc'</code>
* @namespace
*/
Duik.structures = {}
/**
* All the structure methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.structures.functions = []
//The functions
//TODO adjust autorig for animals/quadrupeds
Duik.structures.functions.push( { name:"Hominoid", fn:"Duik.structures.mammal()" } );
Duik.structures.functions.push( { name:"Digitigrade", fn:"Duik.structures.mammal( DuAEF.Duik.Autorig.AnimalTypes.DIGITIGRADE )" } );
Duik.structures.functions.push( { name:"Ungulate", fn:"Duik.structures.mammal( DuAEF.Duik.Autorig.AnimalTypes.Ungulate )" } );
Duik.structures.functions.push( { name:"Plantigrade", fn:"Duik.structures.mammal( DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE , 2, 1, true, true, true, true, true, true, true)" } );
/**
* Creates a structure for a mammal
* @param {DuAEF.Duik.Autorig.AnimalTypes} [type=DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE] - One of DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE, DuAEF.Duik.Autorig.AnimalTypes.DIGITIGRADE, DuAEF.Duik.Autorig.AnimalTypes.UNGULATE. See the {@link http://duaef-reference.rainboxlab.org/ | DuAEF Reference}
* @param {int} [numSpine=2] - The number of structure elements for the spine
* @param {int} [numNeck=1] - The number of structure elements for the neck
* @param {boolean} [head=true] - Wether to add a structure element for a head
* @param {boolean} [shoulder=true] - Wether to add a structure element for shouders
* @param {boolean} [humerus=true] - Wether to add a structure element for humerus
* @param {boolean} [radius=true] - Wether to add a structure element for radius
* @param {boolean} [hand=true] - Wether to add a structure element for hands
* @param {boolean} [frontClaws=false] - Wether to add a structure element for frontClaws. True by default if the structure is not for a Plantigrade.
* @param {boolean} [femur=true] - Wether to add a structure element for femurs
* @param {boolean} [tibia=true] - Wether to add a structure element for tibias
* @param {boolean} [foot=true] - Wether to add a structure element for feet
* @param {boolean} [backClaws=false] - Wether to add a structure element for backClaws. True by default if the structure is not for a Plantigrade.
* @return {Array} An array containing two arrays: the first one is the list of Structure objects created (see the {@link http://duaef-reference.rainboxlab.org/ | DuAEF Reference}), the second one is the list of the new layers.
*/
Duik.structures.mammal = function (type, numSpine, numNeck, hips, head, shoulder, humerus, radius, hand, frontClaws, femur, tibia, foot, backClaws)
{
//defaults
type = def( type, DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE );
numSpine = def( numSpine, 2);
numNeck = def( numNeck, 1);
hips = def( hips, true);
head = def( head, true);
shoulder = def( shoulder, true );
humerus = def( humerus, true );
radius = def( radius, true );
hand = def( hand, true );
if ( type == def( type, DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE ) )
{
frontClaws = def( frontClaws, false);
}
else
{
frontClaws = def( frontClaws, true);
}
femur = def( femur, true );
tibia = def( tibia, true );
foot = def( foot, true );
backClaws = def( backClaws, true );
var comp = DuAEF.DuAE.Project.getActiveComp();
if ( !comp ) return [];
var sizeUnit = comp.height / 12;
DuAEF.DuAE.App.beginUndoGroup( "Create hominoid structure" );
DuAEF.DuAE.Project.setProgressMode( true );
var structureLayers = [];
var structures = [];
//SPINE
var originPos = [ comp.width / 2, comp.height / 2 + sizeUnit ];
var structure = DuAEF.Duik.Structure.createSpine( hips, numSpine, numNeck, head, comp, originPos );
structure = structure[ 0 ];
structureLayers = structureLayers.concat( structure.elements );
structures.push( structure );
DuAEF.DuAE.Comp.unselectLayers( comp );
//LEFT ARM
originPos = [ comp.width / 2 - sizeUnit, 4 * sizeUnit ];
if ( shoulder ) originPos = [ comp.width / 2 - sizeUnit / 2, 4 * sizeUnit ];
structure = DuAEF.Duik.Structure.createArm( shoulder, humerus, radius, hand, false, undefined, type, comp, originPos );
structure = structure[ 0 ];
structureLayers = structureLayers.concat( structure.elements );
structures.push( structure );
DuAEF.DuAE.Comp.unselectLayers( comp );
//RIGHT ARM
originPos = [ comp.width / 2 + sizeUnit, 4 * sizeUnit ];
if ( shoulder ) originPos = [ comp.width / 2 + sizeUnit / 2, 4 * sizeUnit ];
structure = DuAEF.Duik.Structure.createArm( shoulder, humerus, radius, hand, false, undefined, type, comp, originPos, true );
structure = structure[ 0 ];
structureLayers = structureLayers.concat( structure.elements );
structures.push( structure );
DuAEF.DuAE.Comp.unselectLayers( comp );
//LEFT LEG
originPos = [ comp.width / 2 - sizeUnit / 2, comp.height / 2 + sizeUnit ];
structure = DuAEF.Duik.Structure.createLeg( femur, tibia, foot, backClaws, undefined, type, comp, originPos );
structure = structure[ 0 ];
structureLayers = structureLayers.concat( structure.elements );
structures.push( structure );
DuAEF.DuAE.Comp.unselectLayers( comp );
//RIGHT LEG
originPos = [ comp.width / 2 + sizeUnit / 2, comp.height / 2 + sizeUnit ];
structure = DuAEF.Duik.Structure.createLeg( femur, tibia, foot, backClaws, undefined, type, comp, originPos );
structure = structure[ 0 ];
structureLayers = structureLayers.concat( structure.elements );
structures.push( structure );
DuAEF.DuAE.App.endUndoGroup( );
DuAEF.DuAE.Project.setProgressMode(false);
return [structures, structureLayers];
}
Duik.structures.functions.push( { name:"Arm", fn:"Duik.structures.arm()" } );
Duik.structures.functions.push( { name:"Arm_Digitigrade", fn:"Duik.structures.arm(DuAEF.Duik.Autorig.AnimalTypes.DIGITIGRADE)" } );
Duik.structures.functions.push( { name:"Arm_Ungulate", fn:"Duik.structures.arm(DuAEF.Duik.Autorig.AnimalTypes.UNGULATE)" } );
Duik.structures.functions.push( { name:"Arm_Plantigrade", fn:"Duik.structures.arm(DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE, true, true, true, true, true)" } );
/**
* Creates a structure for an arm/front leg.
* @param {DuAEF.Duik.Autorig.AnimalTypes} [type=DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE] - One of DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE, DuAEF.Duik.Autorig.AnimalTypes.DIGITIGRADE, DuAEF.Duik.Autorig.AnimalTypes.UNGULATE. See the {@link http://duaef-reference.rainboxlab.org/ | DuAEF Reference}
* @param {boolean} [shoulder=true] - Wether to add a structure element for the shouder
* @param {boolean} [humerus=true] - Wether to add a structure element for the humerus
* @param {boolean} [radius=true] - Wether to add a structure element for the radius
* @param {boolean} [hand=true] - Wether to add a structure element for the hand
* @param {boolean} [frontClaws=false] - Wether to add a structure element for the front claws. True by default if the structure is not for a Plantigrade.
* @param {boolean} [forceLink=false] - Wether link the selected layers/properties to the new structures
*/
Duik.structures.arm = function ( type, shoulder, humerus, radius, hand, claws, forceLink)
{
forceLink = def( forceLink, false);
type = def( type, DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE);
shoulder = def( shoulder, true);
humerus = def( humerus, true);
radius = def( radius, true);
hand = def( hand, true);
if (type == DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE) claws = def( claws, false);
else claws = def( claws, true);
DuAEF.DuAE.App.beginUndoGroup("Create arm structure");
DuAEF.DuAE.Project.setProgressMode(true);
//if we have a shape layer selected and its path, and only a path, we're going to remove it after creation.
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var layerToRemove = null;
var linkPath = false;
if (typeof settings.data.structureLinkPaths !== 'undefined')
{
linkPath = settings.data.structureLinkPaths;
if (forceLink) linkPath = !settings.data.structureLinkPaths;
}
if (layers.length == 1 && !linkPath)
{
var l = layers[0];
if (DuAEF.DuAE.Shape.isSingleShape(l)) layerToRemove = l;
}
DuAEF.Duik.Structure.createArm(shoulder, humerus, radius, hand, claws,undefined,type,undefined, undefined, undefined, forceLink);
if (layerToRemove != null) layerToRemove.remove();
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Leg", fn:"Duik.structures.leg()" } );
Duik.structures.functions.push( { name:"Leg_Digitigrade", fn:"Duik.structures.leg(DuAEF.Duik.Autorig.AnimalTypes.DIGITIGRADE)" } );
Duik.structures.functions.push( { name:"Leg_Ungulate", fn:"Duik.structures.leg(DuAEF.Duik.Autorig.AnimalTypes.UNGULATE)" } );
Duik.structures.functions.push( { name:"Leg_Plantigrade", fn:"Duik.structures.leg(DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE, true, true, true, true)" } );
/**
* Creates a structure for an arm/back leg.
* @param {DuAEF.Duik.Autorig.AnimalTypes} [type=DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE] - One of DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE, DuAEF.Duik.Autorig.AnimalTypes.DIGITIGRADE, DuAEF.Duik.Autorig.AnimalTypes.UNGULATE. See the {@link http://duaef-reference.rainboxlab.org/ | DuAEF Reference}
* @param {boolean} [femur=true] - Wether to add a structure element for the femur
* @param {boolean} [tibia=true] - Wether to add a structure element for the tibia
* @param {boolean} [foot=true] - Wether to add a structure element for the foot
* @param {boolean} [frontClaws=false] - Wether to add a structure element for the back claws. True by default if the structure is not for a Plantigrade.
* @param {boolean} [forceLink=false] - Wether link the selected layers/properties to the new structures
*/
Duik.structures.leg = function ( type, femur, tibia, foot, claws, forceLink)
{
forceLink = def( forceLink, false);
type = def( type, DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE);
femur = def( femur, true);
tibia = def( tibia, true);
foot = def( foot, true);
if (type == DuAEF.Duik.Autorig.AnimalTypes.PLANTIGRADE) claws = def( claws, false);
else claws = def( claws, true);
DuAEF.DuAE.App.beginUndoGroup("Create leg structure");
DuAEF.DuAE.Project.setProgressMode(true);
//if we have a shape layer selected and its path, and only a path, we're going to remove it after creation.
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var layerToRemove = null;
var linkPath = false;
if (typeof settings.data.structureLinkPaths !== 'undefined')
{
linkPath = settings.data.structureLinkPaths;
if (forceLink) linkPath = !settings.data.structureLinkPaths;
}
if (layers.length == 1 && !linkPath)
{
var l = layers[0];
if (DuAEF.DuAE.Shape.isSingleShape(l)) layerToRemove = l;
}
DuAEF.Duik.Structure.createLeg( femur, tibia, foot, claws,undefined,type, undefined, undefined, forceLink);
if (layerToRemove != null) layerToRemove.remove();
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Spine", fn:"Duik.structures.spine()" } );
/**
* Creates a structure for a spine, neck and head.
* @param {int} [numSpine=2] - The number of structure elements for the spine
* @param {int} [numNeck=1] - The number of structure elements for the neck
* @param {boolean} [head=true] - Wether to add a structure element for a head
* @param {boolean} [forceLink=false] - Wether link the selected layers/properties to the new structures
*/
Duik.structures.spine = function ( numSpine, numNeck, hips, head, forceLink )
{
forceLink = def( forceLink, false);
numSpine = def( numSpine, 2);
numNeck = def( numNeck, 1);
hips = def( hips, true);
head = def( head, true);
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("Create spine structure");
DuAEF.DuAE.Project.setProgressMode(true);
//if we have a shape layer selected and its path, and only a path, we're going to remove it after creation.
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var layerToRemove = null;
var linkPath = false;
if (typeof settings.data.structureLinkPaths !== 'undefined')
{
linkPath = settings.data.structureLinkPaths;
if (forceLink) linkPath = !settings.data.structureLinkPaths;
}
if (layers.length == 1 && !linkPath)
{
var l = layers[0];
if (DuAEF.DuAE.Shape.isSingleShape(l)) layerToRemove = l;
}
DuAEF.Duik.Structure.createSpine(hips ,numSpine,numNeck, head, undefined, undefined, forceLink);
if (layerToRemove != null) layerToRemove.remove();
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Tail", fn:"Duik.structures.tail()" } );
/**
* Creates a structure for a tail.
* @param {int} [numTail=3] - The number of structure elements for the tail
* @param {boolean} [forceLink=false] - Wether link the selected layers/properties to the new structures
*/
Duik.structures.tail = function ( numTail, forceLink )
{
forceLink = def( forceLink, false);
numTail = def( numTail, 3);
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("Create tail structure");
DuAEF.DuAE.Project.setProgressMode(true);
//if we have a shape layer selected and its path, and only a path, we're going to remove it after creation.
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var layerToRemove = null;
var linkPath = false;
if (typeof settings.data.structureLinkPaths !== 'undefined')
{
linkPath = settings.data.structureLinkPaths;
if (forceLink) linkPath = !settings.data.structureLinkPaths;
}
if (layers.length == 1 && !linkPath)
{
var l = layers[0];
if (DuAEF.DuAE.Shape.isSingleShape(l)) layerToRemove = l;
}
DuAEF.Duik.Structure.createTail(numTail, undefined, forceLink);
if (layerToRemove != null) layerToRemove.remove();
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Custom Structures", fn:"Duik.structures.custom()" } );
/**
* Creates custom structures.
* @param {int} [num=3] - The number of structure elements
* @param {string} [name='Structure'] - The name of the Structure
* @param {boolean} [forceLink=false] - Wether link the selected layers/properties to the new structures
* @param {boolean} [randomColor=false] - Wether pick a random color for the new Structure
*/
Duik.structures.custom = function ( num, name, forceLink, randomColor )
{
randomColor = def( randomColor, false);
num = def( num, 1);
forceLink = def( forceLink, false);
name = def( name, 'Structure');
//get current comp
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var pColor = DuAEF.Duik.Structure.color;
if (randomColor) DuAEF.Duik.Structure.color = DuAEF.DuJS.Color.Colors.RANDOM;
DuAEF.DuAE.App.beginUndoGroup("Create structure");
DuAEF.DuAE.Project.setProgressMode(true);
//if we have a shape layer selected and its path, and only a path, we're going to remove it after creation.
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var layerToRemove = null;
var linkPath = settings.data.structureLinkPaths;
if (forceLink) linkPath = !settings.data.structureLinkPaths;
if (layers.length == 1 && !linkPath)
{
var l = layers[0];
if (DuAEF.DuAE.Shape.isSingleShape(l)) layerToRemove = l;
}
DuAEF.Duik.Structure.addStructures(num, comp, name, false, forceLink);
if (layerToRemove != null) layerToRemove.remove();
DuAEF.DuAE.Project.setProgressMode(false);
DuAEF.DuAE.App.endUndoGroup();
DuAEF.Duik.Structure.color = pColor;
}
Duik.structures.functions.push( { name:"Show / Hide all structures", fn:"Duik.structures.show()" } );
/**
* Shows/Hides all structures.
* @param {boolean} [invert=false] - Wether invert the structure visibility instead of showing/hiding all
*/
Duik.structures.show = function ( invert )
{
invert = def( invert, false);
var structures = DuAEF.Duik.Structure.getStructureLayers();
if (structures.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Show/hide structures");
var visible = !structures[0].enabled;
for (var i = 0 ; i < structures.length ; i++)
{
if (invert) structures[i].enabled = !structures[i].enabled;
else structures[i].enabled = visible;
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Edit Mode", fn:"Duik.structures.edit()" } );
/**
* Toggles edit mode.
*/
Duik.structures.edit = function ( )
{
//get from first element
var structures = DuAEF.Duik.Structure.getStructures(undefined,DuAEF.Duik.Structure.SelectionModes.ELEMENT);
DuAEF.DuAE.App.beginUndoGroup("Edit structures");
for (var i = 0 ; i < structures.length ; i++)
{
structures[i].toggleEditMode();
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Select all structures", fn:"Duik.structures.select()" } );
/**
* Selects all structures.
*/
Duik.structures.select = function ( )
{
DuAEF.DuAE.App.beginUndoGroup("Select structures");
DuAEF.Duik.Structure.selectStructures(undefined, DuAEF.Duik.Structure.SelectionModes.ALL);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.structures.functions.push( { name:"Duplicate structures", fn:"Duik.structures.duplicate()" } );
/**
* Duplicates selected structures.
*/
Duik.structures.duplicate = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var structures;
if (comp.selectedLayers.length == 0) structures = DuAEF.Duik.Structure.getStructures(comp, DuAEF.Duik.Structure.SelectionModes.ALL);
else structures = DuAEF.Duik.Structure.getStructures(comp, DuAEF.Duik.Structure.SelectionModes.ELEMENT);
if (structures.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Duplicate structures");
var autorigIds = [];
var newStructures = [];
var it = new Iterator(structures);
it.do(function(structure)
{
var newStructure = structure.duplicate();
newStructures.push(newStructure);
//adjust autorig id
if (newStructure.elements.length > 0)
{
var element = newStructure.elements[0];
var params = DuAEF.Duik.getDuikMarkerParameters(element);
var newAutorigId = -1;
var autorigId = -1;
if (params[DuAEF.Duik.MarkerParameters.AUTORIG_ID]) autorigId = params[DuAEF.Duik.MarkerParameters.AUTORIG_ID];
else return;
for (var i = 0, num = autorigIds.length; i < num; i++)
{
if (autorigIds[i][0] == autorigId) newAutorigId = autorigIds[i][1];
}
if (newAutorigId == -1)
{
newAutorigId = new Date().getTime();
autorigIds.push([autorigId,newAutorigId]);
}
var itElements = new Iterator(structure.elements);
itElements.do(function(elmt)
{
DuAEF.Duik.setDuikMarkerParameter(elmt,DuAEF.Duik.MarkerParameters.AUTORIG_ID,newAutorigId);
});
}
});
//select all structures
var itNew = new Iterator(newStructures);
itNew.do(function(structure)
{
structure.select();
});
DuAEF.DuAE.App.endUndoGroup();
}// ==================== |------------------------------| ====================
// ==================== | Duik16_controllers_functions | ====================
// ==================== |------------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/automations.html Controllers}<br />
* Read the {@link http://duik-docs.rainboxlab.org | Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/automations.html Controllers} for more information about each method.<br />
* <code>#include 'Duik16_controllers_functions.jsxinc'</code>
* @namespace
*/
Duik.controllers = {}
/**
* All the controller methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.controllers.functions = []
//The functions
Duik.controllers.functions.push( { name:"Rotation", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.ROTATION)" } );
Duik.controllers.functions.push( { name:"X_Position", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.X_POSITION)" } );
Duik.controllers.functions.push( { name:"Y_Position", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.Y_POSITION)" } );
Duik.controllers.functions.push( { name:"Position", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.POSITION)" } );
Duik.controllers.functions.push( { name:"Transform", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.TRANSFORM)" } );
Duik.controllers.functions.push( { name:"Eye", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.EYE)" } );
Duik.controllers.functions.push( { name:"Camera", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.CAMERA)" } );
Duik.controllers.functions.push( { name:"Slider", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.SLIDER)" } );
Duik.controllers.functions.push( { name:"2D_Slider", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.DOUBLE_SLIDER)" } );
Duik.controllers.functions.push( { name:"Angle", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.ANGLE)" } );
Duik.controllers.functions.push( { name:"Head", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.HEAD)" } );
Duik.controllers.functions.push( { name:"Foot", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.FOOT)" } );
Duik.controllers.functions.push( { name:"Claws", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.CLAWS)" } );
Duik.controllers.functions.push( { name:"Hoof", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.HOOF)" } );
Duik.controllers.functions.push( { name:"Hand", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.HAND)" } );
Duik.controllers.functions.push( { name:"Hips", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.HIPS)" } );
Duik.controllers.functions.push( { name:"Spine", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.BODY)" } );
Duik.controllers.functions.push( { name:"Shoulders", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.SHOULDERS)" } );
Duik.controllers.functions.push( { name:"Tail", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.TAIL)" } );
Duik.controllers.functions.push( { name:"Null", fn:"Duik.controllers.create(DuAEF.Duik.Controller.Types.NULL)" } );
/**
* Creates an controller
* @param {DuAEF.Duik.Controller.Types} [type = DuAEF.Duik.Controller.Types.TRANSFORM] - The type of the controller. See the {@link http://duaef-reference.rainboxlab.org DuAEF} reference for more information.
* @param {boolean} [parent = false] - Wether to parent the selected layers to the controllers
* @param {boolean} [single = false] - Wether to create a single controller for all the layers
* @return {Controller[]} the controllers created. See the {@link http://duaef-reference.rainboxlab.org DuAEF} reference for more information about the <code>Controller</code> object.
*/
Duik.controllers.create = function ( type, parent, single )
{
type = def( type, DuAEF.Duik.Controller.Types.TRANSFORM);
parent = def (parent, false);
single = def (single, false);
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return null;
DuAEF.DuAE.App.beginUndoGroup( "Create controller");
var layers = DuAEF.DuAE.Comp.unselectLayers();
var ctrls = [];
if (layers.length == 0) ctrls.push(DuAEF.Duik.Controller.create(comp,type));
else if (single)
{
var ctrl = DuAEF.Duik.Controller.create(comp,type,layers, undefined, undefined, parent);
ctrls.push(ctrl.layer);
}
else
{
for (var i = 0 ; i < layers.length ; i++)
{
var ctrl = DuAEF.Duik.Controller.create(comp,type,layers[i], undefined, undefined, parent);
ctrls.push(ctrl.layer);
}
}
DuAEF.DuAE.Comp.selectLayers(ctrls);
DuAEF.DuAE.App.endUndoGroup();
return ctrls;
}
Duik.controllers.functions.push( { name:"PE_Eye", fn:"Duik.controllers.pseudoEffect(DuAEF.Duik.PseudoEffects.EYES)" } );
Duik.controllers.functions.push( { name:"PE_Fingers", fn:"Duik.controllers.pseudoEffect(DuAEF.Duik.PseudoEffects.FINGERS)" } );
Duik.controllers.functions.push( { name:"PE_Hand", fn:"Duik.controllers.pseudoEffect(DuAEF.Duik.PseudoEffects.HAND)" } );
Duik.controllers.functions.push( { name:"PE_Head", fn:"Duik.controllers.pseudoEffect(DuAEF.Duik.PseudoEffects.HEAD)" } );
/**
* Adds a controller pseudo effect on the selected layers
* @param {DuAEF.Duik.Controller.Types} type - The type of pseudo effect, one of: EYES, FINGERS, HAND, HEAD. See the {@link http://duaef-reference.rainboxlab.org DuAEF} reference for more information.
*/
Duik.controllers.pseudoEffect = function ( type )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
DuAEF.DuAE.App.beginUndoGroup("Add Pseudo-Effect");
for (var i = 0, num = layers.length; i < num; i++)
{
//add effect
DuAEF.DuAE.Layer.applyPreset(layers[i],type);
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.controllers.functions.push( { name:"Select all", fn:"Duik.controllers.select()" } );
/**
* Selects all controllers in the composition
*/
Duik.controllers.select = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var ctrls = DuAEF.Duik.Controller.getControllers(comp,false);
if (ctrls.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Select controllers");
DuAEF.DuAE.Comp.unselectLayers(comp);
for (var i = 0 ; i < ctrls.length ; i++)
{
ctrls[i].layer.selected = true;
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.controllers.functions.push( { name:"Show / Hide", fn:"Duik.controllers.show()" } );
/**
* Shows or hides all controllers in the composition
* @param {boolean} [invert=false] - If true, inverts the controller visibilities
*/
Duik.controllers.show = function ( invert )
{
invert = def (invert, false);
var ctrls = DuAEF.Duik.Controller.getControllers();
if (ctrls.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Show/hide controllers");
var visible = !ctrls[0].layer.enabled;
for (var i = 0 ; i < ctrls.length ; i++)
{
if (invert) ctrls[i].layer.enabled = !ctrls[i].layer.enabled;
else ctrls[i].layer.enabled = visible;
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.controllers.functions.push( { name:"Extract", fn:"Duik.controllers.extract()" } );
/**
* Extracts the controllers from the selected precomposition
* @param {boolean} [useMasterProperties=true] - Wether to use master properties instead of expressions to extract the controllers. True by default if Ae >= 17.0
*/
Duik.controllers.extract = function ( useMasterProperties )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var layers = comp.selectedLayers;
if (layers.length == 0) return;
var precomp = layers[0];
DuAEF.DuAE.App.beginUndoGroup("Extract Controllers");
var result = DuAEF.Duik.Animation.extractControllersFromComp(precomp,useMasterProperties);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.controllers.functions.push( { name:"Un-Extract", fn:"Duik.controllers.unExtract()" } );
/**
* Un-Extracts the controllers from the selected precomposition
*/
Duik.controllers.unExtract = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var layers = comp.selectedLayers;
if (layers.length == 0) return;
var precomp = layers[0];
DuAEF.DuAE.App.beginUndoGroup("Un-Extract Controllers");
var result = DuAEF.Duik.Animation.unExtractControllersFromComp(precomp);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.controllers.functions.push( { name:"Tag", fn:"Duik.controllers.tag()" } );
/**
* Tags the layers as controllers
*/
Duik.controllers.tag = function ( )
{
DuAEF.DuAE.App.beginUndoGroup("Tag controllers");
DuAEF.Duik.Controller.tag();
DuAEF.DuAE.App.endUndoGroup();
}// ==================== |------------------------| ====================
// ==================== | Duik16_tools_functions | ====================
// ==================== |------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html Tools}<br />
* Read the {@link http://duik-docs.rainboxlab.org Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html Tools} for more information about each method.<br />
* <code>#include 'Duik16_tools_functions.jsxinc'</code>
* @namespace
*/
Duik.tools = {}
/**
* All the tools methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.tools.functions = []
//The functions
Duik.tools.functions.push( { name:"Align layers", fn:"Duik.tools.align()" } );
/**
* Align selected Layers to the last selected one
* @param {boolean} [position=true] - Wether to align the position.
* @param {boolean} [rotation=true] - Wether to align the rotation.
* @param {boolean} [scale=true] - Wether to align the scale.
* @param {boolean} [opacity=true] - Wether to align the opacity.
*/
Duik.tools.align = function ( position, rotation, scale, opacity )
{
position = def (position, true);
rotation = def (rotation, true);
scale = def (scale, true);
opacity = def (opacity, false);
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
if (layers.length == 0) return;
var target = layers.pop();
DuAEF.DuAE.App.beginUndoGroup("Align layers");
DuAEF.DuAE.Layer.align(
layers,
target,
position,
rotation,
scale,
opacity
);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.tools.functions.push( { name:"Edit Mode", fn:"Duik.tools.editMode()" } );
/**
* Toggle Edit Mode on selected layers.
*/
Duik.tools.editMode = function ( )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
DuAEF.DuAE.App.beginUndoGroup("Edit mode");
for (var i = 0, num = layers.length ; i < num ; i++)
{
DuAEF.DuAE.Layer.toggleEditMode(layers[i]);
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.tools.functions.push( { name:"Remove thisComp", fn:"Duik.tools.removeThisComp()" } );
/**
* Replace all <code>thisComp</code> occurences by <code>comp("name")</code>.
* @param {bool} [currentComp=true] true: in current compositions, false: in all compositions of the project
* @param {bool} [selectedComps=false] When currentComp is false, true to replace only in selected compositions
* @param {bool} [selectedLayers=false] When currentComp is true, wether to replace only on selected layers
*/
Duik.tools.removeThisComp = function ( currentComp, selectedComps, selectedLayers )
{
currentComp = def(currentComp, true);
selectedComps = def(selectedComps, false);
selectedLayers = def(selectedLayers, false);
DuAEF.DuAE.App.beginUndoGroup("Remove 'thisComp'");
if (currentComp) DuAEF.DuAE.Comp.removeThisCompInExpressions(selectedLayers);
else DuAEF.DuAE.Project.removeThisCompInExpressions(selectedComps);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.tools.functions.push( { name:"Remove Comp(\"name\")", fn:"Duik.tools.removeComp()" } );
/**
* Replace all <code>comp("name")</code> occurences by <code>thisComp</code>.
* @param {bool} [currentComp=true] true: in current compositions, false: in all compositions of the project
* @param {bool} [selectedComps=false] When currentComp is false, true to replace only in selected compositions
* @param {bool} [selectedLayers=false] When currentComp is true, wether to replace only on selected layers
*/
Duik.tools.removeComp = function ( currentComp, selectedComps, selectedLayers )
{
currentComp = def(currentComp, true);
selectedComps = def(selectedComps, false);
selectedLayers = def(selectedLayers, false);
DuAEF.DuAE.App.beginUndoGroup("Remove 'thisComp'");
if (currentComp) DuAEF.DuAE.Comp.removeCompInExpressions(selectedLayers);
else DuAEF.DuAE.Project.removeCompInExpressions(selectedComps);
DuAEF.DuAE.App.endUndoGroup();
}
Duik.tools.functions.push( { name:"Remove Expressions", fn:"Duik.tools.removeExpressions()" } );
/**
* Remove expressions from selected properties.
* @param {bool} [keepPostExpressionValue=true] Set to false to just remove the expressions and get back the pre expression value
*/
Duik.tools.removeExpressions = function ( keepPostExpressionValue )
{
keepPostExpressionValue = def (keepPostExpressionValue, true);
var props = DuAEF.DuAE.Comp.getSelectedProps();
DuAEF.DuAE.App.beginUndoGroup("Remove expressions");
if (props.length > 0)
{
for (var i = 0, num = props.length; i < num; i++)
{
DuAEF.DuAE.Property.removeExpression(props[i], undefined, keepPostExpressionValue);
}
}
else
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
for (var i = 0, num = layers.length; i < num; i++)
{
DuAEF.DuAE.Property.removeExpressions(layers[i], undefined, keepPostExpressionValue);
}
}
DuAEF.DuAE.App.endUndoGroup();
}
/**
* The expression which has been copied by {@link Duik.tools.copyExpression} and which can be pasted by {@link Duik.tools.pasteExpression}.
*/
Duik.tools.copiedExpression = '';
Duik.tools.functions.push( { name:"Copy Expression", fn:"Duik.tools.copyExpression()" } );
/**
* Copies the expression from the selected property. You can paste it with {@link Duik.tools.pasteExpression}.
* @return {string} The expression
*/
Duik.tools.copyExpression = function ( )
{
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
prop = props.pop();
if (prop.riggable)
{
prop = prop.getProperty();
Duik.tools.copiedExpression = prop.expression;
}
return Duik.tools.copiedExpression;
}
Duik.tools.functions.push( { name:"Paste Expression", fn:"Duik.tools.pasteExpression()" } );
/**
* Pastes the expression previously copied with {@link Duik.tools.copyExpression} to the selected properties
* @param {string} [expression] - The expression to set. If not provided, will automatically use the expression copied by {@link Duik.tools.copyExpression}.
*/
Duik.tools.pasteExpression = function ( expression )
{
expression = def (expression , Duik.tools.copiedExpression);
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Paste expression");
new Iterator(props).do(function(prop)
{
if (prop.riggable)
{
var p = prop.getProperty();
p.expression = expression;
}
});
DuAEF.DuAE.App.endUndoGroup();
}// ==================== |----------------------------| ====================
// ==================== | Duik16_animation_functions | ====================
// ==================== |----------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html Animation}<br />
* Read the {@link http://duik-docs.rainboxlab.org Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html Animation} for more information about each method.<br />
* @namespace
*/
Duik.animation = {}
/**
* All the animation methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.animation.functions = []
//The functions
Duik.animation.functions.push( { name:"Klean", fn:"Duik.animation.klean()" } );
/**
* Automatically clean the animation of the selected properties.
* @param {boolean} [separateDimensions=true] - Wether to separate the dimensions of the property before kleaning it.
* @param {boolean} [spatialInterpolation=true] - Wether to fix spatial interpolation (when dimensions are not separated).
* @param {boolean} [smoothCurves=true] - Wether to apply a smart algorithm to smooth the curves.
* @param {boolean} [smoothUsingExpression=true] - Wether to smooth the curves using expressions. Set to false to adjust directly the interpolation of the keyframes.
* @param {boolean} [removeUnnecessaryKeys=true] - Wether to remove all redundants keyframes.
* @param {boolean} [smoothIn=true] - Wether to smooth the incoming curve if smoothCurves is set to true
* @param {boolean} [smoothOut=true] - Wether to smooth the outgoing curve if smoothCurves is set to true
* @return {Property[]} The effects created to control the kleaner.
*/
Duik.animation.klean = function ( separateDimensions, spatialInterpolation, smoothCurves, smoothUsingExpression, removeUnnecessaryKeys, smoothIn, smoothOut )
{
separateDimensions = def (separateDimensions, true);
spatialInterpolation = def (spatialInterpolation, true);
smoothCurves = def (smoothCurves, true);
removeUnnecessaryKeys = def (removeUnnecessaryKeys, true);
smoothIn = def (smoothIn, true);
smoothOut = def (smoothOut, true);
smoothUsingExpression = def (smoothUsingExpression, true);
DuAEF.DuAE.App.beginUndoGroup("Kleaner");
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
var props = DuAEF.DuAE.Comp.getSelectedProps();
if (props.length == 0)
{
DuAEF.DuAE.App.endUndoGroup();
return null;
}
if (separateDimensions)
{
var newProps = [];
for (var i = 0, num = props.length ; i < num ; i++)
{
newProps = newProps.concat(DuAEF.Duik.Rigging.separateDimensions(props[i]));
}
props = newProps;
}
var effect = null;
var effects = [];
for (var i = 0, num = props.length ; i < num ; i++)
{
//SPATIAL AUTO
if (!separateDimensions && spatialInterpolation ) DuAEF.DuAE.Property.fixSpatialInterpolation(props[i]);
//SMART SMOOTH
if ( smoothCurves ) effect = DuAEF.Duik.Animation.kleaner(props[i], smoothUsingExpression, smoothIn , smoothOut, effect);
if (effect != null) effects.push(effect);
}
for (var i = 0, num = props.length; i < num; i++)
{
//CLEAN
if ( removeUnnecessaryKeys ) DuAEF.DuAE.Property.cleanKeyframes(props[i]);
}
DuAEF.DuAE.Comp.selectLayers( layers );
DuAEF.DuAE.App.endUndoGroup();
return effects;
}
/**
* The animation copied by {@link Duik.animation.copy} which can be pasted with {@link Duik.animation.paste}.
*/
Duik.animation.copied = {}
Duik.animation.functions.push( { name:"Copy Animation", fn:"Duik.animation.copy()" } );
/**
* Copies the animation from the selected properties. Use {@link Duik.animation.paste} to paste it.
*/
Duik.animation.copy = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var layers = comp.selectedLayers;
if (layers.length == 0) return;
copiedAnim = [];
for (var i = 0 ; i < layers.length ; i++)
{
copiedAnim.push(DuAEF.DuAE.Layer.getAnim(layers[i],true));
}
//get the first keyframe time to offset when pasting
copiedAnim.firstKeyFrameTime = DuAEF.DuAE.Layer.firstKeyFrameTime(layers,true);
Duik.animation.copied = copiedAnim;
}
Duik.animation.functions.push( { name:"Paste", fn:"Duik.animation.paste()" } );
Duik.animation.functions.push( { name:"Paste_Reverse", fn:"Duik.animation.paste( false, false, true )" } );
Duik.animation.functions.push( { name:"Paste_Offset", fn:"Duik.animation.paste( false, true )" } );
Duik.animation.functions.push( { name:"Paste_Replace", fn:"Duik.animation.paste( true )" } );
/**
* Pastes the animation previously copied by {@link Duik.animation.copy} to the selected properties.
* @param {boolean} replace - Wether to completely erase and replace the current animation
* @param {boolean} offset - Wether to offset the animation from the current value
* @param {boolean} reverse - Wether to reverse the animation
*/
Duik.animation.paste = function ( replace, offset, reverse )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
if (layers.length == 0) layers = comp.layers;
if (layers.length == 0) return;
//options
var time = comp.time-copiedAnim.firstKeyFrameTime;
replace = def( replace, false );
offset = def( offset, false );
reverse = def( reverse, false );
DuAEF.DuAE.App.beginUndoGroup("Paste animation");
var remaining = DuAEF.DuAE.Layer.setAnims(layers, Duik.animation.copied, time, undefined, undefined, undefined, replace, undefined, offset, reverse);
if (remaining.length > 0)
{
var ui_pasteLayerPicker = DuAEF.DuScriptUI.createLayerPickerDialog("Missing layers");
for (var i = 0, num = remaining.length; i < num; i++)
{
ui_pasteLayerPicker.addSelector(remaining[i]._index + ' | ' + remaining[i]._name);
//try to preselect by name
var ok = false;
for (var j = 1, numLayers = comp.numLayers; j <= numLayers; j++)
{
var l = comp.layer(j);
if (l.name == remaining[i]._name)
{
ui_pasteLayerPicker.layerPicker.selectors[i].setCurrentIndex(j);
ok = true;
break;
}
}
if (!ok && remaining[i]._index > 0 && remaining[i]._index <= comp.numLayers) ui_pasteLayerPicker.layerPicker.selectors[i].setCurrentIndex(remaining[i]._index);
}
ui_pasteLayerPicker.onAccept = function () {DuAEF.DuAE.App.beginUndoGroup("Paste animation"); DuAEF.DuAE.Layer.setAllAnims(ui_pasteLayerPicker.getLayers(), Duik.animation.copied, time, undefined, undefined, undefined, replace, undefined, offset, false); DuAEF.DuAE.App.endUndoGroup();};
DuAEF.DuScriptUI.showUI(ui_pasteLayerPicker);
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.animation.functions.push( { name:"IK/FK Switch", fn:"Duik.animation.switchIkFk( )" } );
/**
* Switches the selected controller between IK and FK
*/
Duik.animation.switchIkFk = function ( )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
DuAEF.DuAE.App.beginUndoGroup("FK/IK Switch");
var it = new Iterator(comp.selectedLayers);
it.do(function (layer) {
DuAEF.Duik.Animation.switchIkFk(layer);
});
DuAEF.DuAE.App.endUndoGroup();
}
Duik.animation.functions.push( { name:"Motion Trail", fn:"Duik.animation.motionTrail( )" } );
/**
* Draws the trajectory of the selected layers
* @param {float[]|null} [color=DuAEF.DuJS.Color.random()] - The [R,G,B,A] color of the trails. Random color if null.
* @param {boolean} [useExisting=true] - Wether to use the existing motion trail layer, if any
*/
Duik.animation.motionTrail = function ( color, useExisting )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
if (color == null) color = DuAEF.DuJS.Color.random();
DuAEF.DuAE.App.beginUndoGroup("Motion trail");
useExisting = def(useExisting, true);
//trail layer
var trailLayer = null;
if (useExisting) trailLayer = DuAEF.Duik.getLayer( DuAEF.Duik.LayerTypes.MOTION_TRAIL );
var layers = DuAEF.DuAE.Comp.unselectLayers();
if (layers.length > 0)
{
for (var i = 0 ; i < layers.length ; i++)
{
trailLayer = DuAEF.Duik.Animation.motionTrail(comp,layers[i],trailLayer,color);
}
}
else
{
DuAEF.Duik.Animation.motionTrail(comp,undefined,trailLayer, color);
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.animation.functions.push( { name:"X-Sheet", fn:"Duik.animation.xSheet( )" } );
/**
* Adds an Exposure Sheet (X-Sheet) effect on the selected layers or composition
* @param {boolean} [autoDetect=false] - If true, will try to detect and animate the best exposure values for a nice traditionnal look.
*/
Duik.animation.xSheet = function ( autoDetect )
{
var comp = DuAEF.DuAE.Project.getActiveComp();
if (!comp) return;
autoDetect = def (autoDetect, false);
var props = DuAEF.DuAE.Comp.getSelectedProps();
DuAEF.DuAE.App.beginUndoGroup("X-Sheet");
var ok = false;
if (props.length > 0)
{
var effect = null;
for (var i = 0 ; i < props.length ; i++)
{
effect = DuAEF.Duik.Animation.xSheet(comp,props[i],effect);
if (effect != null) ok = true;
}
}
if (!ok)
{
effect = DuAEF.Duik.Animation.xSheet(comp);
}
if ( autoDetect && props.length > 0)
{
//detect limit
var averageSpeed = DuAEF.DuAE.Property.getAverageSpeed(props);
if (averageSpeed > 0)
{
var precision = averageSpeed*2.5;
var frames = comp.duration / comp.frameDuration;
//set Keyframes
var step = 0;
effect(19).addKey(0);
for (var frame = 0 ; frame < frames ; frame++)
{
var time = frame * comp.frameDuration;
var maxSpeed = 0;
for (var j = 0 ; j < props.length ; j++)
{
var prop = props[j].getProperty();
var speedTest = DuAEF.DuAE.Property.getSpeed(prop,time);
if (speedTest > maxSpeed) maxSpeed = speedTest;
}
step += maxSpeed;
if (step >= precision && averageSpeed > 0)
{
step = 0;
effect(19).addKey(time);
}
}
effect(7).setValue(2);
}
}
DuAEF.DuAE.App.endUndoGroup();
}
Duik.animation.functions.push( { name:"Time Remapping", fn:"Duik.animation.timeRemap( )" } );
/**
* Activates time remapping on the selected layers, and add the looper {@link Duik.constraints.loop} to it.
*/
Duik.animation.timeRemap = function ( )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
DuAEF.DuAE.App.beginUndoGroup("Time Remap");
DuAEF.Duik.Animation.timeRemap(layers);
DuAEF.DuAE.App.endUndoGroup();
}// ==================== |-------------------------| ====================
// ==================== | Duik16_camera_functions | ====================
// ==================== |-------------------------| ====================
/**
* Duik {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html Camera}<br />
* Read the {@link http://duik-docs.rainboxlab.org Duik User Guide} > {@link http://duaef-docs.rainboxlab.org/Guides/Duik/constraints.html Camera} for more information about each method.<br />
* @namespace
*/
Duik.camera = {}
/**
* All the camera methods stored as objects which can be parsed easily, for example to automatically build a ui with a button for each method.
* @property {string} name - A display name for the method
* @property {string} fn - The source script to eval
*/
Duik.camera.functions = []
//The functions
Duik.camera.functions.push( { name:"Rig", fn:"Duik.camera.rig()" } );
/**
* Rigs the selected 3D Camera
*/
Duik.camera.rig = function ( )
{
var layers = DuAEF.DuAE.Comp.unselectLayers();
var numLayers = layers.length;
if (numLayers == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Camera rig");
var it = new Iterator(layers);
it.do(function (layer)
{
if (layer instanceof CameraLayer)
{
DuAEF.Duik.Camera.rigCamera(layer);
}
});
DuAEF.DuAE.App.endUndoGroup();
}
Duik.camera.functions.push( { name:"Scale Z-Link", fn:"Duik.camera.zLink()" } );
/**
* Toggles the scale Z-link on the selected 3D Layers
*/
Duik.camera.zLink = function ( )
{
var layers = DuAEF.DuAE.Comp.getSelectedLayers();
if (layers.length == 0) return;
DuAEF.DuAE.App.beginUndoGroup("Toggle Scale Z-Link");
var result = DuAEF.Duik.Camera.toggleScaleZLink(layers);
if (result == 0) alert("Scale Z-Link needs a Camera in the comp to work correctly. Please create a camera first.")
DuAEF.DuAE.App.endUndoGroup();
}
Duik.camera.functions.push( { name:"2D Camera", fn:"Duik.camera.create2DCam()" } );
/**
* Creates a 2D multi-plane camera
*/
Duik.camera.create2DCam = function ( )
{
DuAEF.DuAE.App.beginUndoGroup("2D Camera");
DuAEF.Duik.Camera.create2DCam();
DuAEF.DuAE.App.endUndoGroup();
}
Duik.camera.functions.push( { name:"Framing guides", fn:"Duik.camera.frame()" } );
/**
* Adds framing guides to the composition
*/
Duik.camera.frame = function ( )
{
DuAEF.DuAE.App.beginUndoGroup("Framing Guides");
DuAEF.Duik.Camera.addFrame();
DuAEF.DuAE.App.endUndoGroup();
}