AEJoy—— 使用 JS 脚本创建预合成(四)

举报
ShaderJoy 发表于 2021/11/18 23:16:40 2021/11/18
【摘要】 这是由 Brian Maffitt 设计出的一个很实用的脚本。当你想将一个或多个图层创建预合成时,产生的新合成会占用当前合成的长度,而嵌入的剪辑的持续时间则会相应被隐藏。这个脚本搭配 “Move all ...

这是由 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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。