-
[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脚本】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脚本】对齐整数帧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脚本】获取本工程所有效果,并发送到剪切板
代码 /** * @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
-
【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脚本】计算关键帧间隔帧数
原贴: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
-
【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脚本]批量删除表达式
表达式批量删除脚本。如果选择特定属性,只删除该属性的表达式。如果选择图层,则删除图层设置的所有表达式。 如果把它放在 ScriptUI Panels 文件夹中,它有一个 UI,如果你把它放在 Scripts 文件夹中,可以在没有 UI 的情况下工作。 /*------------------------------------- Select Parents N Children Version History 1.0.1 [Current version] - Aug 16, 2021 Change file name. 1.0.0 - Aug 13, 2021 Initial release -------------------------------------*/ //______Files Path______ var thisFile = new File(this); var thisFolderPath = thisFile.path; var resourcePath = thisFolderPath + "/Remove Expressions Resources" //______Build Main Panel______ function buildUI(thisObj){ if(thisObj instanceof Panel){ var win = thisObj; }else{ /* var win = new Window("palette", "Remove Expressions", [0, 0, 116, 236], {resizeable:true}) win.center(); win.show(); */ removeExpressions(); } return win; } try{ var win = buildUI(this); var buttonRect = [0, 0, 100, 30]; var panelButtonSpace = [5, 5, 5, 5]; var buttonSpace = [55, 0, 55, 0]; var buttonA = win.add("Button", panelButtonSpace + buttonRect, "Remove!"); function removeExpressions(){ app.beginUndoGroup("Remove all Expressions"); var comp = app.project.activeItem; var layerNumber = comp.selectedLayers.length; var slLayers = comp.selectedLayers; var slProp; var propNumber; if(layerNumber >= 1){ for(var i = 0; i < layerNumber; i++){ if(slLayers[i].selectedProperties.length >= 1){ deleteAllExpMenuCmd(); }else{ var layerNames = slLayers[i].index; recurse_children(comp.layers[layerNames]); } } }else{ alert('no layer selected'); } function deleteAllExpMenuCmd(){ slProp; for(var i = 0; i < layerNumber; i++){ for(var k = 0; k < slLayers[i].selectedProperties.length; k++){ slProp = slLayers[i].selectedProperties[k]; if(slProp.canSetExpression && slProp.expression) slProp.expression = ''; }…- 0
- 0
- 354
-
【AE脚本】NT - 批量导入表达式(位置、缩放、不透明度)
[sc name="zhuanzai" author="NT" link="https://github.com/NTProductions/basic-expression-injector/blob/master/Expression%20Injector.jsx" ][/sc] 备注:我稍微改了下文字编辑区 //UI 构建 var mainWindow = new Window("palette", "表达式插入器", undefined); mainWindow.orientation = "column"; // 下拉菜单 var groupOne = mainWindow.add("group", undefined, "groupOne"); groupOne.orientation = "row"; groupOne.alignment = "left"; var dropDown = groupOne.add("dropdownlist", undefined, ["位置", "缩放", "不透明度"]); dropDown.selection = 0; // 表达式编辑区 var groupTwo = mainWindow.add("group", undefined, "groupTwo"); groupTwo.orientation = "row"; var expressionText = mainWindow.add('edittext {size: [200,80], properties: {name: "expressionText", multiline: true'); expressionText.text = "请输入表达式"; // 应用按钮 var groupThree = mainWindow.add("group", undefined, "groupThree"); groupThree.orientation = "row"; groupThree.alignment = "right"; var applyButton = groupThree.add("button", undefined, "应用表达式"); mainWindow.center(); mainWindow.show(); applyButton.onClick = function () { if (app.project.activeItem.selectedLayers.length < 1) { alert("请先选择图层", ""); return false; } else { app.beginUndoGroup("Expression Injection"); injectExpression(app.project.activeItem.selectedLayers); app.endUndoGroup(); } } function injectExpression(layerArray) { for (var i = 0; i < layerArray.length; i++) { layerArray[i].property(getPropertyName()).expression = expressionText.text; } alert("成功应用!", ""); } function getPropertyName() { switch (dropDown.selection.index) { case 0: return "Position"; break; case 1: return "Scale"; break; case 2: return "Opacity"; break; } }- 0
- 0
- 341
-
【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
-
【AE脚本】以播放头前一个关键帧的速度添加关键帧 | 熊猫 | 免费
//以播放头前一个关键帧的速度添加关键帧 //当属性极限值达不到播放头时间时,则在极限值处添加关键帧。否则在播放头处添加关键帧。 //总结: //关键帧包含入点缓动对象组和出点缓动对象组。属性有几个参数,组里就有几个缓动对象; //但位置属性只有一个缓动对象(y、z共用x的缓动),因为位置属性具有2D/3D空间维度,包含空间切线对象。 //所有具有空间维度的属性其关键帧都有空间切线对象,切线对象是一个坐标数组,数组中所有元素均为0时,此关键帧为空间插值为线性,否则为贝塞尔曲线。 //当一个关键帧的 出点空间切线数据 = -入点空间切线数据 != [0,0,0] 时,曲线最平滑(数组中所有元素的绝对值越大越趋近于直线)。 app.beginUndoGroup("addKey"); if (app.project.activeItem != null && app.project.activeItem instanceof CompItem) { var myComp = app.project.activeItem; var myFrameDuration = myComp.frameDuration; var props = myComp.selectedProperties; for(var i=0; i<props.length; i++){ if(props[i].canVaryOverTime){addkey(props[i])} } function addkey(prop){ var keyIndex = prop.nearestKeyIndex(myComp.time); if(prop.keyTime(keyIndex)>myComp.time){keyIndex--} if(keyIndex){ var speed , inSpeed; var inEase = prop.keyInTemporalEase(keyIndex); if ((prop.propertyValueType === PropertyValueType.TwoD_SPATIAL) || (prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL)) { //具有2D/3D空间维度的属性 if(inEase[0].speed === 0){ speed = 0 }else{ speed = prop.keyInSpatialTangent(keyIndex)/-4; //入点空间切线除以4并反向 if(eval(speed.join("+")) === 0){ //线性空间插值 // 缓动的速度 // speed = function(){ // var keyvalue = prop.keyValue(keyIndex); // var sps = [inEase[0].speed,inEase[0].speed*(keyvalue[1]/keyvalue[0])]; // if(prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL){sps.push(inEase[0].speed*(keyvalue[2]/keyvalue[0]))} // return sps*myFrameDuration // }() //关键帧前百分之一帧的平均速度*100 speed = (prop.keyValue(keyIndex)-prop.valueAtTime(prop.keyTime(keyIndex)-myFrameDuration/100,false))*100; } } }else{ //不具有空间维度的属性 if(inEase.length>1){ inSpeed = []; for(var i=0; i<inEase.length; i++){ inSpeed.push(inEase[i].speed) } }else{ inSpeed = inEase[0].speed; } speed = inSpeed*myFrameDuration; } var timevalue = prop.keyValue(keyIndex)+(myComp.time-prop.keyTime(keyIndex))/myFrameDuration*speed; //指定时间的值 = 最后关键帧值+(指定时间-最后关键帧时间)/合成帧持续时间*最后关键帧速度速度 if(prop.hasMin&&timevalue<prop.minValue){ var mintime = prop.keyTime(keyIndex)+(prop.minValue-prop.keyValue(keyIndex)/speed)*myFrameDuration; //属性允许的最小值所在时间 prop.setValueAtKey(prop.addKey(mintime),prop.minValue) }else if(prop.hasMax&&timevalue>prop.maxValue){ var maxtime = prop.keyTime(keyIndex)+((prop.maxValue-prop.keyValue(keyIndex))/speed)*myFrameDuration; //属性允许的最小值所在时间 prop.setValueAtKey(prop.addKey(maxtime),prop.maxValue) }else{ prop.setValueAtKey(prop.addKey(myComp.time),timevalue) } prop.setTemporalEaseAtKey(keyIndex,inEase,inEase); //把关键帧的出缓动改为跟入一致 prop.setTemporalEaseAtKey(keyIndex+1,inEase,inEase); //设置新关键帧的出入缓动与前一个关键帧一致 if ((prop.propertyValueType === PropertyValueType.TwoD_SPATIAL) || (prop.propertyValueType === PropertyValueType.ThreeD_SPATIAL)) { if(speed === 0){ prop.setSpatialTangentsAtKey(keyIndex,prop.keyInSpatialTangent(keyIndex),prop.keyInSpatialTangent(keyIndex)*0) prop.setSpatialTangentsAtKey(keyIndex+1,prop.keyInSpatialTangent(keyIndex)*0,prop.keyInSpatialTangent(keyIndex)*0) }else{ prop.setSpatialTangentsAtKey(keyIndex,prop.keyInSpatialTangent(keyIndex),prop.keyInSpatialTangent(keyIndex)*-1) prop.setSpatialTangentsAtKey(keyIndex+1,prop.keyInSpatialTangent(keyIndex),prop.keyInSpatialTangent(keyIndex)*-1) //把新关键帧的出入空间切线改为与前一个关键帧出切线一致 } } }else{} } } app.endUndoGroup();- 0
- 0
- 318
-
[AE脚本] 删除有错误的表达式 DelErrorExps
删除当前活动合成中的错误表达式。 复制下面代码到文本txt中,更改扩展名为 DelErrorExps.jsx (function () { app.beginUndoGroup("DelErrorExps"); // 为了确保不会错误地处理项目面板中的一个项目,暂时将查看器设为活动状态。 app.activeViewer.setActive(); var mAi = app.project.activeItem; var mLyrs = mAi.layers; var mAllValProps = []; //检查是否隐藏的常规表达式。 var mRegExpHdn = new RegExp("hidden"); // 从所有的图层中收集带有"value"属性。 for (var i = 1; i <= mLyrs.length; i++) { mAllValProps = mAllValProps.concat(mGetValProps(mLyrs[i])); } //将其中具有可应用表达式且错误消息不为空(即存在错误)的表达式设置为""(空字符串)。 for (var i = 0; i < mAllValProps.length; i++) { var mProp = mAllValProps[i]; if (mProp.canSetExpression && mProp.expressionError !== "" && !(mIsHidden(mProp, mRegExpHdn))) { mProp.expression = ""; } } app.endUndoGroup(); //-------------------------------------------------- //-------------------------------------------------- // 从图层中收集具有"value"属性的属性。 function mGetValProps(aLyr) { var mRstProps = []; mFunc(aLyr); function mFunc(aProp) { if (aProp.propertyType === PropertyType.PROPERTY) { mRstProps.push(aProp); } else { for (var i = 1; i <= aProp.numProperties; i++) { mFunc(aProp(i)); } } } return mRstProps; } //检查属性是否为隐藏状态。请注意关键帧被全部选择的情况。 function mIsHidden(aProp, aRegExpHdn) { try { aProp.selected = aProp.selected; return false; } catch (e) { return aRegExpHdn.test(e.message); } } })(); 用法 当执行这段 JSX 代码时,它将从当前活动合成中提取所有图层的所有属性。然后删除其中存在表达式错误的属性的表达式。 没有用户界面(UI)。 不适用于整个项目。如果要应用于整个项目,这可能会有些麻烦。您需要单击错误消息下方的放大镜图标,在打开的错误合成中逐个执行此 JSX。 如果存在"存在错误但未显示的属性",它们将不会被处理。例如,如果您将图层先设置为3D图层,并对"方向"属性应用表达式,然后出现表达式错误,但将3D开关重新设置为2D,以便消除错误,这种情况将不会被处理。这也可能在图层样式中发生。 解释 目前,您正在从合成中收集所有图层,并使用递归函数收集它们的所有属性。然后,您将对这些属性中的表达式错误不为空的属性(即存在错误的属性)的表达式进行清空处理。第一个空字符串("")用于检查是否存在错误消息,第二个空字符串("")是用于清空表达式的空字符串,请注意它们是不同的。 我也尝试创建了适用于整个项目的版本,但似乎检查表达式错误是否为空字符串(即是否存在错误)的功能在未打开的合成中的行为似乎是不确定的。我认为这与打开的合成中没有在查看器中显示错误警告有关,即使合成中存在具有错误表达式的合成,如果未打开合成,可能不会在查看器中显示错误警告。 另外,关于hidden属性,例如2D图层的"方向"属性或未应用的图层样式等,这些都是"实际上图层已经具有但被隐藏的属性",除非将其显示出来,否则脚本无法处理它们。严格来说,虽然可以处理它们,但无法更改其值等。由于缺乏能够检查hidden属性的方法,您正在使用以下判断函数来处理此类情况。如果出现错误并且错误消息中包含"hidden",则返回true,否则返回false。对于这些函数返回true的属性,您将省略处理。- 0
- 0
- 314
-
【脚本案例】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
-
【脚本案例】导入预设文件 修改合成尺寸
用户需求 导入指定位置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脚本示例]一个标记管理器
简单的获取设置标记 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
-
【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脚本】对齐整数帧V1.0
介绍 在使用alt拖拽关键帧时,你一定遇到过,拖时一时爽,拖完火葬场(拖后关键帧可能不是整数)这时候本脚本就派上用场啦 修复前 修复后 更新 V1.0 @草哥 首发 V1.1 @RaymondClr 完善 源码 var myComp= app.project.activeItem; var allSelLayers = myComp.selectedLayers; var thisCompFrameDuration = myComp.frameDuration; app.beginUndoGroup("Undo 对齐整数帧"); var allSelProperties = []; for(var i=0;i<allSelLayers.length;i++) { var myProperties=allSelLayers[i].selectedProperties; for(var k=0;k<myProperties.length;k++) { allSelProperties.push(myProperties[k]); } } for(var k=0;k<allSelProperties.length;k++) { var allSelKeysArr=allSelProperties[k].numKeys; for(var j=1;j<=allSelProperties[k].numKeys;j++) { var thisKeyValue = allSelProperties[k].keyValue(j); var thisKeyTime = allSelProperties[k].keyTime(j); if( thisKeyTime%thisCompFrameDuration != 0) { var chu = thisKeyTime/thisCompFrameDuration + ""; var intPart = parseInt( chu.split(".")[0] ); var floatPart = parseFloat( "0."+chu.split(".")[1] ); if( floatPart < 0.5 && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration) == j) { allSelProperties[k].removeKey(j); var copyKey = allSelProperties[k].setValueAtTime(intPart*thisCompFrameDuration, thisKeyValue); } if( floatPart < 0.5 && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration) != j && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration+thisCompFrameDuration) == j) { allSelProperties[k].removeKey(j); allSelProperties[k].setValueAtTime(intPart*thisCompFrameDuration+thisCompFrameDuration, thisKeyValue); } if( floatPart < 0.5 && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration) != j && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration+thisCompFrameDuration) != j) { allSelProperties[k].removeKey(j); j--; } if( floatPart >= 0.5 && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration+thisCompFrameDuration) == j) { allSelProperties[k].removeKey(j); var copyKey = allSelProperties[k].setValueAtTime(intPart*thisCompFrameDuration+thisCompFrameDuration, thisKeyValue); } if( floatPart >= 0.5 && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration+thisCompFrameDuration) != j && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration) == j) { allSelProperties[k].removeKey(j); allSelProperties[k].setValueAtTime(intPart*thisCompFrameDuration, thisKeyValue); } if( floatPart >= 0.5 && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration+thisCompFrameDuration) != j && allSelProperties[k].nearestKeyIndex(intPart*thisCompFrameDuration) != j) { allSelProperties[k].removeKey(j); j--; } } } } app.endUndoGroup();- 0
- 0
- 257
-
[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
-
【脚本案例】表达式解析 (未完)
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
-
【脚本案例】关键帧时间复刻
介绍 选择一个带关键帧的属性,单击抓手拾取时间。选择新的属性们,单击应用,会基于时间生成线性关键帧 应用前 应用后 源码 /** * 名称:关键帧时间复刻(或叫关键帧复刻) * 功能:选择一个带关键帧的属性,单击抓手拾取时间。选择新的属性们,单击应用,会基于时间生成线性关键帧 * V1.2 : 忘了每次拾取的时候,把时间列表先清空了 >_< * V1.1 :忘了加撤销组,补上 * V1.0 * 源码:https://www.yuelili.com/?p=18058 */ var panelGlobal = this; var main = (function () { /* Code for Import https://scriptui.joonas.me — (Triple click to select): {"activeId":4,"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"enabled":true,"varName":"main","windowType":"Palette","creationProps":{"su1PanelCoordinates":false,"maximizeButton":false,"minimizeButton":false,"independent":false,"closeButton":true,"borderless":false,"resizeable":false},"text":"提醒保存小助手","preferredSize":[0,0],"margins":16,"orientation":"row","spacing":10,"alignChildren":["center","top"],"item-3":{"id":3,"type":"Image","parentId":0,"style":{"enabled":true,"varName":"catch_img","image":["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAACS0lEQVRIieWWTYhOURjH/6/NlGZYSZMFpcRM5CMki9mILCilxIyYhGQ1WShKKTWl2WiYbLBBPsdi8jmLaUqU2FjZTSYlJh8ZNSNeP536vzneeee991zLeerpnOe5z//+3nPuuc97NeOsVFkwkLL2+ZJ6JU1K6pL0Ka+wVCr9mwjgBH/IX7uWop1iCeKjRrYBOz3fnQqeVeBstXgclvTE82aPg2ENksYkrah3kyzwYkkjvtkF535E1395/CapR9ImSd2SypKGci1jmq35CnwEbntLDwNdnofrDZ6fA74D/c63O99a5BlvrBK/BN4CfRG45PmIx23OX3E8rwh4ucWdjg85HvVOVOrGnR+PcsEGPN8KLE091cEeed4ETDr3Iar54twNxxscXwReR69dd9ihvOD+aFuDX68BflG1zb2Oy8AE0AIcce5MXvA+C9Y6Xu34alSzAFgfxe+iVa50bp3jS3nBTRb05GwQayLo9ig/6tzmvODgb4D3OcGNwGNgf5Q7ZWhHass8YeGihLZa8WZrX2Wd6mXAmIuHgDnAQsd7CoDvWttaD7zF3eezX6GKDXi8kwhts+5sVgO55cJVLpoN3Ix+wHAieNC6xizwMRdervGcTgNLEqBzoyaiLHDwkxbcK/A8Y++oev8zwcGPWzT4H+D7VR0vFzj4QQufFgQT/UUmgYPv8g2eJUIr3auzKDiGp6z8fK3TnAqW21+wBznB5Xq7lAIOfoA0a88Cp3zQ75C0V9KEpJ/+AAz+O6ppkPRcUt90N5nyQT8zTNIfh/Zbfkki7F0AAAAASUVORK5CYII="],"alignment":null,"helpTip":null,"item-4":{"id":4,"type":"Image","parentId":0,"style":{"enabled":true,"varName":"apply_img","image":["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABz0lEQVRIie2WyyvFQRTHP9c7JNkoZUHyKI9sbC1kwcZKSbbIRkphY+NfsCO2ZOORndW1sWF7S1IWEqXIKxJHP82vpuk385vxWvnWNOfeOXc+c2buOTP866+U0TkiEpuzQJPnGt6BXWArzTGTySQPiEiRiKzI19QTLdzVrBKR+S9CIz2ISL4vuMBYRKtmbwBZ8zjMTQKmgXqgDKgAbtK2PAn8pNnrwKbHHH0KLL7QJLC+HzXGWDvQoXxivzegUfMZBR61XSoEjoGDNLBNa8BQik8EW7KMRUc2ApzHX+R5QNs8oGnqBuZ0Hx9w1zehsapCwS8/BH4OBTsynx1gDLgNXYUL/G70SYrObRnoBO6+A87X7Hiie8fva1V/pmr7oy/YTKdizV4AJoBydWm8GVUssnPa50uV53tAne8CPiUiA5Y67Cz+Rhu2zLHqingb6AcWVRlEldFBFbGpfeDa2LGZoGhVxHqrVG3ccSP1av4FInLi8HVGrCtOkSuHz4XqS4EjoME3SJ88LnOMRTncAhwCzb5QX7DrPp5U/+yWEKgvuCR0UouKQsE5Dx8fvVp9HLmZDXh7JelURNp0lu15a6oamFJ9qO7UAyFnfd7+69cEfACTHfD/B8fzSAAAAABJRU5ErkJggg=="],"alignment":null,"helpTip":null},"order":[0,3,4],"settings":{"importJSON":true,"indentSize":false,"cepExport":false,"includeCSSJS":true,"showDialog":true,"functionWrapper":true,"afterEffectsDockable":true,"itemReferenceList":"None" */ // 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 catch_img_imgString = "%C2%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%1E%00%00%00%1E%08%06%00%00%00%3B0%C2%AE%C2%A2%00%00%02KIDATH%C2%89%C3%A5%C2%96M%C2%88NQ%18%C3%87%C3%BF%C2%AF%C3%8D%C2%94fXI%C2%93%05%C2%A5%C3%84L%C3%A4%23%24%C2%8B%C3%99%C2%88%2C(%C2%A5%C3%84%C2%8C%C2%98%C2%84d5Y(J)5%C2%A5%C3%99h%C2%98l%C2%B0A%3E%C3%87b%C3%B29%C2%8BiJ%C2%94%C3%98X%C3%99M%26%25%26%1F%195%23%5E%3F%C2%9D%C3%BA%C2%BF9%C3%9Ey%C3%A7%C2%BD%C3%B7%5C%C3%8By%C3%AA%C3%A9%C2%9C%C3%A7%C2%B9%C3%8F%C3%BF%C3%BE%C3%9Es%C3%AE%C2%B9%C3%8F%7B5%C3%A3%C2%ACTY0%C2%90%C2%B2%C3%B6%C3%B9%C2%92z%25MJ%C3%AA%C2%92%C3%B4)%C2%AF%C2%B0T*%C3%BD%C2%9B%08%C3%A0%04%7F%C3%88_%C2%BB%C2%96%C2%A2%C2%9Db%09%C3%A2%C2%A3F%C2%B6%01%3B%3D%C3%9F%C2%9D%0A%C2%9EU%C3%A0l%C2%B5x%1C%C2%96%C3%B4%C3%84%C3%B3f%C2%8F%C2%83a%0D%C2%92%C3%86%24%C2%AD%C2%A8w%C2%93%2C%C3%B0bI%23%C2%BE%C3%99%05%C3%A7~D%C3%97%7Fy%C3%BC%26%C2%A9G%C3%92%26I%C3%9D%C2%92%C3%8A%C2%92%C2%86r-c%C2%9A%C2%AD%C3%B9%0A%7C%04n%7BK%0F%03%5D%C2%9E%C2%87%C3%AB%0D%C2%9E%C2%9F%03%C2%BE%03%C3%BD%C3%8E%C2%B7%3B%C3%9FZ%C3%A4%19o%C2%AC%12%C2%BF%04%C3%9E%02%7D%11%C2%B8%C3%A4%C3%B9%C2%88%C3%87m%C3%8E_q%3C%C2%AF%08x%C2%B9%C3%85%C2%9D%C2%8E%0F9%1E%C3%B5NT%C3%AA%C3%86%C2%9D%1F%C2%8Fr%C3%81%06%3C%C3%9F%0A%2CM%3D%C3%95%C3%81%1Ey%C3%9E%04L%3A%C3%B7!%C2%AA%C3%B9%C3%A2%C3%9C%0D%C3%87%1B%1C_%04%5EG%C2%AF%5Dw%C3%98%C2%A1%C2%BC%C3%A0%C3%BEh%5B%C2%83_%C2%AF%01~Q%C2%B5%C3%8D%C2%BD%C2%8E%C3%8B%C3%80%04%C3%90%02%1Cq%C3%AEL%5E%C3%B0%3E%0B%C3%96%3A%5E%C3%AD%C3%B8jT%C2%B3%00X%1F%C3%85%C3%AF%C2%A2U%C2%AEtn%C2%9D%C3%A3Ky%C3%81M%16%C3%B4%C3%A4l%10k%22%C3%A8%C3%B6(%3F%C3%AA%C3%9C%C3%A6%C2%BC%C3%A0%C3%A0o%C2%80%C3%B79%C3%81%C2%8D%C3%80c%60%7F%C2%94%3BehGj%C3%8B%3Ca%C3%A1%C2%A2%C2%84%C2%B6Z%C3%B1fk_e%C2%9D%C3%AAe%C3%80%C2%98%C2%8B%C2%87%C2%809%C3%80B%C3%87%7B%0A%C2%80%C3%AFZ%C3%9BZ%0F%C2%BC%C3%85%C3%9D%C3%A7%C2%B3_%C2%A1%C2%8A%0Dx%C2%BC%C2%93%08m%C2%B3%C3%AElV%03%C2%B9%C3%A5%C3%82U.%C2%9A%0D%C3%9C%C2%8C~%C3%80p%22x%C3%90%C2%BA%C3%86%2C%C3%B01%17%5E%C2%AE%C3%B1%C2%9CN%03K%12%C2%A0s%C2%A3%26%C2%A2%2Cp%C3%B0%C2%93%16%C3%9C%2B%C3%B0%3Cc%C3%AF%C2%A8z%C3%BF3%C3%81%C3%81%C2%8F%5B4%C3%B8%1F%C3%A0%C3%BBU%1D%2F%178%C3%B8A%0B%C2%9F%16%04%13%C3%BDE%26%C2%81%C2%83%C3%AF%C3%B2%0D%C2%9E%25B%2B%C3%9D%C2%AB%C2%B3(8%C2%86%C2%A7%C2%AC%C3%BC%7C%C2%AD%C3%93%C2%9C%0A%C2%96%C3%9B_%C2%B0%079%C3%81%C3%A5z%C2%BB%C2%94%02%0E~%C2%804k%C3%8F%02%C2%A7%7C%C3%90%C3%AF%C2%90%C2%B4W%C3%92%C2%84%C2%A4%C2%9F%C3%BE%00%0C%C3%BE%3B%C2%AAi%C2%90%C3%B4%5CR%C3%9Ft7%C2%99%C3%B2A%3F3L%C3%92%1F%C2%87%C3%B6%5B~I%22%C3%AC%5D%00%00%00%00IEND%C2%AEB%60%C2%82"; var catch_img = main.add("image", undefined, File.decode(catch_img_imgString), { name: "catch_img" }); catch_img.addEventListener("click", catch_it, false) var apply_img_imgString = "%C2%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%1E%00%00%00%1E%08%06%00%00%00%3B0%C2%AE%C2%A2%00%00%01%C3%8FIDATH%C2%89%C3%AD%C2%96%C3%8B%2B%C3%85A%14%C3%87%3F%C3%97%3B%24%C3%99(eA%C3%B2(%C2%8Fll-d%C3%81%C3%86JI%C2%B6%C3%88FJac%C3%A3_%C2%B0%23%C2%B6d%C3%A3%C2%91%C2%9D%C3%95%C2%B5%C2%B1a%7BKR%16%12%C2%A5%C3%88%2B%12G%3F%C3%8D%C2%AF%C2%A6%C3%A97%C3%B3%C2%9B%C3%B1Z%C3%B9%C3%964%C3%A7%C3%9E9w%3Esf%C3%AE93%C3%BC%C3%AB%C2%AF%C2%94%C3%919%22%12%C2%9B%C2%B3%40%C2%93%C3%A7%1A%C3%9E%C2%81%5D%60%2B%C3%8D1%C2%93%C3%89%24%0F%C2%88H%C2%91%C2%88%C2%AC%C3%88%C3%97%C3%94%13-%C3%9C%C3%95%C2%AC%12%C2%91%C3%B9%2FB%23%3D%C2%88H%C2%BE%2F%C2%B8%C3%80XD%C2%ABfo%00Y%C3%B38%C3%8CM%02%C2%A6%C2%81z%C2%A0%0C%C2%A8%00n%C3%92%C2%B6%3C%09%C3%BC%C2%A4%C3%99%C3%AB%C3%80%C2%A6%C3%87%1C%7D%0A%2C%C2%BE%C3%90%24%C2%B0%C2%BE%1F5%C3%86X%3B%C3%90%C2%A1%7Cb%C2%BF7%C2%A0Q%C3%B3%19%05%1E%C2%B5%5D*%04%C2%8E%C2%81%C2%834%C2%B0Mk%C3%80P%C2%8AO%04%5B%C2%B2%C2%8CEG6%02%C2%9C%C3%87_%C3%A4y%40%C3%9B%3C%C2%A0i%C3%AA%06%C3%A6t%1F%1Fp%C3%977%C2%A1%C2%B1%C2%AAB%C3%81%2F%3F%04~%0E%05%3B2%C2%9F%1D%60%0C%C2%B8%0D%5D%C2%85%0B%C3%BCn%C3%B4I%C2%8A%C3%8Em%19%C3%A8%04%C3%AE%C2%BE%03%C3%8E%C3%97%C3%ACx%C2%A2%7B%C3%87%C3%AFkU%7F%C2%A6j%C3%BB%C2%A3%2F%C3%98L%C2%A7b%C3%8D%5E%00%26%C2%80rui%C2%BC%19U%2C%C2%B2s%C3%9A%C3%A7K%C2%95%C3%A7%7B%40%C2%9D%C3%AF%02%3E%25%22%03%C2%96%3A%C3%AC%2C%C3%BEF%1B%C2%B6%C3%8C%C2%B1%C3%AA%C2%8Ax%1B%C3%A8%07%16U%19D%C2%95%C3%91A%15%C2%B1%C2%A9%7D%C3%A0%C3%9A%C3%98%C2%B1%C2%99%C2%A0hU%C3%84z%C2%ABTm%C3%9Cq%23%C3%B5j%C3%BE%05%22r%C3%A2%C3%B0uF%C2%AC%2BN%C2%91%2B%C2%87%C3%8F%C2%85%C3%AAK%C2%81%23%C2%A0%C3%817H%C2%9F%3C.s%C2%8CE9%C3%9C%02%1C%02%C3%8D%C2%BEP_%C2%B0%C3%AB%3E%C2%9ET%C3%BF%C3%AC%C2%96%10%C2%A8%2F%C2%B8%24tR%C2%8B%C2%8AB%C3%819%0F%1F%1F%C2%BDZ%7D%1C%C2%B9%C2%99%0Dx%7B%25%C3%A9TD%C3%9At%C2%96%C3%ADyk%C2%AA%1A%C2%98R%7D%C2%A8%C3%AE%C3%94%03!g%7D%C3%9E%C3%BE%C3%AB%C3%97%04%7C%00%C2%93%1D%C3%B0%C3%BF%07%C3%87%C3%B3H%00%00%00%00IEND%C2%AEB%60%C2%82"; var apply_img = main.add("image", undefined, File.decode(apply_img_imgString), { name: "apply_img" }); apply_img.addEventListener("click", apply_it, false) // 全局变量 var time_list = [] // 记住属性的关键帧时间 function get_key_time(prop) { time_list = [] var selKeyList = prop.selectedKeys if (selKeyList.length > 0) { for (var j = 0; j < selKeyList.length; j++) { var k = prop.keyTime(selKeyList[j]) time_list.push(k) } } return time_list } function apply_key(propGroup, time_list) { for (var i = 0; i < propGroup.length; i++) { prp = propGroup[i] for (var j = 0; j < time_list.length; j++) { prp.setValueAtTime(time_list[j], prp.valueAtTime(time_list[j],true)) } } } // prp.setValueAtTime(time, newValue) // 记住属性 function rem_prop_group(propGroup) { var rem_prop_group_res =…- 0
- 0
- 233
-
【脚本示例】随机添加效果
/** * 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
-
【脚本案例】获取属性表达式的完整层级
介绍 选择一个属性,运行脚本 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
-
重置图层变换所有属性
干净! 其他 用法:选择一个或多个图层,运行此脚本 重置图层的变换,比如拖拽创建形状图层的时候,会很方便 如果有关键帧的话,会在当前时间打个新关键帧,并重置。 代码 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]; reset_transform(comp, layer); }; } else { alert('您没有选中图层。'); }; /** * @description:重置图层变换,可以有关键帧 * @param {*} comp :合成 * @param {*} layer :图层 */ function reset_transform(comp, layer) { var TRANSFORM = layer.property("ADBE Transform Group") // 锚点 try { TRANSFORM.property("ADBE Anchor Point").setValue([comp.width / 2, comp.height / 2]); } catch (e) { TRANSFORM.property("ADBE Anchor Point").setValueAtTime(comp.time, [comp.width / 2, comp.height / 2]); } // 位置:要判断是否分离尺寸 if (TRANSFORM.property("ADBE Position").dimensionsSeparated) { try { TRANSFORM.property("ADBE Position_0").setValue(comp.width / 2); // X TRANSFORM.property("ADBE Position_1").setValue(comp.height / 2); // Y TRANSFORM.property("ADBE Position_2").setValue(0); // Y } catch (e) { TRANSFORM.property("ADBE Position_0").setValueAtTime(comp.time, comp.width / 2); // X TRANSFORM.property("ADBE Position_1").setValueAtTime(comp.time, comp.height / 2); // Y TRANSFORM.property("ADBE Position_2").setValueAtTime(comp.time, 0); // Y } } else { try { TRANSFORM.property("ADBE Position").setValue([comp.width / 2, comp.height / 2]); } catch (e) { TRANSFORM.property("ADBE Position").setValueAtTime(comp.time, [comp.width / 2, comp.height / 2]); } } // 缩放 ADBE Scale try { TRANSFORM.property("ADBE Scale").setValue([100, 100, 100]); } catch (e) { TRANSFORM.property("ADBE Scale").setValueAtTime(comp.time, [100, 100, 100]); } // 旋转 if (layer.threeDLayer) { try { TRANSFORM.property("ADBE Rotate X").setValue(0); // X TRANSFORM.property("ADBE Rotate Y").setValue(0); // Y…- 0
- 0
- 199
-
【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
-
【脚本案例】关键帧倍增
介绍 选择关键帧,可以基于整数倍扩散,并且关键帧类型不变 移动前 移动后(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