// rd_Shifter.jsx // Copyright (c) 2005-2013 redefinery (Jeffrey R. Almasol). All rights reserved. // check it: www.redefinery.com // // Name: rd_Shifter // Version: 3.0 // // Description: // This script displays a palette with controls for shifting the selected // layers in unison to specific points in time in the composition. // // Note: This version of the script requires After Effects CS5 // or later. It can be used as a dockable panel by placing the // script in a ScriptUI Panels subfolder of the Scripts folder, // and then choosing this script from the Window menu. // // Originally requested by Gary Jaeger. Enhancements requested by Matt // Silverman. // // Legal stuff: // This script is provided "as is," without warranty of any kind, expressed // or implied. In no event shall the author be held liable for any damages // arising in any way from the use of this script. // // In other words, I'm just trying to share knowledge with and help out my // fellow AE script heads, so don't blame me if my code doesn't rate. :-) // rd_Shifter() // // Description: // This function contains the main logic for this script. // // Parameters: // thisObj - "this" object. // // Returns: // Nothing. // (function rd_Shifter(thisObj) { // Globals var rd_ShifterData = new Object(); // Store globals in an object rd_ShifterData.scriptName = "rd: Shifter"; rd_ShifterData.scriptTitle = rd_ShifterData.scriptName + " v3.0"; rd_ShifterData.strRefLayer = {en: "Ref. Layer:"}; rd_ShifterData.strRefLayerOpts = {en: '["Top Selected", "Bottom Selected", "First Selected", "Last Selected", "Earliest (In Point) Selected", "Latest (In Point) Selected"]'}; rd_ShifterData.strShiftTo = {en: "Shift To:"}; rd_ShifterData.strShiftToOpts = {en: '["Current Time", "Start of Composition", "Start of Work Area"]'}; rd_ShifterData.strShift = {en: "Shift"}; rd_ShifterData.strHelp = {en: "?"} rd_ShifterData.strErrNoCompSel = {en: "Cannot perform operation. Please select or open a single composition in the Project panel, and try again."}; rd_ShifterData.strErrNoLayerSel = {en: "Cannot perform operation. Please select at least one layer, and try again."}; rd_ShifterData.strMinAE100 = {en: "This script requires Adobe After Effects CS5 or later."}; rd_ShifterData.strHelpText = { en: "Copyright (c) 2005-2013 redefinery (Jeffrey R. Almasol). \n" + "All rights reserved.\n" + "\n" + "This script displays a palette with controls for shifting the selected layers in unison to specific points in time in the composition.\n" + "\n" + "Note: This version of the script requires After Effects CS5 or later. It can be used as a dockable panel by placing the script in a ScriptUI Panels subfolder of the Scripts folder, and then choosing this script from the Window menu.\n" + "\n" + "Originally requested by Gary Jaeger. Enhancements requested by Matt Silverman." }; // rd_Shifter_localize() // // Description: // This function localizes the given string variable based on the current locale. // // Parameters: // strVar - The string variable's name. // // Returns: // String. // function rd_Shifter_localize(strVar) { return strVar["en"]; } // rd_Shifter_buildUI() // // Description: // This function builds the user interface. // // Parameters: // thisObj - Panel object (if script is launched from Window menu); null otherwise. // // Returns: // Window or Panel object representing the built user interface. // function rd_Shifter_buildUI(thisObj) { var pal = (thisObj instanceof Panel) ? thisObj : new Window("palette", rd_ShifterData.scriptName, undefined, {resizeable:true}); if (pal !== null) { var res = "group { \ orientation:'column', alignment:['fill','top'], \ header: Group { \ alignment:['fill','top'], \ title: StaticText { text:'" + rd_ShifterData.scriptName + "', alignment:['fill','center'] }, \ help: Button { text:'" + rd_Shifter_localize(rd_ShifterData.strHelp) +"', maximumSize:[30,20], alignment:['right','center'] }, \ }, \ r1: Group { \ alignment:['fill','top'], \ refLayer: StaticText { text:'" + rd_Shifter_localize(rd_ShifterData.strRefLayer) + "' }, \ refLayerOpts: DropDownList { properties:{items:" + rd_Shifter_localize(rd_ShifterData.strRefLayerOpts) + "}, alignment:['fill','top'], preferredSize:[-1,20] }, \ }, \ r2: Group { \ alignment:['fill','top'], \ shiftTo: StaticText { text:'" + rd_Shifter_localize(rd_ShifterData.strShiftTo) + "' }, \ shiftToOpts: DropDownList { properties:{items:" + rd_Shifter_localize(rd_ShifterData.strShiftToOpts) + "}, alignment:['fill','top'], preferredSize:[-1,20] }, \ }, \ cmds: Group { \ alignment:['right','top'], \ shiftBtn: Button { text:'" + rd_Shifter_localize(rd_ShifterData.strShift) + "', preferredSize:[-1,20] }, \ }, \ }"; pal.grp = pal.add(res); pal.grp.r2.shiftTo.preferredSize.width = pal.grp.r1.refLayer.preferredSize.width; pal.layout.layout(true); pal.grp.minimumSize = pal.grp.size; pal.layout.resize(); pal.onResizing = pal.onResize = function () {this.layout.resize();} pal.grp.r1.refLayerOpts.selection = 0; pal.grp.r2.shiftToOpts.selection = 0; pal.grp.header.help.onClick = function () {alert(rd_ShifterData.scriptTitle + "\n" + rd_Shifter_localize(rd_ShifterData.strHelpText), rd_ShifterData.scriptName);} pal.grp.cmds.shiftBtn.onClick = rd_Shifter_doShifter; } return pal; } // rd_Shifter_doShifter() // // Description: // This function performs the actual shifting of the selected layers. // // Parameters: // None. // // Returns: // Nothing. // function rd_Shifter_doShifter() { var refLayerOpt; var shiftToOpt; refLayerOpt = this.parent.parent.r1.refLayerOpts.selection.index; shiftToOpt = this.parent.parent.r2.shiftToOpts.selection.index; // Check that a project exists if (app.project === null) return; // Get the current (active/frontmost) comp var comp = app.project.activeItem; if ((comp === null) || !(comp instanceof CompItem)) { alert(rd_Shifter_localize(rd_ShifterData.strErrNoCompSel), rd_ShifterData.scriptName); return; } // If no layers are selected, nothing to do if (comp.selectedLayers.length === 0) { alert(rd_Shifter_localize(rd_ShifterData.strErrNoLayerSel), rd_ShifterData.scriptName); return; } // Determine layers to process var layers = new Array(), refLayerIndex = 0; if ((refLayerOpt === 0) || (refLayerOpt === 1)) // Top Selected or Bottom Selected { for (var i=1; i<=comp.layers.length; i++) // Check for selected layers from top to bottom if (comp.layer(i).selected) layers[layers.length] = comp.layer(i); if (refLayerOpt === 1) refLayerIndex = layers.length - 1; } else if (refLayerOpt === 2) // First Selected layers = comp.selectedLayers; else if (refLayerOpt === 3) // Last Selected { layers = comp.selectedLayers; refLayerIndex = layers.length - 1; } else if (refLayerOpt === 4) // Earliest (In-Point) Selected { layers = comp.selectedLayers; for (var i=1; i layers[refLayerIndex].inPoint) refLayerIndex = i; } // Determine offset from selected shift point to start of reference layer // (give special consideration to negatively stretched layers) var offset; if (shiftToOpt === 0) // Current Time offset = comp.time - ((layers[refLayerIndex].stretch < 0) ? layers[refLayerIndex].outPoint : layers[refLayerIndex].inPoint); else if (shiftToOpt === 1) // Start of Composition offset = -((layers[refLayerIndex].stretch < 0) ? layers[refLayerIndex].outPoint : layers[refLayerIndex].inPoint); else if (shiftToOpt === 2) // Start of Work Area offset = comp.workAreaStart - ((layers[refLayerIndex].stretch < 0) ? layers[refLayerIndex].outPoint : layers[refLayerIndex].inPoint); // Shift the layers app.beginUndoGroup(rd_ShifterData.scriptName); for (var i=0; i