AEJoy—— 使用 JS 脚本创建预合成(四)
这是由 Brian Maffitt 设计出的一个很实用的脚本。当你想将一个或多个图层创建预合成时,产生的新合成会占用当前合成的长度,而嵌入的剪辑的持续时间则会相应被隐藏。这个脚本搭配 “Move all attributes…” 选项,将一个或多个选定的层进行预合成,产生的新的 comp 的 In Point 将是选定层最早的 In Point ,同样该 comp 的 Out Point 将是选定层最晚的 Out Point。如果你只选择一个层,新的 comp 的持续时间和开始时间是与层相匹配的。
分步代码解析
范围限定
首先要注意的是,我们将脚本封装在标准作用域限制的大括号和撤销组中:
{
// create undo group
app.beginUndoGroup("Pre-Compose to Layer Duration");
[the rest of the script goes in here]
app.endUndoGroup();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
如果你不确定我们为什么要这样做,请参考这篇文章《AEJoy—— JS 脚本的代码管理好习惯(三)》。
测试分支条件
脚本的实际主体以两个条件测试开始,如果没有满足这些测试,脚本将以两个错误消息中的一个退出。这是通过两个嵌套的 if/else 结构来完成的,它们像这样包围了脚本的其余部分:
// select the active item in the project window
// and make sure it's a comp
var myComp = app.project.activeItem;
if(myComp instanceof CompItem) {
// make sure one or more layers are selected
var myLayers = myComp.selectedLayers;
if(myLayers.length > 0){
[the rest of the script goes in here]
}else{
alert("select at least one layer to precompose.");
}
}else{
alert("please select a composition.");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
这段代码的第一行(忽略注释)创建了一个名为 “myComp” 的新对象,该对象被设置为项目窗口中的活动项(activeItem)的值。我们假设它是一个 comp,但我们需要确保(不会发生以下情形) —— 因为如果它不是,而我们仍然继续执行的话,脚本将中止(这种执行形式总是比较糟糕的)。因此,下一行代码将使用 JavaScript 操作符 “instanceof” 来测试 “myComp” 是否是一个类型为 “CompItem” 的对象。如果是,脚本继续执行下一个语句,如果不是,执行跳转到代码末尾的警告(第一个 if /else 的 “else” 子句),并为用户生成一个错误消息对话框,如下所示:
在第二个测试中,我们创建了一个名为 “myLayers” 的新对象,它构成了 “myComp” 中选中的图层集合。然后我们测试 “myLayers” 的长度,如果有任何层被选中,那么该值将大于零。如果是这样的话,则继续执行脚本的其余部分。如果不满足条件,则弹出警告,显示如下对话框:
因此,如果没有满足运行脚本的任何要求,就会显示适当的有帮助的对话框,脚本会优雅地退出,而不做任何事情。
脚本执行前后对比
在进入代码的真正核心之前,让我们看看成功运行脚本应该是什么样子的。这是我们运行脚本前的两个图层的小合成:
脚本执行前:
脚本执行后:
注意,三个被选中的图层已经被一个名为 “comp R Arm” 的预合成替换了。新 comp 的名字是通过将第一个选中的图层的名字连接到 comp 来构建的。注意,新的合成被修剪,以精确地适合所选图层们的合并持续时间。
回到代码
好的,让我们来看看建立和创建新的预合成的代码块。这是第一部分:
// set new comp's default In and Out points to those of first layer
var newInPoint = myLayers[0].inPoint;
var newOutPoint = myLayers[0].outPoint;
- 1
- 2
- 3
- 4
在这里,我们只是设置了两个新变量,它们最终将成为新 comp 的 InPoint 和 OutPoint 。记住“myLayers” 是一个对象,它包含了所选图层的集合。结果是,这些是按它们被选中的顺序排列的——所以 myLayers[0] 是第一个被选中的图层。
稍后在代码中,我们会看到每个选中的层,并决定我们是否应该使用它的 InPoint 或 OutPoint ,这里我们只是初始化这些变量,稍后我们会比较一些东西。
命名该预合成
下一段代码为新 comp 创建了名称,代码如下:
// create new comp name of "comp " plus name of first layer
var newCompName = "comp ";
var layerName = myLayers[0].name;
if(layerName.length > 26) {
layerName = layerName.substring(0, 26);
}
newCompName += layerName;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
首先,我们创建一个名为 “newCompName” 的字符串变量,并将其初始化为字符串 “comp” 。然后我们创建另一个名为 “layerName” 的字符串变量,并将其设置为选中图层集合 “myLayers” 中第一个选中的图层的名称。然后我们检查层名是否超过 26 个字符。我们这样做是因为 AE 最大层名长度为 31 个字符,我们将使用 “comp” 中的 5 个字符。如果层名超过 26 个字符,我们只使用前 26 个字符。然后我们添加图层名称(或前 26 个字符)到 “comp” 来创建新的图层名称。
创建一个层索引的数组
构造 “预合成” 的方法, 我们需要更进一步的代码,其中一个输 —— 一个数组, 其包含将被移动到新的 comp 的层索引。这里我们将通过遍历选择层的集合来构建数组, 选择它们的层索引值并将它们添加到数组中。这也是我们对所选层进行循环遍历的地方,以确定最早的层 InPoint 和最晚的 OutPoint 。这是代码:
// "precompose" expects an array of layer indices
var layerIndices = new Array();
for (var i = 0; i < myLayers.length; i++) {
layerIndices[layerIndices.length] = myLayers[i].index;
// make sure new comp In point is In point of earliest layer
// and new comp Out point is Out point of latest layer
if (myLayers[i].inPoint < newInPoint) newInPoint = myLayers[i].inPoint;
if (myLayers[i].outPoint > newOutPoint) newOutPoint = myLayers[i].outPoint;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
创建合成
现在我们有了创建新合成所需的一切,这里我们使用图层集合对象的 “预合成” 方法来预合成选中的图层。“precomp” 需要三个参数。
- 第一个是要被预合成的层的层索引数组;
- 第二个是新合成的名称;
- 如果你想要预合成选项 “Move all attributes into the new composition”,你可以设置第三个参数为 “true”,就像我们在本例中做的那样。
下面是创建新 comp 的代码:
// create the new comp
var newComp = myComp.layers.precompose(layerIndices, newCompName, true );
- 1
- 2
- 3
设置新合成的 InPoint 和 OutPoint
至此,我们选择层已经被我们的新合成替代了。我们需要做的最后一件事是在新 comp 中设置 InPoint 和 OutPoint。事实证明, 这种新的 comp 将是在旧 comp 中选中的层。所以我们创建一个新的对象 “preCompLayer” 并设置它等于在旧 comp 当前选中的层(此时已是新的 comp )。变量 “newInPoint” 有我们需要的新 comp 的 InPoint 的值,变量 “newOutPoint” 有我们需要的新 comp 的 OutPoint 的值。下面是我们需要为新 comp 设置 inPoint 和 outPoint 属性的代码:
// set in and out points of new comp
var preCompLayer = myComp.selectedLayers[0];
preCompLayer.inPoint = newInPoint;
preCompLayer.outPoint = newOutPoint;
- 1
- 2
- 3
- 4
- 5
完整的脚本
//
// preCompToLayerDur.jsx (revised 7/26/04)
//
// This script will pre-compose selected layers with "Move all attributes..."
// The in point of the new comp will be the earliest in point of the selected
// layers and the out point will be the latest out point of the selected layers.
//
// The new comp will thus be trimmed so that its duration reflects the composite
// duration of the included layers.
//
// Based on an idea by Brian Maffitt
// Original code design by Keiko Yamada
// Final tweaks and enhancements by Dan Ebberts
//
{
// create undo group
app.beginUndoGroup("Pre-Compose to Layer Duration");
// select the active item in the project window
// and make sure it's a comp
var myComp = app.project.activeItem;
if(myComp instanceof CompItem) {
// make sure one or more layers are selected
var myLayers = myComp.selectedLayers;
if(myLayers.length > 0){
// set new comp's default in and out points to those of first layer
var newInPoint = myLayers[0].inPoint;
var newOutPoint = myLayers[0].outPoint;
// create new comp name of "comp " plus name of first layer
var newCompName = "comp ";
var layerName = myLayers[0].name;
if(layerName.length > 26) {
layerName = layerName.substring(0, 26);
}
newCompName += layerName;
// "precompose" expects an array of layer indices
var layerIndices = new Array();
for (var i = 0; i < myLayers.length; i++) {
layerIndices[layerIndices.length] = myLayers[i].index;
// make sure new comp in point is in point of earliest layer
// and new comp out point is out point of latest layer
if (myLayers[i].inPoint < newInPoint) newInPoint = myLayers[i].inPoint;
if (myLayers[i].outPoint > newOutPoint) newOutPoint = myLayers[i].outPoint;
}
// create the new comp
var newComp = myComp.layers.precompose(layerIndices, newCompName, true );
// set in and out points of new comp
var preCompLayer = myComp.selectedLayers[0];
preCompLayer.inPoint = newInPoint;
preCompLayer.outPoint = newOutPoint;
}else{
alert("select at least one layer to precompose.");
}
}else{
alert("please select a composition.");
}
app.endUndoGroup();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
(完)
文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。
原文链接:panda1234lee.blog.csdn.net/article/details/120359038
- 点赞
- 收藏
- 关注作者
评论(0)