-
[AE脚本开发]事件监听 鼠标篇
姊妹篇: 事件监听 按键篇 var myButton = new Window("palette", "我的按钮"); myButton.button = myButton.add("button", undefined, "单击我"); // 监听右键菜单事件 myButton.button.addEventListener("mousedown", clickHandler); // 鼠标左键是 0 中间滚轮是 1 右键 是2 function clickHandler(event) { if (event.button == 0) { alert("点了左键") } if (event.button == 1) { alert("滚轮") } if (event.button == 2) { alert("点了右键") } } myButton.show();- 0
- 0
- 383
-
【AE 脚本】只在时间轴打开选择的合成的一种实现方法
function filterComp(seletion) { var compArr = []; for(var i=0;i<seletion.length;i++){ if(seletion[i] instanceof CompItem) {compArr.push(seletion[i])} } return compArr; } function onlyOpenSelComp() { var myComp= filterComp(app.project.selection); var selCompID = []; for(var n=0;n<myComp.length;n++){ selCompID.push(myComp[n].id); } var thisFile = app.project.file; if(!thisFile) {alert("Save project first!","Warning");return;} app.project.close(CloseOptions.SAVE_CHANGES); app["openFast"](thisFile); for(var n=0;n<selCompID.length;n++){ app.project.itemByID(selCompID[n]).openInViewer(); } } app.beginUndoGroup("Undo 只打开选中合成"); onlyOpenSelComp(); app.endUndoGroup();- 0
- 0
- 348
-
【脚本相关】借助AutoHotKey来实现保存预设自动化操作(有瑕疵)
半自动化看这边:【脚本相关】使用脚本来半自动化保存预设 前面代码部分一样,后半部分用AutoHotKey模拟点击Ctrl+V以及Alt+S保存,实现自动化保存流程。 不过有瑕疵,像选中效果控件里面的插件,还需要用户手动操作,目前还做不到完全的全自动化。不过也没差了,我们可以在脚本设定好预设保存文件夹、文件名,至于预设什么内容由用户选择也没什么不好2333 因为双方编码不一致,导致传递过去的中文会乱码,所以我这边提供两个方法:一个只允许英文;另一个是把中文参数保存在确定位置的文本文件里,然后用AutoHotKey去解析该文本文件获得内容,并拷贝到剪贴板。 myPreset.jsx var comp = app.project.activeItem; // 获取合成 var layer = comp.selectedLayers; // 获取选中图层 var effect = layer[0].property("ADBE Effect Parade"); // 获取图层的效果列表 var num = effect.numProperties; // 获取效果列表的数量 var plug = effect.property(1); // 序号可以用for遍历,或者用name、matchName查找 // 用名称或者元属性名的时候,如果没找到返回null var isSeleEffect = plug.selected; //检测是否在效果控件选中插件 var presetPath = Folder.temp.fsName + "ae_ffxpath.ffx"; // 声明一个ffx文件的保存全路径,Folder.temp是系统缓存文件夹 copyToClipboard(presetPath); // 把内容推送到系统的剪贴板,如果不用可以注释掉 // https://www.yuelili.com/ae-script-case-transferring-information-to-the-system-clipboard/ function str2cmd(str, list) { var cmd = str; for (i = 0, ii = list.length; i < ii; i++) { var tmp = '"' + list[i] + '"'; // var tmp = list[i]; cmd = cmd.toString().replace("${" + (i + 1) + "}", tmp); } return cmd; } var list = ["(pwcode)\\AutoHotkey","AutoHotkeyU64.exe","autoSavePreset.ahk"]; var cmd = str2cmd('cmd /c start "" /d ${1} ${2} ${3}', list); system.callSystem(cmd); // 启动AutoHotKey待命 app.executeCommand(3075); // 模拟点击 菜单栏的保存预设功能 其中的list是一个占位数组,对应 ${Number},Number从1开始。str2cmd函数原理是替换占位符,再也不用手动用+"'来连接变量。 system.callSystem一定要放在app.executeCommand前面,打开的AutoHotKey可以在后台等待触发条件,一旦保存预设文件窗口弹出,立马模拟点击Ctrl+V以及Alt+S,自动化操作。 如果你的可执行文件放到子文件夹里或者其他位置,那么用/d path指定程序所在的path文件夹就会方便很多,这样你只需要输入程序名即可,打开程序时自动在当前位置寻找程序运行。如果程序在脚本同目录 /d path 可以删掉。 下面是总结出来的cmd字符串指令内容,start 后面必须跟随一个空的双引号,这是因为start会把第一个双引号当成打开新窗口的标题,如果没有/d /min等start参数隔断,会把加了双引号的可执行程序当成标题。 var cmd = 'cmd /c start "" "program.exe" "parameter"' program.exe 可执行文件,在这边是AutoHotKey.exe parameter yao 要传递给可执行文件的参数,这边是一个ahk脚本文件 这行代码的作用是用ahk程序运行ahk脚本文件,在任务栏能看到一个绿绿的H图标就是了,右键可以选择暂停或者编辑脚本文件后需要手动reload导入。 有关start和system.callSystem详细介绍可以移步另一个帖子观看:【脚本相关】关于system.callSystem()踩坑记录与解决方法探索 接下来介绍ahk脚本文件,我已经在代码块里解释清楚了,也没啥可补充的了,另外软件有安装版和解压即用的便携版。 如果是便携版的,需要你把ahk文件打开方式选择成AutoHotKey程序,或者是把文件拽托到exe直接运行,单纯双击exe是没反应的。有几个exe,选择u64就行。 autoSavePreset.ahk clipboard := "" ; 清空剪贴板 ClipWait ; 等待剪贴板重新拷贝新内容 ; clipboard := A_Temp "\ae_ffxpath.ffx" ; A_Temp 是系统缓存文件夹,需要注意ahk无需用+来连接字符串 ; 如果不用剪贴板传递数据,想用确定的文件路径 ; 可以用分号把前面的剪贴板代码注释掉 ; 至于用AutoHotKey读取文本文件,等有空再来研究 = = ; MsgBox % clipboard ; 英文版AE用这个英文关键词,中文用中文关键词 WinWait Save Animation Preset…- 0
- 0
- 479
-
【AE脚本】图层批量位移 | 朝仓 | 免费
将所选图层的入点完全移动到指示器的位置(可分配快捷方式) /*------------------------------------- Version History 1.0.2 [Current version] - Aug 16, 2021 Change file name. 1.0.1 - Aug 13, 2021 Fix for bug with a trimmed layer. 1.0.0 - Aug 13, 2021 Initial release -------------------------------------*/ app.beginUndoGroup("layerShifter"); var comp = app.project.activeItem; var currentTime = comp.time; var slLayers = comp.selectedLayers; var startTimesArr = []; var startTimesArrSort = []; // Get start points. for(var i = 0; i < slLayers.length; i++){ startTimesArr.push(slLayers[i].startTime); startTimesArrSort.push(slLayers[i].inPoint); } // Sort(SortGet the start point of the foremost layer.) startTimesArrSort.sort(function(a,b){ if( a < b ) return -1; if( a > b ) return 1; return 0; }); // Change start points. for(var i = 0; i < startTimesArr.length; i++){ slLayers[i].startTime = currentTime + startTimesArr[i] - startTimesArrSort[0]; } app.endUndoGroup();- 0
- 0
- 330
-
[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脚本] 如何快速修改AE版本语言?
众所周知,修改AE版本的语言是到AE的安装目录下,修改一个名叫application.xml的文件 那既然涉及到了XML,那这个时候就有人问了?怎么读取XML? 那也是非常的简单,先new一个XML,然后把读取到的内容,放在XML里就行了,也是非常的简单,好像eval也行,不过推荐new XML,因为我没试过eval 那怎么调用XML的属性和值呢?推荐去看文档 那既然获得了XML对象,那怎么获得AE的安装目录呢?也是非常的简单,new一个File或者Folder出来,打印一下,你会发现内容是这样的: alert(new File().fsName) // F:\Adobe\Adobe After Effects 2024\Support Files\tmp00000001 那么开始写代码了 if (confirm('确定要切换AE语言吗?')) { var f = new File(new File().parent.toString() + '/AMT/application.xml'), l = prompt('请输入语言', app.isoLanguage); if (l && l.length >= 4) { f.open('r'); var t = new XML(f.read()); t.xpath("/Payload[@adobeCode='{AEFT-24.2.1-64-ADBEADBEADBEADBEADBEA}']/Data[@key='installedLanguages']")[0] = l; f.open('w'); if (f.write('<?xml version="1.0" encoding="utf-8"?>\n' + t)) { f.close(); alert('切换成功请重启AE'); } else { f.close(); alert('切换失败'); } } } 那么到这里就结束了- 0
- 1
- 243
-
【AE脚本】基于图层位置 从左到右排序图层
// name:sort-l-to-r.jsx // description:sort layers from left to right // source:https://github.com/ff6347/after-effects-script-snippets/blob/master/sort-l-to-r.jsx (function(thisObj) { // 比较A、B图层,大就返回1,否则-1 var compare = function(a, b) { if(a.xy[0] < b.xy[0]) { return -1; } if(a.xy[0] > b.xy[0]) { return 1; } return 0; }; // 基于选择的图层,获得图层、以及它的位置 var main = function() { var curComp = app.project.activeItem; if (!curComp || !(curComp instanceof CompItem)) { alert('请选择/打开合成'); return; } var arr = []; for (var i = 0; i < curComp.selectedLayers.length; i++) { var l = curComp.selectedLayers[i]; var pos = l.transform.position.value; arr.push({layer: l, xy: pos}); } //重新排序 arr.sort(compare); // 移到最后 for(var j = 0; j < arr.length; j++) { arr[j].layer.moveToEnd(); } }; var run = function(f) { f(); }; run(main); }(this));- 0
- 0
- 276
-
批量变更图层叠加模式
(function (global) { eval( "@JSXBIN@ES@2.0@MyBbyBn0ACJAnAUzCjcjcBXzHjGjPjSiFjBjDjICfXzJjQjSjPjUjPjUjZjQjFDfjzFiBjSjSjBjZEfBXCfXDfjEfNyBnAMAbyBn0AEOAfAnAEjzJiUjZjQjFiFjSjSjPjSFfRBFegchAjUjIjJjThAjJjThAjOjVjMjMhAjPjShAjOjPjUhAjEjFjGjJjOjFjEftACzChdhdGnezEjUjIjJjTHfbnnbAn0ACJAnASzBjFICEjzGiPjCjKjFjDjUJfRBeHfffnftJAnASzBjJKDCzDheheheLXzGjMjFjOjHjUjIMfVIfCnndAnftOAfAnAEjFfRBCzBhLNVzBjSOfFnneShAjJjThAjOjPjUhAjBhAjGjVjOjDjUjJjPjOftACzChBhdPnizGjUjZjQjFjPjGQVOfFeIjGjVjOjDjUjJjPjOnnKAbAn0ABbAn0ACJAnAUzChGhGRCzCjJjOSVzBjOTfBVIfCnnRCSzBjBUEQzAVfVIfCVTfBnffEXzEjDjBjMjMWfVOfFREVzBjPXfAVUfEVTfBVIfCfftnnJAnATTBBtARCURCzBheYXMfVzJjBjSjHjVjNjFjOjUjTZf4kBkWkYAnndBSXAVzBjUgafGnffnnSTBndAfftCYVKfDVTfBnnnAHK4D0AiAga4B0AhAX40BiAI4C0AiAU4E0AiAO40BhAT4B0AiACFAVCAnfnnJBnAUBXzEjGjSjPjNgbfjEfBXgbfjEfENyBnAMBbyBn0ACbyBn0AFJBnASOAXzIjUjPiTjUjSjJjOjHgcfXDfjJfnftJyBnASTBNyBnAMBbyBn0ABZyBnAUBCGniQVTfAeIjGjVjOjDjUjJjPjOnCzDhdhdhdgdnEXWfjOfRBVTfAffeRibjPjCjKjFjDjUhAiGjVjOjDjUjJjPjOidnnnABT40BhAB0AVCBnftJyBnASgaCNyBnAMBbyBn0ACJyBnASTAEjzGiOjVjNjCjFjSgefRBVOfBffnftZyBnAddEjzFjJjTiOjBiOgffRBVTfAffFdAURCzDhBhdhdhAnVTfAdAnEjzIjJjTiGjJjOjJjUjFhBfRBVTfAffnnCzBhKhCdCYVTfAnndAFdBFdyBEXzFjGjMjPjPjShDfjzEiNjBjUjIhEfRBEXzDjBjCjThFfjhEfRBVTfAffffnnVTf0ACO40BhAT40BiABBAVCBnftJyBnASIDCzBhNhGEXzDjQjPjXhHfjhEfRCFdCFdhVffnndBnftJyBnASXENyBnAMBbyBn0ACJyBnASTAEjgafRBVOfBffnftZyBnAEXzDjNjJjOhIfjhEfRCEXzDjNjBjYhJfjhEfRCVTfAFdAffjIfffACO40BhAT40BiABBAVCBnftZyBnANyBnAMBbyBn0AGbyBn0ACJyBnASgaAeHfnftJyBnASIBEjJfRBVOfIffnftOyBfyBnAEjFfRBFeiAiBjSjSjBjZhOjGjSjPjNhAjSjFjRjVjJjSjFjThAjBjOhAjBjSjSjBjZhNjMjJjLjFhAjPjCjKjFjDjUhAhNhAjOjPjUhAjOjVjMjMhAjPjShAjVjOjEjFjGjJjOjFjEftACGnVOfIbnnJyBnASKDdCYXMfVZf4kBkWkYAnndBXzBhRhKfVZf4kBkWkYAhzEjWjPjJjEhLFdAnftOyBbyBn0ACOyBfyBnAEjFfRBFeiBiBjSjSjBjZhOjGjSjPjNhahAjXjIjFjOhAjQjSjPjWjJjEjFjEhMhAjUjIjFhAjTjFjDjPjOjEhAjBjSjHjVjNjFjOjUhAjNjVjTjUhAjCjFhAjBhAjGjVjOjDjUjJjPjOftAhzBhBhMEjTfRBVKfDffnJyBnAURCYXMfVZf4kBkWkYAnndCSUCXzBhShNfVZf4kBkWkYAnffnnACPniQVKfDeJjVjOjEjFjGjJjOjFjEnnKyBbyBn0ADJyBnASzBjGhOEQVfVIfBVzBjIhPfHnffJyBnAdVKfDBQVfVzBjDhQfGVhPfHdCGniQVUfCeJjVjOjEjFjGjJjOjFjEnEVKfDRCVhOfEVhPfHffEXWfVKfDRDVUfCVhOfEVhPfHffnfBQVfVhQfGVhPfHVhOfEnfJyBnAShPHCNnnndBntfAREVhOfESzBjVhRFEjXfRBXMfVIfBffnftShQGdEjTfRBVgafAffEjJfRBEVgafARBVhRfFftffEjEfRBVhRfFftnftShPHndAfttCYVhRfFVhPfHnnnZyBnARCBXMfVhQfGVhRfFnfVhQfGtAJK4D0AiAhP4H0AiAhO4E0AiAga40BiAhR4F0AiAI4B0AiAU4C0AiAO40BhAhQ4G0AiABIAVCBAFga4C0AiAX4E0AiAI4D0AiAO40BiAT4B0AiAAFAVCBnfnfnn0DVByB" ); //批量变更图层叠加模式 Beta 1.0.2 2021-11-01 //© Raymond Yan 2021 (RaymondClr@outlook.com / QQ: 1107677019) var settings = new Settings(); var userInterface = new UserInterface(); var afterEffect = new AfterEffect(); runScript(); function runScript() { var buttons = userInterface.getButtons(); buttons.forEach(function (button) { button.onClick = function () { afterEffect.changeBlendingMode(BlendingMode[this.mode]); }; }); } function Settings() { //配置按钮排列方向 //可选参数: //row 排成一行 //column 排成一列 var buttonsDirection = "column"; //配置按钮白名单 //1、按钮排序:列表呈现顺序对应按钮在UI中的显示顺序,调整此顺序可对按钮排序。 //2、按钮文字:中文内容为按钮显示文本,可按个人喜好更改。 //注意事项 //1、请务必遵从列表的现有书写格式进行增删改,否则,可能会引发程序错误。 //2、左侧大写英文不可随意更改,此英文决定了叠加模式的最终结果;如需增删,仅可输入以下文档中列举的单词: //https://ae-scripting.docsforadobe.dev/layers/avlayer.html?highlight=blending#avlayer-frameblendingtype var whiteList = { ADD: "相加", ALPHA_ADD: "Alpha 添加", CLASSIC_COLOR_BURN: "经典颜色加深", CLASSIC_COLOR_DODGE: "经典颜色减淡", CLASSIC_DIFFERENCE: "经典差值", COLOR: "颜色", COLOR_BURN: "颜色加深", COLOR_DODGE: "颜色减淡", DANCING_DISSOLVE: "动态抖动溶解", DARKEN: "变暗", DARKER_COLOR: "较深的颜色", DIFFERENCE: "差值", DISSOLVE: "溶解", DIVIDE: "相除", EXCLUSION: "排除", HARD_LIGHT: "强光", HARD_MIX: "纯色混合", HUE: "色相", LIGHTEN: "变亮", LIGHTER_COLOR: "较浅的颜色", LINEAR_BURN: "线性加深", LINEAR_DODGE: "线性减淡", LINEAR_LIGHT: "线性光", LUMINESCENT_PREMUL: "冷光预乘", LUMINOSITY: "发光度", MULTIPLY: "相乘", NORMAL: "正常", OVERLAY: "叠加", PIN_LIGHT: "点光", SATURATION: "饱和度", SCREEN: "屏幕", SILHOUETE_ALPHA: "轮廓 Alpha", SILHOUETTE_LUMA: "轮廓亮度", SOFT_LIGHT: "柔光", STENCIL_ALPHA: "模板 Alpha", STENCIL_LUMA: "模板亮度", SUBTRACT: "相减", VIVID_LIGHT: "亮光", }; return { getWhiteList: function () { return whiteList; }, getDirection: function () { return buttonsDirection; }, }; } function AfterEffect() { function getActiveItem() { var activeItem = app.project.activeItem; var hasActiveItem = (function () { return activeItem instanceof CompItem && activeItem !== null; })();…- 0
- 0
- 232
-
【脚本案例】提醒保存小助手V1.1
名称:提醒保存小助手 功能:单击开启提醒,shift单击关闭提醒(如果没开启,按住shift则会开启提醒) 1分钟检测一次,如果已保存,则计时器归零。因此,提醒保存时长必须超过1分钟 注意: 只是提醒你保存, 并不会自动保存! 这样可以防止工程过大产生的卡死 脚本可以直接丢UI panel文件夹里 使用条件 已测版本:AE2020 更新 V1.1: 原版本有点逻辑问题,写2分钟,实际会3分钟提醒 知识点 app.scheduleTask:定时函数的应用 源码 /** * 名称:提醒保存小助手 * 功能:单击开启提醒,shift单击关闭提醒(如果没开启,按住shift则会开启提醒) * V1.1: 原版本有点逻辑问题,写2分钟,实际会3分钟提醒 * V1.0 * 源码:https://www.yuelili.com/?p=18056 */ var n = 1 // 初始化计时器 var t = 10// 默认多少分钟弹出保存 var id = 0 timerIt = function () { // 判断当前项目是否保存,保存则计时器归零 if (!app.project.dirty) { n = 0 } if (n == t) { n = 0 // 计时器归零 alert("记得ctrl s保存工程哟") //弹出保存对话框 } n = n + 1 } 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 edittext1 = main.add('edittext {properties: {name: "edittext1"'); edittext1.text = "10"; var alert_btn = main.add("button", undefined, undefined, { name: "alert_btn" }); alert_btn.text = "计时"; alert_btn.helpTip = "单击开启,按住shift单击关闭"; alert_btn.preferredSize.width = 50; alert_btn.onClick = start function start() { t = parseInt(edittext1.text) var shiftHeld = ScriptUI.environment.keyboardState.shiftKey; if (shiftHeld && id) { alert("已关闭提醒") app.cancelTask(id) } else { alert("已打开提醒小助手:" + edittext1.text + "分钟提醒一次哦") id = app.scheduleTask("timerIt()", 60000, true) // 60秒 也就是1分钟检测一次 } } main.layout.layout(true); main.layout.resize(); main.onResizing = main.onResize = function () {…- 0
- 0
- 401
-
监听冲突(优化)
// 熊猫 var res = palette { orientation:'row', \ A: DropDownList { properties:{items:['A','B','C','D','E','F','G']} }, \ B: DropDownList { properties:{items:['A','B','C','D','E','F','G']} }, \ }; var win = new Window (res); win.show(); var L = win.A; L.selection = 0; var R = win.B; R.selection = 1; function A() { return 0 } function B() { return 0 } //========================错误的实现========================== L.onChange = function () {var i = this.selection.index; R.selection = B(); this.selection = i} R.onChange = function () {var i = this.selection.index; L.selection = A(); this.selection = i} //============================================================ //目前的问题:L绑定了监听,R绑定了监听,L值发生改变会使R的值发生改变,R值的改变又会触发R的监听,导致L的值被改变,反之亦然。 //期望的结果:L发生改变时,R的值发生改变,但不触发R的监听(或不执行相应的处理程序)。R发生改变时,L的值发生改变,但不触发R的监听(或不执行相应的处理程序)。 /*=======================一种解决方案========================= var change = false; function pass() { change ? change = false : change = true; } L.onChange = function () { pass(); if(change) R.selection = B(); pass();} R.onChange = function () { pass(); if(change) L.selection = A(); pass();} //===========================================================*/- 0
- 0
- 138
-
【脚本问答】获取文件夹路径,比如说工程的文件夹,渲染输出的文件夹?
//获取项目工程的路径 app.project.file.fsName //设置渲染的路径 var Path = "/c/output/" var myRQ = proj.renderQueue; myRQ.item(i).outputModule(1).file=new File(Path); //获取渲染路径 myRQ.item(i).outputModule(1).file.fsName;- 0
- 0
- 243
-
【AE脚本】选择一个图层的所有蒙版
/** * @author redefinery with some edits by fabiantheblind * @description :选择一个图层所有蒙版 * source:https://github.com/ff6347/after-effects-script-snippets/blob/master/select-all-masks-on%20layer.jsx * @todo [description] */ // 需求: // layer = 图层对象, 而且该对象可以应用蒙版 // fun(); function fun() { app.beginUndoGroup('XXX'); var curComp = app.project.activeItem; if (!curComp || !(curComp instanceof CompItem)) { alert('noComp'); return; } var layer = curComp.selectedLayers[0]; var masksGroup = layer('Masks'); var selectedMasks = new Array(); // 存储蒙版对象; 起始为空 if (masksGroup != null) { // 遍历masksGroup(蒙版组) // 追加蒙版进组 for (var i = 1; i <= masksGroup.numProperties; i++) { masksGroup.property(i).selected = true; } // ~ if (masksGroup.property(i).selected) // ~ selectedMasks[selectedMasks.length] = masksGroup.property(i); // ~ } // The selectedMasks array now contains the list of selected masks // in top-to-bottom order } app.endUndoGroup(); }- 0
- 0
- 202
-
【AE脚本开发】颜色转换
[sc name="zhuanzai" author="jonathantneal" link="https://github.com/jonathantneal/convert-colors/tree/master/src" ][/sc] HEX and RGB @无名 正则hex转rgb function hexToRgb(hex) { var result; hex = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/gi, '$1$1$2$2$3$3'); hex.replace(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/gi, function (match, $1, $2, $3) { result = [parseInt($1, 16), parseInt($2, 16), parseInt($3, 16)]; }); return result; } function hex2rgb(hex) { // #<hex-color>{3,4,6,8} const hexColorMatch = /^#?(?:([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?|([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?)$/i; const [, r, g, b, a, rr, gg, bb, aa] = hex.match(hexColorMatch) || []; if (rr !== undefined || r !== undefined) { const red = rr !== undefined ? parseInt(rr, 16) : parseInt(r + r, 16); const green = gg !== undefined ? parseInt(gg, 16) : parseInt(g + g, 16); const blue = bb !== undefined ? parseInt(bb, 16) : parseInt(b + b, 16); const alpha = aa !== undefined ? parseInt(aa, 16) : a !== undefined ? parseInt(a + a, 16) : 255; return [red, green, blue, alpha].map(c => c * 100 / 255); } return undefined; } export function rgb2hex(rgbR, rgbG, rgbB) { return `#${((1 << 24) + (Math.round(rgbR * 255 / 100) << 16) + (Math.round(rgbG * 255 / 100) << 8) + Math.round(rgbB * 255 / 100)).toString(16).slice(1)}`; } HSL and hsv function hsl2hsv(hslH, hslS, hslL) { const hsv1 = hslS * (hslL < 50 ? hslL…- 0
- 0
- 672
-
【脚本案例】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
-
【脚本案例】关键帧倍增
介绍 选择关键帧,可以基于整数倍扩散,并且关键帧类型不变 移动前 移动后(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
-
【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
-
【脚本案例】调整图层置顶
介绍 选择一个合成,置顶当前合成的所有调整图层 排序前 排序后 源码 ```javascript * 功能:选择一个合成,指定当前合成的所有调整图层 * 源码:https://www.yuelili.com/?p=17996 * 版本:1.0 */ var panelGlobal = this; var palette = (function () { // 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 = move_top // 判断 function move_top() { app.beginUndoGroup("adjust_to_top"); var comp = app.project.activeItem if (comp instanceof CompItem) { myLayers = comp.layers var jug = 0 for (var i = myLayers.length; i > 1; i--) { theLayer = comp.layer(i) if (theLayer.adjustmentLayer == true) { theLayer.moveToBeginning() i = i + 1 jug += 1 } if (jug + 1 == i) { break } } } else { alert("请选择一个合成") } app.endUndoGroup(); } palette.layout.layout(true); palette.layout.resize(); palette.onResizing = palette.onResize = function () { this.layout.resize(); } if (palette instanceof Window) palette.show(); return palette; }()); ```- 0
- 0
- 178
-
【脚本示例】随机添加效果
/** * 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
-
【脚本案例】渲染指定图层 rd_Render Layers
介绍 基本上渲染参数都玩明白了,拆一下,大有裨益 源码 // rd_RenderLayers.jsx // Copyright (c) 2006-2013 redefinery (Jeffrey R. Almasol). All rights reserved. // check it: www.redefinery.com // // Name: rd_RenderLayers // Version: 3.1 // // 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…- 0
- 0
- 235
-
AE内置效果预览包v1.0
https://www.bilibili.com/video/BV1rM4y1N7pD/ 使用AEViewer,进行AE内置效果预览及运用 能力一般,水平有限 加上时间原因,以下几类效果未做成预览(期待有想法的同学一起完善) Audio - 音频 Channel - 通道 Color Correction - 颜色校正 Immersive Video - 沉浸式视频 Obsolete - 过时 Utility - 实用工具 *本效果整合包大部分效果为 次元饺子(B站)制作 *小部分效果以及脚本整合为 JimWho (B站)制作 *(效果包本人测试版本AE2020,使用效果有问题及时联系我)- 0
- 0
- 963
-
【事件监听】键盘按键监控源码
/** * 名称:检测键盘状态,并弹出按键名称 * source:https://www.youtube.com/watch?v=UBqdWdDmvao * web:https://www.yuelili.com/?p=18460 **/ var window = new Window("palette", "", undefined); var text = window.add("statictext", undefined, "Detect keyboard input"); window.center(); window.show(); var inUI = true; function inside() { inUI = true; } function outside() { inUI = false; } window.addEventListener('mouseover', inside); window.addEventListener('mouseout', outside); window.addEventListener('keydown', alertKey); function alertKey() { var myKeyState = ScriptUI.environment.keyboardState; var pressedString = myKeyState.keyName; if (myKeyState.altKey) { pressedString = "Alt + " + pressedString; } if (myKeyState.ctrlKey) { pressedString = "Ctrl + " + pressedString; } if (myKeyState.shiftKey) { pressedString = "Shift + " + pressedString; } if (myKeyState.keyName == "F" && myKeyState.shiftKey == true) { alert("You pressed Shift + F"); } if (myKeyState.keyName) { alert("You pressed " + pressedString); } }- 0
- 0
- 227
-
【AE脚本】已知一个图层的属性对象,反求它所在图层和合成
//熊猫 var layer = myProp.propertyGroup(myProp.propertyDepth); var comp = layer.containingComp;- 0
- 0
- 167
-
【AE脚本开发】给脚本写个联网激活机制
/* 激活流程: 1.用户填写授权码; 2.利用授权码与机器码生成网页链接; 3.脚本调用curl程序访问链接。如果授权码有效,得到服务器通过机器码计算出来的激活码;否则得到服务器返回的授权码不可用。 4.将激活码存于本地。 说明:重装系统等原因导致本地激活码丢失,电脑需要再次激活时,只需联网验证机器码即可,无需再次填授权码。这个步骤自己扩展,这里写首次激活的示例。 */ //打开注册面板 function zhuCe(){ if(pc.pcJQM.length == 0 && (!isMac ())){ alert ("请先启用已禁用的网卡!\n然后关闭脚本重新打开。","无法验证激活状态!"); system.callSystem("cmd.exe /c ncpa.cpl"); return; } var zhuCeW = new Window("dialog", "注册"); var res = "group {\ orientation:'column', alignment:['fill','fill'],preferredSize:[0,0] \ GG: Group { \ orientation:'row', alignment:['fill','fill'],preferredSize:[0,0] \ }, \ fen: Panel { alignment:['fill','top'],preferredSize:[300,2] }, \ GG2: Group{\ orientation:'column', alignment:['fill','fill'],preferredSize:[0,0] \ t1 : Group { alignment:['fill','center']\ text: StaticText { text:'注册码:', alignment:['left','center'] }, \ passText: EditText { text:'', characters:20, alignment:['fill','center'] }, \ },\ btn: Group { \ orientation:'row', alignment:['fill','fill'],preferredSize:[0,0] \ zhuCe: Button { text:'注册', alignment:['right','center'],preferredSize:[150,30] }, \ gouMai: Button { text:'去淘宝购买注册码', alignment:['left','center'],preferredSize:[150,30] }, \ }, \ },\ }"; zhuCeW.gr = zhuCeW.add(res); //注册 zhuCeW.gr.GG2.btn.zhuCe.onClick = function(){ var sma = zhuCeW.gr.GG2.t1.passText.text.replace (/\W/g, ""); //app.settings.saveSetting(Hound.name,"sma" , strToUrl (sma)); if(pc.pcJQM.length == 0){alert("识别主板失败!\n请先启用以太网卡(win7:本地连接)。")} if(sma.length == 30){ if(web_jihuo (sma, pc.pcJQM.toString ().replace (/,/g, ''))){alert("注册成功!");zhuCeW.close ()} } else{alert("注册码输入有误!")} } //去淘宝购买注册码 //zhuCeW.gr.GG2.btn.gouMai.onClick = function(){ openURL(url.taobao) ;zhuCeW.close();}; zhuCeW.show(); } //获取机器码 function getPcMac(){ if(isMac ()){ var macId = system.callSystem("ifconfig en0 | awk '/ether/{print $2}'"); macId = macId.substr(0,17); if(macId.substr (0, 8) !=="ifconfig"){ pc.pcJQM.push (mac2jqm (macId)); } var patt = new RegExp(/[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}/ig); var s , j; macId = system.callSystem("ifconfig"); while((s = patt.exec(macId)) != null){ j = s.toString().replace (/\:/g, "").replace(/\s/g,""); if(pc.pcJQM.toString ().indexOf (j) == -1 && pc.pcJQM.length <…- 0
- 0
- 630
-
【脚本示例】获取实时属性值
/** * 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
-
按钮自动换行
var palette = (this instanceof Panel) ? panelGlobal : new Window("palette", undefined, undefined, { resizeable: true }); palette.text = "Panel"; palette.orientation = "column"; palette.preferredSize.width = 500; palette.preferredSize.height = 300; buttomnum = 24; //按钮数量 //创建30个尺寸50x50的按钮 var btn = new Array(); for (var b = 1; b <= buttomnum; b++) { btn[b] = palette.add("button", undefined, undefined); btn[b].preferredSize.width = 50; btn[b].preferredSize.height = 50; btn[b].text = b; } var buttomSpace = 10;//按钮间隔 var btnX = btn[1].preferredSize.width + buttomSpace;//一个按钮摆放宽度 var btnY = btn[1].preferredSize.height + buttomSpace;//一个按钮摆放高度 palette.onResizing = palette.onResize = function () { var buttonsPerRow = Math.floor(palette.size.width / btnX); //计算界面宽度下一行最多可以放下的按钮数量 if (buttonsPerRow > buttomnum) { buttonsPerRow = buttomnum; } // 左边多余间距(用来按钮居中) var letfSpace = (palette.size.width - buttonsPerRow * btnX + buttomSpace) / 2 for (var c = 0; c < buttomnum; c++) { if (buttonsPerRow < 2) { //判断界面大小,如果宽度小于2个按钮,则按一列排,中间无间隔 btn[c + 1].location = [0, c * 50]; btn[c + 1].size.width = palette.size.width; btn[c + 1].size.height = 50; } else if (buttonsPerRow >= buttomnum) { // 如果界面能容纳所有按钮, 则一行排列, 并且无间隔 palette.size.height = btnY btn[c + 1].location = [(palette.size.width / buttonsPerRow) * c, 0]; btn[c + 1].size.height = 50; btn[c + 1].size.width = (palette.size.width / buttonsPerRow); } else { // 如果界面宽度大于2个按钮,则按上述排列,按钮大小50x50 for (var b = 1; b <= buttomnum;…- 0
- 0
- 260