// rd_RenderLayers_IsoscelesFix.jsx // Code modified by ChatGPT-5 // Date: March 14, 2025 // This is a very useful script in certain situations. But it had been broken for several years due to changes in After Effects and so it wasn't usable. I did some tests and was able to determine what was causing the issue. So I crafted up a text prompt (listed below) and ChatGPT was able to fix the script after a few clarifications. // ChatGPT Text Prompt: "The following script is not working properly in After Effects 2024 when using the "Layer In/Out Range" option. When I execute the script then it will correctly add items into the render queue, but after rendering out the videos then it's just black video. So I examined the duplicated comps and realized that there are two issues happening: While the duration of the layer range is correct, it is always starting at frame 0 instead of the expected layer in/out range. Also all of the layers are not visible. Can you fix the attached script for me?" // Although there was no license attached to this script, the original authors website is offline , and yet the broken version of the script is freely distributed on . That left me in a bit of an awkward situation regarding distribution of the modified version of this script. But the code comment included below from the original author gave a feeling of openness: "I'm just trying to share knowledge with and help out my fellow AE script heads". And so with that in mind, I've decided to distribute this modified version of the script using the GPL-3.0 license. // Copyright (c) 2006-2013 redefinery (Jeffrey R. Almasol). All rights reserved. // check it: www.redefinery.com // // Name: rd_RenderLayers // Version: 3.2 // // Description: // This script renders each of the selected layers separately. You might // find this script useful if layers represent different versions of an // effect or different parts of an effect that you want to render as // separate "passes" for flexibility in how they get composited. // // Rendering uses existing render settings and output module template, so // be sure to create them beforehand. When you run this script, you can // select the templates to use; select the range of frames for each selected // layer to render; control if unselected, adjustment, active camera, and // light layers should be rendered as well; and define the name for each // rendered output. Each rendered layer will generate separate "render // finished" sounds. // // The Output Name Template can be defined with the same properties // available in the File Name Templates dialog box, with the following // additions: // [layerName] - Current layer's name // [layerNumber] - Current layer's index number // // Note: If you select an output template that uses a single-image // format (such as Photoshop), be sure to include the [#####] property // in the Output Name Template. // // Note: If the layer is completely outside of the composition time range, // the layer will not be rendered. However, if you select a range of // Work Area and the layer is outside of the composition's work area, the // layer will still be rendered. // // The Queue Only option is available only when Layer Range to Render // is set to Layer In/Out Range or Work Area. Also, this mode creates a // temp folder (in the same location as the comp) with " - Temp Comps" // in the name. The comp is duplicated (with incremented comp name) // to retain the state of each selected layer. // // 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. // // Enhancements requested by Gary Jaeger and James Tobias. // // 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_RenderLayers() // // Description: // This function contains the main logic for this script. // // Parameters: // thisObj - "this" object. // // Returns: // Nothing. // (function rd_RenderLayers(thisObj) { // Globals var rd_RenderLayersData = new Object(); // Store globals in an object rd_RenderLayersData.scriptName = "rd: Render Layers"; rd_RenderLayersData.scriptTitle = rd_RenderLayersData.scriptName + " v3.1"; rd_RenderLayersData.strLayerRange = {en: "Layer Range to Render:"}; rd_RenderLayersData.strLayerRangeOpts = {en: '["Work Area", "Entire Composition", "Layer In/Out Range"]'}; rd_RenderLayersData.strKeepInRender = {en: "Keep in Render:"}; rd_RenderLayersData.strKeepInUnsel = {en: "Unselected layers"}; rd_RenderLayersData.strKeepInAdjust = {en: "Adjustment layers"}; rd_RenderLayersData.strKeepInActiveCam = {en: "Active Camera"}; rd_RenderLayersData.strKeepInLights = {en: "Lights"}; rd_RenderLayersData.strRSTemplate = {en: "Render Settings Template:"}; rd_RenderLayersData.strOMTemplate = {en: "Output Module Template:"}; rd_RenderLayersData.strRefresh = {en: "Refresh"}; rd_RenderLayersData.strOutFolder = {en: "Output Folder:"}; rd_RenderLayersData.strOutFolderBrowse = {en: "Browse..."}; rd_RenderLayersData.strOutName = {en: "Output Name Template:"} rd_RenderLayersData.strQueueOnly = {en: "Queue Only"}; rd_RenderLayersData.strRender = {en: "Render"}; rd_RenderLayersData.strHelp = {en: "?"}; rd_RenderLayersData.strErrNoCompSel = {en: "Cannot perform operation. Please select or open a single composition in the Project panel, and try again."}; rd_RenderLayersData.strErrNoLayerSel = {en: "Cannot perform operation. Please select at least one layer, and try again."}; rd_RenderLayersData.strMinAE100 = {en: "This script requires Adobe After Effects CS5 or later."}; rd_RenderLayersData.strHelpText = { en: "Copyright (c) 2006-2013 redefinery (Jeffrey R. Almasol). \n" + "All rights reserved.\n" + "\n" + "This script renders each of the selected layers separately. You might find this script useful if layers represent different versions of an effect or different parts of an effect that you want to render as separate \"passes\" for flexibility in how they get composited.\n" + "\n" + "Rendering uses existing render settings and output module template, so be sure to create them beforehand. When you run this script, you can select the templates to use; select the range of frames for each selected layer to render; control if unselected, adjustment, active camera, and light layers should be rendered as well; and define the name for each rendered output. Each rendered layer will generate separate \"render finished\" sounds.\n" + "\n" + "The Output Name Template can be defined with the same properties available in the File Name Templates dialog box, with the following additions:\n" + " [layerName] - Current layer's name\n" + " [layerNumber] - Current layer's index number\n" + "\n" + "Note: If you select an output template that uses a single-image format (such as Photoshop), be sure to include the [#####] property in the Output Name Template.\n" + "\n" + "Note: If the layer is completely outside of the composition time range, the layer will not be rendered. However, if you select a range of Work Area and the layer is outside of the composition's work area, the layer will still be rendered.\n" + "\n" + "The Queue Only option is available only when Layer Range to Layer In/Out Range or Render is set to Work Area. Also, this mode creates a temp folder (in the same location as the comp) with \" - Temp Comps\" in the name. The comp is duplicated (with incremented comp name) to retain the state of each selected layer.\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" + "Enhancements requested by Gary Jaeger and James Tobias" }; // rd_RenderLayers_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_RenderLayers_localize(strVar) { return strVar["en"]; } // rd_RenderLayers_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_RenderLayers_buildUI(thisObj) { var pal = (thisObj instanceof Panel) ? thisObj : new Window("palette", rd_RenderLayersData.scriptName, undefined, {resizeable:true}); if (pal !== null) { var res = "group { \ orientation:'column', alignment:['fill','top'], \ header: Group { \ alignment:['fill','top'], \ title: StaticText { text:'" + rd_RenderLayersData.scriptName + "', alignment:['fill','center'] }, \ help: Button { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strHelp) +"', maximumSize:[30,20], alignment:['right','center'] }, \ }, \ r1: Group { \ alignment:['fill','top'], \ layerRange: StaticText { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strLayerRange) + "' }, \ layerRangeList: DropDownList { properties:{items:" + rd_RenderLayers_localize(rd_RenderLayersData.strLayerRangeOpts) + "}, alignment:['fill','top'], preferredSize:[-1,20] }, \ }, \ r2: Group { \ alignment:['fill','top'], \ keepInRender: StaticText { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strKeepInRender) + "' }, \ keepInUnsel: Checkbox { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strKeepInUnsel) + "', value:false }, \ keepInAdjust: Checkbox { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strKeepInAdjust) + "', value:true }, \ }, \ r3: Group { \ alignment:['fill','top'], \ keepInActiveCam: Checkbox { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strKeepInActiveCam) + "', value:true }, \ keepInLights: Checkbox { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strKeepInLights) + "', value:true }, \ }, \ r4: Group { \ alignment:['fill','top'], \ r4left: Group { \ orientation:'column', alignment:['fill','center'], \ r4top: Group { \ alignment:['fill','top'], \ rsTpl: StaticText { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strRSTemplate) + "' }, \ rsTplList: DropDownList { alignment:['fill','top'], alignment:['fill','top'], preferredSize:[-1,20] }, \ }, \ r4btm: Group { \ alignment:['fill','top'], \ omTpl: StaticText { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strOMTemplate) + "' }, \ omTplList: DropDownList { alignment:['fill','top'], alignment:['fill','top'], preferredSize:[-1,20] }, \ }, \ }, \ refresh: Button { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strRefresh) + "', alignment:['right','center'], preferredSize:[-1,20] }, \ }, \ r5: Group { \ alignment:['fill','top'], \ outFolder: StaticText { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strOutFolder) + "' }, \ outFolderName: EditText { text:'', characters:20, alignment:['fill','top'], preferredSize:[-1,20] }, \ outFolderBrowse: Button { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strOutFolderBrowse) + "', alignment:['right','top'], preferredSize:[-1,20] }, \ }, \ r6: Group { \ alignment:['fill','top'], \ outName: StaticText { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strOutName) + "' }, \ outNameTpl: EditText { text:'[compName]_[layerName].[fileExtension]', characters:20, alignment:['fill','top'], preferredSize:[-1,20] }, \ }, \ cmds: Group { \ alignment:['right','top'], \ queueOnlyBtn: Button { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strQueueOnly) + "', preferredSize:[-1,20] }, \ renderBtn: Button { text:'" + rd_RenderLayers_localize(rd_RenderLayersData.strRender) + "', preferredSize:[-1,20] }, \ }, \ }"; pal.grp = pal.add(res); pal.grp.r1.layerRange.preferredSize.width = pal.grp.r2.keepInRender.preferredSize.width = pal.grp.r4.r4left.r4btm.omTpl.preferredSize.width = pal.grp.r5.outFolder.preferredSize.width = pal.grp.r6.outName.preferredSize.width = pal.grp.r4.r4left.r4top.rsTpl.preferredSize.width; pal.grp.r3.margins.left = pal.grp.r4.r4left.r4top.rsTpl.preferredSize.width + pal.grp.r2.spacing; pal.grp.r3.keepInActiveCam.preferredSize.width = pal.grp.r2.keepInUnsel.preferredSize.width; pal.grp.r4.r4left.r4btm.margins.top -= 5; pal.grp.cmds.margins.top += 5; pal.layout.layout(true); pal.grp.minimumSize = pal.grp.size; pal.layout.resize(); pal.onResizing = pal.onResize = function () {this.layout.resize();} pal.grp.r1.layerRangeList.selection = 0; pal.grp.r1.layerRangeList.onChange = function () { // Enable the Queue Only button only if using Work Area this.parent.parent.cmds.queueOnlyBtn.enabled = (this.selection.index === 0) || (this.selection.index === 2); } pal.grp.r4.refresh.onClick = function () { rd_RenderLayers_doRefreshTemplates(this.parent.parent.parent); } pal.grp.r5.outFolderBrowse.onClick = function () { var defaultFolder = this.parent.outFolderName.text; if ($.os.indexOf("Windows") !== -1) // On Windows, escape backslashes first defaultFolder = defaultFolder.replace("\\", "\\\\"); var folder = Folder.selectDialog("Output To Folder", defaultFolder); if (folder !== null) this.parent.outFolderName.text = folder.fsName; } pal.grp.header.help.onClick = function () {alert(rd_RenderLayersData.scriptTitle + "\n" + rd_RenderLayers_localize(rd_RenderLayersData.strHelpText), rd_RenderLayersData.scriptName);} pal.grp.cmds.queueOnlyBtn.onClick = function () {rd_RenderLayers_doRenderLayers(this.parent.parent, false);} pal.grp.cmds.renderBtn.onClick = function () {rd_RenderLayers_doRenderLayers(this.parent.parent, true);} pal.grp.cmds.margins.top += 5; } return pal; } // rd_RenderLayers_doRefreshTemplates() // // Description: // This callback function rescans the render settings and output module templates, // updating the user interface. // // Parameters: // pal - Window object representing the palette. // // Returns: // Nothing. // function rd_RenderLayers_doRefreshTemplates(pal) { var activeComp = app.project.activeItem; if ((activeComp === null) || !(activeComp instanceof CompItem)) { alert(rd_RenderLayers_localize(rd_RenderLayersData.strErrNoCompSel)); return; } pal.grp.r4.r4left.r4top.rsTplList.selection = null; pal.grp.r4.r4left.r4top.rsTplList.removeAll(); pal.grp.r4.r4left.r4btm.omTplList.selection = null; pal.grp.r4.r4left.r4btm.omTplList.removeAll(); // Get the list of render settings and output module templates // (Need to add a dummy comp to the render queue to do this) var rqi = app.project.renderQueue.items.add(activeComp); var om = rqi.outputModule(1); // Assumes at least one output module for (var i=0; i