-
【脚本案例】关键帧倍增
介绍 选择关键帧,可以基于整数倍扩散,并且关键帧类型不变 移动前 移动后(2倍) 源码 /** * 名称:关键帧倍增 * 功能:选择关键帧,可以基于整数倍扩散,并且关键帧类型不变 * 版本:V1.0 * 源码:https://www.yuelili.com/?p=18038 */ var panelGlobal = this; var main = (function () { // MAIN // ==== var main = (panelGlobal instanceof Panel) ? panelGlobal : new Window("palette"); if (!(panelGlobal instanceof Panel)) main.text = "关键帧倍增"; main.orientation = "row"; main.alignChildren = ["center", "top"]; main.spacing = 10; main.margins = 16; var num = main.add('edittext {properties: {name: "num"'); num.text = "2"; num.preferredSize.width = 30; var tm_btn = main.add("button", undefined, undefined, { name: "tm_btn" }); tm_btn.helpTip = "选择你的关键帧们,然后单击"; tm_btn.text = "倍增"; tm_btn.preferredSize.width = 35; tm_btn.onClick = key_it // 主函数 function key_it() { app.beginUndoGroup("keyframe mu"); var selLayers = app.project.activeItem.selectedLayers var propGroup var num_times = parseFloat(num.text) - 1 if (selLayers.length > 0 && num_times>0) { if (selLayers.length == 1) { propGroup = selLayers[0].selectedProperties } else { propGroup = app.project.activeItem.selectedProperties } // 记住选择关键帧的属性 res = rem_prop_group(propGroup, num_times) for (var i = 0; i < res[0].length; i++) { rd_Scooter_scootAllPropGroupKeys(res[0][i], res[1][i], res[2][i]) } } else { alert("请选择一个合成,并且倍数大于1") } app.endUndoGroup(); } function rd_Scooter_shiftKeyToNewTime(prop, keyToCopy, offset, keyToRemove) { // Remember the key's settings before creating the new setting, just in case creating the new key affects keyToCopy's settings // 记住旧关键帧的设置,然后基于该设置,创建新关键帧 var inInterp = prop.keyInInterpolationType(keyToCopy); // 入点插值类型 var outInterp =…- 0
- 0
- 178
-
【脚本案例】导入预设文件 修改合成尺寸
用户需求 导入指定位置aep,并且基于选择的素材修改预设aep内合成大小 自定义 代码第10行:可以设置导入预设文件位置 代码第14行:可以设置修改合成内容(高宽、持续时间、帧速率) 源码 /** / https://www.yuelili.com/?p=18012 * 导入预设文件aep,并且基于项目面板选择的素材,批量修改合成尺寸等 */ var panelGlobal = this; var palette = (function () { // 用户自定义区。预设aep位置 var file = new File("F:/Footage/cell预设.aep") // 对合成进行修改内容,基于选择的素材。如果不想更改那么多,可以在每行前面加 “// “ 比如当前帧速率就不会随素材更改 function do_some_change(comp) { comp.width = selFootage.width // 合成宽度 comp.height = selFootage.height // 合成高度 // comp.frameRate = selFootage.frameRate // 合成帧速率 comp.duration = selFootage.duration // 合成持续时间 } // PALETTE // ======= var palette = (panelGlobal instanceof Panel) ? panelGlobal : new Window("palette"); if (!(panelGlobal instanceof Panel)) palette.text = "导入预设 并修改尺寸"; palette.orientation = "row"; palette.alignChildren = ["center", "top"]; palette.spacing = 10; palette.margins = 16; var create = palette.add("button", undefined, undefined, { name: "create" }); create.helpTip = "选择一个素材,然后单击“导入”按钮"; create.text = "导入"; create.preferredSize.width = 80; create.onClick = create_it // 主函数区 function create_it() { var selItems = app.project.selection if (selItems.length === 0) { alert("请在项目面板选择至少一个素材文件") } else { app.beginUndoGroup("import file") selFootage = selItems[0] // 导入预设 var itemFolder = app.project.importFile(new ImportOptions(file)); for (var i = 1; i <= itemFolder.numItems; i++) { var mainComp = itemFolder.item(i); // 判断顶级合成名称 if (mainComp.name == "合成1") { if (mainComp && mainComp instanceof CompItem) { // 嵌套合成处理 do_some_change(mainComp) app.beginUndoGroup("Comp Recursive"); previousComps = []; comp_recursive(mainComp); app.endUndoGroup(); } } } app.endUndoGroup() } } function comp_recursive(comp) { // 循环合成内的图层与子合成 for (var i =…- 0
- 0
- 286
-
【AE脚本案例】预设小助手
展示 用法 保存:弹出保存预设对话框,请保存到脚本同级目录下的Custom_Presets文件夹内 删除:删除当前预设,注意:本地文件也会被删除 应用:应用所选预设到所有选择的图层上 源码 // 构建UI Panel 函数 var panelGlobal = this; var palette = (function () { // JSON的polyfill "object" != typeof JSON && (JSON = {}), function () { "use strict"; var rx_one = /^[\],:{}\s]*$/, rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rx_four = /(?:^|:|,)(?:\s*\[)+/g, rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta, rep; function f(t) { return t < 10 ? "0" + t : t } function this_value() { return this.valueOf() } function quote(t) { return rx_escapable.lastIndex = 0, rx_escapable.test(t) ? '"' + t.replace(rx_escapable, function (t) { var e = meta[t]; return "string" == typeof e ? e : "\\u" + ("0000" + t.charCodeAt(0).toString(16)).slice(-4) }) + '"' : '"' + t + '"' } function str(t, e) { var r, n, o, u, f, a = gap, i = e[t]; switch (i && "object" == typeof i && "function" == typeof i.toJSON && (i = i.toJSON(t)), "function" == typeof rep && (i = rep.call(e, t, i)), typeof i) { case "string": return quote(i); case "number": return isFinite(i) ? String(i) : "null"; case "boolean": case "null": return String(i); case "object": if (!i) return "null"; if (gap += indent, f = [], "[object Array]" === Object.prototype.toString.apply(i))…- 0
- 1
- 375
-
【AE脚本】获取/设置一个关键帧的所有信息
使用方法 使用获取函数,获取这个关键帧的所有信息(需要一个属性,和关键帧索引)返回关键帧信息 再使用创建关键帧函数,创建一个新关键帧(需要关键帧信息,和新的时间、是否删除旧关键帧) 源码(获取) /** * @param {*} prop :属性 * @param {*} key_index :关键帧索引 * @returns :关键帧所有信息 */ function save_key_info(prop, key_index) { var inInterp = prop.keyInInterpolationType(key_index); // 入点插值类型(线性、贝塞尔、定格) var outInterp = prop.keyOutInterpolationType(key_index); //出点插值类型(线性、贝塞尔、定格) key_info = { "prop":prop, // 所在属性(废话 "index": key_index, // 关键帧索引 "time":prop.keyTime(key_index), // 当前关键帧的时间 "value": prop.keyValue(key_index), // 关键帧的值 "both_bezier": (inInterp === KeyframeInterpolationType.BEZIER) && (outInterp === KeyframeInterpolationType.BEZIER), // 判断入点/出点贝塞尔 如果都是的话 先存一下 "key_hold": outInterp !== KeyframeInterpolationType.HOLD, // 判断出点是不是 非定格 "key_space": (prop.propertyValueType === PropertyValueType.TwoD_SPATIAL) || (prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL), // 判断是不是空间值 } // 判断入点/出点贝塞尔 如果是的话 先存一下 if ((key_info["both_bezier"])) { key_info["tempAutoBezier"] = prop.keyTemporalAutoBezier(key_index); // 时间自动贝塞尔 → 布尔 key_info["tempContBezier"] = prop.keyTemporalContinuous(key_index); // 时间连续性 → 布尔 } // 判断出点是不是 非定格 if ((key_info["key_hold"])) { key_info["inTempEase"] = prop.keyInTemporalEase(key_index); // 入点关键帧缓入(1/2/3个对象) key_info["outTempEase"] = prop.keyOutTemporalEase(key_index); // 出点关键帧缓入(1/2/3个对象) } // 2D空间值 与 3D空间值:锚点、位置之类 if ((key_info["key_space"])) { key_info["spatAutoBezier"] = prop.keySpatialAutoBezier(key_index); // 空间自动贝塞尔 → 布尔 key_info["spatContBezier"] = prop.keySpatialContinuous(key_index); // 空间连续性 → 布尔 key_info["inSpatTangent"] = prop.keyInSpatialTangent(key_index); // 入点空间线性 → 浮点值数组(2/3) key_info["tempAutoBezier"] = prop.keyOutSpatialTangent(key_index); // 出点空间线性 → 浮点值数组(2/3) key_info["outSpatTangent"] = prop.keyRoving(key_index); } return key_info } 源码(创建) /** * @param {*} key_info :关键帧信息,使用save_key_info(prop,index)获得 * @param {*} newTime :新关键帧的时间:数值(秒) */ function create_new_key(key_info, newTime) { var prop = key_info["prop"] var newKeyIndex = prop.addKey(newTime); prop.setValueAtKey(newKeyIndex, key_info.value); // 设置关键帧的值 if ((key_info["key_hold"])) { prop.setTemporalEaseAtKey(newKeyIndex, key_info["inTempEase"], key_info["outTempEase"]); // 设置指定关键帧的入点出点时间缓动 }…- 0
- 8
- 452
-
【AE脚本】获取本工程所有效果,并发送到剪切板
代码 /** * @description : 获取本工程所有效果,并复制到剪切板 * @link: https://www.yuelili.com/?p=18805 */ var previousComps; var effect_list = []; function folder_recursive(folderGroup) { for (var i = 1; i <= folderGroup.numItems; i++) { var items = folderGroup.item(i); num += 1; // 判断当前属性是否为文件夹,如果是,则继续遍历 if (items instanceof FolderItem) { //对每个文件夹逐个操作 比如判断名称 folder_recursive(items); continue; } if (items instanceof CompItem) { previousComps = []; comp_recursive(items); } } } folder_recursive(app.project.rootFolder); send_to_clipboard(uniqueArray(effect_list)) function effect_recursive(layer) { var eff = layer.property("ADBE Effect Parade"); for (var i = 1, l = eff.numProperties; i <= l; i++) { effect_list.push(eff(i).name); // 对每个效果进行操作 // effectMissing(eff(i).matchName) // 如果你想的话,这里可以获取缺失效果 } } function send_to_clipboard(info) { var cmd, isWindows; // 判断是不是字符串 info = typeof info === "string" ? info : info.toString(); isWindows = $.os.indexOf("Windows") !== -1; //OS的命令 cmd = 'echo "' + info + '" | pbcopy'; //windows的cmd命令 if (isWindows) { cmd = 'cmd.exe /c cmd.exe /c "echo ' + info + ' | clip"'; } system.callSystem(cmd); } function uniqueArray(arr) { return arr.filter(function (item, pos) { return arr.indexOf(item) == pos; }); } function comp_recursive(comp) { // 循环合成内的图层与子合成 for (var i = 1; i <= comp.numLayers; i++) { var layer = comp.layer(i); // 检查图层是否有源 并且类型为合成 if (layer.source && layer.source instanceof CompItem) { // 检查是否遍历过该合成 check = checkPreviousComps(layer.source.id); if (check == null)…- 0
- 2
- 478
-
【脚本示例】冻结属性 表达式法
使用场景: K了参数的关键帧动画,希望关键帧临时不生效,但又不想删掉关键帧 /** * Freezes (or unfreezes) selected properties * 冻结/取消冻结所选属性 不选择则冻结当前图层的所有属性 * * @author Zack Lovatt <zack@zacklovatt.com> * @version 0.2.0 */ (function freezeSelectedProperties() { var frozenText = "// FROZEN"; function freezeProp(property) { if (!property.canSetExpression) { return; } var expression = property.expression; if (expression === "") { try { property.expression = generateExpression(property); } catch (e) { throw new Error( [ "当前属性“ " + property.name + " 不支持!", "请截图并联系zack@zacklovatt.com", e ].join("\n") ); } } else { if (expression.indexOf(frozenText) > -1) { property.expression = ""; } else { // prop has expression; skip! } } } /** * Freezes a given property * 冻结给出的属性 * * @param {Property | Layer | PropertyGroup} property Property to freeze */ function freeze(property) { if (skipProperty(property)) { return; } if (property instanceof Property) { freezeProp(property); } else if ( property instanceof PropertyGroup || property.matchName.indexOf("Layer") > -1 ) { for (var ii = 1; ii <= property.numProperties; ii++) { var prop = property.property(ii); freeze(prop); } } } /** * Check whether to skip a given property * 检查需要跳过的属性 * * @param {Property} property Property to check * @returns {boolean} Whether to skip this prop */ function skipProperty(property) { var depth = property.propertyDepth; if (depth > 1) {…- 0
- 0
- 169
-
【脚本案例】rd_Scooter 图层时间与关键帧控制
介绍 把图层/关键帧/标记玩透了,拆完即无敌 // 此脚本显示带有滑动和滑动控件的面板 // 图层设置,例如图层素材源、输入/输出范围、标记和关键帧。 // 对图层编辑操作进行更强大控制的设置。 界面 其他 免费购买:https://aescripts.com/rd-scooter/ 作者: 源码 // rd_Scooter.jsx // AES:https://aescripts.com/rd-scooter/ // Copyright (c) 2005-2013 redefinery (Jeffrey R. Almasol). All rights reserved. // check it: www.redefinery.com // // Name: rd_Scooter // Version: 3.1 // // 描述: // 此脚本显示带有滑动和滑动控件的面板 // 图层设置,例如图层素材源、输入/输出范围、标记和关键帧。 // 对图层编辑操作进行更强大控制的设置。 // // 注意: Keyframes 设置为 Selected 选项,脚本可能会需要一段时间才能完成,具体取决于关键帧的数量和选定的设置。 // 此外,此选项仅适用于第一个选定图层。 // // 您可以使用四个导航按钮。帧偏移 // 出现在每个按钮上方,但您可以将它们更改为任何正值数字。这些偏移量被保存为设置以供后续使用会话。 // // 注意:此版本的脚本需要 After Effects CS5或以后。它可以用作可停靠面板, // 通过放置Scripts 文件夹的 ScriptUI Panels 子文件夹中的脚本, // 然后从窗口菜单中选择这个脚本。 // // 最初由 Stu Maschwitz 请求。谢谢你的挑战。 // // 法律申明: // 此脚本按“原样”提供,不提供任何形式的保证,明示或暗示。在任何情况下,作者均不对任何损害承担责任因使用此脚本而以任何方式产生。 // // 换句话说,我只是想与我分享知识并帮助我 // AE 脚本负责人,所以如果我的代码没有评级,请不要怪我。 :-) // rd_Scooter() // // Description: // This function contains the main logic for this script. // // Parameters: // thisObj - "this" object. // // Returns: // Nothing. // (function rd_Scooter(thisObj) { // Globals var rd_ScooterData = new Object(); // Store globals in an object rd_ScooterData.scriptName = "rd: Scooter"; rd_ScooterData.scriptTitle = rd_ScooterData.scriptName + " v3.1"; rd_ScooterData.strAffectPnl = {en: "Affect"}; rd_ScooterData.strLayerSrc = {en: "Layer Source"}; rd_ScooterData.strLayerInOut = {en: "Layer In/Out"}; rd_ScooterData.strLayerMarkers = {en: "Layer Markers"}; rd_ScooterData.strKfs = {en: "Keyframes:"}; rd_ScooterData.strKfsNone = {en: "None"}; rd_ScooterData.strKfsSel = {en: "Selected"}; rd_ScooterData.strKfsAll = {en: "All"}; rd_ScooterData.strRew = {en: "<<"}; rd_ScooterData.strPrev = {en: "<"}; rd_ScooterData.strNext = {en: ">"}; rd_ScooterData.strFwd = {en: ">>"}; rd_ScooterData.strHelp = {en:…- 0
- 0
- 287
-
【脚本示例】获取实时属性值
/** * Gets value of current property at current time. * 获取实时属性值 * * @author Zack Lovatt <zack@zacklovatt.com> * @version 0.2.0 */ (function getPropertyValue(thisObj) { /** * Draws UI */ function createUI() { var win = thisObj instanceof Panel ? thisObj : new Window("palette", "Get Property Value", undefined, { resizeable: true }); win.add("statictext", undefined, "Current Property Value:"); win.alignChildren = ["left", "top"]; win.minimumSize = [50, 80]; win.et = win.add("edittext", undefined, "", { multiline: true }); win.et.minimumSize = [50, 30]; win.et.alignment = ["fill", "fill"]; var grpBtns = win.add("group"); grpBtns.orientation = "row"; grpBtns.alignChildren = ["left", "top"]; var btnUpdate = grpBtns.add("button", undefined, "Update"); btnUpdate.onClick = function () { try { win.et.text = getValue(); } catch (e) { alert(e, "Get Property Value Error"); return; } }; var btnCopy = grpBtns.add( "button", undefined, "Copy to Clipboard (wait 2s)" ); btnCopy.onClick = function () { copyToClipboard(win.et.text); }; win.layout.layout(); win.et.active = true; win.onResizing = win.onResize = function () { this.layout.resize(); }; return win; } /** * Copies text to clipboard (may not work in all cases!) * 复制到剪切板,也许不生效 * * @param {string} text Text to copy */ function copyToClipboard(text) { var command = 'echo "' + text + '" | pbcopy'; if ($.os.indexOf("Windows") > -1) { command =…- 0
- 0
- 150
-
【脚本案例】基于选择的item创建相同合成,添加效果
介绍 选择项目面板的序列图层,创建对应持续时长的合成,并且添加效果,然后再合成 思路 1.遍历选择项目 2.基于单项素材创建一个合成A,该合成添加对应的素材图层 3.再创建合成B,把合成A丢进去 4.给合成A添加属性,再更改属性值 新增 V1.1 可以基于图片创建,此时使用首选项的默认导入时间 会把所有合成放入目标文件夹内 源码 V1.1 /** * 作者:yueli * 源码:https://www.yuelili.com/?p=18010 */ var panelGlobal = this; var palette = (function () { // UI 构建 // ======= var palette = (panelGlobal instanceof Panel) ? panelGlobal : new Window("palette"); if (!(panelGlobal instanceof Panel)) palette.text = "序列创建合成"; palette.orientation = "row"; palette.alignChildren = ["center", "top"]; palette.spacing = 10; palette.margins = 16; var create = palette.add("button", undefined, undefined, { name: "create" }); create.helpTip = "选择一个素材,然后单击"; create.text = "创建合成"; create.preferredSize.width = 80; create.onClick = create_it // 主函数功能区 function create_it() { var selItems = app.project.selection // 判断是否选择项目 if (selItems.length === 0) { alert("请在项目面板选择至少一个序列") } else { app.beginUndoGroup("pre comp") app.preferences.saveToDisk() app.preferences.reload() var still_time = app.preferences.getPrefAsString("Main Pref Section v2", 'Pref_DEFAULT_STILL_OUT_POINT v2', PREFType.PREF_Type_MACHINE_INDEPENDENT); STILL_TIME = still_time.slice(0, still_time.indexOf("/")) var trg_folder = app.project.items.addFolder("cell comp") for (var i = 0; i < selItems.length; i++) { var layer = selItems[i]; if (layer.duration) { dura = layer.duration } else { dura = STILL_TIME / 30 } if (layer.frameRate) { fram = layer.frameRate } else { fram = 24 } if (layer.pixelAspect) { pixe = layer.pixelAspect } else { pixe = 1 } var nnm if (layer.name.indexOf("[") + 1) { nnm = layer.name.slice(0, layer.name.indexOf("[")) } else { nnm…- 0
- 0
- 122
-
【AE脚本案例】储存加载关键帧
/** * 保存&加载 关键帧 * 默认有5组,重复保存会覆盖 * 上方为保存,下方为加载 * 按住SHIFT点击保存,可以设置名称 * * * If run as a kbar Script button: * • Specify a unique Kbar Argument to save/restore that key set * • You can have as many simultaneous sets, as long as each as a unique name * • Press the button to SAVE * • Hold SHIFT to LOAD that selection. * * @author Zack Lovatt <zack@zacklovatt.com> * @version 0.1.2 */ (function keySets(thisObj) { var NUM_SETS = 5; $._keySetsCache = $._keySetsCache || {}; var ui = createUI(thisObj); if (ui instanceof Window) { if (typeof kbar !== "undefined" && kbar.button && kbar.button.argument !== "") { // ran as script, with kbar var argument = kbar.button.argument; _quickKbarAction(argument); } else { // run as script, not kbar ui.show(); } } else { // set window layout ui.layout.layout(true); } /** * Quickly stores or loads a given ID * * @param {string} cacheID Cache ID to save to */ function _quickKbarAction(cacheID) { if (ScriptUI.environment.keyboardState.shiftKey) { restoreSelection(cacheID); } else { storeSelection(cacheID); } } /** * Builds UI * * @returns {Window | Panel} Created window */ function createUI(thisObj) { var win = thisObj instanceof Panel ? thisObj : new Window("palette", "Key Sets",…- 0
- 0
- 192
-
【脚本案例】获取属性表达式的完整层级
介绍 选择一个属性,运行脚本 A函数(数字版):thisComp.layer(2)(5)(6) B函数(文字版):thisComp.layer("文字图层")("变换")("缩放"); 其他 1.想要获取匹配名,可以把文字版的name改成matchName。返回:thisComp.layer("ADBE Text Layer")("ADBE Transform Group")("ADBE Scale"); 2.想要外部引用合成,请把函数里的注释打开。返回:comp("合成 1").layer("文字图层")("变换")("缩放"); 来源 https://terriblejunkshow.com/tutorial/proptoexpstr 源码 // 获取属性的表达式的数字层级 function mGetDotSyntaxForExp(aProp) { var mProp = aProp; var mAdrs = []; // 按照从上到下的顺序处理父属性。 for (var i = mProp.propertyDepth; i >= 1; i--) { var mPropTmp = mProp.propertyGroup(i); if (i === mProp.propertyDepth) { mAdrs.push(mPropTmp.index); } else { mAdrs.push(mPropTmp.propertyIndex); } } //自身处理。 mAdrs.push(mProp.propertyIndex); //生成字符串 var mAdrsStr = mAdrs.join(')('); mRstAdrsStr = 'thisComp.layer(' + mAdrsStr + ');' //是否外部引用合成 /* var mSl = mProp.propertyGroup(mProp.propertyDepth); var mAi = mSl.containingComp; var mAiName = mAi.name; mRstAdrsStr = 'comp("' + mAiName + '").layer(' + mAdrsStr + ');' */ return mRstAdrsStr; } // 获取属性的表达式的名称层级 function mGetDotSyntaxForExpName(aProp) { var mProp = aProp; var mAdrs = []; // 按照从上到下的顺序处理父属性。 for (var i = mProp.propertyDepth; i >= 1; i--) { var mPropTmp = mProp.propertyGroup(i); mAdrs.push('"' + mPropTmp.name + '"'); } //自身处理。 mAdrs.push('"' + mProp.name + '"'); //生成字符串 var mAdrsStr = mAdrs.join(')('); mRstAdrsStr = 'thisComp.layer(' + mAdrsStr + ');' //是否外部引用合成 /* var mSl = mProp.propertyGroup(mProp.propertyDepth); var mAi = mSl.containingComp; var mAiName = mAi.name; mRstAdrsStr = 'comp("' + mAiName + '").layer(' + mAdrsStr + ');' */ return mRstAdrsStr; } var selLayer = app.project.activeItem.selectedLayers[0] var selProp = mGetDotSyntaxForExp(selLayer.selectedProperties[0]) //thisComp.layer(2)(5)(6); var selProp = mGetDotSyntaxForExpName(selLayer.selectedProperties[0]) // thisComp.layer("111")("变换")("缩放");- 0
- 0
- 204
-
【脚本案例】将变换的关键帧修复到邻近整数关键帧
源网址:https://sundstedt.se/blog/ae-script-nudge-keyframes-to-nearest-exact-frame/ 介绍 将关键帧修复到邻近整数关键帧 优化版可以参见本站对齐整数帧V1.2 注意 该脚本适用于所有变换关键帧,即锚点、位置、缩放、旋转和不透明度。不会处理任何效果关键帧。也不保留插值方法! 源码 // asu_NudgeKeyFrames.jsx // Copyright (c) 2010 sundstedt.se (Anders Sundstedt). All rights reserved. // check it: http://www.aescripts.blogspot.com/ // // Name: asu_NudgeKeyFrames // souce:https://sundstedt.se/blog/ae-script-nudge-keyframes-to-nearest-exact-frame/ // Version: 1.1 // // Description: // This script moves all keyframes to the nearest matching keyframe for the framerate of that comp // Note: It handles AnchorPoint, Position, Scale, Rotation and Opacity keyframes. // Note: Existing keyframes are removed prior to creating the adjusted (nudged) keyframe // // Usage: Just run this script on any open project (make sure you save project first just in case). // Script has been tested using Adobe After Effects CS3 and works for me but may still need improvements. // Originally requested by David Aughenbaugh // // 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. // ***Modified April 2008 by Mary Snyder (mary@pxlgirl.com)*** // ***In this version of the script, you must have layers selected within a comp.*** // ***Otherwise, the script will generate an error.*** var proj = app.project; var…- 0
- 0
- 117
-
[AE脚本示例] 遍历效果并创建文件夹
今天我想做做内置效果笔记, 于是想先遍历所有效果, 并创建对应的.md文件 用到的脚本方法与关键点 effects fsName (文件的特定平台的完整路径名) 源码 var effects = app.effects; var effects_store = {}; // 引入File类 var File = File || $.global.File; // 获取当前脚本文件所在的文件夹路径 var scriptFile = File($.fileName); var scriptFolder = scriptFile.parent.fsName; // 遍历所有效果 for (var i = 0; i < effects.length; i++) { var effect = effects[i]; var cat = effect.category; // 将效果添加到字典中 if (!effects_store.hasOwnProperty(cat)) { effects_store[cat] = []; } effects_store[cat].push(effect.displayName); } // 遍历储存的效果字典 for (var category in effects_store) { if (effects_store.hasOwnProperty(category)) { var effs = effects_store[category]; // 有的效果没有分类, 所以分类名为空, // 如果你也想获取这些效果, 请在else里处理 if (category) { // 创建文件夹,文件夹名字为 category // 保存在脚本目录下的cache目录里 var folderPath = scriptFolder + "/cache/" + category; var folder = new Folder(folderPath); if (!folder.exists) { folder.create(); } // 遍历effs,并创建文件 for (var i = 0; i < effs.length; i++) { var fileName = effs[i] + ".md"; // 文件名为效果名称 var filePath = folderPath + "/" + fileName; // 打印下文件路径吧 $.writeln(filePath); var file = new File(filePath); if (!file.exists) { file.open("w"); file.close(); } } } } }- 0
- 0
- 249
-
【脚本案例】移动属性组关键帧,类型不变
从rd_Scooter 脚本拆解出来的 源码 var propGroup = app.project.activeItem.layer(1) //定义属性组,图层也是属性组 rd_Scooter_scootAllPropGroupKeys(propGroup, -10) //偏移-10秒 function rd_Scooter_shiftKeyToNewTime(prop, keyToCopy, offset, keyToRemove) { // Remember the key's settings before creating the new setting, just in case creating the new key affects keyToCopy's settings // 记住旧关键帧的设置,然后基于该设置,创建新关键帧 var inInterp = prop.keyInInterpolationType(keyToCopy); // 入点插值类型 var outInterp = prop.keyOutInterpolationType(keyToCopy); //出点插值类型 var keyToCopyValue = prop.keyValue(keyToCopy); // 关键帧值 // 判断贝塞尔 if ((inInterp === KeyframeInterpolationType.BEZIER) && (outInterp === KeyframeInterpolationType.BEZIER)) { var tempAutoBezier = prop.keyTemporalAutoBezier(keyToCopy); var tempContBezier = prop.keyTemporalContinuous(keyToCopy); } if (outInterp !== KeyframeInterpolationType.HOLD) { var inTempEase = prop.keyInTemporalEase(keyToCopy); var outTempEase = prop.keyOutTemporalEase(keyToCopy); } if ((prop.propertyValueType === PropertyValueType.TwoD_SPATIAL) || (prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL)) { var spatAutoBezier = prop.keySpatialAutoBezier(keyToCopy); var spatContBezier = prop.keySpatialContinuous(keyToCopy); var inSpatTangent = prop.keyInSpatialTangent(keyToCopy); var outSpatTangent = prop.keyOutSpatialTangent(keyToCopy); var roving = prop.keyRoving(keyToCopy); } // Create the new keyframe // 创建新关键帧 var newTime = prop.keyTime(keyToCopy) + offset; var newKeyIndex = prop.addKey(newTime); prop.setValueAtKey(newKeyIndex, keyToCopyValue); if (outInterp !== KeyframeInterpolationType.HOLD) { prop.setTemporalEaseAtKey(newKeyIndex, inTempEase, outTempEase); } // Copy over the keyframe settings prop.setInterpolationTypeAtKey(newKeyIndex, inInterp, outInterp); if ((inInterp === KeyframeInterpolationType.BEZIER) && (outInterp === KeyframeInterpolationType.BEZIER) && tempContBezier) { prop.setTemporalContinuousAtKey(newKeyIndex, tempContBezier); prop.setTemporalAutoBezierAtKey(newKeyIndex, tempAutoBezier); // Implies Continuous, so do after it } if ((prop.propertyValueType === PropertyValueType.TwoD_SPATIAL) || (prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL)) { prop.setSpatialContinuousAtKey(newKeyIndex, spatContBezier); prop.setSpatialAutoBezierAtKey(newKeyIndex, spatAutoBezier); // Implies Continuous, so do after it prop.setSpatialTangentsAtKey(newKeyIndex,…- 0
- 0
- 146
-
[AE脚本示例]一个标记管理器
简单的获取设置标记 Get: 当前选择图层 => 获取图层标记, 否则获取合成的 Set: 当前选择图层 => 设置图层标记, 设置获取合成的 放置 要丢在 scrip Ui 文件夹里 代码 // Author: 月离 // Version: 0.0.1 // 链接: https://www.yuelili.com/?p=22409 // Get: 当前选择图层 => 获取图层标记, 否则获取合成的 // Set: 当前选择图层 => 设置图层标记, 设置获取合成的 var panelGlobal = this; var palette = (function () { /* Code for Import https://scriptui.joonas.me — (Triple click to select): {"activeId":2,"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"enabled":true,"varName":"","windowType":"Palette","creationProps":{"su1PanelCoordinates":false,"maximizeButton":false,"minimizeButton":false,"independent":false,"closeButton":true,"borderless":false,"resizeable":false},"text":"Marker","preferredSize":[0,0],"margins":16,"orientation":"column","spacing":10,"alignChildren":["center","top"],"item-1":{"id":1,"type":"Button","parentId":0,"style":{"enabled":true,"varName":null,"text":"Get","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null,"item-2":{"id":2,"type":"Button","parentId":0,"style":{"enabled":true,"varName":null,"text":"Set","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null},"order":[0,1,2],"settings":{"importJSON":true,"indentSize":false,"cepExport":false,"includeCSSJS":true,"showDialog":true,"functionWrapper":true,"afterEffectsDockable":true,"itemReferenceList":"None" */ // PALETTE // ======= var palette = (panelGlobal instanceof Panel) ? panelGlobal : new Window("palette"); if (!(panelGlobal instanceof Panel)) palette.text = "Marker"; palette.orientation = "column"; palette.alignChildren = ["center", "top"]; palette.spacing = 10; palette.margins = 16; var button1 = palette.add("button", undefined, undefined, { name: "button1" }); button1.text = "Get"; var button2 = palette.add("button", undefined, undefined, { name: "button2" }); button2.text = "Set"; var marker_time = [] button1.onClick = function () { app.beginUndoGroup("Get Marker Time"); var comp = app.project.activeItem; var selLayers = comp.selectedLayers; if (selLayers.length > 0) { marker_time = get_layer_marker_time(selLayers[0]) } else { marker_time = get_comp_marker_time(comp) } app.endUndoGroup(); } button2.onClick = function () { app.beginUndoGroup("Set Marker Time"); var comp = app.project.activeItem; var selLayers = comp.selectedLayers; if (selLayers.length > 0 && marker_time) { set_layer_marker_time(selLayers[0], marker_time) } else { set_comp_marker_time(comp, marker_time) } app.endUndoGroup(); } /** * @description:获取合成标记时间列表 * @param comp :合成 * @returns…- 0
- 0
- 280
-
【脚本案例】表达式解析 (未完)
var selpropList = app.project.activeItem.selectedProperties var selLayers = app.project.activeItem.selectedLayers if (selLayers.length == 1) { trg_layer = selLayers[0] } else { trg_layer = selLayers[1] } if (selpropList.length > 0) { for (var i = 0; i <= selpropList.length; i++) { if (selpropList[i] instanceof PropertyGroup) { continue } else { selprop = selpropList[i] exp_text = selpropList[i].expression break } } json_exp = { "wiggle": [{ "info": "随机抖动,基于当前属性,返回对应维度的值" }, [["freq", "频率", "slide"], ["amp", "振幅", "slider"]]] } // 判断是否存在 for (prop in json_exp) { res = exp_text.indexOf(prop) if (res > -1) { reg = new RegExp(prop + '(?=\\().+\\)', 'ig') var rep_txt = "" var extra_exp = "" for (var i = 0; i < json_exp[prop][1].length; i++) { para = json_exp[prop][1][i][0] rep_txt = rep_txt + para + "," extra_exp = extra_exp + para + " = " + 'thisComp.layer("' + trg_layer.name + '")' + '.effect("' + para + '")(1)' + '\n' var eff = trg_layer.property('ADBE Effect Parade').addProperty("ADBE Slider Control") eff.name = para } rep_txt = prop + "(" + rep_txt.slice(0, rep_txt.length - 1) + ")" final_res = extra_exp + exp_text.replace(reg, rep_txt) } } selprop.expression = final_res } else { alert("请至少选择一个属性") }- 0
- 0
- 233
-
【脚本示例】开关选择图层所有属性的表达式
/** * 开关选择图层所有属性的表达式,如果开启,则关闭。如果关闭则开启 * * @author Zack Lovatt <zack@zacklovatt.com> * @version 0.2.0 */ (function() { /** * Recursively loops through all properties and disables found expressions * 递归遍历所有属性,并禁用表达式 * @param {PropertyGroup} propertyGroup Property group to loop through */ function recursiveDisableExpressions(propertyGroup) { for (var ii = 1; ii <= propertyGroup.numProperties; ii++) { var property = propertyGroup.property(ii); if (property instanceof PropertyGroup) { recursiveDisableExpressions(property); continue; } if (!property.canSetExpression) { continue; } try { if (property.expressionEnabled === true) { property.expressionEnabled = false; } else{ property.expressionEnabled = true; } } catch (error) { continue } } } app.beginUndoGroup('Disable All Comp Expressions'); if (!(comp && comp instanceof CompItem)) { alert('Open a comp!'); return; } // 遍历合成(我觉得不合理,改成遍历选择图层了 // for (var ii = 1; ii <= comp.numLayers; ii++) { // var layer = comp.layer(ii); var comp = app.project.activeItem; var layerNumber = comp.selectedLayers.length; var slLayers = comp.selectedLayers; for (var ii = 0; ii < layerNumber; ii++) { var layer = slLayers[ii]; recursiveDisableExpressions(layer); } app.endUndoGroup(); })();- 0
- 0
- 105
-
PSR归零
//熊猫 function sseett(ll) { //ll.property(String('castsShadows')).setValue(0); //ll.property(String('acceptsShadows')).setValue(0); //ll.property(String('acceptsLights')).setValue(0); ll.property(String('scale')).setValue([0,0,0]); ll.property(String('position')).setValue([0,0,0]); ll.property(String('rotation')).setValue(0); } var comp = app.project.activeItem; if(comp && comp.selectedLayers.length > 0){ for(var i = 0 ; i < comp.selectedLayers.length ; i++){ var layer = comp.selectedLayers[i]; sseett(layer); }; }else{ alert('您没有选中图层。'); };- 0
- 0
- 150
-
【AE脚本】PropDrive 属性效果管理器 | 免费
https://terriblejunkshow.com/manual/howtousepropdrive 简介 如果需要对属性、关键帧、效果进行批处理。比如同时关闭含该属性的图层眼睛,删除效果之类的。说明太长 懒得翻译。 界面截图 使用方法 选择属性或者效果 然后单击“GetInfo”按钮以获取有关该属性的各种信息。 选择喜欢的图层 如果应用列中选择“所有图层”,则不需要选择图层。在整个合成中搜索该属性。 如果选择 SelectedLayers,则处理选定的图层。 批处理列表 从列表中选择一个进程并双击它。即可分批处理! 参数 & copy:如果选中,当您使用GetInfo 获取信息时,将复制该属性。如果你想粘贴关键帧,后面会有用处。 regex for Incl:如果勾选,去掉name字段中name后面的“空格或连字符或下划线+数字”,并在正则表达式中添加各种条件“包括~”。可以添加的函数)。 可以通过打开和关闭检查来添加或删除它,因此如果您认为“我想处理包括名称在内的所有内容”,只需将其打开。 可以添加的正则表达式为“.” “.”代表某个字符,“”代表0次或多次重复。 获取信息字段 根属性(Root Prop):所选属性顶部的属性。也可以说是图层正下方的一个属性。 例如,如果选择形状路径,则为“内容”,如果选择效果,则为“效果”。 匹配名称(matchName):所选属性的官方名称,由 AE 脚本分类。 *只有当你真的想一次操作不同类型的属性时,才可以将其留空。在这种情况下,您可能还需要将 root Prop 留空。 名称(name):名称。如果可以通过属性类型搜索处理目标(例如,“我想消除所有分形噪声,无论名称如何”),请清除右侧的复选框。 propertyIndex:属性的编号。说到效果,效果栏最上面是1。当您只想关闭效果数量时,请选中此项。 propertyDepth:属性在哪一层?是。对于形状路径等复杂层次的属性,在“我想删除组1中的路径,但我想保留组1中的组2的路径”的情况下检查它。 自定义值:应用列下方的列。如果要对值进行处理,可以将原始值放在这里进行处理,但GetInfo会自动输入选中属性的值,以了解值的形状。如果该属性没有值,则输入为未定义。 可输入的形式因参数而异,例如一个参数一个数值,两个参数用逗号分隔的两个数值。格式请参考取件结果。[] 两个或多个数字(数组)不需要。 ■ 批量处理列表 Del Key at Indicator:如果指标时间有key,则将其删除。 Eye OnOff:打开和关闭眼球标记。 选择和删除:选择并执行与按键盘上的“del”相同的操作。如果选择的参数是参数,则删除所有关键帧,如果该属性不是参数且可以删除,则删除该属性本身。 选择并粘贴:选择并执行与按键盘上的“Ctrl + V”相同的操作。如果选中 & Copy,则可以轻松粘贴关键帧。 如果您想粘贴属性本身但不起作用,请注意以下几点。 如果要复制粘贴某个属性,正常的操作是选择“该属性的父属性”,然后按Ctrl+V。我想重现它,所以先正常选择属性,用Ctrl + C复制它,选择它的父属性,取消选中&复制和GetInfo。现在,GetInfo 获取的 parent 属性将被批量处理。您所要做的就是按“选择并粘贴”。 此外,在效果的情况下,您所要做的就是选择一个图层并复制和粘贴。 选择:选择。 设置自定义键:按当前指标时间在“自定义值”字段中输入的值的键。您可以设置 Select & Paste 无法设置的原始值。 设置自定义值或键:将在“自定义值”字段中输入的值应用到当前指标时间。如果该属性具有现有键,则点击该键,否则应用静态值。您可以设置 Select & Paste 无法设置的原始值。 (NotToUse) Del All Key in the folder :擦除所有关键帧。效果与选择和删除相同。 Del Prop:擦除所有属性。效果与选择和删除相同。 查找隐藏的道具:如果检索到的属性中有隐藏的属性,它们会提醒您它们的图层索引、名称和父属性名称。 关于 forPropDrive 文件夹 这包含处理列中描述的处理脚本。 您可以通过在此处进行更改来自由组织流程。 如果你说“我不需要这个过程”,你可以把它放在(不使用)文件夹中,它不会显示在列表中。 如果要更改名称,可以随意更改每个 jsx 的文件名。也支持日语,但不推荐。 如何制作一个原始的过程 在ShapeDrive和EffectsDrive中,在文中写流程是一个规范,但是难度比较大,所以选择了jsx的读取方式。 创建一个原始进程,将其封装在一个立即函数中,将其放入“forPropDrive 文件夹”中,就大功告成了。 可以使用的变量如下。 props:所有属性的知情数组。 valueTxt:“自定义值”字段中的字符串。 valueObj:如果是对象,则包含GetInfo获取的属性的对象。 hiddenProps:隐藏属性(隐藏)检查为真的属性数组。由于 props 省略了预先隐藏,因此 props 中没有隐藏的 Props。 对于撤消组,您不必编写 app.beginUndoGroup() 和 app.endUndoGroup(),因为它们在 PropDrive 中。 如果在PropDrive端做类型推断和for语句,原来处理中能做的事情也是有限的,所以我们把它们改成在处理脚本中做的规范。 每种方法都可以在After Effects Script Reference网站上确认。 PropertyBase 对象、PropertyGroup 对象、Property 对象子页面“属性”和“方法”以及图层属性匹配名称很有帮助。 如果您收到有关隐藏的警报 如果基于该信息获取的属性组中存在“AE UI 中未显示但存在”的隐藏属性,则会发出以下警报。 有些属性是隐藏的。 脚本无法处理隐藏的属性。 继续吗? 隐藏的属性不能被脚本处理,所以如果你想“继续处理而不对隐藏的属性做任何事情”,请按是。如果您不想处理它,请按否。由于它是在AE中实际更改某些内容的过程之前,因此按No并不意味着该过程在奇怪的地方结束。 ■ 隐藏属性示例 相机、光比例等。 未应用图层样式的各种图层样式。 与插件部分(ver4)的“ShowSystems”设置为非零时的编号不对应的系统属性。这可以通过预先准备来避免,例如在批处理中将 ShowSystems 设置为零(显示全部)。- 0
- 0
- 598
-
【AE脚本】计算关键帧间隔帧数
原贴:https://www.bilibili.com/read/cv12796485 作者:JoffeeLin 功能:计算关键帧间隔帧 特性:选择多个关键帧时,计算的是头尾两个关键帧的间隔帧数 //by JoffeeLin //link:https://www.bilibili.com/read/cv12796485 var myWindow; var myPalette = buildUI(this); if (myPalette != null && myPalette instanceof Window) { myPalette.show(); } function buildUI(thisObject) { if (thisObject instanceof Panel) { myWindow = thisObject; } else { myWindow = new Window("window", "窗口",undefined,{resizeable:true}); // 可选参数 dialog palette window } //创建面板 myWindow.myPanel = myWindow.add("group"); // 可选参数 panel group myWindow.myPanel.orientation = "column"; // 可选参数 row column myWindow.myPanel.alignment = ['left','left']; myWindow.myPanel.alignChildren = ['left','left']; //往面板里添加按钮 //myWindow.myPanel.resultLabel = myWindow.myPanel.add("statictext",[0,0,200,20],"请选择关键帧",{multiline:true}); myWindow.myPanel.okButton = myWindow.myPanel.add("button",[0,0,200,20]); myWindow.myPanel.okButton.text = "w(゚Д゚)w"; myWindow.layout.layout(true); myWindow.layout.resize(); myWindow.onResizing = myWindow.onRize = function(){this.layout.resize();} myWindow.myPanel.okButton.onClick = onPressed } function setResult(txt) { if (myWindow && myWindow.myPanel && myWindow.myPanel.okButton) { //myWindow.myPanel.resultLabel.text = txt myWindow.myPanel.okButton.text = txt } } function onPressed() { //参数 var thisComp = app.project.activeItem; var mSp = thisComp.selectedProperties; var count = 0; // 条件检查 if (!thisComp || !(thisComp instanceof CompItem)) { setResult("没有选中合成") return } else if (mSp.length < 1) { setResult("没有选中属性"); return } // 统计 var count = countKeys(mSp); //如果关键帧数量大于2 if (count >= 2) { var maxmin = maxminTime(mSp); var z = maxmin.max - maxmin.min; setResult((z * thisComp.frameRate).toFixed(1) +"帧") } // 如果关键帧数量小于2 if (count < 2) { setResult("请选择两个以上关键帧"); } }; //统计所选关键帧个数 function countKeys(sp) { var total = null; for (i = 0; i < sp.length; i++) {…- 0
- 0
- 413
-
【脚本示例】随机添加效果
/** * souce:https://github.com/zlovatt/zl_Scriptlets * Adds a random AE effect to selected layers. * * @author Zack Lovatt <zack@zacklovatt.com> * @version 1.0.1 */ (function addRandomEffect() { var comp = app.project.activeItem; if (!(comp && comp instanceof CompItem)) { alert('Open a comp!'); return; } var layer = comp.selectedLayers[0]; if (!layer) { alert('No layer selected!'); return; } var layerEffects = layer.property('ADBE Effect Parade'); var numEffects = app.effects.length; var randomEffectNumber = numEffects * Math.random(0, numEffects - 1); var randomEffect = app.effects[Math.floor(randomEffectNumber)]; app.beginUndoGroup('Add Random Effect'); if (layerEffects.canAddProperty(randomEffect.matchName)) { layerEffects.addProperty(randomEffect.matchName); } app.endUndoGroup(); })();- 0
- 1
- 209
-
【AE脚本】对齐整数帧V1.2
介绍 在使用alt拖拽关键帧时,你一定遇到过,拖时一时爽,拖完火葬场(拖后关键帧可能不是整数)这时候本脚本就派上用场啦 ### 修复前 修复后 更新 V1.0 @草哥 首发 V1.1 @RaymondClr 完善 源码V1.1 //将所有选择属性的关键帧对齐到整数帧 v1.0.10 2021-07-30 //Raymond Yan 2021 (RaymondClr@outlook.com / QQ: 1107677019) ('use strict'); var win = new Window(palette { A: Button {text: '对齐关键帧' } }); win.show(); win.A.onClick = function () { var activeItem = getActiveItem(); if (!activeItem) return; var selectedProperties = getSelectedProperties(activeItem); if (!selectedProperties) return; var valueProperties = getSelectedValueProperties(selectedProperties); if (valueProperties.length === 0) return; app.beginUndoGroup('Align Keyframes'); alignKeyframes(activeItem.frameRate, valueProperties); app.endUndoGroup(); }; function getActiveItem() { var activeItem = app.project.activeItem; return activeItem instanceof CompItem ? activeItem : false; } function alignKeyframes(frameRate, valueProperties) { for (var i = 0, l = valueProperties.length; i < l; i++) { setNewKeyframes(frameRate, valueProperties[i]); } } function getSelectedProperties(activeItem) { return ( activeItem instanceof CompItem && activeItem.selectedLayers.length > 0 && activeItem.selectedProperties.length > 0 && activeItem.selectedProperties ); } function getSelectedValueProperties(selectedProperties) { var valuePropertiesArr = []; for (var i = 0, l = selectedProperties.length; i < l; i++) { var property = selectedProperties[i]; if (!(property.propertyType === PropertyType.PROPERTY)) continue; valuePropertiesArr.push(selectedProperties[i]); } return valuePropertiesArr; } function setNewKeyframes(frameRate, valueProperty) { for (var i = valueProperty.numKeys; i > 0; i--) { var keyValue = valueProperty.keyValue(i); var newKeyTime = Math.round(valueProperty.keyTime(i) * frameRate) / frameRate; valueProperty.removeKey(i); valueProperty.setValueAtTime(newKeyTime, keyValue); } } 源码V1.2 //将所有选择属性的关键帧对齐到整数帧 v1.0.2 2021-07-31 //Raymond Yan…- 0
- 0
- 533
-
[AE脚本] 笔记向: 获取所有效果的更改参数
最近在学赤动的教程, 顺手想写写笔记, 但是效果太多了而且截图好麻烦, 于是写个脚本, 用来获取已选图层上, 所有效果中, 参数更改的内容, 并发送到剪切板, 效果如下 ____________ Curves ____________ VC Color Vibrance Brightness: 0.5 Matte Alpha: 2 ____________ Glow Glow Radius: 100 ____________ Glow 2 Glow Threshold: 97.5 Glow Radius: 100 更新 2023/7/20: 修复某些属性获取不了的问题, 加了个try顶一下, 暂时没空研究 2023/7/6: 追加表达式更改检测 脚本源码 只需复制内容, 新建一个getAllChangeProperties.jsx 文件,然后记事本打开, 粘贴进去, 再用ae调用即可 // 源码: https://www.yuelili.com/?p=22695 // 介绍: 获取当前选择图层所有效果已更改的属性名和数值 // 字符串发送到剪切板 function copyToClipboard(text) { var tempFile = new File(Folder.temp.fullName + "/temp.txt"); tempFile.open("w"); tempFile.write(text); tempFile.close(); if (Folder.fs === "Windows") { var cmdCommand = 'cmd.exe /c cmd.exe /c "type ' + tempFile.fsName + ' | clip"'; system.callSystem(cmdCommand); } else if (Folder.fs === "Macintosh") { var osaCommand = 'cat "' + tempFile.fsName + '" | pbcopy'; system.callSystem("osascript -e '" + osaCommand + "'"); } else { alert("Unsupported operating system."); } // 删除临时文件 tempFile.remove(); } var activeComp = app.project.activeItem; if (activeComp instanceof CompItem) { var selectedLayer = activeComp.selectedLayers[0]; if (selectedLayer) { var effects = selectedLayer.property("ADBE Effect Parade"); var result = "" // 遍历所有效果 for (var i = 1; i <= effects.numProperties; i++) { var effect = effects.property(i); // 检查效果是否被更改 if (effect.isModified) { var effectName = effect.name; result += "\n\n---\n\n"; result += "\n" + effectName; var numProperties = effect.numProperties; // 遍历属性 for (var j = 1; j <= numProperties; j++) {…- 0
- 0
- 668
-
【AE脚本】案例:移除所选图层的所有表达式
介绍 选择一个或者多个图层,会移除它们的所有表达式 ## 知识点 属性组/属性循环遍历:下面的[yl_keyword]recurse_children[/yl_keyword]函数 ## 源码 // 名称:移除所选图层的表达式 // 来源: // 源码:https://www.yuelili.com/?p=10427 app.beginUndoGroup(Remove all Expressions); { var comp = app.project.activeItem; var layerNumber = comp.selectedLayers.length; var chosenLayers = comp.selectedLayers; if (layerNumber >= 1) { for (var i = 0; i < layerNumber; i++) { var layerNames = chosenLayers[i].index; recurse_children(comp.layers[layerNames]); } } else { alert('no layer selected'); } function recurse_children(propParent) { if (propParent != null) { var prop; for (var i = 1; i <= propParent.numProperties; i++) { prop = propParent.property(i); switch (prop.propertyType) { case PropertyType.PROPERTY: if (prop.canSetExpression && prop.expression) prop.expression = ''; break; case PropertyType.INDEXED_GROUP: recurse_children(prop); break; case PropertyType.NAMED_GROUP: recurse_children(prop); break; default: break; } } } } } app.endUndoGroup();- 0
- 0
- 258
-
【AE脚本】基于选择的属性,开启/关闭表达式
/** * @author fabiantheblind * @description enable expression * @source:https://github.com/ff6347/after-effects-script-snippets/blob/master/disable-expression.jsx * * @todo [description] */ /** * This snippet disables/enables all sellected expressions * */ var curComp = app.project.activeItem; app.beginUndoGroup('disable expression'); for(var i = 0; i < curComp.selectedProperties.length; i++) { //如果当前属性开启表达式 则关闭,反之开启 var prop = curComp.selectedProperties[i]; if(prop.expressionEnabled === false) { prop.expressionEnabled = true; }else{ prop.expressionEnabled = false; } } app.endUndoGroup();- 0
- 0
- 340